@quereus/quereus 3.2.1 → 4.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 (935) hide show
  1. package/README.md +7 -0
  2. package/dist/src/common/datatype.d.ts +12 -0
  3. package/dist/src/common/datatype.d.ts.map +1 -1
  4. package/dist/src/common/datatype.js.map +1 -1
  5. package/dist/src/common/types.d.ts +24 -0
  6. package/dist/src/common/types.d.ts.map +1 -1
  7. package/dist/src/common/types.js.map +1 -1
  8. package/dist/src/core/database-assertions.d.ts +37 -9
  9. package/dist/src/core/database-assertions.d.ts.map +1 -1
  10. package/dist/src/core/database-assertions.js +62 -106
  11. package/dist/src/core/database-assertions.js.map +1 -1
  12. package/dist/src/core/database-events.d.ts +163 -0
  13. package/dist/src/core/database-events.d.ts.map +1 -1
  14. package/dist/src/core/database-events.js +235 -21
  15. package/dist/src/core/database-events.js.map +1 -1
  16. package/dist/src/core/database-external-changes.d.ts +28 -0
  17. package/dist/src/core/database-external-changes.d.ts.map +1 -0
  18. package/dist/src/core/database-external-changes.js +242 -0
  19. package/dist/src/core/database-external-changes.js.map +1 -0
  20. package/dist/src/core/database-internal.d.ts +50 -1
  21. package/dist/src/core/database-internal.d.ts.map +1 -1
  22. package/dist/src/core/database-materialized-views.d.ts +1253 -0
  23. package/dist/src/core/database-materialized-views.d.ts.map +1 -0
  24. package/dist/src/core/database-materialized-views.js +3064 -0
  25. package/dist/src/core/database-materialized-views.js.map +1 -0
  26. package/dist/src/core/database-options.d.ts +4 -0
  27. package/dist/src/core/database-options.d.ts.map +1 -1
  28. package/dist/src/core/database-options.js +10 -0
  29. package/dist/src/core/database-options.js.map +1 -1
  30. package/dist/src/core/database-transaction.d.ts +19 -3
  31. package/dist/src/core/database-transaction.d.ts.map +1 -1
  32. package/dist/src/core/database-transaction.js +30 -3
  33. package/dist/src/core/database-transaction.js.map +1 -1
  34. package/dist/src/core/database-watchers.d.ts +19 -0
  35. package/dist/src/core/database-watchers.d.ts.map +1 -1
  36. package/dist/src/core/database-watchers.js +63 -3
  37. package/dist/src/core/database-watchers.js.map +1 -1
  38. package/dist/src/core/database.d.ts +203 -11
  39. package/dist/src/core/database.d.ts.map +1 -1
  40. package/dist/src/core/database.js +493 -29
  41. package/dist/src/core/database.js.map +1 -1
  42. package/dist/src/core/derived-row-validator.d.ts +137 -0
  43. package/dist/src/core/derived-row-validator.d.ts.map +1 -0
  44. package/dist/src/core/derived-row-validator.js +314 -0
  45. package/dist/src/core/derived-row-validator.js.map +1 -0
  46. package/dist/src/core/statement.d.ts.map +1 -1
  47. package/dist/src/core/statement.js +30 -9
  48. package/dist/src/core/statement.js.map +1 -1
  49. package/dist/src/emit/ast-stringify.d.ts +135 -1
  50. package/dist/src/emit/ast-stringify.d.ts.map +1 -1
  51. package/dist/src/emit/ast-stringify.js +795 -120
  52. package/dist/src/emit/ast-stringify.js.map +1 -1
  53. package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
  54. package/dist/src/func/builtins/aggregate.js +11 -10
  55. package/dist/src/func/builtins/aggregate.js.map +1 -1
  56. package/dist/src/func/builtins/builtin-window-functions.d.ts.map +1 -1
  57. package/dist/src/func/builtins/builtin-window-functions.js +32 -0
  58. package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
  59. package/dist/src/func/builtins/explain.d.ts +3 -0
  60. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  61. package/dist/src/func/builtins/explain.js +229 -0
  62. package/dist/src/func/builtins/explain.js.map +1 -1
  63. package/dist/src/func/builtins/index.d.ts.map +1 -1
  64. package/dist/src/func/builtins/index.js +10 -2
  65. package/dist/src/func/builtins/index.js.map +1 -1
  66. package/dist/src/func/builtins/json.d.ts.map +1 -1
  67. package/dist/src/func/builtins/json.js +3 -2
  68. package/dist/src/func/builtins/json.js.map +1 -1
  69. package/dist/src/func/builtins/mutation.d.ts +2 -0
  70. package/dist/src/func/builtins/mutation.d.ts.map +1 -0
  71. package/dist/src/func/builtins/mutation.js +53 -0
  72. package/dist/src/func/builtins/mutation.js.map +1 -0
  73. package/dist/src/func/builtins/schema.d.ts +2 -0
  74. package/dist/src/func/builtins/schema.d.ts.map +1 -1
  75. package/dist/src/func/builtins/schema.js +713 -26
  76. package/dist/src/func/builtins/schema.js.map +1 -1
  77. package/dist/src/func/builtins/string.js +1 -1
  78. package/dist/src/func/builtins/string.js.map +1 -1
  79. package/dist/src/func/registration.d.ts +9 -0
  80. package/dist/src/func/registration.d.ts.map +1 -1
  81. package/dist/src/func/registration.js +4 -0
  82. package/dist/src/func/registration.js.map +1 -1
  83. package/dist/src/index.d.ts +25 -6
  84. package/dist/src/index.d.ts.map +1 -1
  85. package/dist/src/index.js +27 -3
  86. package/dist/src/index.js.map +1 -1
  87. package/dist/src/parser/ast.d.ts +353 -21
  88. package/dist/src/parser/ast.d.ts.map +1 -1
  89. package/dist/src/parser/index.d.ts +14 -1
  90. package/dist/src/parser/index.d.ts.map +1 -1
  91. package/dist/src/parser/index.js +19 -0
  92. package/dist/src/parser/index.js.map +1 -1
  93. package/dist/src/parser/lexer.d.ts +9 -0
  94. package/dist/src/parser/lexer.d.ts.map +1 -1
  95. package/dist/src/parser/lexer.js +9 -0
  96. package/dist/src/parser/lexer.js.map +1 -1
  97. package/dist/src/parser/parser.d.ts +277 -8
  98. package/dist/src/parser/parser.d.ts.map +1 -1
  99. package/dist/src/parser/parser.js +1393 -471
  100. package/dist/src/parser/parser.js.map +1 -1
  101. package/dist/src/parser/visitor.d.ts.map +1 -1
  102. package/dist/src/parser/visitor.js +12 -8
  103. package/dist/src/parser/visitor.js.map +1 -1
  104. package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -1
  105. package/dist/src/planner/analysis/assertion-classifier.js +4 -0
  106. package/dist/src/planner/analysis/assertion-classifier.js.map +1 -1
  107. package/dist/src/planner/analysis/assertion-hoist-cache.d.ts.map +1 -1
  108. package/dist/src/planner/analysis/assertion-hoist-cache.js +8 -4
  109. package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -1
  110. package/dist/src/planner/analysis/authored-inverse.d.ts +22 -0
  111. package/dist/src/planner/analysis/authored-inverse.d.ts.map +1 -0
  112. package/dist/src/planner/analysis/authored-inverse.js +267 -0
  113. package/dist/src/planner/analysis/authored-inverse.js.map +1 -0
  114. package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -1
  115. package/dist/src/planner/analysis/binding-extractor.js +9 -6
  116. package/dist/src/planner/analysis/binding-extractor.js.map +1 -1
  117. package/dist/src/planner/analysis/change-scope.d.ts +34 -4
  118. package/dist/src/planner/analysis/change-scope.d.ts.map +1 -1
  119. package/dist/src/planner/analysis/change-scope.js +115 -7
  120. package/dist/src/planner/analysis/change-scope.js.map +1 -1
  121. package/dist/src/planner/analysis/check-extraction.d.ts +36 -2
  122. package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -1
  123. package/dist/src/planner/analysis/check-extraction.js +174 -46
  124. package/dist/src/planner/analysis/check-extraction.js.map +1 -1
  125. package/dist/src/planner/analysis/coarsened-key.d.ts +109 -0
  126. package/dist/src/planner/analysis/coarsened-key.d.ts.map +1 -0
  127. package/dist/src/planner/analysis/coarsened-key.js +228 -0
  128. package/dist/src/planner/analysis/coarsened-key.js.map +1 -0
  129. package/dist/src/planner/analysis/comparison-collation.d.ts +216 -0
  130. package/dist/src/planner/analysis/comparison-collation.d.ts.map +1 -0
  131. package/dist/src/planner/analysis/comparison-collation.js +341 -0
  132. package/dist/src/planner/analysis/comparison-collation.js.map +1 -0
  133. package/dist/src/planner/analysis/constraint-extractor.d.ts +13 -1
  134. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  135. package/dist/src/planner/analysis/constraint-extractor.js +220 -21
  136. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  137. package/dist/src/planner/analysis/coverage-prover.d.ts +321 -0
  138. package/dist/src/planner/analysis/coverage-prover.d.ts.map +1 -0
  139. package/dist/src/planner/analysis/coverage-prover.js +1038 -0
  140. package/dist/src/planner/analysis/coverage-prover.js.map +1 -0
  141. package/dist/src/planner/analysis/key-filter.d.ts +22 -0
  142. package/dist/src/planner/analysis/key-filter.d.ts.map +1 -0
  143. package/dist/src/planner/analysis/key-filter.js +105 -0
  144. package/dist/src/planner/analysis/key-filter.js.map +1 -0
  145. package/dist/src/planner/analysis/partial-unique-extraction.d.ts +36 -1
  146. package/dist/src/planner/analysis/partial-unique-extraction.d.ts.map +1 -1
  147. package/dist/src/planner/analysis/partial-unique-extraction.js +148 -22
  148. package/dist/src/planner/analysis/partial-unique-extraction.js.map +1 -1
  149. package/dist/src/planner/analysis/predicate-normalizer.d.ts.map +1 -1
  150. package/dist/src/planner/analysis/predicate-normalizer.js +30 -1
  151. package/dist/src/planner/analysis/predicate-normalizer.js.map +1 -1
  152. package/dist/src/planner/analysis/predicate-shape.d.ts +36 -1
  153. package/dist/src/planner/analysis/predicate-shape.d.ts.map +1 -1
  154. package/dist/src/planner/analysis/predicate-shape.js +51 -13
  155. package/dist/src/planner/analysis/predicate-shape.js.map +1 -1
  156. package/dist/src/planner/analysis/query-rewrite-matcher.d.ts +314 -0
  157. package/dist/src/planner/analysis/query-rewrite-matcher.d.ts.map +1 -0
  158. package/dist/src/planner/analysis/query-rewrite-matcher.js +1081 -0
  159. package/dist/src/planner/analysis/query-rewrite-matcher.js.map +1 -0
  160. package/dist/src/planner/analysis/scalar-invertibility.d.ts +92 -0
  161. package/dist/src/planner/analysis/scalar-invertibility.d.ts.map +1 -0
  162. package/dist/src/planner/analysis/scalar-invertibility.js +129 -0
  163. package/dist/src/planner/analysis/scalar-invertibility.js.map +1 -0
  164. package/dist/src/planner/analysis/update-lineage.d.ts +196 -0
  165. package/dist/src/planner/analysis/update-lineage.d.ts.map +1 -0
  166. package/dist/src/planner/analysis/update-lineage.js +322 -0
  167. package/dist/src/planner/analysis/update-lineage.js.map +1 -0
  168. package/dist/src/planner/analysis/view-complement.d.ts +42 -0
  169. package/dist/src/planner/analysis/view-complement.d.ts.map +1 -0
  170. package/dist/src/planner/analysis/view-complement.js +54 -0
  171. package/dist/src/planner/analysis/view-complement.js.map +1 -0
  172. package/dist/src/planner/building/alter-table.d.ts +1 -1
  173. package/dist/src/planner/building/alter-table.d.ts.map +1 -1
  174. package/dist/src/planner/building/alter-table.js +211 -2
  175. package/dist/src/planner/building/alter-table.js.map +1 -1
  176. package/dist/src/planner/building/block.d.ts.map +1 -1
  177. package/dist/src/planner/building/block.js +18 -1
  178. package/dist/src/planner/building/block.js.map +1 -1
  179. package/dist/src/planner/building/constraint-builder.d.ts +33 -5
  180. package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
  181. package/dist/src/planner/building/constraint-builder.js +63 -28
  182. package/dist/src/planner/building/constraint-builder.js.map +1 -1
  183. package/dist/src/planner/building/create-view.d.ts +9 -0
  184. package/dist/src/planner/building/create-view.d.ts.map +1 -1
  185. package/dist/src/planner/building/create-view.js +41 -12
  186. package/dist/src/planner/building/create-view.js.map +1 -1
  187. package/dist/src/planner/building/ddl.d.ts.map +1 -1
  188. package/dist/src/planner/building/ddl.js +94 -0
  189. package/dist/src/planner/building/ddl.js.map +1 -1
  190. package/dist/src/planner/building/declare-schema.d.ts +1 -0
  191. package/dist/src/planner/building/declare-schema.d.ts.map +1 -1
  192. package/dist/src/planner/building/declare-schema.js +4 -1
  193. package/dist/src/planner/building/declare-schema.js.map +1 -1
  194. package/dist/src/planner/building/default-scope.d.ts +26 -0
  195. package/dist/src/planner/building/default-scope.d.ts.map +1 -0
  196. package/dist/src/planner/building/default-scope.js +41 -0
  197. package/dist/src/planner/building/default-scope.js.map +1 -0
  198. package/dist/src/planner/building/delete.d.ts +19 -1
  199. package/dist/src/planner/building/delete.d.ts.map +1 -1
  200. package/dist/src/planner/building/delete.js +116 -34
  201. package/dist/src/planner/building/delete.js.map +1 -1
  202. package/dist/src/planner/building/dml-target.d.ts +118 -0
  203. package/dist/src/planner/building/dml-target.d.ts.map +1 -0
  204. package/dist/src/planner/building/dml-target.js +282 -0
  205. package/dist/src/planner/building/dml-target.js.map +1 -0
  206. package/dist/src/planner/building/drop-index.d.ts.map +1 -1
  207. package/dist/src/planner/building/drop-index.js +4 -1
  208. package/dist/src/planner/building/drop-index.js.map +1 -1
  209. package/dist/src/planner/building/drop-view.d.ts.map +1 -1
  210. package/dist/src/planner/building/drop-view.js +4 -2
  211. package/dist/src/planner/building/drop-view.js.map +1 -1
  212. package/dist/src/planner/building/expression.d.ts.map +1 -1
  213. package/dist/src/planner/building/expression.js +60 -21
  214. package/dist/src/planner/building/expression.js.map +1 -1
  215. package/dist/src/planner/building/foreign-key-builder.d.ts +30 -0
  216. package/dist/src/planner/building/foreign-key-builder.d.ts.map +1 -1
  217. package/dist/src/planner/building/foreign-key-builder.js +160 -129
  218. package/dist/src/planner/building/foreign-key-builder.js.map +1 -1
  219. package/dist/src/planner/building/insert.d.ts +45 -2
  220. package/dist/src/planner/building/insert.d.ts.map +1 -1
  221. package/dist/src/planner/building/insert.js +257 -88
  222. package/dist/src/planner/building/insert.js.map +1 -1
  223. package/dist/src/planner/building/lens-auxiliary-access.d.ts +22 -0
  224. package/dist/src/planner/building/lens-auxiliary-access.d.ts.map +1 -0
  225. package/dist/src/planner/building/lens-auxiliary-access.js +132 -0
  226. package/dist/src/planner/building/lens-auxiliary-access.js.map +1 -0
  227. package/dist/src/planner/building/materialized-view.d.ts +16 -0
  228. package/dist/src/planner/building/materialized-view.d.ts.map +1 -0
  229. package/dist/src/planner/building/materialized-view.js +57 -0
  230. package/dist/src/planner/building/materialized-view.js.map +1 -0
  231. package/dist/src/planner/building/returning-star.d.ts +32 -0
  232. package/dist/src/planner/building/returning-star.d.ts.map +1 -0
  233. package/dist/src/planner/building/returning-star.js +45 -0
  234. package/dist/src/planner/building/returning-star.js.map +1 -0
  235. package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
  236. package/dist/src/planner/building/select-aggregates.js +51 -13
  237. package/dist/src/planner/building/select-aggregates.js.map +1 -1
  238. package/dist/src/planner/building/select-compound.d.ts.map +1 -1
  239. package/dist/src/planner/building/select-compound.js +84 -11
  240. package/dist/src/planner/building/select-compound.js.map +1 -1
  241. package/dist/src/planner/building/select-context.d.ts +10 -2
  242. package/dist/src/planner/building/select-context.d.ts.map +1 -1
  243. package/dist/src/planner/building/select-context.js +7 -1
  244. package/dist/src/planner/building/select-context.js.map +1 -1
  245. package/dist/src/planner/building/select-modifiers.js +6 -0
  246. package/dist/src/planner/building/select-modifiers.js.map +1 -1
  247. package/dist/src/planner/building/select-ordinal.d.ts +18 -0
  248. package/dist/src/planner/building/select-ordinal.d.ts.map +1 -1
  249. package/dist/src/planner/building/select-ordinal.js +30 -0
  250. package/dist/src/planner/building/select-ordinal.js.map +1 -1
  251. package/dist/src/planner/building/select-projections.d.ts +8 -2
  252. package/dist/src/planner/building/select-projections.d.ts.map +1 -1
  253. package/dist/src/planner/building/select-projections.js +26 -4
  254. package/dist/src/planner/building/select-projections.js.map +1 -1
  255. package/dist/src/planner/building/select-window.d.ts.map +1 -1
  256. package/dist/src/planner/building/select-window.js +8 -5
  257. package/dist/src/planner/building/select-window.js.map +1 -1
  258. package/dist/src/planner/building/select.d.ts.map +1 -1
  259. package/dist/src/planner/building/select.js +164 -59
  260. package/dist/src/planner/building/select.js.map +1 -1
  261. package/dist/src/planner/building/set-object-tags.d.ts +7 -0
  262. package/dist/src/planner/building/set-object-tags.d.ts.map +1 -0
  263. package/dist/src/planner/building/set-object-tags.js +38 -0
  264. package/dist/src/planner/building/set-object-tags.js.map +1 -0
  265. package/dist/src/planner/building/tag-diagnostics.d.ts +27 -0
  266. package/dist/src/planner/building/tag-diagnostics.d.ts.map +1 -0
  267. package/dist/src/planner/building/tag-diagnostics.js +37 -0
  268. package/dist/src/planner/building/tag-diagnostics.js.map +1 -0
  269. package/dist/src/planner/building/update.d.ts +18 -1
  270. package/dist/src/planner/building/update.d.ts.map +1 -1
  271. package/dist/src/planner/building/update.js +134 -58
  272. package/dist/src/planner/building/update.js.map +1 -1
  273. package/dist/src/planner/building/view-mutation-builder.d.ts +15 -0
  274. package/dist/src/planner/building/view-mutation-builder.d.ts.map +1 -0
  275. package/dist/src/planner/building/view-mutation-builder.js +1158 -0
  276. package/dist/src/planner/building/view-mutation-builder.js.map +1 -0
  277. package/dist/src/planner/building/with.d.ts +11 -0
  278. package/dist/src/planner/building/with.d.ts.map +1 -1
  279. package/dist/src/planner/building/with.js +48 -10
  280. package/dist/src/planner/building/with.js.map +1 -1
  281. package/dist/src/planner/cost/index.d.ts +83 -0
  282. package/dist/src/planner/cost/index.d.ts.map +1 -1
  283. package/dist/src/planner/cost/index.js +114 -0
  284. package/dist/src/planner/cost/index.js.map +1 -1
  285. package/dist/src/planner/framework/characteristics.d.ts +38 -4
  286. package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
  287. package/dist/src/planner/framework/characteristics.js +50 -6
  288. package/dist/src/planner/framework/characteristics.js.map +1 -1
  289. package/dist/src/planner/framework/pass.d.ts.map +1 -1
  290. package/dist/src/planner/framework/pass.js +2 -1
  291. package/dist/src/planner/framework/pass.js.map +1 -1
  292. package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
  293. package/dist/src/planner/framework/physical-utils.js +7 -1
  294. package/dist/src/planner/framework/physical-utils.js.map +1 -1
  295. package/dist/src/planner/framework/registry.d.ts +39 -1
  296. package/dist/src/planner/framework/registry.d.ts.map +1 -1
  297. package/dist/src/planner/framework/registry.js +18 -2
  298. package/dist/src/planner/framework/registry.js.map +1 -1
  299. package/dist/src/planner/mutation/backward-body.d.ts +131 -0
  300. package/dist/src/planner/mutation/backward-body.d.ts.map +1 -0
  301. package/dist/src/planner/mutation/backward-body.js +135 -0
  302. package/dist/src/planner/mutation/backward-body.js.map +1 -0
  303. package/dist/src/planner/mutation/cte-flatten.d.ts +17 -0
  304. package/dist/src/planner/mutation/cte-flatten.d.ts.map +1 -0
  305. package/dist/src/planner/mutation/cte-flatten.js +364 -0
  306. package/dist/src/planner/mutation/cte-flatten.js.map +1 -0
  307. package/dist/src/planner/mutation/decomposition.d.ts +273 -0
  308. package/dist/src/planner/mutation/decomposition.d.ts.map +1 -0
  309. package/dist/src/planner/mutation/decomposition.js +1719 -0
  310. package/dist/src/planner/mutation/decomposition.js.map +1 -0
  311. package/dist/src/planner/mutation/lens-enforcement.d.ts +165 -0
  312. package/dist/src/planner/mutation/lens-enforcement.d.ts.map +1 -0
  313. package/dist/src/planner/mutation/lens-enforcement.js +745 -0
  314. package/dist/src/planner/mutation/lens-enforcement.js.map +1 -0
  315. package/dist/src/planner/mutation/multi-source.d.ts +568 -0
  316. package/dist/src/planner/mutation/multi-source.d.ts.map +1 -0
  317. package/dist/src/planner/mutation/multi-source.js +2915 -0
  318. package/dist/src/planner/mutation/multi-source.js.map +1 -0
  319. package/dist/src/planner/mutation/mutation-diagnostic.d.ts +37 -0
  320. package/dist/src/planner/mutation/mutation-diagnostic.d.ts.map +1 -0
  321. package/dist/src/planner/mutation/mutation-diagnostic.js +24 -0
  322. package/dist/src/planner/mutation/mutation-diagnostic.js.map +1 -0
  323. package/dist/src/planner/mutation/mutation-tags.d.ts +33 -0
  324. package/dist/src/planner/mutation/mutation-tags.d.ts.map +1 -0
  325. package/dist/src/planner/mutation/mutation-tags.js +31 -0
  326. package/dist/src/planner/mutation/mutation-tags.js.map +1 -0
  327. package/dist/src/planner/mutation/propagate.d.ts +97 -0
  328. package/dist/src/planner/mutation/propagate.d.ts.map +1 -0
  329. package/dist/src/planner/mutation/propagate.js +220 -0
  330. package/dist/src/planner/mutation/propagate.js.map +1 -0
  331. package/dist/src/planner/mutation/scope-transform.d.ts +181 -0
  332. package/dist/src/planner/mutation/scope-transform.d.ts.map +1 -0
  333. package/dist/src/planner/mutation/scope-transform.js +574 -0
  334. package/dist/src/planner/mutation/scope-transform.js.map +1 -0
  335. package/dist/src/planner/mutation/set-op.d.ts +242 -0
  336. package/dist/src/planner/mutation/set-op.d.ts.map +1 -0
  337. package/dist/src/planner/mutation/set-op.js +1687 -0
  338. package/dist/src/planner/mutation/set-op.js.map +1 -0
  339. package/dist/src/planner/mutation/single-source.d.ts +261 -0
  340. package/dist/src/planner/mutation/single-source.d.ts.map +1 -0
  341. package/dist/src/planner/mutation/single-source.js +1096 -0
  342. package/dist/src/planner/mutation/single-source.js.map +1 -0
  343. package/dist/src/planner/nodes/aggregate-node.d.ts +6 -4
  344. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  345. package/dist/src/planner/nodes/aggregate-node.js +11 -9
  346. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  347. package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
  348. package/dist/src/planner/nodes/alias-node.js +5 -1
  349. package/dist/src/planner/nodes/alias-node.js.map +1 -1
  350. package/dist/src/planner/nodes/alter-table-node.d.ts +124 -1
  351. package/dist/src/planner/nodes/alter-table-node.d.ts.map +1 -1
  352. package/dist/src/planner/nodes/alter-table-node.js +27 -0
  353. package/dist/src/planner/nodes/alter-table-node.js.map +1 -1
  354. package/dist/src/planner/nodes/analyze-node.d.ts +2 -1
  355. package/dist/src/planner/nodes/analyze-node.d.ts.map +1 -1
  356. package/dist/src/planner/nodes/analyze-node.js +21 -1
  357. package/dist/src/planner/nodes/analyze-node.js.map +1 -1
  358. package/dist/src/planner/nodes/asserted-keys-node.d.ts +43 -0
  359. package/dist/src/planner/nodes/asserted-keys-node.d.ts.map +1 -0
  360. package/dist/src/planner/nodes/asserted-keys-node.js +99 -0
  361. package/dist/src/planner/nodes/asserted-keys-node.js.map +1 -0
  362. package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -1
  363. package/dist/src/planner/nodes/async-gather-node.js +33 -8
  364. package/dist/src/planner/nodes/async-gather-node.js.map +1 -1
  365. package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
  366. package/dist/src/planner/nodes/bloom-join-node.js +2 -1
  367. package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
  368. package/dist/src/planner/nodes/create-view-node.d.ts +7 -2
  369. package/dist/src/planner/nodes/create-view-node.d.ts.map +1 -1
  370. package/dist/src/planner/nodes/create-view-node.js +4 -1
  371. package/dist/src/planner/nodes/create-view-node.js.map +1 -1
  372. package/dist/src/planner/nodes/declarative-schema.d.ts +13 -1
  373. package/dist/src/planner/nodes/declarative-schema.d.ts.map +1 -1
  374. package/dist/src/planner/nodes/declarative-schema.js +32 -0
  375. package/dist/src/planner/nodes/declarative-schema.js.map +1 -1
  376. package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
  377. package/dist/src/planner/nodes/distinct-node.js +2 -0
  378. package/dist/src/planner/nodes/distinct-node.js.map +1 -1
  379. package/dist/src/planner/nodes/dml-executor-node.d.ts +29 -1
  380. package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
  381. package/dist/src/planner/nodes/dml-executor-node.js +27 -3
  382. package/dist/src/planner/nodes/dml-executor-node.js.map +1 -1
  383. package/dist/src/planner/nodes/eager-prefetch-node.d.ts.map +1 -1
  384. package/dist/src/planner/nodes/eager-prefetch-node.js +2 -0
  385. package/dist/src/planner/nodes/eager-prefetch-node.js.map +1 -1
  386. package/dist/src/planner/nodes/envelope-scan-node.d.ts +42 -0
  387. package/dist/src/planner/nodes/envelope-scan-node.d.ts.map +1 -0
  388. package/dist/src/planner/nodes/envelope-scan-node.js +62 -0
  389. package/dist/src/planner/nodes/envelope-scan-node.js.map +1 -0
  390. package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts.map +1 -1
  391. package/dist/src/planner/nodes/fanout-lookup-join-node.js +11 -1
  392. package/dist/src/planner/nodes/fanout-lookup-join-node.js.map +1 -1
  393. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  394. package/dist/src/planner/nodes/filter.js +63 -13
  395. package/dist/src/planner/nodes/filter.js.map +1 -1
  396. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
  397. package/dist/src/planner/nodes/hash-aggregate.js +6 -16
  398. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
  399. package/dist/src/planner/nodes/join-node.d.ts +41 -1
  400. package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
  401. package/dist/src/planner/nodes/join-node.js +78 -8
  402. package/dist/src/planner/nodes/join-node.js.map +1 -1
  403. package/dist/src/planner/nodes/join-utils.d.ts +33 -6
  404. package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
  405. package/dist/src/planner/nodes/join-utils.js +131 -10
  406. package/dist/src/planner/nodes/join-utils.js.map +1 -1
  407. package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts +104 -0
  408. package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts.map +1 -0
  409. package/dist/src/planner/nodes/lens-auxiliary-access-node.js +91 -0
  410. package/dist/src/planner/nodes/lens-auxiliary-access-node.js.map +1 -0
  411. package/dist/src/planner/nodes/limit-offset.d.ts +12 -0
  412. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  413. package/dist/src/planner/nodes/limit-offset.js +52 -3
  414. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  415. package/dist/src/planner/nodes/materialized-view-nodes.d.ts +69 -0
  416. package/dist/src/planner/nodes/materialized-view-nodes.d.ts.map +1 -0
  417. package/dist/src/planner/nodes/materialized-view-nodes.js +111 -0
  418. package/dist/src/planner/nodes/materialized-view-nodes.js.map +1 -0
  419. package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
  420. package/dist/src/planner/nodes/merge-join-node.js +2 -1
  421. package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
  422. package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -1
  423. package/dist/src/planner/nodes/ordinal-slice-node.js +2 -0
  424. package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
  425. package/dist/src/planner/nodes/plan-node-type.d.ts +9 -0
  426. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  427. package/dist/src/planner/nodes/plan-node-type.js +9 -0
  428. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  429. package/dist/src/planner/nodes/plan-node.d.ts +265 -5
  430. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  431. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  432. package/dist/src/planner/nodes/pragma.d.ts +2 -1
  433. package/dist/src/planner/nodes/pragma.d.ts.map +1 -1
  434. package/dist/src/planner/nodes/pragma.js +12 -0
  435. package/dist/src/planner/nodes/pragma.js.map +1 -1
  436. package/dist/src/planner/nodes/project-node.d.ts +14 -1
  437. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  438. package/dist/src/planner/nodes/project-node.js +103 -16
  439. package/dist/src/planner/nodes/project-node.js.map +1 -1
  440. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  441. package/dist/src/planner/nodes/reference.js +63 -30
  442. package/dist/src/planner/nodes/reference.js.map +1 -1
  443. package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
  444. package/dist/src/planner/nodes/retrieve-node.js +7 -0
  445. package/dist/src/planner/nodes/retrieve-node.js.map +1 -1
  446. package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
  447. package/dist/src/planner/nodes/returning-node.js +10 -3
  448. package/dist/src/planner/nodes/returning-node.js.map +1 -1
  449. package/dist/src/planner/nodes/scalar.d.ts +20 -0
  450. package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
  451. package/dist/src/planner/nodes/scalar.js +71 -14
  452. package/dist/src/planner/nodes/scalar.js.map +1 -1
  453. package/dist/src/planner/nodes/set-object-tags-node.d.ts +39 -0
  454. package/dist/src/planner/nodes/set-object-tags-node.d.ts.map +1 -0
  455. package/dist/src/planner/nodes/set-object-tags-node.js +41 -0
  456. package/dist/src/planner/nodes/set-object-tags-node.js.map +1 -0
  457. package/dist/src/planner/nodes/set-operation-node.d.ts +123 -1
  458. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  459. package/dist/src/planner/nodes/set-operation-node.js +302 -18
  460. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  461. package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
  462. package/dist/src/planner/nodes/single-row.js +3 -0
  463. package/dist/src/planner/nodes/single-row.js.map +1 -1
  464. package/dist/src/planner/nodes/sort.d.ts.map +1 -1
  465. package/dist/src/planner/nodes/sort.js +8 -7
  466. package/dist/src/planner/nodes/sort.js.map +1 -1
  467. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  468. package/dist/src/planner/nodes/stream-aggregate.js +8 -23
  469. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  470. package/dist/src/planner/nodes/subquery.d.ts +2 -0
  471. package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
  472. package/dist/src/planner/nodes/subquery.js +18 -2
  473. package/dist/src/planner/nodes/subquery.js.map +1 -1
  474. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  475. package/dist/src/planner/nodes/table-access-nodes.js +23 -3
  476. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  477. package/dist/src/planner/nodes/table-function-call.js +6 -0
  478. package/dist/src/planner/nodes/table-function-call.js.map +1 -1
  479. package/dist/src/planner/nodes/values-node.d.ts +3 -1
  480. package/dist/src/planner/nodes/values-node.d.ts.map +1 -1
  481. package/dist/src/planner/nodes/values-node.js +26 -0
  482. package/dist/src/planner/nodes/values-node.js.map +1 -1
  483. package/dist/src/planner/nodes/view-mutation-node.d.ts +259 -0
  484. package/dist/src/planner/nodes/view-mutation-node.d.ts.map +1 -0
  485. package/dist/src/planner/nodes/view-mutation-node.js +273 -0
  486. package/dist/src/planner/nodes/view-mutation-node.js.map +1 -0
  487. package/dist/src/planner/nodes/window-function.d.ts +17 -1
  488. package/dist/src/planner/nodes/window-function.d.ts.map +1 -1
  489. package/dist/src/planner/nodes/window-function.js +15 -1
  490. package/dist/src/planner/nodes/window-function.js.map +1 -1
  491. package/dist/src/planner/nodes/window-node.js +3 -3
  492. package/dist/src/planner/nodes/window-node.js.map +1 -1
  493. package/dist/src/planner/optimizer.d.ts.map +1 -1
  494. package/dist/src/planner/optimizer.js +372 -39
  495. package/dist/src/planner/optimizer.js.map +1 -1
  496. package/dist/src/planner/planning-context.d.ts +1 -1
  497. package/dist/src/planner/planning-context.d.ts.map +1 -1
  498. package/dist/src/planner/rules/access/lens-access-form-matcher.d.ts +70 -0
  499. package/dist/src/planner/rules/access/lens-access-form-matcher.d.ts.map +1 -0
  500. package/dist/src/planner/rules/access/lens-access-form-matcher.js +156 -0
  501. package/dist/src/planner/rules/access/lens-access-form-matcher.js.map +1 -0
  502. package/dist/src/planner/rules/access/rule-lens-auxiliary-access.d.ts +31 -0
  503. package/dist/src/planner/rules/access/rule-lens-auxiliary-access.d.ts.map +1 -0
  504. package/dist/src/planner/rules/access/rule-lens-auxiliary-access.js +176 -0
  505. package/dist/src/planner/rules/access/rule-lens-auxiliary-access.js.map +1 -0
  506. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  507. package/dist/src/planner/rules/access/rule-select-access-path.js +435 -37
  508. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  509. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
  510. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +8 -27
  511. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
  512. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +9 -3
  513. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -1
  514. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +56 -5
  515. package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -1
  516. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts +39 -0
  517. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts.map +1 -0
  518. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js +616 -0
  519. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js.map +1 -0
  520. package/dist/src/planner/rules/cache/rule-scalar-cse.d.ts.map +1 -1
  521. package/dist/src/planner/rules/cache/rule-scalar-cse.js +8 -1
  522. package/dist/src/planner/rules/cache/rule-scalar-cse.js.map +1 -1
  523. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +8 -7
  524. package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -1
  525. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +14 -21
  526. package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
  527. package/dist/src/planner/rules/join/equi-pair-extractor.d.ts +36 -0
  528. package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -1
  529. package/dist/src/planner/rules/join/equi-pair-extractor.js +42 -5
  530. package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -1
  531. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts.map +1 -1
  532. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +10 -0
  533. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js.map +1 -1
  534. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +25 -9
  535. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -1
  536. package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.d.ts +130 -0
  537. package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.d.ts.map +1 -0
  538. package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.js +206 -0
  539. package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.js.map +1 -0
  540. package/dist/src/planner/rules/join/rule-join-elimination.d.ts +67 -14
  541. package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -1
  542. package/dist/src/planner/rules/join/rule-join-elimination.js +81 -25
  543. package/dist/src/planner/rules/join/rule-join-elimination.js.map +1 -1
  544. package/dist/src/planner/rules/join/rule-join-existence-pruning.d.ts +84 -0
  545. package/dist/src/planner/rules/join/rule-join-existence-pruning.d.ts.map +1 -0
  546. package/dist/src/planner/rules/join/rule-join-existence-pruning.js +138 -0
  547. package/dist/src/planner/rules/join/rule-join-existence-pruning.js.map +1 -0
  548. package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -1
  549. package/dist/src/planner/rules/join/rule-join-greedy-commute.js +19 -1
  550. package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
  551. package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
  552. package/dist/src/planner/rules/join/rule-join-physical-selection.js +14 -2
  553. package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
  554. package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts.map +1 -1
  555. package/dist/src/planner/rules/join/rule-lateral-top1-asof.js +5 -2
  556. package/dist/src/planner/rules/join/rule-lateral-top1-asof.js.map +1 -1
  557. package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -1
  558. package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +4 -0
  559. package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -1
  560. package/dist/src/planner/rules/join/rule-quickpick-enumeration.d.ts.map +1 -1
  561. package/dist/src/planner/rules/join/rule-quickpick-enumeration.js +10 -0
  562. package/dist/src/planner/rules/join/rule-quickpick-enumeration.js.map +1 -1
  563. package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.d.ts +286 -0
  564. package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.d.ts.map +1 -0
  565. package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.js +548 -0
  566. package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.js.map +1 -0
  567. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts.map +1 -1
  568. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js +9 -1
  569. package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js.map +1 -1
  570. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts.map +1 -1
  571. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js +7 -0
  572. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js.map +1 -1
  573. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts.map +1 -1
  574. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js +10 -1
  575. package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js.map +1 -1
  576. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts.map +1 -1
  577. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +10 -1
  578. package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -1
  579. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts.map +1 -1
  580. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +18 -0
  581. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js.map +1 -1
  582. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -1
  583. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +7 -0
  584. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -1
  585. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts.map +1 -1
  586. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js +9 -0
  587. package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -1
  588. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js +13 -3
  589. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +1 -1
  590. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +2 -2
  591. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
  592. package/dist/src/planner/rules/retrieve/rule-projection-pruning.d.ts.map +1 -1
  593. package/dist/src/planner/rules/retrieve/rule-projection-pruning.js +14 -0
  594. package/dist/src/planner/rules/retrieve/rule-projection-pruning.js.map +1 -1
  595. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +16 -0
  596. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -1
  597. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +47 -4
  598. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -1
  599. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts.map +1 -1
  600. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +8 -0
  601. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js.map +1 -1
  602. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts.map +1 -1
  603. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +7 -0
  604. package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js.map +1 -1
  605. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
  606. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +12 -0
  607. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
  608. package/dist/src/planner/rules/window/rule-monotonic-window.js +1 -1
  609. package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -1
  610. package/dist/src/planner/type-utils.d.ts +14 -0
  611. package/dist/src/planner/type-utils.d.ts.map +1 -1
  612. package/dist/src/planner/type-utils.js +66 -21
  613. package/dist/src/planner/type-utils.js.map +1 -1
  614. package/dist/src/planner/util/fd-utils.d.ts +228 -36
  615. package/dist/src/planner/util/fd-utils.d.ts.map +1 -1
  616. package/dist/src/planner/util/fd-utils.js +501 -84
  617. package/dist/src/planner/util/fd-utils.js.map +1 -1
  618. package/dist/src/planner/util/ind-utils.d.ts +27 -1
  619. package/dist/src/planner/util/ind-utils.d.ts.map +1 -1
  620. package/dist/src/planner/util/ind-utils.js +80 -6
  621. package/dist/src/planner/util/ind-utils.js.map +1 -1
  622. package/dist/src/planner/util/key-utils.d.ts +26 -3
  623. package/dist/src/planner/util/key-utils.d.ts.map +1 -1
  624. package/dist/src/planner/util/key-utils.js +182 -33
  625. package/dist/src/planner/util/key-utils.js.map +1 -1
  626. package/dist/src/planner/util/set-op-wrapper.d.ts +37 -0
  627. package/dist/src/planner/util/set-op-wrapper.d.ts.map +1 -0
  628. package/dist/src/planner/util/set-op-wrapper.js +82 -0
  629. package/dist/src/planner/util/set-op-wrapper.js.map +1 -0
  630. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
  631. package/dist/src/planner/validation/plan-validator.js +1 -0
  632. package/dist/src/planner/validation/plan-validator.js.map +1 -1
  633. package/dist/src/runtime/context-helpers.d.ts +13 -1
  634. package/dist/src/runtime/context-helpers.d.ts.map +1 -1
  635. package/dist/src/runtime/context-helpers.js +7 -1
  636. package/dist/src/runtime/context-helpers.js.map +1 -1
  637. package/dist/src/runtime/delta-executor.d.ts +30 -1
  638. package/dist/src/runtime/delta-executor.d.ts.map +1 -1
  639. package/dist/src/runtime/delta-executor.js +38 -4
  640. package/dist/src/runtime/delta-executor.js.map +1 -1
  641. package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -1
  642. package/dist/src/runtime/emit/add-constraint.js +38 -5
  643. package/dist/src/runtime/emit/add-constraint.js.map +1 -1
  644. package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
  645. package/dist/src/runtime/emit/aggregate.js +10 -8
  646. package/dist/src/runtime/emit/aggregate.js.map +1 -1
  647. package/dist/src/runtime/emit/alter-table.d.ts +1 -1
  648. package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
  649. package/dist/src/runtime/emit/alter-table.js +664 -108
  650. package/dist/src/runtime/emit/alter-table.js.map +1 -1
  651. package/dist/src/runtime/emit/analyze.d.ts.map +1 -1
  652. package/dist/src/runtime/emit/analyze.js +2 -1
  653. package/dist/src/runtime/emit/analyze.js.map +1 -1
  654. package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -1
  655. package/dist/src/runtime/emit/asof-scan.js +24 -9
  656. package/dist/src/runtime/emit/asof-scan.js.map +1 -1
  657. package/dist/src/runtime/emit/asserted-keys.d.ts +13 -0
  658. package/dist/src/runtime/emit/asserted-keys.d.ts.map +1 -0
  659. package/dist/src/runtime/emit/asserted-keys.js +13 -0
  660. package/dist/src/runtime/emit/asserted-keys.js.map +1 -0
  661. package/dist/src/runtime/emit/between.d.ts.map +1 -1
  662. package/dist/src/runtime/emit/between.js +24 -19
  663. package/dist/src/runtime/emit/between.js.map +1 -1
  664. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  665. package/dist/src/runtime/emit/binary.js +24 -36
  666. package/dist/src/runtime/emit/binary.js.map +1 -1
  667. package/dist/src/runtime/emit/block.d.ts.map +1 -1
  668. package/dist/src/runtime/emit/block.js +11 -2
  669. package/dist/src/runtime/emit/block.js.map +1 -1
  670. package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
  671. package/dist/src/runtime/emit/bloom-join.js +12 -4
  672. package/dist/src/runtime/emit/bloom-join.js.map +1 -1
  673. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
  674. package/dist/src/runtime/emit/constraint-check.js +50 -1
  675. package/dist/src/runtime/emit/constraint-check.js.map +1 -1
  676. package/dist/src/runtime/emit/create-table.d.ts.map +1 -1
  677. package/dist/src/runtime/emit/create-table.js +8 -0
  678. package/dist/src/runtime/emit/create-table.js.map +1 -1
  679. package/dist/src/runtime/emit/create-view.d.ts.map +1 -1
  680. package/dist/src/runtime/emit/create-view.js +16 -1
  681. package/dist/src/runtime/emit/create-view.js.map +1 -1
  682. package/dist/src/runtime/emit/delete.d.ts.map +1 -1
  683. package/dist/src/runtime/emit/delete.js +15 -5
  684. package/dist/src/runtime/emit/delete.js.map +1 -1
  685. package/dist/src/runtime/emit/dml-executor.d.ts +27 -0
  686. package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
  687. package/dist/src/runtime/emit/dml-executor.js +413 -193
  688. package/dist/src/runtime/emit/dml-executor.js.map +1 -1
  689. package/dist/src/runtime/emit/drop-table.d.ts.map +1 -1
  690. package/dist/src/runtime/emit/drop-table.js +10 -0
  691. package/dist/src/runtime/emit/drop-table.js.map +1 -1
  692. package/dist/src/runtime/emit/drop-view.d.ts.map +1 -1
  693. package/dist/src/runtime/emit/drop-view.js +17 -0
  694. package/dist/src/runtime/emit/drop-view.js.map +1 -1
  695. package/dist/src/runtime/emit/envelope-scan.d.ts +13 -0
  696. package/dist/src/runtime/emit/envelope-scan.d.ts.map +1 -0
  697. package/dist/src/runtime/emit/envelope-scan.js +22 -0
  698. package/dist/src/runtime/emit/envelope-scan.js.map +1 -0
  699. package/dist/src/runtime/emit/join.d.ts +10 -2
  700. package/dist/src/runtime/emit/join.d.ts.map +1 -1
  701. package/dist/src/runtime/emit/join.js +128 -38
  702. package/dist/src/runtime/emit/join.js.map +1 -1
  703. package/dist/src/runtime/emit/lens-auxiliary-access.d.ts +16 -0
  704. package/dist/src/runtime/emit/lens-auxiliary-access.d.ts.map +1 -0
  705. package/dist/src/runtime/emit/lens-auxiliary-access.js +16 -0
  706. package/dist/src/runtime/emit/lens-auxiliary-access.js.map +1 -0
  707. package/dist/src/runtime/emit/materialized-view-helpers.d.ts +640 -0
  708. package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -0
  709. package/dist/src/runtime/emit/materialized-view-helpers.js +2576 -0
  710. package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -0
  711. package/dist/src/runtime/emit/materialized-view.d.ts +31 -0
  712. package/dist/src/runtime/emit/materialized-view.d.ts.map +1 -0
  713. package/dist/src/runtime/emit/materialized-view.js +187 -0
  714. package/dist/src/runtime/emit/materialized-view.js.map +1 -0
  715. package/dist/src/runtime/emit/merge-join.d.ts.map +1 -1
  716. package/dist/src/runtime/emit/merge-join.js +19 -5
  717. package/dist/src/runtime/emit/merge-join.js.map +1 -1
  718. package/dist/src/runtime/emit/project.d.ts.map +1 -1
  719. package/dist/src/runtime/emit/project.js +10 -5
  720. package/dist/src/runtime/emit/project.js.map +1 -1
  721. package/dist/src/runtime/emit/schema-declarative.d.ts +1 -0
  722. package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
  723. package/dist/src/runtime/emit/schema-declarative.js +101 -5
  724. package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
  725. package/dist/src/runtime/emit/set-object-tags.d.ts +16 -0
  726. package/dist/src/runtime/emit/set-object-tags.d.ts.map +1 -0
  727. package/dist/src/runtime/emit/set-object-tags.js +57 -0
  728. package/dist/src/runtime/emit/set-object-tags.js.map +1 -0
  729. package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
  730. package/dist/src/runtime/emit/set-operation.js +140 -24
  731. package/dist/src/runtime/emit/set-operation.js.map +1 -1
  732. package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
  733. package/dist/src/runtime/emit/subquery.js +110 -5
  734. package/dist/src/runtime/emit/subquery.js.map +1 -1
  735. package/dist/src/runtime/emit/unary.d.ts.map +1 -1
  736. package/dist/src/runtime/emit/unary.js +34 -6
  737. package/dist/src/runtime/emit/unary.js.map +1 -1
  738. package/dist/src/runtime/emit/view-mutation.d.ts +70 -0
  739. package/dist/src/runtime/emit/view-mutation.d.ts.map +1 -0
  740. package/dist/src/runtime/emit/view-mutation.js +299 -0
  741. package/dist/src/runtime/emit/view-mutation.js.map +1 -0
  742. package/dist/src/runtime/emit/window.js +29 -5
  743. package/dist/src/runtime/emit/window.js.map +1 -1
  744. package/dist/src/runtime/foreign-key-actions.d.ts +66 -3
  745. package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
  746. package/dist/src/runtime/foreign-key-actions.js +580 -172
  747. package/dist/src/runtime/foreign-key-actions.js.map +1 -1
  748. package/dist/src/runtime/parallel-driver.d.ts +4 -1
  749. package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
  750. package/dist/src/runtime/parallel-driver.js +5 -1
  751. package/dist/src/runtime/parallel-driver.js.map +1 -1
  752. package/dist/src/runtime/register.d.ts.map +1 -1
  753. package/dist/src/runtime/register.js +17 -1
  754. package/dist/src/runtime/register.js.map +1 -1
  755. package/dist/src/runtime/types.d.ts +10 -0
  756. package/dist/src/runtime/types.d.ts.map +1 -1
  757. package/dist/src/runtime/types.js.map +1 -1
  758. package/dist/src/schema/basis-backfill.d.ts +63 -0
  759. package/dist/src/schema/basis-backfill.d.ts.map +1 -0
  760. package/dist/src/schema/basis-backfill.js +161 -0
  761. package/dist/src/schema/basis-backfill.js.map +1 -0
  762. package/dist/src/schema/catalog.d.ts +115 -1
  763. package/dist/src/schema/catalog.d.ts.map +1 -1
  764. package/dist/src/schema/catalog.js +249 -22
  765. package/dist/src/schema/catalog.js.map +1 -1
  766. package/dist/src/schema/change-events.d.ts +42 -1
  767. package/dist/src/schema/change-events.d.ts.map +1 -1
  768. package/dist/src/schema/change-events.js.map +1 -1
  769. package/dist/src/schema/column.d.ts +16 -0
  770. package/dist/src/schema/column.d.ts.map +1 -1
  771. package/dist/src/schema/column.js.map +1 -1
  772. package/dist/src/schema/constraint-builder.d.ts +182 -0
  773. package/dist/src/schema/constraint-builder.d.ts.map +1 -0
  774. package/dist/src/schema/constraint-builder.js +424 -0
  775. package/dist/src/schema/constraint-builder.js.map +1 -0
  776. package/dist/src/schema/ddl-generator.d.ts +86 -1
  777. package/dist/src/schema/ddl-generator.d.ts.map +1 -1
  778. package/dist/src/schema/ddl-generator.js +316 -20
  779. package/dist/src/schema/ddl-generator.js.map +1 -1
  780. package/dist/src/schema/declared-schema-manager.d.ts +51 -0
  781. package/dist/src/schema/declared-schema-manager.d.ts.map +1 -1
  782. package/dist/src/schema/declared-schema-manager.js +61 -0
  783. package/dist/src/schema/declared-schema-manager.js.map +1 -1
  784. package/dist/src/schema/derivation.d.ts +106 -0
  785. package/dist/src/schema/derivation.d.ts.map +1 -0
  786. package/dist/src/schema/derivation.js +25 -0
  787. package/dist/src/schema/derivation.js.map +1 -0
  788. package/dist/src/schema/function.d.ts +13 -0
  789. package/dist/src/schema/function.d.ts.map +1 -1
  790. package/dist/src/schema/function.js.map +1 -1
  791. package/dist/src/schema/lens-ack.d.ts +90 -0
  792. package/dist/src/schema/lens-ack.d.ts.map +1 -0
  793. package/dist/src/schema/lens-ack.js +361 -0
  794. package/dist/src/schema/lens-ack.js.map +1 -0
  795. package/dist/src/schema/lens-compiler.d.ts +62 -0
  796. package/dist/src/schema/lens-compiler.d.ts.map +1 -0
  797. package/dist/src/schema/lens-compiler.js +1594 -0
  798. package/dist/src/schema/lens-compiler.js.map +1 -0
  799. package/dist/src/schema/lens-fk-discovery.d.ts +175 -0
  800. package/dist/src/schema/lens-fk-discovery.d.ts.map +1 -0
  801. package/dist/src/schema/lens-fk-discovery.js +336 -0
  802. package/dist/src/schema/lens-fk-discovery.js.map +1 -0
  803. package/dist/src/schema/lens-prover.d.ts +336 -0
  804. package/dist/src/schema/lens-prover.d.ts.map +1 -0
  805. package/dist/src/schema/lens-prover.js +1988 -0
  806. package/dist/src/schema/lens-prover.js.map +1 -0
  807. package/dist/src/schema/lens.d.ts +254 -0
  808. package/dist/src/schema/lens.d.ts.map +1 -0
  809. package/dist/src/schema/lens.js +21 -0
  810. package/dist/src/schema/lens.js.map +1 -0
  811. package/dist/src/schema/manager.d.ts +676 -18
  812. package/dist/src/schema/manager.d.ts.map +1 -1
  813. package/dist/src/schema/manager.js +1573 -238
  814. package/dist/src/schema/manager.js.map +1 -1
  815. package/dist/src/schema/mapping-advertisement-tags.d.ts +39 -0
  816. package/dist/src/schema/mapping-advertisement-tags.d.ts.map +1 -0
  817. package/dist/src/schema/mapping-advertisement-tags.js +216 -0
  818. package/dist/src/schema/mapping-advertisement-tags.js.map +1 -0
  819. package/dist/src/schema/rename-rewriter.d.ts +45 -4
  820. package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
  821. package/dist/src/schema/rename-rewriter.js +412 -19
  822. package/dist/src/schema/rename-rewriter.js.map +1 -1
  823. package/dist/src/schema/reserved-tags-policy.d.ts +32 -0
  824. package/dist/src/schema/reserved-tags-policy.d.ts.map +1 -0
  825. package/dist/src/schema/reserved-tags-policy.js +34 -0
  826. package/dist/src/schema/reserved-tags-policy.js.map +1 -0
  827. package/dist/src/schema/reserved-tags.d.ts +170 -0
  828. package/dist/src/schema/reserved-tags.d.ts.map +1 -0
  829. package/dist/src/schema/reserved-tags.js +507 -0
  830. package/dist/src/schema/reserved-tags.js.map +1 -0
  831. package/dist/src/schema/schema-differ.d.ts +158 -2
  832. package/dist/src/schema/schema-differ.d.ts.map +1 -1
  833. package/dist/src/schema/schema-differ.js +1460 -78
  834. package/dist/src/schema/schema-differ.js.map +1 -1
  835. package/dist/src/schema/schema-hasher.d.ts +8 -3
  836. package/dist/src/schema/schema-hasher.d.ts.map +1 -1
  837. package/dist/src/schema/schema-hasher.js +22 -2
  838. package/dist/src/schema/schema-hasher.js.map +1 -1
  839. package/dist/src/schema/schema.d.ts +25 -1
  840. package/dist/src/schema/schema.d.ts.map +1 -1
  841. package/dist/src/schema/schema.js +36 -2
  842. package/dist/src/schema/schema.js.map +1 -1
  843. package/dist/src/schema/table.d.ts +259 -10
  844. package/dist/src/schema/table.d.ts.map +1 -1
  845. package/dist/src/schema/table.js +309 -26
  846. package/dist/src/schema/table.js.map +1 -1
  847. package/dist/src/schema/unique-enforcement.d.ts +78 -0
  848. package/dist/src/schema/unique-enforcement.d.ts.map +1 -0
  849. package/dist/src/schema/unique-enforcement.js +93 -0
  850. package/dist/src/schema/unique-enforcement.js.map +1 -0
  851. package/dist/src/schema/view.d.ts +83 -2
  852. package/dist/src/schema/view.d.ts.map +1 -1
  853. package/dist/src/schema/view.js +67 -1
  854. package/dist/src/schema/view.js.map +1 -1
  855. package/dist/src/schema/window-function.d.ts +9 -1
  856. package/dist/src/schema/window-function.d.ts.map +1 -1
  857. package/dist/src/schema/window-function.js.map +1 -1
  858. package/dist/src/types/temporal-types.d.ts.map +1 -1
  859. package/dist/src/types/temporal-types.js +71 -36
  860. package/dist/src/types/temporal-types.js.map +1 -1
  861. package/dist/src/util/comparison.d.ts +24 -0
  862. package/dist/src/util/comparison.d.ts.map +1 -1
  863. package/dist/src/util/comparison.js +34 -0
  864. package/dist/src/util/comparison.js.map +1 -1
  865. package/dist/src/util/mutation-statement.d.ts.map +1 -1
  866. package/dist/src/util/mutation-statement.js +4 -1
  867. package/dist/src/util/mutation-statement.js.map +1 -1
  868. package/dist/src/util/serialization.d.ts +9 -0
  869. package/dist/src/util/serialization.d.ts.map +1 -1
  870. package/dist/src/util/serialization.js +26 -0
  871. package/dist/src/util/serialization.js.map +1 -1
  872. package/dist/src/vtab/backing-host.d.ts +286 -0
  873. package/dist/src/vtab/backing-host.d.ts.map +1 -0
  874. package/dist/src/vtab/backing-host.js +118 -0
  875. package/dist/src/vtab/backing-host.js.map +1 -0
  876. package/dist/src/vtab/best-access-plan.d.ts +21 -0
  877. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  878. package/dist/src/vtab/best-access-plan.js.map +1 -1
  879. package/dist/src/vtab/capabilities.d.ts +5 -5
  880. package/dist/src/vtab/capabilities.d.ts.map +1 -1
  881. package/dist/src/vtab/mapping-advertisement.d.ts +163 -0
  882. package/dist/src/vtab/mapping-advertisement.d.ts.map +1 -0
  883. package/dist/src/vtab/mapping-advertisement.js +2 -0
  884. package/dist/src/vtab/mapping-advertisement.js.map +1 -0
  885. package/dist/src/vtab/memory/index.d.ts +64 -4
  886. package/dist/src/vtab/memory/index.d.ts.map +1 -1
  887. package/dist/src/vtab/memory/index.js +119 -12
  888. package/dist/src/vtab/memory/index.js.map +1 -1
  889. package/dist/src/vtab/memory/layer/base.d.ts +38 -1
  890. package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
  891. package/dist/src/vtab/memory/layer/base.js +112 -24
  892. package/dist/src/vtab/memory/layer/base.js.map +1 -1
  893. package/dist/src/vtab/memory/layer/manager.d.ts +291 -4
  894. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  895. package/dist/src/vtab/memory/layer/manager.js +1050 -91
  896. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  897. package/dist/src/vtab/memory/layer/plan-filter.d.ts.map +1 -1
  898. package/dist/src/vtab/memory/layer/plan-filter.js +35 -6
  899. package/dist/src/vtab/memory/layer/plan-filter.js.map +1 -1
  900. package/dist/src/vtab/memory/layer/scan-layer.d.ts.map +1 -1
  901. package/dist/src/vtab/memory/layer/scan-layer.js +66 -14
  902. package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
  903. package/dist/src/vtab/memory/layer/scan-plan.d.ts +14 -0
  904. package/dist/src/vtab/memory/layer/scan-plan.d.ts.map +1 -1
  905. package/dist/src/vtab/memory/layer/scan-plan.js +27 -4
  906. package/dist/src/vtab/memory/layer/scan-plan.js.map +1 -1
  907. package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
  908. package/dist/src/vtab/memory/layer/transaction.js +5 -1
  909. package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
  910. package/dist/src/vtab/memory/module.d.ts +17 -0
  911. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  912. package/dist/src/vtab/memory/module.js +82 -3
  913. package/dist/src/vtab/memory/module.js.map +1 -1
  914. package/dist/src/vtab/memory/table.d.ts.map +1 -1
  915. package/dist/src/vtab/memory/table.js +15 -5
  916. package/dist/src/vtab/memory/table.js.map +1 -1
  917. package/dist/src/vtab/memory/types.d.ts +20 -2
  918. package/dist/src/vtab/memory/types.d.ts.map +1 -1
  919. package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
  920. package/dist/src/vtab/memory/utils/predicate.js +46 -24
  921. package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
  922. package/dist/src/vtab/memory/utils/primary-key-encode.d.ts +31 -0
  923. package/dist/src/vtab/memory/utils/primary-key-encode.d.ts.map +1 -0
  924. package/dist/src/vtab/memory/utils/primary-key-encode.js +101 -0
  925. package/dist/src/vtab/memory/utils/primary-key-encode.js.map +1 -0
  926. package/dist/src/vtab/memory/utils/primary-key.d.ts +8 -0
  927. package/dist/src/vtab/memory/utils/primary-key.d.ts.map +1 -1
  928. package/dist/src/vtab/memory/utils/primary-key.js +12 -5
  929. package/dist/src/vtab/memory/utils/primary-key.js.map +1 -1
  930. package/dist/src/vtab/module.d.ts +203 -4
  931. package/dist/src/vtab/module.d.ts.map +1 -1
  932. package/dist/src/vtab/table.d.ts +9 -0
  933. package/dist/src/vtab/table.d.ts.map +1 -1
  934. package/dist/src/vtab/table.js.map +1 -1
  935. package/package.json +6 -5
@@ -0,0 +1,1081 @@
1
+ /**
2
+ * Query-rewrite matcher — the read-side dual of the coverage prover. It
3
+ * recognizes when an *arbitrary* scan-projection-filter query fragment (one that
4
+ * never names a materialized view) is **answered from** a covering MV, so the
5
+ * optimizer can scan the MV's backing table with a bounded residual instead of
6
+ * recomputing the body against the base tables.
7
+ *
8
+ * Distinct from `coverage-prover.ts` (which proves a *base-table UNIQUE
9
+ * constraint* is covered, on the write/enforcement path) but sharing its
10
+ * entailment vocabulary: `recognizeConjunctiveClauses` / `guardClausesEntail`
11
+ * (`partial-unique-extraction.ts`). The question answered here is **output-relation
12
+ * subsumption**: does the MV's stored output relation contain a superset (re-
13
+ * coverable via a bounded residual) of the rows the fragment produces, keyed so
14
+ * the residual recovers exactly the fragment's output?
15
+ *
16
+ * Soundness contract (mirrors the coverage prover exactly): **a false NotMatch
17
+ * only forgoes a speedup; a false Match returns wrong rows.** Every check forgoes
18
+ * the rewrite on doubt. The pre-existing recompute-over-base path is correct by
19
+ * construction; the rule only ever replaces it with a provably row-equivalent
20
+ * plan, so the rewrite is non-regressing.
21
+ *
22
+ * This phase delivers the **projection + filter subsumption** shape only.
23
+ * Aggregate rollup (`mv-query-rewrite-aggregate-rollup`) and join subsumption
24
+ * (`mv-query-rewrite-join-subsumption`) are pure additions to this matcher.
25
+ *
26
+ * ## Where the predicates come from (the pristine-fragment requirement)
27
+ *
28
+ * The fragment's WHERE is read from the live plan's `FilterNode` predicate (its
29
+ * `.expression` AST), and the MV's WHERE from `mv.derivation.selectAst.where`. Reading the
30
+ * fragment WHERE from the plan is only sound while the predicate is still an
31
+ * explicit `FilterNode` above the table access — *before* predicate-pushdown
32
+ * absorbs it into a range-bounded scan (where the matcher could no longer see it
33
+ * and would falsely treat the fragment as unfiltered). The rule that drives this
34
+ * matcher therefore fires in the **Structural rewrite pass, before grow-retrieve /
35
+ * predicate-pushdown**, where the fragment is the pristine
36
+ * `Project(Filter?(Retrieve(TableReference)))`. The shape walk additionally
37
+ * rejects any range-bounded physical scan (`SeqScan`/`IndexScan` with
38
+ * `rangeBoundedOn`, or an `IndexSeek`/`TableSeek`) as `'shape'` — defense in depth
39
+ * should an absorbed predicate ever reach the walk by another path.
40
+ *
41
+ * ## Why `.expression` recognition is sound under constant folding
42
+ *
43
+ * A scalar plan node retains its originating AST in `.expression`. Constant
44
+ * folding (which runs before the Structural pass) may make the *plan* more
45
+ * specific than its `.expression` (e.g. folding `1+1` → `2` while `.expression`
46
+ * still reads `amt > 1+1`). Such a divergence only ever makes a clause
47
+ * *unrecognized* (`literalValue` of a non-literal AST returns undefined), which is
48
+ * a conservative NotMatch — it never fabricates a recognized clause weaker than
49
+ * what the plan computes, so it cannot produce a false Match.
50
+ */
51
+ import { isRelationalNode } from '../nodes/plan-node.js';
52
+ import { ProjectNode } from '../nodes/project-node.js';
53
+ import { FilterNode } from '../nodes/filter.js';
54
+ import { RetrieveNode } from '../nodes/retrieve-node.js';
55
+ import { AliasNode } from '../nodes/alias-node.js';
56
+ import { TableReferenceNode, ColumnReferenceNode } from '../nodes/reference.js';
57
+ import { SeqScanNode, IndexScanNode } from '../nodes/table-access-nodes.js';
58
+ import { BinaryOpNode } from '../nodes/scalar.js';
59
+ import { AggregateNode } from '../nodes/aggregate-node.js';
60
+ import { AggregateFunctionCallNode } from '../nodes/aggregate-function.js';
61
+ import { JoinNode } from '../nodes/join-node.js';
62
+ import { CapabilityDetectors } from '../framework/characteristics.js';
63
+ import { recognizeConjunctiveClauses, guardClausesEntail } from './partial-unique-extraction.js';
64
+ import { proveOneToOneJoin, pureJoinEquiAttrPairs } from './coverage-prover.js';
65
+ import { containsNonDeterministicCall } from './check-extraction.js';
66
+ function fail(reason) {
67
+ return { match: undefined, reason };
68
+ }
69
+ /**
70
+ * Recognize a query fragment rooted at a `ProjectNode` as a single-source
71
+ * scan-project-filter chain. Walks `Project → Filter? → {Retrieve|Alias|full
72
+ * SeqScan/IndexScan}* → TableReference`. Any other node (Sort/Limit/Distinct/
73
+ * Aggregate/Join/SetOp, or a row-reducing seek / range-bounded scan) ⇒ `'shape'`.
74
+ */
75
+ export function analyzeQueryFragment(root) {
76
+ if (!(root instanceof ProjectNode))
77
+ return { ok: false, reason: 'shape' };
78
+ // Descend the source chain, collecting WHERE conjuncts, down to the base table.
79
+ const walk = walkScanFilterChain(root.source);
80
+ if (!walk)
81
+ return { ok: false, reason: 'shape' };
82
+ const { tableRef, conjuncts } = walk;
83
+ // Each output column must be a bare column reference into the base table; a
84
+ // computed output is unrecoverable from the backing in v1 (missing-column).
85
+ const outputs = root.projections.map((proj, i) => ({
86
+ attrId: root.getAttributes()[i].id,
87
+ baseCol: proj.node instanceof ColumnReferenceNode ? proj.node.columnIndex : undefined,
88
+ }));
89
+ return {
90
+ ok: true,
91
+ shape: { project: root, tableRef, baseTable: tableRef.tableSchema, outputs, conjuncts },
92
+ };
93
+ }
94
+ /**
95
+ * Walk a single-source scan-project-filter source chain `Filter? → {Retrieve|Alias|
96
+ * full SeqScan/IndexScan}* → TableReference`, collecting top-level AND-split WHERE
97
+ * conjuncts (plan-node level). Returns the leaf `TableReferenceNode` and conjuncts,
98
+ * or `undefined` for any other node (a row-reducing seek / range-bounded scan,
99
+ * Sort/Limit/Distinct/Aggregate/Join/SetOp). Shared by the projection-filter and
100
+ * aggregate arms so the recognized source shape is identical.
101
+ */
102
+ function walkScanFilterChain(start) {
103
+ const conjuncts = [];
104
+ let node = start;
105
+ let tableRef;
106
+ while (node) {
107
+ if (node instanceof TableReferenceNode) {
108
+ tableRef = node;
109
+ break;
110
+ }
111
+ if (node instanceof FilterNode) {
112
+ splitConjuncts(node.predicate, conjuncts);
113
+ node = node.source;
114
+ continue;
115
+ }
116
+ if (node instanceof RetrieveNode || node instanceof AliasNode) {
117
+ node = singleRelation(node);
118
+ if (!node)
119
+ return undefined;
120
+ continue;
121
+ }
122
+ // A full (non-range-bounded) physical scan is a row-preserving pass-through;
123
+ // a range-bounded scan has absorbed a predicate we can no longer see (sound
124
+ // only because the rule fires before access selection — this is defensive).
125
+ if (node instanceof SeqScanNode || node instanceof IndexScanNode) {
126
+ if (node.rangeBoundedOn)
127
+ return undefined;
128
+ node = node.source;
129
+ continue;
130
+ }
131
+ return undefined;
132
+ }
133
+ if (!tableRef)
134
+ return undefined;
135
+ return { tableRef, conjuncts };
136
+ }
137
+ /**
138
+ * Decide whether `mv` (backed by `backing`) answers the fragment `shape`. See the
139
+ * module doc for the soundness contract. `isDeterministic` probes the function
140
+ * registry for the determinism gate (a registered MV is already deterministic by
141
+ * construction — the create gate rejects non-deterministic bodies — so this is
142
+ * defense in depth).
143
+ */
144
+ export function matchFragmentToMv(shape, mv, backing, isDeterministic) {
145
+ const baseTable = shape.baseTable;
146
+ // ---- Candidate gates (a false-positive here only forgoes a speedup). ----
147
+ // Stale: the backing is an unmaintained snapshot — never read it.
148
+ if (mv.derivation.stale === true)
149
+ return fail('no-candidate');
150
+ // Registered + has a live backing table.
151
+ if (!backing)
152
+ return fail('no-candidate');
153
+ // Deterministic body: a random()/now()/volatile-UDF body cannot substitute for
154
+ // live recomputation. Reuses the function-registry determinism metadata.
155
+ if (mvBodyHasNonDeterminism(mv.derivation.selectAst, isDeterministic))
156
+ return fail('no-candidate');
157
+ // Source-schema sanity: the MV must read exactly the one base table the
158
+ // fragment reads (single-source v1). `sourceTables` dedups, so a self-join
159
+ // collapses to one entry — the AST single-`table` FROM check below rejects it.
160
+ const qualified = `${baseTable.schemaName}.${baseTable.name}`.toLowerCase();
161
+ if (mv.derivation.sourceTables.length !== 1 || mv.derivation.sourceTables[0] !== qualified) {
162
+ return fail('source-mismatch');
163
+ }
164
+ // ---- MV body shape (AST): single-source projection + optional filter. ----
165
+ if (mv.derivation.selectAst.type !== 'select')
166
+ return fail('shape');
167
+ const sel = mv.derivation.selectAst;
168
+ if ((sel.groupBy && sel.groupBy.length > 0) || sel.having || sel.distinct
169
+ || sel.limit !== undefined || sel.offset !== undefined
170
+ || sel.union || sel.compound) {
171
+ return fail('shape');
172
+ }
173
+ if (!sel.from || sel.from.length !== 1 || sel.from[0].type !== 'table')
174
+ return fail('shape');
175
+ // ---- MV projection → base-column mapping (which backing column holds which
176
+ // base column). A computed select item leaves that backing column unmapped
177
+ // (it cannot answer a passthrough need). ----
178
+ const baseColOfBackingCol = mvProjectionBaseCols(sel.columns, baseTable);
179
+ if (!baseColOfBackingCol)
180
+ return fail('shape');
181
+ const backingColOfBaseCol = new Map();
182
+ baseColOfBackingCol.forEach((baseCol, backingCol) => {
183
+ if (baseCol !== undefined && !backingColOfBaseCol.has(baseCol)) {
184
+ backingColOfBaseCol.set(baseCol, backingCol);
185
+ }
186
+ });
187
+ // ---- Predicate entailment (containment): the fragment's row set must be a
188
+ // subset of the MV's, i.e. the MV's WHERE `P_mv` is entailed by the
189
+ // fragment's WHERE `P_q` (every MV-required clause is implied by the
190
+ // query). The residual is the conjunction of `P_q` clauses not already
191
+ // entailed by `P_mv`. ----
192
+ const mvClauses = sel.where ? recognizeConjunctiveClauses(sel.where, baseTable) : [];
193
+ if (mvClauses === undefined)
194
+ return fail('predicate-not-entailed');
195
+ const queryClauses = [];
196
+ const residualConjuncts = [];
197
+ const residualClauses = [];
198
+ for (const conjunct of shape.conjuncts) {
199
+ const expr = conjunctExpression(conjunct);
200
+ const clauses = expr ? recognizeConjunctiveClauses(expr, baseTable) : undefined;
201
+ if (!clauses)
202
+ return fail('predicate-not-entailed');
203
+ queryClauses.push(...clauses);
204
+ // A conjunct already entailed by `P_mv` holds for every backing row, so it
205
+ // is dropped from the residual; the rest become the residual filter.
206
+ if (!guardClausesEntail(mvClauses, clauses)) {
207
+ residualConjuncts.push(conjunct);
208
+ residualClauses.push(...clauses);
209
+ }
210
+ }
211
+ if (!guardClausesEntail(queryClauses, mvClauses))
212
+ return fail('predicate-not-entailed');
213
+ // ---- Projection coverage: every fragment output column must be a base column
214
+ // the MV projects. ----
215
+ const outputColumnMap = [];
216
+ for (const out of shape.outputs) {
217
+ if (out.baseCol === undefined)
218
+ return fail('missing-column');
219
+ const backingCol = backingColOfBaseCol.get(out.baseCol);
220
+ if (backingCol === undefined)
221
+ return fail('missing-column');
222
+ outputColumnMap.push({ attrId: out.attrId, backingCol });
223
+ }
224
+ // ---- Residual coverage: every base column the residual references must also be
225
+ // a backing column (so the residual filter can be applied on the scan). ----
226
+ for (const clause of residualClauses) {
227
+ for (const col of clauseColumns(clause)) {
228
+ if (!backingColOfBaseCol.has(col))
229
+ return fail('missing-column');
230
+ }
231
+ }
232
+ return {
233
+ match: {
234
+ mv,
235
+ backing,
236
+ residualClauses,
237
+ residualConjuncts,
238
+ outputColumnMap,
239
+ backingColOfBaseCol,
240
+ },
241
+ };
242
+ }
243
+ /**
244
+ * Convenience entry point (used by the unit tests): analyze `root` as a fragment
245
+ * and, on success, match it against `mv`. Returns the fragment-analysis failure
246
+ * reason when `root` is not a recognizable scan-project-filter chain.
247
+ */
248
+ export function matchMaterializedViewRewrite(root, mv, backing, isDeterministic) {
249
+ const frag = analyzeQueryFragment(root);
250
+ if (!frag.ok)
251
+ return fail(frag.reason);
252
+ return matchFragmentToMv(frag.shape, mv, backing, isDeterministic);
253
+ }
254
+ /**
255
+ * Recognize a query fragment rooted at a logical {@link AggregateNode} (the shape
256
+ * the optimizer presents in the Structural pass, before physical aggregate
257
+ * selection) as a single-source aggregate over a scan-filter chain. Requires
258
+ * **bare-column** GROUP BY expressions and aggregate arguments — a computed group
259
+ * key or aggregate argument (`group by d+1`, `sum(amt*2)`, `group_concat(x, ',')`)
260
+ * is unrecoverable from a stored MV column in v1 ⇒ `aggregate-shape`. Mirrors the
261
+ * row-time aggregate eligibility gate, which likewise requires bare group columns.
262
+ */
263
+ export function analyzeAggregateFragment(root) {
264
+ if (!(root instanceof AggregateNode))
265
+ return { ok: false, reason: 'aggregate-shape' };
266
+ const walk = walkScanFilterChain(root.source);
267
+ if (!walk)
268
+ return { ok: false, reason: 'aggregate-shape' };
269
+ const { tableRef, conjuncts } = walk;
270
+ const attrs = root.getAttributes();
271
+ const groupCount = root.groupBy.length;
272
+ // GROUP BY key: every expression must be a bare column reference into the base table.
273
+ const groupBaseCols = [];
274
+ for (const gb of root.groupBy) {
275
+ if (!(gb instanceof ColumnReferenceNode))
276
+ return { ok: false, reason: 'aggregate-shape' };
277
+ groupBaseCols.push(gb.columnIndex);
278
+ }
279
+ // Aggregates: each must be an aggregate function over `count(*)` (no arg) or a
280
+ // single bare base column.
281
+ const aggregates = [];
282
+ for (let i = 0; i < root.aggregates.length; i++) {
283
+ const expr = root.aggregates[i].expression;
284
+ if (!(expr instanceof AggregateFunctionCallNode))
285
+ return { ok: false, reason: 'aggregate-shape' };
286
+ let argBaseCol;
287
+ if (expr.args.length === 0) {
288
+ argBaseCol = undefined; // count(*)
289
+ }
290
+ else if (expr.args.length === 1 && expr.args[0] instanceof ColumnReferenceNode) {
291
+ argBaseCol = expr.args[0].columnIndex;
292
+ }
293
+ else {
294
+ return { ok: false, reason: 'aggregate-shape' }; // computed / multi-arg argument
295
+ }
296
+ aggregates.push({
297
+ funcName: expr.functionName.toLowerCase(),
298
+ argBaseCol,
299
+ isDistinct: expr.isDistinct,
300
+ outAttr: attrs[groupCount + i],
301
+ });
302
+ }
303
+ return {
304
+ ok: true,
305
+ shape: {
306
+ aggregateNode: root,
307
+ tableRef,
308
+ baseTable: tableRef.tableSchema,
309
+ groupBaseCols,
310
+ groupOutAttrs: attrs.slice(0, groupCount),
311
+ aggregates,
312
+ conjuncts,
313
+ },
314
+ };
315
+ }
316
+ /**
317
+ * Decide whether the grouped MV `mv` (backed by `backing`) answers the aggregate
318
+ * fragment `shape`. See the arm doc above for the two sub-cases and the soundness
319
+ * contract; every check forgoes on doubt (a false NotMatch only forgoes a speedup).
320
+ */
321
+ export function matchAggregateFragmentToMv(shape, mv, backing, isDeterministic) {
322
+ const baseTable = shape.baseTable;
323
+ // ---- Candidate gates (a false-positive here only forgoes a speedup). ----
324
+ if (mv.derivation.stale === true)
325
+ return fail('no-candidate');
326
+ if (!backing)
327
+ return fail('no-candidate');
328
+ if (mvBodyHasNonDeterminism(mv.derivation.selectAst, isDeterministic))
329
+ return fail('no-candidate');
330
+ const qualified = `${baseTable.schemaName}.${baseTable.name}`.toLowerCase();
331
+ if (mv.derivation.sourceTables.length !== 1 || mv.derivation.sourceTables[0] !== qualified) {
332
+ return fail('source-mismatch');
333
+ }
334
+ // ---- MV body shape: a single-source grouped aggregate, no HAVING/DISTINCT/cap. ----
335
+ if (mv.derivation.selectAst.type !== 'select')
336
+ return fail('aggregate-shape');
337
+ const sel = mv.derivation.selectAst;
338
+ if (!sel.groupBy || sel.groupBy.length === 0)
339
+ return fail('aggregate-shape'); // not a grouped MV
340
+ if (sel.having || sel.distinct || sel.limit !== undefined || sel.offset !== undefined
341
+ || sel.union || sel.compound) {
342
+ return fail('aggregate-shape');
343
+ }
344
+ if (!sel.from || sel.from.length !== 1 || sel.from[0].type !== 'table')
345
+ return fail('aggregate-shape');
346
+ // ---- MV group key (base columns) — every GROUP BY expr must be a bare column. ----
347
+ const mvGroupBaseCols = [];
348
+ for (const gb of sel.groupBy) {
349
+ const col = baseColumnOfExpr(gb, baseTable);
350
+ if (col === undefined)
351
+ return fail('aggregate-shape'); // computed MV group key
352
+ mvGroupBaseCols.push(col);
353
+ }
354
+ const mvGroupSet = new Set(mvGroupBaseCols);
355
+ // ---- MV stored columns: group-key passthroughs + stored aggregates. ----
356
+ const stored = analyzeMvStoredColumns(sel.columns, baseTable);
357
+ if (!stored)
358
+ return fail('aggregate-shape');
359
+ // Every MV group-key column must be stored as a backing column (so the backing is
360
+ // addressable by the group key — needed for re-grouping and residual filtering).
361
+ for (const gc of mvGroupBaseCols) {
362
+ if (!stored.groupBackingOfBaseCol.has(gc))
363
+ return fail('missing-column');
364
+ }
365
+ // ---- One-row-per-MV-group witness: the backing's primary key must be exactly the
366
+ // MV group key (as backing columns). This is the schema-level form of
367
+ // `coverage-prover.ts`'s `proveEffectiveKeyUnique` — it certifies the backing
368
+ // is a *set* keyed by the group columns, so the exact-key direct scan returns
369
+ // one row per query group and the rollup re-aggregates a set (not a bag). The
370
+ // backing of a grouped MV is maintained keyed on its group columns, so this
371
+ // holds by construction; the check forgoes if a future shape ever diverges. ----
372
+ if (!backingPkIsGroupKey(backing, mvGroupBaseCols, stored.groupBackingOfBaseCol)) {
373
+ return fail('aggregate-shape');
374
+ }
375
+ // ---- Group-key alignment: query key must be a subset of the MV key. ----
376
+ const queryGroupSet = new Set(shape.groupBaseCols);
377
+ for (const gc of queryGroupSet) {
378
+ if (!mvGroupSet.has(gc))
379
+ return fail('group-key-mismatch');
380
+ }
381
+ const exact = queryGroupSet.size === mvGroupSet.size;
382
+ // Query group-key columns must be stored (to re-group / output them).
383
+ const groupKeyBackingCols = [];
384
+ for (const gc of shape.groupBaseCols) {
385
+ const bc = stored.groupBackingOfBaseCol.get(gc);
386
+ if (bc === undefined)
387
+ return fail('missing-column');
388
+ groupKeyBackingCols.push(bc);
389
+ }
390
+ // `backingColOfBaseCol` exposes only the stored group-key columns. The residual
391
+ // coverage check (below) then forgoes any residual conjunct on a non-group column
392
+ // — exactly the columns the MV has already aggregated away.
393
+ const backingColOfBaseCol = new Map(stored.groupBackingOfBaseCol);
394
+ // ---- Aggregate decomposition: a recipe per fragment aggregate. ----
395
+ const recipes = [];
396
+ const outputColumnMap = [];
397
+ for (const qa of shape.aggregates) {
398
+ const recipe = exact
399
+ ? recipeForExact(qa, stored.storedAggs)
400
+ : recipeForRollup(qa, stored.storedAggs, baseTable);
401
+ if (!recipe)
402
+ return fail('aggregate-not-decomposable');
403
+ recipes.push(recipe);
404
+ if (exact)
405
+ outputColumnMap.push({ attrId: qa.outAttr.id, backingCol: recipe.backingCols[0] });
406
+ }
407
+ // ---- Predicate alignment (identical containment logic to the foundation), with
408
+ // the aggregate-specific gate that every residual conjunct references only
409
+ // MV group-key columns (so it partitions whole MV groups and commutes with
410
+ // the rollup). A residual on a non-group column resolves to a base column
411
+ // absent from `backingColOfBaseCol` ⇒ `missing-column`. ----
412
+ const mvClauses = sel.where ? recognizeConjunctiveClauses(sel.where, baseTable) : [];
413
+ if (mvClauses === undefined)
414
+ return fail('predicate-not-entailed');
415
+ const queryClauses = [];
416
+ const residualConjuncts = [];
417
+ const residualClauses = [];
418
+ for (const conjunct of shape.conjuncts) {
419
+ const expr = conjunctExpression(conjunct);
420
+ const clauses = expr ? recognizeConjunctiveClauses(expr, baseTable) : undefined;
421
+ if (!clauses)
422
+ return fail('predicate-not-entailed');
423
+ queryClauses.push(...clauses);
424
+ if (!guardClausesEntail(mvClauses, clauses)) {
425
+ residualConjuncts.push(conjunct);
426
+ residualClauses.push(...clauses);
427
+ }
428
+ }
429
+ if (!guardClausesEntail(queryClauses, mvClauses))
430
+ return fail('predicate-not-entailed');
431
+ for (const clause of residualClauses) {
432
+ for (const col of clauseColumns(clause)) {
433
+ if (!backingColOfBaseCol.has(col))
434
+ return fail('missing-column');
435
+ }
436
+ }
437
+ // Group-key reorder guard. When the query WHERE constant-pins (`g = 1`, `g is
438
+ // null`) or equates (`g1 = g2`) a group-key column AND there are ≥2 group keys,
439
+ // the base's `rule-groupby-fd-simplification` drops the functionally-determined
440
+ // group column and re-emits it as a picker `min` at a *shifted* output position,
441
+ // changing the result's column ORDER. The rewrite preserves the pristine column
442
+ // order, so the two would diverge — forgo to remain a faithful drop-in. (A single
443
+ // group key is never dropped — the rule keeps ≥1 — and range/IN residuals create
444
+ // no determining FD, so both stay eligible. Checks the full query WHERE, not just
445
+ // the residual: a pin entailed by the MV still drives the base's simplification.)
446
+ if (queryGroupSet.size >= 2 && queryClauses.some(c => clausePinsOrEquatesGroupCol(c, queryGroupSet))) {
447
+ return fail('group-key-pinned');
448
+ }
449
+ // A rollup with a residual is sound: the residual coverage check above admits only
450
+ // conjuncts over MV group-key columns, which partition whole MV groups — so the
451
+ // residual `Filter` on the backing scan keeps or drops each backing group entire,
452
+ // and the re-aggregate over the survivors commutes with it (filtering whole groups
453
+ // pre- vs post-rollup is identical). The rule builds that residual `Filter` on the
454
+ // backing scan before the re-aggregate (the same `buildBackingSource` the exact-key
455
+ // and projection-filter arms use). This shape — `group by k` re-aggregating a
456
+ // composite-PK backing with a `WHERE` on a non-grouped PK column — previously
457
+ // tripped a base streaming-aggregate filter-drop bug, which is now fixed
458
+ // (`streaming-aggregate-stale-group-context-shadows-child-filter`); the equivalence
459
+ // harness covers the rollup+residual shapes as the soundness backstop.
460
+ // ---- Exact-key: assemble the output column map for the group-key passthroughs so
461
+ // the foundation's `buildReplacement` can re-emit the whole row directly. ----
462
+ if (exact) {
463
+ const groupOut = [];
464
+ shape.groupBaseCols.forEach((_gc, i) => {
465
+ groupOut.push({ attrId: shape.groupOutAttrs[i].id, backingCol: groupKeyBackingCols[i] });
466
+ });
467
+ // outputColumnMap currently holds the aggregate outputs; prepend the group outputs
468
+ // so the order matches the fragment's [group…, aggregate…] output order.
469
+ outputColumnMap.unshift(...groupOut);
470
+ }
471
+ const rollup = {
472
+ exact,
473
+ groupKeyBackingCols,
474
+ groupOutAttrs: shape.groupOutAttrs,
475
+ aggregates: recipes,
476
+ };
477
+ return {
478
+ match: {
479
+ mv,
480
+ backing,
481
+ residualClauses,
482
+ residualConjuncts,
483
+ outputColumnMap,
484
+ backingColOfBaseCol,
485
+ rollup,
486
+ },
487
+ };
488
+ }
489
+ /**
490
+ * Convenience entry point (used by the unit tests): analyze `root` as an aggregate
491
+ * fragment and, on success, match it against `mv`.
492
+ */
493
+ export function matchAggregateMaterializedViewRewrite(root, mv, backing, isDeterministic) {
494
+ const frag = analyzeAggregateFragment(root);
495
+ if (!frag.ok)
496
+ return fail(frag.reason);
497
+ return matchAggregateFragmentToMv(frag.shape, mv, backing, isDeterministic);
498
+ }
499
+ /**
500
+ * Recognize a query fragment rooted at a `ProjectNode` whose source descends —
501
+ * through an optional `Filter` (post-join WHERE) and single-source pass-throughs —
502
+ * into a single binary {@link JoinNode} over exactly two distinct base tables. Any
503
+ * other shape (no join, a multi-way join, a non-passthrough node, a row-reducing
504
+ * scan) ⇒ `'shape'`. The fragment is pristine (the rule fires before
505
+ * predicate-pushdown / grow-retrieve), so the join's `ON` condition and the WHERE
506
+ * `Filter` are still explicit.
507
+ */
508
+ export function analyzeJoinQueryFragment(root) {
509
+ if (!(root instanceof ProjectNode))
510
+ return { ok: false, reason: 'shape' };
511
+ const walk = walkToFragmentJoin(root.source);
512
+ if (!walk)
513
+ return { ok: false, reason: 'shape' };
514
+ const { joinNode, conjuncts } = walk;
515
+ // Exactly two distinct base tables under the join (a self-join or a 3-way join
516
+ // is out of scope — the latter is partial-join matching, deferred).
517
+ const tableRefs = collectBaseTableRefs(joinNode);
518
+ if (tableRefs.length !== 2)
519
+ return { ok: false, reason: 'shape' };
520
+ if (qualifiedOf(tableRefs[0].tableSchema) === qualifiedOf(tableRefs[1].tableSchema)) {
521
+ return { ok: false, reason: 'shape' }; // self-join
522
+ }
523
+ return { ok: true, shape: { project: root, joinNode, tableRefs: [tableRefs[0], tableRefs[1]], conjuncts } };
524
+ }
525
+ /**
526
+ * Walk a fragment's `Project.source` down to its single binary join, collecting the
527
+ * post-join WHERE conjuncts. Passes through `Filter` (splitting its predicate),
528
+ * `Retrieve`, and `Alias`; returns `undefined` for any other node (so a Distinct /
529
+ * Aggregate / second join above the first ⇒ NotMatch).
530
+ */
531
+ function walkToFragmentJoin(start) {
532
+ const conjuncts = [];
533
+ let node = start;
534
+ while (node) {
535
+ if (node instanceof JoinNode)
536
+ return { joinNode: node, conjuncts };
537
+ if (node instanceof FilterNode) {
538
+ splitConjuncts(node.predicate, conjuncts);
539
+ node = node.source;
540
+ continue;
541
+ }
542
+ if (node instanceof RetrieveNode || node instanceof AliasNode) {
543
+ node = singleRelation(node);
544
+ if (!node)
545
+ return undefined;
546
+ continue;
547
+ }
548
+ return undefined;
549
+ }
550
+ return undefined;
551
+ }
552
+ /**
553
+ * Decide whether the 1:1-join MV `mv` (optimized body `mvBodyRoot`, backed by
554
+ * `backing`) answers the join fragment `shape`. See the arm doc above for the
555
+ * soundness contract; every check forgoes on doubt.
556
+ *
557
+ * `mvBodyRoot` is the MV body's optimized relational root (the rule plans it
558
+ * suppressed and caches it). When the rule could not plan it, pass `undefined` ⇒
559
+ * `no-candidate`.
560
+ */
561
+ export function matchJoinFragmentToMv(shape, mv, mvBodyRoot, backing, isDeterministic) {
562
+ // ---- Candidate gates (a false-positive here only forgoes a speedup). ----
563
+ if (mv.derivation.stale === true)
564
+ return fail('no-candidate');
565
+ if (!backing)
566
+ return fail('no-candidate');
567
+ if (!mvBodyRoot)
568
+ return fail('no-candidate'); // body did not plan
569
+ if (mvBodyHasNonDeterminism(mv.derivation.selectAst, isDeterministic))
570
+ return fail('no-candidate');
571
+ // ---- Backing alignment: the stored-column map keys each backing column by the
572
+ // MV body's output *position*, which is only sound while the backing columns
573
+ // correspond positionally to the body output (the invariant established when
574
+ // the backing is built from the body). A source `alter` can desynchronize
575
+ // them — `refresh` does not reorder the backing to match a re-planned
576
+ // `select *` body, which interleaves the new column — so a stale mapping would
577
+ // read the wrong backing column or run off its end. Verify positional name
578
+ // alignment up front and forgo (→ correct base recompute) on any mismatch. ----
579
+ if (!backingAlignsWithBody(mvBodyRoot, backing))
580
+ return fail('no-candidate');
581
+ // ---- Source-set match: the MV must read exactly the fragment's two tables. ----
582
+ const qualA = qualifiedOf(shape.tableRefs[0].tableSchema);
583
+ const qualB = qualifiedOf(shape.tableRefs[1].tableSchema);
584
+ const mvSources = new Set(mv.derivation.sourceTables);
585
+ if (mvSources.size !== 2 || !mvSources.has(qualA) || !mvSources.has(qualB)) {
586
+ return fail('source-mismatch');
587
+ }
588
+ // ---- Join equivalence: find a (T, lookup) assignment over which BOTH the
589
+ // fragment and the MV body are provably 1:1, with the same inner/cross join
590
+ // type and the same equi-pairs. A mismatch on any ⇒ NotMatch (shape). ----
591
+ const assignment = findJoinAssignment(shape, mvBodyRoot);
592
+ if (!assignment)
593
+ return fail('shape');
594
+ const { drivingRef, lookupRef, mvDrivingRef, mvLookupRef } = assignment;
595
+ // ---- Stored-column map: each MV backing column (by output position) → the
596
+ // (side, base column) it passes through. A computed MV column is unmapped. ----
597
+ const stored = mvStoredJoinColumns(mvBodyRoot, mvDrivingRef, mvLookupRef);
598
+ // Fragment source attribute id → (side, base column).
599
+ const fragDriving = attrToBaseCol(drivingRef);
600
+ const fragLookup = attrToBaseCol(lookupRef);
601
+ // ---- Projection coverage: every fragment output column must be a bare
602
+ // passthrough of a `T`/`P` column the MV stores. ----
603
+ const outputColumnMap = [];
604
+ const outAttrs = shape.project.getAttributes();
605
+ const projections = shape.project.projections;
606
+ for (let i = 0; i < projections.length; i++) {
607
+ const proj = projections[i];
608
+ if (!(proj.node instanceof ColumnReferenceNode))
609
+ return fail('missing-column'); // computed output
610
+ const backingCol = backingColForAttr(proj.node.attributeId, fragDriving, fragLookup, stored);
611
+ if (backingCol === undefined)
612
+ return fail('missing-column');
613
+ outputColumnMap.push({ attrId: outAttrs[i].id, backingCol });
614
+ }
615
+ // ---- Residual: the MV body has no WHERE (the row-time gate forbids it), so the
616
+ // whole fragment WHERE is residual. Every conjunct must be a subquery-free
617
+ // predicate over stored `T`/`P` columns so it re-binds onto the backing. ----
618
+ const backingColOfSourceAttrId = storedSourceAttrIds(fragDriving, fragLookup, stored);
619
+ for (const conjunct of shape.conjuncts) {
620
+ if (conjunctHasSubquery(conjunct))
621
+ return fail('predicate-not-entailed');
622
+ for (const attrId of conjunctColumnAttrIds(conjunct)) {
623
+ if (!backingColOfSourceAttrId.has(attrId))
624
+ return fail('missing-column');
625
+ }
626
+ }
627
+ return {
628
+ match: {
629
+ mv,
630
+ backing,
631
+ residualClauses: [],
632
+ residualConjuncts: shape.conjuncts,
633
+ outputColumnMap,
634
+ backingColOfBaseCol: new Map(),
635
+ backingColOfSourceAttrId,
636
+ joinInfo: { drivingTable: drivingRef.tableSchema, lookupTable: lookupRef.tableSchema },
637
+ },
638
+ };
639
+ }
640
+ /**
641
+ * Convenience entry point (used by the unit tests): analyze `root` as a join
642
+ * fragment and, on success, match it against `mv` (whose optimized body root is
643
+ * `mvBodyRoot`).
644
+ */
645
+ export function matchJoinMaterializedViewRewrite(root, mv, mvBodyRoot, backing, isDeterministic) {
646
+ const frag = analyzeJoinQueryFragment(root);
647
+ if (!frag.ok)
648
+ return fail(frag.reason);
649
+ return matchJoinFragmentToMv(frag.shape, mv, mvBodyRoot, backing, isDeterministic);
650
+ }
651
+ /**
652
+ * Find a (driving, lookup) assignment of the fragment's two tables over which the
653
+ * fragment join *and* the MV body join are both provably 1:1 (inner/cross),
654
+ * carrying the same equi-pairs in `(driving-col, lookup-col)` terms. Tries each
655
+ * table as the driver; returns the first that discharges every obligation, else
656
+ * `undefined` (⇒ a `shape` NotMatch). A 1:1 FK join determines the driver uniquely,
657
+ * so at most one assignment ever succeeds.
658
+ */
659
+ function findJoinAssignment(shape, mvBodyRoot) {
660
+ const [a, b] = shape.tableRefs;
661
+ for (const [drivingRef, lookupRef] of [[a, b], [b, a]]) {
662
+ const driving = drivingRef.tableSchema;
663
+ // Both joins must be 1:1 over this driver, via an inner/cross top join.
664
+ const fragProof = proveOneToOneJoin(shape.joinNode, driving);
665
+ if (!fragProof.ok || !fragProof.topJoin || !isInnerOrCross(fragProof.topJoin))
666
+ continue;
667
+ const mvProof = proveOneToOneJoin(mvBodyRoot, driving);
668
+ if (!mvProof.ok || !mvProof.topJoin || !isInnerOrCross(mvProof.topJoin))
669
+ continue;
670
+ // Locate the MV body's matching table references (by qualified name).
671
+ const mvDrivingRef = findTableRef(mvBodyRoot, qualifiedOf(driving));
672
+ const mvLookupRef = findTableRef(mvBodyRoot, qualifiedOf(lookupRef.tableSchema));
673
+ if (!mvDrivingRef || !mvLookupRef)
674
+ continue;
675
+ // Same equi-pairs (as a set, in driving→lookup base-column terms).
676
+ const fragPairs = equiPairsByBaseCol(fragProof.topJoin, drivingRef, lookupRef);
677
+ const mvPairs = equiPairsByBaseCol(mvProof.topJoin, mvDrivingRef, mvLookupRef);
678
+ if (!fragPairs || !mvPairs || !sameStringSet(fragPairs, mvPairs))
679
+ continue;
680
+ return { drivingRef, lookupRef, mvDrivingRef, mvLookupRef };
681
+ }
682
+ return undefined;
683
+ }
684
+ /** True when `join` is an inner or cross join (an outer join is deferred — its
685
+ * null-extended rows make the stored relation differ from an inner-join query). */
686
+ function isInnerOrCross(join) {
687
+ if (!CapabilityDetectors.isJoin(join))
688
+ return false;
689
+ const t = join.getJoinType();
690
+ return t === 'inner' || t === 'cross';
691
+ }
692
+ /**
693
+ * The join's equi-pairs as a set of `"drivingCol:lookupCol"` base-column keys, or
694
+ * `undefined` when the join is not a pure equi-join or a pair does not connect the
695
+ * driving and lookup tables cleanly. Shared shape for fragment and MV comparison.
696
+ */
697
+ function equiPairsByBaseCol(topJoin, drivingRef, lookupRef) {
698
+ const pairs = pureJoinEquiAttrPairs(topJoin);
699
+ if (!pairs || pairs.length === 0)
700
+ return undefined;
701
+ const dCol = attrToBaseCol(drivingRef);
702
+ const lCol = attrToBaseCol(lookupRef);
703
+ const out = new Set();
704
+ for (const p of pairs) {
705
+ let d = dCol.get(p.leftAttrId);
706
+ let l = lCol.get(p.rightAttrId);
707
+ if (d === undefined || l === undefined) {
708
+ d = dCol.get(p.rightAttrId);
709
+ l = lCol.get(p.leftAttrId);
710
+ }
711
+ if (d === undefined || l === undefined)
712
+ return undefined; // not a clean driving↔lookup pair
713
+ out.add(`${d}:${l}`);
714
+ }
715
+ return out;
716
+ }
717
+ function mvStoredJoinColumns(mvBodyRoot, mvDrivingRef, mvLookupRef) {
718
+ const dAttr = attrToBaseCol(mvDrivingRef);
719
+ const lAttr = attrToBaseCol(mvLookupRef);
720
+ const driving = new Map();
721
+ const lookup = new Map();
722
+ // A bare passthrough output column preserves its source attribute id, so the MV
723
+ // output attribute id resolves back to a driving/lookup base column (cf. the
724
+ // projection-coverage technique in `coverage-prover.ts`). A computed column gets
725
+ // a fresh id absent from both maps and is left unmapped.
726
+ mvBodyRoot.getAttributes().forEach((attr, backingCol) => {
727
+ const d = dAttr.get(attr.id);
728
+ if (d !== undefined) {
729
+ if (!driving.has(d))
730
+ driving.set(d, backingCol);
731
+ return;
732
+ }
733
+ const l = lAttr.get(attr.id);
734
+ if (l !== undefined && !lookup.has(l))
735
+ lookup.set(l, backingCol);
736
+ });
737
+ return { driving, lookup };
738
+ }
739
+ /** The backing column storing the fragment source attribute `attrId` (resolved to a
740
+ * driving/lookup base column), or `undefined` when the MV does not store it. */
741
+ function backingColForAttr(attrId, fragDriving, fragLookup, stored) {
742
+ const d = fragDriving.get(attrId);
743
+ if (d !== undefined)
744
+ return stored.driving.get(d);
745
+ const l = fragLookup.get(attrId);
746
+ if (l !== undefined)
747
+ return stored.lookup.get(l);
748
+ return undefined;
749
+ }
750
+ /** Fragment source attribute id → backing column, for every `T`/`P` column the MV
751
+ * stores — the residual re-bind map (`backingColOfSourceAttrId`). */
752
+ function storedSourceAttrIds(fragDriving, fragLookup, stored) {
753
+ const out = new Map();
754
+ fragDriving.forEach((baseCol, attrId) => {
755
+ const bc = stored.driving.get(baseCol);
756
+ if (bc !== undefined)
757
+ out.set(attrId, bc);
758
+ });
759
+ fragLookup.forEach((baseCol, attrId) => {
760
+ const bc = stored.lookup.get(baseCol);
761
+ if (bc !== undefined)
762
+ out.set(attrId, bc);
763
+ });
764
+ return out;
765
+ }
766
+ /** Stable attribute id → base column index for a table reference. */
767
+ function attrToBaseCol(ref) {
768
+ const out = new Map();
769
+ ref.getAttributes().forEach((attr, i) => out.set(attr.id, i));
770
+ return out;
771
+ }
772
+ /** All `TableReferenceNode`s in `node`'s subtree (depth-first, left-to-right). */
773
+ function collectBaseTableRefs(node) {
774
+ if (node instanceof TableReferenceNode)
775
+ return [node];
776
+ const out = [];
777
+ for (const rel of node.getRelations())
778
+ out.push(...collectBaseTableRefs(rel));
779
+ return out;
780
+ }
781
+ /** The first `TableReferenceNode` in `node`'s subtree over the qualified table, or
782
+ * `undefined`. The fragment rejects self-joins upstream, so the first match is
783
+ * unambiguous. */
784
+ function findTableRef(node, qualified) {
785
+ if (node instanceof TableReferenceNode) {
786
+ return qualifiedOf(node.tableSchema) === qualified ? node : undefined;
787
+ }
788
+ for (const rel of node.getRelations()) {
789
+ const found = findTableRef(rel, qualified);
790
+ if (found)
791
+ return found;
792
+ }
793
+ return undefined;
794
+ }
795
+ /** True iff `conjunct` embeds a relational subquery (an Exists/In/scalar-subquery
796
+ * whose child is a relation). Such a predicate is not re-bindable onto a flat
797
+ * backing scan, so the join arm forgoes it (matching the foundation's no-subquery
798
+ * invariant that licenses `sideEffectMode: 'safe'`). */
799
+ function conjunctHasSubquery(node) {
800
+ for (const child of node.getChildren()) {
801
+ if (isRelationalNode(child))
802
+ return true;
803
+ if (conjunctHasSubquery(child))
804
+ return true;
805
+ }
806
+ return false;
807
+ }
808
+ /** Every `ColumnReferenceNode` attribute id referenced (transitively) by a
809
+ * subquery-free conjunct. */
810
+ function conjunctColumnAttrIds(node) {
811
+ const out = [];
812
+ const visit = (n) => {
813
+ if (n instanceof ColumnReferenceNode)
814
+ out.push(n.attributeId);
815
+ for (const child of n.getChildren())
816
+ visit(child);
817
+ };
818
+ visit(node);
819
+ return out;
820
+ }
821
+ /**
822
+ * True iff the backing table's columns correspond positionally — same count, same
823
+ * names in order — to the MV body root's output attributes. This is the invariant
824
+ * the position-keyed stored-column map relies on (the backing is built column-for-
825
+ * column from the body output). A source `alter` followed by `refresh` can break it
826
+ * without marking the MV permanently unusable: the backing's column order and a
827
+ * re-planned `select *` body's output order diverge (a new source column appends to
828
+ * the backing but interleaves in the body). The join arm verifies the invariant
829
+ * here rather than trusting position, so a desynchronized MV forgoes the rewrite
830
+ * (the base recompute stays correct) instead of reading the wrong column.
831
+ */
832
+ function backingAlignsWithBody(mvBodyRoot, backing) {
833
+ const attrs = mvBodyRoot.getAttributes();
834
+ if (attrs.length !== backing.columns.length)
835
+ return false;
836
+ for (let i = 0; i < attrs.length; i++) {
837
+ if (attrs[i].name.toLowerCase() !== backing.columns[i].name.toLowerCase())
838
+ return false;
839
+ }
840
+ return true;
841
+ }
842
+ /** `schema.table` lowercased — the canonical qualified key matching `sourceTables`. */
843
+ function qualifiedOf(table) {
844
+ return `${table.schemaName}.${table.name}`.toLowerCase();
845
+ }
846
+ /** Set equality over two string sets. */
847
+ function sameStringSet(a, b) {
848
+ if (a.size !== b.size)
849
+ return false;
850
+ for (const x of a)
851
+ if (!b.has(x))
852
+ return false;
853
+ return true;
854
+ }
855
+ /** Decomposable rollup aggregates that re-aggregate as plain `sum`/`min`/`max`. */
856
+ const ROLLUP_SUM_LIKE = new Map([
857
+ ['sum', 'sum'], ['min', 'min'], ['max', 'max'],
858
+ ]);
859
+ /**
860
+ * Exact-key recipe: the query aggregate must be *exactly* a stored MV aggregate
861
+ * (same function, same argument column, same DISTINCT flag). The stored value is
862
+ * the answer, so this admits any aggregate — including `count(distinct)` /
863
+ * `group_concat` — as a passthrough. Returns a `sum`-kind passthrough recipe whose
864
+ * `backingCols[0]` is the stored column (the kind is unused for exact-key, which the
865
+ * rule answers via `outputColumnMap`).
866
+ */
867
+ function recipeForExact(qa, stored) {
868
+ const match = stored.find(sa => sa.funcName === qa.funcName && sa.argBaseCol === qa.argBaseCol && sa.isDistinct === qa.isDistinct);
869
+ if (!match)
870
+ return undefined;
871
+ return { outAttr: qa.outAttr, kind: 'sum', backingCols: [match.backingCol] };
872
+ }
873
+ /**
874
+ * Rollup recipe: reconstruct `qa` by re-aggregating the MV's stored partials. Only
875
+ * the decomposable allowlist is admitted; a DISTINCT aggregate never composes.
876
+ */
877
+ function recipeForRollup(qa, stored, baseTable) {
878
+ if (qa.isDistinct)
879
+ return undefined; // count(distinct …) and friends never compose under rollup.
880
+ const sumLike = ROLLUP_SUM_LIKE.get(qa.funcName);
881
+ if (sumLike) {
882
+ // sum(x) ← sum(stored sum(x)); min/max(x) ← min/max(stored min/max(x)).
883
+ const col = findStored(stored, qa.funcName, qa.argBaseCol);
884
+ return col === undefined ? undefined : { outAttr: qa.outAttr, kind: sumLike, backingCols: [col] };
885
+ }
886
+ if (qa.funcName === 'count') {
887
+ // count(*) ← sum(stored count(*)); count(x) ← sum(stored count(x)). The 'count'
888
+ // kind adds the coalesce-to-0 the rule emits (count over zero rows is 0, not NULL).
889
+ const col = findStored(stored, 'count', qa.argBaseCol);
890
+ return col === undefined ? undefined : { outAttr: qa.outAttr, kind: 'count', backingCols: [col] };
891
+ }
892
+ if (qa.funcName === 'avg') {
893
+ // avg(x) ← sum(stored sum(x)) / sum(stored count). Requires both partials; the
894
+ // count must exclude the same NULLs `avg` does — a stored `count(x)` always
895
+ // qualifies, and a stored `count(*)` only when `x` is declared NOT NULL.
896
+ const sumCol = findStored(stored, 'sum', qa.argBaseCol);
897
+ if (sumCol === undefined)
898
+ return undefined;
899
+ let countCol = findStored(stored, 'count', qa.argBaseCol);
900
+ if (countCol === undefined && qa.argBaseCol !== undefined && baseTable.columns[qa.argBaseCol]?.notNull === true) {
901
+ countCol = findStored(stored, 'count', undefined); // count(*) is sound when x is NOT NULL.
902
+ }
903
+ if (countCol === undefined)
904
+ return undefined;
905
+ return { outAttr: qa.outAttr, kind: 'avg', backingCols: [sumCol, countCol] };
906
+ }
907
+ return undefined; // total / group_concat / unknown ⇒ not decomposable.
908
+ }
909
+ /** The backing column of a stored, non-distinct aggregate `f(argBaseCol)`, or undefined. */
910
+ function findStored(stored, funcName, argBaseCol) {
911
+ const match = stored.find(sa => sa.funcName === funcName && sa.argBaseCol === argBaseCol && !sa.isDistinct);
912
+ return match?.backingCol;
913
+ }
914
+ /**
915
+ * Parse a grouped MV's select list into its group-key passthrough columns and its
916
+ * stored aggregate columns, by backing-column position. A bare column is a group
917
+ * key; an aggregate function call (`count(*)`, or `f(col)`) is a stored aggregate;
918
+ * a `*` or any other computed item is ignored (it answers no group key or aggregate).
919
+ * Returns undefined only for a `table.*` naming a non-base table (defensive).
920
+ */
921
+ function analyzeMvStoredColumns(columns, baseTable) {
922
+ const groupBackingOfBaseCol = new Map();
923
+ const storedAggs = [];
924
+ for (let backingCol = 0; backingCol < columns.length; backingCol++) {
925
+ const col = columns[backingCol];
926
+ if (col.type === 'all') {
927
+ if (col.table && col.table.toLowerCase() !== baseTable.name.toLowerCase())
928
+ return undefined;
929
+ // A `*` in a grouped body would be an error at create time; ignore defensively.
930
+ continue;
931
+ }
932
+ const expr = col.expr;
933
+ if (expr.type === 'function') {
934
+ const fn = expr;
935
+ const argBaseCol = mvAggregateArgBaseCol(fn, baseTable);
936
+ if (argBaseCol === 'unrecognized')
937
+ continue; // computed/multi-arg ⇒ unusable
938
+ storedAggs.push({
939
+ funcName: fn.name.toLowerCase(),
940
+ argBaseCol,
941
+ isDistinct: fn.distinct === true,
942
+ backingCol,
943
+ });
944
+ continue;
945
+ }
946
+ const baseCol = baseColumnOfExpr(expr, baseTable);
947
+ if (baseCol !== undefined && !groupBackingOfBaseCol.has(baseCol)) {
948
+ groupBackingOfBaseCol.set(baseCol, backingCol);
949
+ }
950
+ // A computed non-aggregate select item is left unmapped (unusable).
951
+ }
952
+ return { groupBackingOfBaseCol, storedAggs };
953
+ }
954
+ /**
955
+ * The base-table column index of an MV aggregate's argument: `undefined` for
956
+ * `count(*)` (no argument), a base column index for a single bare-column argument,
957
+ * or `'unrecognized'` for a computed / multi-argument call (which no fragment
958
+ * aggregate — itself required to be bare — can match).
959
+ */
960
+ function mvAggregateArgBaseCol(fn, baseTable) {
961
+ if (fn.args.length === 0)
962
+ return undefined;
963
+ if (fn.args.length === 1) {
964
+ const col = baseColumnOfExpr(fn.args[0], baseTable);
965
+ return col === undefined ? 'unrecognized' : col;
966
+ }
967
+ return 'unrecognized';
968
+ }
969
+ /**
970
+ * True iff the backing table's primary key is exactly the MV's group key (mapped to
971
+ * backing columns). The witness that the backing is one row per MV group.
972
+ */
973
+ function backingPkIsGroupKey(backing, mvGroupBaseCols, groupBackingOfBaseCol) {
974
+ const pk = backing.primaryKeyDefinition;
975
+ if (pk.length !== mvGroupBaseCols.length)
976
+ return false;
977
+ const pkSet = new Set(pk.map(c => c.index));
978
+ if (pkSet.size !== pk.length)
979
+ return false;
980
+ for (const gc of mvGroupBaseCols) {
981
+ const bc = groupBackingOfBaseCol.get(gc);
982
+ if (bc === undefined || !pkSet.has(bc))
983
+ return false;
984
+ }
985
+ return true;
986
+ }
987
+ /** The sole relational child of a single-source pass-through, or undefined. */
988
+ function singleRelation(node) {
989
+ const rels = node.getRelations();
990
+ return rels.length === 1 ? rels[0] : undefined;
991
+ }
992
+ /** Flatten a predicate into its top-level AND conjuncts (plan-node level). */
993
+ function splitConjuncts(predicate, out) {
994
+ if (predicate instanceof BinaryOpNode && predicate.expression.operator === 'AND') {
995
+ splitConjuncts(predicate.left, out);
996
+ splitConjuncts(predicate.right, out);
997
+ return;
998
+ }
999
+ out.push(predicate);
1000
+ }
1001
+ /** The originating AST of a scalar plan node, or undefined when it has none. */
1002
+ function conjunctExpression(node) {
1003
+ const expr = node.expression;
1004
+ return expr && typeof expr === 'object' && 'type' in expr
1005
+ ? expr
1006
+ : undefined;
1007
+ }
1008
+ /**
1009
+ * Map each MV backing column (by output position) to the base-table column it
1010
+ * passes through, reading the MV's select list. A `*` expands to every base
1011
+ * column in order; a bare column resolves by name; a computed item leaves that
1012
+ * position `undefined` (unmapped). Returns undefined when a `table.*` form names a
1013
+ * table other than the base (cannot happen for a single-source body, but rejected
1014
+ * defensively).
1015
+ */
1016
+ function mvProjectionBaseCols(columns, baseTable) {
1017
+ const out = [];
1018
+ for (const col of columns) {
1019
+ if (col.type === 'all') {
1020
+ if (col.table && col.table.toLowerCase() !== baseTable.name.toLowerCase())
1021
+ return undefined;
1022
+ for (let i = 0; i < baseTable.columns.length; i++)
1023
+ out.push(i);
1024
+ continue;
1025
+ }
1026
+ out.push(baseColumnOfExpr(col.expr, baseTable));
1027
+ }
1028
+ return out;
1029
+ }
1030
+ /** Resolve a bare column / identifier expression to a base-table column index. */
1031
+ function baseColumnOfExpr(expr, baseTable) {
1032
+ if (expr.type === 'column') {
1033
+ return baseTable.columnIndexMap.get(expr.name.toLowerCase());
1034
+ }
1035
+ if (expr.type === 'identifier') {
1036
+ const id = expr;
1037
+ if (id.schema)
1038
+ return undefined;
1039
+ return baseTable.columnIndexMap.get(id.name.toLowerCase());
1040
+ }
1041
+ return undefined;
1042
+ }
1043
+ /**
1044
+ * True when `clause` constant-pins (`g = literal`, `g is null`) or equates
1045
+ * (`g1 = g2`) a column in `groupSet` — the predicate shapes that give a group-key
1046
+ * column a determining FD and so drive `rule-groupby-fd-simplification` to drop and
1047
+ * reposition it. Range / IN (`or-of`) clauses create no such FD and return false.
1048
+ */
1049
+ function clausePinsOrEquatesGroupCol(clause, groupSet) {
1050
+ switch (clause.kind) {
1051
+ case 'eq-literal': return groupSet.has(clause.column);
1052
+ case 'is-null': return groupSet.has(clause.column);
1053
+ case 'eq-column': return groupSet.has(clause.left) || groupSet.has(clause.right);
1054
+ default: return false; // range / or-of: no constant-determining FD
1055
+ }
1056
+ }
1057
+ /** The base-table column indices a recognized guard clause references. */
1058
+ function clauseColumns(clause) {
1059
+ switch (clause.kind) {
1060
+ case 'eq-literal': return [clause.column];
1061
+ case 'eq-column': return [clause.left, clause.right];
1062
+ case 'is-null': return [clause.column];
1063
+ case 'range': return [clause.column];
1064
+ case 'or-of': return clause.clauses.flatMap(clauseColumns);
1065
+ default: return [];
1066
+ }
1067
+ }
1068
+ /** True when the MV body's WHERE or any projection expression calls a
1069
+ * non-deterministic function (or embeds a subquery). */
1070
+ function mvBodyHasNonDeterminism(selectAst, isDeterministic) {
1071
+ if (selectAst.type !== 'select')
1072
+ return false;
1073
+ if (selectAst.where && containsNonDeterministicCall(selectAst.where, isDeterministic))
1074
+ return true;
1075
+ for (const col of selectAst.columns) {
1076
+ if (col.type === 'column' && containsNonDeterministicCall(col.expr, isDeterministic))
1077
+ return true;
1078
+ }
1079
+ return false;
1080
+ }
1081
+ //# sourceMappingURL=query-rewrite-matcher.js.map