@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,5 +1,5 @@
1
1
  import type { Scope } from '../scopes/scope.js';
2
- import { PlanNode, type RelationalPlanNode, type Attribute } from './plan-node.js';
2
+ import { PlanNode, type RelationalPlanNode, type Attribute, isRelationalNode } from './plan-node.js';
3
3
  import { PlanNodeType } from './plan-node-type.js';
4
4
  import type { ScalarPlanNode } from './plan-node.js';
5
5
  import type { RelationType } from '../../common/datatype.js';
@@ -150,25 +150,37 @@ export class ReturningNode extends PlanNode implements RelationalPlanNode {
150
150
  return [this.executor];
151
151
  }
152
152
 
153
- getChildren(): readonly ScalarPlanNode[] {
154
- return this.projections.map(proj => proj.node);
153
+ getChildren(): readonly PlanNode[] {
154
+ // Return executor first, then all projection expressions
155
+ return [this.executor, ...this.projections.map(proj => proj.node)];
155
156
  }
156
157
 
157
158
  withChildren(newChildren: readonly PlanNode[]): PlanNode {
158
- if (newChildren.length !== this.projections.length) {
159
- throw new Error(`ReturningNode expects ${this.projections.length} children, got ${newChildren.length}`);
159
+ const expectedChildren = 1 + this.projections.length; // executor + projections
160
+ if (newChildren.length !== expectedChildren) {
161
+ throw new Error(`ReturningNode expects ${expectedChildren} children, got ${newChildren.length}`);
160
162
  }
161
163
 
162
- // Type check
163
- for (const child of newChildren) {
164
- if (!('expression' in child)) {
165
- throw new Error('ReturningNode: all children must be ScalarPlanNodes');
164
+ const [newExecutor, ...newProjectionNodes] = newChildren;
165
+
166
+ // Type check the executor
167
+ if (!isRelationalNode(newExecutor)) {
168
+ throw new Error('ReturningNode: first child must be a RelationalPlanNode (executor)');
169
+ }
170
+
171
+ // Type check projection expressions
172
+ for (let i = 0; i < newProjectionNodes.length; i++) {
173
+ const expr = newProjectionNodes[i];
174
+ if (!('expression' in expr)) {
175
+ throw new Error(`ReturningNode: projection child ${i + 1} must be a ScalarPlanNode`);
166
176
  }
167
177
  }
168
178
 
169
179
  // Check if anything changed
170
- const childrenChanged = newChildren.some((child, i) => child !== this.projections[i].node);
171
- if (!childrenChanged) {
180
+ const executorChanged = newExecutor !== this.executor;
181
+ const projectionsChanged = newProjectionNodes.some((child, i) => child !== this.projections[i].node);
182
+
183
+ if (!executorChanged && !projectionsChanged) {
172
184
  return this;
173
185
  }
174
186
 
@@ -177,7 +189,7 @@ export class ReturningNode extends PlanNode implements RelationalPlanNode {
177
189
 
178
190
  // Create new projections with preserved attribute IDs
179
191
  const newProjections = this.projections.map((proj, i) => ({
180
- node: newChildren[i] as ScalarPlanNode,
192
+ node: newProjectionNodes[i] as ScalarPlanNode,
181
193
  alias: proj.alias,
182
194
  attributeId: originalAttributes[i].id // Preserve original attribute ID
183
195
  }));
@@ -185,7 +197,7 @@ export class ReturningNode extends PlanNode implements RelationalPlanNode {
185
197
  // Create new instance with preserved attributes
186
198
  return new ReturningNode(
187
199
  this.scope,
188
- this.executor, // Executor doesn't change via withChildren
200
+ newExecutor as RelationalPlanNode,
189
201
  newProjections,
190
202
  originalAttributes // Pass original attributes to preserve IDs
191
203
  );
@@ -1,6 +1,6 @@
1
1
  import type { ScalarType } from "../../common/datatype.js";
2
2
  import { OutputValue, SqlDataType } from "../../common/types.js";
3
- import { PlanNode, type ScalarPlanNode, type UnaryScalarNode, type NaryScalarNode, type ZeroAryScalarNode, type BinaryScalarNode, PhysicalProperties, type ConstantNode } from "./plan-node.js";
3
+ import { PlanNode, type ScalarPlanNode, type UnaryScalarNode, type NaryScalarNode, type ZeroAryScalarNode, type BinaryScalarNode, PhysicalProperties, type ConstantNode, type TernaryScalarNode } from "./plan-node.js";
4
4
  import type * as AST from "../../parser/ast.js";
5
5
  import type { Scope } from "../scopes/scope.js";
6
6
  import { PlanNodeType } from "./plan-node-type.js";
@@ -150,7 +150,6 @@ export class BinaryOpNode extends PlanNode implements BinaryScalarNode {
150
150
  case 'IS':
151
151
  case 'IS NOT':
152
152
  case 'IN':
153
- case 'BETWEEN':
154
153
  datatype = SqlDataType.INTEGER;
155
154
  break;
156
155
  case '||':
@@ -227,15 +226,28 @@ export class BinaryOpNode extends PlanNode implements BinaryScalarNode {
227
226
 
228
227
  export class LiteralNode extends PlanNode implements ZeroAryScalarNode, ConstantNode {
229
228
  readonly nodeType = PlanNodeType.Literal;
230
-
229
+ /**
230
+ * When constant folding replaces an expression with a literal, we still need to
231
+ * preserve the *type metadata* (affinity, collation, nullability, etc.).
232
+ *
233
+ * The optional `explicitType` allows the caller to override the
234
+ * automatically-derived type so that information (e.g. COLLATE NOCASE)
235
+ * survives the folding pass.
236
+ */
231
237
  constructor(
232
238
  public readonly scope: Scope,
233
239
  public readonly expression: AST.LiteralExpr,
240
+ private readonly explicitType?: ScalarType,
234
241
  ) {
235
242
  super(scope, 0.001); // Minimal cost
236
243
  }
237
244
 
238
245
  getType(): ScalarType {
246
+ // If a caller supplied an explicit type (to preserve metadata such as
247
+ // collation) honour it verbatim.
248
+ if (this.explicitType) {
249
+ return this.explicitType;
250
+ }
239
251
  const value = this.expression.value;
240
252
  if (value === null) {
241
253
  return {
@@ -667,7 +679,7 @@ export class CollateNode extends PlanNode implements UnaryScalarNode {
667
679
  public readonly expression: AST.CollateExpr,
668
680
  public readonly operand: ScalarPlanNode,
669
681
  ) {
670
- super(scope, 0); // No runtime cost - collation is metadata
682
+ super(scope, 0.001); // Minimal cost for COLLATE
671
683
  this.cachedType = new Cached(this.generateType);
672
684
  }
673
685
 
@@ -678,14 +690,9 @@ export class CollateNode extends PlanNode implements UnaryScalarNode {
678
690
  generateType = (): ScalarType => {
679
691
  const operandType = this.operand.getType();
680
692
 
681
- // COLLATE preserves the operand type but changes the collation
682
693
  return {
683
- typeClass: 'scalar',
684
- affinity: operandType.affinity,
685
- nullable: operandType.nullable,
686
- isReadOnly: operandType.isReadOnly,
687
- datatype: operandType.datatype,
688
- collationName: this.expression.collation.toUpperCase(),
694
+ ...operandType,
695
+ collationName: this.expression.collation.toUpperCase()
689
696
  };
690
697
  }
691
698
 
@@ -734,3 +741,80 @@ export class CollateNode extends PlanNode implements UnaryScalarNode {
734
741
  };
735
742
  }
736
743
  }
744
+
745
+ export class BetweenNode extends PlanNode implements TernaryScalarNode {
746
+ readonly nodeType = PlanNodeType.Between;
747
+
748
+ constructor(
749
+ public readonly scope: Scope,
750
+ public readonly expression: AST.BetweenExpr,
751
+ public readonly expr: ScalarPlanNode,
752
+ public readonly lower: ScalarPlanNode,
753
+ public readonly upper: ScalarPlanNode,
754
+ ) {
755
+ super(scope, 0.03); // Cost for three comparisons
756
+ }
757
+
758
+ getType(): ScalarType {
759
+ // BETWEEN always returns INTEGER (0 or 1)
760
+ return {
761
+ typeClass: 'scalar',
762
+ affinity: SqlDataType.INTEGER,
763
+ nullable: false,
764
+ isReadOnly: true,
765
+ datatype: SqlDataType.INTEGER,
766
+ };
767
+ }
768
+
769
+ getChildren(): readonly [ScalarPlanNode, ScalarPlanNode, ScalarPlanNode] {
770
+ return [this.expr, this.lower, this.upper];
771
+ }
772
+
773
+ getRelations(): readonly [] {
774
+ return [];
775
+ }
776
+
777
+ withChildren(newChildren: readonly PlanNode[]): PlanNode {
778
+ if (newChildren.length !== 3) {
779
+ quereusError(`BetweenNode expects 3 children, got ${newChildren.length}`, StatusCode.INTERNAL);
780
+ }
781
+
782
+ const [newExpr, newLower, newUpper] = newChildren;
783
+
784
+ // Type check
785
+ for (const child of newChildren) {
786
+ if (!('expression' in child)) {
787
+ quereusError('BetweenNode: all children must be ScalarPlanNodes', StatusCode.INTERNAL);
788
+ }
789
+ }
790
+
791
+ // Return same instance if nothing changed
792
+ if (newExpr === this.expr && newLower === this.lower && newUpper === this.upper) {
793
+ return this;
794
+ }
795
+
796
+ // Create new instance
797
+ return new BetweenNode(
798
+ this.scope,
799
+ this.expression,
800
+ newExpr as ScalarPlanNode,
801
+ newLower as ScalarPlanNode,
802
+ newUpper as ScalarPlanNode
803
+ );
804
+ }
805
+
806
+ override toString(): string {
807
+ const notPrefix = this.expression.not ? 'NOT ' : '';
808
+ return `${formatExpression(this.expr)} ${notPrefix}BETWEEN ${formatExpression(this.lower)} AND ${formatExpression(this.upper)}`;
809
+ }
810
+
811
+ override getLogicalAttributes(): Record<string, unknown> {
812
+ return {
813
+ expr: formatExpression(this.expr),
814
+ lower: formatExpression(this.lower),
815
+ upper: formatExpression(this.upper),
816
+ not: this.expression.not ?? false,
817
+ resultType: formatScalarType(this.getType())
818
+ };
819
+ }
820
+ }
@@ -1,5 +1,5 @@
1
1
  import { PlanNodeType } from './plan-node-type.js';
2
- import { PlanNode, type Attribute, type RelationalPlanNode, type UnaryRelationalNode } from './plan-node.js';
2
+ import { isRelationalNode, PlanNode, type Attribute, type RelationalPlanNode, type UnaryRelationalNode } from './plan-node.js';
3
3
  import type { RelationType } from '../../common/datatype.js';
4
4
  import type { Scope } from '../scopes/scope.js';
5
5
  import { Cached } from '../../util/cached.js';
@@ -79,7 +79,7 @@ export class SequencingNode extends PlanNode implements UnaryRelationalNode {
79
79
  const [newSource] = newChildren;
80
80
 
81
81
  // Type check
82
- if (!('getAttributes' in newSource) || typeof (newSource as any).getAttributes !== 'function') {
82
+ if (!isRelationalNode(newSource)) {
83
83
  throw new Error('SequencingNode: child must be a RelationalPlanNode');
84
84
  }
85
85
 
@@ -1,4 +1,4 @@
1
- import { PlanNode } from './plan-node.js';
1
+ import { isRelationalNode, PlanNode } from './plan-node.js';
2
2
  import type { RelationalPlanNode, Attribute, BinaryRelationalNode } from './plan-node.js';
3
3
  import type { RelationType } from '../../common/datatype.js';
4
4
  import { PlanNodeType } from './plan-node-type.js';
@@ -60,10 +60,10 @@ export class SetOperationNode extends PlanNode implements BinaryRelationalNode {
60
60
  const [newLeft, newRight] = newChildren;
61
61
 
62
62
  // Type check
63
- if (!('getAttributes' in newLeft) || typeof (newLeft as any).getAttributes !== 'function') {
63
+ if (!isRelationalNode(newLeft)) {
64
64
  quereusError('SetOperationNode: first child must be a RelationalPlanNode', StatusCode.INTERNAL);
65
65
  }
66
- if (!('getAttributes' in newRight) || typeof (newRight as any).getAttributes !== 'function') {
66
+ if (!isRelationalNode(newRight)) {
67
67
  quereusError('SetOperationNode: second child must be a RelationalPlanNode', StatusCode.INTERNAL);
68
68
  }
69
69
 
@@ -1,14 +1,15 @@
1
1
  import { PlanNodeType } from './plan-node-type.js';
2
- import { PlanNode, type ZeroAryRelationalNode, type Attribute, PhysicalProperties } from './plan-node.js';
2
+ import { PlanNode, type ZeroAryRelationalNode, type Attribute, PhysicalProperties, type ConstantNode } from './plan-node.js';
3
3
  import type { RelationType } from '../../common/datatype.js';
4
4
  import { EmptyScope } from '../scopes/empty.js';
5
5
  import type { Scope } from '../scopes/scope.js';
6
+ import type { Row } from '../../common/types.js';
6
7
 
7
8
  /**
8
9
  * A dummy relational node that produces a single row with no columns.
9
10
  * Used as a source for SELECT statements without a FROM clause.
10
11
  */
11
- export class SingleRowNode extends PlanNode implements ZeroAryRelationalNode {
12
+ export class SingleRowNode extends PlanNode implements ZeroAryRelationalNode, ConstantNode {
12
13
  override readonly nodeType = PlanNodeType.SingleRow;
13
14
 
14
15
  private static readonly singleInstance = new SingleRowNode(EmptyScope.instance); // HACK: null scope for singleton
@@ -77,4 +78,8 @@ export class SingleRowNode extends PlanNode implements ZeroAryRelationalNode {
77
78
  constant: true,
78
79
  };
79
80
  }
81
+
82
+ async *getValue(): AsyncIterable<Row> {
83
+ yield [];
84
+ }
80
85
  }
@@ -30,15 +30,15 @@ export class SinkNode extends PlanNode {
30
30
  };
31
31
  }
32
32
 
33
- getChildren(): readonly PlanNode[] {
34
- return [];
33
+ getChildren(): readonly [RelationalPlanNode] {
34
+ return [this.source];
35
35
  }
36
36
 
37
37
  withChildren(newChildren: readonly PlanNode[]): PlanNode {
38
- if (newChildren.length !== 0) {
39
- throw new Error(`SinkNode expects 0 children, got ${newChildren.length}`);
38
+ if (newChildren.length !== 1) {
39
+ throw new Error(`SinkNode expects 1 child, got ${newChildren.length}`);
40
40
  }
41
- return this; // No children in getChildren(), source is accessed via getRelations()
41
+ return new SinkNode(this.scope, newChildren[0] as RelationalPlanNode, this.operation);
42
42
  }
43
43
 
44
44
  getRelations(): readonly [RelationalPlanNode] {
@@ -1,5 +1,5 @@
1
1
  import { PlanNodeType } from './plan-node-type.js';
2
- import { PlanNode, type RelationalPlanNode, type ScalarPlanNode, type UnaryRelationalNode, type PhysicalProperties, type Attribute } from './plan-node.js';
2
+ import { PlanNode, type RelationalPlanNode, type ScalarPlanNode, type UnaryRelationalNode, type PhysicalProperties, type Attribute, isRelationalNode } from './plan-node.js';
3
3
  import type { RelationType } from '../../common/datatype.js';
4
4
  import type { Scope } from '../scopes/scope.js';
5
5
  import { formatSortKey } from '../../util/plan-formatter.js';
@@ -108,7 +108,7 @@ export class SortNode extends PlanNode implements UnaryRelationalNode {
108
108
  const [newSource, ...newSortExpressions] = newChildren;
109
109
 
110
110
  // Type check
111
- if (!('getAttributes' in newSource) || typeof (newSource as any).getAttributes !== 'function') {
111
+ if (!isRelationalNode(newSource)) {
112
112
  quereusError('SortNode: first child must be a RelationalPlanNode', StatusCode.INTERNAL);
113
113
  }
114
114
 
@@ -1,5 +1,5 @@
1
1
  import { PlanNodeType } from './plan-node-type.js';
2
- import { PlanNode, type RelationalPlanNode, type UnaryRelationalNode, type ScalarPlanNode, type PhysicalProperties, type Attribute } from './plan-node.js';
2
+ import { PlanNode, type RelationalPlanNode, type UnaryRelationalNode, type ScalarPlanNode, type PhysicalProperties, type Attribute, isRelationalNode } from './plan-node.js';
3
3
  import type { RelationType } from '../../common/datatype.js';
4
4
  import type { Scope } from '../scopes/scope.js';
5
5
  import { Cached } from '../../util/cached.js';
@@ -31,15 +31,19 @@ export class StreamAggregateNode extends PlanNode implements UnaryRelationalNode
31
31
 
32
32
  super(scope, estimatedCostOverride ?? (source.getTotalCost() + streamingCost));
33
33
 
34
+
35
+
34
36
  this.attributesCache = new Cached(() => this.buildAttributes());
35
37
  }
36
38
 
37
- private buildAttributes(): Attribute[] {
38
- // If we have preserved attribute IDs, use them
39
+ private buildAttributes(): Attribute[] {
40
+ // If we have preserved attribute IDs, use them directly
41
+ // The optimizer rule now passes both aggregate AND source attributes
39
42
  if (this.preserveAttributeIds) {
40
- return this.preserveAttributeIds.slice(); // Return a copy
43
+ return this.preserveAttributeIds.slice();
41
44
  }
42
45
 
46
+ // Fallback: build attributes from scratch (used when not created via optimizer)
43
47
  const attributes: Attribute[] = [];
44
48
 
45
49
  // Group by columns come first
@@ -63,6 +67,18 @@ export class StreamAggregateNode extends PlanNode implements UnaryRelationalNode
63
67
  });
64
68
  });
65
69
 
70
+ // Add source attributes to support HAVING clauses
71
+ const sourceAttributes = this.source.getAttributes();
72
+ const existingAttrNames = new Set(attributes.map(attr => attr.name));
73
+
74
+ for (const sourceAttr of sourceAttributes) {
75
+ // Only add if not already present by name (avoid duplicates for GROUP BY columns)
76
+ if (!existingAttrNames.has(sourceAttr.name)) {
77
+ attributes.push(sourceAttr);
78
+ existingAttrNames.add(sourceAttr.name);
79
+ }
80
+ }
81
+
66
82
  return attributes;
67
83
  }
68
84
 
@@ -78,21 +94,44 @@ export class StreamAggregateNode extends PlanNode implements UnaryRelationalNode
78
94
  }
79
95
 
80
96
  getType(): RelationType {
81
- // Same output type as logical aggregate
82
- const columns = [
97
+ const columns = [];
98
+
99
+ // Start with preserved attributes if we have them, otherwise build GROUP BY + aggregates
100
+ if (this.preserveAttributeIds) {
101
+ // Use preserved attributes to match getAttributes() exactly
102
+ for (const attr of this.preserveAttributeIds) {
103
+ columns.push({
104
+ name: attr.name,
105
+ type: attr.type,
106
+ generated: false // Source attributes are not generated
107
+ });
108
+ }
109
+ } else {
83
110
  // Group by columns come first
84
- ...this.groupBy.map((expr, index) => ({
111
+ columns.push(...this.groupBy.map((expr, index) => ({
85
112
  name: this.getGroupByColumnName(expr, index),
86
113
  type: expr.getType(),
87
114
  generated: false
88
- })),
115
+ })));
116
+
89
117
  // Then aggregate columns
90
- ...this.aggregates.map(agg => ({
118
+ columns.push(...this.aggregates.map(agg => ({
91
119
  name: agg.alias,
92
120
  type: agg.expression.getType(),
93
121
  generated: true
94
- }))
95
- ];
122
+ })));
123
+
124
+ // Add all source columns to support HAVING clauses (consistent with getAttributes())
125
+ const sourceType = this.source.getType();
126
+ const existingNames = new Set(columns.map(col => col.name));
127
+
128
+ for (const sourceCol of sourceType.columns) {
129
+ // Only add if not already present (avoid duplicates for GROUP BY columns)
130
+ if (!existingNames.has(sourceCol.name)) {
131
+ columns.push(sourceCol);
132
+ }
133
+ }
134
+ }
96
135
 
97
136
  return {
98
137
  typeClass: 'relation',
@@ -109,6 +148,31 @@ export class StreamAggregateNode extends PlanNode implements UnaryRelationalNode
109
148
  return this.attributesCache.value;
110
149
  }
111
150
 
151
+ getProducingExprs(): Map<number, ScalarPlanNode> {
152
+ const attributes = this.getAttributes();
153
+ const map = new Map<number, ScalarPlanNode>();
154
+
155
+ // Map GROUP BY expressions to their attribute IDs
156
+ for (let i = 0; i < this.groupBy.length; i++) {
157
+ const expr = this.groupBy[i];
158
+ const attr = attributes[i];
159
+ if (attr) {
160
+ map.set(attr.id, expr);
161
+ }
162
+ }
163
+
164
+ // Map aggregate expressions to their attribute IDs
165
+ for (let i = 0; i < this.aggregates.length; i++) {
166
+ const agg = this.aggregates[i];
167
+ const attr = attributes[this.groupBy.length + i]; // Aggregates come after GROUP BY
168
+ if (attr) {
169
+ map.set(attr.id, agg.expression);
170
+ }
171
+ }
172
+
173
+ return map;
174
+ }
175
+
112
176
  getChildren(): readonly PlanNode[] {
113
177
  return [this.source, ...this.groupBy, ...this.aggregates.map(agg => agg.expression)];
114
178
  }
@@ -193,7 +257,7 @@ export class StreamAggregateNode extends PlanNode implements UnaryRelationalNode
193
257
  const newAggregateExpressions = restChildren.slice(this.groupBy.length);
194
258
 
195
259
  // Type check
196
- if (!('getAttributes' in newSource) || typeof (newSource as any).getAttributes !== 'function') {
260
+ if (!isRelationalNode(newSource)) {
197
261
  quereusError('StreamAggregateNode: first child must be a RelationalPlanNode', StatusCode.INTERNAL);
198
262
  }
199
263
 
@@ -7,6 +7,8 @@ import type { Scope } from "../scopes/scope.js";
7
7
  import { compareSqlValues } from "../../util/comparison.js";
8
8
  import type { Expression } from "../../parser/ast.js";
9
9
  import { formatExpression, formatScalarType } from "../../util/plan-formatter.js";
10
+ import { quereusError } from "../../common/errors.js";
11
+ import { StatusCode } from "../../common/types.js";
10
12
 
11
13
  export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
12
14
  override readonly nodeType = PlanNodeType.ScalarSubquery;
@@ -36,8 +38,9 @@ export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
36
38
  };
37
39
  }
38
40
 
39
- getChildren(): readonly [] {
40
- return [];
41
+ getChildren(): readonly PlanNode[] {
42
+ // Include the subquery so the optimizer can visit it
43
+ return [this.subquery];
41
44
  }
42
45
 
43
46
  getRelations(): readonly [RelationalPlanNode] {
@@ -45,10 +48,28 @@ export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
45
48
  }
46
49
 
47
50
  withChildren(newChildren: readonly PlanNode[]): PlanNode {
48
- if (newChildren.length !== 0) {
49
- throw new Error(`ScalarSubqueryNode expects 0 children, got ${newChildren.length}`);
51
+ if (newChildren.length !== 1) {
52
+ quereusError(`ScalarSubqueryNode expects 1 child, got ${newChildren.length}`, StatusCode.INTERNAL);
53
+ }
54
+
55
+ const [newSubquery] = newChildren;
56
+
57
+ // Type check
58
+ if (newSubquery.getType().typeClass !== 'relation') {
59
+ quereusError('ScalarSubqueryNode: child must be a RelationalPlanNode', StatusCode.INTERNAL);
60
+ }
61
+
62
+ // Check if anything changed
63
+ if (newSubquery === this.subquery) {
64
+ return this;
50
65
  }
51
- return this; // No children in getChildren(), subquery is accessed via getRelations()
66
+
67
+ // Create new instance
68
+ return new ScalarSubqueryNode(
69
+ this.scope,
70
+ this.expression,
71
+ newSubquery as RelationalPlanNode
72
+ );
52
73
  }
53
74
 
54
75
  override toString(): string {
@@ -89,11 +110,16 @@ export class InNode extends PlanNode implements ScalarPlanNode {
89
110
  }
90
111
  }
91
112
 
92
- getChildren(): readonly ScalarPlanNode[] {
113
+ getChildren(): readonly PlanNode[] {
114
+ // Include condition, values (if any), and source subquery (if any)
115
+ const children: PlanNode[] = [this.condition];
93
116
  if (this.values) {
94
- return [this.condition, ...this.values];
117
+ children.push(...this.values);
95
118
  }
96
- return [this.condition];
119
+ if (this.source) {
120
+ children.push(this.source);
121
+ }
122
+ return children;
97
123
  }
98
124
 
99
125
  getRelations(): readonly RelationalPlanNode[] {
@@ -104,29 +130,47 @@ export class InNode extends PlanNode implements ScalarPlanNode {
104
130
  }
105
131
 
106
132
  withChildren(newChildren: readonly PlanNode[]): PlanNode {
107
- const expectedLength = this.values ? 1 + this.values.length : 1;
133
+ const expectedLength = 1 + (this.values?.length ?? 0) + (this.source ? 1 : 0);
108
134
  if (newChildren.length !== expectedLength) {
109
- throw new Error(`InNode expects ${expectedLength} children, got ${newChildren.length}`);
135
+ quereusError(`InNode expects ${expectedLength} children, got ${newChildren.length}`, StatusCode.INTERNAL);
110
136
  }
111
137
 
112
- const [newCondition, ...newValues] = newChildren;
138
+ let childIndex = 0;
139
+ const newCondition = newChildren[childIndex++];
113
140
 
114
- // Type check
115
- if (!('expression' in newCondition)) {
116
- throw new Error('InNode: condition must be a ScalarPlanNode');
141
+ // Type check condition
142
+ if (newCondition.getType().typeClass !== 'scalar') {
143
+ quereusError('InNode: condition must be a ScalarPlanNode', StatusCode.INTERNAL);
144
+ }
145
+
146
+ // Extract new values if they exist
147
+ let newValues: ScalarPlanNode[] | undefined;
148
+ if (this.values) {
149
+ newValues = [];
150
+ for (let i = 0; i < this.values.length; i++) {
151
+ const value = newChildren[childIndex++];
152
+ if (value.getType().typeClass !== 'scalar') {
153
+ quereusError('InNode: values must be ScalarPlanNodes', StatusCode.INTERNAL);
154
+ }
155
+ newValues.push(value as ScalarPlanNode);
156
+ }
117
157
  }
118
158
 
119
- for (const value of newValues) {
120
- if (!('expression' in value)) {
121
- throw new Error('InNode: values must be ScalarPlanNodes');
159
+ // Extract new source if it exists
160
+ let newSource: RelationalPlanNode | undefined;
161
+ if (this.source) {
162
+ newSource = newChildren[childIndex++] as RelationalPlanNode;
163
+ if (newSource.getType().typeClass !== 'relation') {
164
+ quereusError('InNode: source must be a RelationalPlanNode', StatusCode.INTERNAL);
122
165
  }
123
166
  }
124
167
 
125
168
  // Check if anything changed
126
169
  const conditionChanged = newCondition !== this.condition;
127
- const valuesChanged = this.values && newValues.some((val, i) => val !== this.values![i]);
170
+ const valuesChanged = this.values && newValues && newValues.some((val, i) => val !== this.values![i]);
171
+ const sourceChanged = newSource !== this.source;
128
172
 
129
- if (!conditionChanged && !valuesChanged) {
173
+ if (!conditionChanged && !valuesChanged && !sourceChanged) {
130
174
  return this;
131
175
  }
132
176
 
@@ -135,8 +179,8 @@ export class InNode extends PlanNode implements ScalarPlanNode {
135
179
  this.scope,
136
180
  this.expression,
137
181
  newCondition as ScalarPlanNode,
138
- this.source, // Source doesn't change via withChildren
139
- this.values ? newValues as ScalarPlanNode[] : undefined
182
+ newSource,
183
+ newValues
140
184
  );
141
185
  }
142
186
 
@@ -179,19 +223,38 @@ export class ExistsNode extends PlanNode implements ScalarPlanNode {
179
223
  };
180
224
  }
181
225
 
182
- getChildren(): readonly [] {
183
- return [];
226
+ getChildren(): readonly PlanNode[] {
227
+ // Include the subquery so the optimizer can visit it
228
+ return [this.subquery];
184
229
  }
185
230
 
186
- getRelations(): readonly [RelationalPlanNode] {
231
+ getRelations(): readonly RelationalPlanNode[] {
187
232
  return [this.subquery];
188
233
  }
189
234
 
190
235
  withChildren(newChildren: readonly PlanNode[]): PlanNode {
191
- if (newChildren.length !== 0) {
192
- throw new Error(`ExistsNode expects 0 children, got ${newChildren.length}`);
236
+ if (newChildren.length !== 1) {
237
+ quereusError(`ExistsNode expects 1 child, got ${newChildren.length}`, StatusCode.INTERNAL);
238
+ }
239
+
240
+ const [newSubquery] = newChildren;
241
+
242
+ // Type check
243
+ if (newSubquery.getType().typeClass !== 'relation') {
244
+ quereusError('ExistsNode: child must be a RelationalPlanNode', StatusCode.INTERNAL);
245
+ }
246
+
247
+ // Check if anything changed
248
+ if (newSubquery === this.subquery) {
249
+ return this;
193
250
  }
194
- return this; // No children in getChildren(), subquery is accessed via getRelations()
251
+
252
+ // Create new instance
253
+ return new ExistsNode(
254
+ this.scope,
255
+ this.expression,
256
+ newSubquery as RelationalPlanNode
257
+ );
195
258
  }
196
259
 
197
260
  override toString(): string {