@quereus/quereus 3.1.2 → 3.2.1

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 (142) hide show
  1. package/dist/src/core/database-assertions.js +3 -3
  2. package/dist/src/core/database-assertions.js.map +1 -1
  3. package/dist/src/core/database.js +3 -3
  4. package/dist/src/core/database.js.map +1 -1
  5. package/dist/src/core/statement.js +3 -3
  6. package/dist/src/core/statement.js.map +1 -1
  7. package/dist/src/index.d.ts +2 -1
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/index.js +1 -0
  10. package/dist/src/index.js.map +1 -1
  11. package/dist/src/parser/visitor.js +1 -1
  12. package/dist/src/parser/visitor.js.map +1 -1
  13. package/dist/src/planner/analysis/attribute-provenance.d.ts +45 -0
  14. package/dist/src/planner/analysis/attribute-provenance.d.ts.map +1 -0
  15. package/dist/src/planner/analysis/attribute-provenance.js +81 -0
  16. package/dist/src/planner/analysis/attribute-provenance.js.map +1 -0
  17. package/dist/src/planner/analysis/const-evaluator.js +5 -5
  18. package/dist/src/planner/analysis/const-evaluator.js.map +1 -1
  19. package/dist/src/planner/building/select-window.d.ts.map +1 -1
  20. package/dist/src/planner/building/select-window.js +54 -21
  21. package/dist/src/planner/building/select-window.js.map +1 -1
  22. package/dist/src/planner/cache/correlation-detector.d.ts +7 -0
  23. package/dist/src/planner/cache/correlation-detector.d.ts.map +1 -1
  24. package/dist/src/planner/cache/correlation-detector.js +34 -2
  25. package/dist/src/planner/cache/correlation-detector.js.map +1 -1
  26. package/dist/src/planner/nodes/async-gather-node.d.ts +169 -0
  27. package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -0
  28. package/dist/src/planner/nodes/async-gather-node.js +488 -0
  29. package/dist/src/planner/nodes/async-gather-node.js.map +1 -0
  30. package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
  31. package/dist/src/planner/nodes/bloom-join-node.js +8 -7
  32. package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
  33. package/dist/src/planner/nodes/eager-prefetch-node.d.ts +47 -0
  34. package/dist/src/planner/nodes/eager-prefetch-node.d.ts.map +1 -0
  35. package/dist/src/planner/nodes/eager-prefetch-node.js +96 -0
  36. package/dist/src/planner/nodes/eager-prefetch-node.js.map +1 -0
  37. package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts +150 -0
  38. package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts.map +1 -0
  39. package/dist/src/planner/nodes/fanout-lookup-join-node.js +265 -0
  40. package/dist/src/planner/nodes/fanout-lookup-join-node.js.map +1 -0
  41. package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
  42. package/dist/src/planner/nodes/merge-join-node.js +8 -7
  43. package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
  44. package/dist/src/planner/nodes/plan-node-type.d.ts +3 -0
  45. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  46. package/dist/src/planner/nodes/plan-node-type.js +3 -0
  47. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  48. package/dist/src/planner/nodes/plan-node.d.ts +36 -0
  49. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  50. package/dist/src/planner/nodes/plan-node.js +26 -0
  51. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  52. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  53. package/dist/src/planner/nodes/reference.js +13 -0
  54. package/dist/src/planner/nodes/reference.js.map +1 -1
  55. package/dist/src/planner/optimizer-tuning.d.ts +107 -0
  56. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
  57. package/dist/src/planner/optimizer-tuning.js +43 -0
  58. package/dist/src/planner/optimizer-tuning.js.map +1 -1
  59. package/dist/src/planner/optimizer.d.ts.map +1 -1
  60. package/dist/src/planner/optimizer.js +91 -0
  61. package/dist/src/planner/optimizer.js.map +1 -1
  62. package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -1
  63. package/dist/src/planner/rules/access/rule-monotonic-range-access.js +1 -6
  64. package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -1
  65. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts +74 -0
  66. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts.map +1 -0
  67. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +139 -0
  68. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js.map +1 -0
  69. package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts +58 -0
  70. package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts.map +1 -0
  71. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +592 -0
  72. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -0
  73. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts +43 -0
  74. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts.map +1 -0
  75. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js +115 -0
  76. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js.map +1 -0
  77. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts +102 -0
  78. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts.map +1 -0
  79. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js +545 -0
  80. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js.map +1 -0
  81. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts +45 -0
  82. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts.map +1 -0
  83. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js +78 -0
  84. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js.map +1 -0
  85. package/dist/src/planner/scopes/param.d.ts.map +1 -1
  86. package/dist/src/planner/scopes/param.js +13 -11
  87. package/dist/src/planner/scopes/param.js.map +1 -1
  88. package/dist/src/planner/type-utils.js +1 -1
  89. package/dist/src/planner/type-utils.js.map +1 -1
  90. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
  91. package/dist/src/planner/validation/plan-validator.js +17 -19
  92. package/dist/src/planner/validation/plan-validator.js.map +1 -1
  93. package/dist/src/runtime/async-semaphore.d.ts +36 -0
  94. package/dist/src/runtime/async-semaphore.d.ts.map +1 -0
  95. package/dist/src/runtime/async-semaphore.js +72 -0
  96. package/dist/src/runtime/async-semaphore.js.map +1 -0
  97. package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
  98. package/dist/src/runtime/deferred-constraint-queue.js +4 -3
  99. package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
  100. package/dist/src/runtime/emit/async-gather.d.ts +77 -0
  101. package/dist/src/runtime/emit/async-gather.d.ts.map +1 -0
  102. package/dist/src/runtime/emit/async-gather.js +234 -0
  103. package/dist/src/runtime/emit/async-gather.js.map +1 -0
  104. package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
  105. package/dist/src/runtime/emit/bloom-join.js +38 -17
  106. package/dist/src/runtime/emit/bloom-join.js.map +1 -1
  107. package/dist/src/runtime/emit/eager-prefetch.d.ts +77 -0
  108. package/dist/src/runtime/emit/eager-prefetch.d.ts.map +1 -0
  109. package/dist/src/runtime/emit/eager-prefetch.js +223 -0
  110. package/dist/src/runtime/emit/eager-prefetch.js.map +1 -0
  111. package/dist/src/runtime/emit/fanout-lookup-join.d.ts +130 -0
  112. package/dist/src/runtime/emit/fanout-lookup-join.d.ts.map +1 -0
  113. package/dist/src/runtime/emit/fanout-lookup-join.js +521 -0
  114. package/dist/src/runtime/emit/fanout-lookup-join.js.map +1 -0
  115. package/dist/src/runtime/parallel-driver.d.ts +68 -0
  116. package/dist/src/runtime/parallel-driver.d.ts.map +1 -0
  117. package/dist/src/runtime/parallel-driver.js +233 -0
  118. package/dist/src/runtime/parallel-driver.js.map +1 -0
  119. package/dist/src/runtime/register.d.ts.map +1 -1
  120. package/dist/src/runtime/register.js +9 -0
  121. package/dist/src/runtime/register.js.map +1 -1
  122. package/dist/src/runtime/strict-fork.d.ts +36 -0
  123. package/dist/src/runtime/strict-fork.d.ts.map +1 -0
  124. package/dist/src/runtime/strict-fork.js +125 -0
  125. package/dist/src/runtime/strict-fork.js.map +1 -0
  126. package/dist/src/util/comparison.d.ts.map +1 -1
  127. package/dist/src/util/comparison.js +11 -1
  128. package/dist/src/util/comparison.js.map +1 -1
  129. package/dist/src/vtab/concurrency.d.ts +29 -0
  130. package/dist/src/vtab/concurrency.d.ts.map +1 -0
  131. package/dist/src/vtab/concurrency.js +47 -0
  132. package/dist/src/vtab/concurrency.js.map +1 -0
  133. package/dist/src/vtab/memory/layer/scan-layer.d.ts.map +1 -1
  134. package/dist/src/vtab/memory/layer/scan-layer.js +67 -29
  135. package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
  136. package/dist/src/vtab/memory/module.d.ts +21 -0
  137. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  138. package/dist/src/vtab/memory/module.js +21 -0
  139. package/dist/src/vtab/memory/module.js.map +1 -1
  140. package/dist/src/vtab/module.d.ts +47 -0
  141. package/dist/src/vtab/module.d.ts.map +1 -1
  142. package/package.json +4 -3
@@ -0,0 +1,545 @@
1
+ /**
2
+ * Rule: Async Gather ZIP BY KEY
3
+ *
4
+ * Recognizes a `Project` over a chain of binary full-outer `JoinNode`s that
5
+ * all equate the **same** key column set across every participating relation,
6
+ * and folds the whole shape into a single N-ary
7
+ * `AsyncGatherNode({ kind: 'zipByKey', branchKeyAttrs, outputKeyAttrs })`.
8
+ *
9
+ * Generalizes `rule-async-gather-union-all` from the `unionAll` combinator to
10
+ * `zipByKey`. The recognized SQL is the natural spelling of an N-way
11
+ * full-outer merge on a shared key:
12
+ *
13
+ * select coalesce(a.k, b.k, c.k) as k, a.av, b.bv, c.cv
14
+ * from a full outer join b on a.k = b.k
15
+ * full outer join c on a.k = c.k
16
+ *
17
+ * which the builder produces as:
18
+ *
19
+ * Project[ coalesce(a.k,b.k,c.k) as k, a.av, b.bv, c.cv ]
20
+ * Join(full, on a.k = c.k)
21
+ * Join(full, on a.k = b.k)
22
+ * <a> <b>
23
+ * <c>
24
+ *
25
+ * The binary full-outer chain is O(N²) null-padding and infers worse FDs than
26
+ * the symmetric N-ary merge; the `zipByKey` gather drives the N branches
27
+ * concurrently and hash-merges them by key. (Binary FULL JOIN has no runtime
28
+ * lowering at all — this rewrite is the only execution path for it.)
29
+ *
30
+ * ## Recognized shape
31
+ *
32
+ * 1. A `ProjectNode` whose `source` is a `JoinNode(joinType='full')`.
33
+ * 2. The full-join chain flattens (any nesting) into ≥ `minBranches` leaf
34
+ * branches. Each join's `ON` condition is a pure conjunction of
35
+ * column-ref equalities (no residual / non-equi predicate — those block).
36
+ * (`USING`/`NATURAL` full joins carry no synthesized `ON` condition, so the
37
+ * chain walk declines them — out of scope; see *Out of scope* below.)
38
+ * 3. Those equalities partition the branches' key columns into K equivalence
39
+ * classes ("key positions"), and **every branch contributes exactly one
40
+ * column to every class** (the shared-key precondition). A branch missing
41
+ * from any class would be a cross-product, not a zip — block.
42
+ * 4. The projection list must express, in **any order**:
43
+ * - K merged keys, each a `coalesce(...)` whose argument set is exactly
44
+ * one key class's per-branch key attrs; and
45
+ * - the forwarded non-key column references it selects (a subset is fine),
46
+ * plus arbitrary additional pure scalar expressions over those outputs
47
+ * (e.g. `coalesce(a.k, b.k) * 10`). The only hard constraint: a branch *key*
48
+ * column may appear **only** inside a recognizing full-group `coalesce` — a
49
+ * bare/partial reference to it (e.g. `select a.k …`) blocks, because the
50
+ * per-branch key is consumed into the single merged key and is unavailable
51
+ * above the gather.
52
+ *
53
+ * When the projection happens to be exactly the emitter's canonical order
54
+ * (`[K coalesce calls][branch0 non-key][branch1 non-key]…`), the gather
55
+ * replaces the `Project` outright (fast path). Otherwise the gather is built
56
+ * in canonical layout and wrapped in a thin reordering `Project` that
57
+ * reproduces the user's list (rewriting each full-group `coalesce` to a
58
+ * reference to the gather's merged-key output).
59
+ *
60
+ * ## Gates (mirror `rule-async-gather-union-all`)
61
+ *
62
+ * - **Concurrency safety.** Every branch must declare
63
+ * `physical.concurrencySafe === true`.
64
+ * - **Uncorrelated branches.** No branch may reference attributes outside its
65
+ * own subtree (lateral dependency) — the parallel driver forks independent
66
+ * contexts. `isCorrelatedSubquery` on each branch must be false.
67
+ * - **Latency win.** The slowest branch's `physical.expectedLatencyMs` must
68
+ * meet `tuning.parallel.gatherThresholdMs`. This is 0 on memory-vtab /
69
+ * in-process leaves, so the rule is inert by design on local-only plans
70
+ * (the golden-plan no-rewrite invariant).
71
+ * - **Key collation agreement.** Every key column at a given key position must
72
+ * declare the *same* collation across all branches (binary or not). The
73
+ * runtime comparator derives from branch 0 only, so a disagreement would
74
+ * compare keys under the wrong collation. Non-binary collations are allowed:
75
+ * the emitter composes the merged key deterministically from the
76
+ * lowest-indexed present branch (`composeMergedKeyCells`), matching
77
+ * `coalesce`'s left-to-right pick even when collation-equal keys are
78
+ * byte-distinct (e.g. NOCASE merging `'A'`/`'a'`). This mirrors the
79
+ * *agreement* invariant `AsyncGatherNode.validateZipByKey` enforces (which
80
+ * throws on a true mismatch); checking it here declines gracefully instead.
81
+ *
82
+ * ## Attribute provenance (Option A — per-branch refs + minted output keys)
83
+ *
84
+ * - `branchKeyAttrs[b]` — branch b's K key attr ids, in key order (distinct
85
+ * per branch; each branch originates its own key id — provenance-clean).
86
+ * - `outputKeyAttrs` — the K ids the `Project` minted for its `coalesce`
87
+ * outputs (computed expressions → fresh ids, disjoint from all child ids).
88
+ * The gather *mints* these, so `preserveAttributeIds[0..K-1] ===
89
+ * outputKeyAttrs` and downstream references to the coalesced key resolve.
90
+ * - `preserveAttributeIds` — the `Project`'s full output attribute list,
91
+ * which (because we matched the canonical order) is exactly
92
+ * `[minted keys] ++ [each branch's non-key attrs]`.
93
+ *
94
+ * ## Idempotence
95
+ *
96
+ * After the rewrite the matched node is an `AsyncGatherNode`, not a
97
+ * `ProjectNode`, so a second firing's matcher rejects immediately.
98
+ */
99
+ import { createLogger } from '../../../common/logger.js';
100
+ import { PlanNode, isRelationalNode } from '../../nodes/plan-node.js';
101
+ import { ProjectNode } from '../../nodes/project-node.js';
102
+ import { JoinNode } from '../../nodes/join-node.js';
103
+ import { BinaryOpNode } from '../../nodes/scalar.js';
104
+ import { ColumnReferenceNode } from '../../nodes/reference.js';
105
+ import { ScalarFunctionCallNode } from '../../nodes/function.js';
106
+ import { AsyncGatherNode } from '../../nodes/async-gather-node.js';
107
+ import { isCorrelatedSubquery } from '../../cache/correlation-detector.js';
108
+ const log = createLogger('optimizer:rule:async-gather-zip-by-key');
109
+ export function ruleAsyncGatherZipByKey(node, context) {
110
+ if (!(node instanceof ProjectNode))
111
+ return null;
112
+ if (!(node.source instanceof JoinNode) || node.source.joinType !== 'full')
113
+ return null;
114
+ const tuning = context.tuning.parallel;
115
+ if (tuning.minBranches < 2)
116
+ return null;
117
+ // (1) Flatten the full-outer chain into leaf branches + ON conditions.
118
+ const branches = [];
119
+ const conditions = [];
120
+ if (!collectFullJoinChain(node.source, branches, conditions))
121
+ return null;
122
+ if (branches.length < tuning.minBranches)
123
+ return null;
124
+ // (2) Each ON condition must be a pure AND-of-column-equalities. Collect the
125
+ // (attrId, attrId) pairs; a residual / non-equi conjunct blocks the rewrite.
126
+ const equalities = [];
127
+ for (const cond of conditions) {
128
+ if (!extractKeyEqualities(cond, equalities)) {
129
+ log('Aborting: join condition has a residual / non-equi predicate');
130
+ return null;
131
+ }
132
+ }
133
+ if (equalities.length === 0)
134
+ return null;
135
+ // (3) Partition the equated columns into key groups (equivalence classes),
136
+ // requiring every branch to contribute exactly one column to every group.
137
+ const branchOfAttr = buildBranchOfAttr(branches);
138
+ const groups = buildKeyGroups(equalities, branchOfAttr, branches.length);
139
+ if (!groups)
140
+ return null;
141
+ const k = groups.length;
142
+ // Per-branch key attr ids in key-group order — shared by the gates and the
143
+ // reordering path. Key-position order is layout-independent here; the
144
+ // canonical fast path derives its own coalesce-aligned order separately.
145
+ const branchKeyAttrs = branches.map((_branch, b) => groups.map(g => g.byBranch[b]));
146
+ // Gates (mirror rule-async-gather-union-all). These are projection-layout
147
+ // independent, so they run once before deciding canonical-vs-reordered.
148
+ for (const branch of branches) {
149
+ if (branch.physical.concurrencySafe !== true) {
150
+ log('Aborting: branch %s is not concurrencySafe', branch.id);
151
+ return null;
152
+ }
153
+ if (isCorrelatedSubquery(branch)) {
154
+ log('Aborting: branch %s is correlated (lateral dependency)', branch.id);
155
+ return null;
156
+ }
157
+ }
158
+ let maxLatency = 0;
159
+ for (const branch of branches) {
160
+ const l = branch.physical.expectedLatencyMs ?? 0;
161
+ if (l > maxLatency)
162
+ maxLatency = l;
163
+ }
164
+ if (maxLatency < tuning.gatherThresholdMs)
165
+ return null;
166
+ // Collation agreement per key position (the runtime comparator uses branch
167
+ // 0's collation only). validateZipByKey also enforces this and *throws* on a
168
+ // mismatch, but checking here lets the rule decline the rewrite gracefully —
169
+ // the chain simply stays a JoinNode (which then errors at emit as an
170
+ // unsupported FULL JOIN, the pre-rule baseline) rather than aborting planning.
171
+ //
172
+ // Non-binary collations are permitted as long as every branch agrees on the
173
+ // collation per key position. The emitter's merged key value is deterministic
174
+ // (lowest-indexed present branch supplies the key cells — see
175
+ // `composeMergedKeyCells`), matching `coalesce`'s left-to-right pick even when
176
+ // collation-equal keys are byte-distinct (e.g. NOCASE merging 'A'/'a'). The
177
+ // branch-0-derived comparator is correct because the collations agree.
178
+ if (!keyCollationsAgree(branches, branchKeyAttrs, k)) {
179
+ log('Aborting: key columns disagree on collation across branches');
180
+ return null;
181
+ }
182
+ // Each branch must be key-unique on its equated key columns. The zipByKey
183
+ // emitter assumes one row per key per branch (a duplicate silently
184
+ // overwrites); a true FULL JOIN on a non-unique key would multiply rows, so
185
+ // folding a non-unique branch would change results. Require the zip key to
186
+ // cover a declared unique key of every branch.
187
+ if (!branchesKeyUnique(branches, branchKeyAttrs)) {
188
+ log('Aborting: a branch is not provably unique on the equated key columns');
189
+ return null;
190
+ }
191
+ const concurrencyCap = Math.max(1, Math.min(tuning.concurrency, branches.length));
192
+ // (4a) Fast path: the projection is exactly the canonical zipByKey layout, so
193
+ // the gather replaces the Project outright (no reordering wrapper).
194
+ const canonical = matchCanonicalProjections(node, branches, groups, branchOfAttr);
195
+ if (canonical) {
196
+ log('Folding canonical full-outer zip chain of %d branches (K=%d) into AsyncGather(zipByKey) (cap=%d, maxLatency=%d ms)', branches.length, k, concurrencyCap, maxLatency);
197
+ return new AsyncGatherNode(node.scope, branches, { kind: 'zipByKey', branchKeyAttrs: canonical.branchKeyAttrs, outputKeyAttrs: canonical.outputKeyAttrs }, concurrencyCap, node.getAttributes());
198
+ }
199
+ // (4b) General path: arbitrary projection order / derived scalars over the
200
+ // merged-key and non-key outputs. Build the gather in its canonical layout
201
+ // and wrap it in a thin reordering Project reproducing the user's list.
202
+ const wrapped = buildReorderingGather(node, branches, groups, branchKeyAttrs, concurrencyCap);
203
+ if (!wrapped) {
204
+ log('Aborting: a projection references a branch key outside a full-group coalesce');
205
+ return null;
206
+ }
207
+ log('Folding reordered full-outer zip chain of %d branches (K=%d) into AsyncGather(zipByKey)+Project (cap=%d, maxLatency=%d ms)', branches.length, k, concurrencyCap, maxLatency);
208
+ return wrapped;
209
+ }
210
+ /**
211
+ * Build the canonical `zipByKey` gather and wrap it in a reordering `Project`
212
+ * that reproduces the user's projection list against the gather's canonical
213
+ * output. Each `coalesce(<exactly one full key group>)` sub-expression is
214
+ * rewritten to a bare reference to that group's merged-key output; non-key
215
+ * column refs and arbitrary pure scalar expressions over those outputs are
216
+ * carried through unchanged. Returns null if any branch key column is
217
+ * referenced outside a recognized full-group coalesce — such a reference is
218
+ * unavailable above the gather, which consumes each per-branch key into the
219
+ * single merged key.
220
+ */
221
+ function buildReorderingGather(proj, branches, groups, branchKeyAttrs, concurrencyCap) {
222
+ // Mint the K merged-key output ids (key-group order) and build the gather in
223
+ // its natural [merged keys][branch non-key] layout. preserveAttributeIds is
224
+ // omitted so the node mints/forwards the canonical ids itself; the wrapper
225
+ // Project below restores the user's original output attribute ids.
226
+ const outputKeyAttrs = groups.map(() => PlanNode.nextAttrId());
227
+ const gather = new AsyncGatherNode(proj.scope, branches, { kind: 'zipByKey', branchKeyAttrs, outputKeyAttrs }, concurrencyCap);
228
+ const gatherAttrs = gather.getAttributes();
229
+ const keyAttrIds = new Set();
230
+ for (const g of groups)
231
+ for (const id of g.idSet)
232
+ keyAttrIds.add(id);
233
+ const outAttrs = proj.getAttributes();
234
+ const newProjections = [];
235
+ for (let i = 0; i < proj.projections.length; i++) {
236
+ const rewritten = rewriteMergedKeyRefs(proj.projections[i].node, groups, outputKeyAttrs, gatherAttrs, keyAttrIds);
237
+ if (!rewritten)
238
+ return null;
239
+ newProjections.push({
240
+ node: rewritten,
241
+ alias: proj.projections[i].alias,
242
+ attributeId: outAttrs[i].id,
243
+ });
244
+ }
245
+ return new ProjectNode(proj.scope, gather, newProjections, undefined, outAttrs, proj.preserveInputColumns);
246
+ }
247
+ /**
248
+ * Rewrite a projection scalar expression for evaluation above the gather:
249
+ * - `coalesce(<exactly one full key group's branch keys>)` → a bare reference
250
+ * to that group's merged-key output (`outputKeyAttrs[gi]`);
251
+ * - bare non-key column refs are forwarded unchanged (the gather forwards
252
+ * their ids); arbitrary pure scalar structure is rebuilt around the above;
253
+ * - any other reference to a branch *key* column blocks (returns null) — the
254
+ * per-branch key is consumed into the merged key and is unavailable above.
255
+ * Returns the rewritten expression, or null to decline the whole rewrite.
256
+ */
257
+ function rewriteMergedKeyRefs(expr, groups, outputKeyAttrs, gatherAttrs, keyAttrIds) {
258
+ // coalesce over exactly one full key group → merged-key reference.
259
+ if (expr instanceof ScalarFunctionCallNode && expr.expression.name.toLowerCase() === 'coalesce') {
260
+ const gi = matchFullGroupCoalesce(expr, groups);
261
+ if (gi >= 0) {
262
+ const attr = gatherAttrs[gi];
263
+ return new ColumnReferenceNode(expr.scope, { type: 'column', name: attr.name }, attr.type, outputKeyAttrs[gi], gi);
264
+ }
265
+ // Not a full-group coalesce — fall through to generic child recursion.
266
+ }
267
+ if (expr instanceof ColumnReferenceNode) {
268
+ // A stray reference to a branch key column cannot survive the merge.
269
+ if (keyAttrIds.has(expr.attributeId))
270
+ return null;
271
+ return expr;
272
+ }
273
+ const children = expr.getChildren();
274
+ if (children.length === 0)
275
+ return expr;
276
+ const newChildren = [];
277
+ let changed = false;
278
+ for (const child of children) {
279
+ if (isRelationalNode(child)) {
280
+ // A relational child (e.g. a scalar subquery). Keep it only when it does
281
+ // not reference a consumed branch key column (conservative — such a
282
+ // reference would not resolve above the gather).
283
+ if (subtreeReferencesKey(child, keyAttrIds))
284
+ return null;
285
+ newChildren.push(child);
286
+ continue;
287
+ }
288
+ const rewritten = rewriteMergedKeyRefs(child, groups, outputKeyAttrs, gatherAttrs, keyAttrIds);
289
+ if (!rewritten)
290
+ return null;
291
+ if (rewritten !== child)
292
+ changed = true;
293
+ newChildren.push(rewritten);
294
+ }
295
+ return changed ? expr.withChildren(newChildren) : expr;
296
+ }
297
+ /**
298
+ * If `call`'s operands are exactly one key group's branch key columns (as bare
299
+ * column references), return that group's index; otherwise -1.
300
+ */
301
+ function matchFullGroupCoalesce(call, groups) {
302
+ const argIds = [];
303
+ for (const operand of call.operands) {
304
+ if (!(operand instanceof ColumnReferenceNode))
305
+ return -1;
306
+ argIds.push(operand.attributeId);
307
+ }
308
+ return groups.findIndex(g => g.idSet.size === argIds.length && argIds.every(id => g.idSet.has(id)));
309
+ }
310
+ /**
311
+ * Walk a plan subtree (relational + scalar children) for any column reference
312
+ * to a key attr id the merge consumes.
313
+ */
314
+ function subtreeReferencesKey(node, keyAttrIds) {
315
+ if (node instanceof ColumnReferenceNode && keyAttrIds.has(node.attributeId))
316
+ return true;
317
+ for (const child of node.getChildren()) {
318
+ if (subtreeReferencesKey(child, keyAttrIds))
319
+ return true;
320
+ }
321
+ return false;
322
+ }
323
+ /**
324
+ * Flatten a left-deep (or arbitrarily nested) chain of full-outer `JoinNode`s
325
+ * into leaf branches and ON conditions. Branch order mirrors the join's
326
+ * attribute concatenation (left subtree before right), so it lines up with the
327
+ * canonical projection layout. Returns false if a full join is missing its ON
328
+ * condition (cross-shaped full join — not recognizable).
329
+ */
330
+ function collectFullJoinChain(node, branches, conditions) {
331
+ if (node instanceof JoinNode && node.joinType === 'full') {
332
+ if (!node.condition)
333
+ return false;
334
+ conditions.push(node.condition);
335
+ return collectFullJoinChain(node.left, branches, conditions)
336
+ && collectFullJoinChain(node.right, branches, conditions);
337
+ }
338
+ branches.push(node);
339
+ return true;
340
+ }
341
+ /**
342
+ * Walk a join condition collecting `=`-of-two-column-refs pairs as
343
+ * (attrId, attrId). Returns false if any conjunct is not an `AND` or a
344
+ * column=column equality (i.e. a residual predicate the zip can't absorb).
345
+ */
346
+ function extractKeyEqualities(cond, out) {
347
+ const stack = [cond];
348
+ while (stack.length) {
349
+ const n = stack.pop();
350
+ if (!(n instanceof BinaryOpNode))
351
+ return false;
352
+ const op = n.expression.operator;
353
+ if (op === 'AND') {
354
+ stack.push(n.left, n.right);
355
+ continue;
356
+ }
357
+ if (op !== '=')
358
+ return false;
359
+ if (!(n.left instanceof ColumnReferenceNode) || !(n.right instanceof ColumnReferenceNode))
360
+ return false;
361
+ out.push([n.left.attributeId, n.right.attributeId]);
362
+ }
363
+ return true;
364
+ }
365
+ /** Map each branch attribute id to its branch index (for key-group membership). */
366
+ function buildBranchOfAttr(branches) {
367
+ const map = new Map();
368
+ branches.forEach((branch, b) => {
369
+ for (const attr of branch.getAttributes())
370
+ map.set(attr.id, b);
371
+ });
372
+ return map;
373
+ }
374
+ /**
375
+ * Union-find the equality pairs into key groups, then validate that each group
376
+ * holds exactly one attr from every branch. Returns null (block) on any
377
+ * cross-branch shape that isn't a clean shared key.
378
+ */
379
+ function buildKeyGroups(equalities, branchOfAttr, branchCount) {
380
+ const parent = new Map();
381
+ const find = (x) => {
382
+ let root = x;
383
+ while (parent.get(root) !== root)
384
+ root = parent.get(root);
385
+ let cur = x;
386
+ while (parent.get(cur) !== root) {
387
+ const next = parent.get(cur);
388
+ parent.set(cur, root);
389
+ cur = next;
390
+ }
391
+ return root;
392
+ };
393
+ const ensure = (x) => { if (!parent.has(x))
394
+ parent.set(x, x); };
395
+ for (const [a, b] of equalities) {
396
+ // Every equated column must belong to one of the flattened branches.
397
+ if (!branchOfAttr.has(a) || !branchOfAttr.has(b))
398
+ return null;
399
+ ensure(a);
400
+ ensure(b);
401
+ parent.set(find(a), find(b));
402
+ }
403
+ const byRoot = new Map();
404
+ for (const id of parent.keys()) {
405
+ const root = find(id);
406
+ let members = byRoot.get(root);
407
+ if (!members) {
408
+ members = [];
409
+ byRoot.set(root, members);
410
+ }
411
+ members.push(id);
412
+ }
413
+ const groups = [];
414
+ for (const members of byRoot.values()) {
415
+ const byBranch = new Array(branchCount).fill(-1);
416
+ for (const id of members) {
417
+ const b = branchOfAttr.get(id);
418
+ if (byBranch[b] !== -1)
419
+ return null; // two key columns from one branch in one group
420
+ byBranch[b] = id;
421
+ }
422
+ if (byBranch.some(v => v === -1))
423
+ return null; // a branch is missing from this key group
424
+ groups.push({ byBranch, idSet: new Set(members) });
425
+ }
426
+ return groups;
427
+ }
428
+ /**
429
+ * Fast-path detector: is the projection list *exactly* the canonical zipByKey
430
+ * layout
431
+ * [ K coalesce(group) calls ] ++ [ branch0 non-key refs, branch1 non-key refs, … ]
432
+ * so the gather can replace the `Project` outright with no reordering wrapper?
433
+ * If so, derive `branchKeyAttrs` (ordered to match the coalesce order) and
434
+ * `outputKeyAttrs` (the coalesce output attr ids). Returns null on any mismatch —
435
+ * the caller then tries the general reordering path (`buildReorderingGather`).
436
+ */
437
+ function matchCanonicalProjections(proj, branches, groups, branchOfAttr) {
438
+ const k = groups.length;
439
+ const projections = proj.projections;
440
+ const outAttrs = proj.getAttributes();
441
+ // Expected non-key tail: each branch's non-key attrs, in branch + column order.
442
+ const keyAttrIds = new Set();
443
+ for (const g of groups)
444
+ for (const id of g.idSet)
445
+ keyAttrIds.add(id);
446
+ const nonKeyTail = [];
447
+ for (const branch of branches) {
448
+ for (const attr of branch.getAttributes()) {
449
+ if (!keyAttrIds.has(attr.id))
450
+ nonKeyTail.push(attr.id);
451
+ }
452
+ }
453
+ if (projections.length !== k + nonKeyTail.length)
454
+ return null;
455
+ // First K projections: each a coalesce over exactly one (still-unused) group.
456
+ const orderedGroups = [];
457
+ const outputKeyAttrs = [];
458
+ const usedGroup = new Set();
459
+ for (let p = 0; p < k; p++) {
460
+ const expr = projections[p].node;
461
+ if (!(expr instanceof ScalarFunctionCallNode))
462
+ return null;
463
+ if (expr.expression.name.toLowerCase() !== 'coalesce')
464
+ return null;
465
+ const argIds = [];
466
+ for (const operand of expr.operands) {
467
+ if (!(operand instanceof ColumnReferenceNode))
468
+ return null;
469
+ argIds.push(operand.attributeId);
470
+ }
471
+ const group = groups.find(g => !usedGroup.has(g)
472
+ && g.idSet.size === argIds.length
473
+ && argIds.every(id => g.idSet.has(id)));
474
+ if (!group)
475
+ return null;
476
+ usedGroup.add(group);
477
+ orderedGroups.push(group);
478
+ outputKeyAttrs.push(outAttrs[p].id);
479
+ }
480
+ // Remaining projections: bare column refs matching the non-key tail exactly.
481
+ for (let i = 0; i < nonKeyTail.length; i++) {
482
+ const expr = projections[k + i].node;
483
+ if (!(expr instanceof ColumnReferenceNode))
484
+ return null;
485
+ if (expr.attributeId !== nonKeyTail[i])
486
+ return null;
487
+ // A non-key projection must forward its source id (ProjectNode does this
488
+ // for bare column refs); confirm it actually belongs to a branch.
489
+ if (!branchOfAttr.has(expr.attributeId))
490
+ return null;
491
+ }
492
+ const branchKeyAttrs = branches.map((_branch, b) => orderedGroups.map(g => g.byBranch[b]));
493
+ return { branchKeyAttrs, outputKeyAttrs };
494
+ }
495
+ /**
496
+ * Confirm every branch is provably unique on its equated key columns: some
497
+ * declared unique key of the branch must be covered by (a subset of) the zip's
498
+ * key-column indices. Branches without statistics-free uniqueness (no covering
499
+ * key) block the rewrite — the zip's one-row-per-key merge would otherwise
500
+ * differ from a true full join's per-key product.
501
+ */
502
+ function branchesKeyUnique(branches, branchKeyAttrs) {
503
+ for (let b = 0; b < branches.length; b++) {
504
+ const attrs = branches[b].getAttributes();
505
+ const keyIndices = new Set();
506
+ for (const id of branchKeyAttrs[b]) {
507
+ const ix = attrs.findIndex((a) => a.id === id);
508
+ if (ix < 0)
509
+ return false;
510
+ keyIndices.add(ix);
511
+ }
512
+ const declaredKeys = branches[b].getType().keys;
513
+ const covered = declaredKeys.some(key => key.every(ref => keyIndices.has(ref.index)));
514
+ if (!covered)
515
+ return false;
516
+ }
517
+ return true;
518
+ }
519
+ /**
520
+ * Confirm every branch's key column at every key position declares the **same**
521
+ * collation as branch 0's (absent collation = binary). The runtime comparator
522
+ * derives solely from branch 0's collations, so a disagreement would silently
523
+ * compare (and merge) keys under the wrong collation. Agreement is sufficient:
524
+ * the emitter's merged key value is deterministic (lowest-indexed present branch
525
+ * wins — see `composeMergedKeyCells`), so any agreed collation, binary or not,
526
+ * yields a well-defined merged key that matches `coalesce`.
527
+ */
528
+ function keyCollationsAgree(branches, branchKeyAttrs, k) {
529
+ const norm = (c) => (c && c.length > 0 ? c.toUpperCase() : 'BINARY');
530
+ const collationOf = (branch, attrId) => {
531
+ const attrs = branch.getAttributes();
532
+ const cols = branch.getType().columns;
533
+ const ix = attrs.findIndex((a) => a.id === attrId);
534
+ return ix >= 0 ? norm(cols[ix].type.collationName) : 'BINARY';
535
+ };
536
+ for (let pos = 0; pos < k; pos++) {
537
+ const base = collationOf(branches[0], branchKeyAttrs[0][pos]);
538
+ for (let b = 1; b < branches.length; b++) {
539
+ if (collationOf(branches[b], branchKeyAttrs[b][pos]) !== base)
540
+ return false;
541
+ }
542
+ }
543
+ return true;
544
+ }
545
+ //# sourceMappingURL=rule-async-gather-zip-by-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-async-gather-zip-by-key.js","sourceRoot":"","sources":["../../../../../src/planner/rules/parallel/rule-async-gather-zip-by-key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Rule: Eager Prefetch Probe
3
+ *
4
+ * Wraps the probe (`left`) input of a physical hash join in an
5
+ * `EagerPrefetchNode` when the build (`right`) side advertises high first-row
6
+ * latency, so the buffered pump can pipeline its probe-side reads with the
7
+ * parent emit's per-row work.
8
+ *
9
+ * Target shape: `BloomJoinNode` (physical, `PlanNodeType.HashJoin`). Per the
10
+ * node contract, **`left` is the probe (streamed) side** and `right` is the
11
+ * build (materialized) side — opposite of the textbook convention. The wrap
12
+ * target is therefore `left`.
13
+ *
14
+ * Cost gate: anchored on `node.right.physical.expectedLatencyMs`, the same
15
+ * field consumed by `rule-fanout-lookup-join` and `rule-async-gather-union-all`.
16
+ * That field is 0 on every in-process / memory-vtab leaf and non-zero only
17
+ * when a remote vtab plugin declares `expectedLatencyMs` at a leaf. As a
18
+ * consequence the rule is **inert by design on memory-vtab plans**, preserving
19
+ * the local-only golden-plan invariant the parallel rules already lock. We gate
20
+ * on the build side specifically: if `left` were the slow one the consumer
21
+ * above the join takes the latency hit regardless, so prefetching it doesn't
22
+ * change first-row time meaningfully.
23
+ *
24
+ * Skip predicates (the probe is already pump-driven or pre-materialized):
25
+ * - `left` is an `EagerPrefetchNode` — already wrapped (idempotence).
26
+ * - `left` is a `Cache` — pre-materialized; a prefetch over a cache buys
27
+ * nothing and confuses plan output.
28
+ * - `left` is an `AsyncGather` — already drives its branches concurrently;
29
+ * inserting a prefetch buffer just adds latency-of-first-row.
30
+ *
31
+ * Concurrency gate: as of the eager-start change, the prefetch pump begins on
32
+ * `run()` (scheduler arg-assembly), so the probe (`left`) subtree iterates
33
+ * **concurrently** with the build's for-await over `right`. If either side sits
34
+ * over a non-reentrant (`'serial'`) cursor, concurrent iteration corrupts state.
35
+ * We therefore only wrap when **both** `node.left` and `node.right` advertise
36
+ * `physical.concurrencySafe === true` (mirroring `rule-async-gather-union-all`'s
37
+ * strict `=== true` check — wrap only when *proven* safe; `undefined` blocks).
38
+ *
39
+ * Idempotence: after the rewrite `left` is an `EagerPrefetchNode`, so a second
40
+ * firing hits the first skip predicate and no-ops.
41
+ */
42
+ import type { OptContext } from '../../framework/context.js';
43
+ import type { PlanNode } from '../../nodes/plan-node.js';
44
+ export declare function ruleEagerPrefetchProbe(node: PlanNode, context: OptContext): PlanNode | null;
45
+ //# sourceMappingURL=rule-eager-prefetch-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-eager-prefetch-probe.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/parallel/rule-eager-prefetch-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAOzD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAkC3F"}