@quereus/quereus 0.17.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +80 -14
  2. package/dist/src/common/type-inference.d.ts +1 -0
  3. package/dist/src/common/type-inference.d.ts.map +1 -1
  4. package/dist/src/common/type-inference.js +6 -1
  5. package/dist/src/common/type-inference.js.map +1 -1
  6. package/dist/src/common/types.d.ts +10 -2
  7. package/dist/src/common/types.d.ts.map +1 -1
  8. package/dist/src/common/types.js +13 -1
  9. package/dist/src/common/types.js.map +1 -1
  10. package/dist/src/emit/ast-stringify.d.ts.map +1 -1
  11. package/dist/src/emit/ast-stringify.js +5 -0
  12. package/dist/src/emit/ast-stringify.js.map +1 -1
  13. package/dist/src/func/builtins/conversion.d.ts +2 -2
  14. package/dist/src/func/builtins/conversion.js +3 -3
  15. package/dist/src/func/builtins/conversion.js.map +1 -1
  16. package/dist/src/func/builtins/index.d.ts.map +1 -1
  17. package/dist/src/func/builtins/index.js +2 -1
  18. package/dist/src/func/builtins/index.js.map +1 -1
  19. package/dist/src/func/builtins/json-helpers.d.ts +10 -0
  20. package/dist/src/func/builtins/json-helpers.d.ts.map +1 -1
  21. package/dist/src/func/builtins/json-helpers.js +26 -0
  22. package/dist/src/func/builtins/json-helpers.js.map +1 -1
  23. package/dist/src/func/builtins/json-tvf.d.ts.map +1 -1
  24. package/dist/src/func/builtins/json-tvf.js +9 -15
  25. package/dist/src/func/builtins/json-tvf.js.map +1 -1
  26. package/dist/src/func/builtins/json.d.ts.map +1 -1
  27. package/dist/src/func/builtins/json.js +100 -227
  28. package/dist/src/func/builtins/json.js.map +1 -1
  29. package/dist/src/func/builtins/schema.d.ts.map +1 -1
  30. package/dist/src/func/builtins/schema.js +9 -0
  31. package/dist/src/func/builtins/schema.js.map +1 -1
  32. package/dist/src/index.d.ts +1 -1
  33. package/dist/src/index.d.ts.map +1 -1
  34. package/dist/src/parser/lexer.d.ts +1 -0
  35. package/dist/src/parser/lexer.d.ts.map +1 -1
  36. package/dist/src/parser/lexer.js +2 -1
  37. package/dist/src/parser/lexer.js.map +1 -1
  38. package/dist/src/parser/parser.d.ts +12 -0
  39. package/dist/src/parser/parser.d.ts.map +1 -1
  40. package/dist/src/parser/parser.js +54 -1
  41. package/dist/src/parser/parser.js.map +1 -1
  42. package/dist/src/planner/analysis/const-evaluator.d.ts +5 -0
  43. package/dist/src/planner/analysis/const-evaluator.d.ts.map +1 -1
  44. package/dist/src/planner/analysis/const-evaluator.js +106 -0
  45. package/dist/src/planner/analysis/const-evaluator.js.map +1 -1
  46. package/dist/src/planner/analysis/const-pass.d.ts +4 -2
  47. package/dist/src/planner/analysis/const-pass.d.ts.map +1 -1
  48. package/dist/src/planner/analysis/const-pass.js +23 -13
  49. package/dist/src/planner/analysis/const-pass.js.map +1 -1
  50. package/dist/src/planner/analysis/constraint-extractor.d.ts +19 -1
  51. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  52. package/dist/src/planner/analysis/constraint-extractor.js +265 -14
  53. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  54. package/dist/src/planner/analysis/expression-fingerprint.d.ts +15 -0
  55. package/dist/src/planner/analysis/expression-fingerprint.d.ts.map +1 -0
  56. package/dist/src/planner/analysis/expression-fingerprint.js +126 -0
  57. package/dist/src/planner/analysis/expression-fingerprint.js.map +1 -0
  58. package/dist/src/planner/cost/index.d.ts +16 -0
  59. package/dist/src/planner/cost/index.d.ts.map +1 -1
  60. package/dist/src/planner/cost/index.js +22 -0
  61. package/dist/src/planner/cost/index.js.map +1 -1
  62. package/dist/src/planner/framework/pass.d.ts.map +1 -1
  63. package/dist/src/planner/framework/pass.js +4 -3
  64. package/dist/src/planner/framework/pass.js.map +1 -1
  65. package/dist/src/planner/nodes/hash-aggregate.d.ts +38 -0
  66. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -0
  67. package/dist/src/planner/nodes/hash-aggregate.js +213 -0
  68. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -0
  69. package/dist/src/planner/nodes/plan-node-type.d.ts +1 -0
  70. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  71. package/dist/src/planner/nodes/plan-node-type.js +1 -0
  72. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  73. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  74. package/dist/src/planner/nodes/table-access-nodes.d.ts +11 -0
  75. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  76. package/dist/src/planner/nodes/table-access-nodes.js +32 -0
  77. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  78. package/dist/src/planner/nodes/values-node.d.ts +3 -1
  79. package/dist/src/planner/nodes/values-node.d.ts.map +1 -1
  80. package/dist/src/planner/nodes/values-node.js +9 -2
  81. package/dist/src/planner/nodes/values-node.js.map +1 -1
  82. package/dist/src/planner/optimizer.d.ts.map +1 -1
  83. package/dist/src/planner/optimizer.js +35 -7
  84. package/dist/src/planner/optimizer.js.map +1 -1
  85. package/dist/src/planner/rules/access/rule-select-access-path.js +175 -5
  86. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  87. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts +9 -11
  88. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
  89. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +54 -67
  90. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
  91. package/dist/src/planner/rules/cache/rule-scalar-cse.d.ts +19 -0
  92. package/dist/src/planner/rules/cache/rule-scalar-cse.d.ts.map +1 -0
  93. package/dist/src/planner/rules/cache/rule-scalar-cse.js +245 -0
  94. package/dist/src/planner/rules/cache/rule-scalar-cse.js.map +1 -0
  95. package/dist/src/planner/rules/predicate/rule-filter-merge.d.ts +15 -0
  96. package/dist/src/planner/rules/predicate/rule-filter-merge.d.ts.map +1 -0
  97. package/dist/src/planner/rules/predicate/rule-filter-merge.js +39 -0
  98. package/dist/src/planner/rules/predicate/rule-filter-merge.js.map +1 -0
  99. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts +1 -0
  100. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts.map +1 -1
  101. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js +9 -0
  102. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +1 -1
  103. package/dist/src/planner/rules/retrieve/rule-projection-pruning.d.ts +17 -0
  104. package/dist/src/planner/rules/retrieve/rule-projection-pruning.d.ts.map +1 -0
  105. package/dist/src/planner/rules/retrieve/rule-projection-pruning.js +75 -0
  106. package/dist/src/planner/rules/retrieve/rule-projection-pruning.js.map +1 -0
  107. package/dist/src/runtime/emit/aggregate.d.ts +9 -0
  108. package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
  109. package/dist/src/runtime/emit/aggregate.js +2 -2
  110. package/dist/src/runtime/emit/aggregate.js.map +1 -1
  111. package/dist/src/runtime/emit/empty-result.d.ts +5 -0
  112. package/dist/src/runtime/emit/empty-result.d.ts.map +1 -0
  113. package/dist/src/runtime/emit/empty-result.js +11 -0
  114. package/dist/src/runtime/emit/empty-result.js.map +1 -0
  115. package/dist/src/runtime/emit/hash-aggregate.d.ts +5 -0
  116. package/dist/src/runtime/emit/hash-aggregate.d.ts.map +1 -0
  117. package/dist/src/runtime/emit/hash-aggregate.js +319 -0
  118. package/dist/src/runtime/emit/hash-aggregate.js.map +1 -0
  119. package/dist/src/runtime/register.d.ts.map +1 -1
  120. package/dist/src/runtime/register.js +4 -1
  121. package/dist/src/runtime/register.js.map +1 -1
  122. package/dist/src/types/json-type.d.ts +3 -3
  123. package/dist/src/types/json-type.d.ts.map +1 -1
  124. package/dist/src/types/json-type.js +44 -38
  125. package/dist/src/types/json-type.js.map +1 -1
  126. package/dist/src/types/logical-type.d.ts +2 -1
  127. package/dist/src/types/logical-type.d.ts.map +1 -1
  128. package/dist/src/types/logical-type.js +4 -0
  129. package/dist/src/types/logical-type.js.map +1 -1
  130. package/dist/src/util/comparison.d.ts +1 -1
  131. package/dist/src/util/comparison.d.ts.map +1 -1
  132. package/dist/src/util/comparison.js +22 -4
  133. package/dist/src/util/comparison.js.map +1 -1
  134. package/dist/src/vtab/best-access-plan.d.ts +1 -1
  135. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  136. package/dist/src/vtab/memory/layer/base-cursor.d.ts.map +1 -1
  137. package/dist/src/vtab/memory/layer/base-cursor.js +81 -6
  138. package/dist/src/vtab/memory/layer/base-cursor.js.map +1 -1
  139. package/dist/src/vtab/memory/layer/scan-plan.d.ts +9 -0
  140. package/dist/src/vtab/memory/layer/scan-plan.d.ts.map +1 -1
  141. package/dist/src/vtab/memory/layer/scan-plan.js +76 -9
  142. package/dist/src/vtab/memory/layer/scan-plan.js.map +1 -1
  143. package/dist/src/vtab/memory/layer/transaction-cursor.d.ts.map +1 -1
  144. package/dist/src/vtab/memory/layer/transaction-cursor.js +79 -11
  145. package/dist/src/vtab/memory/layer/transaction-cursor.js.map +1 -1
  146. package/dist/src/vtab/memory/module.d.ts +4 -0
  147. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  148. package/dist/src/vtab/memory/module.js +79 -11
  149. package/dist/src/vtab/memory/module.js.map +1 -1
  150. package/package.json +25 -5
@@ -10,7 +10,9 @@ import { emitPlanNode } from '../../runtime/emitters.js';
10
10
  import { EmissionContext } from '../../runtime/emission-context.js';
11
11
  import { Scheduler } from '../../runtime/scheduler.js';
12
12
  import { RowContextMap } from '../../runtime/context-helpers.js';
13
+ import { isAsyncIterable } from '../../runtime/utils.js';
13
14
  import { createLogger } from '../../common/logger.js';
15
+ import { TableLiteralNode } from '../nodes/values-node.js';
14
16
  const log = createLogger('optimizer:folding:eval');
15
17
  /**
16
18
  * Create an expression evaluator that uses the runtime to evaluate constant expressions
@@ -50,4 +52,108 @@ export function createRuntimeExpressionEvaluator(db) {
50
52
  }
51
53
  };
52
54
  }
55
+ /**
56
+ * A self-materializing async iterable that caches rows on first iteration.
57
+ * First iteration runs the source, collects all rows, and caches them.
58
+ * Subsequent iterations yield from the cached array.
59
+ */
60
+ class MaterializingAsyncIterable {
61
+ createSource;
62
+ cached = null;
63
+ materializing = null;
64
+ constructor(createSource) {
65
+ this.createSource = createSource;
66
+ }
67
+ [Symbol.asyncIterator]() {
68
+ if (this.cached) {
69
+ return arrayToAsyncIterator(this.cached);
70
+ }
71
+ return this.materializeAndYield();
72
+ }
73
+ materializeAndYield() {
74
+ // If already materializing from another iterator, wait for it
75
+ if (!this.materializing) {
76
+ this.materializing = this.doMaterialize();
77
+ }
78
+ const promise = this.materializing;
79
+ let index = 0;
80
+ return {
81
+ next: async () => {
82
+ const rows = await promise;
83
+ if (index < rows.length) {
84
+ return { value: rows[index++], done: false };
85
+ }
86
+ return { value: undefined, done: true };
87
+ }
88
+ };
89
+ }
90
+ async doMaterialize() {
91
+ const rows = [];
92
+ let source = this.createSource();
93
+ // Resolve if promise
94
+ if (source instanceof Promise) {
95
+ source = await source;
96
+ }
97
+ // Source should be an AsyncIterable<Row>
98
+ if (isAsyncIterable(source)) {
99
+ for await (const row of source) {
100
+ rows.push(row);
101
+ }
102
+ }
103
+ else {
104
+ throw new QuereusError('Relational evaluation did not produce an async iterable');
105
+ }
106
+ this.cached = rows;
107
+ return rows;
108
+ }
109
+ }
110
+ function arrayToAsyncIterator(rows) {
111
+ let index = 0;
112
+ return {
113
+ next: async () => {
114
+ if (index < rows.length) {
115
+ return { value: rows[index++], done: false };
116
+ }
117
+ return { value: undefined, done: true };
118
+ }
119
+ };
120
+ }
121
+ /**
122
+ * Create a relational evaluator that replaces constant relational subtrees
123
+ * with TableLiteralNodes using deferred materialization.
124
+ */
125
+ export function createRuntimeRelationalEvaluator(db) {
126
+ return function evaluateRelation(node) {
127
+ log('Evaluating relational constant: %s', node.nodeType);
128
+ try {
129
+ // Emit the relational subtree to an instruction tree
130
+ const emissionCtx = new EmissionContext(db);
131
+ const instruction = emitPlanNode(node, emissionCtx);
132
+ const scheduler = new Scheduler(instruction);
133
+ // Create a self-materializing async iterable
134
+ const iterable = new MaterializingAsyncIterable(() => {
135
+ const runtimeCtx = {
136
+ db,
137
+ stmt: undefined,
138
+ params: {},
139
+ context: new RowContextMap(),
140
+ tableContexts: new Map(),
141
+ enableMetrics: false
142
+ };
143
+ return scheduler.run(runtimeCtx);
144
+ });
145
+ // Preserve the original node's type and attributes
146
+ const relType = node.getType();
147
+ const relNode = node;
148
+ const originalAttrs = [...relNode.getAttributes()];
149
+ const replacement = new TableLiteralNode(node.scope, iterable, relNode.estimatedRows, relType, originalAttrs);
150
+ log('Replaced relational node %s with TableLiteralNode', node.id);
151
+ return replacement;
152
+ }
153
+ catch (error) {
154
+ log('Failed to evaluate relational node %s: %s', node.nodeType, error);
155
+ throw new QuereusError('Relational evaluation failed', StatusCode.ERROR, error instanceof Error ? error : undefined);
156
+ }
157
+ };
158
+ }
53
159
  //# sourceMappingURL=const-evaluator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"const-evaluator.js","sourceRoot":"","sources":["../../../../src/planner/analysis/const-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,MAAM,GAAG,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,gCAAgC,CAAC,EAAY;IAC5D,OAAO,SAAS,kBAAkB,CAAC,IAAc;QAChD,GAAG,CAAC,oCAAoC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEzD,IAAI,CAAC;YACJ,oCAAoC;YACpC,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,CAAC;YAE5C,wCAAwC;YACxC,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAEpD,gDAAgD;YAChD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC;YAE7C,gDAAgD;YAChD,uEAAuE;YACvE,MAAM,UAAU,GAAmB;gBAClC,EAAE;gBACF,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,EAAE,EAAE,qCAAqC;gBACjD,OAAO,EAAE,IAAI,aAAa,EAAE,EAAE,wBAAwB;gBACtD,aAAa,EAAE,IAAI,GAAG,EAAE,EAAE,yCAAyC;gBACnE,aAAa,EAAE,KAAK;aACpB,CAAC;YAEF,6BAA6B;YAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAEzC,uCAAuC;YACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,YAAY,CAAC,0CAA0C,CAAC,CAAC;YACpE,CAAC;YAED,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;YAC3C,OAAO,MAAmC,CAAC;QAE5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,GAAG,CAAC,sCAAsC,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAClE,MAAM,IAAI,YAAY,CAAC,8BAA8B,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACtH,CAAC;IACF,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"const-evaluator.js","sourceRoot":"","sources":["../../../../src/planner/analysis/const-evaluator.ts"],"names":[],"mappings":"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"}
@@ -33,16 +33,18 @@ export interface ConstFoldingContext {
33
33
  borderNodes: Map<string, PlanNode>;
34
34
  /** Evaluation function for border expressions */
35
35
  evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>;
36
+ /** Evaluation function for relational border nodes */
37
+ evaluateRelation?: (node: PlanNode) => PlanNode;
36
38
  }
37
39
  /**
38
40
  * Create a new constant folding context
39
41
  */
40
- export declare function createConstFoldingContext(evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>): ConstFoldingContext;
42
+ export declare function createConstFoldingContext(evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>, evaluateRelation?: (node: PlanNode) => PlanNode): ConstFoldingContext;
41
43
  /**
42
44
  * Perform complete single-pass constant folding on a plan tree
43
45
  * This is the main entry point for efficient constant folding
44
46
  */
45
- export declare function performConstantFolding(root: PlanNode, evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>): PlanNode;
47
+ export declare function performConstantFolding(root: PlanNode, evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>, evaluateRelation?: (node: PlanNode) => PlanNode): PlanNode;
46
48
  /**
47
49
  * Perform bottom-up constant classification on a plan tree
48
50
  */
@@ -1 +1 @@
1
- {"version":3,"file":"const-pass.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/const-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAiB,KAAK,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAQtF;;GAEG;AACH,UAAU,cAAc;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;CACf;AAED,UAAU,YAAY;IACrB,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAClB;AAED,UAAU,YAAY;IACrB,IAAI,EAAE,WAAW,CAAC;CAClB;AAED,KAAK,SAAS,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,mDAAmD;IACnD,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,yDAAyD;IACzD,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,iDAAiD;IACjD,kBAAkB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,YAAY,CAAC,WAAW,CAAC,CAAC;CAClE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACxC,kBAAkB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,YAAY,CAAC,WAAW,CAAC,GAC/D,mBAAmB,CAMrB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,QAAQ,EACd,kBAAkB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,YAAY,CAAC,WAAW,CAAC,GAC/D,QAAQ,CAWV;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAehF"}
1
+ {"version":3,"file":"const-pass.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/const-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAiB,KAAK,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAQtF;;GAEG;AACH,UAAU,cAAc;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;CACf;AAED,UAAU,YAAY;IACrB,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAClB;AAED,UAAU,YAAY;IACrB,IAAI,EAAE,WAAW,CAAC;CAClB;AAED,KAAK,SAAS,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,mDAAmD;IACnD,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,yDAAyD;IACzD,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,iDAAiD;IACjD,kBAAkB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,YAAY,CAAC,WAAW,CAAC,CAAC;IAClE,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC;CAChD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACxC,kBAAkB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,YAAY,CAAC,WAAW,CAAC,EACjE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,QAAQ,GAC7C,mBAAmB,CAOrB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,QAAQ,EACd,kBAAkB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,YAAY,CAAC,WAAW,CAAC,EACjE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,QAAQ,GAC7C,QAAQ,CAWV;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAehF"}
@@ -14,19 +14,20 @@ const log = createLogger('optimizer:folding');
14
14
  /**
15
15
  * Create a new constant folding context
16
16
  */
17
- export function createConstFoldingContext(evaluateExpression) {
17
+ export function createConstFoldingContext(evaluateExpression, evaluateRelation) {
18
18
  return {
19
19
  constInfo: new Map(),
20
20
  borderNodes: new Map(),
21
- evaluateExpression
21
+ evaluateExpression,
22
+ evaluateRelation
22
23
  };
23
24
  }
24
25
  /**
25
26
  * Perform complete single-pass constant folding on a plan tree
26
27
  * This is the main entry point for efficient constant folding
27
28
  */
28
- export function performConstantFolding(root, evaluateExpression) {
29
- const ctx = createConstFoldingContext(evaluateExpression);
29
+ export function performConstantFolding(root, evaluateExpression, evaluateRelation) {
30
+ const ctx = createConstFoldingContext(evaluateExpression, evaluateRelation);
30
31
  // Phase 1: Bottom-up classification
31
32
  classifyConstants(root, ctx);
32
33
  // Phase 2: Top-down border detection with dependency resolution
@@ -108,13 +109,19 @@ function detectBorderNodes(node, ctx, knownConstAttrs = new Set()) {
108
109
  const nodeInfo = ctx.constInfo.get(node.id);
109
110
  // Check if this node is a border node
110
111
  if (nodeInfo?.kind === 'const') {
111
- if (!node.physical.constant) {
112
- // Const nodes are always border nodes
112
+ const typeClass = node.getType().typeClass;
113
+ if (!node.physical.constant && (typeClass === 'scalar' || typeClass === 'relation')) {
114
+ // Foldable const border node (scalar or relational)
113
115
  ctx.borderNodes.set(node.id, node);
114
116
  log('Detected const border node: %s (%s)', node.id, node.nodeType);
117
+ // Don't recurse into const subtrees - they'll all be replaced
118
+ return;
119
+ }
120
+ if (node.physical.constant) {
121
+ // Already a physical constant (e.g. LiteralNode) - no folding needed
122
+ return;
115
123
  }
116
- // Don't recurse into const subtrees - they'll all be replaced
117
- return;
124
+ // Non-foldable const node (e.g. Block with void type) - recurse to find inner borders
118
125
  }
119
126
  else if (nodeInfo?.kind === 'dep') {
120
127
  // Dep nodes become border nodes if all dependencies are resolved
@@ -171,9 +178,8 @@ function replaceBorderNodes(node, ctx) {
171
178
  // If this node is a border node, replace it
172
179
  if (ctx.borderNodes.has(node.id)) {
173
180
  try {
174
- const evaluatedValue = ctx.evaluateExpression(node);
175
- // Choose replacement type based on node type
176
181
  if (node.getType().typeClass === 'scalar') {
182
+ const evaluatedValue = ctx.evaluateExpression(node);
177
183
  const literalExpr = { type: 'literal', value: evaluatedValue };
178
184
  const replacement = new LiteralNode(node.scope, literalExpr,
179
185
  // Preserve the original node's type metadata so that information like
@@ -182,10 +188,14 @@ function replaceBorderNodes(node, ctx) {
182
188
  log('Replaced scalar border node %s with LiteralNode', node.id);
183
189
  return replacement;
184
190
  }
185
- else {
191
+ else if (ctx.evaluateRelation) {
186
192
  // Relational node - replace with TableLiteralNode
187
- // TODO: Handle relational evaluation properly
188
- log('Relational border node %s detected but not yet implemented', node.id);
193
+ const replacement = ctx.evaluateRelation(node);
194
+ log('Replaced relational border node %s with TableLiteralNode', node.id);
195
+ return replacement;
196
+ }
197
+ else {
198
+ log('Relational border node %s skipped (no relational evaluator)', node.id);
189
199
  return node;
190
200
  }
191
201
  }
@@ -1 +1 @@
1
- {"version":3,"file":"const-pass.js","sourceRoot":"","sources":["../../../../src/planner/analysis/const-pass.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"const-pass.js","sourceRoot":"","sources":["../../../../src/planner/analysis/const-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAItD,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAmC9C;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACxC,kBAAiE,EACjE,gBAA+C;IAE/C,OAAO;QACN,SAAS,EAAE,IAAI,GAAG,EAAE;QACpB,WAAW,EAAE,IAAI,GAAG,EAAE;QACtB,kBAAkB;QAClB,gBAAgB;KAChB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACrC,IAAc,EACd,kBAAiE,EACjE,gBAA+C;IAE/C,MAAM,GAAG,GAAG,yBAAyB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IAE5E,oCAAoC;IACpC,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE7B,gEAAgE;IAChE,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IAExC,gCAAgC;IAChC,OAAO,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAc,EAAE,GAAwB;IACzE,mDAAmD;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC9B,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,oDAAoD;IACpD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1C,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAEtC,GAAG,CAAC,6BAA6B,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EACxD,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACtC,SAAS,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7E,WAAW,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAc,EAAE,GAAwB;IAC7D,mDAAmD;IACnD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC5B,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACxB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACtC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,gDAAgD,CAAC,CAAC;IAC/E,CAAC;IAED,8CAA8C;IAC9C,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,eAAe,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAA2B,CAAA;QAC1C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;IAC7D,CAAC;IAED,oEAAoE;IACpE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC9B,CAAC;IAED,mEAAmE;IACnE,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QACtD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,iDAAiD;IACjD,+DAA+D;IAC/D,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;QACxF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,gEAAgE;IAChE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAC/G,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClB,CAAC;YACF,CAAC;QACF,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACvC,CAAC;IAED,wBAAwB;IACxB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CACzB,IAAc,EACd,GAAwB,EACxB,kBAA+B,IAAI,GAAG,EAAE;IAExC,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAE5C,sCAAsC;IACtC,IAAI,QAAQ,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,UAAU,CAAC,EAAE,CAAC;YACrF,oDAAoD;YACpD,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACnC,GAAG,CAAC,qCAAqC,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnE,8DAA8D;YAC9D,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5B,qEAAqE;YACrE,OAAO;QACR,CAAC;QACD,sFAAsF;IACvF,CAAC;SAAM,IAAI,QAAQ,EAAE,IAAI,KAAK,KAAK,EAAE,CAAC;QACrC,iEAAiE;QACjE,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACnC,GAAG,CAAC,qEAAqE,EACxE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EACtB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EACnC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxC,uDAAuD;YACvD,OAAO;QACR,CAAC;IACF,CAAC;IAED,kDAAkD;IAClD,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;IAEnD,iGAAiG;IACjG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,KAAK,UAAU,IAAI,mBAAmB,IAAI,IAAI,EAAE,CAAC;QAC5E,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAkB,EAAE,CAAC;QAEjD,IAAI,cAAc,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,cAAc,EAAE,CAAC;gBAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAE5C,IAAI,QAAQ,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;oBAChC,gDAAgD;oBAChD,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAC9B,GAAG,CAAC,wCAAwC,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBAChE,CAAC;qBAAM,IAAI,QAAQ,EAAE,IAAI,KAAK,KAAK,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;oBACnF,yEAAyE;oBACzE,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAC9B,GAAG,CAAC,iEAAiE,EACpE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxD,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,6DAA6D;IAC7D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAClD,CAAC;AACF,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAI,IAAY,EAAE,IAAY;IAChD,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,oCAAoC;IACtE,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,IAAc,EAAE,GAAwB;IACnE,4CAA4C;IAC5C,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACJ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAC3C,MAAM,cAAc,GAAG,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBACpD,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,SAAkB,EAAE,KAAK,EAAE,cAA0B,EAAE,CAAC;gBAEpF,MAAM,WAAW,GAAG,IAAI,WAAW,CAClC,IAAI,CAAC,KAAK,EACV,WAAW;gBACX,sEAAsE;gBACtE,iDAAiD;gBACjD,IAAI,CAAC,OAAO,EAAgB,CAC5B,CAAC;gBACF,GAAG,CAAC,iDAAiD,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChE,OAAO,WAAW,CAAC;YACpB,CAAC;iBAAM,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBACjC,kDAAkD;gBAClD,MAAM,WAAW,GAAG,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBAC/C,GAAG,CAAC,0DAA0D,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzE,OAAO,WAAW,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACP,GAAG,CAAC,6DAA6D,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC5E,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,GAAG,CAAC,uCAAuC,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAE/E,2CAA2C;IAC3C,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -3,8 +3,24 @@
3
3
  * Converts scalar expressions into constraints that can be pushed down to virtual tables
4
4
  */
5
5
  import type { ScalarPlanNode, RelationalPlanNode, PlanNode } from '../nodes/plan-node.js';
6
- import type { Row } from '../../common/types.js';
6
+ import type { Row, SqlValue } from '../../common/types.js';
7
7
  import type { PredicateConstraint as VtabPredicateConstraint } from '../../vtab/best-access-plan.js';
8
+ /**
9
+ * A single range specification within an OR_RANGE constraint.
10
+ * Each range has optional lower and upper bounds.
11
+ */
12
+ export interface RangeSpec {
13
+ lower?: {
14
+ op: '>=' | '>';
15
+ value: SqlValue;
16
+ valueExpr?: ScalarPlanNode;
17
+ };
18
+ upper?: {
19
+ op: '<=' | '<';
20
+ value: SqlValue;
21
+ valueExpr?: ScalarPlanNode;
22
+ };
23
+ }
8
24
  /**
9
25
  * A constraint extracted from a predicate expression
10
26
  * Extends the vtab PredicateConstraint with additional metadata for the planner
@@ -20,6 +36,8 @@ export interface PredicateConstraint extends VtabPredicateConstraint {
20
36
  valueExpr?: ScalarPlanNode | ScalarPlanNode[];
21
37
  /** Binding kind describing how value is supplied */
22
38
  bindingKind?: 'literal' | 'parameter' | 'correlated' | 'expression' | 'mixed';
39
+ /** Range specifications for OR_RANGE constraints */
40
+ ranges?: RangeSpec[];
23
41
  }
24
42
  /**
25
43
  * Result of constraint extraction
@@ -1 +1 @@
1
- {"version":3,"file":"constraint-extractor.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/constraint-extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constraint-extractor.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/constraint-extractor.ts"],"names":[],"mappings":"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"}
@@ -108,9 +108,18 @@ function extractFromExpression(expr, constraints, residual, attributeToTableMap,
108
108
  extractFromExpression(binaryOp.right, constraints, residual, attributeToTableMap, perTableParts);
109
109
  return;
110
110
  }
111
- // Handle OR expressions - for now, treat as residual (could be enhanced later)
111
+ // Handle OR expressions: try to extract as IN or OR constraint group
112
112
  if (isOrExpression(expr)) {
113
- log('OR expression found, treating as residual: %s', expr.toString());
113
+ const orResult = tryExtractOrBranches(expr, attributeToTableMap);
114
+ if (orResult) {
115
+ for (const c of orResult.constraints) {
116
+ constraints.push(c);
117
+ }
118
+ addSupportedPart(expr, attributeToTableMap, perTableParts);
119
+ log('OR expression extracted %d constraints', orResult.constraints.length);
120
+ return;
121
+ }
122
+ log('OR expression not extractable, treating as residual');
114
123
  residual.push(expr);
115
124
  return;
116
125
  }
@@ -132,6 +141,18 @@ function extractFromExpression(expr, constraints, residual, attributeToTableMap,
132
141
  return;
133
142
  }
134
143
  }
144
+ // IS NULL / IS NOT NULL → unary constraint
145
+ if (expr.nodeType === PlanNodeType.UnaryOp) {
146
+ const unaryOp = expr;
147
+ if (unaryOp.expression.operator === 'IS NULL' || unaryOp.expression.operator === 'IS NOT NULL') {
148
+ const c = extractNullConstraint(unaryOp, attributeToTableMap);
149
+ if (c) {
150
+ constraints.push(c);
151
+ addSupportedPart(expr, attributeToTableMap, perTableParts);
152
+ return;
153
+ }
154
+ }
155
+ }
135
156
  // Try to extract constraint from binary comparison
136
157
  const constraint = extractBinaryConstraint(expr, attributeToTableMap);
137
158
  if (constraint) {
@@ -318,7 +339,7 @@ function extractBetweenConstraints(expr, attributeToTableMap) {
318
339
  ];
319
340
  }
320
341
  function extractInConstraint(expr, attributeToTableMap) {
321
- // Only support column IN (literal, ...)
342
+ // Only support column IN (value-list), not subqueries
322
343
  if (expr.source)
323
344
  return null;
324
345
  if (!expr.values || expr.values.length === 0)
@@ -326,9 +347,6 @@ function extractInConstraint(expr, attributeToTableMap) {
326
347
  const col = expr.condition;
327
348
  if (col.nodeType !== PlanNodeType.ColumnReference)
328
349
  return null;
329
- // Ensure all are literals
330
- if (!expr.values.every(v => isLiteralConstant(v)))
331
- return null;
332
350
  const columnRef = col;
333
351
  const tableInfo = attributeToTableMap.get(columnRef.attributeId);
334
352
  if (!tableInfo)
@@ -336,10 +354,15 @@ function extractInConstraint(expr, attributeToTableMap) {
336
354
  const columnIndex = tableInfo.columnIndexMap.get(columnRef.attributeId);
337
355
  if (columnIndex === undefined)
338
356
  return null;
339
- // Virtual table IN constraint can carry a single array value or multiple equality constraints.
340
- // Our API supports op 'IN' with value array.
341
- const values = expr.values.map(v => getLiteralValue(v));
342
- return {
357
+ // Check if all values are literals, or if some are dynamic (parameters/expressions)
358
+ const allLiteral = expr.values.every(v => isLiteralConstant(v));
359
+ const allUsable = expr.values.every(v => isLiteralConstant(v) || isDynamicValue(v));
360
+ if (!allUsable)
361
+ return null;
362
+ const values = allLiteral
363
+ ? expr.values.map(v => getLiteralValue(v))
364
+ : expr.values.map(v => isLiteralConstant(v) ? getLiteralValue(v) : undefined);
365
+ const result = {
343
366
  columnIndex,
344
367
  attributeId: columnRef.attributeId,
345
368
  op: 'IN',
@@ -349,6 +372,38 @@ function extractInConstraint(expr, attributeToTableMap) {
349
372
  sourceExpression: expr,
350
373
  targetRelation: tableInfo.relationKey
351
374
  };
375
+ // Attach dynamic binding metadata when not all values are literals
376
+ if (!allLiteral) {
377
+ result.valueExpr = expr.values;
378
+ result.bindingKind = 'mixed';
379
+ }
380
+ return result;
381
+ }
382
+ /**
383
+ * Extract constraint from IS NULL / IS NOT NULL unary expression
384
+ */
385
+ function extractNullConstraint(expr, attributeToTableMap) {
386
+ const operand = expr.operand;
387
+ if (!isColumnReference(operand))
388
+ return null;
389
+ const columnRef = getColumnReference(operand);
390
+ const tableInfo = attributeToTableMap.get(columnRef.attributeId);
391
+ if (!tableInfo)
392
+ return null;
393
+ const columnIndex = tableInfo.columnIndexMap.get(columnRef.attributeId);
394
+ if (columnIndex === undefined)
395
+ return null;
396
+ const op = expr.expression.operator;
397
+ return {
398
+ columnIndex,
399
+ attributeId: columnRef.attributeId,
400
+ op,
401
+ value: undefined,
402
+ usable: true,
403
+ sourceExpression: expr,
404
+ targetRelation: tableInfo.relationKey,
405
+ bindingKind: 'literal'
406
+ };
352
407
  }
353
408
  /**
354
409
  * Map AST operators to constraint operators
@@ -365,13 +420,209 @@ function mapOperatorToConstraint(operator, _rightValue) {
365
420
  case 'MATCH': return 'MATCH';
366
421
  case 'IN': return 'IN';
367
422
  case 'NOT IN': return 'NOT IN';
368
- // NOTE: IS NULL / IS NOT NULL are parsed as unary expressions, not binary
369
- // 'IS' / 'IS NOT'. To support constraint extraction for these, add unary
370
- // expression handling in extractConstraints alongside a proper
371
- // empty-result physical node for the IS NULL on NOT NULL optimization.
372
423
  default: return null;
373
424
  }
374
425
  }
426
+ /**
427
+ * Flatten an OR expression tree into a list of disjuncts.
428
+ */
429
+ function flattenOrDisjuncts(expr) {
430
+ const result = [];
431
+ const stack = [expr];
432
+ while (stack.length > 0) {
433
+ const node = stack.pop();
434
+ if (isOrExpression(node)) {
435
+ const binary = node;
436
+ stack.push(binary.right, binary.left);
437
+ }
438
+ else {
439
+ result.push(node);
440
+ }
441
+ }
442
+ return result;
443
+ }
444
+ /**
445
+ * Attempt to extract index-friendly constraints from an OR expression.
446
+ *
447
+ * Handles two cases:
448
+ * 1. All branches are equality on the same column → collapse to IN constraint
449
+ * 2. All branches target the same table with extractable constraints → OR constraint group
450
+ *
451
+ * Returns null if the OR cannot be extracted (remains residual).
452
+ */
453
+ function tryExtractOrBranches(expr, attributeToTableMap) {
454
+ const disjuncts = flattenOrDisjuncts(expr);
455
+ if (disjuncts.length < 2)
456
+ return null;
457
+ // Extract constraints from each branch independently
458
+ const branches = [];
459
+ for (const d of disjuncts) {
460
+ const branchConstraints = [];
461
+ const branchResidual = [];
462
+ const branchParts = new Map();
463
+ extractFromExpression(d, branchConstraints, branchResidual, attributeToTableMap, branchParts);
464
+ branches.push({
465
+ constraints: branchConstraints,
466
+ hasResidual: branchResidual.length > 0
467
+ });
468
+ }
469
+ // If any branch has residual (not fully extractable), the entire OR must be residual.
470
+ // We can't partially push down an OR — all branches must be handled.
471
+ if (branches.some(b => b.hasResidual || b.constraints.length === 0)) {
472
+ return null;
473
+ }
474
+ // Check if all branches target the same table
475
+ const allRelations = new Set();
476
+ for (const b of branches) {
477
+ for (const c of b.constraints) {
478
+ if (c.targetRelation)
479
+ allRelations.add(c.targetRelation);
480
+ }
481
+ }
482
+ if (allRelations.size !== 1)
483
+ return null;
484
+ // Case 1: All branches are single equality or IN on the same column → collapse to IN
485
+ const allEqOrIn = branches.every(b => b.constraints.length === 1 &&
486
+ (b.constraints[0].op === '=' || b.constraints[0].op === 'IN'));
487
+ if (allEqOrIn) {
488
+ const firstConstraint = branches[0].constraints[0];
489
+ const sameColumn = branches.every(b => b.constraints[0].columnIndex === firstConstraint.columnIndex &&
490
+ b.constraints[0].attributeId === firstConstraint.attributeId);
491
+ if (sameColumn) {
492
+ return collapseBranchesToIn(branches, firstConstraint, expr);
493
+ }
494
+ }
495
+ // Case 2: All branches are range (or equality) on the same column → OR_RANGE
496
+ const orRangeResult = tryCollapseToOrRange(branches, expr);
497
+ if (orRangeResult)
498
+ return orRangeResult;
499
+ return null;
500
+ }
501
+ /**
502
+ * Collapse OR branches (equality and/or IN) on the same column into a single IN constraint.
503
+ * Handles mixed equality + IN branches (e.g., from nested OR normalization)
504
+ * and both literal and non-literal (parameter, expression) values.
505
+ */
506
+ function collapseBranchesToIn(branches, template, sourceExpr) {
507
+ const values = [];
508
+ const valueExprs = [];
509
+ let hasNonLiteral = false;
510
+ for (const b of branches) {
511
+ const c = b.constraints[0];
512
+ if (c.op === 'IN' && Array.isArray(c.value)) {
513
+ // IN branch: merge all its values
514
+ for (const v of c.value) {
515
+ values.push(v);
516
+ }
517
+ if (Array.isArray(c.valueExpr)) {
518
+ for (const ve of c.valueExpr) {
519
+ valueExprs.push(ve);
520
+ }
521
+ hasNonLiteral = true;
522
+ }
523
+ else {
524
+ // All literal IN — push placeholder source expressions
525
+ for (const _v of c.value) {
526
+ valueExprs.push(c.sourceExpression);
527
+ }
528
+ }
529
+ }
530
+ else {
531
+ // Equality branch: single value
532
+ values.push(c.value);
533
+ if (c.valueExpr && !Array.isArray(c.valueExpr)) {
534
+ valueExprs.push(c.valueExpr);
535
+ hasNonLiteral = true;
536
+ }
537
+ else {
538
+ valueExprs.push(c.sourceExpression);
539
+ }
540
+ }
541
+ }
542
+ const result = {
543
+ columnIndex: template.columnIndex,
544
+ attributeId: template.attributeId,
545
+ op: 'IN',
546
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
547
+ value: values,
548
+ usable: true,
549
+ sourceExpression: sourceExpr,
550
+ targetRelation: template.targetRelation,
551
+ valueExpr: hasNonLiteral ? valueExprs : undefined,
552
+ bindingKind: hasNonLiteral ? 'mixed' : 'literal'
553
+ };
554
+ return { constraints: [result] };
555
+ }
556
+ /**
557
+ * Collapse OR branches that are all range/equality constraints on the same column
558
+ * into a single OR_RANGE constraint with multiple range specs.
559
+ */
560
+ function tryCollapseToOrRange(branches, sourceExpr) {
561
+ // All branches must have constraints on a single column (possibly multiple for BETWEEN-style ranges)
562
+ let targetColumnIndex;
563
+ let targetAttributeId;
564
+ let targetRelation;
565
+ const rangeSpecs = [];
566
+ for (const b of branches) {
567
+ // A branch may have 1 constraint (single bound or equality) or 2 constraints (lower + upper on same col)
568
+ if (b.constraints.length === 0 || b.constraints.length > 2)
569
+ return null;
570
+ // All constraints in this branch must target the same column
571
+ const firstCol = b.constraints[0].columnIndex;
572
+ const firstAttr = b.constraints[0].attributeId;
573
+ const firstRel = b.constraints[0].targetRelation;
574
+ if (!b.constraints.every(c => c.columnIndex === firstCol))
575
+ return null;
576
+ // Initialize target or verify consistency across branches
577
+ if (targetColumnIndex === undefined) {
578
+ targetColumnIndex = firstCol;
579
+ targetAttributeId = firstAttr;
580
+ targetRelation = firstRel;
581
+ }
582
+ else if (targetColumnIndex !== firstCol || targetAttributeId !== firstAttr) {
583
+ return null;
584
+ }
585
+ // Build range spec from branch constraints
586
+ const spec = {};
587
+ for (const c of b.constraints) {
588
+ const dynExpr = c.valueExpr && !Array.isArray(c.valueExpr) ? c.valueExpr : undefined;
589
+ if (c.op === '=') {
590
+ // Equality: treat as >= v AND <= v
591
+ spec.lower = { op: '>=', value: c.value, valueExpr: dynExpr };
592
+ spec.upper = { op: '<=', value: c.value, valueExpr: dynExpr };
593
+ }
594
+ else if (c.op === '>' || c.op === '>=') {
595
+ spec.lower = { op: c.op, value: c.value, valueExpr: dynExpr };
596
+ }
597
+ else if (c.op === '<' || c.op === '<=') {
598
+ spec.upper = { op: c.op, value: c.value, valueExpr: dynExpr };
599
+ }
600
+ else {
601
+ // Non-range, non-equality op → can't collapse
602
+ return null;
603
+ }
604
+ }
605
+ // Each branch must define at least one bound
606
+ if (!spec.lower && !spec.upper)
607
+ return null;
608
+ rangeSpecs.push(spec);
609
+ }
610
+ if (targetColumnIndex === undefined || targetAttributeId === undefined || rangeSpecs.length < 2) {
611
+ return null;
612
+ }
613
+ const result = {
614
+ columnIndex: targetColumnIndex,
615
+ attributeId: targetAttributeId,
616
+ op: 'OR_RANGE',
617
+ value: undefined,
618
+ usable: true,
619
+ sourceExpression: sourceExpr,
620
+ targetRelation: targetRelation,
621
+ bindingKind: 'literal',
622
+ ranges: rangeSpecs,
623
+ };
624
+ return { constraints: [result] };
625
+ }
375
626
  /**
376
627
  * Check if expression is an AND operation
377
628
  */