@quereus/quereus 0.1.0 → 0.2.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 (465) hide show
  1. package/README.md +47 -23
  2. package/dist/src/core/database.d.ts +22 -4
  3. package/dist/src/core/database.d.ts.map +1 -1
  4. package/dist/src/core/database.js +44 -6
  5. package/dist/src/core/database.js.map +1 -1
  6. package/dist/src/core/statement.d.ts +0 -7
  7. package/dist/src/core/statement.d.ts.map +1 -1
  8. package/dist/src/core/statement.js +1 -51
  9. package/dist/src/core/statement.js.map +1 -1
  10. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  11. package/dist/src/func/builtins/explain.js +0 -11
  12. package/dist/src/func/builtins/explain.js.map +1 -1
  13. package/dist/src/index.d.ts +13 -5
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/index.js +5 -2
  16. package/dist/src/index.js.map +1 -1
  17. package/dist/src/parser/ast.d.ts +9 -2
  18. package/dist/src/parser/ast.d.ts.map +1 -1
  19. package/dist/src/parser/parser.d.ts.map +1 -1
  20. package/dist/src/parser/parser.js +40 -44
  21. package/dist/src/parser/parser.js.map +1 -1
  22. package/dist/src/planner/analysis/const-pass.d.ts.map +1 -1
  23. package/dist/src/planner/analysis/const-pass.js +12 -6
  24. package/dist/src/planner/analysis/const-pass.js.map +1 -1
  25. package/dist/src/planner/building/constraint-builder.d.ts +11 -0
  26. package/dist/src/planner/building/constraint-builder.d.ts.map +1 -0
  27. package/dist/src/planner/building/constraint-builder.js +79 -0
  28. package/dist/src/planner/building/constraint-builder.js.map +1 -0
  29. package/dist/src/planner/building/delete.d.ts.map +1 -1
  30. package/dist/src/planner/building/delete.js +6 -3
  31. package/dist/src/planner/building/delete.js.map +1 -1
  32. package/dist/src/planner/building/expression.d.ts +3 -0
  33. package/dist/src/planner/building/expression.d.ts.map +1 -1
  34. package/dist/src/planner/building/expression.js +33 -7
  35. package/dist/src/planner/building/expression.js.map +1 -1
  36. package/dist/src/planner/building/insert.d.ts.map +1 -1
  37. package/dist/src/planner/building/insert.js +4 -1
  38. package/dist/src/planner/building/insert.js.map +1 -1
  39. package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
  40. package/dist/src/planner/building/select-aggregates.js +46 -9
  41. package/dist/src/planner/building/select-aggregates.js.map +1 -1
  42. package/dist/src/planner/building/select-context.js +20 -11
  43. package/dist/src/planner/building/select-context.js.map +1 -1
  44. package/dist/src/planner/building/select-modifiers.d.ts +5 -3
  45. package/dist/src/planner/building/select-modifiers.d.ts.map +1 -1
  46. package/dist/src/planner/building/select-modifiers.js +29 -20
  47. package/dist/src/planner/building/select-modifiers.js.map +1 -1
  48. package/dist/src/planner/building/select-projections.d.ts +3 -1
  49. package/dist/src/planner/building/select-projections.d.ts.map +1 -1
  50. package/dist/src/planner/building/select-projections.js +15 -20
  51. package/dist/src/planner/building/select-projections.js.map +1 -1
  52. package/dist/src/planner/building/select-window.d.ts.map +1 -1
  53. package/dist/src/planner/building/select-window.js +6 -3
  54. package/dist/src/planner/building/select-window.js.map +1 -1
  55. package/dist/src/planner/building/select.d.ts +25 -2
  56. package/dist/src/planner/building/select.d.ts.map +1 -1
  57. package/dist/src/planner/building/select.js +147 -24
  58. package/dist/src/planner/building/select.js.map +1 -1
  59. package/dist/src/planner/building/table.d.ts +0 -10
  60. package/dist/src/planner/building/table.d.ts.map +1 -1
  61. package/dist/src/planner/building/table.js +1 -35
  62. package/dist/src/planner/building/table.js.map +1 -1
  63. package/dist/src/planner/building/update.d.ts.map +1 -1
  64. package/dist/src/planner/building/update.js +7 -4
  65. package/dist/src/planner/building/update.js.map +1 -1
  66. package/dist/src/planner/building/with.d.ts.map +1 -1
  67. package/dist/src/planner/building/with.js +7 -8
  68. package/dist/src/planner/building/with.js.map +1 -1
  69. package/dist/src/planner/cache/correlation-detector.d.ts +11 -0
  70. package/dist/src/planner/cache/correlation-detector.d.ts.map +1 -0
  71. package/dist/src/planner/cache/correlation-detector.js +73 -0
  72. package/dist/src/planner/cache/correlation-detector.js.map +1 -0
  73. package/dist/src/planner/cache/materialization-advisory.d.ts +12 -18
  74. package/dist/src/planner/cache/materialization-advisory.d.ts.map +1 -1
  75. package/dist/src/planner/cache/materialization-advisory.js +65 -46
  76. package/dist/src/planner/cache/materialization-advisory.js.map +1 -1
  77. package/dist/src/planner/cache/reference-graph.d.ts +14 -9
  78. package/dist/src/planner/cache/reference-graph.d.ts.map +1 -1
  79. package/dist/src/planner/cache/reference-graph.js +93 -84
  80. package/dist/src/planner/cache/reference-graph.js.map +1 -1
  81. package/dist/src/planner/debug.d.ts +25 -0
  82. package/dist/src/planner/debug.d.ts.map +1 -1
  83. package/dist/src/planner/debug.js +127 -0
  84. package/dist/src/planner/debug.js.map +1 -1
  85. package/dist/src/planner/framework/context.d.ts +11 -0
  86. package/dist/src/planner/framework/context.d.ts.map +1 -1
  87. package/dist/src/planner/framework/context.js +25 -2
  88. package/dist/src/planner/framework/context.js.map +1 -1
  89. package/dist/src/planner/framework/registry.d.ts +3 -7
  90. package/dist/src/planner/framework/registry.d.ts.map +1 -1
  91. package/dist/src/planner/framework/registry.js +20 -31
  92. package/dist/src/planner/framework/registry.js.map +1 -1
  93. package/dist/src/planner/nodes/add-constraint-node.d.ts +2 -1
  94. package/dist/src/planner/nodes/add-constraint-node.d.ts.map +1 -1
  95. package/dist/src/planner/nodes/add-constraint-node.js +3 -0
  96. package/dist/src/planner/nodes/add-constraint-node.js.map +1 -1
  97. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  98. package/dist/src/planner/nodes/aggregate-node.js +6 -4
  99. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  100. package/dist/src/planner/nodes/cache-node.d.ts.map +1 -1
  101. package/dist/src/planner/nodes/cache-node.js +2 -2
  102. package/dist/src/planner/nodes/cache-node.js.map +1 -1
  103. package/dist/src/planner/nodes/constraint-check-node.d.ts +11 -4
  104. package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
  105. package/dist/src/planner/nodes/constraint-check-node.js +38 -12
  106. package/dist/src/planner/nodes/constraint-check-node.js.map +1 -1
  107. package/dist/src/planner/nodes/create-index-node.d.ts +2 -1
  108. package/dist/src/planner/nodes/create-index-node.d.ts.map +1 -1
  109. package/dist/src/planner/nodes/create-index-node.js +3 -0
  110. package/dist/src/planner/nodes/create-index-node.js.map +1 -1
  111. package/dist/src/planner/nodes/create-table-node.d.ts +2 -1
  112. package/dist/src/planner/nodes/create-table-node.d.ts.map +1 -1
  113. package/dist/src/planner/nodes/create-table-node.js +3 -0
  114. package/dist/src/planner/nodes/create-table-node.js.map +1 -1
  115. package/dist/src/planner/nodes/create-view-node.d.ts +2 -1
  116. package/dist/src/planner/nodes/create-view-node.d.ts.map +1 -1
  117. package/dist/src/planner/nodes/create-view-node.js +3 -0
  118. package/dist/src/planner/nodes/create-view-node.js.map +1 -1
  119. package/dist/src/planner/nodes/cte-node.d.ts +1 -1
  120. package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
  121. package/dist/src/planner/nodes/cte-node.js +33 -12
  122. package/dist/src/planner/nodes/cte-node.js.map +1 -1
  123. package/dist/src/planner/nodes/cte-reference-node.d.ts +18 -4
  124. package/dist/src/planner/nodes/cte-reference-node.d.ts.map +1 -1
  125. package/dist/src/planner/nodes/cte-reference-node.js +40 -10
  126. package/dist/src/planner/nodes/cte-reference-node.js.map +1 -1
  127. package/dist/src/planner/nodes/delete-node.d.ts +4 -3
  128. package/dist/src/planner/nodes/delete-node.d.ts.map +1 -1
  129. package/dist/src/planner/nodes/delete-node.js +20 -6
  130. package/dist/src/planner/nodes/delete-node.js.map +1 -1
  131. package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
  132. package/dist/src/planner/nodes/distinct-node.js +2 -2
  133. package/dist/src/planner/nodes/distinct-node.js.map +1 -1
  134. package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
  135. package/dist/src/planner/nodes/dml-executor-node.js +2 -2
  136. package/dist/src/planner/nodes/dml-executor-node.js.map +1 -1
  137. package/dist/src/planner/nodes/drop-table-node.d.ts +2 -1
  138. package/dist/src/planner/nodes/drop-table-node.d.ts.map +1 -1
  139. package/dist/src/planner/nodes/drop-table-node.js +3 -0
  140. package/dist/src/planner/nodes/drop-table-node.js.map +1 -1
  141. package/dist/src/planner/nodes/drop-view-node.d.ts +2 -1
  142. package/dist/src/planner/nodes/drop-view-node.d.ts.map +1 -1
  143. package/dist/src/planner/nodes/drop-view-node.js +3 -0
  144. package/dist/src/planner/nodes/drop-view-node.js.map +1 -1
  145. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  146. package/dist/src/planner/nodes/filter.js +3 -3
  147. package/dist/src/planner/nodes/filter.js.map +1 -1
  148. package/dist/src/planner/nodes/insert-node.d.ts +2 -1
  149. package/dist/src/planner/nodes/insert-node.d.ts.map +1 -1
  150. package/dist/src/planner/nodes/insert-node.js +18 -5
  151. package/dist/src/planner/nodes/insert-node.js.map +1 -1
  152. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts +28 -0
  153. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts.map +1 -0
  154. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js +69 -0
  155. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js.map +1 -0
  156. package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
  157. package/dist/src/planner/nodes/join-node.js +3 -3
  158. package/dist/src/planner/nodes/join-node.js.map +1 -1
  159. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  160. package/dist/src/planner/nodes/limit-offset.js +2 -2
  161. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  162. package/dist/src/planner/nodes/plan-node-type.d.ts +1 -1
  163. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  164. package/dist/src/planner/nodes/plan-node-type.js +1 -1
  165. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  166. package/dist/src/planner/nodes/plan-node.d.ts +23 -0
  167. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  168. package/dist/src/planner/nodes/plan-node.js +25 -2
  169. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  170. package/dist/src/planner/nodes/project-node.d.ts +5 -1
  171. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  172. package/dist/src/planner/nodes/project-node.js +39 -20
  173. package/dist/src/planner/nodes/project-node.js.map +1 -1
  174. package/dist/src/planner/nodes/recursive-cte-node.d.ts +2 -2
  175. package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -1
  176. package/dist/src/planner/nodes/recursive-cte-node.js +20 -8
  177. package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -1
  178. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  179. package/dist/src/planner/nodes/reference.js +4 -2
  180. package/dist/src/planner/nodes/reference.js.map +1 -1
  181. package/dist/src/planner/nodes/returning-node.d.ts +1 -1
  182. package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
  183. package/dist/src/planner/nodes/returning-node.js +21 -13
  184. package/dist/src/planner/nodes/returning-node.js.map +1 -1
  185. package/dist/src/planner/nodes/scalar.d.ts +26 -2
  186. package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
  187. package/dist/src/planner/nodes/scalar.js +82 -10
  188. package/dist/src/planner/nodes/scalar.js.map +1 -1
  189. package/dist/src/planner/nodes/sequencing-node.d.ts.map +1 -1
  190. package/dist/src/planner/nodes/sequencing-node.js +2 -2
  191. package/dist/src/planner/nodes/sequencing-node.js.map +1 -1
  192. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  193. package/dist/src/planner/nodes/set-operation-node.js +3 -3
  194. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  195. package/dist/src/planner/nodes/single-row.d.ts +4 -2
  196. package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
  197. package/dist/src/planner/nodes/single-row.js +3 -0
  198. package/dist/src/planner/nodes/single-row.js.map +1 -1
  199. package/dist/src/planner/nodes/sink-node.d.ts +1 -1
  200. package/dist/src/planner/nodes/sink-node.d.ts.map +1 -1
  201. package/dist/src/planner/nodes/sink-node.js +4 -4
  202. package/dist/src/planner/nodes/sink-node.js.map +1 -1
  203. package/dist/src/planner/nodes/sort.d.ts.map +1 -1
  204. package/dist/src/planner/nodes/sort.js +2 -2
  205. package/dist/src/planner/nodes/sort.js.map +1 -1
  206. package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -0
  207. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  208. package/dist/src/planner/nodes/stream-aggregate.js +64 -11
  209. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  210. package/dist/src/planner/nodes/subquery.d.ts +4 -4
  211. package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
  212. package/dist/src/planner/nodes/subquery.js +68 -23
  213. package/dist/src/planner/nodes/subquery.js.map +1 -1
  214. package/dist/src/planner/nodes/table-access-nodes.d.ts +83 -0
  215. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -0
  216. package/dist/src/planner/nodes/table-access-nodes.js +226 -0
  217. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -0
  218. package/dist/src/planner/nodes/update-node.d.ts +4 -2
  219. package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
  220. package/dist/src/planner/nodes/update-node.js +26 -13
  221. package/dist/src/planner/nodes/update-node.js.map +1 -1
  222. package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
  223. package/dist/src/planner/nodes/window-node.js +25 -23
  224. package/dist/src/planner/nodes/window-node.js.map +1 -1
  225. package/dist/src/planner/optimizer.d.ts.map +1 -1
  226. package/dist/src/planner/optimizer.js +46 -50
  227. package/dist/src/planner/optimizer.js.map +1 -1
  228. package/dist/src/planner/planning-context.d.ts +13 -0
  229. package/dist/src/planner/planning-context.d.ts.map +1 -1
  230. package/dist/src/planner/planning-context.js.map +1 -1
  231. package/dist/src/planner/rules/access/rule-select-access-path.d.ts +1 -1
  232. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  233. package/dist/src/planner/rules/access/rule-select-access-path.js +59 -53
  234. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  235. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
  236. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +62 -2
  237. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
  238. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts.map +1 -1
  239. package/dist/src/planner/rules/cache/rule-materialization-advisory.js +31 -24
  240. package/dist/src/planner/rules/cache/rule-materialization-advisory.js.map +1 -1
  241. package/dist/src/planner/scopes/base.d.ts +0 -10
  242. package/dist/src/planner/scopes/base.d.ts.map +1 -1
  243. package/dist/src/planner/scopes/base.js +0 -14
  244. package/dist/src/planner/scopes/base.js.map +1 -1
  245. package/dist/src/planner/scopes/empty.d.ts +0 -2
  246. package/dist/src/planner/scopes/empty.d.ts.map +1 -1
  247. package/dist/src/planner/scopes/empty.js +0 -8
  248. package/dist/src/planner/scopes/empty.js.map +1 -1
  249. package/dist/src/planner/scopes/multi.d.ts.map +1 -1
  250. package/dist/src/planner/scopes/multi.js +0 -1
  251. package/dist/src/planner/scopes/multi.js.map +1 -1
  252. package/dist/src/planner/scopes/param.d.ts.map +1 -1
  253. package/dist/src/planner/scopes/param.js +0 -1
  254. package/dist/src/planner/scopes/param.js.map +1 -1
  255. package/dist/src/planner/scopes/registered.d.ts +0 -10
  256. package/dist/src/planner/scopes/registered.d.ts.map +1 -1
  257. package/dist/src/planner/scopes/registered.js +1 -17
  258. package/dist/src/planner/scopes/registered.js.map +1 -1
  259. package/dist/src/planner/scopes/scope.d.ts +0 -8
  260. package/dist/src/planner/scopes/scope.d.ts.map +1 -1
  261. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
  262. package/dist/src/planner/validation/plan-validator.js +1 -7
  263. package/dist/src/planner/validation/plan-validator.js.map +1 -1
  264. package/dist/src/runtime/context-helpers.d.ts +45 -0
  265. package/dist/src/runtime/context-helpers.d.ts.map +1 -0
  266. package/dist/src/runtime/context-helpers.js +139 -0
  267. package/dist/src/runtime/context-helpers.js.map +1 -0
  268. package/dist/src/runtime/emission-context.d.ts +1 -0
  269. package/dist/src/runtime/emission-context.d.ts.map +1 -1
  270. package/dist/src/runtime/emission-context.js +2 -1
  271. package/dist/src/runtime/emission-context.js.map +1 -1
  272. package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
  273. package/dist/src/runtime/emit/aggregate.js +119 -86
  274. package/dist/src/runtime/emit/aggregate.js.map +1 -1
  275. package/dist/src/runtime/emit/between.d.ts +5 -0
  276. package/dist/src/runtime/emit/between.d.ts.map +1 -0
  277. package/dist/src/runtime/emit/between.js +38 -0
  278. package/dist/src/runtime/emit/between.js.map +1 -0
  279. package/dist/src/runtime/emit/binary.d.ts +0 -1
  280. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  281. package/dist/src/runtime/emit/binary.js +0 -36
  282. package/dist/src/runtime/emit/binary.js.map +1 -1
  283. package/dist/src/runtime/emit/column-reference.d.ts.map +1 -1
  284. package/dist/src/runtime/emit/column-reference.js +2 -26
  285. package/dist/src/runtime/emit/column-reference.js.map +1 -1
  286. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
  287. package/dist/src/runtime/emit/constraint-check.js +14 -121
  288. package/dist/src/runtime/emit/constraint-check.js.map +1 -1
  289. package/dist/src/runtime/emit/cte-reference.d.ts.map +1 -1
  290. package/dist/src/runtime/emit/cte-reference.js +16 -48
  291. package/dist/src/runtime/emit/cte-reference.js.map +1 -1
  292. package/dist/src/runtime/emit/distinct.d.ts.map +1 -1
  293. package/dist/src/runtime/emit/distinct.js +2 -8
  294. package/dist/src/runtime/emit/distinct.js.map +1 -1
  295. package/dist/src/runtime/emit/filter.d.ts.map +1 -1
  296. package/dist/src/runtime/emit/filter.js +6 -13
  297. package/dist/src/runtime/emit/filter.js.map +1 -1
  298. package/dist/src/runtime/emit/internal-recursive-cte-ref.d.ts +5 -0
  299. package/dist/src/runtime/emit/internal-recursive-cte-ref.d.ts.map +1 -0
  300. package/dist/src/runtime/emit/internal-recursive-cte-ref.js +23 -0
  301. package/dist/src/runtime/emit/internal-recursive-cte-ref.js.map +1 -0
  302. package/dist/src/runtime/emit/join.d.ts.map +1 -1
  303. package/dist/src/runtime/emit/join.js +40 -40
  304. package/dist/src/runtime/emit/join.js.map +1 -1
  305. package/dist/src/runtime/emit/project.d.ts.map +1 -1
  306. package/dist/src/runtime/emit/project.js +13 -13
  307. package/dist/src/runtime/emit/project.js.map +1 -1
  308. package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
  309. package/dist/src/runtime/emit/recursive-cte.js +3 -14
  310. package/dist/src/runtime/emit/recursive-cte.js.map +1 -1
  311. package/dist/src/runtime/emit/returning.d.ts.map +1 -1
  312. package/dist/src/runtime/emit/returning.js +7 -14
  313. package/dist/src/runtime/emit/returning.js.map +1 -1
  314. package/dist/src/runtime/emit/scan.d.ts +5 -2
  315. package/dist/src/runtime/emit/scan.d.ts.map +1 -1
  316. package/dist/src/runtime/emit/scan.js +21 -17
  317. package/dist/src/runtime/emit/scan.js.map +1 -1
  318. package/dist/src/runtime/emit/sort.d.ts.map +1 -1
  319. package/dist/src/runtime/emit/sort.js +8 -11
  320. package/dist/src/runtime/emit/sort.js.map +1 -1
  321. package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
  322. package/dist/src/runtime/emit/subquery.js +95 -40
  323. package/dist/src/runtime/emit/subquery.js.map +1 -1
  324. package/dist/src/runtime/emit/table-valued-function.d.ts.map +1 -1
  325. package/dist/src/runtime/emit/table-valued-function.js +7 -22
  326. package/dist/src/runtime/emit/table-valued-function.js.map +1 -1
  327. package/dist/src/runtime/emit/update.d.ts.map +1 -1
  328. package/dist/src/runtime/emit/update.js +20 -27
  329. package/dist/src/runtime/emit/update.js.map +1 -1
  330. package/dist/src/runtime/emit/window.d.ts.map +1 -1
  331. package/dist/src/runtime/emit/window.js +55 -83
  332. package/dist/src/runtime/emit/window.js.map +1 -1
  333. package/dist/src/runtime/emitters.d.ts.map +1 -1
  334. package/dist/src/runtime/emitters.js +49 -1
  335. package/dist/src/runtime/emitters.js.map +1 -1
  336. package/dist/src/runtime/register.d.ts.map +1 -1
  337. package/dist/src/runtime/register.js +5 -4
  338. package/dist/src/runtime/register.js.map +1 -1
  339. package/dist/src/runtime/scheduler.d.ts.map +1 -1
  340. package/dist/src/runtime/scheduler.js +47 -42
  341. package/dist/src/runtime/scheduler.js.map +1 -1
  342. package/dist/src/runtime/types.d.ts +34 -0
  343. package/dist/src/runtime/types.d.ts.map +1 -1
  344. package/dist/src/runtime/types.js +21 -0
  345. package/dist/src/runtime/types.js.map +1 -1
  346. package/dist/src/schema/manager.d.ts.map +1 -1
  347. package/dist/src/schema/manager.js +29 -16
  348. package/dist/src/schema/manager.js.map +1 -1
  349. package/dist/src/util/plugin-loader.d.ts +10 -1
  350. package/dist/src/util/plugin-loader.d.ts.map +1 -1
  351. package/dist/src/util/plugin-loader.js +56 -1
  352. package/dist/src/util/plugin-loader.js.map +1 -1
  353. package/dist/src/util/working-table-iterable.d.ts.map +1 -1
  354. package/dist/src/util/working-table-iterable.js +8 -8
  355. package/dist/src/util/working-table-iterable.js.map +1 -1
  356. package/dist/src/vtab/manifest.d.ts +36 -0
  357. package/dist/src/vtab/manifest.d.ts.map +1 -1
  358. package/package.json +8 -3
  359. package/src/core/database.ts +48 -6
  360. package/src/core/statement.ts +1 -49
  361. package/src/func/builtins/explain.ts +0 -11
  362. package/src/index.ts +39 -5
  363. package/src/parser/ast.ts +11 -2
  364. package/src/parser/parser.ts +40 -47
  365. package/src/planner/analysis/const-pass.ts +281 -270
  366. package/src/planner/building/constraint-builder.ts +114 -0
  367. package/src/planner/building/delete.ts +16 -3
  368. package/src/planner/building/expression.ts +35 -7
  369. package/src/planner/building/insert.ts +14 -1
  370. package/src/planner/building/select-aggregates.ts +57 -11
  371. package/src/planner/building/select-context.ts +22 -12
  372. package/src/planner/building/select-modifiers.ts +35 -21
  373. package/src/planner/building/select-projections.ts +25 -26
  374. package/src/planner/building/select-window.ts +14 -9
  375. package/src/planner/building/select.ts +163 -31
  376. package/src/planner/building/table.ts +1 -40
  377. package/src/planner/building/update.ts +19 -4
  378. package/src/planner/building/with.ts +12 -13
  379. package/src/planner/cache/correlation-detector.ts +83 -0
  380. package/src/planner/cache/materialization-advisory.ts +71 -50
  381. package/src/planner/cache/reference-graph.ts +115 -91
  382. package/src/planner/debug.ts +163 -0
  383. package/src/planner/framework/context.ts +36 -2
  384. package/src/planner/framework/registry.ts +261 -274
  385. package/src/planner/nodes/add-constraint-node.ts +5 -1
  386. package/src/planner/nodes/aggregate-node.ts +6 -4
  387. package/src/planner/nodes/cache-node.ts +2 -2
  388. package/src/planner/nodes/constraint-check-node.ts +47 -13
  389. package/src/planner/nodes/create-index-node.ts +5 -1
  390. package/src/planner/nodes/create-table-node.ts +5 -1
  391. package/src/planner/nodes/create-view-node.ts +5 -1
  392. package/src/planner/nodes/cte-node.ts +45 -14
  393. package/src/planner/nodes/cte-reference-node.ts +49 -13
  394. package/src/planner/nodes/delete-node.ts +31 -7
  395. package/src/planner/nodes/distinct-node.ts +2 -2
  396. package/src/planner/nodes/dml-executor-node.ts +2 -2
  397. package/src/planner/nodes/drop-table-node.ts +5 -1
  398. package/src/planner/nodes/drop-view-node.ts +5 -1
  399. package/src/planner/nodes/filter.ts +3 -3
  400. package/src/planner/nodes/function.ts +93 -93
  401. package/src/planner/nodes/insert-node.ts +28 -5
  402. package/src/planner/nodes/internal-recursive-cte-ref-node.ts +76 -0
  403. package/src/planner/nodes/join-node.ts +3 -3
  404. package/src/planner/nodes/limit-offset.ts +2 -2
  405. package/src/planner/nodes/plan-node-type.ts +1 -1
  406. package/src/planner/nodes/plan-node.ts +39 -2
  407. package/src/planner/nodes/project-node.ts +39 -19
  408. package/src/planner/nodes/recursive-cte-node.ts +37 -9
  409. package/src/planner/nodes/reference.ts +4 -2
  410. package/src/planner/nodes/returning-node.ts +25 -13
  411. package/src/planner/nodes/scalar.ts +95 -11
  412. package/src/planner/nodes/sequencing-node.ts +2 -2
  413. package/src/planner/nodes/set-operation-node.ts +3 -3
  414. package/src/planner/nodes/single-row.ts +7 -2
  415. package/src/planner/nodes/sink-node.ts +5 -5
  416. package/src/planner/nodes/sort.ts +2 -2
  417. package/src/planner/nodes/stream-aggregate.ts +76 -12
  418. package/src/planner/nodes/subquery.ts +90 -27
  419. package/src/planner/nodes/{physical-access-nodes.ts → table-access-nodes.ts} +6 -6
  420. package/src/planner/nodes/update-node.ts +31 -13
  421. package/src/planner/nodes/window-node.ts +28 -22
  422. package/src/planner/optimizer.ts +257 -263
  423. package/src/planner/planning-context.ts +15 -0
  424. package/src/planner/rules/access/rule-select-access-path.ts +68 -64
  425. package/src/planner/rules/aggregate/rule-aggregate-streaming.ts +74 -2
  426. package/src/planner/rules/cache/rule-materialization-advisory.ts +31 -27
  427. package/src/planner/scopes/base.ts +0 -17
  428. package/src/planner/scopes/empty.ts +0 -10
  429. package/src/planner/scopes/multi.ts +0 -1
  430. package/src/planner/scopes/param.ts +0 -1
  431. package/src/planner/scopes/registered.ts +1 -20
  432. package/src/planner/scopes/scope.ts +0 -12
  433. package/src/planner/validation/plan-validator.ts +1 -8
  434. package/src/runtime/context-helpers.ts +191 -0
  435. package/src/runtime/emission-context.ts +5 -2
  436. package/src/runtime/emit/aggregate.ts +131 -85
  437. package/src/runtime/emit/between.ts +51 -0
  438. package/src/runtime/emit/binary.ts +0 -46
  439. package/src/runtime/emit/column-reference.ts +3 -36
  440. package/src/runtime/emit/constraint-check.ts +17 -142
  441. package/src/runtime/emit/cte-reference.ts +23 -60
  442. package/src/runtime/emit/distinct.ts +2 -7
  443. package/src/runtime/emit/filter.ts +6 -13
  444. package/src/runtime/emit/internal-recursive-cte-ref.ts +37 -0
  445. package/src/runtime/emit/join.ts +45 -43
  446. package/src/runtime/emit/project.ts +18 -12
  447. package/src/runtime/emit/recursive-cte.ts +3 -12
  448. package/src/runtime/emit/returning.ts +7 -14
  449. package/src/runtime/emit/scan.ts +25 -23
  450. package/src/runtime/emit/sort.ts +8 -11
  451. package/src/runtime/emit/subquery.ts +108 -48
  452. package/src/runtime/emit/table-valued-function.ts +7 -20
  453. package/src/runtime/emit/update.ts +22 -29
  454. package/src/runtime/emit/window.ts +74 -88
  455. package/src/runtime/emitters.ts +52 -1
  456. package/src/runtime/register.ts +5 -4
  457. package/src/runtime/scheduler.ts +54 -54
  458. package/src/runtime/types.ts +45 -0
  459. package/src/schema/manager.ts +34 -19
  460. package/src/util/plugin-loader.ts +78 -4
  461. package/src/util/working-table-iterable.ts +15 -7
  462. package/src/vtab/manifest.ts +42 -0
  463. package/src/planner/nodes/scan.ts +0 -103
  464. package/src/planner/rules/physical/rule-mark-physical.ts +0 -37
  465. package/src/runtime/emit/table-reference.ts +0 -92
@@ -1,270 +1,281 @@
1
- /**
2
- * Constant folding analysis for the Titan optimizer
3
- *
4
- * This module implements efficient single-pass constant folding:
5
- * 1. Bottom-up classification: Assign ConstInfo to every node during post-order DFS
6
- * 2. Top-down border detection: Identify const nodes whose parents are non-const
7
- * 3. Replacement: Replace border nodes with appropriate literals
8
- */
9
-
10
- import { PlanNode } from '../nodes/plan-node.js';
11
- import { PlanNodeType } from '../nodes/plan-node-type.js';
12
- import { type SqlValue, type MaybePromise, OutputValue } from '../../common/types.js';
13
- import { LiteralNode } from '../nodes/scalar.js';
14
- import { createLogger } from '../../common/logger.js';
15
-
16
- const log = createLogger('optimizer:folding');
17
-
18
- /**
19
- * Constant information classification for plan nodes
20
- */
21
- interface ConstInfoConst {
22
- kind: 'const';
23
- node: PlanNode; // Store the const node itself, not its value
24
- }
25
-
26
- interface ConstInfoDep {
27
- kind: 'dep';
28
- deps: Set<number>; // Set of AttributeId
29
- }
30
-
31
- interface ConstInfoVar {
32
- kind: 'non-const';
33
- }
34
-
35
- type ConstInfo = ConstInfoConst | ConstInfoDep | ConstInfoVar;
36
-
37
- /**
38
- * Context for constant folding analysis
39
- */
40
- export interface ConstFoldingContext {
41
- /** Map from node ID to ConstInfo classification */
42
- constInfo: Map<string, ConstInfo>;
43
- /** Border nodes that need evaluation (nodeId -> node) */
44
- borderNodes: Map<string, PlanNode>;
45
- /** Evaluation function for border expressions */
46
- evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>;
47
- }
48
-
49
- /**
50
- * Create a new constant folding context
51
- */
52
- export function createConstFoldingContext(
53
- evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>
54
- ): ConstFoldingContext {
55
- return {
56
- constInfo: new Map(),
57
- borderNodes: new Map(),
58
- evaluateExpression
59
- };
60
- }
61
-
62
- /**
63
- * Perform complete single-pass constant folding on a plan tree
64
- * This is the main entry point for efficient constant folding
65
- */
66
- export function performConstantFolding(
67
- root: PlanNode,
68
- evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>
69
- ): PlanNode {
70
- const ctx = createConstFoldingContext(evaluateExpression);
71
-
72
- // Phase 1: Bottom-up classification
73
- classifyConstants(root, ctx);
74
-
75
- // Phase 2: Top-down border detection with dependency resolution
76
- detectBorderNodes(root, ctx, new Set());
77
-
78
- // Phase 3: Replace border nodes
79
- return replaceBorderNodes(root, ctx);
80
- }
81
-
82
- /**
83
- * Perform bottom-up constant classification on a plan tree
84
- */
85
- export function classifyConstants(root: PlanNode, ctx: ConstFoldingContext): void {
86
- // Post-order DFS - classify children before parent
87
- const children = root.getChildren();
88
- for (const child of children) {
89
- classifyConstants(child, ctx);
90
- }
91
-
92
- // Classify this node based on its type and children
93
- const constInfo = classifyNode(root, ctx);
94
- ctx.constInfo.set(root.id, constInfo);
95
-
96
- log('Classified node %s (%s): %s', root.id, root.nodeType,
97
- constInfo.kind === 'const' ? `const` :
98
- constInfo.kind === 'dep' ? `dep([${Array.from(constInfo.deps).join(',')}])` :
99
- 'non-const');
100
- }
101
-
102
- /**
103
- * Classify a single node - works for ANY node type
104
- */
105
- function classifyNode(node: PlanNode, ctx: ConstFoldingContext): ConstInfo {
106
- // Rule 1: Any node with physical.constant === true
107
- if (node.physical.constant) {
108
- if ('getValue' in node) {
109
- return { kind: 'const', node: node };
110
- }
111
- throw new Error(`Node ${node} is constant but does not implement getValue()`);
112
- }
113
-
114
- // Rule 2: ColumnReference → dep with {attrId}
115
- if (node.nodeType === PlanNodeType.ColumnReference) {
116
- const colRef = node as any; // ColumnReferenceNode
117
- return { kind: 'dep', deps: new Set([colRef.attributeId]) };
118
- }
119
-
120
- // Rule 3: Any other node - check if functional and inspect children
121
- if (!PlanNode.isFunctional(node.physical)) {
122
- return { kind: 'non-const' };
123
- }
124
-
125
- // Inspect children (works for both scalar and relational children)
126
- const childConstInfos = node.getChildren().map(child => {
127
- const childInfo = ctx.constInfo.get(child.id);
128
- if (!childInfo) {
129
- throw new Error(`No ConstInfo found for child node ${child.id}`);
130
- }
131
- return childInfo;
132
- });
133
-
134
- // If all children are const → this node is const
135
- if (childConstInfos.every(info => info.kind === 'const')) {
136
- return { kind: 'const', node: node };
137
- }
138
-
139
- // If all children ∈ {const, dep} → dep with union of child deps
140
- if (childConstInfos.every(info => info.kind === 'const' || info.kind === 'dep')) {
141
- const allDeps = new Set<number>();
142
- for (const info of childConstInfos) {
143
- if (info.kind === 'dep') {
144
- for (const dep of info.deps) {
145
- allDeps.add(dep);
146
- }
147
- }
148
- }
149
- return { kind: 'dep', deps: allDeps };
150
- }
151
-
152
- // Otherwise → non-const
153
- return { kind: 'non-const' };
154
- }
155
-
156
- /**
157
- * Top-down border detection with dependency resolution
158
- * A border node is:
159
- * - A const node (always foldable)
160
- * - A dep node whose dependencies are all resolved by known constant attributes
161
- */
162
- function detectBorderNodes(
163
- node: PlanNode,
164
- ctx: ConstFoldingContext,
165
- knownConstAttrs: Set<number> = new Set()
166
- ): void {
167
- const nodeInfo = ctx.constInfo.get(node.id);
168
-
169
- // Check if this node is a border node
170
- if (nodeInfo?.kind === 'const') {
171
- // Const nodes are always border nodes
172
- ctx.borderNodes.set(node.id, node);
173
- log('Detected const border node: %s (%s)', node.id, node.nodeType);
174
- // Don't recurse into const subtrees - they'll all be replaced
175
- return;
176
- } else if (nodeInfo?.kind === 'dep') {
177
- // Dep nodes become border nodes if all dependencies are resolved
178
- if (isSubsetOf(nodeInfo.deps, knownConstAttrs)) {
179
- ctx.borderNodes.set(node.id, node);
180
- log('Detected resolved dep border node: %s (%s) - deps %s resolved by %s',
181
- node.id, node.nodeType,
182
- Array.from(nodeInfo.deps).join(','),
183
- Array.from(knownConstAttrs).join(','));
184
- // Don't recurse - this entire subtree will be replaced
185
- return;
186
- }
187
- }
188
-
189
- // Update known constant attributes for this scope
190
- const updatedKnownAttrs = new Set(knownConstAttrs);
191
-
192
- // If this is a relational node that produces expressions, check what new constants it introduces
193
- if (node.getType().typeClass === 'relation' && 'getProducingExprs' in node) {
194
- const producingExprs = (node as any).getProducingExprs();
195
-
196
- if (producingExprs) {
197
- for (const [attrId, expr] of producingExprs) {
198
- const exprInfo = ctx.constInfo.get(expr.id);
199
-
200
- if (exprInfo?.kind === 'const') {
201
- // This expression produces a constant attribute
202
- updatedKnownAttrs.add(attrId);
203
- log('Node %s produces constant attribute %d', node.id, attrId);
204
- } else if (exprInfo?.kind === 'dep' && isSubsetOf(exprInfo.deps, knownConstAttrs)) {
205
- // This expression's dependencies are resolved, so it produces a constant
206
- updatedKnownAttrs.add(attrId);
207
- log('Node %s produces resolved constant attribute %d (was dep on %s)',
208
- node.id, attrId, Array.from(exprInfo.deps).join(','));
209
- }
210
- }
211
- }
212
- }
213
-
214
- // Recurse to children with updated known constant attributes
215
- for (const child of node.getChildren()) {
216
- detectBorderNodes(child, ctx, updatedKnownAttrs);
217
- }
218
- }
219
-
220
- /**
221
- * Utility function to check if set A is a subset of set B
222
- */
223
- function isSubsetOf<T>(setA: Set<T>, setB: Set<T>): boolean {
224
- if (setA.size === 0) return true; // Empty set is subset of everything
225
- for (const elem of setA) {
226
- if (!setB.has(elem)) {
227
- return false;
228
- }
229
- }
230
- return true;
231
- }
232
-
233
- /**
234
- * Replace border nodes with appropriate literals
235
- */
236
- function replaceBorderNodes(node: PlanNode, ctx: ConstFoldingContext): PlanNode {
237
- // If this node is a border node, replace it
238
- if (ctx.borderNodes.has(node.id)) {
239
- try {
240
- const evaluatedValue = ctx.evaluateExpression(node);
241
-
242
- // Choose replacement type based on node type
243
- if (node.getType().typeClass === 'scalar') {
244
- const literalExpr = { type: 'literal' as const, value: evaluatedValue as SqlValue };
245
- const replacement = new LiteralNode(node.scope, literalExpr);
246
- log('Replaced scalar border node %s with LiteralNode', node.id);
247
- return replacement;
248
- } else {
249
- // Relational node - replace with TableLiteralNode
250
- // TODO: Handle relational evaluation properly
251
- log('Relational border node %s detected but not yet implemented', node.id);
252
- return node;
253
- }
254
- } catch (error) {
255
- log('Failed to evaluate border node %s: %s', node.id, error);
256
- return node;
257
- }
258
- }
259
-
260
- // Recursively replace children
261
- const children = node.getChildren();
262
- const replacedChildren = children.map(child => replaceBorderNodes(child, ctx));
263
-
264
- // If any children changed, create new node
265
- if (replacedChildren.some((child, i) => child !== children[i])) {
266
- return node.withChildren(replacedChildren);
267
- }
268
-
269
- return node;
270
- }
1
+ /**
2
+ * Constant folding analysis for the Titan optimizer
3
+ *
4
+ * This module implements efficient single-pass constant folding:
5
+ * 1. Bottom-up classification: Assign ConstInfo to every node during post-order DFS
6
+ * 2. Top-down border detection: Identify const nodes whose parents are non-const
7
+ * 3. Replacement: Replace border nodes with appropriate literals
8
+ */
9
+
10
+ import { PlanNode } from '../nodes/plan-node.js';
11
+ import { PlanNodeType } from '../nodes/plan-node-type.js';
12
+ import { type SqlValue, type MaybePromise, OutputValue } from '../../common/types.js';
13
+ import { LiteralNode } from '../nodes/scalar.js';
14
+ import { createLogger } from '../../common/logger.js';
15
+ import type { ScalarType } from '../../common/datatype.js';
16
+
17
+ const log = createLogger('optimizer:folding');
18
+
19
+ /**
20
+ * Constant information classification for plan nodes
21
+ */
22
+ interface ConstInfoConst {
23
+ kind: 'const';
24
+ node: PlanNode; // Store the const node itself, not its value
25
+ }
26
+
27
+ interface ConstInfoDep {
28
+ kind: 'dep';
29
+ deps: Set<number>; // Set of AttributeId
30
+ }
31
+
32
+ interface ConstInfoVar {
33
+ kind: 'non-const';
34
+ }
35
+
36
+ type ConstInfo = ConstInfoConst | ConstInfoDep | ConstInfoVar;
37
+
38
+ /**
39
+ * Context for constant folding analysis
40
+ */
41
+ export interface ConstFoldingContext {
42
+ /** Map from node ID to ConstInfo classification */
43
+ constInfo: Map<string, ConstInfo>;
44
+ /** Border nodes that need evaluation (nodeId -> node) */
45
+ borderNodes: Map<string, PlanNode>;
46
+ /** Evaluation function for border expressions */
47
+ evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>;
48
+ }
49
+
50
+ /**
51
+ * Create a new constant folding context
52
+ */
53
+ export function createConstFoldingContext(
54
+ evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>
55
+ ): ConstFoldingContext {
56
+ return {
57
+ constInfo: new Map(),
58
+ borderNodes: new Map(),
59
+ evaluateExpression
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Perform complete single-pass constant folding on a plan tree
65
+ * This is the main entry point for efficient constant folding
66
+ */
67
+ export function performConstantFolding(
68
+ root: PlanNode,
69
+ evaluateExpression: (node: PlanNode) => MaybePromise<OutputValue>
70
+ ): PlanNode {
71
+ const ctx = createConstFoldingContext(evaluateExpression);
72
+
73
+ // Phase 1: Bottom-up classification
74
+ classifyConstants(root, ctx);
75
+
76
+ // Phase 2: Top-down border detection with dependency resolution
77
+ detectBorderNodes(root, ctx, new Set());
78
+
79
+ // Phase 3: Replace border nodes
80
+ return replaceBorderNodes(root, ctx);
81
+ }
82
+
83
+ /**
84
+ * Perform bottom-up constant classification on a plan tree
85
+ */
86
+ export function classifyConstants(root: PlanNode, ctx: ConstFoldingContext): void {
87
+ // Post-order DFS - classify children before parent
88
+ const children = root.getChildren();
89
+ for (const child of children) {
90
+ classifyConstants(child, ctx);
91
+ }
92
+
93
+ // Classify this node based on its type and children
94
+ const constInfo = classifyNode(root, ctx);
95
+ ctx.constInfo.set(root.id, constInfo);
96
+
97
+ log('Classified node %s (%s): %s', root.id, root.nodeType,
98
+ constInfo.kind === 'const' ? `const` :
99
+ constInfo.kind === 'dep' ? `dep([${Array.from(constInfo.deps).join(',')}])` :
100
+ 'non-const');
101
+ }
102
+
103
+ /**
104
+ * Classify a single node - works for ANY node type
105
+ */
106
+ function classifyNode(node: PlanNode, ctx: ConstFoldingContext): ConstInfo {
107
+ // Rule 1: Any node with physical.constant === true
108
+ if (node.physical.constant) {
109
+ if ('getValue' in node) {
110
+ return { kind: 'const', node: node };
111
+ }
112
+ throw new Error(`Node ${node} is constant but does not implement getValue()`);
113
+ }
114
+
115
+ // Rule 2: ColumnReference → dep with {attrId}
116
+ if (node.nodeType === PlanNodeType.ColumnReference) {
117
+ const colRef = node as any; // ColumnReferenceNode
118
+ return { kind: 'dep', deps: new Set([colRef.attributeId]) };
119
+ }
120
+
121
+ // Rule 3: Any other node - check if functional and inspect children
122
+ if (!PlanNode.isFunctional(node.physical)) {
123
+ return { kind: 'non-const' };
124
+ }
125
+
126
+ // Inspect children (works for both scalar and relational children)
127
+ const childConstInfos = node.getChildren().map(child => {
128
+ const childInfo = ctx.constInfo.get(child.id);
129
+ if (!childInfo) {
130
+ throw new Error(`No ConstInfo found for child node ${child.id}`);
131
+ }
132
+ return childInfo;
133
+ });
134
+
135
+ // If all children are const → this node is const
136
+ // IMPORTANT: Only nodes with children can inherit const status
137
+ if (childConstInfos.length > 0 && childConstInfos.every(info => info.kind === 'const')) {
138
+ return { kind: 'const', node: node };
139
+ }
140
+
141
+ // If all children ∈ {const, dep} dep with union of child deps
142
+ if (childConstInfos.length > 0 && childConstInfos.every(info => info.kind === 'const' || info.kind === 'dep')) {
143
+ const allDeps = new Set<number>();
144
+ for (const info of childConstInfos) {
145
+ if (info.kind === 'dep') {
146
+ for (const dep of info.deps) {
147
+ allDeps.add(dep);
148
+ }
149
+ }
150
+ }
151
+ return { kind: 'dep', deps: allDeps };
152
+ }
153
+
154
+ // Otherwise → non-const
155
+ return { kind: 'non-const' };
156
+ }
157
+
158
+ /**
159
+ * Top-down border detection with dependency resolution
160
+ * A border node is:
161
+ * - A const node (always foldable)
162
+ * - A dep node whose dependencies are all resolved by known constant attributes
163
+ */
164
+ function detectBorderNodes(
165
+ node: PlanNode,
166
+ ctx: ConstFoldingContext,
167
+ knownConstAttrs: Set<number> = new Set()
168
+ ): void {
169
+ const nodeInfo = ctx.constInfo.get(node.id);
170
+
171
+ // Check if this node is a border node
172
+ if (nodeInfo?.kind === 'const') {
173
+ if (!node.physical.constant) {
174
+ // Const nodes are always border nodes
175
+ ctx.borderNodes.set(node.id, node);
176
+ log('Detected const border node: %s (%s)', node.id, node.nodeType);
177
+ }
178
+ // Don't recurse into const subtrees - they'll all be replaced
179
+ return;
180
+ } else if (nodeInfo?.kind === 'dep') {
181
+ // Dep nodes become border nodes if all dependencies are resolved
182
+ if (isSubsetOf(nodeInfo.deps, knownConstAttrs)) {
183
+ ctx.borderNodes.set(node.id, node);
184
+ log('Detected resolved dep border node: %s (%s) - deps %s resolved by %s',
185
+ node.id, node.nodeType,
186
+ Array.from(nodeInfo.deps).join(','),
187
+ Array.from(knownConstAttrs).join(','));
188
+ // Don't recurse - this entire subtree will be replaced
189
+ return;
190
+ }
191
+ }
192
+
193
+ // Update known constant attributes for this scope
194
+ const updatedKnownAttrs = new Set(knownConstAttrs);
195
+
196
+ // If this is a relational node that produces expressions, check what new constants it introduces
197
+ if (node.getType().typeClass === 'relation' && 'getProducingExprs' in node) {
198
+ const producingExprs = (node as any).getProducingExprs();
199
+
200
+ if (producingExprs) {
201
+ for (const [attrId, expr] of producingExprs) {
202
+ const exprInfo = ctx.constInfo.get(expr.id);
203
+
204
+ if (exprInfo?.kind === 'const') {
205
+ // This expression produces a constant attribute
206
+ updatedKnownAttrs.add(attrId);
207
+ log('Node %s produces constant attribute %d', node.id, attrId);
208
+ } else if (exprInfo?.kind === 'dep' && isSubsetOf(exprInfo.deps, knownConstAttrs)) {
209
+ // This expression's dependencies are resolved, so it produces a constant
210
+ updatedKnownAttrs.add(attrId);
211
+ log('Node %s produces resolved constant attribute %d (was dep on %s)',
212
+ node.id, attrId, Array.from(exprInfo.deps).join(','));
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ // Recurse to children with updated known constant attributes
219
+ for (const child of node.getChildren()) {
220
+ detectBorderNodes(child, ctx, updatedKnownAttrs);
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Utility function to check if set A is a subset of set B
226
+ */
227
+ function isSubsetOf<T>(setA: Set<T>, setB: Set<T>): boolean {
228
+ if (setA.size === 0) return true; // Empty set is subset of everything
229
+ for (const elem of setA) {
230
+ if (!setB.has(elem)) {
231
+ return false;
232
+ }
233
+ }
234
+ return true;
235
+ }
236
+
237
+ /**
238
+ * Replace border nodes with appropriate literals
239
+ */
240
+ function replaceBorderNodes(node: PlanNode, ctx: ConstFoldingContext): PlanNode {
241
+ // If this node is a border node, replace it
242
+ if (ctx.borderNodes.has(node.id)) {
243
+ try {
244
+ const evaluatedValue = ctx.evaluateExpression(node);
245
+
246
+ // Choose replacement type based on node type
247
+ if (node.getType().typeClass === 'scalar') {
248
+ const literalExpr = { type: 'literal' as const, value: evaluatedValue as SqlValue };
249
+
250
+ const replacement = new LiteralNode(
251
+ node.scope,
252
+ literalExpr,
253
+ // Preserve the original node's type metadata so that information like
254
+ // collation sequences survives the folding pass.
255
+ node.getType() as ScalarType
256
+ );
257
+ log('Replaced scalar border node %s with LiteralNode', node.id);
258
+ return replacement;
259
+ } else {
260
+ // Relational node - replace with TableLiteralNode
261
+ // TODO: Handle relational evaluation properly
262
+ log('Relational border node %s detected but not yet implemented', node.id);
263
+ return node;
264
+ }
265
+ } catch (error) {
266
+ log('Failed to evaluate border node %s: %s', node.id, error);
267
+ return node;
268
+ }
269
+ }
270
+
271
+ // Recursively replace children
272
+ const children = node.getChildren();
273
+ const replacedChildren = children.map(child => replaceBorderNodes(child, ctx));
274
+
275
+ // If any children changed, create new node
276
+ if (replacedChildren.some((child, i) => child !== children[i])) {
277
+ return node.withChildren(replacedChildren);
278
+ }
279
+
280
+ return node;
281
+ }