@quereus/quereus 2.8.0 → 3.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 (454) hide show
  1. package/README.md +224 -222
  2. package/dist/src/core/database-assertions.d.ts +36 -16
  3. package/dist/src/core/database-assertions.d.ts.map +1 -1
  4. package/dist/src/core/database-assertions.js +222 -118
  5. package/dist/src/core/database-assertions.js.map +1 -1
  6. package/dist/src/core/database-transaction.d.ts +96 -13
  7. package/dist/src/core/database-transaction.d.ts.map +1 -1
  8. package/dist/src/core/database-transaction.js +294 -35
  9. package/dist/src/core/database-transaction.js.map +1 -1
  10. package/dist/src/core/database-watchers.d.ts +58 -0
  11. package/dist/src/core/database-watchers.d.ts.map +1 -0
  12. package/dist/src/core/database-watchers.js +206 -0
  13. package/dist/src/core/database-watchers.js.map +1 -0
  14. package/dist/src/core/database.d.ts +78 -5
  15. package/dist/src/core/database.d.ts.map +1 -1
  16. package/dist/src/core/database.js +120 -20
  17. package/dist/src/core/database.js.map +1 -1
  18. package/dist/src/core/statement.d.ts +9 -0
  19. package/dist/src/core/statement.d.ts.map +1 -1
  20. package/dist/src/core/statement.js +29 -0
  21. package/dist/src/core/statement.js.map +1 -1
  22. package/dist/src/core/table-handle.d.ts +45 -0
  23. package/dist/src/core/table-handle.d.ts.map +1 -0
  24. package/dist/src/core/table-handle.js +54 -0
  25. package/dist/src/core/table-handle.js.map +1 -0
  26. package/dist/src/emit/ast-stringify.d.ts.map +1 -1
  27. package/dist/src/emit/ast-stringify.js +0 -3
  28. package/dist/src/emit/ast-stringify.js.map +1 -1
  29. package/dist/src/func/builtins/conversion.d.ts.map +1 -1
  30. package/dist/src/func/builtins/conversion.js +12 -1
  31. package/dist/src/func/builtins/conversion.js.map +1 -1
  32. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  33. package/dist/src/func/builtins/explain.js +22 -8
  34. package/dist/src/func/builtins/explain.js.map +1 -1
  35. package/dist/src/func/builtins/generation.d.ts.map +1 -1
  36. package/dist/src/func/builtins/generation.js +26 -1
  37. package/dist/src/func/builtins/generation.js.map +1 -1
  38. package/dist/src/func/builtins/index.d.ts.map +1 -1
  39. package/dist/src/func/builtins/index.js +5 -1
  40. package/dist/src/func/builtins/index.js.map +1 -1
  41. package/dist/src/func/builtins/json-tvf.d.ts.map +1 -1
  42. package/dist/src/func/builtins/json-tvf.js +16 -2
  43. package/dist/src/func/builtins/json-tvf.js.map +1 -1
  44. package/dist/src/func/builtins/schema.d.ts +4 -0
  45. package/dist/src/func/builtins/schema.d.ts.map +1 -1
  46. package/dist/src/func/builtins/schema.js +270 -11
  47. package/dist/src/func/builtins/schema.js.map +1 -1
  48. package/dist/src/func/registration.d.ts +19 -1
  49. package/dist/src/func/registration.d.ts.map +1 -1
  50. package/dist/src/func/registration.js +8 -3
  51. package/dist/src/func/registration.js.map +1 -1
  52. package/dist/src/index.d.ts +7 -1
  53. package/dist/src/index.d.ts.map +1 -1
  54. package/dist/src/index.js +5 -0
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/parser/ast.d.ts +3 -2
  57. package/dist/src/parser/ast.d.ts.map +1 -1
  58. package/dist/src/parser/parser.d.ts.map +1 -1
  59. package/dist/src/parser/parser.js +25 -8
  60. package/dist/src/parser/parser.js.map +1 -1
  61. package/dist/src/planner/analysis/assertion-classifier.d.ts +71 -0
  62. package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -0
  63. package/dist/src/planner/analysis/assertion-classifier.js +286 -0
  64. package/dist/src/planner/analysis/assertion-classifier.js.map +1 -0
  65. package/dist/src/planner/analysis/assertion-hoist-cache.d.ts +34 -0
  66. package/dist/src/planner/analysis/assertion-hoist-cache.d.ts.map +1 -0
  67. package/dist/src/planner/analysis/assertion-hoist-cache.js +119 -0
  68. package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -0
  69. package/dist/src/planner/analysis/binding-extractor.d.ts +58 -0
  70. package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -0
  71. package/dist/src/planner/analysis/binding-extractor.js +110 -0
  72. package/dist/src/planner/analysis/binding-extractor.js.map +1 -0
  73. package/dist/src/planner/analysis/change-scope.d.ts +184 -0
  74. package/dist/src/planner/analysis/change-scope.d.ts.map +1 -0
  75. package/dist/src/planner/analysis/change-scope.js +825 -0
  76. package/dist/src/planner/analysis/change-scope.js.map +1 -0
  77. package/dist/src/planner/analysis/check-extraction.d.ts +29 -0
  78. package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -0
  79. package/dist/src/planner/analysis/check-extraction.js +420 -0
  80. package/dist/src/planner/analysis/check-extraction.js.map +1 -0
  81. package/dist/src/planner/analysis/constraint-extractor.d.ts +47 -7
  82. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  83. package/dist/src/planner/analysis/constraint-extractor.js +169 -92
  84. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  85. package/dist/src/planner/analysis/partial-unique-extraction.d.ts +68 -0
  86. package/dist/src/planner/analysis/partial-unique-extraction.d.ts.map +1 -0
  87. package/dist/src/planner/analysis/partial-unique-extraction.js +347 -0
  88. package/dist/src/planner/analysis/partial-unique-extraction.js.map +1 -0
  89. package/dist/src/planner/analysis/predicate-conjuncts.d.ts +14 -0
  90. package/dist/src/planner/analysis/predicate-conjuncts.d.ts.map +1 -0
  91. package/dist/src/planner/analysis/predicate-conjuncts.js +31 -0
  92. package/dist/src/planner/analysis/predicate-conjuncts.js.map +1 -0
  93. package/dist/src/planner/analysis/predicate-shape.d.ts +52 -0
  94. package/dist/src/planner/analysis/predicate-shape.d.ts.map +1 -0
  95. package/dist/src/planner/analysis/predicate-shape.js +119 -0
  96. package/dist/src/planner/analysis/predicate-shape.js.map +1 -0
  97. package/dist/src/planner/analysis/sat-checker.d.ts +43 -0
  98. package/dist/src/planner/analysis/sat-checker.d.ts.map +1 -0
  99. package/dist/src/planner/analysis/sat-checker.js +393 -0
  100. package/dist/src/planner/analysis/sat-checker.js.map +1 -0
  101. package/dist/src/planner/building/foreign-key-builder.d.ts.map +1 -1
  102. package/dist/src/planner/building/foreign-key-builder.js +3 -2
  103. package/dist/src/planner/building/foreign-key-builder.js.map +1 -1
  104. package/dist/src/planner/building/select.js +14 -2
  105. package/dist/src/planner/building/select.js.map +1 -1
  106. package/dist/src/planner/building/table.d.ts.map +1 -1
  107. package/dist/src/planner/building/table.js +1 -1
  108. package/dist/src/planner/building/table.js.map +1 -1
  109. package/dist/src/planner/building/update.d.ts.map +1 -1
  110. package/dist/src/planner/building/update.js +10 -6
  111. package/dist/src/planner/building/update.js.map +1 -1
  112. package/dist/src/planner/framework/characteristics.d.ts +13 -2
  113. package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
  114. package/dist/src/planner/framework/characteristics.js +31 -5
  115. package/dist/src/planner/framework/characteristics.js.map +1 -1
  116. package/dist/src/planner/framework/pass.d.ts.map +1 -1
  117. package/dist/src/planner/framework/pass.js +46 -16
  118. package/dist/src/planner/framework/pass.js.map +1 -1
  119. package/dist/src/planner/framework/physical-utils.d.ts +21 -9
  120. package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
  121. package/dist/src/planner/framework/physical-utils.js +47 -31
  122. package/dist/src/planner/framework/physical-utils.js.map +1 -1
  123. package/dist/src/planner/nodes/aggregate-node.d.ts +25 -0
  124. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  125. package/dist/src/planner/nodes/aggregate-node.js +75 -8
  126. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  127. package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
  128. package/dist/src/planner/nodes/alias-node.js +8 -1
  129. package/dist/src/planner/nodes/alias-node.js.map +1 -1
  130. package/dist/src/planner/nodes/asof-scan-node.d.ts +137 -0
  131. package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -0
  132. package/dist/src/planner/nodes/asof-scan-node.js +237 -0
  133. package/dist/src/planner/nodes/asof-scan-node.js.map +1 -0
  134. package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
  135. package/dist/src/planner/nodes/bloom-join-node.js +19 -9
  136. package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
  137. package/dist/src/planner/nodes/constraint-check-node.d.ts +3 -0
  138. package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
  139. package/dist/src/planner/nodes/constraint-check-node.js.map +1 -1
  140. package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
  141. package/dist/src/planner/nodes/distinct-node.js +17 -6
  142. package/dist/src/planner/nodes/distinct-node.js.map +1 -1
  143. package/dist/src/planner/nodes/empty-relation-node.d.ts +27 -0
  144. package/dist/src/planner/nodes/empty-relation-node.d.ts.map +1 -0
  145. package/dist/src/planner/nodes/empty-relation-node.js +61 -0
  146. package/dist/src/planner/nodes/empty-relation-node.js.map +1 -0
  147. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  148. package/dist/src/planner/nodes/filter.js +67 -5
  149. package/dist/src/planner/nodes/filter.js.map +1 -1
  150. package/dist/src/planner/nodes/function.d.ts +11 -1
  151. package/dist/src/planner/nodes/function.d.ts.map +1 -1
  152. package/dist/src/planner/nodes/function.js +94 -1
  153. package/dist/src/planner/nodes/function.js.map +1 -1
  154. package/dist/src/planner/nodes/hash-aggregate.d.ts +1 -1
  155. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
  156. package/dist/src/planner/nodes/hash-aggregate.js +10 -6
  157. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
  158. package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
  159. package/dist/src/planner/nodes/join-node.js +21 -10
  160. package/dist/src/planner/nodes/join-node.js.map +1 -1
  161. package/dist/src/planner/nodes/join-utils.d.ts +42 -1
  162. package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
  163. package/dist/src/planner/nodes/join-utils.js +132 -0
  164. package/dist/src/planner/nodes/join-utils.js.map +1 -1
  165. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  166. package/dist/src/planner/nodes/limit-offset.js +8 -1
  167. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  168. package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
  169. package/dist/src/planner/nodes/merge-join-node.js +22 -9
  170. package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
  171. package/dist/src/planner/nodes/ordinal-slice-node.d.ts +50 -0
  172. package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -0
  173. package/dist/src/planner/nodes/ordinal-slice-node.js +130 -0
  174. package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -0
  175. package/dist/src/planner/nodes/plan-node-type.d.ts +3 -0
  176. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  177. package/dist/src/planner/nodes/plan-node-type.js +3 -0
  178. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  179. package/dist/src/planner/nodes/plan-node.d.ts +316 -5
  180. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  181. package/dist/src/planner/nodes/plan-node.js +49 -0
  182. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  183. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  184. package/dist/src/planner/nodes/project-node.js +78 -28
  185. package/dist/src/planner/nodes/project-node.js.map +1 -1
  186. package/dist/src/planner/nodes/reference.d.ts +27 -2
  187. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  188. package/dist/src/planner/nodes/reference.js +117 -1
  189. package/dist/src/planner/nodes/reference.js.map +1 -1
  190. package/dist/src/planner/nodes/retrieve-node.d.ts +9 -1
  191. package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
  192. package/dist/src/planner/nodes/retrieve-node.js +21 -0
  193. package/dist/src/planner/nodes/retrieve-node.js.map +1 -1
  194. package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
  195. package/dist/src/planner/nodes/returning-node.js +64 -28
  196. package/dist/src/planner/nodes/returning-node.js.map +1 -1
  197. package/dist/src/planner/nodes/scalar.d.ts +8 -1
  198. package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
  199. package/dist/src/planner/nodes/scalar.js +112 -1
  200. package/dist/src/planner/nodes/scalar.js.map +1 -1
  201. package/dist/src/planner/nodes/set-operation-node.d.ts +2 -1
  202. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  203. package/dist/src/planner/nodes/set-operation-node.js +24 -0
  204. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  205. package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
  206. package/dist/src/planner/nodes/single-row.js +3 -1
  207. package/dist/src/planner/nodes/single-row.js.map +1 -1
  208. package/dist/src/planner/nodes/sort.d.ts.map +1 -1
  209. package/dist/src/planner/nodes/sort.js +28 -1
  210. package/dist/src/planner/nodes/sort.js.map +1 -1
  211. package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -1
  212. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  213. package/dist/src/planner/nodes/stream-aggregate.js +10 -8
  214. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  215. package/dist/src/planner/nodes/table-access-nodes.d.ts +40 -5
  216. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  217. package/dist/src/planner/nodes/table-access-nodes.js +113 -18
  218. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  219. package/dist/src/planner/nodes/table-function-call.d.ts +4 -1
  220. package/dist/src/planner/nodes/table-function-call.d.ts.map +1 -1
  221. package/dist/src/planner/nodes/table-function-call.js +224 -14
  222. package/dist/src/planner/nodes/table-function-call.js.map +1 -1
  223. package/dist/src/planner/nodes/update-node.d.ts +1 -3
  224. package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
  225. package/dist/src/planner/nodes/update-node.js +3 -9
  226. package/dist/src/planner/nodes/update-node.js.map +1 -1
  227. package/dist/src/planner/nodes/window-node.d.ts +61 -2
  228. package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
  229. package/dist/src/planner/nodes/window-node.js +71 -3
  230. package/dist/src/planner/nodes/window-node.js.map +1 -1
  231. package/dist/src/planner/optimizer-tuning.d.ts +38 -1
  232. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
  233. package/dist/src/planner/optimizer-tuning.js +6 -0
  234. package/dist/src/planner/optimizer-tuning.js.map +1 -1
  235. package/dist/src/planner/optimizer.d.ts.map +1 -1
  236. package/dist/src/planner/optimizer.js +278 -0
  237. package/dist/src/planner/optimizer.js.map +1 -1
  238. package/dist/src/planner/rules/access/rule-asof-strategy-select.d.ts +30 -0
  239. package/dist/src/planner/rules/access/rule-asof-strategy-select.d.ts.map +1 -0
  240. package/dist/src/planner/rules/access/rule-asof-strategy-select.js +112 -0
  241. package/dist/src/planner/rules/access/rule-asof-strategy-select.js.map +1 -0
  242. package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.d.ts +33 -0
  243. package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.d.ts.map +1 -0
  244. package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.js +162 -0
  245. package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.js.map +1 -0
  246. package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts +29 -0
  247. package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -0
  248. package/dist/src/planner/rules/access/rule-monotonic-range-access.js +175 -0
  249. package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -0
  250. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  251. package/dist/src/planner/rules/access/rule-select-access-path.js +53 -17
  252. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  253. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +30 -0
  254. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -0
  255. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +116 -0
  256. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -0
  257. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +7 -7
  258. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -1
  259. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +18 -16
  260. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
  261. package/dist/src/planner/rules/join/equi-pair-extractor.d.ts +61 -0
  262. package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -0
  263. package/dist/src/planner/rules/join/equi-pair-extractor.js +155 -0
  264. package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -0
  265. package/dist/src/planner/rules/join/rule-join-elimination.d.ts +56 -0
  266. package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -0
  267. package/dist/src/planner/rules/join/rule-join-elimination.js +326 -0
  268. package/dist/src/planner/rules/join/rule-join-elimination.js.map +1 -0
  269. package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -1
  270. package/dist/src/planner/rules/join/rule-join-greedy-commute.js +10 -2
  271. package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
  272. package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
  273. package/dist/src/planner/rules/join/rule-join-physical-selection.js +2 -122
  274. package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
  275. package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts +21 -0
  276. package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts.map +1 -0
  277. package/dist/src/planner/rules/join/rule-lateral-top1-asof.js +405 -0
  278. package/dist/src/planner/rules/join/rule-lateral-top1-asof.js.map +1 -0
  279. package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts +31 -0
  280. package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -0
  281. package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +113 -0
  282. package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -0
  283. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts +20 -0
  284. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts.map +1 -0
  285. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +181 -0
  286. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -0
  287. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts +46 -0
  288. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts.map +1 -0
  289. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +156 -0
  290. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js.map +1 -0
  291. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts +30 -0
  292. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -0
  293. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +60 -0
  294. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -0
  295. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts +45 -0
  296. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts.map +1 -0
  297. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js +210 -0
  298. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -0
  299. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts +29 -0
  300. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts.map +1 -0
  301. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js +161 -0
  302. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js.map +1 -0
  303. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +39 -0
  304. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -0
  305. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +91 -0
  306. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -0
  307. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts +35 -0
  308. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts.map +1 -0
  309. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +74 -0
  310. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js.map +1 -0
  311. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts +27 -0
  312. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts.map +1 -0
  313. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +103 -0
  314. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js.map +1 -0
  315. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
  316. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +1 -25
  317. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
  318. package/dist/src/planner/rules/window/rule-monotonic-window.d.ts +47 -0
  319. package/dist/src/planner/rules/window/rule-monotonic-window.d.ts.map +1 -0
  320. package/dist/src/planner/rules/window/rule-monotonic-window.js +341 -0
  321. package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -0
  322. package/dist/src/planner/scopes/global.js +2 -2
  323. package/dist/src/planner/scopes/global.js.map +1 -1
  324. package/dist/src/planner/type-utils.d.ts.map +1 -1
  325. package/dist/src/planner/type-utils.js +11 -0
  326. package/dist/src/planner/type-utils.js.map +1 -1
  327. package/dist/src/planner/util/fd-utils.d.ts +245 -0
  328. package/dist/src/planner/util/fd-utils.d.ts.map +1 -0
  329. package/dist/src/planner/util/fd-utils.js +1416 -0
  330. package/dist/src/planner/util/fd-utils.js.map +1 -0
  331. package/dist/src/planner/util/ind-utils.d.ts +79 -0
  332. package/dist/src/planner/util/ind-utils.d.ts.map +1 -0
  333. package/dist/src/planner/util/ind-utils.js +146 -0
  334. package/dist/src/planner/util/ind-utils.js.map +1 -0
  335. package/dist/src/planner/util/key-utils.d.ts +75 -14
  336. package/dist/src/planner/util/key-utils.d.ts.map +1 -1
  337. package/dist/src/planner/util/key-utils.js +234 -57
  338. package/dist/src/planner/util/key-utils.js.map +1 -1
  339. package/dist/src/runtime/context-helpers.d.ts +9 -0
  340. package/dist/src/runtime/context-helpers.d.ts.map +1 -1
  341. package/dist/src/runtime/context-helpers.js +5 -0
  342. package/dist/src/runtime/context-helpers.js.map +1 -1
  343. package/dist/src/runtime/delta-executor.d.ts +134 -0
  344. package/dist/src/runtime/delta-executor.d.ts.map +1 -0
  345. package/dist/src/runtime/delta-executor.js +382 -0
  346. package/dist/src/runtime/delta-executor.js.map +1 -0
  347. package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
  348. package/dist/src/runtime/emit/alter-table.js +52 -16
  349. package/dist/src/runtime/emit/alter-table.js.map +1 -1
  350. package/dist/src/runtime/emit/asof-scan.d.ts +10 -0
  351. package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -0
  352. package/dist/src/runtime/emit/asof-scan.js +467 -0
  353. package/dist/src/runtime/emit/asof-scan.js.map +1 -0
  354. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
  355. package/dist/src/runtime/emit/constraint-check.js +20 -0
  356. package/dist/src/runtime/emit/constraint-check.js.map +1 -1
  357. package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
  358. package/dist/src/runtime/emit/create-assertion.js +3 -2
  359. package/dist/src/runtime/emit/create-assertion.js.map +1 -1
  360. package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
  361. package/dist/src/runtime/emit/dml-executor.js +40 -13
  362. package/dist/src/runtime/emit/dml-executor.js.map +1 -1
  363. package/dist/src/runtime/emit/drop-assertion.js +1 -1
  364. package/dist/src/runtime/emit/drop-assertion.js.map +1 -1
  365. package/dist/src/runtime/emit/empty-relation.d.ts +5 -0
  366. package/dist/src/runtime/emit/empty-relation.d.ts.map +1 -0
  367. package/dist/src/runtime/emit/empty-relation.js +11 -0
  368. package/dist/src/runtime/emit/empty-relation.js.map +1 -0
  369. package/dist/src/runtime/emit/ordinal-slice.d.ts +13 -0
  370. package/dist/src/runtime/emit/ordinal-slice.d.ts.map +1 -0
  371. package/dist/src/runtime/emit/ordinal-slice.js +89 -0
  372. package/dist/src/runtime/emit/ordinal-slice.js.map +1 -0
  373. package/dist/src/runtime/emit/returning.d.ts.map +1 -1
  374. package/dist/src/runtime/emit/returning.js +9 -4
  375. package/dist/src/runtime/emit/returning.js.map +1 -1
  376. package/dist/src/runtime/emit/scan.d.ts +19 -3
  377. package/dist/src/runtime/emit/scan.d.ts.map +1 -1
  378. package/dist/src/runtime/emit/scan.js +12 -8
  379. package/dist/src/runtime/emit/scan.js.map +1 -1
  380. package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
  381. package/dist/src/runtime/emit/schema-declarative.js +91 -14
  382. package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
  383. package/dist/src/runtime/emit/window.d.ts.map +1 -1
  384. package/dist/src/runtime/emit/window.js +732 -37
  385. package/dist/src/runtime/emit/window.js.map +1 -1
  386. package/dist/src/runtime/foreign-key-actions.d.ts +16 -0
  387. package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
  388. package/dist/src/runtime/foreign-key-actions.js +86 -5
  389. package/dist/src/runtime/foreign-key-actions.js.map +1 -1
  390. package/dist/src/runtime/register.d.ts.map +1 -1
  391. package/dist/src/runtime/register.js +6 -0
  392. package/dist/src/runtime/register.js.map +1 -1
  393. package/dist/src/schema/assertion.d.ts +8 -0
  394. package/dist/src/schema/assertion.d.ts.map +1 -1
  395. package/dist/src/schema/catalog.d.ts +10 -0
  396. package/dist/src/schema/catalog.d.ts.map +1 -1
  397. package/dist/src/schema/catalog.js +29 -6
  398. package/dist/src/schema/catalog.js.map +1 -1
  399. package/dist/src/schema/change-events.d.ts +5 -1
  400. package/dist/src/schema/change-events.d.ts.map +1 -1
  401. package/dist/src/schema/change-events.js.map +1 -1
  402. package/dist/src/schema/function.d.ts +89 -1
  403. package/dist/src/schema/function.d.ts.map +1 -1
  404. package/dist/src/schema/function.js +31 -0
  405. package/dist/src/schema/function.js.map +1 -1
  406. package/dist/src/schema/manager.d.ts +43 -0
  407. package/dist/src/schema/manager.d.ts.map +1 -1
  408. package/dist/src/schema/manager.js +105 -4
  409. package/dist/src/schema/manager.js.map +1 -1
  410. package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
  411. package/dist/src/schema/rename-rewriter.js +303 -102
  412. package/dist/src/schema/rename-rewriter.js.map +1 -1
  413. package/dist/src/schema/schema-differ.d.ts +18 -1
  414. package/dist/src/schema/schema-differ.d.ts.map +1 -1
  415. package/dist/src/schema/schema-differ.js +307 -42
  416. package/dist/src/schema/schema-differ.js.map +1 -1
  417. package/dist/src/schema/table.d.ts +21 -2
  418. package/dist/src/schema/table.d.ts.map +1 -1
  419. package/dist/src/schema/table.js +17 -8
  420. package/dist/src/schema/table.js.map +1 -1
  421. package/dist/src/types/logical-type.d.ts +11 -0
  422. package/dist/src/types/logical-type.d.ts.map +1 -1
  423. package/dist/src/types/logical-type.js.map +1 -1
  424. package/dist/src/types/temporal-types.d.ts.map +1 -1
  425. package/dist/src/types/temporal-types.js +32 -0
  426. package/dist/src/types/temporal-types.js.map +1 -1
  427. package/dist/src/util/ast-literal.d.ts +11 -0
  428. package/dist/src/util/ast-literal.d.ts.map +1 -0
  429. package/dist/src/util/ast-literal.js +26 -0
  430. package/dist/src/util/ast-literal.js.map +1 -0
  431. package/dist/src/vtab/best-access-plan.d.ts +41 -0
  432. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  433. package/dist/src/vtab/best-access-plan.js +29 -0
  434. package/dist/src/vtab/best-access-plan.js.map +1 -1
  435. package/dist/src/vtab/events.d.ts +9 -0
  436. package/dist/src/vtab/events.d.ts.map +1 -1
  437. package/dist/src/vtab/events.js +19 -0
  438. package/dist/src/vtab/events.js.map +1 -1
  439. package/dist/src/vtab/filter-info.d.ts +14 -0
  440. package/dist/src/vtab/filter-info.d.ts.map +1 -1
  441. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  442. package/dist/src/vtab/memory/layer/manager.js +24 -5
  443. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  444. package/dist/src/vtab/memory/module.d.ts +39 -1
  445. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  446. package/dist/src/vtab/memory/module.js +206 -44
  447. package/dist/src/vtab/memory/module.js.map +1 -1
  448. package/dist/src/vtab/memory/utils/predicate.d.ts +2 -1
  449. package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
  450. package/dist/src/vtab/memory/utils/predicate.js +32 -1
  451. package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
  452. package/dist/src/vtab/module.d.ts +24 -0
  453. package/dist/src/vtab/module.d.ts.map +1 -1
  454. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-monotonic-merge-join.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-monotonic-merge-join.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAA6B,MAAM,0BAA0B,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAU7D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAwF5F"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Rule: Monotonic Merge Join
3
+ *
4
+ * Required Characteristics:
5
+ * - Node must be a logical JoinNode (not already physical)
6
+ * - Both inputs advertise `MonotonicOn` on (at least) one of the equi-pair
7
+ * attributes, with matching direction (ASC for v1, since the merge-join
8
+ * emitter assumes ASC ordering).
9
+ *
10
+ * Why this rule exists alongside `rule-join-physical-selection`:
11
+ * The existing rule chooses merge-join when both sources' `physical.ordering`
12
+ * matches the equi-pair attribute order positionally. That misses the canonical
13
+ * case where a merge-join's *output* declares `monotonicOn = [l.X, r.X]` but
14
+ * `ordering` reflects only the left side — a parent join on `r.X` then sees
15
+ * the right ordering implicitly through `monotonicOn` but not through
16
+ * `ordering[0]`. This rule looks the equi-pair attrs up directly in
17
+ * `monotonicOn`, recognising those (and other future MonotonicOn-propagating
18
+ * paths) without sorting.
19
+ *
20
+ * Out of scope (TODO):
21
+ * - Composite monotonic-on prefixes (multi-key streaming merge keyed on
22
+ * `(X, Y)` when both sides are jointly monotonic on the prefix).
23
+ * - Right and full outer joins — emitter doesn't support them today.
24
+ * - Recognising `monotonicOn(asc)` vs `monotonicOn(desc)` by reversing one
25
+ * side via Sort. That defeats this rule's premise (the rule's whole point is
26
+ * that no sort is needed because both sides are already monotonic).
27
+ */
28
+ import { createLogger } from '../../../common/logger.js';
29
+ import { JoinNode } from '../../nodes/join-node.js';
30
+ import { MergeJoinNode } from '../../nodes/merge-join-node.js';
31
+ import { nestedLoopJoinCost, hashJoinCost, mergeJoinCost } from '../../cost/index.js';
32
+ import { PlanNodeCharacteristics } from '../../framework/characteristics.js';
33
+ import { extractEquiPairs, extractEquiPairsFromUsing, combineResidual, isMergeReadyOnAllPairs } from './equi-pair-extractor.js';
34
+ const log = createLogger('optimizer:rule:monotonic-merge-join');
35
+ export function ruleMonotonicMergeJoin(node, _context) {
36
+ if (!(node instanceof JoinNode))
37
+ return null;
38
+ const joinType = node.joinType;
39
+ if (joinType !== 'inner' && joinType !== 'left' && joinType !== 'semi' && joinType !== 'anti')
40
+ return null;
41
+ const leftAttrs = node.left.getAttributes();
42
+ const rightAttrs = node.right.getAttributes();
43
+ const leftAttrIds = new Set(leftAttrs.map(a => a.id));
44
+ const rightAttrIds = new Set(rightAttrs.map(a => a.id));
45
+ const extracted = node.condition
46
+ ? extractEquiPairs(node.condition, leftAttrIds, rightAttrIds)
47
+ : extractEquiPairsFromUsing(node.usingColumns, leftAttrs, rightAttrs);
48
+ if (!extracted || extracted.equiPairs.length === 0)
49
+ return null;
50
+ // Defer to `rule-join-physical-selection` whenever both sides' physical
51
+ // ordering already covers ALL equi-pairs in merge-ready order. The
52
+ // ordering-based path produces a multi-key merge join with full
53
+ // unique-key propagation; demoting pairs to residual here would lose that
54
+ // propagation. Our rule is meant to *extend* recognition, not regress it.
55
+ if (isMergeReadyOnAllPairs(node.left, node.right, extracted.equiPairs))
56
+ return null;
57
+ const leftMon = PlanNodeCharacteristics.getMonotonicOn(node.left);
58
+ const rightMon = PlanNodeCharacteristics.getMonotonicOn(node.right);
59
+ if (leftMon.length === 0 || rightMon.length === 0)
60
+ return null;
61
+ // Find equi-pairs where BOTH sides are MonotonicOn on their respective
62
+ // attrId with matching direction. v1 requires ASC because the merge-join
63
+ // emitter assumes ASC; DESC-DESC streaming would need a reversed compareKeys.
64
+ const matchedIndices = [];
65
+ for (let i = 0; i < extracted.equiPairs.length; i++) {
66
+ const pair = extracted.equiPairs[i];
67
+ const l = leftMon.find(m => m.attrId === pair.leftAttrId && m.direction === 'asc');
68
+ if (!l)
69
+ continue;
70
+ const r = rightMon.find(m => m.attrId === pair.rightAttrId && m.direction === 'asc');
71
+ if (!r)
72
+ continue;
73
+ matchedIndices.push(i);
74
+ }
75
+ if (matchedIndices.length === 0)
76
+ return null;
77
+ // v1: pick a single driving equi-pair. Other equi-pairs (matched or not)
78
+ // must be evaluated as residual conjuncts — the merge-join emitter assumes
79
+ // the right side is sorted lexicographically across ALL listed equi-pair
80
+ // columns, which we cannot guarantee for non-driving keys.
81
+ // TODO: composite monotonic-on prefixes — recognise when both sides are
82
+ // jointly MonotonicOn on a multi-key prefix and use multiple driving keys.
83
+ const drivingIndex = matchedIndices[0];
84
+ const driving = [extracted.equiPairs[drivingIndex]];
85
+ // Residualize the rest. For pairs that originated from a real `=` BinaryOpNode
86
+ // (ON-condition path), reuse the original node. For USING-derived pairs,
87
+ // `equiPairNodes[i]` is undefined — bail out and let the existing
88
+ // ordering-based rule handle USING-with-multiple-pairs.
89
+ const extras = [];
90
+ for (let i = 0; i < extracted.equiPairs.length; i++) {
91
+ if (i === drivingIndex)
92
+ continue;
93
+ const orig = extracted.equiPairNodes[i];
94
+ if (!orig)
95
+ return null;
96
+ extras.push(orig);
97
+ }
98
+ const residual = combineResidual(extracted.residual, extras);
99
+ // Cost gate: even with the precondition met, hash or nested-loop may win
100
+ // on tiny inputs. Don't regress those.
101
+ const leftRows = node.left.estimatedRows ?? 100;
102
+ const rightRows = node.right.estimatedRows ?? 100;
103
+ const mergeC = mergeJoinCost(leftRows, rightRows, false, false);
104
+ const hashC = hashJoinCost(Math.min(leftRows, rightRows), Math.max(leftRows, rightRows));
105
+ const nlC = nestedLoopJoinCost(leftRows, rightRows);
106
+ if (Math.min(hashC, nlC) < mergeC) {
107
+ log('Skipping monotonic-merge: cheaper alternative exists (merge=%.2f, hash=%.2f, nl=%.2f)', mergeC, hashC, nlC);
108
+ return null;
109
+ }
110
+ log('Selecting monotonic merge-join on equi-pair %d=%d (merge=%.2f, hash=%.2f, nl=%.2f)', driving[0].leftAttrId, driving[0].rightAttrId, mergeC, hashC, nlC);
111
+ return new MergeJoinNode(node.scope, node.left, node.right, joinType, driving, residual, node.getAttributes().slice());
112
+ }
113
+ //# sourceMappingURL=rule-monotonic-merge-join.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-monotonic-merge-join.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-monotonic-merge-join.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Rule: Aggregate Predicate Pushdown
3
+ *
4
+ * Subsumes WHERE-on-group-by-column and HAVING-on-group-by-column. For a
5
+ * FilterNode(predicate, AggregateNode|StreamAggregateNode|HashAggregateNode)
6
+ * each conjunct of `predicate` that references only GROUP-BY columns (or
7
+ * columns FD-determined by them in the aggregate's output FDs) is rewritten
8
+ * onto the aggregate's source attribute IDs and moved below the aggregate.
9
+ * Conjuncts referencing aggregate outputs (sum/count/etc.) or non-column
10
+ * GROUP-BY expressions stay above.
11
+ *
12
+ * Aggregate output indices in `physical.fds` come exclusively from
13
+ * bare-`ColumnReferenceNode` GROUP BYs (per `propagateAggregateFds`), so every
14
+ * output column in the FD closure has a known source attribute and can be
15
+ * rewritten.
16
+ */
17
+ import type { PlanNode } from '../../nodes/plan-node.js';
18
+ import type { OptContext } from '../../framework/context.js';
19
+ export declare function ruleAggregatePredicatePushdown(node: PlanNode, _context: OptContext): PlanNode | null;
20
+ //# sourceMappingURL=rule-aggregate-predicate-pushdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-aggregate-predicate-pushdown.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-aggregate-predicate-pushdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAiD,MAAM,0BAA0B,CAAC;AAExG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAqB7D,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CA8EpG"}
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Rule: Aggregate Predicate Pushdown
3
+ *
4
+ * Subsumes WHERE-on-group-by-column and HAVING-on-group-by-column. For a
5
+ * FilterNode(predicate, AggregateNode|StreamAggregateNode|HashAggregateNode)
6
+ * each conjunct of `predicate` that references only GROUP-BY columns (or
7
+ * columns FD-determined by them in the aggregate's output FDs) is rewritten
8
+ * onto the aggregate's source attribute IDs and moved below the aggregate.
9
+ * Conjuncts referencing aggregate outputs (sum/count/etc.) or non-column
10
+ * GROUP-BY expressions stay above.
11
+ *
12
+ * Aggregate output indices in `physical.fds` come exclusively from
13
+ * bare-`ColumnReferenceNode` GROUP BYs (per `propagateAggregateFds`), so every
14
+ * output column in the FD closure has a known source attribute and can be
15
+ * rewritten.
16
+ */
17
+ import { createLogger } from '../../../common/logger.js';
18
+ import { isRelationalNode } from '../../nodes/plan-node.js';
19
+ import { PlanNodeType } from '../../nodes/plan-node-type.js';
20
+ import { FilterNode } from '../../nodes/filter.js';
21
+ import { AggregateNode } from '../../nodes/aggregate-node.js';
22
+ import { StreamAggregateNode } from '../../nodes/stream-aggregate.js';
23
+ import { HashAggregateNode } from '../../nodes/hash-aggregate.js';
24
+ import { ColumnReferenceNode } from '../../nodes/reference.js';
25
+ import { normalizePredicate } from '../../analysis/predicate-normalizer.js';
26
+ import { splitConjuncts, combineConjuncts } from '../../analysis/predicate-conjuncts.js';
27
+ import { computeClosure } from '../../util/fd-utils.js';
28
+ const log = createLogger('optimizer:rule:aggregate-predicate-pushdown');
29
+ function isAggregateNode(node) {
30
+ return node instanceof AggregateNode
31
+ || node instanceof StreamAggregateNode
32
+ || node instanceof HashAggregateNode;
33
+ }
34
+ export function ruleAggregatePredicatePushdown(node, _context) {
35
+ if (node.nodeType !== PlanNodeType.Filter)
36
+ return null;
37
+ const filter = node;
38
+ if (!isAggregateNode(filter.source))
39
+ return null;
40
+ const agg = filter.source;
41
+ // Scalar aggregate (no GROUP BY): the predicate selects on the single output
42
+ // row, so nothing is pushable.
43
+ if (agg.groupBy.length === 0)
44
+ return null;
45
+ const aggAttrs = agg.getAttributes();
46
+ const sourceAttrs = agg.source.getAttributes();
47
+ // Build the output → source mapping for bare-column GROUP BYs. Aggregate
48
+ // output columns (indices ≥ groupCount) have no source mapping. Non-column
49
+ // GROUP BY expressions (`group_${i}`) also have no source mapping.
50
+ const outputToSource = new Map();
51
+ const groupByOutputIndices = new Set();
52
+ for (let i = 0; i < agg.groupBy.length; i++) {
53
+ const gbExpr = agg.groupBy[i];
54
+ if (!(gbExpr instanceof ColumnReferenceNode))
55
+ continue;
56
+ const outAttrId = aggAttrs[i].id;
57
+ const srcAttrId = gbExpr.attributeId;
58
+ const srcIdx = sourceAttrs.findIndex(a => a.id === srcAttrId);
59
+ if (srcIdx < 0)
60
+ continue;
61
+ outputToSource.set(outAttrId, { sourceAttrId: srcAttrId, sourceColIdx: srcIdx });
62
+ groupByOutputIndices.add(i);
63
+ }
64
+ if (outputToSource.size === 0)
65
+ return null;
66
+ // Map output attribute id → output column index, used to test FD closure
67
+ // membership.
68
+ const outAttrIdToIndex = new Map();
69
+ aggAttrs.forEach((a, i) => outAttrIdToIndex.set(a.id, i));
70
+ // FD closure on the aggregate's output indices, seeded by the bare-column
71
+ // GROUP BY output indices. With composite GROUP BYs and inherited source
72
+ // FDs, this can widen `outputToSource` membership to FD-dependent columns
73
+ // (which by `propagateAggregateFds`'s projection are themselves bare-column
74
+ // GROUP BY outputs and therefore already in `outputToSource`).
75
+ const aggFds = agg.physical.fds ?? [];
76
+ const pushableOutputIndices = computeClosure(groupByOutputIndices, aggFds);
77
+ // Normalize → split → partition conjuncts.
78
+ const normalized = normalizePredicate(filter.predicate);
79
+ const conjuncts = splitConjuncts(normalized);
80
+ const pushable = [];
81
+ const remaining = [];
82
+ for (const conj of conjuncts) {
83
+ if (isConjunctPushable(conj, outAttrIdToIndex, outputToSource, pushableOutputIndices)) {
84
+ pushable.push(conj);
85
+ }
86
+ else {
87
+ remaining.push(conj);
88
+ }
89
+ }
90
+ if (pushable.length === 0)
91
+ return null;
92
+ // Rewrite pushable conjuncts: rebind output column refs to source ones.
93
+ const rewrittenPushable = pushable.map(c => rewriteOutputToSource(c, outputToSource, sourceAttrs));
94
+ const pushedPredicate = combineConjuncts(rewrittenPushable);
95
+ const newSource = new FilterNode(agg.source.scope, agg.source, pushedPredicate);
96
+ // Rebuild the aggregate over the filtered source, preserving attribute IDs.
97
+ const newAgg = rebuildAggregate(agg, newSource);
98
+ log('Pushed %d/%d conjunct(s) below %s', pushable.length, conjuncts.length, agg.nodeType);
99
+ if (remaining.length === 0) {
100
+ return newAgg;
101
+ }
102
+ const residualPredicate = combineConjuncts(remaining);
103
+ return new FilterNode(filter.scope, newAgg, residualPredicate);
104
+ }
105
+ function isConjunctPushable(conj, outAttrIdToIndex, outputToSource, pushableOutputIndices) {
106
+ const referenced = collectReferencedAttributeIds(conj);
107
+ if (referenced.size === 0) {
108
+ // Constant conjunct: safe to push (and safe to keep above too — pushing
109
+ // reduces work below). Keep above to avoid spurious rule firings; the
110
+ // rule only "fires" when there's a real column-driven push.
111
+ return false;
112
+ }
113
+ for (const attrId of referenced) {
114
+ const idx = outAttrIdToIndex.get(attrId);
115
+ if (idx === undefined)
116
+ return false;
117
+ if (!pushableOutputIndices.has(idx))
118
+ return false;
119
+ // Every pushable index must have a source mapping for rewrite.
120
+ if (!outputToSource.has(attrId))
121
+ return false;
122
+ }
123
+ return true;
124
+ }
125
+ function collectReferencedAttributeIds(expr) {
126
+ const ids = new Set();
127
+ walkScalar(expr, n => {
128
+ if (n instanceof ColumnReferenceNode) {
129
+ ids.add(n.attributeId);
130
+ }
131
+ });
132
+ return ids;
133
+ }
134
+ function walkScalar(expr, fn) {
135
+ fn(expr);
136
+ for (const c of expr.getChildren()) {
137
+ if (!isRelationalNode(c)) {
138
+ walkScalar(c, fn);
139
+ }
140
+ }
141
+ }
142
+ function rewriteOutputToSource(expr, outputToSource, sourceAttrs) {
143
+ if (expr instanceof ColumnReferenceNode) {
144
+ const mapping = outputToSource.get(expr.attributeId);
145
+ if (mapping === undefined)
146
+ return expr;
147
+ const srcAttr = sourceAttrs.find(a => a.id === mapping.sourceAttrId);
148
+ // `sourceAttrs` was indexed against to build `outputToSource`; the lookup must hit.
149
+ if (!srcAttr)
150
+ return expr;
151
+ return new ColumnReferenceNode(expr.scope, expr.expression, srcAttr.type, mapping.sourceAttrId, mapping.sourceColIdx);
152
+ }
153
+ const children = expr.getChildren();
154
+ if (children.length === 0)
155
+ return expr;
156
+ const newChildren = [];
157
+ let changed = false;
158
+ for (const c of children) {
159
+ if (isRelationalNode(c)) {
160
+ newChildren.push(c);
161
+ continue;
162
+ }
163
+ const replaced = rewriteOutputToSource(c, outputToSource, sourceAttrs);
164
+ newChildren.push(replaced);
165
+ if (replaced !== c)
166
+ changed = true;
167
+ }
168
+ if (!changed)
169
+ return expr;
170
+ return expr.withChildren(newChildren);
171
+ }
172
+ function rebuildAggregate(agg, newSource) {
173
+ if (agg instanceof AggregateNode) {
174
+ return new AggregateNode(agg.scope, newSource, agg.groupBy, agg.aggregates, undefined, agg.getAttributes());
175
+ }
176
+ if (agg instanceof StreamAggregateNode) {
177
+ return new StreamAggregateNode(agg.scope, newSource, agg.groupBy, agg.aggregates, undefined, agg.getAttributes());
178
+ }
179
+ return new HashAggregateNode(agg.scope, newSource, agg.groupBy, agg.aggregates, undefined, agg.getAttributes());
180
+ }
181
+ //# sourceMappingURL=rule-aggregate-predicate-pushdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-aggregate-predicate-pushdown.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-aggregate-predicate-pushdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Rule: Empty-Relation Folding
3
+ *
4
+ * Const-fold pass that recognizes provably-empty subtrees and replaces them
5
+ * with `EmptyRelationNode`, preserving attribute IDs and `RelationType` shape
6
+ * so consumers above the rewrite keep working.
7
+ *
8
+ * Recognized shapes (E = EmptyRelationNode):
9
+ * - Filter(x, lit-false / lit-null / lit-0) → E with x's schema
10
+ * - Filter(E, _) → E (pass-through)
11
+ * - Project(E, projections) → E with project's schema
12
+ * - Sort(E, _) / LimitOffset(E, _) / Distinct(E) → E (schema unchanged)
13
+ * - Join(E, R, inner|cross|semi) → E with join's schema
14
+ * - Join(L, E, inner|cross|semi) → E with join's schema
15
+ * - Join(E, R, left) → E (empty driving side)
16
+ * - Join(L, E, right) → E (symmetric)
17
+ * - Join(E, _, anti) → E (anti drives from left)
18
+ * - Join(E, E, full) → E (both sides empty)
19
+ *
20
+ * Deliberately NOT folded (sound reasons):
21
+ * - Join(L, E, left) — returns L null-padded on right
22
+ * - Join(E, R, right) — symmetric
23
+ * - Join(L, E, anti) — anti with empty right returns all of L
24
+ * - Single-side-empty FULL — still emits null-padded rows for non-empty side
25
+ *
26
+ * Runs in the Structural pass (TopDown) after the IND rules. Cascade is
27
+ * bounded: rules chain within a single node visit via the per-node fixed-
28
+ * point loop in `applyPassRules`, but the Structural pass itself is one
29
+ * top-down traversal — a parent already visited won't re-fire when an inner
30
+ * Filter folds. See "Cascade limits" in `docs/optimizer.md`.
31
+ */
32
+ import type { PlanNode } from '../../nodes/plan-node.js';
33
+ import type { OptContext } from '../../framework/context.js';
34
+ /**
35
+ * WHERE-clause truthiness: `false`, `null`, `0`, `0n` all reject every row.
36
+ * Conservatively cover only the canonical "no rows" literals. Other coercions
37
+ * (e.g. empty string, 0.0) are left out; if needed, expand here.
38
+ */
39
+ export declare function isLiteralFalsy(node: PlanNode): boolean;
40
+ export declare function ruleFilterFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
41
+ export declare function ruleProjectFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
42
+ export declare function ruleSortFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
43
+ export declare function ruleLimitOffsetFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
44
+ export declare function ruleDistinctFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
45
+ export declare function ruleJoinFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
46
+ //# sourceMappingURL=rule-empty-relation-folding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-empty-relation-folding.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-empty-relation-folding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AA2B7D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAItD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAWrF;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAKtF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAKnF;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAK1F;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAKvF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAwCnF"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Rule: Empty-Relation Folding
3
+ *
4
+ * Const-fold pass that recognizes provably-empty subtrees and replaces them
5
+ * with `EmptyRelationNode`, preserving attribute IDs and `RelationType` shape
6
+ * so consumers above the rewrite keep working.
7
+ *
8
+ * Recognized shapes (E = EmptyRelationNode):
9
+ * - Filter(x, lit-false / lit-null / lit-0) → E with x's schema
10
+ * - Filter(E, _) → E (pass-through)
11
+ * - Project(E, projections) → E with project's schema
12
+ * - Sort(E, _) / LimitOffset(E, _) / Distinct(E) → E (schema unchanged)
13
+ * - Join(E, R, inner|cross|semi) → E with join's schema
14
+ * - Join(L, E, inner|cross|semi) → E with join's schema
15
+ * - Join(E, R, left) → E (empty driving side)
16
+ * - Join(L, E, right) → E (symmetric)
17
+ * - Join(E, _, anti) → E (anti drives from left)
18
+ * - Join(E, E, full) → E (both sides empty)
19
+ *
20
+ * Deliberately NOT folded (sound reasons):
21
+ * - Join(L, E, left) — returns L null-padded on right
22
+ * - Join(E, R, right) — symmetric
23
+ * - Join(L, E, anti) — anti with empty right returns all of L
24
+ * - Single-side-empty FULL — still emits null-padded rows for non-empty side
25
+ *
26
+ * Runs in the Structural pass (TopDown) after the IND rules. Cascade is
27
+ * bounded: rules chain within a single node visit via the per-node fixed-
28
+ * point loop in `applyPassRules`, but the Structural pass itself is one
29
+ * top-down traversal — a parent already visited won't re-fire when an inner
30
+ * Filter folds. See "Cascade limits" in `docs/optimizer.md`.
31
+ */
32
+ import { createLogger } from '../../../common/logger.js';
33
+ import { FilterNode } from '../../nodes/filter.js';
34
+ import { ProjectNode } from '../../nodes/project-node.js';
35
+ import { SortNode } from '../../nodes/sort.js';
36
+ import { LimitOffsetNode } from '../../nodes/limit-offset.js';
37
+ import { DistinctNode } from '../../nodes/distinct-node.js';
38
+ import { JoinNode } from '../../nodes/join-node.js';
39
+ import { AliasNode } from '../../nodes/alias-node.js';
40
+ import { LiteralNode } from '../../nodes/scalar.js';
41
+ import { EmptyRelationNode } from '../../nodes/empty-relation-node.js';
42
+ const log = createLogger('optimizer:rule:empty-relation-folding');
43
+ /**
44
+ * Detects EmptyRelation, including the common case where it sits beneath one
45
+ * or more attribute-renaming wrappers (Alias) introduced by FROM-clause
46
+ * subquery aliases. Looking through Alias is sound here because the *host*
47
+ * fold (Join, Project, etc.) produces an EmptyRelation carrying the host's
48
+ * own attributes — the wrapped Alias's rename is discarded along with the
49
+ * Alias itself.
50
+ */
51
+ function isEmpty(node) {
52
+ if (node instanceof EmptyRelationNode)
53
+ return true;
54
+ if (node instanceof AliasNode)
55
+ return isEmpty(node.source);
56
+ return false;
57
+ }
58
+ /**
59
+ * WHERE-clause truthiness: `false`, `null`, `0`, `0n` all reject every row.
60
+ * Conservatively cover only the canonical "no rows" literals. Other coercions
61
+ * (e.g. empty string, 0.0) are left out; if needed, expand here.
62
+ */
63
+ export function isLiteralFalsy(node) {
64
+ if (!(node instanceof LiteralNode))
65
+ return false;
66
+ const v = node.expression.value;
67
+ return v === false || v === null || v === 0 || v === 0n;
68
+ }
69
+ export function ruleFilterFoldEmpty(node, _ctx) {
70
+ if (!(node instanceof FilterNode))
71
+ return null;
72
+ if (isEmpty(node.source)) {
73
+ log('Filter(Empty, _) → Empty');
74
+ return node.source;
75
+ }
76
+ if (isLiteralFalsy(node.predicate)) {
77
+ log('Filter(x, lit-false) → Empty');
78
+ return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
79
+ }
80
+ return null;
81
+ }
82
+ export function ruleProjectFoldEmpty(node, _ctx) {
83
+ if (!(node instanceof ProjectNode))
84
+ return null;
85
+ if (!isEmpty(node.source))
86
+ return null;
87
+ log('Project(Empty, _) → Empty');
88
+ return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
89
+ }
90
+ export function ruleSortFoldEmpty(node, _ctx) {
91
+ if (!(node instanceof SortNode))
92
+ return null;
93
+ if (!isEmpty(node.source))
94
+ return null;
95
+ log('Sort(Empty, _) → Empty');
96
+ return node.source;
97
+ }
98
+ export function ruleLimitOffsetFoldEmpty(node, _ctx) {
99
+ if (!(node instanceof LimitOffsetNode))
100
+ return null;
101
+ if (!isEmpty(node.source))
102
+ return null;
103
+ log('LimitOffset(Empty, _) → Empty');
104
+ return node.source;
105
+ }
106
+ export function ruleDistinctFoldEmpty(node, _ctx) {
107
+ if (!(node instanceof DistinctNode))
108
+ return null;
109
+ if (!isEmpty(node.source))
110
+ return null;
111
+ log('Distinct(Empty) → Empty');
112
+ return node.source;
113
+ }
114
+ export function ruleJoinFoldEmpty(node, _ctx) {
115
+ if (!(node instanceof JoinNode))
116
+ return null;
117
+ const leftEmpty = isEmpty(node.left);
118
+ const rightEmpty = isEmpty(node.right);
119
+ if (!leftEmpty && !rightEmpty)
120
+ return null;
121
+ let fold = false;
122
+ switch (node.joinType) {
123
+ case 'inner':
124
+ case 'cross':
125
+ fold = leftEmpty || rightEmpty;
126
+ break;
127
+ case 'left':
128
+ // LEFT JOIN: empty left → empty output. Empty right → keep (null-pad L).
129
+ fold = leftEmpty;
130
+ break;
131
+ case 'right':
132
+ // RIGHT JOIN: empty right → empty output. Empty left → keep (null-pad R).
133
+ fold = rightEmpty;
134
+ break;
135
+ case 'full':
136
+ // FULL JOIN: only fold when BOTH sides empty; one empty side still
137
+ // emits null-padded rows from the non-empty side.
138
+ fold = leftEmpty && rightEmpty;
139
+ break;
140
+ case 'semi':
141
+ // SEMI JOIN: empty L → empty. Empty R → empty (no matches possible).
142
+ fold = leftEmpty || rightEmpty;
143
+ break;
144
+ case 'anti':
145
+ // ANTI JOIN: empty L → empty. Empty R → all of L (do NOT fold).
146
+ fold = leftEmpty;
147
+ break;
148
+ default:
149
+ return null;
150
+ }
151
+ if (!fold)
152
+ return null;
153
+ log('Join(%s) with empty side(s) → Empty', node.joinType);
154
+ return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
155
+ }
156
+ //# sourceMappingURL=rule-empty-relation-folding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-empty-relation-folding.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-empty-relation-folding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Rule: Filter Predicate Contradiction
3
+ *
4
+ * Folds Filter nodes whose conjuncts together with the source's
5
+ * `domainConstraints` and literal `constantBindings` are provably
6
+ * unsatisfiable. The empty result is materialized as `EmptyRelationNode`
7
+ * carrying the Filter's own attribute IDs / RelationType, so the const-fold
8
+ * cascade (Project / Sort / LimitOffset / Distinct / inner-or-cross-or-semi
9
+ * Join) can drop the parent subtree.
10
+ *
11
+ * Scope (see `analysis/sat-checker.ts`):
12
+ * - Single-column comparisons against literals (= / != / < / <= / > / >=).
13
+ * - Single-column BETWEEN literal AND literal.
14
+ * - Single-column IN (lit, lit, ...) and intersection across IN-lists.
15
+ * - Domain-vs-predicate intersection.
16
+ *
17
+ * Out of scope (treated as `unknown`, never folded):
18
+ * - OR / CASE branch analysis, cross-column arithmetic, LIKE, IS NULL,
19
+ * user-function reasoning. The sat-checker tracks an `unknown` flag
20
+ * per column so an in-scope contradiction on column `a` still fires
21
+ * even if an unrelated LIKE on column `b` is present.
22
+ *
23
+ * Registered at Structural pass priority 27 — runs alongside the empty-
24
+ * relation-folding rules so any `Filter(_, false)` produced by other rules
25
+ * has already been collapsed.
26
+ */
27
+ import type { PlanNode } from '../../nodes/plan-node.js';
28
+ import type { OptContext } from '../../framework/context.js';
29
+ export declare function ruleFilterContradiction(node: PlanNode, _ctx: OptContext): PlanNode | null;
30
+ //# sourceMappingURL=rule-filter-contradiction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-filter-contradiction.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-filter-contradiction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAS7D,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAoCzF"}