@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
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Rule: Scalar Common Subexpression Elimination (CSE)
3
+ *
4
+ * Detects duplicate scalar expression computations across a ProjectNode and
5
+ * its immediate relational child chain (Filter, Sort), then injects a
6
+ * lower ProjectNode that computes each deduplicated expression once.
7
+ *
8
+ * Guards:
9
+ * - Only deduplicate deterministic expressions
10
+ * - Skip bare column references and literals (cost 0, cheap to recompute)
11
+ * - Require at least 2 occurrences of the same fingerprint
12
+ *
13
+ * Pass: Structural (top-down), priority 22
14
+ * Node type: PlanNodeType.Project
15
+ */
16
+ import type { PlanNode } from '../../nodes/plan-node.js';
17
+ import type { OptContext } from '../../framework/context.js';
18
+ export declare function ruleScalarCSE(node: PlanNode, _context: OptContext): PlanNode | null;
19
+ //# sourceMappingURL=rule-scalar-cse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-scalar-cse.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-scalar-cse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAiD,MAAM,0BAA0B,CAAC;AAExG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AA0F7D,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAkOnF"}
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Rule: Scalar Common Subexpression Elimination (CSE)
3
+ *
4
+ * Detects duplicate scalar expression computations across a ProjectNode and
5
+ * its immediate relational child chain (Filter, Sort), then injects a
6
+ * lower ProjectNode that computes each deduplicated expression once.
7
+ *
8
+ * Guards:
9
+ * - Only deduplicate deterministic expressions
10
+ * - Skip bare column references and literals (cost 0, cheap to recompute)
11
+ * - Require at least 2 occurrences of the same fingerprint
12
+ *
13
+ * Pass: Structural (top-down), priority 22
14
+ * Node type: PlanNodeType.Project
15
+ */
16
+ import { createLogger } from '../../../common/logger.js';
17
+ import { PlanNode as PlanNodeClass } from '../../nodes/plan-node.js';
18
+ import { PlanNodeType } from '../../nodes/plan-node-type.js';
19
+ import { ProjectNode } from '../../nodes/project-node.js';
20
+ import { FilterNode } from '../../nodes/filter.js';
21
+ import { SortNode } from '../../nodes/sort.js';
22
+ import { ColumnReferenceNode } from '../../nodes/reference.js';
23
+ import { fingerprintExpression } from '../../analysis/expression-fingerprint.js';
24
+ const log = createLogger('optimizer:rule:scalar-cse');
25
+ /**
26
+ * Recursively collect all scalar subexpression locations from a scalar expression tree.
27
+ * Each subexpression that is non-trivial and deterministic gets its own location entry.
28
+ */
29
+ function collectSubexpressions(root, owner, index, out) {
30
+ // Skip column references and literals - they're trivially cheap
31
+ if (root.nodeType === PlanNodeType.ColumnReference || root.nodeType === PlanNodeType.Literal) {
32
+ return;
33
+ }
34
+ // Skip non-deterministic expressions
35
+ if (root.physical.deterministic === false) {
36
+ return;
37
+ }
38
+ // Skip parameter references - cheap to evaluate
39
+ if (root.nodeType === PlanNodeType.ParameterReference) {
40
+ return;
41
+ }
42
+ out.push({ owner, index, node: root });
43
+ // Recurse into children (scalar children only)
44
+ for (const child of root.getChildren()) {
45
+ if (child.getType().typeClass === 'scalar') {
46
+ collectSubexpressions(child, owner, index, out);
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Collect the relational child chain under a ProjectNode.
52
+ * Returns [filter?, sort?, bottomSource] where filter/sort are optional
53
+ * intermediate nodes and bottomSource is the first non-Filter/non-Sort child.
54
+ */
55
+ function collectChain(project) {
56
+ let current = project.source;
57
+ let filter = null;
58
+ let sort = null;
59
+ // Walk at most two levels: Filter then Sort, or Sort then Filter
60
+ for (let i = 0; i < 2; i++) {
61
+ if (!filter && current instanceof FilterNode) {
62
+ filter = current;
63
+ current = current.source;
64
+ }
65
+ else if (!sort && current instanceof SortNode) {
66
+ sort = current;
67
+ current = current.source;
68
+ }
69
+ else {
70
+ break;
71
+ }
72
+ }
73
+ return { filter, sort, bottomSource: current };
74
+ }
75
+ export function ruleScalarCSE(node, _context) {
76
+ if (node.nodeType !== PlanNodeType.Project) {
77
+ return null;
78
+ }
79
+ const project = node;
80
+ const { filter, sort, bottomSource } = collectChain(project);
81
+ // Collect all subexpressions from the chain
82
+ const allLocations = [];
83
+ // Collect from projections
84
+ for (let i = 0; i < project.projections.length; i++) {
85
+ collectSubexpressions(project.projections[i].node, 'project', i, allLocations);
86
+ }
87
+ // Collect from filter predicate
88
+ if (filter) {
89
+ collectSubexpressions(filter.predicate, 'filter', 0, allLocations);
90
+ }
91
+ // Collect from sort keys
92
+ if (sort) {
93
+ for (let i = 0; i < sort.sortKeys.length; i++) {
94
+ collectSubexpressions(sort.sortKeys[i].expression, 'sort', i, allLocations);
95
+ }
96
+ }
97
+ if (allLocations.length === 0) {
98
+ return null;
99
+ }
100
+ // Group by fingerprint
101
+ const groups = new Map();
102
+ for (const loc of allLocations) {
103
+ const fp = fingerprintExpression(loc.node);
104
+ let group = groups.get(fp);
105
+ if (!group) {
106
+ group = [];
107
+ groups.set(fp, group);
108
+ }
109
+ group.push(loc);
110
+ }
111
+ // Find groups with duplicates (2+ locations with distinct node identities)
112
+ const duplicateGroups = [];
113
+ for (const [fingerprint, locations] of groups) {
114
+ // Deduplicate by node identity - same node object appearing in multiple positions
115
+ // counts as one, we need at least 2 distinct node instances
116
+ const uniqueNodes = new Set(locations.map(l => l.node));
117
+ if (uniqueNodes.size >= 2) {
118
+ duplicateGroups.push({ fingerprint, locations });
119
+ }
120
+ }
121
+ if (duplicateGroups.length === 0) {
122
+ return null;
123
+ }
124
+ log('Found %d duplicate expression groups in Project chain', duplicateGroups.length);
125
+ // For each duplicate group, pick the canonical instance and create a computed column
126
+ const injectedProjections = [];
127
+ const injectedAttributes = [];
128
+ // Map from canonical node id to the new attribute/column ref info
129
+ const replacements = new Map();
130
+ // We'll build the injected projections: passthrough of bottomSource + computed columns
131
+ // First, collect passthrough from the bottomSource
132
+ const bottomAttrs = bottomSource.getAttributes();
133
+ // Index for the new columns starts after passthrough columns
134
+ let nextColIndex = bottomAttrs.length;
135
+ for (const group of duplicateGroups) {
136
+ const canonical = group.locations[0].node;
137
+ const attrId = PlanNodeClass.nextAttrId();
138
+ const alias = `$cse_${attrId}`;
139
+ const colRefExpr = {
140
+ type: 'column',
141
+ name: alias,
142
+ };
143
+ const colRef = new ColumnReferenceNode(project.scope, colRefExpr, canonical.getType(), attrId, nextColIndex);
144
+ injectedProjections.push({
145
+ node: canonical,
146
+ alias,
147
+ attributeId: attrId,
148
+ });
149
+ injectedAttributes.push({
150
+ id: attrId,
151
+ name: alias,
152
+ type: canonical.getType(),
153
+ sourceRelation: 'cse',
154
+ relationName: 'cse',
155
+ });
156
+ replacements.set(group.fingerprint, { attrId, colRef, canonical });
157
+ nextColIndex++;
158
+ }
159
+ // Build the passthrough projections for the injected ProjectNode
160
+ const passthroughProjections = bottomAttrs.map((attr, i) => {
161
+ const colRefExpr = {
162
+ type: 'column',
163
+ name: attr.name,
164
+ };
165
+ const colRef = new ColumnReferenceNode(project.scope, colRefExpr, attr.type, attr.id, i);
166
+ return {
167
+ node: colRef,
168
+ alias: attr.name,
169
+ attributeId: attr.id,
170
+ };
171
+ });
172
+ // Combine passthrough + computed projections
173
+ const allInjectedProjections = [...passthroughProjections, ...injectedProjections];
174
+ // Build predefined attributes for the injected ProjectNode
175
+ const predefinedAttributes = [
176
+ ...bottomAttrs.map(a => ({ ...a })),
177
+ ...injectedAttributes,
178
+ ];
179
+ // Create the injected ProjectNode
180
+ const injectedProject = new ProjectNode(project.scope, bottomSource, allInjectedProjections, undefined, predefinedAttributes, true // preserveInputColumns
181
+ );
182
+ // Now replace all duplicate occurrences in the outer nodes with ColumnReferenceNodes
183
+ // We need to rebuild: project projections, filter predicate, sort keys
184
+ // Helper: replace all occurrences of any duplicate group's nodes with colRefs
185
+ function replaceAllDuplicates(expr) {
186
+ // Check if this exact expression matches a fingerprint group
187
+ if (expr.nodeType !== PlanNodeType.ColumnReference &&
188
+ expr.nodeType !== PlanNodeType.Literal &&
189
+ expr.nodeType !== PlanNodeType.ParameterReference &&
190
+ expr.physical.deterministic !== false) {
191
+ const fp = fingerprintExpression(expr);
192
+ const rep = replacements.get(fp);
193
+ if (rep) {
194
+ return rep.colRef;
195
+ }
196
+ }
197
+ // Recurse into children
198
+ const children = expr.getChildren();
199
+ if (children.length === 0)
200
+ return expr;
201
+ const newChildren = [];
202
+ let changed = false;
203
+ for (const child of children) {
204
+ if (child.getType().typeClass === 'scalar') {
205
+ const replaced = replaceAllDuplicates(child);
206
+ newChildren.push(replaced);
207
+ if (replaced !== child)
208
+ changed = true;
209
+ }
210
+ else {
211
+ newChildren.push(child);
212
+ }
213
+ }
214
+ if (!changed)
215
+ return expr;
216
+ return expr.withChildren(newChildren);
217
+ }
218
+ // Rebuild sort (innermost in the outer chain, sits on injectedProject)
219
+ let newSortOrSource = injectedProject;
220
+ if (sort) {
221
+ const newSortKeys = sort.sortKeys.map(key => ({
222
+ expression: replaceAllDuplicates(key.expression),
223
+ direction: key.direction,
224
+ nulls: key.nulls,
225
+ }));
226
+ newSortOrSource = new SortNode(sort.scope, injectedProject, newSortKeys);
227
+ }
228
+ // Rebuild filter
229
+ let newFilterOrSource = newSortOrSource;
230
+ if (filter) {
231
+ const newPredicate = replaceAllDuplicates(filter.predicate);
232
+ newFilterOrSource = new FilterNode(filter.scope, newSortOrSource, newPredicate);
233
+ }
234
+ // Rebuild the outer project
235
+ const origAttributes = project.getAttributes();
236
+ const newProjections = project.projections.map((proj, i) => ({
237
+ node: replaceAllDuplicates(proj.node),
238
+ alias: proj.alias,
239
+ attributeId: origAttributes[i].id,
240
+ }));
241
+ const newProject = new ProjectNode(project.scope, newFilterOrSource, newProjections, undefined, origAttributes, project.preserveInputColumns);
242
+ log('Injected CSE ProjectNode with %d computed columns', injectedProjections.length);
243
+ return newProject;
244
+ }
245
+ //# sourceMappingURL=rule-scalar-cse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-scalar-cse.js","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-scalar-cse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Rule: Filter Merge
3
+ *
4
+ * Merges adjacent Filter nodes into a single Filter with an AND-combined predicate.
5
+ *
6
+ * Filter(pred_outer) → Filter(pred_inner) → source
7
+ * becomes:
8
+ * Filter(pred_outer AND pred_inner) → source
9
+ *
10
+ * Always safe: the conjunction is semantically identical.
11
+ */
12
+ import type { PlanNode } from '../../nodes/plan-node.js';
13
+ import type { OptContext } from '../../framework/context.js';
14
+ export declare function ruleFilterMerge(node: PlanNode, _context: OptContext): PlanNode | null;
15
+ //# sourceMappingURL=rule-filter-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-filter-merge.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-filter-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAQ7D,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAsBrF"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Rule: Filter Merge
3
+ *
4
+ * Merges adjacent Filter nodes into a single Filter with an AND-combined predicate.
5
+ *
6
+ * Filter(pred_outer) → Filter(pred_inner) → source
7
+ * becomes:
8
+ * Filter(pred_outer AND pred_inner) → source
9
+ *
10
+ * Always safe: the conjunction is semantically identical.
11
+ */
12
+ import { createLogger } from '../../../common/logger.js';
13
+ import { PlanNodeType } from '../../nodes/plan-node-type.js';
14
+ import { FilterNode } from '../../nodes/filter.js';
15
+ import { BinaryOpNode } from '../../nodes/scalar.js';
16
+ const log = createLogger('optimizer:rule:filter-merge');
17
+ export function ruleFilterMerge(node, _context) {
18
+ if (node.nodeType !== PlanNodeType.Filter)
19
+ return null;
20
+ let current = node;
21
+ if (current.source.nodeType !== PlanNodeType.Filter)
22
+ return null;
23
+ // Iteratively absorb all adjacent filters (handles triple+ stacks in one visit)
24
+ let predicate = current.predicate;
25
+ while (current.source.nodeType === PlanNodeType.Filter) {
26
+ const inner = current.source;
27
+ const ast = {
28
+ type: 'binary',
29
+ operator: 'AND',
30
+ left: predicate.expression,
31
+ right: inner.predicate.expression,
32
+ };
33
+ predicate = new BinaryOpNode(current.scope, ast, predicate, inner.predicate);
34
+ current = inner;
35
+ }
36
+ log('Merged adjacent filters into single AND predicate');
37
+ return new FilterNode(node.scope, current.source, predicate);
38
+ }
39
+ //# sourceMappingURL=rule-filter-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-filter-merge.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-filter-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,MAAM,GAAG,GAAG,YAAY,CAAC,6BAA6B,CAAC,CAAC;AAExD,MAAM,UAAU,eAAe,CAAC,IAAc,EAAE,QAAoB;IACnE,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,OAAO,GAAG,IAAkB,CAAC;IAEjC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,YAAY,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEjE,gFAAgF;IAChF,IAAI,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAClC,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,YAAY,CAAC,MAAM,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAoB,CAAC;QAC3C,MAAM,GAAG,GAAmB;YAC3B,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,KAAK;YACf,IAAI,EAAG,SAAiB,CAAC,UAAU;YACnC,KAAK,EAAG,KAAK,CAAC,SAAiB,CAAC,UAAU;SAC1C,CAAC;QACF,SAAS,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7E,OAAO,GAAG,KAAK,CAAC;IACjB,CAAC;IAED,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACzD,OAAO,IAAI,UAAU,CAAE,IAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC9E,CAAC"}
@@ -7,6 +7,7 @@
7
7
  * Safe moves implemented now:
8
8
  * - Across Sort: always safe (ordering unaffected by selection)
9
9
  * - Across Distinct: safe for selection predicates (commute)
10
+ * - Across Alias: safe because AliasNode only renames relationName; attribute IDs are unchanged
10
11
  * - Across Project: only if predicate references attribute IDs available below the Project source
11
12
  * (we verify attribute-id coverage), and we keep predicate unchanged (IDs preserved by design)
12
13
  * - Into Retrieve: wrap Retrieve.source with a Filter
@@ -1 +1 @@
1
- {"version":3,"file":"rule-predicate-pushdown.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-pushdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AAE7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAe7D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAc3F"}
1
+ {"version":3,"file":"rule-predicate-pushdown.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-pushdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AAE7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAgB7D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAc3F"}
@@ -7,6 +7,7 @@
7
7
  * Safe moves implemented now:
8
8
  * - Across Sort: always safe (ordering unaffected by selection)
9
9
  * - Across Distinct: safe for selection predicates (commute)
10
+ * - Across Alias: safe because AliasNode only renames relationName; attribute IDs are unchanged
10
11
  * - Across Project: only if predicate references attribute IDs available below the Project source
11
12
  * (we verify attribute-id coverage), and we keep predicate unchanged (IDs preserved by design)
12
13
  * - Into Retrieve: wrap Retrieve.source with a Filter
@@ -23,6 +24,7 @@ import { SortNode } from '../../nodes/sort.js';
23
24
  import { DistinctNode } from '../../nodes/distinct-node.js';
24
25
  import { ProjectNode } from '../../nodes/project-node.js';
25
26
  import { RetrieveNode } from '../../nodes/retrieve-node.js';
27
+ import { AliasNode } from '../../nodes/alias-node.js';
26
28
  import { CapabilityDetectors } from '../../framework/characteristics.js';
27
29
  import { normalizePredicate } from '../../analysis/predicate-normalizer.js';
28
30
  import { collectBindingsInExpr } from '../../analysis/binding-collector.js';
@@ -65,6 +67,13 @@ function tryPushDown(child, predicate, scope) {
65
67
  }
66
68
  return new FilterNode(scope, updatedRetrieve, extraction.residualPredicate);
67
69
  }
70
+ // Across AliasNode (view boundary)
71
+ if (child instanceof AliasNode) {
72
+ log('Pushing predicate below AliasNode');
73
+ const under = child.source;
74
+ const newUnder = new FilterNode(under.scope, under, predicate);
75
+ return new AliasNode(child.scope, newUnder, child.alias);
76
+ }
68
77
  // Across Sort
69
78
  if (child instanceof SortNode) {
70
79
  log('Pushing predicate below Sort');
@@ -1 +1 @@
1
- {"version":3,"file":"rule-predicate-pushdown.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-pushdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rule-predicate-pushdown.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-pushdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Rule: Projection Pruning
3
+ *
4
+ * When an outer ProjectNode references only a subset of an inner ProjectNode's
5
+ * output attributes, the inner projections that are not referenced can be removed.
6
+ *
7
+ * This commonly arises after view expansion:
8
+ * Project(outer: name) → Project(view: id, name, email, category, value) → Scan
9
+ * becomes:
10
+ * Project(outer: name) → Project(view: name) → Scan
11
+ *
12
+ * The rule only fires on ProjectNode whose source is also a ProjectNode.
13
+ */
14
+ import type { PlanNode } from '../../nodes/plan-node.js';
15
+ import type { OptContext } from '../../framework/context.js';
16
+ export declare function ruleProjectionPruning(node: PlanNode, _context: OptContext): PlanNode | null;
17
+ //# sourceMappingURL=rule-projection-pruning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-projection-pruning.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/retrieve/rule-projection-pruning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAoB7D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAqE3F"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Rule: Projection Pruning
3
+ *
4
+ * When an outer ProjectNode references only a subset of an inner ProjectNode's
5
+ * output attributes, the inner projections that are not referenced can be removed.
6
+ *
7
+ * This commonly arises after view expansion:
8
+ * Project(outer: name) → Project(view: id, name, email, category, value) → Scan
9
+ * becomes:
10
+ * Project(outer: name) → Project(view: name) → Scan
11
+ *
12
+ * The rule only fires on ProjectNode whose source is also a ProjectNode.
13
+ */
14
+ import { createLogger } from '../../../common/logger.js';
15
+ import { ProjectNode } from '../../nodes/project-node.js';
16
+ import { ColumnReferenceNode } from '../../nodes/reference.js';
17
+ const log = createLogger('optimizer:rule:projection-pruning');
18
+ /**
19
+ * Collect all attribute IDs referenced by ColumnReferenceNode leaves
20
+ * within a scalar expression tree.
21
+ */
22
+ function collectReferencedAttributeIds(node, out) {
23
+ if (node instanceof ColumnReferenceNode) {
24
+ out.add(node.attributeId);
25
+ return;
26
+ }
27
+ for (const child of node.getChildren()) {
28
+ collectReferencedAttributeIds(child, out);
29
+ }
30
+ }
31
+ export function ruleProjectionPruning(node, _context) {
32
+ if (!(node instanceof ProjectNode))
33
+ return null;
34
+ const outer = node;
35
+ if (!(outer.source instanceof ProjectNode))
36
+ return null;
37
+ const inner = outer.source;
38
+ // Collect attribute IDs the outer project's expressions reference
39
+ const referencedIds = new Set();
40
+ for (const proj of outer.projections) {
41
+ collectReferencedAttributeIds(proj.node, referencedIds);
42
+ }
43
+ // Determine which inner projections are referenced
44
+ const innerAttrs = inner.getAttributes();
45
+ const keptIndices = [];
46
+ for (let i = 0; i < inner.projections.length; i++) {
47
+ if (referencedIds.has(innerAttrs[i].id)) {
48
+ keptIndices.push(i);
49
+ }
50
+ }
51
+ // Nothing to prune
52
+ if (keptIndices.length === inner.projections.length)
53
+ return null;
54
+ // Don't prune to zero projections — keep at least one
55
+ if (keptIndices.length === 0)
56
+ return null;
57
+ log('Pruning inner project from %d to %d projections', inner.projections.length, keptIndices.length);
58
+ // Build pruned inner projections preserving attribute IDs
59
+ const keptProjections = keptIndices.map(i => ({
60
+ node: inner.projections[i].node,
61
+ alias: inner.projections[i].alias,
62
+ attributeId: innerAttrs[i].id,
63
+ }));
64
+ const keptAttributes = keptIndices.map(i => innerAttrs[i]);
65
+ const prunedInner = new ProjectNode(inner.scope, inner.source, keptProjections, undefined, keptAttributes, inner.preserveInputColumns);
66
+ // Rebuild outer project with new source
67
+ const outerAttrs = outer.getAttributes();
68
+ const newOuterProjections = outer.projections.map((proj, i) => ({
69
+ node: proj.node,
70
+ alias: proj.alias,
71
+ attributeId: outerAttrs[i].id,
72
+ }));
73
+ return new ProjectNode(outer.scope, prunedInner, newOuterProjections, undefined, outerAttrs, outer.preserveInputColumns);
74
+ }
75
+ //# sourceMappingURL=rule-projection-pruning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-projection-pruning.js","sourceRoot":"","sources":["../../../../../src/planner/rules/retrieve/rule-projection-pruning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,GAAG,GAAG,YAAY,CAAC,mCAAmC,CAAC,CAAC;AAE9D;;;GAGG;AACH,SAAS,6BAA6B,CAAC,IAAc,EAAE,GAAgB;IACtE,IAAI,IAAI,YAAY,mBAAmB,EAAE,CAAC;QACzC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1B,OAAO;IACR,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,6BAA6B,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC;AACF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAc,EAAE,QAAoB;IACzE,IAAI,CAAC,CAAC,IAAI,YAAY,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhD,MAAM,KAAK,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAExD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAE3B,kEAAkE;IAClE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtC,6BAA6B,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,mDAAmD;IACnD,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;IACzC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnD,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACzC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;IAED,mBAAmB;IACnB,IAAI,WAAW,CAAC,MAAM,KAAK,KAAK,CAAC,WAAW,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEjE,sDAAsD;IACtD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1C,GAAG,CACF,iDAAiD,EACjD,KAAK,CAAC,WAAW,CAAC,MAAM,EACxB,WAAW,CAAC,MAAM,CAClB,CAAC;IAEF,0DAA0D;IAC1D,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI;QAC/B,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK;QACjC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;KAC7B,CAAC,CAAC,CAAC;IAEJ,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3D,MAAM,WAAW,GAAG,IAAI,WAAW,CAClC,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,MAAM,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,KAAK,CAAC,oBAAoB,CAC1B,CAAC;IAEF,wCAAwC;IACxC,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;IACzC,MAAM,mBAAmB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,EAAE,IAAI,CAAC,IAAsB;QACjC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;KAC7B,CAAC,CAAC,CAAC;IAEJ,OAAO,IAAI,WAAW,CACrB,KAAK,CAAC,KAAK,EACX,WAAW,EACX,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,KAAK,CAAC,oBAAoB,CAC1B,CAAC;AACH,CAAC"}
@@ -1,6 +1,15 @@
1
1
  import type { StreamAggregateNode } from '../../planner/nodes/stream-aggregate.js';
2
2
  import type { Instruction } from '../types.js';
3
3
  import type { EmissionContext } from '../emission-context.js';
4
+ import type { PlanNode } from '../../planner/nodes/plan-node.js';
5
+ import { AggValue } from '../../func/registration.js';
4
6
  export declare const ctxLog: import("debug").Debugger;
7
+ /** Clone an aggregate initial value so each group gets an independent accumulator. */
8
+ export declare function cloneInitialValue(initialValue: unknown): AggValue;
9
+ /**
10
+ * Find the source relation node that column references should use as their context key.
11
+ * This traverses up the tree to find the original table scan or similar node.
12
+ */
13
+ export declare function findSourceRelation(node: PlanNode): PlanNode;
5
14
  export declare function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionContext): Instruction;
6
15
  //# sourceMappingURL=aggregate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../../src/runtime/emit/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAE,WAAW,EAAkC,MAAM,aAAa,CAAC;AAG/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAiB9D,eAAO,MAAM,MAAM,0BAAkC,CAAC;AAqCtD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,eAAe,GAAG,WAAW,CAmhBhG"}
1
+ {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../../src/runtime/emit/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAE,WAAW,EAAkC,MAAM,aAAa,CAAC;AAG/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,kCAAkC,CAAC;AAWhF,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtD,eAAO,MAAM,MAAM,0BAAkC,CAAC;AAEtD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,OAAO,GAAG,QAAQ,CAUjE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAgB3D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,eAAe,GAAG,WAAW,CAmhBhG"}
@@ -12,7 +12,7 @@ import { StatusCode } from '../../common/types.js';
12
12
  import { buildRowDescriptor } from '../../util/row-descriptor.js';
13
13
  export const ctxLog = createLogger('runtime:context');
14
14
  /** Clone an aggregate initial value so each group gets an independent accumulator. */
15
- function cloneInitialValue(initialValue) {
15
+ export function cloneInitialValue(initialValue) {
16
16
  if (typeof initialValue === 'function') {
17
17
  return initialValue();
18
18
  }
@@ -30,7 +30,7 @@ function cloneInitialValue(initialValue) {
30
30
  * Find the source relation node that column references should use as their context key.
31
31
  * This traverses up the tree to find the original table scan or similar node.
32
32
  */
33
- function findSourceRelation(node) {
33
+ export function findSourceRelation(node) {
34
34
  // Keep going up until we find a values node
35
35
  let current = node;
36
36
  while (current) {