@quereus/quereus 2.9.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) 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/func/builtins/conversion.d.ts.map +1 -1
  27. package/dist/src/func/builtins/conversion.js +12 -1
  28. package/dist/src/func/builtins/conversion.js.map +1 -1
  29. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  30. package/dist/src/func/builtins/explain.js +22 -8
  31. package/dist/src/func/builtins/explain.js.map +1 -1
  32. package/dist/src/func/builtins/generation.d.ts.map +1 -1
  33. package/dist/src/func/builtins/generation.js +26 -1
  34. package/dist/src/func/builtins/generation.js.map +1 -1
  35. package/dist/src/func/builtins/index.d.ts.map +1 -1
  36. package/dist/src/func/builtins/index.js +5 -1
  37. package/dist/src/func/builtins/index.js.map +1 -1
  38. package/dist/src/func/builtins/json-tvf.d.ts.map +1 -1
  39. package/dist/src/func/builtins/json-tvf.js +16 -2
  40. package/dist/src/func/builtins/json-tvf.js.map +1 -1
  41. package/dist/src/func/builtins/schema.d.ts +4 -0
  42. package/dist/src/func/builtins/schema.d.ts.map +1 -1
  43. package/dist/src/func/builtins/schema.js +270 -11
  44. package/dist/src/func/builtins/schema.js.map +1 -1
  45. package/dist/src/func/registration.d.ts +19 -1
  46. package/dist/src/func/registration.d.ts.map +1 -1
  47. package/dist/src/func/registration.js +8 -3
  48. package/dist/src/func/registration.js.map +1 -1
  49. package/dist/src/index.d.ts +7 -1
  50. package/dist/src/index.d.ts.map +1 -1
  51. package/dist/src/index.js +5 -0
  52. package/dist/src/index.js.map +1 -1
  53. package/dist/src/parser/parser.d.ts.map +1 -1
  54. package/dist/src/parser/parser.js +12 -4
  55. package/dist/src/parser/parser.js.map +1 -1
  56. package/dist/src/planner/analysis/assertion-classifier.d.ts +71 -0
  57. package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -0
  58. package/dist/src/planner/analysis/assertion-classifier.js +286 -0
  59. package/dist/src/planner/analysis/assertion-classifier.js.map +1 -0
  60. package/dist/src/planner/analysis/assertion-hoist-cache.d.ts +34 -0
  61. package/dist/src/planner/analysis/assertion-hoist-cache.d.ts.map +1 -0
  62. package/dist/src/planner/analysis/assertion-hoist-cache.js +119 -0
  63. package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -0
  64. package/dist/src/planner/analysis/binding-extractor.d.ts +58 -0
  65. package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -0
  66. package/dist/src/planner/analysis/binding-extractor.js +110 -0
  67. package/dist/src/planner/analysis/binding-extractor.js.map +1 -0
  68. package/dist/src/planner/analysis/change-scope.d.ts +184 -0
  69. package/dist/src/planner/analysis/change-scope.d.ts.map +1 -0
  70. package/dist/src/planner/analysis/change-scope.js +825 -0
  71. package/dist/src/planner/analysis/change-scope.js.map +1 -0
  72. package/dist/src/planner/analysis/check-extraction.d.ts +29 -0
  73. package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -0
  74. package/dist/src/planner/analysis/check-extraction.js +420 -0
  75. package/dist/src/planner/analysis/check-extraction.js.map +1 -0
  76. package/dist/src/planner/analysis/constraint-extractor.d.ts +47 -7
  77. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  78. package/dist/src/planner/analysis/constraint-extractor.js +186 -93
  79. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  80. package/dist/src/planner/analysis/partial-unique-extraction.d.ts +68 -0
  81. package/dist/src/planner/analysis/partial-unique-extraction.d.ts.map +1 -0
  82. package/dist/src/planner/analysis/partial-unique-extraction.js +347 -0
  83. package/dist/src/planner/analysis/partial-unique-extraction.js.map +1 -0
  84. package/dist/src/planner/analysis/predicate-conjuncts.d.ts +14 -0
  85. package/dist/src/planner/analysis/predicate-conjuncts.d.ts.map +1 -0
  86. package/dist/src/planner/analysis/predicate-conjuncts.js +31 -0
  87. package/dist/src/planner/analysis/predicate-conjuncts.js.map +1 -0
  88. package/dist/src/planner/analysis/predicate-shape.d.ts +52 -0
  89. package/dist/src/planner/analysis/predicate-shape.d.ts.map +1 -0
  90. package/dist/src/planner/analysis/predicate-shape.js +119 -0
  91. package/dist/src/planner/analysis/predicate-shape.js.map +1 -0
  92. package/dist/src/planner/analysis/sat-checker.d.ts +43 -0
  93. package/dist/src/planner/analysis/sat-checker.d.ts.map +1 -0
  94. package/dist/src/planner/analysis/sat-checker.js +393 -0
  95. package/dist/src/planner/analysis/sat-checker.js.map +1 -0
  96. package/dist/src/planner/building/table.d.ts.map +1 -1
  97. package/dist/src/planner/building/table.js +1 -1
  98. package/dist/src/planner/building/table.js.map +1 -1
  99. package/dist/src/planner/framework/characteristics.d.ts +10 -1
  100. package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
  101. package/dist/src/planner/framework/characteristics.js +24 -5
  102. package/dist/src/planner/framework/characteristics.js.map +1 -1
  103. package/dist/src/planner/framework/context.d.ts +1 -8
  104. package/dist/src/planner/framework/context.d.ts.map +1 -1
  105. package/dist/src/planner/framework/context.js +4 -21
  106. package/dist/src/planner/framework/context.js.map +1 -1
  107. package/dist/src/planner/framework/pass.d.ts +18 -2
  108. package/dist/src/planner/framework/pass.d.ts.map +1 -1
  109. package/dist/src/planner/framework/pass.js +145 -46
  110. package/dist/src/planner/framework/pass.js.map +1 -1
  111. package/dist/src/planner/framework/physical-utils.d.ts +0 -9
  112. package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
  113. package/dist/src/planner/framework/physical-utils.js +0 -31
  114. package/dist/src/planner/framework/physical-utils.js.map +1 -1
  115. package/dist/src/planner/nodes/aggregate-node.d.ts +25 -0
  116. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  117. package/dist/src/planner/nodes/aggregate-node.js +75 -8
  118. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  119. package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
  120. package/dist/src/planner/nodes/alias-node.js +6 -1
  121. package/dist/src/planner/nodes/alias-node.js.map +1 -1
  122. package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -1
  123. package/dist/src/planner/nodes/asof-scan-node.js +17 -3
  124. package/dist/src/planner/nodes/asof-scan-node.js.map +1 -1
  125. package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
  126. package/dist/src/planner/nodes/bloom-join-node.js +19 -9
  127. package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
  128. package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
  129. package/dist/src/planner/nodes/distinct-node.js +10 -6
  130. package/dist/src/planner/nodes/distinct-node.js.map +1 -1
  131. package/dist/src/planner/nodes/empty-relation-node.d.ts +27 -0
  132. package/dist/src/planner/nodes/empty-relation-node.d.ts.map +1 -0
  133. package/dist/src/planner/nodes/empty-relation-node.js +61 -0
  134. package/dist/src/planner/nodes/empty-relation-node.js.map +1 -0
  135. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  136. package/dist/src/planner/nodes/filter.js +65 -5
  137. package/dist/src/planner/nodes/filter.js.map +1 -1
  138. package/dist/src/planner/nodes/hash-aggregate.d.ts +1 -1
  139. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
  140. package/dist/src/planner/nodes/hash-aggregate.js +8 -6
  141. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
  142. package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
  143. package/dist/src/planner/nodes/join-node.js +12 -9
  144. package/dist/src/planner/nodes/join-node.js.map +1 -1
  145. package/dist/src/planner/nodes/join-utils.d.ts +24 -1
  146. package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
  147. package/dist/src/planner/nodes/join-utils.js +86 -0
  148. package/dist/src/planner/nodes/join-utils.js.map +1 -1
  149. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  150. package/dist/src/planner/nodes/limit-offset.js +6 -1
  151. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  152. package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
  153. package/dist/src/planner/nodes/merge-join-node.js +19 -9
  154. package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
  155. package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -1
  156. package/dist/src/planner/nodes/ordinal-slice-node.js +5 -2
  157. package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
  158. package/dist/src/planner/nodes/plan-node-type.d.ts +1 -0
  159. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  160. package/dist/src/planner/nodes/plan-node-type.js +1 -0
  161. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  162. package/dist/src/planner/nodes/plan-node.d.ts +186 -4
  163. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  164. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  165. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  166. package/dist/src/planner/nodes/project-node.js +75 -30
  167. package/dist/src/planner/nodes/project-node.js.map +1 -1
  168. package/dist/src/planner/nodes/reference.d.ts +24 -2
  169. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  170. package/dist/src/planner/nodes/reference.js +101 -1
  171. package/dist/src/planner/nodes/reference.js.map +1 -1
  172. package/dist/src/planner/nodes/retrieve-node.d.ts +9 -1
  173. package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
  174. package/dist/src/planner/nodes/retrieve-node.js +21 -0
  175. package/dist/src/planner/nodes/retrieve-node.js.map +1 -1
  176. package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
  177. package/dist/src/planner/nodes/returning-node.js +64 -28
  178. package/dist/src/planner/nodes/returning-node.js.map +1 -1
  179. package/dist/src/planner/nodes/scalar.d.ts +1 -0
  180. package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
  181. package/dist/src/planner/nodes/scalar.js +12 -0
  182. package/dist/src/planner/nodes/scalar.js.map +1 -1
  183. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  184. package/dist/src/planner/nodes/set-operation-node.js +15 -0
  185. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  186. package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
  187. package/dist/src/planner/nodes/single-row.js +3 -1
  188. package/dist/src/planner/nodes/single-row.js.map +1 -1
  189. package/dist/src/planner/nodes/sort.d.ts.map +1 -1
  190. package/dist/src/planner/nodes/sort.js +10 -3
  191. package/dist/src/planner/nodes/sort.js.map +1 -1
  192. package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -1
  193. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  194. package/dist/src/planner/nodes/stream-aggregate.js +8 -8
  195. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  196. package/dist/src/planner/nodes/table-access-nodes.d.ts +3 -3
  197. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  198. package/dist/src/planner/nodes/table-access-nodes.js +26 -8
  199. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  200. package/dist/src/planner/nodes/table-function-call.d.ts +4 -1
  201. package/dist/src/planner/nodes/table-function-call.d.ts.map +1 -1
  202. package/dist/src/planner/nodes/table-function-call.js +224 -14
  203. package/dist/src/planner/nodes/table-function-call.js.map +1 -1
  204. package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
  205. package/dist/src/planner/nodes/window-node.js +9 -2
  206. package/dist/src/planner/nodes/window-node.js.map +1 -1
  207. package/dist/src/planner/optimizer-tuning.d.ts +29 -1
  208. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
  209. package/dist/src/planner/optimizer-tuning.js +3 -0
  210. package/dist/src/planner/optimizer-tuning.js.map +1 -1
  211. package/dist/src/planner/optimizer.d.ts.map +1 -1
  212. package/dist/src/planner/optimizer.js +187 -0
  213. package/dist/src/planner/optimizer.js.map +1 -1
  214. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  215. package/dist/src/planner/rules/access/rule-select-access-path.js +22 -7
  216. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  217. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +30 -0
  218. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -0
  219. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +116 -0
  220. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -0
  221. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +7 -7
  222. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -1
  223. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +18 -16
  224. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
  225. package/dist/src/planner/rules/join/rule-join-elimination.d.ts +56 -0
  226. package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -0
  227. package/dist/src/planner/rules/join/rule-join-elimination.js +326 -0
  228. package/dist/src/planner/rules/join/rule-join-elimination.js.map +1 -0
  229. package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -1
  230. package/dist/src/planner/rules/join/rule-join-greedy-commute.js +10 -2
  231. package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
  232. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts +20 -0
  233. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts.map +1 -0
  234. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +181 -0
  235. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -0
  236. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts +46 -0
  237. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts.map +1 -0
  238. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +156 -0
  239. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js.map +1 -0
  240. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts +30 -0
  241. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -0
  242. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +60 -0
  243. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -0
  244. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts +45 -0
  245. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts.map +1 -0
  246. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js +210 -0
  247. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -0
  248. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts +29 -0
  249. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts.map +1 -0
  250. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js +161 -0
  251. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js.map +1 -0
  252. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +39 -0
  253. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -0
  254. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +91 -0
  255. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -0
  256. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts +35 -0
  257. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts.map +1 -0
  258. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +74 -0
  259. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js.map +1 -0
  260. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts +27 -0
  261. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts.map +1 -0
  262. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +103 -0
  263. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js.map +1 -0
  264. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
  265. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +1 -25
  266. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
  267. package/dist/src/planner/scopes/global.js +2 -2
  268. package/dist/src/planner/scopes/global.js.map +1 -1
  269. package/dist/src/planner/type-utils.d.ts.map +1 -1
  270. package/dist/src/planner/type-utils.js +11 -0
  271. package/dist/src/planner/type-utils.js.map +1 -1
  272. package/dist/src/planner/util/fd-utils.d.ts +245 -0
  273. package/dist/src/planner/util/fd-utils.d.ts.map +1 -0
  274. package/dist/src/planner/util/fd-utils.js +1416 -0
  275. package/dist/src/planner/util/fd-utils.js.map +1 -0
  276. package/dist/src/planner/util/ind-utils.d.ts +79 -0
  277. package/dist/src/planner/util/ind-utils.d.ts.map +1 -0
  278. package/dist/src/planner/util/ind-utils.js +146 -0
  279. package/dist/src/planner/util/ind-utils.js.map +1 -0
  280. package/dist/src/planner/util/key-utils.d.ts +75 -14
  281. package/dist/src/planner/util/key-utils.d.ts.map +1 -1
  282. package/dist/src/planner/util/key-utils.js +234 -57
  283. package/dist/src/planner/util/key-utils.js.map +1 -1
  284. package/dist/src/runtime/delta-executor.d.ts +134 -0
  285. package/dist/src/runtime/delta-executor.d.ts.map +1 -0
  286. package/dist/src/runtime/delta-executor.js +382 -0
  287. package/dist/src/runtime/delta-executor.js.map +1 -0
  288. package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
  289. package/dist/src/runtime/emit/alter-table.js +70 -24
  290. package/dist/src/runtime/emit/alter-table.js.map +1 -1
  291. package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
  292. package/dist/src/runtime/emit/create-assertion.js +3 -2
  293. package/dist/src/runtime/emit/create-assertion.js.map +1 -1
  294. package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
  295. package/dist/src/runtime/emit/dml-executor.js +121 -41
  296. package/dist/src/runtime/emit/dml-executor.js.map +1 -1
  297. package/dist/src/runtime/emit/drop-assertion.js +1 -1
  298. package/dist/src/runtime/emit/drop-assertion.js.map +1 -1
  299. package/dist/src/runtime/emit/empty-relation.d.ts +5 -0
  300. package/dist/src/runtime/emit/empty-relation.d.ts.map +1 -0
  301. package/dist/src/runtime/emit/empty-relation.js +11 -0
  302. package/dist/src/runtime/emit/empty-relation.js.map +1 -0
  303. package/dist/src/runtime/foreign-key-actions.d.ts +39 -0
  304. package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
  305. package/dist/src/runtime/foreign-key-actions.js +219 -1
  306. package/dist/src/runtime/foreign-key-actions.js.map +1 -1
  307. package/dist/src/runtime/register.d.ts.map +1 -1
  308. package/dist/src/runtime/register.js +2 -0
  309. package/dist/src/runtime/register.js.map +1 -1
  310. package/dist/src/schema/assertion.d.ts +8 -0
  311. package/dist/src/schema/assertion.d.ts.map +1 -1
  312. package/dist/src/schema/change-events.d.ts +5 -1
  313. package/dist/src/schema/change-events.d.ts.map +1 -1
  314. package/dist/src/schema/change-events.js.map +1 -1
  315. package/dist/src/schema/function.d.ts +65 -1
  316. package/dist/src/schema/function.d.ts.map +1 -1
  317. package/dist/src/schema/function.js +31 -0
  318. package/dist/src/schema/function.js.map +1 -1
  319. package/dist/src/schema/manager.d.ts +33 -0
  320. package/dist/src/schema/manager.d.ts.map +1 -1
  321. package/dist/src/schema/manager.js +95 -4
  322. package/dist/src/schema/manager.js.map +1 -1
  323. package/dist/src/schema/rename-rewriter.d.ts +32 -0
  324. package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
  325. package/dist/src/schema/rename-rewriter.js +392 -105
  326. package/dist/src/schema/rename-rewriter.js.map +1 -1
  327. package/dist/src/schema/table.d.ts +21 -2
  328. package/dist/src/schema/table.d.ts.map +1 -1
  329. package/dist/src/schema/table.js +17 -8
  330. package/dist/src/schema/table.js.map +1 -1
  331. package/dist/src/types/temporal-types.d.ts.map +1 -1
  332. package/dist/src/types/temporal-types.js +32 -0
  333. package/dist/src/types/temporal-types.js.map +1 -1
  334. package/dist/src/vtab/events.d.ts +9 -0
  335. package/dist/src/vtab/events.d.ts.map +1 -1
  336. package/dist/src/vtab/events.js +19 -0
  337. package/dist/src/vtab/events.js.map +1 -1
  338. package/dist/src/vtab/memory/layer/connection.d.ts +20 -8
  339. package/dist/src/vtab/memory/layer/connection.d.ts.map +1 -1
  340. package/dist/src/vtab/memory/layer/connection.js +95 -73
  341. package/dist/src/vtab/memory/layer/connection.js.map +1 -1
  342. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  343. package/dist/src/vtab/memory/layer/manager.js +91 -10
  344. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  345. package/dist/src/vtab/memory/layer/transaction.d.ts +0 -8
  346. package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
  347. package/dist/src/vtab/memory/layer/transaction.js +0 -15
  348. package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
  349. package/dist/src/vtab/memory/table.d.ts.map +1 -1
  350. package/dist/src/vtab/memory/table.js +13 -2
  351. package/dist/src/vtab/memory/table.js.map +1 -1
  352. package/dist/src/vtab/memory/utils/predicate.d.ts +2 -1
  353. package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
  354. package/dist/src/vtab/memory/utils/predicate.js +32 -1
  355. package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
  356. package/package.json +3 -3
@@ -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":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,GAAG,GAAG,YAAY,CAAC,6CAA6C,CAAC,CAAC;AAIxE,SAAS,eAAe,CAAC,IAAc;IACtC,OAAO,IAAI,YAAY,aAAa;WAChC,IAAI,YAAY,mBAAmB;WACnC,IAAI,YAAY,iBAAiB,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,IAAc,EAAE,QAAoB;IAClF,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,MAAM,GAAG,IAAkB,CAAC;IAClC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,+BAA+B;IAC/B,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IAE/C,yEAAyE;IACzE,2EAA2E;IAC3E,mEAAmE;IACnE,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0D,CAAC;IACzF,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC,MAAM,YAAY,mBAAmB,CAAC;YAAE,SAAS;QACvD,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC;QACrC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAC9D,IAAI,MAAM,GAAG,CAAC;YAAE,SAAS;QACzB,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QACjF,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,yEAAyE;IACzE,cAAc;IACd,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAE1D,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC;IACtC,MAAM,qBAAqB,GAAG,cAAc,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAE3E,2CAA2C;IAC3C,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAE7C,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,MAAM,SAAS,GAAqB,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,qBAAqB,CAAC,EAAE,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACP,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,wEAAwE;IACxE,MAAM,iBAAiB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;IACnG,MAAM,eAAe,GAAG,gBAAgB,CAAC,iBAAiB,CAAE,CAAC;IAE7D,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAEhF,4EAA4E;IAC5E,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEhD,GAAG,CAAC,mCAAmC,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE1F,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC;IACf,CAAC;IACD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,SAAS,CAAE,CAAC;IACvD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,kBAAkB,CAC1B,IAAoB,EACpB,gBAA6C,EAC7C,cAAmF,EACnF,qBAA0C;IAE1C,MAAM,UAAU,GAAG,6BAA6B,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC3B,wEAAwE;QACxE,sEAAsE;QACtE,4DAA4D;QAC5D,OAAO,KAAK,CAAC;IACd,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAClD,+DAA+D;QAC/D,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,6BAA6B,CAAC,IAAoB;IAC1D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE;QACpB,IAAI,CAAC,YAAY,mBAAmB,EAAE,CAAC;YACtC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACxB,CAAC;IACF,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,UAAU,CAAC,IAAoB,EAAE,EAA+B;IACxE,EAAE,CAAC,IAAI,CAAC,CAAC;IACT,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,UAAU,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;AACF,CAAC;AAED,SAAS,qBAAqB,CAC7B,IAAoB,EACpB,cAAmF,EACnF,WAAiC;IAEjC,IAAI,IAAI,YAAY,mBAAmB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACvC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACrE,oFAAoF;QACpF,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO,IAAI,mBAAmB,CAC7B,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,UAAU,EACf,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,YAAY,EACpB,OAAO,CAAC,YAAY,CACpB,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,WAAW,GAAe,EAAE,CAAC;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1B,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,SAAS;QACV,CAAC;QACD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,CAAmB,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;QACzF,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,GAAG,IAAI,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAmB,CAAC;AACzD,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAiB,EAAE,SAA6B;IACzE,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;QAClC,OAAO,IAAI,aAAa,CACvB,GAAG,CAAC,KAAK,EACT,SAAS,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,SAAS,EACT,GAAG,CAAC,aAAa,EAAE,CACnB,CAAC;IACH,CAAC;IACD,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;QACxC,OAAO,IAAI,mBAAmB,CAC7B,GAAG,CAAC,KAAK,EACT,SAAS,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,SAAS,EACT,GAAG,CAAC,aAAa,EAAE,CACnB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,iBAAiB,CAC3B,GAAG,CAAC,KAAK,EACT,SAAS,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,SAAS,EACT,GAAG,CAAC,aAAa,EAAE,CACnB,CAAC;AACH,CAAC"}
@@ -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"}
@@ -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"}