@quereus/quereus 3.1.2 → 3.3.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 (263) hide show
  1. package/dist/src/core/database-assertions.d.ts.map +1 -1
  2. package/dist/src/core/database-assertions.js +7 -3
  3. package/dist/src/core/database-assertions.js.map +1 -1
  4. package/dist/src/core/database.js +3 -3
  5. package/dist/src/core/database.js.map +1 -1
  6. package/dist/src/core/statement.js +3 -3
  7. package/dist/src/core/statement.js.map +1 -1
  8. package/dist/src/emit/ast-stringify.js +2 -2
  9. package/dist/src/emit/ast-stringify.js.map +1 -1
  10. package/dist/src/index.d.ts +2 -1
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/index.js +1 -0
  13. package/dist/src/index.js.map +1 -1
  14. package/dist/src/parser/parser.d.ts +1 -1
  15. package/dist/src/parser/parser.d.ts.map +1 -1
  16. package/dist/src/parser/parser.js +6 -2
  17. package/dist/src/parser/parser.js.map +1 -1
  18. package/dist/src/parser/visitor.js +1 -1
  19. package/dist/src/parser/visitor.js.map +1 -1
  20. package/dist/src/planner/analysis/attribute-provenance.d.ts +45 -0
  21. package/dist/src/planner/analysis/attribute-provenance.d.ts.map +1 -0
  22. package/dist/src/planner/analysis/attribute-provenance.js +81 -0
  23. package/dist/src/planner/analysis/attribute-provenance.js.map +1 -0
  24. package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -1
  25. package/dist/src/planner/analysis/binding-extractor.js +9 -6
  26. package/dist/src/planner/analysis/binding-extractor.js.map +1 -1
  27. package/dist/src/planner/analysis/change-scope.d.ts.map +1 -1
  28. package/dist/src/planner/analysis/change-scope.js +7 -0
  29. package/dist/src/planner/analysis/change-scope.js.map +1 -1
  30. package/dist/src/planner/analysis/const-evaluator.js +5 -5
  31. package/dist/src/planner/analysis/const-evaluator.js.map +1 -1
  32. package/dist/src/planner/analysis/constraint-extractor.d.ts +10 -0
  33. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  34. package/dist/src/planner/analysis/constraint-extractor.js +28 -12
  35. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  36. package/dist/src/planner/building/delete.d.ts.map +1 -1
  37. package/dist/src/planner/building/delete.js +7 -4
  38. package/dist/src/planner/building/delete.js.map +1 -1
  39. package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
  40. package/dist/src/planner/building/select-aggregates.js +4 -13
  41. package/dist/src/planner/building/select-aggregates.js.map +1 -1
  42. package/dist/src/planner/building/select-window.d.ts.map +1 -1
  43. package/dist/src/planner/building/select-window.js +54 -21
  44. package/dist/src/planner/building/select-window.js.map +1 -1
  45. package/dist/src/planner/cache/correlation-detector.d.ts +7 -0
  46. package/dist/src/planner/cache/correlation-detector.d.ts.map +1 -1
  47. package/dist/src/planner/cache/correlation-detector.js +34 -2
  48. package/dist/src/planner/cache/correlation-detector.js.map +1 -1
  49. package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
  50. package/dist/src/planner/framework/physical-utils.js +7 -1
  51. package/dist/src/planner/framework/physical-utils.js.map +1 -1
  52. package/dist/src/planner/nodes/aggregate-node.d.ts +6 -4
  53. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  54. package/dist/src/planner/nodes/aggregate-node.js +8 -6
  55. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  56. package/dist/src/planner/nodes/analyze-node.d.ts.map +1 -1
  57. package/dist/src/planner/nodes/analyze-node.js +3 -0
  58. package/dist/src/planner/nodes/analyze-node.js.map +1 -1
  59. package/dist/src/planner/nodes/async-gather-node.d.ts +169 -0
  60. package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -0
  61. package/dist/src/planner/nodes/async-gather-node.js +488 -0
  62. package/dist/src/planner/nodes/async-gather-node.js.map +1 -0
  63. package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
  64. package/dist/src/planner/nodes/bloom-join-node.js +8 -7
  65. package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
  66. package/dist/src/planner/nodes/eager-prefetch-node.d.ts +47 -0
  67. package/dist/src/planner/nodes/eager-prefetch-node.d.ts.map +1 -0
  68. package/dist/src/planner/nodes/eager-prefetch-node.js +96 -0
  69. package/dist/src/planner/nodes/eager-prefetch-node.js.map +1 -0
  70. package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts +150 -0
  71. package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts.map +1 -0
  72. package/dist/src/planner/nodes/fanout-lookup-join-node.js +265 -0
  73. package/dist/src/planner/nodes/fanout-lookup-join-node.js.map +1 -0
  74. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
  75. package/dist/src/planner/nodes/hash-aggregate.js +6 -16
  76. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
  77. package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
  78. package/dist/src/planner/nodes/join-utils.js +7 -1
  79. package/dist/src/planner/nodes/join-utils.js.map +1 -1
  80. package/dist/src/planner/nodes/limit-offset.d.ts +12 -0
  81. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  82. package/dist/src/planner/nodes/limit-offset.js +53 -3
  83. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  84. package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
  85. package/dist/src/planner/nodes/merge-join-node.js +8 -7
  86. package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
  87. package/dist/src/planner/nodes/plan-node-type.d.ts +3 -0
  88. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  89. package/dist/src/planner/nodes/plan-node-type.js +3 -0
  90. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  91. package/dist/src/planner/nodes/plan-node.d.ts +36 -0
  92. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  93. package/dist/src/planner/nodes/plan-node.js +26 -0
  94. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  95. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  96. package/dist/src/planner/nodes/project-node.js +18 -5
  97. package/dist/src/planner/nodes/project-node.js.map +1 -1
  98. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  99. package/dist/src/planner/nodes/reference.js +14 -3
  100. package/dist/src/planner/nodes/reference.js.map +1 -1
  101. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  102. package/dist/src/planner/nodes/set-operation-node.js +12 -1
  103. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  104. package/dist/src/planner/nodes/sort.js +1 -1
  105. package/dist/src/planner/nodes/sort.js.map +1 -1
  106. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  107. package/dist/src/planner/nodes/stream-aggregate.js +8 -23
  108. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  109. package/dist/src/planner/nodes/values-node.d.ts +2 -1
  110. package/dist/src/planner/nodes/values-node.d.ts.map +1 -1
  111. package/dist/src/planner/nodes/values-node.js +16 -0
  112. package/dist/src/planner/nodes/values-node.js.map +1 -1
  113. package/dist/src/planner/nodes/window-node.js +1 -1
  114. package/dist/src/planner/nodes/window-node.js.map +1 -1
  115. package/dist/src/planner/optimizer-tuning.d.ts +107 -0
  116. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
  117. package/dist/src/planner/optimizer-tuning.js +43 -0
  118. package/dist/src/planner/optimizer-tuning.js.map +1 -1
  119. package/dist/src/planner/optimizer.d.ts.map +1 -1
  120. package/dist/src/planner/optimizer.js +91 -0
  121. package/dist/src/planner/optimizer.js.map +1 -1
  122. package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -1
  123. package/dist/src/planner/rules/access/rule-monotonic-range-access.js +1 -6
  124. package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -1
  125. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
  126. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +8 -27
  127. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
  128. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +9 -3
  129. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -1
  130. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +47 -5
  131. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -1
  132. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +8 -7
  133. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -1
  134. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +14 -21
  135. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
  136. package/dist/src/planner/rules/join/equi-pair-extractor.js +4 -4
  137. package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -1
  138. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts +74 -0
  139. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts.map +1 -0
  140. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +139 -0
  141. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js.map +1 -0
  142. package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts +58 -0
  143. package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts.map +1 -0
  144. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +590 -0
  145. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -0
  146. package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -1
  147. package/dist/src/planner/rules/join/rule-join-greedy-commute.js +10 -0
  148. package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
  149. package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
  150. package/dist/src/planner/rules/join/rule-join-physical-selection.js +2 -1
  151. package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
  152. package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts.map +1 -1
  153. package/dist/src/planner/rules/join/rule-lateral-top1-asof.js +1 -2
  154. package/dist/src/planner/rules/join/rule-lateral-top1-asof.js.map +1 -1
  155. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts +43 -0
  156. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts.map +1 -0
  157. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js +115 -0
  158. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js.map +1 -0
  159. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts +102 -0
  160. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts.map +1 -0
  161. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js +545 -0
  162. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js.map +1 -0
  163. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts +45 -0
  164. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts.map +1 -0
  165. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js +78 -0
  166. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js.map +1 -0
  167. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +1 -1
  168. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -1
  169. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +2 -2
  170. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
  171. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +16 -0
  172. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -1
  173. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +47 -4
  174. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -1
  175. package/dist/src/planner/rules/window/rule-monotonic-window.js +1 -1
  176. package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -1
  177. package/dist/src/planner/scopes/param.d.ts.map +1 -1
  178. package/dist/src/planner/scopes/param.js +13 -11
  179. package/dist/src/planner/scopes/param.js.map +1 -1
  180. package/dist/src/planner/type-utils.js +1 -1
  181. package/dist/src/planner/type-utils.js.map +1 -1
  182. package/dist/src/planner/util/fd-utils.d.ts +59 -1
  183. package/dist/src/planner/util/fd-utils.d.ts.map +1 -1
  184. package/dist/src/planner/util/fd-utils.js +122 -0
  185. package/dist/src/planner/util/fd-utils.js.map +1 -1
  186. package/dist/src/planner/util/key-utils.d.ts +26 -3
  187. package/dist/src/planner/util/key-utils.d.ts.map +1 -1
  188. package/dist/src/planner/util/key-utils.js +113 -33
  189. package/dist/src/planner/util/key-utils.js.map +1 -1
  190. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
  191. package/dist/src/planner/validation/plan-validator.js +17 -19
  192. package/dist/src/planner/validation/plan-validator.js.map +1 -1
  193. package/dist/src/runtime/async-semaphore.d.ts +36 -0
  194. package/dist/src/runtime/async-semaphore.d.ts.map +1 -0
  195. package/dist/src/runtime/async-semaphore.js +72 -0
  196. package/dist/src/runtime/async-semaphore.js.map +1 -0
  197. package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
  198. package/dist/src/runtime/deferred-constraint-queue.js +4 -3
  199. package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
  200. package/dist/src/runtime/delta-executor.d.ts.map +1 -1
  201. package/dist/src/runtime/delta-executor.js +9 -0
  202. package/dist/src/runtime/delta-executor.js.map +1 -1
  203. package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -1
  204. package/dist/src/runtime/emit/asof-scan.js +6 -4
  205. package/dist/src/runtime/emit/asof-scan.js.map +1 -1
  206. package/dist/src/runtime/emit/async-gather.d.ts +77 -0
  207. package/dist/src/runtime/emit/async-gather.d.ts.map +1 -0
  208. package/dist/src/runtime/emit/async-gather.js +234 -0
  209. package/dist/src/runtime/emit/async-gather.js.map +1 -0
  210. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  211. package/dist/src/runtime/emit/binary.js +19 -27
  212. package/dist/src/runtime/emit/binary.js.map +1 -1
  213. package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
  214. package/dist/src/runtime/emit/bloom-join.js +42 -19
  215. package/dist/src/runtime/emit/bloom-join.js.map +1 -1
  216. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
  217. package/dist/src/runtime/emit/constraint-check.js +35 -1
  218. package/dist/src/runtime/emit/constraint-check.js.map +1 -1
  219. package/dist/src/runtime/emit/delete.d.ts.map +1 -1
  220. package/dist/src/runtime/emit/delete.js +15 -5
  221. package/dist/src/runtime/emit/delete.js.map +1 -1
  222. package/dist/src/runtime/emit/eager-prefetch.d.ts +77 -0
  223. package/dist/src/runtime/emit/eager-prefetch.d.ts.map +1 -0
  224. package/dist/src/runtime/emit/eager-prefetch.js +223 -0
  225. package/dist/src/runtime/emit/eager-prefetch.js.map +1 -0
  226. package/dist/src/runtime/emit/fanout-lookup-join.d.ts +130 -0
  227. package/dist/src/runtime/emit/fanout-lookup-join.d.ts.map +1 -0
  228. package/dist/src/runtime/emit/fanout-lookup-join.js +521 -0
  229. package/dist/src/runtime/emit/fanout-lookup-join.js.map +1 -0
  230. package/dist/src/runtime/emit/merge-join.d.ts.map +1 -1
  231. package/dist/src/runtime/emit/merge-join.js +4 -2
  232. package/dist/src/runtime/emit/merge-join.js.map +1 -1
  233. package/dist/src/runtime/parallel-driver.d.ts +68 -0
  234. package/dist/src/runtime/parallel-driver.d.ts.map +1 -0
  235. package/dist/src/runtime/parallel-driver.js +233 -0
  236. package/dist/src/runtime/parallel-driver.js.map +1 -0
  237. package/dist/src/runtime/register.d.ts.map +1 -1
  238. package/dist/src/runtime/register.js +9 -0
  239. package/dist/src/runtime/register.js.map +1 -1
  240. package/dist/src/runtime/strict-fork.d.ts +36 -0
  241. package/dist/src/runtime/strict-fork.d.ts.map +1 -0
  242. package/dist/src/runtime/strict-fork.js +125 -0
  243. package/dist/src/runtime/strict-fork.js.map +1 -0
  244. package/dist/src/types/temporal-types.d.ts.map +1 -1
  245. package/dist/src/types/temporal-types.js +71 -36
  246. package/dist/src/types/temporal-types.js.map +1 -1
  247. package/dist/src/util/comparison.d.ts.map +1 -1
  248. package/dist/src/util/comparison.js +11 -1
  249. package/dist/src/util/comparison.js.map +1 -1
  250. package/dist/src/vtab/concurrency.d.ts +29 -0
  251. package/dist/src/vtab/concurrency.d.ts.map +1 -0
  252. package/dist/src/vtab/concurrency.js +47 -0
  253. package/dist/src/vtab/concurrency.js.map +1 -0
  254. package/dist/src/vtab/memory/layer/scan-layer.d.ts.map +1 -1
  255. package/dist/src/vtab/memory/layer/scan-layer.js +67 -29
  256. package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
  257. package/dist/src/vtab/memory/module.d.ts +21 -0
  258. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  259. package/dist/src/vtab/memory/module.js +21 -0
  260. package/dist/src/vtab/memory/module.js.map +1 -1
  261. package/dist/src/vtab/module.d.ts +47 -0
  262. package/dist/src/vtab/module.d.ts.map +1 -1
  263. package/package.json +4 -3
@@ -1,6 +1,6 @@
1
1
  import { createLogger } from '../../../common/logger.js';
2
2
  import { DistinctNode } from '../../nodes/distinct-node.js';
3
- import { hasAnyKey, hasSingletonFd } from '../../util/fd-utils.js';
3
+ import { keysOf } from '../../util/fd-utils.js';
4
4
  const log = createLogger('optimizer:rule:distinct-elimination');
5
5
  /**
6
6
  * Rule: DISTINCT Elimination
@@ -8,30 +8,23 @@ const log = createLogger('optimizer:rule:distinct-elimination');
8
8
  * When a DistinctNode's source already guarantees unique rows, the DISTINCT is
9
9
  * redundant and can be removed.
10
10
  *
11
- * Sources of uniqueness proof:
12
- * 1. Logical keys (`RelationType.keys`) — schema-declared, available at any time.
13
- * 2. Physical FD set encodes derived keys as `K all_other_cols` FDs, plus
14
- * the singleton `∅ all_cols` for at-most-one-row claims.
15
- *
16
- * A non-empty key proof on the source proves it already produces unique rows —
17
- * DISTINCT is a no-op.
11
+ * Uniqueness is read through the single `keysOf` surface, which reconciles all
12
+ * three places a uniqueness fact can live (declared `RelationType.keys`, the
13
+ * physical FD set, and `RelationType.isSet`): a non-empty key set the source
14
+ * is already a set DISTINCT is a no-op. This closes the gap where a
15
+ * `select distinct x, y` (which proves only the all-columns/`isSet` key, not a
16
+ * smaller FD/declared key) was invisible to the FD-only checks so an outer
17
+ * `select distinct x, y from (select distinct x, y …)` now drops the redundant
18
+ * outer DISTINCT.
18
19
  */
19
20
  export function ruleDistinctElimination(node, _context) {
20
21
  if (!(node instanceof DistinctNode))
21
22
  return null;
22
- // Logical keys (RelationType.keys) are the schema-level claim.
23
- const sourceType = node.source.getType();
24
- if (sourceType.keys && sourceType.keys.length > 0) {
25
- log('Eliminating redundant DISTINCT: source has logical keys %j', sourceType.keys);
26
- return node.source;
27
- }
28
- // Physical FDs: an FD whose determinants form a non-trivial superkey of the
29
- // source columns proves uniqueness; the singleton `∅ → all_cols` proves
30
- // at-most-one-row (also unique).
31
- const sourcePhys = node.source.physical;
32
- const colCount = node.source.getAttributes().length;
33
- if (hasAnyKey(sourcePhys?.fds, colCount) || hasSingletonFd(sourcePhys?.fds, colCount)) {
34
- log('Eliminating redundant DISTINCT: source FDs imply unique rows');
23
+ // A non-empty key set proves the source already produces unique rows. This
24
+ // covers logical keys, FD-derived keys, the at-most-one-row empty key, and
25
+ // the all-columns/`isSet` key all via the unified surface.
26
+ if (keysOf(node.source).length > 0) {
27
+ log('Eliminating redundant DISTINCT: source has a proven unique key');
35
28
  return node.source;
36
29
  }
37
30
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"rule-distinct-elimination.js","sourceRoot":"","sources":["../../../../../src/planner/rules/distinct/rule-distinct-elimination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEnE,MAAM,GAAG,GAAG,YAAY,CAAC,qCAAqC,CAAC,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAc,EAAE,QAAoB;IAC3E,IAAI,CAAC,CAAC,IAAI,YAAY,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjD,+DAA+D;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACzC,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,4DAA4D,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,4EAA4E;IAC5E,wEAAwE;IACxE,iCAAiC;IACjC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC;IACpD,IAAI,SAAS,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,cAAc,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;QACvF,GAAG,CAAC,8DAA8D,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"rule-distinct-elimination.js","sourceRoot":"","sources":["../../../../../src/planner/rules/distinct/rule-distinct-elimination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,MAAM,GAAG,GAAG,YAAY,CAAC,qCAAqC,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAc,EAAE,QAAoB;IAC3E,IAAI,CAAC,CAAC,IAAI,YAAY,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjD,2EAA2E;IAC3E,2EAA2E;IAC3E,6DAA6D;IAC7D,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,GAAG,CAAC,gEAAgE,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -20,10 +20,10 @@ export function isOrderedOnEquiPairs(source, equiPairs, side) {
20
20
  return false;
21
21
  if (equiPairs.length > ordering.length)
22
22
  return false;
23
- const attrs = source.getAttributes();
23
+ const attrIndex = source.getAttributeIndex();
24
24
  for (let i = 0; i < equiPairs.length; i++) {
25
25
  const attrId = side === 'left' ? equiPairs[i].leftAttrId : equiPairs[i].rightAttrId;
26
- const idx = attrs.findIndex(a => a.id === attrId);
26
+ const idx = attrIndex.get(attrId) ?? -1;
27
27
  if (idx === -1)
28
28
  return false;
29
29
  if (ordering[i].column !== idx || ordering[i].desc)
@@ -40,10 +40,10 @@ export function reorderEquiPairsForMerge(equiPairs, left, right) {
40
40
  const leftOrdering = PlanNodeCharacteristics.getOrdering(left);
41
41
  if (!leftOrdering || leftOrdering.length < equiPairs.length)
42
42
  return null;
43
- const leftAttrs = left.getAttributes();
43
+ const leftAttrIndex = left.getAttributeIndex();
44
44
  const colToEqIdx = new Map();
45
45
  for (let i = 0; i < equiPairs.length; i++) {
46
- const attrIdx = leftAttrs.findIndex(a => a.id === equiPairs[i].leftAttrId);
46
+ const attrIdx = leftAttrIndex.get(equiPairs[i].leftAttrId) ?? -1;
47
47
  if (attrIdx === -1)
48
48
  return null;
49
49
  colToEqIdx.set(attrIdx, i);
@@ -1 +1 @@
1
- {"version":3,"file":"equi-pair-extractor.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/equi-pair-extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"equi-pair-extractor.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/equi-pair-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Rule: Fan-out Batched Outer
3
+ *
4
+ * Flips an already-formed `FanOutLookupJoinNode` from the default `serial` outer
5
+ * mode to `batched` (cross-row pipelined) when the cost model says overlapping
6
+ * lookups *across* outer rows pays off. This is the recognition rule that
7
+ * *chooses* the batched runtime (`runFanOutLookupJoinBatched`); the runtime
8
+ * itself landed in `parallel-fanout-lookup-join-batched-outer`.
9
+ *
10
+ * **Why a post-pass, not a formation-time decision.** `rule-fanout-lookup-join`
11
+ * forms the node in `PassId.Structural`; this rule runs in `PassId.Post-
12
+ * Optimization` (priority 16, in the `eager-prefetch-probe` / `async-gather`
13
+ * neighborhood) after physical-pass selection has finalized leaf
14
+ * `expectedLatencyMs` / `estimatedRows` / `concurrencySafe`. Matching the
15
+ * already-built `FanOutLookupJoinNode` keeps the batched decision a single,
16
+ * isolated rewrite rather than another recognition path.
17
+ *
18
+ * **When batched wins.** Batched mode helps when there are *many outer rows but
19
+ * few branches per row* — the per-row branch count under-saturates the global
20
+ * in-flight budget, so admitting more outer rows ahead of the emit frontier is
21
+ * the only way to fill it. All of the following must hold:
22
+ *
23
+ * - **Budget under-saturated per row:** `branchCount < outerBatchConcurrency`.
24
+ * When a single row's branches already meet/exceed the global budget,
25
+ * cross-row admission buys nothing (the budget is full from one row).
26
+ * - **High-latency branches:** the slowest branch's `expectedLatencyMs` clears
27
+ * `tuning.parallel.batchedOuterThresholdMs`. This is 0 on every memory-vtab
28
+ * leaf, so the rule is **inert by design on local-only plans** — the golden
29
+ * sweep is unaffected, same discipline as `gatherThresholdMs` /
30
+ * `prefetchProbeThresholdMs`.
31
+ * - **Large outer cardinality:** `outer.estimatedRows >= batchedOuterMinRows`,
32
+ * so cross-row overlap dominates the reorder-buffer + per-row-fork overhead.
33
+ * An unknown estimate fails the gate (never flip on a missing statistic).
34
+ *
35
+ * **Cross branches are out of scope.** A cross (1:n) branch's batched outer
36
+ * mode is owned by `parallel-fanout-lookup-join-cross-mode`; this rule only
37
+ * flips clusters whose branches are all `atMostOne-*`. A node carrying any
38
+ * `cross` or `cross-left` branch is left serial (both are 1:n cross factors).
39
+ *
40
+ * **Outer-source isolation (load-bearing correctness).** The batched driver
41
+ * pumps the outer source *concurrently* with in-flight per-row branch forks —
42
+ * unlike serial mode, which fully resolves one outer row before pulling the
43
+ * next. The scheduler runs every instruction against one shared
44
+ * `RuntimeContext`, so a raw outer sub-plan that mutates `rctx.context` during
45
+ * the pump (installing a row slot, etc.) would (a) risk a torn read for any
46
+ * branch reading that entry and (b) throw a strict-fork violation when the
47
+ * fan-out is nested under another fork (so `rctx.context` is strict-wrapped) and
48
+ * the live row forks hold the bump counter. To neutralize both, this rule wraps
49
+ * the outer in an `EagerPrefetchNode` when it flips to batched: the prefetch
50
+ * pump runs the outer sub-plan against its *own* forked context (mutations land
51
+ * on the fork, never on the shared `rctx.context` the row forks bump), and the
52
+ * batched pump merely drains the prefetch buffer — a pure buffer read that never
53
+ * touches `rctx.context`. So **batched implies prefetch** (the reverse does not
54
+ * hold; `eager-prefetch-probe` uses the node independently). The prefetch buffer
55
+ * also feeds the read-ahead window the batched driver consumes across rows, so
56
+ * the two compose rather than duplicate work. The branch correlations are
57
+ * already safe by construction: `rule-fanout-lookup-join` only clusters branches
58
+ * (spine + correlated scalar-aggregate subqueries) that reference the *outer
59
+ * row's* attributes, which the batched driver isolates per row in its own boxed
60
+ * slot.
61
+ *
62
+ * **Outer concurrency gate.** Because the prefetch pump iterates the outer
63
+ * concurrently with branch lookups, the outer must advertise
64
+ * `physical.concurrencySafe === true` (mirroring `eager-prefetch-probe` /
65
+ * `async-gather`). Serial mode never overlapped these, so this gate is
66
+ * batched-specific.
67
+ *
68
+ * **Idempotence.** After the rewrite `outerMode === 'batched'`, so a second
69
+ * firing returns null immediately.
70
+ */
71
+ import type { OptContext } from '../../framework/context.js';
72
+ import type { PlanNode } from '../../nodes/plan-node.js';
73
+ export declare function ruleFanOutBatchedOuter(node: PlanNode, context: OptContext): PlanNode | null;
74
+ //# sourceMappingURL=rule-fanout-batched-outer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-fanout-batched-outer.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-fanout-batched-outer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AAyB7E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAsD3F"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Rule: Fan-out Batched Outer
3
+ *
4
+ * Flips an already-formed `FanOutLookupJoinNode` from the default `serial` outer
5
+ * mode to `batched` (cross-row pipelined) when the cost model says overlapping
6
+ * lookups *across* outer rows pays off. This is the recognition rule that
7
+ * *chooses* the batched runtime (`runFanOutLookupJoinBatched`); the runtime
8
+ * itself landed in `parallel-fanout-lookup-join-batched-outer`.
9
+ *
10
+ * **Why a post-pass, not a formation-time decision.** `rule-fanout-lookup-join`
11
+ * forms the node in `PassId.Structural`; this rule runs in `PassId.Post-
12
+ * Optimization` (priority 16, in the `eager-prefetch-probe` / `async-gather`
13
+ * neighborhood) after physical-pass selection has finalized leaf
14
+ * `expectedLatencyMs` / `estimatedRows` / `concurrencySafe`. Matching the
15
+ * already-built `FanOutLookupJoinNode` keeps the batched decision a single,
16
+ * isolated rewrite rather than another recognition path.
17
+ *
18
+ * **When batched wins.** Batched mode helps when there are *many outer rows but
19
+ * few branches per row* — the per-row branch count under-saturates the global
20
+ * in-flight budget, so admitting more outer rows ahead of the emit frontier is
21
+ * the only way to fill it. All of the following must hold:
22
+ *
23
+ * - **Budget under-saturated per row:** `branchCount < outerBatchConcurrency`.
24
+ * When a single row's branches already meet/exceed the global budget,
25
+ * cross-row admission buys nothing (the budget is full from one row).
26
+ * - **High-latency branches:** the slowest branch's `expectedLatencyMs` clears
27
+ * `tuning.parallel.batchedOuterThresholdMs`. This is 0 on every memory-vtab
28
+ * leaf, so the rule is **inert by design on local-only plans** — the golden
29
+ * sweep is unaffected, same discipline as `gatherThresholdMs` /
30
+ * `prefetchProbeThresholdMs`.
31
+ * - **Large outer cardinality:** `outer.estimatedRows >= batchedOuterMinRows`,
32
+ * so cross-row overlap dominates the reorder-buffer + per-row-fork overhead.
33
+ * An unknown estimate fails the gate (never flip on a missing statistic).
34
+ *
35
+ * **Cross branches are out of scope.** A cross (1:n) branch's batched outer
36
+ * mode is owned by `parallel-fanout-lookup-join-cross-mode`; this rule only
37
+ * flips clusters whose branches are all `atMostOne-*`. A node carrying any
38
+ * `cross` or `cross-left` branch is left serial (both are 1:n cross factors).
39
+ *
40
+ * **Outer-source isolation (load-bearing correctness).** The batched driver
41
+ * pumps the outer source *concurrently* with in-flight per-row branch forks —
42
+ * unlike serial mode, which fully resolves one outer row before pulling the
43
+ * next. The scheduler runs every instruction against one shared
44
+ * `RuntimeContext`, so a raw outer sub-plan that mutates `rctx.context` during
45
+ * the pump (installing a row slot, etc.) would (a) risk a torn read for any
46
+ * branch reading that entry and (b) throw a strict-fork violation when the
47
+ * fan-out is nested under another fork (so `rctx.context` is strict-wrapped) and
48
+ * the live row forks hold the bump counter. To neutralize both, this rule wraps
49
+ * the outer in an `EagerPrefetchNode` when it flips to batched: the prefetch
50
+ * pump runs the outer sub-plan against its *own* forked context (mutations land
51
+ * on the fork, never on the shared `rctx.context` the row forks bump), and the
52
+ * batched pump merely drains the prefetch buffer — a pure buffer read that never
53
+ * touches `rctx.context`. So **batched implies prefetch** (the reverse does not
54
+ * hold; `eager-prefetch-probe` uses the node independently). The prefetch buffer
55
+ * also feeds the read-ahead window the batched driver consumes across rows, so
56
+ * the two compose rather than duplicate work. The branch correlations are
57
+ * already safe by construction: `rule-fanout-lookup-join` only clusters branches
58
+ * (spine + correlated scalar-aggregate subqueries) that reference the *outer
59
+ * row's* attributes, which the batched driver isolates per row in its own boxed
60
+ * slot.
61
+ *
62
+ * **Outer concurrency gate.** Because the prefetch pump iterates the outer
63
+ * concurrently with branch lookups, the outer must advertise
64
+ * `physical.concurrencySafe === true` (mirroring `eager-prefetch-probe` /
65
+ * `async-gather`). Serial mode never overlapped these, so this gate is
66
+ * batched-specific.
67
+ *
68
+ * **Idempotence.** After the rewrite `outerMode === 'batched'`, so a second
69
+ * firing returns null immediately.
70
+ */
71
+ import { createLogger } from '../../../common/logger.js';
72
+ import { PlanNodeType } from '../../nodes/plan-node-type.js';
73
+ import { FanOutLookupJoinNode, isCrossBranchMode } from '../../nodes/fanout-lookup-join-node.js';
74
+ import { EagerPrefetchNode } from '../../nodes/eager-prefetch-node.js';
75
+ const log = createLogger('optimizer:rule:fanout-batched-outer');
76
+ /**
77
+ * Best-available row estimate for the fan-out's outer. The leaf access node
78
+ * carries `physical.estimatedRows` but several pass-through wrappers (notably
79
+ * `AliasNode`) propagate it via the `.estimatedRows` getter, which the leaves do
80
+ * not all populate — so a value can be present on the leaf's `physical` yet
81
+ * undefined on the wrapper above it. Read the node's own estimate first, then
82
+ * descend single-relation pass-throughs (alias/filter/sort/…) to recover the
83
+ * leaf's estimate. A multi-relation node (a join outer in a subquery cluster)
84
+ * returns `undefined`, which the caller treats as failing the cardinality gate.
85
+ */
86
+ function outerRowEstimate(node) {
87
+ const direct = node.physical?.estimatedRows ?? node.estimatedRows;
88
+ if (direct !== undefined)
89
+ return direct;
90
+ const relations = node.getRelations();
91
+ if (relations.length === 1)
92
+ return outerRowEstimate(relations[0]);
93
+ return undefined;
94
+ }
95
+ export function ruleFanOutBatchedOuter(node, context) {
96
+ if (!(node instanceof FanOutLookupJoinNode))
97
+ return null;
98
+ if (node.outerMode === 'batched')
99
+ return null; // idempotence
100
+ const tuning = context.tuning.parallel;
101
+ const branchCount = node.branches.length;
102
+ // Cross-branch batched outer is owned by the cross-mode ticket; only flip
103
+ // clusters whose branches are all at-most-one. `cross-left` is a 1:n cross
104
+ // factor too, so it is excluded on the same grounds as `cross`.
105
+ if (node.branches.some(b => isCrossBranchMode(b.mode)))
106
+ return null;
107
+ // Budget under-saturation: batched only helps when one row's branches leave
108
+ // global-budget headroom for *more* outer rows to fill.
109
+ if (branchCount >= tuning.outerBatchConcurrency)
110
+ return null;
111
+ // Latency gate: the slowest branch must clear the threshold. Inert on
112
+ // memory-vtab plans (expectedLatencyMs = 0 throughout).
113
+ let maxLatency = 0;
114
+ for (const b of node.branches) {
115
+ const l = b.child.physical.expectedLatencyMs ?? 0;
116
+ if (l > maxLatency)
117
+ maxLatency = l;
118
+ }
119
+ if (maxLatency < tuning.batchedOuterThresholdMs)
120
+ return null;
121
+ // Cardinality gate: enough outer rows for cross-row overlap to amortize the
122
+ // reorder-buffer / per-row-fork overhead. Unknown estimate fails the gate.
123
+ const outerRows = outerRowEstimate(node.outer);
124
+ if (outerRows === undefined || outerRows < tuning.batchedOuterMinRows)
125
+ return null;
126
+ // Concurrency gate: the prefetch pump iterates the outer concurrently with
127
+ // branch lookups, so the outer must be proven concurrency-safe.
128
+ if (node.outer.physical.concurrencySafe !== true)
129
+ return null;
130
+ // Wrap the outer in EagerPrefetch (isolation + read-ahead feed) unless it is
131
+ // already prefetched. Sized to `maxOuterReadAhead` — the outer-read-ahead
132
+ // bound this node's batched driver works against.
133
+ const outer = node.outer.nodeType === PlanNodeType.EagerPrefetch
134
+ ? node.outer
135
+ : new EagerPrefetchNode(node.scope, node.outer, tuning.maxOuterReadAhead);
136
+ log('Flipping FanOutLookupJoin %s to batched outer mode (branches=%d, maxLatency=%d ms, outerRows=%s, globalCap=%d)', node.id, branchCount, maxLatency, String(outerRows), tuning.outerBatchConcurrency);
137
+ return new FanOutLookupJoinNode(node.scope, outer, node.branches, node.concurrencyCap, node.preserveAttributeIds, 'batched');
138
+ }
139
+ //# sourceMappingURL=rule-fanout-batched-outer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-fanout-batched-outer.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-fanout-batched-outer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Rule: Fan-out Lookup Join (FK→PK + 1:n cross + correlated scalar-aggregate
3
+ * subqueries)
4
+ *
5
+ * Clusters per-outer-row branches into one `FanOutLookupJoinNode` that drives
6
+ * them concurrently per outer row. A branch is either *at-most-one* (≤1 row per
7
+ * outer row) or *cross* (data-driven 1:n, Cartesian product per outer row):
8
+ *
9
+ * 1. **Join-spine branches.** A chain of N LEFT/INNER/CROSS nested-loop joins
10
+ * from a common outer where every join's non-preserved side is a
11
+ * parameterized equi-lookup. FK→PK-aligned lookups become at-most-one
12
+ * branches (matching the alignment `ruleJoinElimination` trusts); lookups
13
+ * that are *not* provably at-most-one (no FK, or FK→non-unique) become
14
+ * `cross` branches whose 1:n product is bounded by the row/product guards
15
+ * (`tuning.parallel.maxCrossBranchRows` / `maxCrossProduct`). A chain may
16
+ * legitimately mix both modes.
17
+ *
18
+ * 2. **Subquery branches.** Correlated scalar-aggregate `ScalarSubqueryNode`s
19
+ * found anywhere in the SELECT projection list — bare (`(select count(*)
20
+ * from c where c.fk = o.k)`) or wrapped inside a scalar expression
21
+ * (`coalesce((select sum(...) ...), 0)`, `json((select json_group_array(
22
+ * ...) ...))`). A scalar aggregate with no GROUP BY emits exactly one row
23
+ * per outer row regardless of how many child rows match — relationally an
24
+ * `atMostOne-left` branch driven per outer row, exactly what the fan-out
25
+ * node already does. The subquery's relational root is used verbatim as
26
+ * the branch child (its correlation predicate is internal and resolves
27
+ * through `rctx.context`); only the *inner* `ScalarSubqueryNode` is
28
+ * rewritten to a column reference into the fan-out's wide row, leaving any
29
+ * wrapping expression (`coalesce(<colref>, 0)`) intact.
30
+ *
31
+ * When the *combined* branch count clears `tuning.parallel.minBranches` AND the
32
+ * projected latency win covers the per-branch setup overhead, the cluster
33
+ * forms.
34
+ *
35
+ * Cost gate is anchored on `physical.expectedLatencyMs` — populated 0 for
36
+ * in-process / memory-vtab paths, non-zero for remote vtabs whose access plan
37
+ * declares per-call latency. As a consequence, with no remote-vtab plugin in
38
+ * tree the rule is inert by design (memory-vtab golden plans don't change).
39
+ *
40
+ * Join-spine branch eligibility mirrors `ruleJoinElimination`:
41
+ * - AND-of-column-equalities ON-clause (any residual disqualifies the
42
+ * branch — leave it as a normal nested-loop join),
43
+ * - FK→PK alignment validated via `lookupCoveringFK` + `checkFkPkAlignment`,
44
+ * - INNER branches additionally require NOT-NULL FK + row-preserving path
45
+ * to the PK table.
46
+ *
47
+ * Subquery branch eligibility:
48
+ * - a `ScalarSubqueryNode` reached anywhere in a projection's scalar
49
+ * expression tree (bare or wrapped — `collectScalarSubqueries` finds it),
50
+ * - the subquery is correlated,
51
+ * - beneath pass-through wrappers the relational root is aggregate-shaped
52
+ * with zero grouping keys (⇒ exactly one row per outer),
53
+ * - the subquery exposes exactly one output attribute.
54
+ */
55
+ import type { OptContext } from '../../framework/context.js';
56
+ import { type PlanNode } from '../../nodes/plan-node.js';
57
+ export declare function ruleFanOutLookupJoin(node: PlanNode, context: OptContext): PlanNode | null;
58
+ //# sourceMappingURL=rule-fanout-lookup-join.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-fanout-lookup-join.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-fanout-lookup-join.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAGN,KAAK,QAAQ,EAGb,MAAM,0BAA0B,CAAC;AA4DlC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAgOzF"}