@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,60 @@
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 { createLogger } from '../../../common/logger.js';
28
+ import { FilterNode } from '../../nodes/filter.js';
29
+ import { EmptyRelationNode } from '../../nodes/empty-relation-node.js';
30
+ import { splitConjuncts } from '../../analysis/predicate-conjuncts.js';
31
+ import { checkSatisfiability } from '../../analysis/sat-checker.js';
32
+ import { isLiteralFalsy } from './rule-empty-relation-folding.js';
33
+ const log = createLogger('optimizer:rule:filter-contradiction');
34
+ export function ruleFilterContradiction(node, _ctx) {
35
+ if (!(node instanceof FilterNode))
36
+ return null;
37
+ // `Filter(_, lit-false|null|0|0n)` is the empty-folding rule's job; bail out
38
+ // so this rule doesn't dispatch to the sat-checker for predicates the
39
+ // sibling rule will collapse anyway.
40
+ if (isLiteralFalsy(node.predicate)) {
41
+ return null;
42
+ }
43
+ const sourcePhysical = node.source.physical;
44
+ const domains = sourcePhysical.domainConstraints ?? [];
45
+ const bindings = sourcePhysical.constantBindings ?? [];
46
+ const conjuncts = splitConjuncts(node.predicate);
47
+ const sourceAttrs = node.source.getAttributes();
48
+ const attrIdToIndex = new Map();
49
+ sourceAttrs.forEach((a, i) => attrIdToIndex.set(a.id, i));
50
+ const collationOf = (col) => {
51
+ const attr = sourceAttrs[col];
52
+ return attr?.type.collationName;
53
+ };
54
+ const result = checkSatisfiability(conjuncts, domains, bindings, (attrId) => attrIdToIndex.get(attrId), collationOf);
55
+ if (result !== 'unsat')
56
+ return null;
57
+ log('Filter predicate provably unsatisfiable → Empty');
58
+ return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
59
+ }
60
+ //# sourceMappingURL=rule-filter-contradiction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-filter-contradiction.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-filter-contradiction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,GAAG,GAAG,YAAY,CAAC,qCAAqC,CAAC,CAAC;AAEhE,MAAM,UAAU,uBAAuB,CAAC,IAAc,EAAE,IAAgB;IACvE,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/C,6EAA6E;IAC7E,sEAAsE;IACtE,qCAAqC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,cAAc,CAAC,gBAAgB,IAAI,EAAE,CAAC;IACvD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IAChD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAE1D,MAAM,WAAW,GAAG,CAAC,GAAW,EAAsB,EAAE;QACvD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,mBAAmB,CACjC,SAAS,EACT,OAAO,EACP,QAAQ,EACR,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EACrC,WAAW,CACX,CAAC;IAEF,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAEpC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IACvD,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Rule: Predicate Inference (Equivalence-Class driven)
3
+ *
4
+ * Materializes inferred equality predicates derived from combining
5
+ * (predicate-derived) constant bindings with (source-derived) equivalence
6
+ * classes. When `t.k = u.k` is known via a join's equi-pair and `t.k = V`
7
+ * is asserted in the filter, the rule emits `u.k = V` so the predicate is
8
+ * visible to vtab access plans on the `u` side independently.
9
+ *
10
+ * Simple form (always run):
11
+ * Filter(predicate, source)
12
+ * - Extract `predBindings` from the predicate (col-index → constant value).
13
+ * - Cross with `source.physical.equivClasses`: for every EC member of a
14
+ * bound column that is not itself bound by the predicate, emit a new
15
+ * `col = value` conjunct.
16
+ * - AND the new conjuncts into the filter predicate.
17
+ *
18
+ * Powerful form (additional when source is an inner/cross JoinNode):
19
+ * - Split the newly-inferred conjuncts by which side of the join their
20
+ * columns reference. For each single-side conjunct, inject a FilterNode
21
+ * wrapping that side of the join, re-keyed onto the branch's local
22
+ * column indices.
23
+ * - The outer FilterNode still carries the augmented predicate; the
24
+ * branch filter is what subsequent predicate-pushdown can carry into
25
+ * the leaf's Retrieve pipeline.
26
+ *
27
+ * Fixpoint guard: the rule's emission set is `{otherIdx ∈ EC | otherIdx
28
+ * is not already in predBoundIdx}`. On a second invocation the
29
+ * inferred conjuncts have themselves contributed bindings, so every EC
30
+ * member is in `predBoundIdx` and the rule yields nothing. The registry's
31
+ * per-node `markRuleApplied` is a belt-and-suspenders second guard.
32
+ *
33
+ * Safety:
34
+ * - LEFT/RIGHT/FULL joins: per `propagateJoinFds`, NULL-padded sides drop
35
+ * their bindings/ECs, so the EC visible at the filter's source is
36
+ * restricted to the preserved side. The rule additionally refuses
37
+ * branch injection on these join types (outer filter only).
38
+ * - SEMI/ANTI: only the left side is in the output; no right inference
39
+ * can arise here. Treat as LEFT for branch injection.
40
+ *
41
+ * See ticket `3-rule-predicate-inference-equivalence` for the full design.
42
+ */
43
+ import type { OptContext as _OptContext } from '../../framework/context.js';
44
+ export declare function rulePredicateInferenceEquivalence(node: import('../../nodes/plan-node.js').PlanNode, _context: _OptContext): import('../../nodes/plan-node.js').PlanNode | null;
45
+ //# sourceMappingURL=rule-predicate-inference-equivalence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-predicate-inference-equivalence.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-inference-equivalence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,OAAO,KAAK,EAAE,UAAU,IAAI,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAoB5E,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,OAAO,0BAA0B,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,0BAA0B,EAAE,QAAQ,GAAG,IAAI,CA2D9K"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Rule: Predicate Inference (Equivalence-Class driven)
3
+ *
4
+ * Materializes inferred equality predicates derived from combining
5
+ * (predicate-derived) constant bindings with (source-derived) equivalence
6
+ * classes. When `t.k = u.k` is known via a join's equi-pair and `t.k = V`
7
+ * is asserted in the filter, the rule emits `u.k = V` so the predicate is
8
+ * visible to vtab access plans on the `u` side independently.
9
+ *
10
+ * Simple form (always run):
11
+ * Filter(predicate, source)
12
+ * - Extract `predBindings` from the predicate (col-index → constant value).
13
+ * - Cross with `source.physical.equivClasses`: for every EC member of a
14
+ * bound column that is not itself bound by the predicate, emit a new
15
+ * `col = value` conjunct.
16
+ * - AND the new conjuncts into the filter predicate.
17
+ *
18
+ * Powerful form (additional when source is an inner/cross JoinNode):
19
+ * - Split the newly-inferred conjuncts by which side of the join their
20
+ * columns reference. For each single-side conjunct, inject a FilterNode
21
+ * wrapping that side of the join, re-keyed onto the branch's local
22
+ * column indices.
23
+ * - The outer FilterNode still carries the augmented predicate; the
24
+ * branch filter is what subsequent predicate-pushdown can carry into
25
+ * the leaf's Retrieve pipeline.
26
+ *
27
+ * Fixpoint guard: the rule's emission set is `{otherIdx ∈ EC | otherIdx
28
+ * is not already in predBoundIdx}`. On a second invocation the
29
+ * inferred conjuncts have themselves contributed bindings, so every EC
30
+ * member is in `predBoundIdx` and the rule yields nothing. The registry's
31
+ * per-node `markRuleApplied` is a belt-and-suspenders second guard.
32
+ *
33
+ * Safety:
34
+ * - LEFT/RIGHT/FULL joins: per `propagateJoinFds`, NULL-padded sides drop
35
+ * their bindings/ECs, so the EC visible at the filter's source is
36
+ * restricted to the preserved side. The rule additionally refuses
37
+ * branch injection on these join types (outer filter only).
38
+ * - SEMI/ANTI: only the left side is in the output; no right inference
39
+ * can arise here. Treat as LEFT for branch injection.
40
+ *
41
+ * See ticket `3-rule-predicate-inference-equivalence` for the full design.
42
+ */
43
+ import { createLogger } from '../../../common/logger.js';
44
+ import { FilterNode } from '../../nodes/filter.js';
45
+ import { JoinNode } from '../../nodes/join-node.js';
46
+ import { BinaryOpNode, LiteralNode } from '../../nodes/scalar.js';
47
+ import { ColumnReferenceNode, ParameterReferenceNode } from '../../nodes/reference.js';
48
+ import { extractEqualityFds } from '../../util/fd-utils.js';
49
+ const log = createLogger('optimizer:rule:predicate-inference-equivalence');
50
+ export function rulePredicateInferenceEquivalence(node, _context) {
51
+ if (!(node instanceof FilterNode))
52
+ return null;
53
+ const filter = node;
54
+ const source = filter.source;
55
+ const sourcePhys = source.physical;
56
+ const ecs = sourcePhys?.equivClasses;
57
+ if (!ecs || ecs.length === 0)
58
+ return null;
59
+ const sourceAttrs = source.getAttributes();
60
+ const attrIdToIndex = new Map();
61
+ sourceAttrs.forEach((a, i) => attrIdToIndex.set(a.id, i));
62
+ const { constantBindings: predBindings } = extractEqualityFds(filter.predicate, attrIdToIndex);
63
+ if (predBindings.length === 0)
64
+ return null;
65
+ // Columns the predicate itself directly pins. Used both to find which
66
+ // EC members already have a binding and as the fixpoint guard: once
67
+ // every EC member is in this set, the rule contributes nothing further.
68
+ const predBoundIdx = new Set();
69
+ for (const b of predBindings)
70
+ for (const c of b.attrs)
71
+ predBoundIdx.add(c);
72
+ const inferred = [];
73
+ const seen = new Set();
74
+ for (const binding of predBindings) {
75
+ for (const predIdx of binding.attrs) {
76
+ for (const cls of ecs) {
77
+ if (!cls.includes(predIdx))
78
+ continue;
79
+ for (const otherIdx of cls) {
80
+ if (otherIdx === predIdx)
81
+ continue;
82
+ if (predBoundIdx.has(otherIdx))
83
+ continue;
84
+ const key = `${otherIdx}|${valueSignature(binding.value)}`;
85
+ if (seen.has(key))
86
+ continue;
87
+ seen.add(key);
88
+ const attr = sourceAttrs[otherIdx];
89
+ if (!attr)
90
+ continue;
91
+ const conjunct = synthesizeEquality(filter.scope, attr, otherIdx, binding.value);
92
+ inferred.push({ sourceColIdx: otherIdx, value: binding.value, conjunct });
93
+ }
94
+ }
95
+ }
96
+ }
97
+ if (inferred.length === 0)
98
+ return null;
99
+ log('Inferring %d new equality conjunct(s) on Filter from EC × bindings', inferred.length);
100
+ // AND every inferred conjunct into the predicate.
101
+ let combinedPredicate = filter.predicate;
102
+ for (const inf of inferred) {
103
+ combinedPredicate = andTogether(filter.scope, combinedPredicate, inf.conjunct);
104
+ }
105
+ // Powerful form: branch injection below inner/cross joins.
106
+ let newSource = source;
107
+ if (source instanceof JoinNode) {
108
+ newSource = tryBranchInjection(source, inferred) ?? source;
109
+ }
110
+ return new FilterNode(filter.scope, newSource, combinedPredicate);
111
+ }
112
+ /**
113
+ * For an inner or cross JoinNode whose output bears `inferred` conjuncts,
114
+ * inject single-side conjuncts as FilterNode wrappers on the corresponding
115
+ * branch. Returns the rebuilt join, or null if no inferred conjunct lands
116
+ * on either branch.
117
+ */
118
+ function tryBranchInjection(join, inferred) {
119
+ // Only inner / cross are safe — see file-level "Safety" notes.
120
+ if (join.joinType !== 'inner' && join.joinType !== 'cross')
121
+ return null;
122
+ const leftAttrs = join.left.getAttributes();
123
+ const rightAttrs = join.right.getAttributes();
124
+ const leftCount = leftAttrs.length;
125
+ const leftBranchConjuncts = [];
126
+ const rightBranchConjuncts = [];
127
+ for (const inf of inferred) {
128
+ if (inf.sourceColIdx < leftCount) {
129
+ // Left-branch: attribute id is stable, so re-synthesize against the
130
+ // branch's local column index (which is `sourceColIdx` itself).
131
+ const attr = leftAttrs[inf.sourceColIdx];
132
+ if (!attr)
133
+ continue;
134
+ leftBranchConjuncts.push(synthesizeEquality(join.scope, attr, inf.sourceColIdx, inf.value));
135
+ }
136
+ else {
137
+ const rightIdx = inf.sourceColIdx - leftCount;
138
+ const attr = rightAttrs[rightIdx];
139
+ if (!attr)
140
+ continue;
141
+ rightBranchConjuncts.push(synthesizeEquality(join.scope, attr, rightIdx, inf.value));
142
+ }
143
+ }
144
+ if (leftBranchConjuncts.length === 0 && rightBranchConjuncts.length === 0)
145
+ return null;
146
+ let newLeft = join.left;
147
+ let newRight = join.right;
148
+ if (leftBranchConjuncts.length > 0) {
149
+ const leftPred = combineAnds(join.scope, leftBranchConjuncts);
150
+ newLeft = new FilterNode(join.left.scope, join.left, leftPred);
151
+ }
152
+ if (rightBranchConjuncts.length > 0) {
153
+ const rightPred = combineAnds(join.scope, rightBranchConjuncts);
154
+ newRight = new FilterNode(join.right.scope, join.right, rightPred);
155
+ }
156
+ log('Injecting %d left + %d right branch filter(s) below %s join', leftBranchConjuncts.length, rightBranchConjuncts.length, join.joinType);
157
+ return new JoinNode(join.scope, newLeft, newRight, join.joinType, join.condition, join.usingColumns);
158
+ }
159
+ function synthesizeEquality(scope, attr, columnIndex, value) {
160
+ const colExpr = attr.relationName
161
+ ? { type: 'column', name: attr.name, table: attr.relationName }
162
+ : { type: 'column', name: attr.name };
163
+ const colRef = new ColumnReferenceNode(scope, colExpr, attr.type, attr.id, columnIndex);
164
+ let valueNode;
165
+ if (value.kind === 'literal') {
166
+ const litExpr = { type: 'literal', value: value.value };
167
+ valueNode = new LiteralNode(scope, litExpr);
168
+ }
169
+ else {
170
+ const paramExpr = typeof value.paramRef === 'string'
171
+ ? { type: 'parameter', name: value.paramRef }
172
+ : { type: 'parameter', index: value.paramRef };
173
+ valueNode = new ParameterReferenceNode(scope, paramExpr, value.paramRef, attr.type);
174
+ }
175
+ const eqAst = {
176
+ type: 'binary',
177
+ operator: '=',
178
+ left: colRef.expression,
179
+ right: valueNode.expression,
180
+ };
181
+ return new BinaryOpNode(scope, eqAst, colRef, valueNode);
182
+ }
183
+ function andTogether(scope, left, right) {
184
+ const ast = {
185
+ type: 'binary',
186
+ operator: 'AND',
187
+ left: left.expression,
188
+ right: right.expression,
189
+ };
190
+ return new BinaryOpNode(scope, ast, left, right);
191
+ }
192
+ function combineAnds(scope, conjuncts) {
193
+ let acc = conjuncts[0];
194
+ for (let i = 1; i < conjuncts.length; i++) {
195
+ acc = andTogether(scope, acc, conjuncts[i]);
196
+ }
197
+ return acc;
198
+ }
199
+ function valueSignature(value) {
200
+ if (value.kind === 'literal') {
201
+ const v = value.value;
202
+ if (v === null)
203
+ return 'lit:null';
204
+ if (v instanceof Uint8Array)
205
+ return `lit:blob:${Array.from(v).join(',')}`;
206
+ return `lit:${typeof v}:${String(v)}`;
207
+ }
208
+ return `param:${value.paramRef}`;
209
+ }
210
+ //# sourceMappingURL=rule-predicate-inference-equivalence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-predicate-inference-equivalence.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-inference-equivalence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Rule: Sargable Range Rewrite
3
+ *
4
+ * For predicates of the form `f(col) = c` where `f` is a monotone-but-lossy
5
+ * bucket conversion (e.g. `date(datetime_col) = '2024-01-15'`), rewrite the
6
+ * conjunct to a half-open range on the underlying column:
7
+ *
8
+ * f(col) = c → col >= lower(c) AND col < upper(c)
9
+ *
10
+ * The half-open bounds come from `ScalarPlanNode.rangeRewriteIn(attrId, c)`,
11
+ * which delegates to `LogicalType.bucketBounds` on the column's logical type.
12
+ * The rewritten `col op literal` shape is what `analysis/constraint-extractor`
13
+ * already recognizes, so the resulting range can be pushed through
14
+ * `rule-predicate-pushdown` into the Retrieve pipeline and consumed by
15
+ * `rule-select-access-path` (IndexSeek, range scans, etc.).
16
+ *
17
+ * NULL semantics: a null constant is left alone (`f(col) = null` is already
18
+ * null, which WHERE / ON treat as false). A null column value satisfies neither
19
+ * `col >= L` nor `col < U` (both yield null), so row-rejection behavior
20
+ * matches the original predicate.
21
+ *
22
+ * Only the `=` shape is handled in this pass; `<`/`<=`/`>`/`>=` need direction
23
+ * analysis on `monotonicityIn` and asymmetric bound mapping — tracked
24
+ * separately in the optimization backlog.
25
+ */
26
+ import type { PlanNode } from '../../nodes/plan-node.js';
27
+ import type { OptContext } from '../../framework/context.js';
28
+ export declare function ruleSargableRangeRewrite(node: PlanNode, _context: OptContext): PlanNode | null;
29
+ //# sourceMappingURL=rule-sargable-range-rewrite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-sargable-range-rewrite.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-sargable-range-rewrite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAa7D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAuB9F"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Rule: Sargable Range Rewrite
3
+ *
4
+ * For predicates of the form `f(col) = c` where `f` is a monotone-but-lossy
5
+ * bucket conversion (e.g. `date(datetime_col) = '2024-01-15'`), rewrite the
6
+ * conjunct to a half-open range on the underlying column:
7
+ *
8
+ * f(col) = c → col >= lower(c) AND col < upper(c)
9
+ *
10
+ * The half-open bounds come from `ScalarPlanNode.rangeRewriteIn(attrId, c)`,
11
+ * which delegates to `LogicalType.bucketBounds` on the column's logical type.
12
+ * The rewritten `col op literal` shape is what `analysis/constraint-extractor`
13
+ * already recognizes, so the resulting range can be pushed through
14
+ * `rule-predicate-pushdown` into the Retrieve pipeline and consumed by
15
+ * `rule-select-access-path` (IndexSeek, range scans, etc.).
16
+ *
17
+ * NULL semantics: a null constant is left alone (`f(col) = null` is already
18
+ * null, which WHERE / ON treat as false). A null column value satisfies neither
19
+ * `col >= L` nor `col < U` (both yield null), so row-rejection behavior
20
+ * matches the original predicate.
21
+ *
22
+ * Only the `=` shape is handled in this pass; `<`/`<=`/`>`/`>=` need direction
23
+ * analysis on `monotonicityIn` and asymmetric bound mapping — tracked
24
+ * separately in the optimization backlog.
25
+ */
26
+ import { createLogger } from '../../../common/logger.js';
27
+ import { PlanNodeType } from '../../nodes/plan-node-type.js';
28
+ import { FilterNode } from '../../nodes/filter.js';
29
+ import { BinaryOpNode, LiteralNode } from '../../nodes/scalar.js';
30
+ import { ColumnReferenceNode, ParameterReferenceNode } from '../../nodes/reference.js';
31
+ import { splitConjuncts, combineConjuncts } from '../../analysis/predicate-conjuncts.js';
32
+ import { getSyncLiteral } from '../../../parser/utils.js';
33
+ const log = createLogger('optimizer:rule:sargable-range-rewrite');
34
+ export function ruleSargableRangeRewrite(node, _context) {
35
+ if (node.nodeType !== PlanNodeType.Filter)
36
+ return null;
37
+ const filter = node;
38
+ const conjuncts = splitConjuncts(filter.predicate);
39
+ let rewrittenCount = 0;
40
+ const out = [];
41
+ for (const c of conjuncts) {
42
+ const rewritten = tryRewriteEqualityToRange(c);
43
+ if (rewritten) {
44
+ out.push(rewritten);
45
+ rewrittenCount++;
46
+ }
47
+ else {
48
+ out.push(c);
49
+ }
50
+ }
51
+ if (rewrittenCount === 0)
52
+ return null;
53
+ const combined = combineConjuncts(out);
54
+ if (!combined)
55
+ return null;
56
+ log('Rewrote %d sargable bucket-equality conjunct(s)', rewrittenCount);
57
+ return new FilterNode(filter.scope, filter.source, combined);
58
+ }
59
+ /**
60
+ * Recognize a `f(col) = const` conjunct and lift it to a half-open range on
61
+ * `col`. Returns the rewritten AND-tree on success, or `undefined` when the
62
+ * conjunct is not in the recognized shape / the function declines the rewrite.
63
+ */
64
+ function tryRewriteEqualityToRange(expr) {
65
+ if (expr.nodeType !== PlanNodeType.BinaryOp)
66
+ return undefined;
67
+ const bin = expr;
68
+ if (bin.expression.operator !== '=')
69
+ return undefined;
70
+ // Exactly one side must be a literal constant; the other is the candidate
71
+ // function-shaped expression.
72
+ const leftLit = isLiteralConstant(bin.left);
73
+ const rightLit = isLiteralConstant(bin.right);
74
+ if (leftLit === rightLit)
75
+ return undefined; // both or neither
76
+ const literalSide = leftLit ? bin.left : bin.right;
77
+ const candidateSide = leftLit ? bin.right : bin.left;
78
+ const literalValue = getLiteralValue(literalSide);
79
+ if (literalValue === null)
80
+ return undefined;
81
+ // The candidate must depend on exactly one column attribute. Other leaves
82
+ // (literals / parameters) are fine — `rangeRewriteIn` itself enforces that
83
+ // the operand at the trait index is a bare ColumnReferenceNode.
84
+ const colRef = findUniqueColumnReference(candidateSide);
85
+ if (!colRef)
86
+ return undefined;
87
+ const bounds = candidateSide.rangeRewriteIn(colRef.attributeId, literalValue);
88
+ if (!bounds)
89
+ return undefined;
90
+ // Build `col >= L AND col < U` reusing the original ColumnReferenceNode (so
91
+ // the attribute id survives verbatim for downstream constraint extraction).
92
+ const scope = expr.scope;
93
+ const colType = colRef.getType();
94
+ const lower = makeComparison(scope, colRef, '>=', bounds.lowerInclusive, colType);
95
+ const upper = makeComparison(scope, colRef, '<', bounds.upperExclusive, colType);
96
+ const andAst = {
97
+ type: 'binary',
98
+ operator: 'AND',
99
+ left: lower.expression,
100
+ right: upper.expression,
101
+ };
102
+ return new BinaryOpNode(scope, andAst, lower, upper);
103
+ }
104
+ function makeComparison(scope, colRef, op, value, colType) {
105
+ const litExpr = { type: 'literal', value };
106
+ const literal = new LiteralNode(scope, litExpr, colType);
107
+ const ast = {
108
+ type: 'binary',
109
+ operator: op,
110
+ left: colRef.expression,
111
+ right: litExpr,
112
+ };
113
+ return new BinaryOpNode(scope, ast, colRef, literal);
114
+ }
115
+ /** Strip a planner-inserted CastNode wrapper. */
116
+ function unwrapCast(node) {
117
+ return node.nodeType === PlanNodeType.Cast ? node.operand : node;
118
+ }
119
+ function isLiteralConstant(node) {
120
+ return unwrapCast(node).nodeType === PlanNodeType.Literal;
121
+ }
122
+ function getLiteralValue(node) {
123
+ const lit = unwrapCast(node);
124
+ return getSyncLiteral(lit.expression);
125
+ }
126
+ /**
127
+ * Walk the subtree's leaves and return the single `ColumnReferenceNode` if
128
+ * exactly one is found and every other leaf is a literal or parameter; return
129
+ * undefined for zero, two, or any unrecognized leaf shape (subqueries,
130
+ * function-of-other-column, etc.).
131
+ */
132
+ function findUniqueColumnReference(node) {
133
+ let found;
134
+ let ok = true;
135
+ const visit = (n) => {
136
+ if (!ok)
137
+ return;
138
+ const children = n.getChildren();
139
+ if (children.length === 0) {
140
+ if (n instanceof ColumnReferenceNode) {
141
+ if (found && found !== n) {
142
+ ok = false;
143
+ return;
144
+ }
145
+ found = n;
146
+ return;
147
+ }
148
+ if (n instanceof LiteralNode || n instanceof ParameterReferenceNode) {
149
+ return;
150
+ }
151
+ ok = false;
152
+ return;
153
+ }
154
+ for (const c of children) {
155
+ visit(c);
156
+ }
157
+ };
158
+ visit(node);
159
+ return ok ? found : undefined;
160
+ }
161
+ //# sourceMappingURL=rule-sargable-range-rewrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-sargable-range-rewrite.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-sargable-range-rewrite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Rule: ORDER BY FD pruning
3
+ *
4
+ * Drops trailing ORDER BY keys that are functionally determined by the
5
+ * preceding bare-column keys under the source's FDs and equivalence classes.
6
+ *
7
+ * For a SortNode with ≥ 2 keys, walk the keys front-to-back maintaining
8
+ * `determined = closure({leading bare-column source-indices}, fds, ECs)`.
9
+ * Drop any trailing key whose expression is a bare `ColumnReferenceNode` and
10
+ * whose source-attribute index is already in `determined`. Direction and
11
+ * NULL placement on the dropped trailing key are irrelevant — once the
12
+ * preceding keys pin every value of that column to a single value per group,
13
+ * the trailing key cannot reorder anything.
14
+ *
15
+ * Sort-key matcher semantics: only bare `ColumnReferenceNode` keys
16
+ * participate in either direction of the reasoning. A non-bare-column key
17
+ * contributes nothing to `determined` (we can't prove what expression values
18
+ * "determine"), and a non-bare-column key cannot be dropped. The rule walks
19
+ * past non-bare keys treating them as opaque.
20
+ *
21
+ * Reasoning space: `fds`/`equivClasses` from `node.source.physical` are in
22
+ * source-attribute-INDEX space (positions in `source.getAttributes()`), NOT
23
+ * attribute IDs. The rule converts each sort-key's `ColumnReferenceNode.
24
+ * attributeId` to its source-attribute index before feeding `computeClosure`
25
+ * — mirroring how `SortNode.computePhysical` does its `leadIdx` lookup.
26
+ *
27
+ * Soundness: equality-class FDs from a `WHERE a = b` filter or a join key
28
+ * are sound here because every surviving row has equal values on the EC
29
+ * members, so the trailing key is a no-op tiebreaker.
30
+ *
31
+ * Ordering with other rules: this is a Structural-pass rule. It must run
32
+ * before `monotonic-limit-pushdown` (PostOptimization priority 8) so single-
33
+ * key reductions can enable the pushdown. That ordering is automatic since
34
+ * Structural runs before PostOptimization.
35
+ */
36
+ import type { PlanNode } from '../../nodes/plan-node.js';
37
+ import type { OptContext as _OptContext } from '../../framework/context.js';
38
+ export declare function ruleOrderByFdPruning(node: PlanNode, _context: _OptContext): PlanNode | null;
39
+ //# sourceMappingURL=rule-orderby-fd-pruning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-orderby-fd-pruning.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/sort/rule-orderby-fd-pruning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,IAAI,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAO5E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAmD3F"}