@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
@@ -10,6 +10,7 @@ import { createLogger } from '../../common/logger.js';
10
10
  import { StatusCode } from '../../common/types.js';
11
11
  import { quereusError } from '../../common/errors.js';
12
12
  import { Database } from '../../core/database.js';
13
+ import type { PlanNode } from '../nodes/plan-node.js';
13
14
 
14
15
  const log = createLogger('optimizer:framework:context');
15
16
 
@@ -38,6 +39,12 @@ export interface OptContext {
38
39
 
39
40
  /** Database instance */
40
41
  readonly db: Database;
42
+
43
+ /** Context-scoped visited rules tracking (nodeId → ruleIds) */
44
+ readonly visitedRules: Map<string, Set<string>>;
45
+
46
+ /** Cache of already-optimized nodes within this context (nodeId → optimized result) */
47
+ readonly optimizedNodes: Map<string, PlanNode>;
41
48
  }
42
49
 
43
50
  /**
@@ -45,6 +52,8 @@ export interface OptContext {
45
52
  */
46
53
  export class OptimizationContext implements OptContext {
47
54
  readonly context = new Map<string, any>();
55
+ readonly visitedRules = new Map<string, Set<string>>();
56
+ readonly optimizedNodes = new Map<string, PlanNode>();
48
57
 
49
58
  constructor(
50
59
  public readonly optimizer: Optimizer,
@@ -61,7 +70,7 @@ export class OptimizationContext implements OptContext {
61
70
  * Create a new context for a different phase
62
71
  */
63
72
  withPhase(phase: 'rewrite' | 'impl'): OptimizationContext {
64
- return new OptimizationContext(
73
+ const newContext = new OptimizationContext(
65
74
  this.optimizer,
66
75
  this.stats,
67
76
  this.tuning,
@@ -69,6 +78,10 @@ export class OptimizationContext implements OptContext {
69
78
  this.db,
70
79
  this.depth,
71
80
  );
81
+
82
+ // Copy visited tracking state
83
+ this.copyTrackingState(newContext);
84
+ return newContext;
72
85
  }
73
86
 
74
87
  /**
@@ -79,7 +92,7 @@ export class OptimizationContext implements OptContext {
79
92
  quereusError(`Maximum optimization depth exceeded: ${this.depth}`, StatusCode.ERROR);
80
93
  }
81
94
 
82
- return new OptimizationContext(
95
+ const newContext = new OptimizationContext(
83
96
  this.optimizer,
84
97
  this.stats,
85
98
  this.tuning,
@@ -87,6 +100,10 @@ export class OptimizationContext implements OptContext {
87
100
  this.db,
88
101
  this.depth + 1,
89
102
  );
103
+
104
+ // Copy visited tracking state
105
+ this.copyTrackingState(newContext);
106
+ return newContext;
90
107
  }
91
108
 
92
109
  /**
@@ -110,9 +127,26 @@ export class OptimizationContext implements OptContext {
110
127
  // Add new context
111
128
  newContext.context.set(key, value);
112
129
 
130
+ // Copy visited tracking state
131
+ this.copyTrackingState(newContext);
113
132
  return newContext;
114
133
  }
115
134
 
135
+ /**
136
+ * Copy visited tracking state to another context
137
+ */
138
+ private copyTrackingState(target: OptimizationContext): void {
139
+ // Copy visitedRules
140
+ for (const [nodeId, ruleIds] of this.visitedRules) {
141
+ target.visitedRules.set(nodeId, new Set(ruleIds));
142
+ }
143
+
144
+ // Copy optimizedNodes
145
+ for (const [nodeId, node] of this.optimizedNodes) {
146
+ target.optimizedNodes.set(nodeId, node);
147
+ }
148
+ }
149
+
116
150
  /**
117
151
  * Get context value
118
152
  */
@@ -1,274 +1,261 @@
1
- /**
2
- * Rule registration and management framework for the Titan optimizer
3
- * Provides centralized rule registry with tracing and loop detection
4
- */
5
-
6
- import { createLogger } from '../../common/logger.js';
7
- import type { PlanNode } from '../nodes/plan-node.js';
8
- import { PlanNodeType } from '../nodes/plan-node-type.js';
9
- import type { OptContext } from './context.js';
10
- import { traceRuleStart, traceRuleEnd } from './trace.js';
11
- import { StatusCode } from '../../common/types.js';
12
- import { quereusError } from '../../common/errors.js';
13
-
14
- const log = createLogger('optimizer:framework:registry');
15
-
16
- /**
17
- * Rule function signature for optimization transformations
18
- */
19
- export type RuleFn = (node: PlanNode, context: OptContext) => PlanNode | null;
20
-
21
- /**
22
- * Rule phases for categorizing optimization rules
23
- */
24
- export type RulePhase = 'rewrite' | 'impl';
25
-
26
- /**
27
- * Handle for registered optimization rules
28
- */
29
- export interface RuleHandle {
30
- /** Unique identifier for this rule */
31
- id: string;
32
- /** Node type this rule applies to */
33
- nodeType: PlanNodeType;
34
- /** Phase classification */
35
- phase: RulePhase;
36
- /** Rule implementation function */
37
- fn: RuleFn;
38
- /** Optional priority (lower numbers run first) */
39
- priority?: number;
40
- }
41
-
42
- /**
43
- * Global rule registry
44
- */
45
- class RuleRegistry {
46
- private rules = new Map<PlanNodeType, RuleHandle[]>();
47
- private visitedRules = new Map<string, Set<string>>(); // nodeId -> ruleIds applied
48
-
49
- /**
50
- * Register a new optimization rule
51
- */
52
- registerRule(handle: RuleHandle): void {
53
- if (!this.rules.has(handle.nodeType)) {
54
- this.rules.set(handle.nodeType, []);
55
- }
56
-
57
- const nodeRules = this.rules.get(handle.nodeType)!;
58
-
59
- // Check for duplicate rule IDs
60
- if (nodeRules.some(r => r.id === handle.id)) {
61
- quereusError(`Optimization rule '${handle.id}' already registered for node type ${handle.nodeType}`, StatusCode.INTERNAL);
62
- }
63
-
64
- // Insert rule maintaining priority order (lower priority first)
65
- const priority = handle.priority ?? 100;
66
- const insertIndex = nodeRules.findIndex(r => (r.priority ?? 100) > priority);
67
- if (insertIndex === -1) {
68
- nodeRules.push(handle);
69
- } else {
70
- nodeRules.splice(insertIndex, 0, handle);
71
- }
72
-
73
- log('Registered rule %s for %s (phase: %s, priority: %d)',
74
- handle.id, handle.nodeType, handle.phase, priority);
75
- }
76
-
77
- /**
78
- * Get all rules for a specific node type
79
- */
80
- rulesFor(nodeType: PlanNodeType): readonly RuleHandle[] {
81
- return this.rules.get(nodeType) ?? [];
82
- }
83
-
84
- /**
85
- * Check if a rule has already been applied to a node
86
- */
87
- hasRuleBeenApplied(nodeId: string, ruleId: string): boolean {
88
- const nodeVisited = this.visitedRules.get(nodeId);
89
- return nodeVisited?.has(ruleId) ?? false;
90
- }
91
-
92
- /**
93
- * Mark a rule as applied to a node
94
- */
95
- markRuleApplied(nodeId: string, ruleId: string): void {
96
- if (!this.visitedRules.has(nodeId)) {
97
- this.visitedRules.set(nodeId, new Set());
98
- }
99
- this.visitedRules.get(nodeId)!.add(ruleId);
100
- }
101
-
102
- /**
103
- * Clear visited rules (typically called at start of optimization)
104
- */
105
- clearVisitedRules(): void {
106
- this.visitedRules.clear();
107
- }
108
-
109
- /**
110
- * Get all registered rules (for debugging)
111
- */
112
- getAllRules(): Map<PlanNodeType, readonly RuleHandle[]> {
113
- const result = new Map<PlanNodeType, readonly RuleHandle[]>();
114
- for (const [nodeType, rules] of this.rules) {
115
- result.set(nodeType, [...rules]);
116
- }
117
- return result;
118
- }
119
-
120
- /**
121
- * Get statistics about rule application
122
- */
123
- getStats(): { totalRules: number; nodesWithRules: number; appliedRules: number } {
124
- let totalRules = 0;
125
- for (const rules of this.rules.values()) {
126
- totalRules += rules.length;
127
- }
128
-
129
- let appliedRules = 0;
130
- for (const ruleSet of this.visitedRules.values()) {
131
- appliedRules += ruleSet.size;
132
- }
133
-
134
- return {
135
- totalRules,
136
- nodesWithRules: this.visitedRules.size,
137
- appliedRules
138
- };
139
- }
140
- }
141
-
142
- /**
143
- * Global registry instance
144
- */
145
- const globalRegistry = new RuleRegistry();
146
-
147
- /**
148
- * Register an optimization rule
149
- */
150
- export function registerRule(handle: RuleHandle): void {
151
- globalRegistry.registerRule(handle);
152
- }
153
-
154
- /**
155
- * Get rules for a specific node type
156
- */
157
- export function rulesFor(nodeType: PlanNodeType): readonly RuleHandle[] {
158
- return globalRegistry.rulesFor(nodeType);
159
- }
160
-
161
- /**
162
- * Check if a rule has been applied to a node
163
- */
164
- export function hasRuleBeenApplied(nodeId: string, ruleId: string): boolean {
165
- return globalRegistry.hasRuleBeenApplied(nodeId, ruleId);
166
- }
167
-
168
- /**
169
- * Mark a rule as applied to a node
170
- */
171
- export function markRuleApplied(nodeId: string, ruleId: string): void {
172
- globalRegistry.markRuleApplied(nodeId, ruleId);
173
- }
174
-
175
- /**
176
- * Clear all visited rule tracking
177
- */
178
- export function clearVisitedRules(): void {
179
- globalRegistry.clearVisitedRules();
180
- }
181
-
182
- /**
183
- * Get registry statistics
184
- */
185
- export function getRegistryStats(): { totalRules: number; nodesWithRules: number; appliedRules: number } {
186
- return globalRegistry.getStats();
187
- }
188
-
189
- /**
190
- * Get all registered rules (for debugging/tooling)
191
- */
192
- export function getAllRules(): Map<PlanNodeType, readonly RuleHandle[]> {
193
- return globalRegistry.getAllRules();
194
- }
195
-
196
- /**
197
- * Apply rules to a node with tracing and loop detection
198
- */
199
- export function applyRules(node: PlanNode, context: OptContext): PlanNode {
200
- const applicableRules = rulesFor(node.nodeType);
201
-
202
- if (applicableRules.length === 0) {
203
- return node;
204
- }
205
-
206
- let currentNode = node;
207
- let appliedAnyRule = false;
208
-
209
- for (const rule of applicableRules) {
210
- // Skip if rule already applied to this node
211
- if (hasRuleBeenApplied(currentNode.id, rule.id)) {
212
- log('Skipping rule %s for node %s (already applied)', rule.id, currentNode.id);
213
- continue;
214
- }
215
-
216
- try {
217
- const ruleLog = createLogger(`optimizer:rule:${rule.id}`);
218
-
219
- // Trace rule start
220
- traceRuleStart(rule, currentNode);
221
- ruleLog('Applying rule to node %s', currentNode.id);
222
-
223
- const result = rule.fn(currentNode, context);
224
-
225
- if (result && result !== currentNode) {
226
- ruleLog('Rule transformed %s to %s', currentNode.nodeType, result.nodeType);
227
- markRuleApplied(currentNode.id, rule.id);
228
-
229
- // Trace successful transformation
230
- traceRuleEnd(rule, currentNode, result);
231
-
232
- currentNode = result;
233
- appliedAnyRule = true;
234
- } else {
235
- ruleLog('Rule not applicable to node %s', currentNode.id);
236
-
237
- // Trace rule not applicable
238
- traceRuleEnd(rule, currentNode, null);
239
- }
240
- } catch (error) {
241
- const errorMsg = error instanceof Error ? error.message : String(error);
242
- log('Rule %s failed on node %s: %s', rule.id, currentNode.id, errorMsg);
243
- // Continue with other rules rather than failing entire optimization
244
- }
245
- }
246
-
247
- if (appliedAnyRule) {
248
- log('Applied rules to node %s, result: %s', node.id, currentNode.nodeType);
249
- }
250
-
251
- return currentNode;
252
- }
253
-
254
- /**
255
- * Convenience function to register multiple rules at once
256
- */
257
- export function registerRules(rules: RuleHandle[]): void {
258
- for (const rule of rules) {
259
- registerRule(rule);
260
- }
261
- }
262
-
263
- /**
264
- * Helper to create rule handles with common patterns
265
- */
266
- export function createRule(
267
- id: string,
268
- nodeType: PlanNodeType,
269
- phase: RulePhase,
270
- fn: RuleFn,
271
- priority?: number
272
- ): RuleHandle {
273
- return { id, nodeType, phase, fn, priority };
274
- }
1
+ /**
2
+ * Rule registration and management framework for the Titan optimizer
3
+ * Provides centralized rule registry with tracing and loop detection
4
+ */
5
+
6
+ import { createLogger } from '../../common/logger.js';
7
+ import type { PlanNode } from '../nodes/plan-node.js';
8
+ import { PlanNodeType } from '../nodes/plan-node-type.js';
9
+ import type { OptContext } from './context.js';
10
+ import { traceRuleStart, traceRuleEnd } from './trace.js';
11
+ import { StatusCode } from '../../common/types.js';
12
+ import { quereusError } from '../../common/errors.js';
13
+
14
+ const log = createLogger('optimizer:framework:registry');
15
+
16
+ /**
17
+ * Rule function signature for optimization transformations
18
+ */
19
+ export type RuleFn = (node: PlanNode, context: OptContext) => PlanNode | null;
20
+
21
+ /**
22
+ * Rule phases for categorizing optimization rules
23
+ */
24
+ export type RulePhase = 'rewrite' | 'impl';
25
+
26
+ /**
27
+ * Handle for registered optimization rules
28
+ */
29
+ export interface RuleHandle {
30
+ /** Unique identifier for this rule */
31
+ id: string;
32
+ /** Node type this rule applies to */
33
+ nodeType: PlanNodeType;
34
+ /** Phase classification */
35
+ phase: RulePhase;
36
+ /** Rule implementation function */
37
+ fn: RuleFn;
38
+ /** Optional priority (lower numbers run first) */
39
+ priority?: number;
40
+ }
41
+
42
+ /**
43
+ * Global rule registry
44
+ */
45
+ class RuleRegistry {
46
+ private rules = new Map<PlanNodeType, RuleHandle[]>();
47
+
48
+ /**
49
+ * Register a new optimization rule
50
+ */
51
+ registerRule(handle: RuleHandle): void {
52
+ if (!this.rules.has(handle.nodeType)) {
53
+ this.rules.set(handle.nodeType, []);
54
+ }
55
+
56
+ const nodeRules = this.rules.get(handle.nodeType)!;
57
+
58
+ // Check for duplicate rule IDs
59
+ if (nodeRules.some(r => r.id === handle.id)) {
60
+ quereusError(`Optimization rule '${handle.id}' already registered for node type ${handle.nodeType}`, StatusCode.INTERNAL);
61
+ }
62
+
63
+ // Insert rule maintaining priority order (lower priority first)
64
+ const priority = handle.priority ?? 100;
65
+ const insertIndex = nodeRules.findIndex(r => (r.priority ?? 100) > priority);
66
+ if (insertIndex === -1) {
67
+ nodeRules.push(handle);
68
+ } else {
69
+ nodeRules.splice(insertIndex, 0, handle);
70
+ }
71
+
72
+ log('Registered rule %s for %s (phase: %s, priority: %d)',
73
+ handle.id, handle.nodeType, handle.phase, priority);
74
+ }
75
+
76
+ /**
77
+ * Get all rules for a specific node type
78
+ */
79
+ rulesFor(nodeType: PlanNodeType): readonly RuleHandle[] {
80
+ return this.rules.get(nodeType) ?? [];
81
+ }
82
+
83
+ /**
84
+ * Check if a rule has already been applied to a node
85
+ */
86
+ hasRuleBeenApplied(nodeId: string, ruleId: string, context: OptContext): boolean {
87
+ const nodeVisited = context.visitedRules.get(nodeId);
88
+ return nodeVisited?.has(ruleId) ?? false;
89
+ }
90
+
91
+ /**
92
+ * Mark a rule as applied to a node
93
+ */
94
+ markRuleApplied(nodeId: string, ruleId: string, context: OptContext): void {
95
+ if (!context.visitedRules.has(nodeId)) {
96
+ context.visitedRules.set(nodeId, new Set());
97
+ }
98
+ context.visitedRules.get(nodeId)!.add(ruleId);
99
+ }
100
+
101
+ /**
102
+ * Get all registered rules (for debugging)
103
+ */
104
+ getAllRules(): Map<PlanNodeType, readonly RuleHandle[]> {
105
+ const result = new Map<PlanNodeType, readonly RuleHandle[]>();
106
+ for (const [nodeType, rules] of this.rules) {
107
+ result.set(nodeType, [...rules]);
108
+ }
109
+ return result;
110
+ }
111
+
112
+ /**
113
+ * Get statistics about rule application
114
+ */
115
+ getStats(context?: OptContext): { totalRules: number; nodesWithRules: number; appliedRules: number } {
116
+ let totalRules = 0;
117
+ for (const rules of this.rules.values()) {
118
+ totalRules += rules.length;
119
+ }
120
+
121
+ let appliedRules = 0;
122
+ if (context) {
123
+ for (const ruleSet of context.visitedRules.values()) {
124
+ appliedRules += ruleSet.size;
125
+ }
126
+ }
127
+
128
+ return {
129
+ totalRules,
130
+ nodesWithRules: context?.visitedRules.size ?? 0,
131
+ appliedRules
132
+ };
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Global registry instance
138
+ */
139
+ const globalRegistry = new RuleRegistry();
140
+
141
+ /**
142
+ * Register an optimization rule
143
+ */
144
+ export function registerRule(handle: RuleHandle): void {
145
+ globalRegistry.registerRule(handle);
146
+ }
147
+
148
+ /**
149
+ * Get rules for a specific node type
150
+ */
151
+ export function rulesFor(nodeType: PlanNodeType): readonly RuleHandle[] {
152
+ return globalRegistry.rulesFor(nodeType);
153
+ }
154
+
155
+ /**
156
+ * Check if a rule has been applied to a node
157
+ */
158
+ export function hasRuleBeenApplied(nodeId: string, ruleId: string, context: OptContext): boolean {
159
+ return globalRegistry.hasRuleBeenApplied(nodeId, ruleId, context);
160
+ }
161
+
162
+ /**
163
+ * Mark a rule as applied to a node
164
+ */
165
+ export function markRuleApplied(nodeId: string, ruleId: string, context: OptContext): void {
166
+ globalRegistry.markRuleApplied(nodeId, ruleId, context);
167
+ }
168
+
169
+ /**
170
+ * Get registry statistics
171
+ */
172
+ export function getRegistryStats(context?: OptContext): { totalRules: number; nodesWithRules: number; appliedRules: number } {
173
+ return globalRegistry.getStats(context);
174
+ }
175
+
176
+ /**
177
+ * Get all registered rules (for debugging/tooling)
178
+ */
179
+ export function getAllRules(): Map<PlanNodeType, readonly RuleHandle[]> {
180
+ return globalRegistry.getAllRules();
181
+ }
182
+
183
+ /**
184
+ * Apply rules to a node with tracing and loop detection
185
+ */
186
+ export function applyRules(node: PlanNode, context: OptContext): PlanNode {
187
+ const applicableRules = rulesFor(node.nodeType);
188
+
189
+ if (applicableRules.length === 0) {
190
+ return node;
191
+ }
192
+
193
+ let currentNode = node;
194
+ let appliedAnyRule = false;
195
+
196
+ for (const rule of applicableRules) {
197
+ // Skip if rule already applied to this node
198
+ if (hasRuleBeenApplied(currentNode.id, rule.id, context)) {
199
+ log('Skipping rule %s for node %s (already applied)', rule.id, currentNode.id);
200
+ continue;
201
+ }
202
+
203
+ try {
204
+ const ruleLog = createLogger(`optimizer:rule:${rule.id}`);
205
+
206
+ // Trace rule start
207
+ traceRuleStart(rule, currentNode);
208
+ ruleLog('Applying rule to node %s', currentNode.id);
209
+
210
+ const result = rule.fn(currentNode, context);
211
+
212
+ if (result && result !== currentNode) {
213
+ ruleLog('Rule transformed %s to %s', currentNode.nodeType, result.nodeType);
214
+ markRuleApplied(currentNode.id, rule.id, context);
215
+
216
+ // Trace successful transformation
217
+ traceRuleEnd(rule, currentNode, result);
218
+
219
+ currentNode = result;
220
+ appliedAnyRule = true;
221
+ } else {
222
+ ruleLog('Rule not applicable to node %s', currentNode.id);
223
+
224
+ // Trace rule not applicable
225
+ traceRuleEnd(rule, currentNode, null);
226
+ }
227
+ } catch (error) {
228
+ const errorMsg = error instanceof Error ? error.message : String(error);
229
+ log('Rule %s failed on node %s: %s', rule.id, currentNode.id, errorMsg);
230
+ // Continue with other rules rather than failing entire optimization
231
+ }
232
+ }
233
+
234
+ if (appliedAnyRule) {
235
+ log('Applied rules to node %s, result: %s', node.id, currentNode.nodeType);
236
+ }
237
+
238
+ return currentNode;
239
+ }
240
+
241
+ /**
242
+ * Convenience function to register multiple rules at once
243
+ */
244
+ export function registerRules(rules: RuleHandle[]): void {
245
+ for (const rule of rules) {
246
+ registerRule(rule);
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Helper to create rule handles with common patterns
252
+ */
253
+ export function createRule(
254
+ id: string,
255
+ nodeType: PlanNodeType,
256
+ phase: RulePhase,
257
+ fn: RuleFn,
258
+ priority?: number
259
+ ): RuleHandle {
260
+ return { id, nodeType, phase, fn, priority };
261
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Scope } from '../scopes/scope.js';
2
- import { PlanNode, type VoidNode } from './plan-node.js';
2
+ import { PhysicalProperties, PlanNode, type VoidNode } from './plan-node.js';
3
3
  import { PlanNodeType } from './plan-node-type.js';
4
4
  import type { TableReferenceNode } from './reference.js';
5
5
  import type { VoidType } from '../../common/datatype.js';
@@ -55,4 +55,8 @@ export class AddConstraintNode extends PlanNode implements VoidNode {
55
55
  operations: this.constraint.operations,
56
56
  };
57
57
  }
58
+
59
+ override computePhysical(_children: readonly PhysicalProperties[]): Partial<PhysicalProperties> {
60
+ return { readonly: false };
61
+ }
58
62
  }