@quereus/quereus 0.1.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 (1198) hide show
  1. package/README.md +228 -0
  2. package/dist/src/common/constants.d.ts +49 -0
  3. package/dist/src/common/constants.d.ts.map +1 -0
  4. package/dist/src/common/constants.js +62 -0
  5. package/dist/src/common/constants.js.map +1 -0
  6. package/dist/src/common/datatype.d.ts +72 -0
  7. package/dist/src/common/datatype.d.ts.map +1 -0
  8. package/dist/src/common/datatype.js +10 -0
  9. package/dist/src/common/datatype.js.map +1 -0
  10. package/dist/src/common/errors.d.ts +90 -0
  11. package/dist/src/common/errors.d.ts.map +1 -0
  12. package/dist/src/common/errors.js +142 -0
  13. package/dist/src/common/errors.js.map +1 -0
  14. package/dist/src/common/logger.d.ts +18 -0
  15. package/dist/src/common/logger.d.ts.map +1 -0
  16. package/dist/src/common/logger.js +22 -0
  17. package/dist/src/common/logger.js.map +1 -0
  18. package/dist/src/common/type-inference.d.ts +11 -0
  19. package/dist/src/common/type-inference.d.ts.map +1 -0
  20. package/dist/src/common/type-inference.js +44 -0
  21. package/dist/src/common/type-inference.js.map +1 -0
  22. package/dist/src/common/types.d.ts +131 -0
  23. package/dist/src/common/types.d.ts.map +1 -0
  24. package/dist/src/common/types.js +53 -0
  25. package/dist/src/common/types.js.map +1 -0
  26. package/dist/src/core/database-options.d.ts +67 -0
  27. package/dist/src/core/database-options.d.ts.map +1 -0
  28. package/dist/src/core/database-options.js +211 -0
  29. package/dist/src/core/database-options.js.map +1 -0
  30. package/dist/src/core/database.d.ts +214 -0
  31. package/dist/src/core/database.d.ts.map +1 -0
  32. package/dist/src/core/database.js +750 -0
  33. package/dist/src/core/database.js.map +1 -0
  34. package/dist/src/core/param.d.ts +4 -0
  35. package/dist/src/core/param.d.ts.map +1 -0
  36. package/dist/src/core/param.js +46 -0
  37. package/dist/src/core/param.js.map +1 -0
  38. package/dist/src/core/statement.d.ts +94 -0
  39. package/dist/src/core/statement.d.ts.map +1 -0
  40. package/dist/src/core/statement.js +482 -0
  41. package/dist/src/core/statement.js.map +1 -0
  42. package/dist/src/func/builtins/aggregate.d.ts +13 -0
  43. package/dist/src/func/builtins/aggregate.d.ts.map +1 -0
  44. package/dist/src/func/builtins/aggregate.js +190 -0
  45. package/dist/src/func/builtins/aggregate.js.map +1 -0
  46. package/dist/src/func/builtins/builtin-window-functions.d.ts +2 -0
  47. package/dist/src/func/builtins/builtin-window-functions.d.ts.map +1 -0
  48. package/dist/src/func/builtins/builtin-window-functions.js +161 -0
  49. package/dist/src/func/builtins/builtin-window-functions.js.map +1 -0
  50. package/dist/src/func/builtins/datetime.d.ts +6 -0
  51. package/dist/src/func/builtins/datetime.d.ts.map +1 -0
  52. package/dist/src/func/builtins/datetime.js +417 -0
  53. package/dist/src/func/builtins/datetime.js.map +1 -0
  54. package/dist/src/func/builtins/explain.d.ts +7 -0
  55. package/dist/src/func/builtins/explain.d.ts.map +1 -0
  56. package/dist/src/func/builtins/explain.js +570 -0
  57. package/dist/src/func/builtins/explain.js.map +1 -0
  58. package/dist/src/func/builtins/generation.d.ts +2 -0
  59. package/dist/src/func/builtins/generation.d.ts.map +1 -0
  60. package/dist/src/func/builtins/generation.js +36 -0
  61. package/dist/src/func/builtins/generation.js.map +1 -0
  62. package/dist/src/func/builtins/index.d.ts +4 -0
  63. package/dist/src/func/builtins/index.d.ts.map +1 -0
  64. package/dist/src/func/builtins/index.js +106 -0
  65. package/dist/src/func/builtins/index.js.map +1 -0
  66. package/dist/src/func/builtins/json-helpers.d.ts +64 -0
  67. package/dist/src/func/builtins/json-helpers.d.ts.map +1 -0
  68. package/dist/src/func/builtins/json-helpers.js +237 -0
  69. package/dist/src/func/builtins/json-helpers.js.map +1 -0
  70. package/dist/src/func/builtins/json-tvf.d.ts +3 -0
  71. package/dist/src/func/builtins/json-tvf.d.ts.map +1 -0
  72. package/dist/src/func/builtins/json-tvf.js +199 -0
  73. package/dist/src/func/builtins/json-tvf.js.map +1 -0
  74. package/dist/src/func/builtins/json.d.ts +15 -0
  75. package/dist/src/func/builtins/json.d.ts.map +1 -0
  76. package/dist/src/func/builtins/json.js +417 -0
  77. package/dist/src/func/builtins/json.js.map +1 -0
  78. package/dist/src/func/builtins/scalar.d.ts +19 -0
  79. package/dist/src/func/builtins/scalar.d.ts.map +1 -0
  80. package/dist/src/func/builtins/scalar.js +176 -0
  81. package/dist/src/func/builtins/scalar.js.map +1 -0
  82. package/dist/src/func/builtins/schema.d.ts +4 -0
  83. package/dist/src/func/builtins/schema.d.ts.map +1 -0
  84. package/dist/src/func/builtins/schema.js +167 -0
  85. package/dist/src/func/builtins/schema.js.map +1 -0
  86. package/dist/src/func/builtins/string.d.ts +18 -0
  87. package/dist/src/func/builtins/string.d.ts.map +1 -0
  88. package/dist/src/func/builtins/string.js +233 -0
  89. package/dist/src/func/builtins/string.js.map +1 -0
  90. package/dist/src/func/context.d.ts +102 -0
  91. package/dist/src/func/context.d.ts.map +1 -0
  92. package/dist/src/func/context.js +130 -0
  93. package/dist/src/func/context.js.map +1 -0
  94. package/dist/src/func/registration.d.ts +89 -0
  95. package/dist/src/func/registration.d.ts.map +1 -0
  96. package/dist/src/func/registration.js +103 -0
  97. package/dist/src/func/registration.js.map +1 -0
  98. package/dist/src/index.d.ts +34 -0
  99. package/dist/src/index.d.ts.map +1 -0
  100. package/dist/src/index.js +35 -0
  101. package/dist/src/index.js.map +1 -0
  102. package/dist/src/parser/ast.d.ts +376 -0
  103. package/dist/src/parser/ast.d.ts.map +1 -0
  104. package/dist/src/parser/ast.js +2 -0
  105. package/dist/src/parser/ast.js.map +1 -0
  106. package/dist/src/parser/index.d.ts +29 -0
  107. package/dist/src/parser/index.d.ts.map +1 -0
  108. package/dist/src/parser/index.js +50 -0
  109. package/dist/src/parser/index.js.map +1 -0
  110. package/dist/src/parser/lexer.d.ts +197 -0
  111. package/dist/src/parser/lexer.d.ts.map +1 -0
  112. package/dist/src/parser/lexer.js +762 -0
  113. package/dist/src/parser/lexer.js.map +1 -0
  114. package/dist/src/parser/parser.d.ts +216 -0
  115. package/dist/src/parser/parser.d.ts.map +1 -0
  116. package/dist/src/parser/parser.js +2619 -0
  117. package/dist/src/parser/parser.js.map +1 -0
  118. package/dist/src/parser/utils.d.ts +4 -0
  119. package/dist/src/parser/utils.d.ts.map +1 -0
  120. package/dist/src/parser/utils.js +8 -0
  121. package/dist/src/parser/utils.js.map +1 -0
  122. package/dist/src/parser/visitor.d.ts +38 -0
  123. package/dist/src/parser/visitor.d.ts.map +1 -0
  124. package/dist/src/parser/visitor.js +153 -0
  125. package/dist/src/parser/visitor.js.map +1 -0
  126. package/dist/src/planner/analysis/const-evaluator.d.ts +14 -0
  127. package/dist/src/planner/analysis/const-evaluator.d.ts.map +1 -0
  128. package/dist/src/planner/analysis/const-evaluator.js +50 -0
  129. package/dist/src/planner/analysis/const-evaluator.js.map +1 -0
  130. package/dist/src/planner/analysis/const-pass.d.ts +51 -0
  131. package/dist/src/planner/analysis/const-pass.d.ts.map +1 -0
  132. package/dist/src/planner/analysis/const-pass.js +200 -0
  133. package/dist/src/planner/analysis/const-pass.js.map +1 -0
  134. package/dist/src/planner/analysis/constraint-extractor.d.ts +57 -0
  135. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -0
  136. package/dist/src/planner/analysis/constraint-extractor.js +193 -0
  137. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -0
  138. package/dist/src/planner/building/alter-table.d.ts +5 -0
  139. package/dist/src/planner/building/alter-table.d.ts.map +1 -0
  140. package/dist/src/planner/building/alter-table.js +26 -0
  141. package/dist/src/planner/building/alter-table.js.map +1 -0
  142. package/dist/src/planner/building/block.d.ts +5 -0
  143. package/dist/src/planner/building/block.d.ts.map +1 -0
  144. package/dist/src/planner/building/block.js +68 -0
  145. package/dist/src/planner/building/block.js.map +1 -0
  146. package/dist/src/planner/building/create-view.d.ts +8 -0
  147. package/dist/src/planner/building/create-view.d.ts.map +1 -0
  148. package/dist/src/planner/building/create-view.js +37 -0
  149. package/dist/src/planner/building/create-view.js.map +1 -0
  150. package/dist/src/planner/building/ddl.d.ts +7 -0
  151. package/dist/src/planner/building/ddl.d.ts.map +1 -0
  152. package/dist/src/planner/building/ddl.js +9 -0
  153. package/dist/src/planner/building/ddl.js.map +1 -0
  154. package/dist/src/planner/building/delete.d.ts +5 -0
  155. package/dist/src/planner/building/delete.d.ts.map +1 -0
  156. package/dist/src/planner/building/delete.js +105 -0
  157. package/dist/src/planner/building/delete.js.map +1 -0
  158. package/dist/src/planner/building/drop-table.d.ts +5 -0
  159. package/dist/src/planner/building/drop-table.d.ts.map +1 -0
  160. package/dist/src/planner/building/drop-table.js +5 -0
  161. package/dist/src/planner/building/drop-table.js.map +1 -0
  162. package/dist/src/planner/building/drop-view.d.ts +8 -0
  163. package/dist/src/planner/building/drop-view.d.ts.map +1 -0
  164. package/dist/src/planner/building/drop-view.js +11 -0
  165. package/dist/src/planner/building/drop-view.js.map +1 -0
  166. package/dist/src/planner/building/expression.d.ts +5 -0
  167. package/dist/src/planner/building/expression.d.ts.map +1 -0
  168. package/dist/src/planner/building/expression.js +147 -0
  169. package/dist/src/planner/building/expression.js.map +1 -0
  170. package/dist/src/planner/building/function-call.d.ts +5 -0
  171. package/dist/src/planner/building/function-call.d.ts.map +1 -0
  172. package/dist/src/planner/building/function-call.js +70 -0
  173. package/dist/src/planner/building/function-call.js.map +1 -0
  174. package/dist/src/planner/building/insert.d.ts +5 -0
  175. package/dist/src/planner/building/insert.d.ts.map +1 -0
  176. package/dist/src/planner/building/insert.js +261 -0
  177. package/dist/src/planner/building/insert.js.map +1 -0
  178. package/dist/src/planner/building/pragma.d.ts +5 -0
  179. package/dist/src/planner/building/pragma.d.ts.map +1 -0
  180. package/dist/src/planner/building/pragma.js +28 -0
  181. package/dist/src/planner/building/pragma.js.map +1 -0
  182. package/dist/src/planner/building/schema-resolution.d.ts +25 -0
  183. package/dist/src/planner/building/schema-resolution.d.ts.map +1 -0
  184. package/dist/src/planner/building/schema-resolution.js +119 -0
  185. package/dist/src/planner/building/schema-resolution.js.map +1 -0
  186. package/dist/src/planner/building/select-aggregates.d.ts +22 -0
  187. package/dist/src/planner/building/select-aggregates.d.ts.map +1 -0
  188. package/dist/src/planner/building/select-aggregates.js +164 -0
  189. package/dist/src/planner/building/select-aggregates.js.map +1 -0
  190. package/dist/src/planner/building/select-compound.d.ts +9 -0
  191. package/dist/src/planner/building/select-compound.d.ts.map +1 -0
  192. package/dist/src/planner/building/select-compound.js +78 -0
  193. package/dist/src/planner/building/select-compound.js.map +1 -0
  194. package/dist/src/planner/building/select-context.d.ts +18 -0
  195. package/dist/src/planner/building/select-context.d.ts.map +1 -0
  196. package/dist/src/planner/building/select-context.js +54 -0
  197. package/dist/src/planner/building/select-context.js.map +1 -0
  198. package/dist/src/planner/building/select-modifiers.d.ts +25 -0
  199. package/dist/src/planner/building/select-modifiers.d.ts.map +1 -0
  200. package/dist/src/planner/building/select-modifiers.js +120 -0
  201. package/dist/src/planner/building/select-modifiers.js.map +1 -0
  202. package/dist/src/planner/building/select-projections.d.ts +37 -0
  203. package/dist/src/planner/building/select-projections.d.ts.map +1 -0
  204. package/dist/src/planner/building/select-projections.js +132 -0
  205. package/dist/src/planner/building/select-projections.js.map +1 -0
  206. package/dist/src/planner/building/select-window.d.ts +12 -0
  207. package/dist/src/planner/building/select-window.d.ts.map +1 -0
  208. package/dist/src/planner/building/select-window.js +159 -0
  209. package/dist/src/planner/building/select-window.js.map +1 -0
  210. package/dist/src/planner/building/select.d.ts +28 -0
  211. package/dist/src/planner/building/select.d.ts.map +1 -0
  212. package/dist/src/planner/building/select.js +307 -0
  213. package/dist/src/planner/building/select.js.map +1 -0
  214. package/dist/src/planner/building/table-function.d.ts +5 -0
  215. package/dist/src/planner/building/table-function.d.ts.map +1 -0
  216. package/dist/src/planner/building/table-function.js +21 -0
  217. package/dist/src/planner/building/table-function.js.map +1 -0
  218. package/dist/src/planner/building/table.d.ts +23 -0
  219. package/dist/src/planner/building/table.d.ts.map +1 -0
  220. package/dist/src/planner/building/table.js +57 -0
  221. package/dist/src/planner/building/table.js.map +1 -0
  222. package/dist/src/planner/building/transaction.d.ts +9 -0
  223. package/dist/src/planner/building/transaction.d.ts.map +1 -0
  224. package/dist/src/planner/building/transaction.js +17 -0
  225. package/dist/src/planner/building/transaction.js.map +1 -0
  226. package/dist/src/planner/building/update.d.ts +5 -0
  227. package/dist/src/planner/building/update.d.ts.map +1 -0
  228. package/dist/src/planner/building/update.js +152 -0
  229. package/dist/src/planner/building/update.js.map +1 -0
  230. package/dist/src/planner/building/with.d.ts +13 -0
  231. package/dist/src/planner/building/with.d.ts.map +1 -0
  232. package/dist/src/planner/building/with.js +112 -0
  233. package/dist/src/planner/building/with.js.map +1 -0
  234. package/dist/src/planner/cache/materialization-advisory.d.ts +66 -0
  235. package/dist/src/planner/cache/materialization-advisory.d.ts.map +1 -0
  236. package/dist/src/planner/cache/materialization-advisory.js +187 -0
  237. package/dist/src/planner/cache/materialization-advisory.js.map +1 -0
  238. package/dist/src/planner/cache/reference-graph.d.ts +53 -0
  239. package/dist/src/planner/cache/reference-graph.d.ts.map +1 -0
  240. package/dist/src/planner/cache/reference-graph.js +139 -0
  241. package/dist/src/planner/cache/reference-graph.js.map +1 -0
  242. package/dist/src/planner/cost/index.d.ts +106 -0
  243. package/dist/src/planner/cost/index.d.ts.map +1 -0
  244. package/dist/src/planner/cost/index.js +143 -0
  245. package/dist/src/planner/cost/index.js.map +1 -0
  246. package/dist/src/planner/debug/logger-utils.d.ts +44 -0
  247. package/dist/src/planner/debug/logger-utils.d.ts.map +1 -0
  248. package/dist/src/planner/debug/logger-utils.js +58 -0
  249. package/dist/src/planner/debug/logger-utils.js.map +1 -0
  250. package/dist/src/planner/debug.d.ts +53 -0
  251. package/dist/src/planner/debug.d.ts.map +1 -0
  252. package/dist/src/planner/debug.js +228 -0
  253. package/dist/src/planner/debug.js.map +1 -0
  254. package/dist/src/planner/framework/context.d.ts +86 -0
  255. package/dist/src/planner/framework/context.d.ts.map +1 -0
  256. package/dist/src/planner/framework/context.js +117 -0
  257. package/dist/src/planner/framework/context.js.map +1 -0
  258. package/dist/src/planner/framework/physical-utils.d.ts +62 -0
  259. package/dist/src/planner/framework/physical-utils.d.ts.map +1 -0
  260. package/dist/src/planner/framework/physical-utils.js +149 -0
  261. package/dist/src/planner/framework/physical-utils.js.map +1 -0
  262. package/dist/src/planner/framework/registry.d.ts +75 -0
  263. package/dist/src/planner/framework/registry.d.ts.map +1 -0
  264. package/dist/src/planner/framework/registry.js +203 -0
  265. package/dist/src/planner/framework/registry.js.map +1 -0
  266. package/dist/src/planner/framework/trace.d.ts +84 -0
  267. package/dist/src/planner/framework/trace.d.ts.map +1 -0
  268. package/dist/src/planner/framework/trace.js +198 -0
  269. package/dist/src/planner/framework/trace.js.map +1 -0
  270. package/dist/src/planner/nodes/add-constraint-node.d.ts +23 -0
  271. package/dist/src/planner/nodes/add-constraint-node.d.ts.map +1 -0
  272. package/dist/src/planner/nodes/add-constraint-node.js +47 -0
  273. package/dist/src/planner/nodes/add-constraint-node.js.map +1 -0
  274. package/dist/src/planner/nodes/aggregate-function.d.ts +34 -0
  275. package/dist/src/planner/nodes/aggregate-function.d.ts.map +1 -0
  276. package/dist/src/planner/nodes/aggregate-function.js +119 -0
  277. package/dist/src/planner/nodes/aggregate-function.js.map +1 -0
  278. package/dist/src/planner/nodes/aggregate-node.d.ts +35 -0
  279. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -0
  280. package/dist/src/planner/nodes/aggregate-node.js +176 -0
  281. package/dist/src/planner/nodes/aggregate-node.js.map +1 -0
  282. package/dist/src/planner/nodes/array-index-node.d.ts +22 -0
  283. package/dist/src/planner/nodes/array-index-node.d.ts.map +1 -0
  284. package/dist/src/planner/nodes/array-index-node.js +41 -0
  285. package/dist/src/planner/nodes/array-index-node.js.map +1 -0
  286. package/dist/src/planner/nodes/block.d.ts +26 -0
  287. package/dist/src/planner/nodes/block.d.ts.map +1 -0
  288. package/dist/src/planner/nodes/block.js +58 -0
  289. package/dist/src/planner/nodes/block.js.map +1 -0
  290. package/dist/src/planner/nodes/cache-node.d.ts +29 -0
  291. package/dist/src/planner/nodes/cache-node.d.ts.map +1 -0
  292. package/dist/src/planner/nodes/cache-node.js +73 -0
  293. package/dist/src/planner/nodes/cache-node.js.map +1 -0
  294. package/dist/src/planner/nodes/constraint-check-node.d.ts +28 -0
  295. package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -0
  296. package/dist/src/planner/nodes/constraint-check-node.js +73 -0
  297. package/dist/src/planner/nodes/constraint-check-node.js.map +1 -0
  298. package/dist/src/planner/nodes/create-index-node.d.ts +15 -0
  299. package/dist/src/planner/nodes/create-index-node.d.ts.map +1 -0
  300. package/dist/src/planner/nodes/create-index-node.js +31 -0
  301. package/dist/src/planner/nodes/create-index-node.js.map +1 -0
  302. package/dist/src/planner/nodes/create-table-node.d.ts +15 -0
  303. package/dist/src/planner/nodes/create-table-node.d.ts.map +1 -0
  304. package/dist/src/planner/nodes/create-table-node.js +25 -0
  305. package/dist/src/planner/nodes/create-table-node.js.map +1 -0
  306. package/dist/src/planner/nodes/create-view-node.d.ts +21 -0
  307. package/dist/src/planner/nodes/create-view-node.d.ts.map +1 -0
  308. package/dist/src/planner/nodes/create-view-node.js +39 -0
  309. package/dist/src/planner/nodes/create-view-node.js.map +1 -0
  310. package/dist/src/planner/nodes/cte-node.d.ts +40 -0
  311. package/dist/src/planner/nodes/cte-node.d.ts.map +1 -0
  312. package/dist/src/planner/nodes/cte-node.js +88 -0
  313. package/dist/src/planner/nodes/cte-node.js.map +1 -0
  314. package/dist/src/planner/nodes/cte-reference-node.d.ts +27 -0
  315. package/dist/src/planner/nodes/cte-reference-node.d.ts.map +1 -0
  316. package/dist/src/planner/nodes/cte-reference-node.js +75 -0
  317. package/dist/src/planner/nodes/cte-reference-node.js.map +1 -0
  318. package/dist/src/planner/nodes/delete-node.d.ts +27 -0
  319. package/dist/src/planner/nodes/delete-node.d.ts.map +1 -0
  320. package/dist/src/planner/nodes/delete-node.js +62 -0
  321. package/dist/src/planner/nodes/delete-node.js.map +1 -0
  322. package/dist/src/planner/nodes/distinct-node.d.ts +22 -0
  323. package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -0
  324. package/dist/src/planner/nodes/distinct-node.js +74 -0
  325. package/dist/src/planner/nodes/distinct-node.js.map +1 -0
  326. package/dist/src/planner/nodes/dml-executor-node.d.ts +30 -0
  327. package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -0
  328. package/dist/src/planner/nodes/dml-executor-node.js +73 -0
  329. package/dist/src/planner/nodes/dml-executor-node.js.map +1 -0
  330. package/dist/src/planner/nodes/drop-table-node.d.ts +15 -0
  331. package/dist/src/planner/nodes/drop-table-node.d.ts.map +1 -0
  332. package/dist/src/planner/nodes/drop-table-node.js +25 -0
  333. package/dist/src/planner/nodes/drop-table-node.js.map +1 -0
  334. package/dist/src/planner/nodes/drop-view-node.d.ts +17 -0
  335. package/dist/src/planner/nodes/drop-view-node.d.ts.map +1 -0
  336. package/dist/src/planner/nodes/drop-view-node.js +30 -0
  337. package/dist/src/planner/nodes/drop-view-node.js.map +1 -0
  338. package/dist/src/planner/nodes/filter.d.ts +24 -0
  339. package/dist/src/planner/nodes/filter.d.ts.map +1 -0
  340. package/dist/src/planner/nodes/filter.js +72 -0
  341. package/dist/src/planner/nodes/filter.js.map +1 -0
  342. package/dist/src/planner/nodes/function.d.ts +21 -0
  343. package/dist/src/planner/nodes/function.d.ts.map +1 -0
  344. package/dist/src/planner/nodes/function.js +70 -0
  345. package/dist/src/planner/nodes/function.js.map +1 -0
  346. package/dist/src/planner/nodes/insert-node.d.ts +26 -0
  347. package/dist/src/planner/nodes/insert-node.d.ts.map +1 -0
  348. package/dist/src/planner/nodes/insert-node.js +82 -0
  349. package/dist/src/planner/nodes/insert-node.js.map +1 -0
  350. package/dist/src/planner/nodes/join-node.d.ts +30 -0
  351. package/dist/src/planner/nodes/join-node.d.ts.map +1 -0
  352. package/dist/src/planner/nodes/join-node.js +177 -0
  353. package/dist/src/planner/nodes/join-node.js.map +1 -0
  354. package/dist/src/planner/nodes/limit-offset.d.ts +24 -0
  355. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -0
  356. package/dist/src/planner/nodes/limit-offset.js +103 -0
  357. package/dist/src/planner/nodes/limit-offset.js.map +1 -0
  358. package/dist/src/planner/nodes/physical-access-nodes.d.ts +83 -0
  359. package/dist/src/planner/nodes/physical-access-nodes.d.ts.map +1 -0
  360. package/dist/src/planner/nodes/physical-access-nodes.js +226 -0
  361. package/dist/src/planner/nodes/physical-access-nodes.js.map +1 -0
  362. package/dist/src/planner/nodes/plan-node-type.d.ts +71 -0
  363. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -0
  364. package/dist/src/planner/nodes/plan-node-type.js +81 -0
  365. package/dist/src/planner/nodes/plan-node-type.js.map +1 -0
  366. package/dist/src/planner/nodes/plan-node.d.ts +297 -0
  367. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -0
  368. package/dist/src/planner/nodes/plan-node.js +198 -0
  369. package/dist/src/planner/nodes/plan-node.js.map +1 -0
  370. package/dist/src/planner/nodes/pragma.d.ts +21 -0
  371. package/dist/src/planner/nodes/pragma.d.ts.map +1 -0
  372. package/dist/src/planner/nodes/pragma.js +80 -0
  373. package/dist/src/planner/nodes/pragma.js.map +1 -0
  374. package/dist/src/planner/nodes/project-node.d.ts +34 -0
  375. package/dist/src/planner/nodes/project-node.d.ts.map +1 -0
  376. package/dist/src/planner/nodes/project-node.js +181 -0
  377. package/dist/src/planner/nodes/project-node.js.map +1 -0
  378. package/dist/src/planner/nodes/recursive-cte-node.d.ts +41 -0
  379. package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -0
  380. package/dist/src/planner/nodes/recursive-cte-node.js +114 -0
  381. package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -0
  382. package/dist/src/planner/nodes/reference.d.ts +92 -0
  383. package/dist/src/planner/nodes/reference.d.ts.map +1 -0
  384. package/dist/src/planner/nodes/reference.js +258 -0
  385. package/dist/src/planner/nodes/reference.js.map +1 -0
  386. package/dist/src/planner/nodes/returning-node.d.ts +37 -0
  387. package/dist/src/planner/nodes/returning-node.d.ts.map +1 -0
  388. package/dist/src/planner/nodes/returning-node.js +183 -0
  389. package/dist/src/planner/nodes/returning-node.js.map +1 -0
  390. package/dist/src/planner/nodes/scalar.d.ts +106 -0
  391. package/dist/src/planner/nodes/scalar.d.ts.map +1 -0
  392. package/dist/src/planner/nodes/scalar.js +618 -0
  393. package/dist/src/planner/nodes/scalar.js.map +1 -0
  394. package/dist/src/planner/nodes/scan.d.ts +27 -0
  395. package/dist/src/planner/nodes/scan.d.ts.map +1 -0
  396. package/dist/src/planner/nodes/scan.js +78 -0
  397. package/dist/src/planner/nodes/scan.js.map +1 -0
  398. package/dist/src/planner/nodes/sequencing-node.d.ts +25 -0
  399. package/dist/src/planner/nodes/sequencing-node.d.ts.map +1 -0
  400. package/dist/src/planner/nodes/sequencing-node.js +88 -0
  401. package/dist/src/planner/nodes/sequencing-node.js.map +1 -0
  402. package/dist/src/planner/nodes/set-operation-node.d.ts +21 -0
  403. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -0
  404. package/dist/src/planner/nodes/set-operation-node.js +68 -0
  405. package/dist/src/planner/nodes/set-operation-node.js.map +1 -0
  406. package/dist/src/planner/nodes/single-row.d.ts +24 -0
  407. package/dist/src/planner/nodes/single-row.d.ts.map +1 -0
  408. package/dist/src/planner/nodes/single-row.js +65 -0
  409. package/dist/src/planner/nodes/single-row.js.map +1 -0
  410. package/dist/src/planner/nodes/sink-node.d.ts +25 -0
  411. package/dist/src/planner/nodes/sink-node.d.ts.map +1 -0
  412. package/dist/src/planner/nodes/sink-node.js +52 -0
  413. package/dist/src/planner/nodes/sink-node.js.map +1 -0
  414. package/dist/src/planner/nodes/sort.d.ts +37 -0
  415. package/dist/src/planner/nodes/sort.d.ts.map +1 -0
  416. package/dist/src/planner/nodes/sort.js +97 -0
  417. package/dist/src/planner/nodes/sort.js.map +1 -0
  418. package/dist/src/planner/nodes/stream-aggregate.d.ts +35 -0
  419. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -0
  420. package/dist/src/planner/nodes/stream-aggregate.js +186 -0
  421. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -0
  422. package/dist/src/planner/nodes/subquery.d.ts +54 -0
  423. package/dist/src/planner/nodes/subquery.d.ts.map +1 -0
  424. package/dist/src/planner/nodes/subquery.js +181 -0
  425. package/dist/src/planner/nodes/subquery.js.map +1 -0
  426. package/dist/src/planner/nodes/table-function-call.d.ts +27 -0
  427. package/dist/src/planner/nodes/table-function-call.d.ts.map +1 -0
  428. package/dist/src/planner/nodes/table-function-call.js +101 -0
  429. package/dist/src/planner/nodes/table-function-call.js.map +1 -0
  430. package/dist/src/planner/nodes/transaction-node.d.ts +22 -0
  431. package/dist/src/planner/nodes/transaction-node.d.ts.map +1 -0
  432. package/dist/src/planner/nodes/transaction-node.js +47 -0
  433. package/dist/src/planner/nodes/transaction-node.js.map +1 -0
  434. package/dist/src/planner/nodes/update-executor-node.d.ts +24 -0
  435. package/dist/src/planner/nodes/update-executor-node.d.ts.map +1 -0
  436. package/dist/src/planner/nodes/update-executor-node.js +57 -0
  437. package/dist/src/planner/nodes/update-executor-node.js.map +1 -0
  438. package/dist/src/planner/nodes/update-node.d.ts +38 -0
  439. package/dist/src/planner/nodes/update-node.d.ts.map +1 -0
  440. package/dist/src/planner/nodes/update-node.js +88 -0
  441. package/dist/src/planner/nodes/update-node.js.map +1 -0
  442. package/dist/src/planner/nodes/values-node.d.ts +49 -0
  443. package/dist/src/planner/nodes/values-node.d.ts.map +1 -0
  444. package/dist/src/planner/nodes/values-node.js +204 -0
  445. package/dist/src/planner/nodes/values-node.js.map +1 -0
  446. package/dist/src/planner/nodes/view-reference-node.d.ts +27 -0
  447. package/dist/src/planner/nodes/view-reference-node.d.ts.map +1 -0
  448. package/dist/src/planner/nodes/view-reference-node.js +83 -0
  449. package/dist/src/planner/nodes/view-reference-node.js.map +1 -0
  450. package/dist/src/planner/nodes/window-function.d.ts +25 -0
  451. package/dist/src/planner/nodes/window-function.d.ts.map +1 -0
  452. package/dist/src/planner/nodes/window-function.js +62 -0
  453. package/dist/src/planner/nodes/window-function.js.map +1 -0
  454. package/dist/src/planner/nodes/window-node.d.ts +40 -0
  455. package/dist/src/planner/nodes/window-node.d.ts.map +1 -0
  456. package/dist/src/planner/nodes/window-node.js +156 -0
  457. package/dist/src/planner/nodes/window-node.js.map +1 -0
  458. package/dist/src/planner/optimizer-tuning.d.ts +55 -0
  459. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -0
  460. package/dist/src/planner/optimizer-tuning.js +31 -0
  461. package/dist/src/planner/optimizer-tuning.js.map +1 -0
  462. package/dist/src/planner/optimizer.d.ts +34 -0
  463. package/dist/src/planner/optimizer.d.ts.map +1 -0
  464. package/dist/src/planner/optimizer.js +194 -0
  465. package/dist/src/planner/optimizer.js.map +1 -0
  466. package/dist/src/planner/physical-utils.d.ts +36 -0
  467. package/dist/src/planner/physical-utils.d.ts.map +1 -0
  468. package/dist/src/planner/physical-utils.js +122 -0
  469. package/dist/src/planner/physical-utils.js.map +1 -0
  470. package/dist/src/planner/planning-context.d.ts +111 -0
  471. package/dist/src/planner/planning-context.d.ts.map +1 -0
  472. package/dist/src/planner/planning-context.js +75 -0
  473. package/dist/src/planner/planning-context.js.map +1 -0
  474. package/dist/src/planner/resolve.d.ts +8 -0
  475. package/dist/src/planner/resolve.d.ts.map +1 -0
  476. package/dist/src/planner/resolve.js +91 -0
  477. package/dist/src/planner/resolve.js.map +1 -0
  478. package/dist/src/planner/rules/access/rule-select-access-path.d.ts +11 -0
  479. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -0
  480. package/dist/src/planner/rules/access/rule-select-access-path.js +133 -0
  481. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -0
  482. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts +11 -0
  483. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -0
  484. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +53 -0
  485. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -0
  486. package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts +11 -0
  487. package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts.map +1 -0
  488. package/dist/src/planner/rules/cache/rule-cte-optimization.js +38 -0
  489. package/dist/src/planner/rules/cache/rule-cte-optimization.js.map +1 -0
  490. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts +11 -0
  491. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts.map +1 -0
  492. package/dist/src/planner/rules/cache/rule-materialization-advisory.js +51 -0
  493. package/dist/src/planner/rules/cache/rule-materialization-advisory.js.map +1 -0
  494. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts +11 -0
  495. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts.map +1 -0
  496. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js +79 -0
  497. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js.map +1 -0
  498. package/dist/src/planner/rules/physical/rule-filter-optimization.d.ts +11 -0
  499. package/dist/src/planner/rules/physical/rule-filter-optimization.d.ts.map +1 -0
  500. package/dist/src/planner/rules/physical/rule-filter-optimization.js +49 -0
  501. package/dist/src/planner/rules/physical/rule-filter-optimization.js.map +1 -0
  502. package/dist/src/planner/rules/physical/rule-mark-physical.d.ts +11 -0
  503. package/dist/src/planner/rules/physical/rule-mark-physical.d.ts.map +1 -0
  504. package/dist/src/planner/rules/physical/rule-mark-physical.js +29 -0
  505. package/dist/src/planner/rules/physical/rule-mark-physical.js.map +1 -0
  506. package/dist/src/planner/rules/physical/rule-project-optimization.d.ts +11 -0
  507. package/dist/src/planner/rules/physical/rule-project-optimization.d.ts.map +1 -0
  508. package/dist/src/planner/rules/physical/rule-project-optimization.js +44 -0
  509. package/dist/src/planner/rules/physical/rule-project-optimization.js.map +1 -0
  510. package/dist/src/planner/rules/physical/rule-sort-optimization.d.ts +11 -0
  511. package/dist/src/planner/rules/physical/rule-sort-optimization.d.ts.map +1 -0
  512. package/dist/src/planner/rules/physical/rule-sort-optimization.js +53 -0
  513. package/dist/src/planner/rules/physical/rule-sort-optimization.js.map +1 -0
  514. package/dist/src/planner/rules/rewrite/rule-constant-folding.d.ts +11 -0
  515. package/dist/src/planner/rules/rewrite/rule-constant-folding.d.ts.map +1 -0
  516. package/dist/src/planner/rules/rewrite/rule-constant-folding.js +59 -0
  517. package/dist/src/planner/rules/rewrite/rule-constant-folding.js.map +1 -0
  518. package/dist/src/planner/scopes/aliased.d.ts +18 -0
  519. package/dist/src/planner/scopes/aliased.d.ts.map +1 -0
  520. package/dist/src/planner/scopes/aliased.js +41 -0
  521. package/dist/src/planner/scopes/aliased.js.map +1 -0
  522. package/dist/src/planner/scopes/base.d.ts +20 -0
  523. package/dist/src/planner/scopes/base.d.ts.map +1 -0
  524. package/dist/src/planner/scopes/base.js +20 -0
  525. package/dist/src/planner/scopes/base.js.map +1 -0
  526. package/dist/src/planner/scopes/empty.d.ts +11 -0
  527. package/dist/src/planner/scopes/empty.d.ts.map +1 -0
  528. package/dist/src/planner/scopes/empty.js +16 -0
  529. package/dist/src/planner/scopes/empty.js.map +1 -0
  530. package/dist/src/planner/scopes/global.d.ts +12 -0
  531. package/dist/src/planner/scopes/global.d.ts.map +1 -0
  532. package/dist/src/planner/scopes/global.js +65 -0
  533. package/dist/src/planner/scopes/global.js.map +1 -0
  534. package/dist/src/planner/scopes/multi.d.ts +17 -0
  535. package/dist/src/planner/scopes/multi.d.ts.map +1 -0
  536. package/dist/src/planner/scopes/multi.js +35 -0
  537. package/dist/src/planner/scopes/multi.js.map +1 -0
  538. package/dist/src/planner/scopes/param.d.ts +23 -0
  539. package/dist/src/planner/scopes/param.d.ts.map +1 -0
  540. package/dist/src/planner/scopes/param.js +78 -0
  541. package/dist/src/planner/scopes/param.js.map +1 -0
  542. package/dist/src/planner/scopes/registered.d.ts +47 -0
  543. package/dist/src/planner/scopes/registered.d.ts.map +1 -0
  544. package/dist/src/planner/scopes/registered.js +70 -0
  545. package/dist/src/planner/scopes/registered.js.map +1 -0
  546. package/dist/src/planner/scopes/scope.d.ts +21 -0
  547. package/dist/src/planner/scopes/scope.d.ts.map +1 -0
  548. package/dist/src/planner/scopes/scope.js +3 -0
  549. package/dist/src/planner/scopes/scope.js.map +1 -0
  550. package/dist/src/planner/stats/basic-estimates.d.ts +47 -0
  551. package/dist/src/planner/stats/basic-estimates.d.ts.map +1 -0
  552. package/dist/src/planner/stats/basic-estimates.js +99 -0
  553. package/dist/src/planner/stats/basic-estimates.js.map +1 -0
  554. package/dist/src/planner/stats/index.d.ts +88 -0
  555. package/dist/src/planner/stats/index.d.ts.map +1 -0
  556. package/dist/src/planner/stats/index.js +152 -0
  557. package/dist/src/planner/stats/index.js.map +1 -0
  558. package/dist/src/planner/type-utils.d.ts +30 -0
  559. package/dist/src/planner/type-utils.d.ts.map +1 -0
  560. package/dist/src/planner/type-utils.js +91 -0
  561. package/dist/src/planner/type-utils.js.map +1 -0
  562. package/dist/src/planner/validation/plan-validator.d.ts +29 -0
  563. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -0
  564. package/dist/src/planner/validation/plan-validator.js +238 -0
  565. package/dist/src/planner/validation/plan-validator.js.map +1 -0
  566. package/dist/src/runtime/async-util.d.ts +53 -0
  567. package/dist/src/runtime/async-util.d.ts.map +1 -0
  568. package/dist/src/runtime/async-util.js +238 -0
  569. package/dist/src/runtime/async-util.js.map +1 -0
  570. package/dist/src/runtime/cache/shared-cache.d.ts +68 -0
  571. package/dist/src/runtime/cache/shared-cache.d.ts.map +1 -0
  572. package/dist/src/runtime/cache/shared-cache.js +107 -0
  573. package/dist/src/runtime/cache/shared-cache.js.map +1 -0
  574. package/dist/src/runtime/emission-context.d.ts +121 -0
  575. package/dist/src/runtime/emission-context.d.ts.map +1 -0
  576. package/dist/src/runtime/emission-context.js +258 -0
  577. package/dist/src/runtime/emission-context.js.map +1 -0
  578. package/dist/src/runtime/emit/add-constraint.d.ts +5 -0
  579. package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -0
  580. package/dist/src/runtime/emit/add-constraint.js +35 -0
  581. package/dist/src/runtime/emit/add-constraint.js.map +1 -0
  582. package/dist/src/runtime/emit/aggregate.d.ts +6 -0
  583. package/dist/src/runtime/emit/aggregate.d.ts.map +1 -0
  584. package/dist/src/runtime/emit/aggregate.js +465 -0
  585. package/dist/src/runtime/emit/aggregate.js.map +1 -0
  586. package/dist/src/runtime/emit/array-index.d.ts +5 -0
  587. package/dist/src/runtime/emit/array-index.d.ts.map +1 -0
  588. package/dist/src/runtime/emit/array-index.js +20 -0
  589. package/dist/src/runtime/emit/array-index.js.map +1 -0
  590. package/dist/src/runtime/emit/binary.d.ts +11 -0
  591. package/dist/src/runtime/emit/binary.d.ts.map +1 -0
  592. package/dist/src/runtime/emit/binary.js +310 -0
  593. package/dist/src/runtime/emit/binary.js.map +1 -0
  594. package/dist/src/runtime/emit/block.d.ts +5 -0
  595. package/dist/src/runtime/emit/block.d.ts.map +1 -0
  596. package/dist/src/runtime/emit/block.js +16 -0
  597. package/dist/src/runtime/emit/block.js.map +1 -0
  598. package/dist/src/runtime/emit/cache.d.ts +25 -0
  599. package/dist/src/runtime/emit/cache.d.ts.map +1 -0
  600. package/dist/src/runtime/emit/cache.js +52 -0
  601. package/dist/src/runtime/emit/cache.js.map +1 -0
  602. package/dist/src/runtime/emit/case.d.ts +5 -0
  603. package/dist/src/runtime/emit/case.d.ts.map +1 -0
  604. package/dist/src/runtime/emit/case.js +65 -0
  605. package/dist/src/runtime/emit/case.js.map +1 -0
  606. package/dist/src/runtime/emit/cast.d.ts +5 -0
  607. package/dist/src/runtime/emit/cast.d.ts.map +1 -0
  608. package/dist/src/runtime/emit/cast.js +132 -0
  609. package/dist/src/runtime/emit/cast.js.map +1 -0
  610. package/dist/src/runtime/emit/collate.d.ts +5 -0
  611. package/dist/src/runtime/emit/collate.d.ts.map +1 -0
  612. package/dist/src/runtime/emit/collate.js +6 -0
  613. package/dist/src/runtime/emit/collate.js.map +1 -0
  614. package/dist/src/runtime/emit/column-reference.d.ts +5 -0
  615. package/dist/src/runtime/emit/column-reference.d.ts.map +1 -0
  616. package/dist/src/runtime/emit/column-reference.js +36 -0
  617. package/dist/src/runtime/emit/column-reference.js.map +1 -0
  618. package/dist/src/runtime/emit/constraint-check.d.ts +5 -0
  619. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -0
  620. package/dist/src/runtime/emit/constraint-check.js +211 -0
  621. package/dist/src/runtime/emit/constraint-check.js.map +1 -0
  622. package/dist/src/runtime/emit/create-index.d.ts +5 -0
  623. package/dist/src/runtime/emit/create-index.d.ts.map +1 -0
  624. package/dist/src/runtime/emit/create-index.js +9 -0
  625. package/dist/src/runtime/emit/create-index.js.map +1 -0
  626. package/dist/src/runtime/emit/create-table.d.ts +5 -0
  627. package/dist/src/runtime/emit/create-table.d.ts.map +1 -0
  628. package/dist/src/runtime/emit/create-table.js +9 -0
  629. package/dist/src/runtime/emit/create-table.js.map +1 -0
  630. package/dist/src/runtime/emit/create-view.d.ts +5 -0
  631. package/dist/src/runtime/emit/create-view.d.ts.map +1 -0
  632. package/dist/src/runtime/emit/create-view.js +36 -0
  633. package/dist/src/runtime/emit/create-view.js.map +1 -0
  634. package/dist/src/runtime/emit/cte-reference.d.ts +5 -0
  635. package/dist/src/runtime/emit/cte-reference.d.ts.map +1 -0
  636. package/dist/src/runtime/emit/cte-reference.js +56 -0
  637. package/dist/src/runtime/emit/cte-reference.js.map +1 -0
  638. package/dist/src/runtime/emit/cte.d.ts +5 -0
  639. package/dist/src/runtime/emit/cte.d.ts.map +1 -0
  640. package/dist/src/runtime/emit/cte.js +34 -0
  641. package/dist/src/runtime/emit/cte.js.map +1 -0
  642. package/dist/src/runtime/emit/delete.d.ts +5 -0
  643. package/dist/src/runtime/emit/delete.d.ts.map +1 -0
  644. package/dist/src/runtime/emit/delete.js +18 -0
  645. package/dist/src/runtime/emit/delete.js.map +1 -0
  646. package/dist/src/runtime/emit/distinct.d.ts +5 -0
  647. package/dist/src/runtime/emit/distinct.d.ts.map +1 -0
  648. package/dist/src/runtime/emit/distinct.js +35 -0
  649. package/dist/src/runtime/emit/distinct.js.map +1 -0
  650. package/dist/src/runtime/emit/dml-executor.d.ts +5 -0
  651. package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -0
  652. package/dist/src/runtime/emit/dml-executor.js +90 -0
  653. package/dist/src/runtime/emit/dml-executor.js.map +1 -0
  654. package/dist/src/runtime/emit/drop-table.d.ts +5 -0
  655. package/dist/src/runtime/emit/drop-table.d.ts.map +1 -0
  656. package/dist/src/runtime/emit/drop-table.js +19 -0
  657. package/dist/src/runtime/emit/drop-table.js.map +1 -0
  658. package/dist/src/runtime/emit/drop-view.d.ts +5 -0
  659. package/dist/src/runtime/emit/drop-view.d.ts.map +1 -0
  660. package/dist/src/runtime/emit/drop-view.js +31 -0
  661. package/dist/src/runtime/emit/drop-view.js.map +1 -0
  662. package/dist/src/runtime/emit/filter.d.ts +5 -0
  663. package/dist/src/runtime/emit/filter.d.ts.map +1 -0
  664. package/dist/src/runtime/emit/filter.js +30 -0
  665. package/dist/src/runtime/emit/filter.js.map +1 -0
  666. package/dist/src/runtime/emit/insert.d.ts +5 -0
  667. package/dist/src/runtime/emit/insert.d.ts.map +1 -0
  668. package/dist/src/runtime/emit/insert.js +52 -0
  669. package/dist/src/runtime/emit/insert.js.map +1 -0
  670. package/dist/src/runtime/emit/join.d.ts +9 -0
  671. package/dist/src/runtime/emit/join.d.ts.map +1 -0
  672. package/dist/src/runtime/emit/join.js +116 -0
  673. package/dist/src/runtime/emit/join.js.map +1 -0
  674. package/dist/src/runtime/emit/limit-offset.d.ts +5 -0
  675. package/dist/src/runtime/emit/limit-offset.d.ts.map +1 -0
  676. package/dist/src/runtime/emit/limit-offset.js +56 -0
  677. package/dist/src/runtime/emit/limit-offset.js.map +1 -0
  678. package/dist/src/runtime/emit/literal.d.ts +5 -0
  679. package/dist/src/runtime/emit/literal.d.ts.map +1 -0
  680. package/dist/src/runtime/emit/literal.js +12 -0
  681. package/dist/src/runtime/emit/literal.js.map +1 -0
  682. package/dist/src/runtime/emit/parameter.d.ts +5 -0
  683. package/dist/src/runtime/emit/parameter.d.ts.map +1 -0
  684. package/dist/src/runtime/emit/parameter.js +57 -0
  685. package/dist/src/runtime/emit/parameter.js.map +1 -0
  686. package/dist/src/runtime/emit/pragma.d.ts +5 -0
  687. package/dist/src/runtime/emit/pragma.d.ts.map +1 -0
  688. package/dist/src/runtime/emit/pragma.js +44 -0
  689. package/dist/src/runtime/emit/pragma.js.map +1 -0
  690. package/dist/src/runtime/emit/project.d.ts +5 -0
  691. package/dist/src/runtime/emit/project.d.ts.map +1 -0
  692. package/dist/src/runtime/emit/project.js +32 -0
  693. package/dist/src/runtime/emit/project.js.map +1 -0
  694. package/dist/src/runtime/emit/recursive-cte.d.ts +5 -0
  695. package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -0
  696. package/dist/src/runtime/emit/recursive-cte.js +92 -0
  697. package/dist/src/runtime/emit/recursive-cte.js.map +1 -0
  698. package/dist/src/runtime/emit/returning.d.ts +5 -0
  699. package/dist/src/runtime/emit/returning.d.ts.map +1 -0
  700. package/dist/src/runtime/emit/returning.js +34 -0
  701. package/dist/src/runtime/emit/returning.js.map +1 -0
  702. package/dist/src/runtime/emit/scalar-function.d.ts +5 -0
  703. package/dist/src/runtime/emit/scalar-function.d.ts.map +1 -0
  704. package/dist/src/runtime/emit/scalar-function.js +29 -0
  705. package/dist/src/runtime/emit/scalar-function.js.map +1 -0
  706. package/dist/src/runtime/emit/scan.d.ts +5 -0
  707. package/dist/src/runtime/emit/scan.d.ts.map +1 -0
  708. package/dist/src/runtime/emit/scan.js +63 -0
  709. package/dist/src/runtime/emit/scan.js.map +1 -0
  710. package/dist/src/runtime/emit/sequencing.d.ts +5 -0
  711. package/dist/src/runtime/emit/sequencing.d.ts.map +1 -0
  712. package/dist/src/runtime/emit/sequencing.js +17 -0
  713. package/dist/src/runtime/emit/sequencing.js.map +1 -0
  714. package/dist/src/runtime/emit/set-operation.d.ts +5 -0
  715. package/dist/src/runtime/emit/set-operation.d.ts.map +1 -0
  716. package/dist/src/runtime/emit/set-operation.js +99 -0
  717. package/dist/src/runtime/emit/set-operation.js.map +1 -0
  718. package/dist/src/runtime/emit/sink.d.ts +5 -0
  719. package/dist/src/runtime/emit/sink.d.ts.map +1 -0
  720. package/dist/src/runtime/emit/sink.js +19 -0
  721. package/dist/src/runtime/emit/sink.js.map +1 -0
  722. package/dist/src/runtime/emit/sort.d.ts +5 -0
  723. package/dist/src/runtime/emit/sort.d.ts.map +1 -0
  724. package/dist/src/runtime/emit/sort.js +59 -0
  725. package/dist/src/runtime/emit/sort.js.map +1 -0
  726. package/dist/src/runtime/emit/subquery.d.ts +7 -0
  727. package/dist/src/runtime/emit/subquery.d.ts.map +1 -0
  728. package/dist/src/runtime/emit/subquery.js +114 -0
  729. package/dist/src/runtime/emit/subquery.js.map +1 -0
  730. package/dist/src/runtime/emit/table-reference.d.ts +5 -0
  731. package/dist/src/runtime/emit/table-reference.d.ts.map +1 -0
  732. package/dist/src/runtime/emit/table-reference.js +67 -0
  733. package/dist/src/runtime/emit/table-reference.js.map +1 -0
  734. package/dist/src/runtime/emit/table-valued-function.d.ts +5 -0
  735. package/dist/src/runtime/emit/table-valued-function.d.ts.map +1 -0
  736. package/dist/src/runtime/emit/table-valued-function.js +98 -0
  737. package/dist/src/runtime/emit/table-valued-function.js.map +1 -0
  738. package/dist/src/runtime/emit/transaction.d.ts +5 -0
  739. package/dist/src/runtime/emit/transaction.d.ts.map +1 -0
  740. package/dist/src/runtime/emit/transaction.js +153 -0
  741. package/dist/src/runtime/emit/transaction.js.map +1 -0
  742. package/dist/src/runtime/emit/unary.d.ts +5 -0
  743. package/dist/src/runtime/emit/unary.d.ts.map +1 -0
  744. package/dist/src/runtime/emit/unary.js +81 -0
  745. package/dist/src/runtime/emit/unary.js.map +1 -0
  746. package/dist/src/runtime/emit/update-executor.d.ts +5 -0
  747. package/dist/src/runtime/emit/update-executor.d.ts.map +1 -0
  748. package/dist/src/runtime/emit/update-executor.js +54 -0
  749. package/dist/src/runtime/emit/update-executor.js.map +1 -0
  750. package/dist/src/runtime/emit/update.d.ts +5 -0
  751. package/dist/src/runtime/emit/update.d.ts.map +1 -0
  752. package/dist/src/runtime/emit/update.js +58 -0
  753. package/dist/src/runtime/emit/update.js.map +1 -0
  754. package/dist/src/runtime/emit/values.d.ts +9 -0
  755. package/dist/src/runtime/emit/values.d.ts.map +1 -0
  756. package/dist/src/runtime/emit/values.js +51 -0
  757. package/dist/src/runtime/emit/values.js.map +1 -0
  758. package/dist/src/runtime/emit/window-function.d.ts +5 -0
  759. package/dist/src/runtime/emit/window-function.d.ts.map +1 -0
  760. package/dist/src/runtime/emit/window-function.js +31 -0
  761. package/dist/src/runtime/emit/window-function.js.map +1 -0
  762. package/dist/src/runtime/emit/window.d.ts +5 -0
  763. package/dist/src/runtime/emit/window.d.ts.map +1 -0
  764. package/dist/src/runtime/emit/window.js +328 -0
  765. package/dist/src/runtime/emit/window.js.map +1 -0
  766. package/dist/src/runtime/emitters.d.ts +48 -0
  767. package/dist/src/runtime/emitters.d.ts.map +1 -0
  768. package/dist/src/runtime/emitters.js +73 -0
  769. package/dist/src/runtime/emitters.js.map +1 -0
  770. package/dist/src/runtime/register.d.ts +2 -0
  771. package/dist/src/runtime/register.d.ts.map +1 -0
  772. package/dist/src/runtime/register.js +122 -0
  773. package/dist/src/runtime/register.js.map +1 -0
  774. package/dist/src/runtime/scheduler.d.ts +27 -0
  775. package/dist/src/runtime/scheduler.d.ts.map +1 -0
  776. package/dist/src/runtime/scheduler.js +385 -0
  777. package/dist/src/runtime/scheduler.js.map +1 -0
  778. package/dist/src/runtime/types.d.ts +109 -0
  779. package/dist/src/runtime/types.d.ts.map +1 -0
  780. package/dist/src/runtime/types.js +90 -0
  781. package/dist/src/runtime/types.js.map +1 -0
  782. package/dist/src/runtime/utils.d.ts +32 -0
  783. package/dist/src/runtime/utils.d.ts.map +1 -0
  784. package/dist/src/runtime/utils.js +117 -0
  785. package/dist/src/runtime/utils.js.map +1 -0
  786. package/dist/src/schema/change-events.d.ts +42 -0
  787. package/dist/src/schema/change-events.d.ts.map +1 -0
  788. package/dist/src/schema/change-events.js +55 -0
  789. package/dist/src/schema/change-events.js.map +1 -0
  790. package/dist/src/schema/column.d.ts +33 -0
  791. package/dist/src/schema/column.d.ts.map +1 -0
  792. package/dist/src/schema/column.js +22 -0
  793. package/dist/src/schema/column.js.map +1 -0
  794. package/dist/src/schema/function.d.ts +109 -0
  795. package/dist/src/schema/function.d.ts.map +1 -0
  796. package/dist/src/schema/function.js +26 -0
  797. package/dist/src/schema/function.js.map +1 -0
  798. package/dist/src/schema/manager.d.ts +222 -0
  799. package/dist/src/schema/manager.d.ts.map +1 -0
  800. package/dist/src/schema/manager.js +608 -0
  801. package/dist/src/schema/manager.js.map +1 -0
  802. package/dist/src/schema/schema.d.ts +110 -0
  803. package/dist/src/schema/schema.d.ts.map +1 -0
  804. package/dist/src/schema/schema.js +179 -0
  805. package/dist/src/schema/schema.js.map +1 -0
  806. package/dist/src/schema/table.d.ts +143 -0
  807. package/dist/src/schema/table.d.ts.map +1 -0
  808. package/dist/src/schema/table.js +245 -0
  809. package/dist/src/schema/table.js.map +1 -0
  810. package/dist/src/schema/view.d.ts +18 -0
  811. package/dist/src/schema/view.d.ts.map +1 -0
  812. package/dist/src/schema/view.js +2 -0
  813. package/dist/src/schema/view.js.map +1 -0
  814. package/dist/src/schema/window-function.d.ts +26 -0
  815. package/dist/src/schema/window-function.d.ts.map +1 -0
  816. package/dist/src/schema/window-function.js +34 -0
  817. package/dist/src/schema/window-function.js.map +1 -0
  818. package/dist/src/util/affinity.d.ts +34 -0
  819. package/dist/src/util/affinity.d.ts.map +1 -0
  820. package/dist/src/util/affinity.js +153 -0
  821. package/dist/src/util/affinity.js.map +1 -0
  822. package/dist/src/util/ast-stringify.d.ts +23 -0
  823. package/dist/src/util/ast-stringify.d.ts.map +1 -0
  824. package/dist/src/util/ast-stringify.js +683 -0
  825. package/dist/src/util/ast-stringify.js.map +1 -0
  826. package/dist/src/util/cached.d.ts +11 -0
  827. package/dist/src/util/cached.d.ts.map +1 -0
  828. package/dist/src/util/cached.js +24 -0
  829. package/dist/src/util/cached.js.map +1 -0
  830. package/dist/src/util/coercion.d.ts +34 -0
  831. package/dist/src/util/coercion.d.ts.map +1 -0
  832. package/dist/src/util/coercion.js +106 -0
  833. package/dist/src/util/coercion.js.map +1 -0
  834. package/dist/src/util/comparison.d.ts +153 -0
  835. package/dist/src/util/comparison.d.ts.map +1 -0
  836. package/dist/src/util/comparison.js +397 -0
  837. package/dist/src/util/comparison.js.map +1 -0
  838. package/dist/src/util/environment.d.ts +28 -0
  839. package/dist/src/util/environment.d.ts.map +1 -0
  840. package/dist/src/util/environment.js +47 -0
  841. package/dist/src/util/environment.js.map +1 -0
  842. package/dist/src/util/latches.d.ts +16 -0
  843. package/dist/src/util/latches.d.ts.map +1 -0
  844. package/dist/src/util/latches.js +41 -0
  845. package/dist/src/util/latches.js.map +1 -0
  846. package/dist/src/util/patterns.d.ts +23 -0
  847. package/dist/src/util/patterns.d.ts.map +1 -0
  848. package/dist/src/util/patterns.js +54 -0
  849. package/dist/src/util/patterns.js.map +1 -0
  850. package/dist/src/util/plan-formatter.d.ts +23 -0
  851. package/dist/src/util/plan-formatter.d.ts.map +1 -0
  852. package/dist/src/util/plan-formatter.js +41 -0
  853. package/dist/src/util/plan-formatter.js.map +1 -0
  854. package/dist/src/util/plugin-loader.d.ts +20 -0
  855. package/dist/src/util/plugin-loader.d.ts.map +1 -0
  856. package/dist/src/util/plugin-loader.js +57 -0
  857. package/dist/src/util/plugin-loader.js.map +1 -0
  858. package/dist/src/util/row-descriptor.d.ts +35 -0
  859. package/dist/src/util/row-descriptor.d.ts.map +1 -0
  860. package/dist/src/util/row-descriptor.js +85 -0
  861. package/dist/src/util/row-descriptor.js.map +1 -0
  862. package/dist/src/util/serialization.d.ts +11 -0
  863. package/dist/src/util/serialization.d.ts.map +1 -0
  864. package/dist/src/util/serialization.js +41 -0
  865. package/dist/src/util/serialization.js.map +1 -0
  866. package/dist/src/util/working-table-iterable.d.ts +17 -0
  867. package/dist/src/util/working-table-iterable.d.ts.map +1 -0
  868. package/dist/src/util/working-table-iterable.js +30 -0
  869. package/dist/src/util/working-table-iterable.js.map +1 -0
  870. package/dist/src/vtab/best-access-plan.d.ts +144 -0
  871. package/dist/src/vtab/best-access-plan.d.ts.map +1 -0
  872. package/dist/src/vtab/best-access-plan.js +156 -0
  873. package/dist/src/vtab/best-access-plan.js.map +1 -0
  874. package/dist/src/vtab/connection.d.ts +27 -0
  875. package/dist/src/vtab/connection.d.ts.map +1 -0
  876. package/dist/src/vtab/connection.js +2 -0
  877. package/dist/src/vtab/connection.js.map +1 -0
  878. package/dist/src/vtab/filter-info.d.ts +26 -0
  879. package/dist/src/vtab/filter-info.d.ts.map +1 -0
  880. package/dist/src/vtab/filter-info.js +2 -0
  881. package/dist/src/vtab/filter-info.js.map +1 -0
  882. package/dist/src/vtab/index-info.d.ts +69 -0
  883. package/dist/src/vtab/index-info.d.ts.map +1 -0
  884. package/dist/src/vtab/index-info.js +7 -0
  885. package/dist/src/vtab/index-info.js.map +1 -0
  886. package/dist/src/vtab/manifest.d.ts +35 -0
  887. package/dist/src/vtab/manifest.d.ts.map +1 -0
  888. package/dist/src/vtab/manifest.js +2 -0
  889. package/dist/src/vtab/manifest.js.map +1 -0
  890. package/dist/src/vtab/memory/connection.d.ts +29 -0
  891. package/dist/src/vtab/memory/connection.d.ts.map +1 -0
  892. package/dist/src/vtab/memory/connection.js +61 -0
  893. package/dist/src/vtab/memory/connection.js.map +1 -0
  894. package/dist/src/vtab/memory/index.d.ts +38 -0
  895. package/dist/src/vtab/memory/index.d.ts.map +1 -0
  896. package/dist/src/vtab/memory/index.js +132 -0
  897. package/dist/src/vtab/memory/index.js.map +1 -0
  898. package/dist/src/vtab/memory/layer/base-cursor.d.ts +5 -0
  899. package/dist/src/vtab/memory/layer/base-cursor.d.ts.map +1 -0
  900. package/dist/src/vtab/memory/layer/base-cursor.js +111 -0
  901. package/dist/src/vtab/memory/layer/base-cursor.js.map +1 -0
  902. package/dist/src/vtab/memory/layer/base.d.ts +51 -0
  903. package/dist/src/vtab/memory/layer/base.d.ts.map +1 -0
  904. package/dist/src/vtab/memory/layer/base.js +199 -0
  905. package/dist/src/vtab/memory/layer/base.js.map +1 -0
  906. package/dist/src/vtab/memory/layer/connection.d.ts +38 -0
  907. package/dist/src/vtab/memory/layer/connection.d.ts.map +1 -0
  908. package/dist/src/vtab/memory/layer/connection.js +170 -0
  909. package/dist/src/vtab/memory/layer/connection.js.map +1 -0
  910. package/dist/src/vtab/memory/layer/interface.d.ts +41 -0
  911. package/dist/src/vtab/memory/layer/interface.d.ts.map +1 -0
  912. package/dist/src/vtab/memory/layer/interface.js +2 -0
  913. package/dist/src/vtab/memory/layer/interface.js.map +1 -0
  914. package/dist/src/vtab/memory/layer/manager.d.ts +68 -0
  915. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -0
  916. package/dist/src/vtab/memory/layer/manager.js +752 -0
  917. package/dist/src/vtab/memory/layer/manager.js.map +1 -0
  918. package/dist/src/vtab/memory/layer/safe-iterate.d.ts +9 -0
  919. package/dist/src/vtab/memory/layer/safe-iterate.d.ts.map +1 -0
  920. package/dist/src/vtab/memory/layer/safe-iterate.js +47 -0
  921. package/dist/src/vtab/memory/layer/safe-iterate.js.map +1 -0
  922. package/dist/src/vtab/memory/layer/scan-plan.d.ts +37 -0
  923. package/dist/src/vtab/memory/layer/scan-plan.d.ts.map +1 -0
  924. package/dist/src/vtab/memory/layer/scan-plan.js +87 -0
  925. package/dist/src/vtab/memory/layer/scan-plan.js.map +1 -0
  926. package/dist/src/vtab/memory/layer/transaction-cursor.d.ts +5 -0
  927. package/dist/src/vtab/memory/layer/transaction-cursor.d.ts.map +1 -0
  928. package/dist/src/vtab/memory/layer/transaction-cursor.js +149 -0
  929. package/dist/src/vtab/memory/layer/transaction-cursor.js.map +1 -0
  930. package/dist/src/vtab/memory/layer/transaction.d.ts +44 -0
  931. package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -0
  932. package/dist/src/vtab/memory/layer/transaction.js +183 -0
  933. package/dist/src/vtab/memory/layer/transaction.js.map +1 -0
  934. package/dist/src/vtab/memory/module.d.ts +89 -0
  935. package/dist/src/vtab/memory/module.d.ts.map +1 -0
  936. package/dist/src/vtab/memory/module.js +533 -0
  937. package/dist/src/vtab/memory/module.js.map +1 -0
  938. package/dist/src/vtab/memory/table.d.ts +49 -0
  939. package/dist/src/vtab/memory/table.d.ts.map +1 -0
  940. package/dist/src/vtab/memory/table.js +209 -0
  941. package/dist/src/vtab/memory/table.js.map +1 -0
  942. package/dist/src/vtab/memory/types.d.ts +19 -0
  943. package/dist/src/vtab/memory/types.d.ts.map +1 -0
  944. package/dist/src/vtab/memory/types.js +2 -0
  945. package/dist/src/vtab/memory/types.js.map +1 -0
  946. package/dist/src/vtab/memory/utils/logging.d.ts +13 -0
  947. package/dist/src/vtab/memory/utils/logging.d.ts.map +1 -0
  948. package/dist/src/vtab/memory/utils/logging.js +28 -0
  949. package/dist/src/vtab/memory/utils/logging.js.map +1 -0
  950. package/dist/src/vtab/memory/utils/primary-key.d.ts +21 -0
  951. package/dist/src/vtab/memory/utils/primary-key.d.ts.map +1 -0
  952. package/dist/src/vtab/memory/utils/primary-key.js +107 -0
  953. package/dist/src/vtab/memory/utils/primary-key.js.map +1 -0
  954. package/dist/src/vtab/module.d.ts +111 -0
  955. package/dist/src/vtab/module.d.ts.map +1 -0
  956. package/dist/src/vtab/module.js +2 -0
  957. package/dist/src/vtab/module.js.map +1 -0
  958. package/dist/src/vtab/table.d.ts +114 -0
  959. package/dist/src/vtab/table.d.ts.map +1 -0
  960. package/dist/src/vtab/table.js +26 -0
  961. package/dist/src/vtab/table.js.map +1 -0
  962. package/package.json +61 -0
  963. package/src/common/constants.ts +60 -0
  964. package/src/common/datatype.ts +86 -0
  965. package/src/common/errors.ts +189 -0
  966. package/src/common/logger.ts +23 -0
  967. package/src/common/type-inference.ts +40 -0
  968. package/src/common/types.ts +148 -0
  969. package/src/core/database-options.ts +258 -0
  970. package/src/core/database.ts +875 -0
  971. package/src/core/param.ts +41 -0
  972. package/src/core/statement.ts +490 -0
  973. package/src/func/builtins/aggregate.ts +247 -0
  974. package/src/func/builtins/builtin-window-functions.ts +165 -0
  975. package/src/func/builtins/datetime.ts +453 -0
  976. package/src/func/builtins/explain.ts +648 -0
  977. package/src/func/builtins/generation.ts +43 -0
  978. package/src/func/builtins/index.ts +126 -0
  979. package/src/func/builtins/json-helpers.ts +237 -0
  980. package/src/func/builtins/json-tvf.ts +225 -0
  981. package/src/func/builtins/json.ts +466 -0
  982. package/src/func/builtins/scalar.ts +232 -0
  983. package/src/func/builtins/schema.ts +193 -0
  984. package/src/func/builtins/string.ts +293 -0
  985. package/src/func/context.ts +251 -0
  986. package/src/func/registration.ts +167 -0
  987. package/src/index.ts +67 -0
  988. package/src/parser/ast.ts +475 -0
  989. package/src/parser/index.ts +65 -0
  990. package/src/parser/lexer.ts +767 -0
  991. package/src/parser/parser.ts +2783 -0
  992. package/src/parser/utils.ts +10 -0
  993. package/src/parser/visitor.ts +187 -0
  994. package/src/planner/analysis/README.md +93 -0
  995. package/src/planner/analysis/const-evaluator.ts +63 -0
  996. package/src/planner/analysis/const-pass.ts +270 -0
  997. package/src/planner/analysis/constraint-extractor.ts +277 -0
  998. package/src/planner/building/alter-table.ts +47 -0
  999. package/src/planner/building/block.ts +78 -0
  1000. package/src/planner/building/create-view.ts +56 -0
  1001. package/src/planner/building/ddl.ts +24 -0
  1002. package/src/planner/building/delete.ts +158 -0
  1003. package/src/planner/building/drop-table.ts +13 -0
  1004. package/src/planner/building/drop-view.ts +19 -0
  1005. package/src/planner/building/expression.ts +176 -0
  1006. package/src/planner/building/function-call.ts +87 -0
  1007. package/src/planner/building/insert.ts +336 -0
  1008. package/src/planner/building/pragma.ts +33 -0
  1009. package/src/planner/building/schema-resolution.ts +176 -0
  1010. package/src/planner/building/select-aggregates.ts +245 -0
  1011. package/src/planner/building/select-compound.ts +110 -0
  1012. package/src/planner/building/select-context.ts +75 -0
  1013. package/src/planner/building/select-modifiers.ts +170 -0
  1014. package/src/planner/building/select-projections.ts +177 -0
  1015. package/src/planner/building/select-window.ts +248 -0
  1016. package/src/planner/building/select.ts +388 -0
  1017. package/src/planner/building/table-function.ts +48 -0
  1018. package/src/planner/building/table.ts +73 -0
  1019. package/src/planner/building/transaction.ts +23 -0
  1020. package/src/planner/building/update.ts +255 -0
  1021. package/src/planner/building/with.ts +181 -0
  1022. package/src/planner/cache/materialization-advisory.ts +244 -0
  1023. package/src/planner/cache/reference-graph.ts +172 -0
  1024. package/src/planner/cost/index.ts +169 -0
  1025. package/src/planner/debug/logger-utils.ts +68 -0
  1026. package/src/planner/debug.ts +316 -0
  1027. package/src/planner/framework/README.md +132 -0
  1028. package/src/planner/framework/context.ts +188 -0
  1029. package/src/planner/framework/physical-utils.ts +210 -0
  1030. package/src/planner/framework/registry.ts +274 -0
  1031. package/src/planner/framework/trace.ts +259 -0
  1032. package/src/planner/nodes/add-constraint-node.ts +58 -0
  1033. package/src/planner/nodes/aggregate-function.ts +145 -0
  1034. package/src/planner/nodes/aggregate-node.ts +220 -0
  1035. package/src/planner/nodes/array-index-node.ts +50 -0
  1036. package/src/planner/nodes/block.ts +80 -0
  1037. package/src/planner/nodes/cache-node.ts +94 -0
  1038. package/src/planner/nodes/constraint-check-node.ts +95 -0
  1039. package/src/planner/nodes/create-index-node.ts +37 -0
  1040. package/src/planner/nodes/create-table-node.ts +31 -0
  1041. package/src/planner/nodes/create-view-node.ts +40 -0
  1042. package/src/planner/nodes/cte-node.ts +111 -0
  1043. package/src/planner/nodes/cte-reference-node.ts +89 -0
  1044. package/src/planner/nodes/delete-node.ts +72 -0
  1045. package/src/planner/nodes/distinct-node.ts +93 -0
  1046. package/src/planner/nodes/dml-executor-node.ts +98 -0
  1047. package/src/planner/nodes/drop-table-node.ts +31 -0
  1048. package/src/planner/nodes/drop-view-node.ts +33 -0
  1049. package/src/planner/nodes/filter.ts +91 -0
  1050. package/src/planner/nodes/function.ts +93 -0
  1051. package/src/planner/nodes/insert-node.ts +97 -0
  1052. package/src/planner/nodes/join-node.ts +213 -0
  1053. package/src/planner/nodes/limit-offset.ts +125 -0
  1054. package/src/planner/nodes/physical-access-nodes.ts +298 -0
  1055. package/src/planner/nodes/plan-node-type.ts +87 -0
  1056. package/src/planner/nodes/plan-node.ts +466 -0
  1057. package/src/planner/nodes/pragma.ts +94 -0
  1058. package/src/planner/nodes/project-node.ts +223 -0
  1059. package/src/planner/nodes/recursive-cte-node.ts +130 -0
  1060. package/src/planner/nodes/reference.ts +310 -0
  1061. package/src/planner/nodes/returning-node.ts +215 -0
  1062. package/src/planner/nodes/scalar.ts +736 -0
  1063. package/src/planner/nodes/scan.ts +103 -0
  1064. package/src/planner/nodes/sequencing-node.ts +113 -0
  1065. package/src/planner/nodes/set-operation-node.ts +87 -0
  1066. package/src/planner/nodes/single-row.ts +80 -0
  1067. package/src/planner/nodes/sink-node.ts +61 -0
  1068. package/src/planner/nodes/sort.ts +137 -0
  1069. package/src/planner/nodes/stream-aggregate.ts +225 -0
  1070. package/src/planner/nodes/subquery.ts +207 -0
  1071. package/src/planner/nodes/table-function-call.ts +127 -0
  1072. package/src/planner/nodes/transaction-node.ts +61 -0
  1073. package/src/planner/nodes/update-node.ts +114 -0
  1074. package/src/planner/nodes/values-node.ts +244 -0
  1075. package/src/planner/nodes/view-reference-node.ts +97 -0
  1076. package/src/planner/nodes/window-function.ts +73 -0
  1077. package/src/planner/nodes/window-node.ts +193 -0
  1078. package/src/planner/optimizer-tuning.ts +87 -0
  1079. package/src/planner/optimizer.ts +263 -0
  1080. package/src/planner/planning-context.ts +168 -0
  1081. package/src/planner/resolve.ts +100 -0
  1082. package/src/planner/rules/README.md +96 -0
  1083. package/src/planner/rules/access/rule-select-access-path.ts +180 -0
  1084. package/src/planner/rules/aggregate/rule-aggregate-streaming.ts +76 -0
  1085. package/src/planner/rules/cache/rule-cte-optimization.ts +66 -0
  1086. package/src/planner/rules/cache/rule-materialization-advisory.ts +66 -0
  1087. package/src/planner/rules/cache/rule-mutating-subquery-cache.ts +110 -0
  1088. package/src/planner/rules/physical/rule-mark-physical.ts +37 -0
  1089. package/src/planner/scopes/aliased.ts +50 -0
  1090. package/src/planner/scopes/base.ts +27 -0
  1091. package/src/planner/scopes/empty.ts +22 -0
  1092. package/src/planner/scopes/global.ts +73 -0
  1093. package/src/planner/scopes/multi.ts +41 -0
  1094. package/src/planner/scopes/param.ts +96 -0
  1095. package/src/planner/scopes/registered.ts +78 -0
  1096. package/src/planner/scopes/scope.ts +28 -0
  1097. package/src/planner/stats/basic-estimates.ts +107 -0
  1098. package/src/planner/stats/index.ts +223 -0
  1099. package/src/planner/type-utils.ts +95 -0
  1100. package/src/planner/validation/plan-validator.ts +340 -0
  1101. package/src/runtime/async-util.ts +282 -0
  1102. package/src/runtime/cache/shared-cache.ts +169 -0
  1103. package/src/runtime/emission-context.ts +310 -0
  1104. package/src/runtime/emit/add-constraint.ts +54 -0
  1105. package/src/runtime/emit/aggregate.ts +533 -0
  1106. package/src/runtime/emit/array-index.ts +25 -0
  1107. package/src/runtime/emit/binary.ts +335 -0
  1108. package/src/runtime/emit/block.ts +23 -0
  1109. package/src/runtime/emit/cache.ts +64 -0
  1110. package/src/runtime/emit/case.ts +87 -0
  1111. package/src/runtime/emit/cast.ts +151 -0
  1112. package/src/runtime/emit/collate.ts +9 -0
  1113. package/src/runtime/emit/column-reference.ts +50 -0
  1114. package/src/runtime/emit/constraint-check.ts +285 -0
  1115. package/src/runtime/emit/create-index.ts +15 -0
  1116. package/src/runtime/emit/create-table.ts +15 -0
  1117. package/src/runtime/emit/create-view.ts +52 -0
  1118. package/src/runtime/emit/cte-reference.ts +75 -0
  1119. package/src/runtime/emit/cte.ts +39 -0
  1120. package/src/runtime/emit/delete.ts +24 -0
  1121. package/src/runtime/emit/distinct.ts +45 -0
  1122. package/src/runtime/emit/dml-executor.ts +94 -0
  1123. package/src/runtime/emit/drop-table.ts +27 -0
  1124. package/src/runtime/emit/drop-view.ts +49 -0
  1125. package/src/runtime/emit/filter.ts +37 -0
  1126. package/src/runtime/emit/insert.ts +54 -0
  1127. package/src/runtime/emit/join.ts +145 -0
  1128. package/src/runtime/emit/limit-offset.ts +73 -0
  1129. package/src/runtime/emit/literal.ts +17 -0
  1130. package/src/runtime/emit/parameter.ts +59 -0
  1131. package/src/runtime/emit/pragma.ts +56 -0
  1132. package/src/runtime/emit/project.ts +40 -0
  1133. package/src/runtime/emit/recursive-cte.ts +120 -0
  1134. package/src/runtime/emit/returning.ts +48 -0
  1135. package/src/runtime/emit/scalar-function.ts +43 -0
  1136. package/src/runtime/emit/scan.ts +88 -0
  1137. package/src/runtime/emit/sequencing.ts +24 -0
  1138. package/src/runtime/emit/set-operation.ts +111 -0
  1139. package/src/runtime/emit/sink.ts +27 -0
  1140. package/src/runtime/emit/sort.ts +78 -0
  1141. package/src/runtime/emit/subquery.ts +143 -0
  1142. package/src/runtime/emit/table-reference.ts +92 -0
  1143. package/src/runtime/emit/table-valued-function.ts +119 -0
  1144. package/src/runtime/emit/transaction.ts +167 -0
  1145. package/src/runtime/emit/unary.ts +85 -0
  1146. package/src/runtime/emit/update.ts +73 -0
  1147. package/src/runtime/emit/values.ts +66 -0
  1148. package/src/runtime/emit/window-function.ts +42 -0
  1149. package/src/runtime/emit/window.ts +472 -0
  1150. package/src/runtime/emitters.ts +130 -0
  1151. package/src/runtime/register.ts +134 -0
  1152. package/src/runtime/scheduler.ts +488 -0
  1153. package/src/runtime/types.ts +191 -0
  1154. package/src/runtime/utils.ts +136 -0
  1155. package/src/schema/change-events.ts +80 -0
  1156. package/src/schema/column.ts +45 -0
  1157. package/src/schema/function.ts +139 -0
  1158. package/src/schema/manager.ts +694 -0
  1159. package/src/schema/schema.ts +199 -0
  1160. package/src/schema/table.ts +364 -0
  1161. package/src/schema/view.ts +19 -0
  1162. package/src/schema/window-function.ts +54 -0
  1163. package/src/util/affinity.ts +151 -0
  1164. package/src/util/ast-stringify.ts +764 -0
  1165. package/src/util/cached.ts +25 -0
  1166. package/src/util/coercion.ts +113 -0
  1167. package/src/util/comparison.ts +437 -0
  1168. package/src/util/environment.ts +52 -0
  1169. package/src/util/latches.ts +47 -0
  1170. package/src/util/patterns.ts +56 -0
  1171. package/src/util/plan-formatter.ts +51 -0
  1172. package/src/util/plugin-loader.ts +69 -0
  1173. package/src/util/row-descriptor.ts +105 -0
  1174. package/src/util/serialization.ts +45 -0
  1175. package/src/util/working-table-iterable.ts +30 -0
  1176. package/src/vtab/best-access-plan.ts +270 -0
  1177. package/src/vtab/connection.ts +36 -0
  1178. package/src/vtab/filter-info.ts +23 -0
  1179. package/src/vtab/index-info.ts +84 -0
  1180. package/src/vtab/manifest.ts +37 -0
  1181. package/src/vtab/memory/connection.ts +73 -0
  1182. package/src/vtab/memory/index.ts +178 -0
  1183. package/src/vtab/memory/layer/base-cursor.ts +124 -0
  1184. package/src/vtab/memory/layer/base.ts +273 -0
  1185. package/src/vtab/memory/layer/connection.ts +203 -0
  1186. package/src/vtab/memory/layer/interface.ts +47 -0
  1187. package/src/vtab/memory/layer/manager.ts +861 -0
  1188. package/src/vtab/memory/layer/safe-iterate.ts +49 -0
  1189. package/src/vtab/memory/layer/scan-plan.ts +84 -0
  1190. package/src/vtab/memory/layer/transaction-cursor.ts +162 -0
  1191. package/src/vtab/memory/layer/transaction.ts +229 -0
  1192. package/src/vtab/memory/module.ts +673 -0
  1193. package/src/vtab/memory/table.ts +253 -0
  1194. package/src/vtab/memory/types.ts +23 -0
  1195. package/src/vtab/memory/utils/logging.ts +33 -0
  1196. package/src/vtab/memory/utils/primary-key.ts +158 -0
  1197. package/src/vtab/module.ts +140 -0
  1198. package/src/vtab/table.ts +143 -0
@@ -0,0 +1,2783 @@
1
+ import { createLogger } from '../common/logger.js'; // Import logger
2
+ import { Lexer, type Token, TokenType } from './lexer.js';
3
+ import * as AST from './ast.js';
4
+ import { ConflictResolution } from '../common/constants.js';
5
+ import type { SqlValue } from '../common/types.js';
6
+ import { quereusError } from '../common/errors.js';
7
+ import { StatusCode } from '../common/types.js';
8
+ import { getSyncLiteral } from './utils.js';
9
+
10
+ const log = createLogger('parser:parser'); // Create logger instance
11
+ const errorLog = log.extend('error');
12
+
13
+ export class ParseError extends Error {
14
+ token: Token;
15
+
16
+ constructor(token: Token, message: string) {
17
+ super(message);
18
+ this.token = token;
19
+ this.name = 'ParseError';
20
+ }
21
+ }
22
+
23
+ // Helper function to create the location object
24
+ function _createLoc(startToken: Token, endToken: Token): AST.AstNode['loc'] {
25
+ return {
26
+ start: {
27
+ line: startToken.startLine,
28
+ column: startToken.startColumn,
29
+ offset: startToken.startOffset,
30
+ },
31
+ end: {
32
+ line: endToken.endLine,
33
+ column: endToken.endColumn,
34
+ offset: endToken.endOffset,
35
+ },
36
+ };
37
+ }
38
+
39
+ export class Parser {
40
+ private tokens: Token[] = [];
41
+ private current = 0;
42
+ // Counter for positional parameters
43
+ private parameterPosition = 1;
44
+
45
+ /**
46
+ * Initialize the parser with tokens from a SQL string
47
+ * @param sql SQL string to parse
48
+ * @returns this parser instance for chaining
49
+ */
50
+ initialize(sql: string): Parser {
51
+ const lexer = new Lexer(sql);
52
+ this.tokens = lexer.scanTokens();
53
+ this.current = 0;
54
+ this.parameterPosition = 1; // Reset parameter counter
55
+
56
+ // Check for errors from lexer
57
+ const errorToken = this.tokens.find(t => t.type === TokenType.ERROR);
58
+ if (errorToken) {
59
+ quereusError(
60
+ `Lexer error: ${errorToken.lexeme}`,
61
+ StatusCode.ERROR,
62
+ undefined,
63
+ {
64
+ loc: {
65
+ start: {
66
+ line: errorToken.startLine,
67
+ column: errorToken.startColumn,
68
+ },
69
+ end: {
70
+ line: errorToken.endLine,
71
+ column: errorToken.endColumn,
72
+ }
73
+ }
74
+ }
75
+ );
76
+ }
77
+
78
+ return this;
79
+ }
80
+
81
+ /**
82
+ * Parse SQL text into an array of ASTs
83
+ */
84
+ parseAll(sql: string): AST.Statement[] {
85
+ this.initialize(sql);
86
+ const statements: AST.Statement[] = [];
87
+
88
+ while (!this.isAtEnd()) {
89
+ try {
90
+ const stmt = this.statement();
91
+ statements.push(stmt as AST.Statement); // Cast needed as statement() returns AstNode
92
+
93
+ // Consume optional semicolon at the end of the statement
94
+ this.match(TokenType.SEMICOLON);
95
+
96
+ } catch (e) {
97
+ // error() method now throws QuereusError directly with location info
98
+ if (e instanceof Error && e.name === 'QuereusError') {
99
+ throw e;
100
+ }
101
+
102
+ // Handle unexpected non-QuereusError exceptions
103
+ errorLog("Unhandled parser error: %O", e);
104
+ quereusError(
105
+ `Parser error: ${e instanceof Error ? e.message : e}`,
106
+ StatusCode.ERROR,
107
+ e instanceof Error ? e : undefined
108
+ );
109
+ }
110
+ }
111
+
112
+ // If we consumed all tokens and didn't parse any statements (e.g., empty input or only comments/whitespace),
113
+ // return an empty array instead of throwing an error.
114
+ return statements;
115
+ }
116
+
117
+ /**
118
+ * Parse SQL text into a single AST node.
119
+ * Use parseAll instead for potentially multi-statement strings.
120
+ * Throws error if more than one statement is found after the first.
121
+ */
122
+ parse(sql: string): AST.Statement {
123
+ const statements = this.parseAll(sql);
124
+ if (statements.length === 0) {
125
+ // Handle case of empty input or input with only comments/whitespace
126
+ // Depending on desired behavior, could return null, undefined, or throw.
127
+ // Throwing seems reasonable as prepare/eval expect a statement.
128
+ quereusError("No SQL statement found to parse.", StatusCode.ERROR);
129
+ }
130
+ if (statements.length > 1) {
131
+ // Find the token that starts the second statement for better error location
132
+ const secondStatementStartToken = statements[1]?.loc?.start;
133
+ const errToken = this.tokens.find(t => t.startOffset === secondStatementStartToken?.offset) ?? this.peek();
134
+ this.error(errToken, "Provided SQL string contains multiple statements. Use exec() for multi-statement execution.");
135
+ }
136
+ return statements[0];
137
+ }
138
+
139
+ /**
140
+ * Attempts to parse a WITH clause if present.
141
+ * @returns The WithClause AST node or undefined if no WITH clause is found.
142
+ */
143
+ private tryParseWithClause(): AST.WithClause | undefined {
144
+ if (!this.check(TokenType.WITH)) {
145
+ return undefined;
146
+ }
147
+ const startToken = this.advance(); // Consume WITH
148
+
149
+ const recursive = this.match(TokenType.RECURSIVE);
150
+
151
+ const ctes: AST.CommonTableExpr[] = [];
152
+ do {
153
+ ctes.push(this.commonTableExpression());
154
+ } while (this.match(TokenType.COMMA));
155
+
156
+ // Parse optional OPTION clause
157
+ let options: AST.WithClauseOptions | undefined;
158
+ if (this.matchKeyword('OPTION')) {
159
+ this.consume(TokenType.LPAREN, "Expected '(' after OPTION.");
160
+
161
+ // Parse MAXRECURSION option
162
+ if (this.matchKeyword('MAXRECURSION')) {
163
+ if (!this.check(TokenType.INTEGER)) {
164
+ this.error(this.peek(), "Expected integer value after MAXRECURSION.");
165
+ }
166
+ const maxRecursionToken = this.advance();
167
+ const maxRecursion = maxRecursionToken.literal as number;
168
+
169
+ if (maxRecursion < 0) {
170
+ this.error(maxRecursionToken, "MAXRECURSION value must be non-negative.");
171
+ }
172
+
173
+ options = { maxRecursion };
174
+ } else {
175
+ throw this.error(this.peek(), "Expected MAXRECURSION in OPTION clause.");
176
+ }
177
+
178
+ this.consume(TokenType.RPAREN, "Expected ')' after OPTION clause.");
179
+ }
180
+
181
+ const endToken = this.previous(); // Last token of the WITH clause
182
+
183
+ return { type: 'with', recursive, ctes, options, loc: _createLoc(startToken, endToken) };
184
+ }
185
+
186
+ /**
187
+ * Parses a single Common Table Expression (CTE).
188
+ * cte_name [(col1, col2, ...)] AS (query)
189
+ */
190
+ private commonTableExpression(): AST.CommonTableExpr {
191
+ const startToken = this.peek(); // Peek before consuming name
192
+ const name = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'like'], "Expected CTE name.");
193
+ let endToken = this.previous(); // End token initially is the name
194
+
195
+ let columns: string[] | undefined;
196
+ if (this.match(TokenType.LPAREN)) {
197
+ columns = [];
198
+ if (!this.check(TokenType.RPAREN)) {
199
+ do {
200
+ columns.push(this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'like'], "Expected column name in CTE definition."));
201
+ } while (this.match(TokenType.COMMA));
202
+ }
203
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after CTE column list.");
204
+ }
205
+
206
+ this.consume(TokenType.AS, "Expected 'AS' after CTE name.");
207
+
208
+ let materializationHint: AST.CommonTableExpr['materializationHint'];
209
+ if (this.matchKeyword('MATERIALIZED')) {
210
+ materializationHint = 'materialized';
211
+ } else if (this.matchKeyword('NOT')) {
212
+ this.consumeKeyword('MATERIALIZED', "Expected 'MATERIALIZED' after 'NOT'.");
213
+ materializationHint = 'not_materialized';
214
+ }
215
+
216
+ this.consume(TokenType.LPAREN, "Expected '(' before CTE query.");
217
+
218
+ // Parse the CTE query (can be SELECT, VALUES (via SELECT), INSERT, UPDATE, DELETE)
219
+ const queryStartToken = this.peek();
220
+ let query: AST.SelectStmt | AST.InsertStmt | AST.UpdateStmt | AST.DeleteStmt;
221
+ if (this.check(TokenType.SELECT)) {
222
+ this.advance(); // Consume SELECT token
223
+ query = this.selectStatement(queryStartToken); // Pass start token
224
+ } else if (this.check(TokenType.INSERT)) {
225
+ this.advance(); // Consume INSERT token
226
+ query = this.insertStatement(queryStartToken);
227
+ } else if (this.check(TokenType.UPDATE)) {
228
+ this.advance(); // Consume UPDATE token
229
+ query = this.updateStatement(queryStartToken);
230
+ } else if (this.check(TokenType.DELETE)) {
231
+ this.advance(); // Consume DELETE token
232
+ query = this.deleteStatement(queryStartToken);
233
+ }
234
+ // TODO: Add support for VALUES directly if needed (though VALUES is usually part of SELECT)
235
+ else {
236
+ throw this.error(this.peek(), "Expected SELECT, INSERT, UPDATE, or DELETE statement for CTE query.");
237
+ }
238
+
239
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after CTE query."); // Capture ')' as end token
240
+
241
+ return { type: 'commonTableExpr', name, columns, query, materializationHint, loc: _createLoc(startToken, endToken) };
242
+ }
243
+
244
+ /**
245
+ * Parse a single SQL statement
246
+ */
247
+ private statement(): AST.AstNode {
248
+ // Check for WITH clause first
249
+ let withClause: AST.WithClause | undefined;
250
+ if (this.check(TokenType.WITH)) {
251
+ withClause = this.tryParseWithClause();
252
+ }
253
+
254
+ const startToken = this.peek();
255
+ // --- Check for specific keywords first ---
256
+ const currentKeyword = startToken.lexeme.toUpperCase();
257
+ let stmt: AST.AstNode;
258
+
259
+ switch (currentKeyword) {
260
+ case 'SELECT': this.advance(); stmt = this.selectStatement(startToken, withClause); break;
261
+ case 'INSERT': this.advance(); stmt = this.insertStatement(startToken, withClause); break;
262
+ case 'UPDATE': this.advance(); stmt = this.updateStatement(startToken, withClause); break;
263
+ case 'DELETE': this.advance(); stmt = this.deleteStatement(startToken, withClause); break;
264
+ case 'VALUES': this.advance(); stmt = this.valuesStatement(startToken); break;
265
+ case 'CREATE': this.advance(); stmt = this.createStatement(startToken, withClause); break;
266
+ case 'DROP': this.advance(); stmt = this.dropStatement(startToken, withClause); break;
267
+ case 'ALTER': this.advance(); stmt = this.alterTableStatement(startToken, withClause); break;
268
+ case 'BEGIN': this.advance(); stmt = this.beginStatement(startToken, withClause); break;
269
+ case 'COMMIT': this.advance(); stmt = this.commitStatement(startToken, withClause); break;
270
+ case 'ROLLBACK': this.advance(); stmt = this.rollbackStatement(startToken, withClause); break;
271
+ case 'SAVEPOINT': this.advance(); stmt = this.savepointStatement(startToken, withClause); break;
272
+ case 'RELEASE': this.advance(); stmt = this.releaseStatement(startToken, withClause); break;
273
+ // TODO: Replace pragmas with build-in functions
274
+ case 'PRAGMA': this.advance(); stmt = this.pragmaStatement(startToken, withClause); break;
275
+ // --- Add default case ---
276
+ default:
277
+ // If it wasn't a recognized keyword starting the statement
278
+ throw this.error(startToken, `Expected statement type (SELECT, INSERT, UPDATE, DELETE, VALUES, CREATE, etc.), got '${startToken.lexeme}'.`);
279
+ }
280
+
281
+ // Attach WITH clause if present and supported
282
+ if (withClause && this.statementSupportsWithClause(stmt)) {
283
+ (stmt as any).withClause = withClause;
284
+ if (withClause.loc && stmt.loc) {
285
+ stmt.loc.start = withClause.loc.start;
286
+ }
287
+ } else if (withClause) {
288
+ throw this.error(this.previous(), `WITH clause cannot be used with ${stmt.type} statement.`);
289
+ }
290
+
291
+ return stmt;
292
+ }
293
+
294
+ /**
295
+ * Parse an INSERT statement
296
+ * @returns AST for the INSERT statement
297
+ */
298
+ insertStatement(startToken: Token, withClause?: AST.WithClause): AST.InsertStmt {
299
+ // INTO keyword is optional in SQLite
300
+ this.matchKeyword('INTO'); // Handle missing keyword gracefully
301
+
302
+ // Parse the table reference
303
+ const table = this.tableIdentifier();
304
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
305
+
306
+ // Parse column list if provided
307
+ let columns: string[] | undefined;
308
+ if (this.match(TokenType.LPAREN)) {
309
+ columns = [];
310
+ do {
311
+ if (!this.checkIdentifierLike(contextualKeywords)) {
312
+ throw this.error(this.peek(), "Expected column name.");
313
+ }
314
+ columns.push(this.advance().lexeme);
315
+ } while (this.match(TokenType.COMMA));
316
+
317
+ this.consume(TokenType.RPAREN, "Expected ')' after column list.");
318
+ }
319
+
320
+ // Parse VALUES clause
321
+ let values: AST.Expression[][] | undefined;
322
+ let select: AST.SelectStmt | undefined;
323
+ let lastConsumedToken = this.previous(); // After columns or table id
324
+
325
+ if (this.match(TokenType.VALUES)) {
326
+ values = [];
327
+ do {
328
+ this.consume(TokenType.LPAREN, "Expected '(' before values.");
329
+ const valueList: AST.Expression[] = [];
330
+
331
+ if (!this.check(TokenType.RPAREN)) { // Check for empty value list
332
+ do {
333
+ valueList.push(this.expression());
334
+ } while (this.match(TokenType.COMMA));
335
+ }
336
+
337
+ this.consume(TokenType.RPAREN, "Expected ')' after values.");
338
+ values.push(valueList);
339
+ lastConsumedToken = this.previous(); // Update after closing paren of value list
340
+ } while (this.match(TokenType.COMMA));
341
+ } else if (this.check(TokenType.SELECT)) { // If current token is SELECT
342
+ // Handle INSERT ... SELECT
343
+ // Consume the SELECT token, as selectStatement expects to start parsing after it.
344
+ // selectKeywordToken will be the actual 'SELECT' token object, used for location.
345
+ const selectKeywordToken = this.advance(); // Consume 'SELECT'
346
+ // Pass the withClause so the embedded SELECT can (via the planner) resolve CTEs defined for the INSERT.
347
+ select = this.selectStatement(selectKeywordToken, withClause);
348
+ lastConsumedToken = this.previous(); // After SELECT statement is parsed
349
+ } else {
350
+ throw this.error(this.peek(), "Expected VALUES or SELECT after INSERT.");
351
+ }
352
+
353
+ // Parse RETURNING clause if present
354
+ let returning: AST.ResultColumn[] | undefined;
355
+ if (this.matchKeyword('RETURNING')) {
356
+ returning = this.columnList();
357
+ lastConsumedToken = this.previous(); // Update after RETURNING clause
358
+ }
359
+
360
+ return {
361
+ type: 'insert',
362
+ table,
363
+ columns,
364
+ values,
365
+ select,
366
+ returning,
367
+ loc: _createLoc(startToken, lastConsumedToken),
368
+ };
369
+ }
370
+
371
+ /**
372
+ * Parse a SELECT statement
373
+ * @param startToken The 'SELECT' token or start token of a sub-query
374
+ * @param withClause The WITH clause context for CTE access
375
+ * @param isCompoundSubquery If true, don't parse ORDER BY/LIMIT as they belong to the outer compound
376
+ * @returns AST for the SELECT statement
377
+ */
378
+ selectStatement(startToken?: Token, withClause?: AST.WithClause, isCompoundSubquery: boolean = false): AST.SelectStmt {
379
+ const start = startToken ?? this.previous(); // Use provided or the keyword token
380
+ let lastConsumedToken = start; // Initialize lastConsumed
381
+
382
+ const distinct = this.matchKeyword('DISTINCT');
383
+ if (distinct) lastConsumedToken = this.previous();
384
+ const all = !distinct && this.matchKeyword('ALL');
385
+ if (all) lastConsumedToken = this.previous();
386
+
387
+ // Parse column list
388
+ const columns = this.columnList();
389
+ if (columns.length > 0) lastConsumedToken = this.previous(); // Update after last column element
390
+
391
+ // Parse FROM clause if present
392
+ let from: AST.FromClause[] | undefined;
393
+ if (this.match(TokenType.FROM)) {
394
+ from = this.tableSourceList(withClause);
395
+ if (from.length > 0) lastConsumedToken = this.previous(); // After last source/join
396
+ }
397
+
398
+ // Parse WHERE clause if present
399
+ let where: AST.Expression | undefined;
400
+ if (this.match(TokenType.WHERE)) {
401
+ where = this.expression();
402
+ lastConsumedToken = this.previous(); // After where expression
403
+ }
404
+
405
+ // Parse GROUP BY clause if present
406
+ let groupBy: AST.Expression[] | undefined;
407
+ if (this.match(TokenType.GROUP) && this.consume(TokenType.BY, "Expected 'BY' after 'GROUP'.")) {
408
+ groupBy = [];
409
+ do {
410
+ groupBy.push(this.expression());
411
+ } while (this.match(TokenType.COMMA));
412
+ lastConsumedToken = this.previous(); // After last group by expression
413
+ }
414
+
415
+ // Parse HAVING clause if present
416
+ let having: AST.Expression | undefined;
417
+ if (this.match(TokenType.HAVING)) {
418
+ having = this.expression();
419
+ lastConsumedToken = this.previous(); // After having expression
420
+ }
421
+
422
+ // Check for compound set operations (UNION / INTERSECT / EXCEPT) BEFORE ORDER BY/LIMIT
423
+ let compound: { op: 'union' | 'unionAll' | 'intersect' | 'except'; select: AST.SelectStmt } | undefined;
424
+ if (this.match(TokenType.UNION, TokenType.INTERSECT, TokenType.EXCEPT)) {
425
+ const tok = this.previous();
426
+ let op: 'union' | 'unionAll' | 'intersect' | 'except';
427
+ if (tok.type === TokenType.UNION) {
428
+ if (this.match(TokenType.ALL)) {
429
+ op = 'unionAll';
430
+ } else {
431
+ op = 'union';
432
+ }
433
+ } else if (tok.type === TokenType.INTERSECT) {
434
+ op = 'intersect';
435
+ } else {
436
+ op = 'except';
437
+ }
438
+
439
+ let rightSelect: AST.SelectStmt;
440
+
441
+ // Handle parenthesized subquery after set operation
442
+ if (this.match(TokenType.LPAREN)) {
443
+ const selectToken = this.consume(TokenType.SELECT, "Expected 'SELECT' in parenthesized set operation.");
444
+ rightSelect = this.selectStatement(selectToken, withClause, true); // Pass true to indicate compound subquery
445
+ this.consume(TokenType.RPAREN, "Expected ')' after parenthesized set operation.");
446
+ } else {
447
+ // Handle direct SELECT statement
448
+ const selectStartToken = this.peek();
449
+ if (this.match(TokenType.SELECT)) {
450
+ rightSelect = this.selectStatement(selectStartToken, withClause, true); // Pass true to indicate compound subquery
451
+ } else {
452
+ throw this.error(this.peek(), "Expected 'SELECT' or '(' after set operation keyword.");
453
+ }
454
+ }
455
+
456
+ lastConsumedToken = this.previous();
457
+ compound = { op, select: rightSelect };
458
+ }
459
+
460
+ // Parse ORDER BY clause if present (applies to final result after compound operations)
461
+ // Skip if this is a compound subquery as ORDER BY belongs to the outer compound
462
+ let orderBy: AST.OrderByClause[] | undefined;
463
+ if (!isCompoundSubquery && this.match(TokenType.ORDER) && this.consume(TokenType.BY, "Expected 'BY' after 'ORDER'.")) {
464
+ orderBy = [];
465
+ do {
466
+ const expr = this.expression();
467
+ const direction = this.match(TokenType.DESC) ? 'desc' :
468
+ (this.match(TokenType.ASC) ? 'asc' : 'asc'); // Default to ASC
469
+ orderBy.push({ expr, direction });
470
+ } while (this.match(TokenType.COMMA));
471
+ lastConsumedToken = this.previous(); // After last order by clause
472
+ }
473
+
474
+ // Parse LIMIT clause if present (applies to final result after compound operations)
475
+ // Skip if this is a compound subquery as LIMIT belongs to the outer compound
476
+ let limit: AST.Expression | undefined;
477
+ let offset: AST.Expression | undefined;
478
+ if (!isCompoundSubquery && this.match(TokenType.LIMIT)) {
479
+ limit = this.expression();
480
+ lastConsumedToken = this.previous(); // After limit expression
481
+
482
+ // LIMIT x OFFSET y syntax
483
+ if (this.match(TokenType.OFFSET)) {
484
+ offset = this.expression();
485
+ lastConsumedToken = this.previous(); // After offset expression
486
+ }
487
+ // LIMIT x, y syntax (x is offset, y is limit)
488
+ else if (this.match(TokenType.COMMA)) {
489
+ offset = limit;
490
+ limit = this.expression();
491
+ lastConsumedToken = this.previous(); // After second limit expression
492
+ }
493
+ }
494
+
495
+ return {
496
+ type: 'select',
497
+ columns,
498
+ from,
499
+ where,
500
+ groupBy,
501
+ having,
502
+ orderBy,
503
+ limit,
504
+ offset,
505
+ distinct,
506
+ all,
507
+ compound,
508
+ loc: _createLoc(start, lastConsumedToken),
509
+ };
510
+ }
511
+
512
+ /**
513
+ * Parse a comma-separated list of result columns for SELECT
514
+ */
515
+ private columnList(): AST.ResultColumn[] {
516
+ const columns: AST.ResultColumn[] = [];
517
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
518
+
519
+ do {
520
+ log(`columnList: Loop start. Current token: ${this.peek().lexeme} (${this.peek().type})`); // DEBUG
521
+ // Handle wildcard: * or table.*
522
+ if (this.match(TokenType.ASTERISK)) {
523
+ columns.push({ type: 'all' });
524
+ }
525
+ // Handle table.* syntax
526
+ else if (this.checkIdentifierLike(contextualKeywords) && this.checkNext(1, TokenType.DOT) &&
527
+ this.checkNext(2, TokenType.ASTERISK)) {
528
+ const table = this.consumeIdentifier(contextualKeywords, "Expected table name before '.*'.");
529
+ this.advance(); // consume DOT
530
+ this.advance(); // consume ASTERISK
531
+ columns.push({ type: 'all', table });
532
+ }
533
+ // Handle regular column expression
534
+ else {
535
+ log(`columnList: Parsing expression...`); // DEBUG
536
+ const expr = this.expression();
537
+ log(`columnList: Parsed expression. Current token: ${this.peek().lexeme} (${this.peek().type})`); // DEBUG
538
+ let alias: string | undefined;
539
+
540
+ // Handle AS alias or just alias
541
+ if (this.match(TokenType.AS)) {
542
+ if (this.checkIdentifierLike(contextualKeywords) || this.check(TokenType.STRING)) {
543
+ const aliasToken = this.advance();
544
+ alias = aliasToken.lexeme;
545
+ if (aliasToken.type === TokenType.STRING) {
546
+ alias = aliasToken.literal;
547
+ }
548
+ } else {
549
+ throw this.error(this.peek(), "Expected identifier or string after 'AS'.");
550
+ }
551
+ }
552
+ // Implicit alias (no AS keyword)
553
+ else if (this.checkIdentifierLike([]) &&
554
+ !this.checkNext(1, TokenType.LPAREN) &&
555
+ !this.checkNext(1, TokenType.DOT) &&
556
+ !this.checkNext(1, TokenType.COMMA) &&
557
+ !this.isEndOfClause()) {
558
+ const aliasToken = this.advance();
559
+ alias = aliasToken.lexeme;
560
+ }
561
+
562
+ columns.push({ type: 'column', expr, alias });
563
+ }
564
+ log(`columnList: Checking for comma. Current token: ${this.peek().lexeme} (${this.peek().type})`); // DEBUG
565
+ } while (this.match(TokenType.COMMA));
566
+
567
+ log(`columnList: Loop ended. Current token: ${this.peek().lexeme} (${this.peek().type})`); // DEBUG
568
+ return columns;
569
+ }
570
+
571
+ /**
572
+ * Parse a table identifier (possibly schema-qualified)
573
+ */
574
+ private tableIdentifier(): AST.IdentifierExpr {
575
+ const startToken = this.peek();
576
+ let schema: string | undefined;
577
+ let name: string;
578
+ let endToken = startToken;
579
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
580
+
581
+ // Check for schema.table pattern
582
+ if (this.checkIdentifierLike(contextualKeywords) && this.checkNext(1, TokenType.DOT)) {
583
+ schema = this.consumeIdentifier(contextualKeywords, "Expected schema name.");
584
+ this.advance(); // Consume DOT
585
+ name = this.consumeIdentifier(contextualKeywords, "Expected table name after schema.");
586
+ endToken = this.previous();
587
+ } else if (this.checkIdentifierLike(contextualKeywords)) {
588
+ name = this.consumeIdentifier(contextualKeywords, "Expected table name.");
589
+ endToken = this.previous();
590
+ } else {
591
+ throw this.error(this.peek(), "Expected table name.");
592
+ }
593
+
594
+ return {
595
+ type: 'identifier',
596
+ name,
597
+ schema,
598
+ loc: _createLoc(startToken, endToken),
599
+ };
600
+ }
601
+
602
+ /**
603
+ * Parse a comma-separated list of table sources (FROM clause)
604
+ */
605
+ private tableSourceList(withClause?: AST.WithClause): AST.FromClause[] {
606
+ const sources: AST.FromClause[] = [];
607
+
608
+ do {
609
+ // Get the base table source
610
+ let source: AST.FromClause = this.tableSource(withClause);
611
+
612
+ // Look for JOINs
613
+ while (this.isJoinToken()) {
614
+ source = this.joinClause(source, withClause);
615
+ }
616
+
617
+ sources.push(source);
618
+ } while (this.match(TokenType.COMMA));
619
+
620
+ return sources;
621
+ }
622
+
623
+ /**
624
+ * Parse a single table source, which can now be a table name, table-valued function call, or subquery
625
+ */
626
+ private tableSource(withClause?: AST.WithClause): AST.FromClause {
627
+ const startToken = this.peek();
628
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
629
+
630
+ // Check for subquery: ( SELECT ... or ( VALUES ... or ( INSERT/UPDATE/DELETE ...
631
+ if (this.check(TokenType.LPAREN)) {
632
+ // Look ahead to see if this is a subquery
633
+ const lookahead = this.current + 1;
634
+ if (lookahead < this.tokens.length) {
635
+ const nextTokenType = this.tokens[lookahead].type;
636
+ if (nextTokenType === TokenType.SELECT || nextTokenType === TokenType.VALUES) {
637
+ return this.subquerySource(startToken, withClause);
638
+ } else if (nextTokenType === TokenType.INSERT || nextTokenType === TokenType.UPDATE || nextTokenType === TokenType.DELETE) {
639
+ return this.mutatingSubquerySource(startToken, withClause);
640
+ }
641
+ }
642
+ }
643
+
644
+ // Check for function call syntax: IDENTIFIER (
645
+ if (this.checkIdentifierLike(contextualKeywords) && this.checkNext(1, TokenType.LPAREN)) {
646
+ return this.functionSource(startToken);
647
+ }
648
+ // Otherwise, assume it's a standard table source
649
+ else {
650
+ return this.standardTableSource(startToken);
651
+ }
652
+ }
653
+
654
+ /** Parses a subquery source: (SELECT ...) AS alias */
655
+ private subquerySource(startToken: Token, withClause?: AST.WithClause): AST.SubquerySource {
656
+ this.consume(TokenType.LPAREN, "Expected '(' before subquery.");
657
+
658
+ let subquery: AST.SelectStmt | AST.ValuesStmt;
659
+
660
+ if (this.check(TokenType.SELECT)) {
661
+ // Consume the SELECT token and pass it as startToken to selectStatement
662
+ const selectToken = this.advance();
663
+ subquery = this.selectStatement(selectToken, withClause);
664
+ } else if (this.check(TokenType.VALUES)) {
665
+ // Handle VALUES subquery
666
+ const valuesToken = this.advance();
667
+ subquery = this.valuesStatement(valuesToken);
668
+ } else {
669
+ throw this.error(this.peek(), "Expected 'SELECT' or 'VALUES' in subquery.");
670
+ }
671
+
672
+ this.consume(TokenType.RPAREN, "Expected ')' after subquery.");
673
+
674
+ // Parse optional alias for subquery
675
+ let alias: string;
676
+ let columns: string[] | undefined;
677
+
678
+ if (this.match(TokenType.AS)) {
679
+ if (!this.checkIdentifierLike([])) {
680
+ throw this.error(this.peek(), "Expected alias after 'AS'.");
681
+ }
682
+ const aliasToken = this.advance();
683
+ alias = aliasToken.lexeme;
684
+ } else if (this.checkIdentifierLike([]) &&
685
+ !this.checkNext(1, TokenType.DOT) &&
686
+ !this.checkNext(1, TokenType.COMMA) &&
687
+ !this.isJoinToken() &&
688
+ !this.isEndOfClause()) {
689
+ const aliasToken = this.advance();
690
+ alias = aliasToken.lexeme;
691
+ } else {
692
+ // Generate a default alias if none provided
693
+ alias = `subquery_${startToken.startOffset}`;
694
+ }
695
+
696
+ // Parse optional column list after alias: AS alias(col1, col2, ...)
697
+ if (this.match(TokenType.LPAREN)) {
698
+ columns = [];
699
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
700
+
701
+ if (!this.check(TokenType.RPAREN)) {
702
+ do {
703
+ columns.push(this.consumeIdentifier(contextualKeywords, "Expected column name in alias column list."));
704
+ } while (this.match(TokenType.COMMA));
705
+ }
706
+ this.consume(TokenType.RPAREN, "Expected ')' after alias column list.");
707
+ }
708
+
709
+ const endToken = this.previous();
710
+ return {
711
+ type: 'subquerySource',
712
+ subquery,
713
+ alias,
714
+ columns,
715
+ loc: _createLoc(startToken, endToken),
716
+ };
717
+ }
718
+
719
+ /** Parses a mutating subquery source: (INSERT/UPDATE/DELETE ... RETURNING ...) AS alias */
720
+ private mutatingSubquerySource(startToken: Token, withClause?: AST.WithClause): AST.MutatingSubquerySource {
721
+ this.consume(TokenType.LPAREN, "Expected '(' before mutating subquery.");
722
+
723
+ let stmt: AST.InsertStmt | AST.UpdateStmt | AST.DeleteStmt;
724
+
725
+ if (this.check(TokenType.INSERT)) {
726
+ const insertToken = this.advance();
727
+ stmt = this.insertStatement(insertToken, withClause);
728
+ } else if (this.check(TokenType.UPDATE)) {
729
+ const updateToken = this.advance();
730
+ stmt = this.updateStatement(updateToken, withClause);
731
+ } else if (this.check(TokenType.DELETE)) {
732
+ const deleteToken = this.advance();
733
+ stmt = this.deleteStatement(deleteToken, withClause);
734
+ } else {
735
+ throw this.error(this.peek(), "Expected 'INSERT', 'UPDATE', or 'DELETE' in mutating subquery.");
736
+ }
737
+
738
+ // Validate that the statement has a RETURNING clause
739
+ if (!stmt.returning || stmt.returning.length === 0) {
740
+ throw this.error(this.previous(), "Mutating subqueries must have a RETURNING clause to be used as table sources.");
741
+ }
742
+
743
+ this.consume(TokenType.RPAREN, "Expected ')' after mutating subquery.");
744
+
745
+ // Parse optional alias for mutating subquery
746
+ let alias: string;
747
+ let columns: string[] | undefined;
748
+
749
+ if (this.match(TokenType.AS)) {
750
+ if (!this.checkIdentifierLike([])) {
751
+ throw this.error(this.peek(), "Expected alias after 'AS'.");
752
+ }
753
+ const aliasToken = this.advance();
754
+ alias = aliasToken.lexeme;
755
+ } else if (this.checkIdentifierLike([]) &&
756
+ !this.checkNext(1, TokenType.DOT) &&
757
+ !this.checkNext(1, TokenType.COMMA) &&
758
+ !this.isJoinToken() &&
759
+ !this.isEndOfClause()) {
760
+ const aliasToken = this.advance();
761
+ alias = aliasToken.lexeme;
762
+ } else {
763
+ // Generate a default alias if none provided
764
+ alias = `mutating_subquery_${startToken.startOffset}`;
765
+ }
766
+
767
+ // Parse optional column list after alias: AS alias(col1, col2, ...)
768
+ if (this.match(TokenType.LPAREN)) {
769
+ columns = [];
770
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
771
+
772
+ if (!this.check(TokenType.RPAREN)) {
773
+ do {
774
+ columns.push(this.consumeIdentifier(contextualKeywords, "Expected column name in alias column list."));
775
+ } while (this.match(TokenType.COMMA));
776
+ }
777
+ this.consume(TokenType.RPAREN, "Expected ')' after alias column list.");
778
+ }
779
+
780
+ const endToken = this.previous();
781
+ return {
782
+ type: 'mutatingSubquerySource',
783
+ stmt,
784
+ alias,
785
+ columns,
786
+ loc: _createLoc(startToken, endToken),
787
+ };
788
+ }
789
+
790
+ /** Parses a standard table source (schema.table or table) */
791
+ private standardTableSource(startToken: Token): AST.TableSource {
792
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
793
+
794
+ // Parse table name (potentially schema-qualified)
795
+ const table = this.tableIdentifier();
796
+ let endToken = this.previous(); // Initialize endToken after parsing table identifier
797
+
798
+ // Parse optional alias
799
+ let alias: string | undefined;
800
+ if (this.match(TokenType.AS)) {
801
+ if (!this.checkIdentifierLike(contextualKeywords)) {
802
+ throw this.error(this.peek(), "Expected alias after 'AS'.");
803
+ }
804
+ const aliasToken = this.advance();
805
+ alias = aliasToken.lexeme;
806
+ endToken = aliasToken;
807
+ } else if (this.checkIdentifierLike([]) &&
808
+ !this.checkNext(1, TokenType.DOT) &&
809
+ !this.checkNext(1, TokenType.COMMA) &&
810
+ !this.isJoinToken() &&
811
+ !this.isEndOfClause()) {
812
+ const aliasToken = this.advance();
813
+ alias = aliasToken.lexeme;
814
+ endToken = aliasToken;
815
+ }
816
+
817
+ return {
818
+ type: 'table',
819
+ table,
820
+ alias,
821
+ loc: _createLoc(startToken, endToken),
822
+ };
823
+ }
824
+
825
+ /** Parses a table-valued function source: name(arg1, ...) [AS alias] */
826
+ private functionSource(startToken: Token): AST.FunctionSource {
827
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
828
+
829
+ const name = this.tableIdentifier(); // name has its own loc
830
+ let endToken = this.previous(); // Initialize endToken after parsing function identifier
831
+
832
+ this.consume(TokenType.LPAREN, "Expected '(' after table function name.");
833
+
834
+ const args: AST.Expression[] = [];
835
+ if (!this.check(TokenType.RPAREN)) {
836
+ // Handle DISTINCT inside function calls like COUNT(DISTINCT col)
837
+ const distinct = this.matchKeyword('DISTINCT');
838
+ // Handle * argument AFTER checking for distinct
839
+ if (this.match(TokenType.ASTERISK)) {
840
+ // Do not add '*' as an argument to the list for aggregates like COUNT(*)
841
+ if (args.length > 0 || distinct) {
842
+ // '*' is only valid as the *only* argument, potentially after DISTINCT
843
+ // e.g. COUNT(*), COUNT(DISTINCT *) - though DISTINCT * might not be standard SQL?
844
+ // For now, disallow '*' if other args exist.
845
+ throw this.error(this.previous(), "'*' cannot be used with other arguments in function call.");
846
+ }
847
+ // If we parsed '*', the args list remains empty.
848
+ } else {
849
+ // Parse regular arguments if '*' wasn't found
850
+ do {
851
+ args.push(this.expression());
852
+ } while (this.match(TokenType.COMMA));
853
+ }
854
+ }
855
+
856
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after table function arguments.");
857
+
858
+ // Parse optional alias (same logic as for standard tables)
859
+ let alias: string | undefined;
860
+ if (this.match(TokenType.AS)) {
861
+ if (!this.checkIdentifierLike(contextualKeywords)) {
862
+ throw this.error(this.peek(), "Expected alias after 'AS'.");
863
+ }
864
+ const aliasToken = this.advance();
865
+ alias = aliasToken.lexeme;
866
+ endToken = aliasToken;
867
+ } else if (this.checkIdentifierLike([]) &&
868
+ !this.checkNext(1, TokenType.DOT) &&
869
+ !this.checkNext(1, TokenType.COMMA) &&
870
+ !this.isJoinToken() &&
871
+ !this.isEndOfClause()) {
872
+ const aliasToken = this.advance();
873
+ alias = aliasToken.lexeme;
874
+ endToken = aliasToken;
875
+ }
876
+
877
+ return {
878
+ type: 'functionSource',
879
+ name,
880
+ args,
881
+ alias,
882
+ loc: _createLoc(startToken, endToken),
883
+ };
884
+ }
885
+
886
+ /**
887
+ * Parse a JOIN clause
888
+ */
889
+ private joinClause(left: AST.FromClause, withClause?: AST.WithClause): AST.JoinClause {
890
+ const joinStartToken = this.peek(); // Capture token before parsing JOIN type
891
+
892
+ // Determine join type
893
+ let joinType: 'inner' | 'left' | 'right' | 'full' | 'cross' = 'inner';
894
+
895
+ if (this.match(TokenType.LEFT)) {
896
+ this.match(TokenType.OUTER); // optional
897
+ joinType = 'left';
898
+ } else if (this.match(TokenType.RIGHT)) {
899
+ this.match(TokenType.OUTER); // optional
900
+ joinType = 'right';
901
+ } else if (this.match(TokenType.FULL)) {
902
+ this.match(TokenType.OUTER); // optional
903
+ joinType = 'full';
904
+ } else if (this.match(TokenType.CROSS)) {
905
+ joinType = 'cross';
906
+ } else if (this.match(TokenType.INNER)) {
907
+ joinType = 'inner';
908
+ }
909
+
910
+ // Consume JOIN token
911
+ this.consume(TokenType.JOIN, "Expected 'JOIN'.");
912
+
913
+ // Parse right side of join
914
+ const right = this.tableSource(withClause);
915
+
916
+ // Parse join condition
917
+ let condition: AST.Expression | undefined;
918
+ let columns: string[] | undefined;
919
+ let endToken = this.previous(); // End token is end of right source initially
920
+
921
+ if (this.match(TokenType.ON)) {
922
+ condition = this.expression();
923
+ endToken = this.previous(); // End token is end of ON expression
924
+ } else if (this.match(TokenType.USING)) {
925
+ this.consume(TokenType.LPAREN, "Expected '(' after 'USING'.");
926
+ columns = [];
927
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
928
+
929
+ do {
930
+ columns.push(this.consumeIdentifier(contextualKeywords, "Expected column name."));
931
+ } while (this.match(TokenType.COMMA));
932
+
933
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after columns.");
934
+ } else if (joinType !== 'cross') {
935
+ throw this.error(this.peek(), "Expected 'ON' or 'USING' after JOIN.");
936
+ }
937
+
938
+ return {
939
+ type: 'join',
940
+ joinType,
941
+ left,
942
+ right,
943
+ condition,
944
+ columns,
945
+ loc: _createLoc(joinStartToken, endToken),
946
+ };
947
+ }
948
+
949
+ /**
950
+ * Parse an expression
951
+ */
952
+ private expression(): AST.Expression {
953
+ return this.logicalXorOr();
954
+ }
955
+
956
+ /**
957
+ * Parse logical OR and XOR expressions (lowest precedence)
958
+ */
959
+ private logicalXorOr(): AST.Expression {
960
+ let expr = this.logicalAnd();
961
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
962
+
963
+ while (this.match(TokenType.OR, TokenType.XOR)) { // Added XOR
964
+ const operator = this.previous().type === TokenType.XOR ? 'XOR' : 'OR'; // Determine operator
965
+ const right = this.logicalAnd();
966
+ const endToken = this.previous(); // End token is end of right expr
967
+ expr = {
968
+ type: 'binary',
969
+ operator,
970
+ left: expr,
971
+ right,
972
+ loc: _createLoc(startToken, endToken),
973
+ };
974
+ }
975
+
976
+ return expr;
977
+ }
978
+
979
+ /**
980
+ * Parse logical AND expression
981
+ */
982
+ private logicalAnd(): AST.Expression {
983
+ let expr = this.isNull();
984
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
985
+
986
+ while (this.match(TokenType.AND)) {
987
+ const operator = 'AND';
988
+ const right = this.isNull();
989
+ const endToken = this.previous(); // End token is end of right expr
990
+ expr = {
991
+ type: 'binary',
992
+ operator,
993
+ left: expr,
994
+ right,
995
+ loc: _createLoc(startToken, endToken),
996
+ };
997
+ }
998
+
999
+ return expr;
1000
+ }
1001
+
1002
+ /**
1003
+ * Parse IS NULL / IS NOT NULL expressions
1004
+ */
1005
+ private isNull(): AST.Expression {
1006
+ const expr = this.equality();
1007
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
1008
+
1009
+ if (this.match(TokenType.IS)) {
1010
+ let isNot = false;
1011
+ if (this.match(TokenType.NOT)) {
1012
+ isNot = true;
1013
+ }
1014
+ if (this.match(TokenType.NULL)) {
1015
+ const endToken = this.previous(); // End token is NULL
1016
+ const operator = isNot ? 'IS NOT NULL' : 'IS NULL';
1017
+ // Represent IS NULL / IS NOT NULL as UnaryExpr for simplicity
1018
+ return { type: 'unary', operator, expr, loc: _createLoc(startToken, endToken) };
1019
+ }
1020
+ // If it was IS or IS NOT but not followed by NULL, maybe it's IS TRUE/FALSE/DISTINCT FROM?
1021
+ // For now, assume standard comparison if NULL doesn't follow IS [NOT]
1022
+ // We need to "unread" the IS and optional NOT token if we didn't match NULL.
1023
+ // Backtrack current position.
1024
+ if (isNot) this.current--; // Backtrack NOT
1025
+ this.current--; // Backtrack IS
1026
+ }
1027
+
1028
+ return expr;
1029
+ }
1030
+
1031
+ /**
1032
+ * Parse equality expression
1033
+ */
1034
+ private equality(): AST.Expression {
1035
+ let expr = this.comparison();
1036
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
1037
+
1038
+ while (this.match(TokenType.EQUAL, TokenType.EQUAL_EQUAL, TokenType.NOT_EQUAL)) {
1039
+ let operator: string;
1040
+ switch (this.previous().type) {
1041
+ case TokenType.NOT_EQUAL: operator = '!='; break;
1042
+ case TokenType.EQUAL_EQUAL: operator = '=='; break;
1043
+ default: operator = '='; break;
1044
+ }
1045
+ const right = this.comparison();
1046
+ const endToken = this.previous(); // End token is end of right expr
1047
+ expr = {
1048
+ type: 'binary',
1049
+ operator,
1050
+ left: expr,
1051
+ right,
1052
+ loc: _createLoc(startToken, endToken),
1053
+ };
1054
+ }
1055
+
1056
+ return expr;
1057
+ }
1058
+
1059
+ /**
1060
+ * Parse comparison expression
1061
+ */
1062
+ private comparison(): AST.Expression {
1063
+ let expr = this.term();
1064
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
1065
+
1066
+ while (this.match(
1067
+ TokenType.LESS, TokenType.LESS_EQUAL,
1068
+ TokenType.GREATER, TokenType.GREATER_EQUAL,
1069
+ TokenType.BETWEEN, TokenType.IN, TokenType.NOT,
1070
+ TokenType.LIKE
1071
+ )) {
1072
+ const operatorToken = this.previous();
1073
+
1074
+ // Handle NOT IN, NOT BETWEEN, and NOT LIKE
1075
+ if (operatorToken.type === TokenType.NOT) {
1076
+ const notStartToken = operatorToken;
1077
+ if (this.match(TokenType.IN)) {
1078
+ // NOT IN
1079
+ this.consume(TokenType.LPAREN, "Expected '(' after NOT IN.");
1080
+
1081
+ if (this.check(TokenType.SELECT)) {
1082
+ // NOT IN subquery: expr NOT IN (SELECT ...)
1083
+ const selectToken = this.advance(); // Consume SELECT
1084
+ const subquery = this.selectStatement(selectToken);
1085
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after NOT IN subquery.");
1086
+
1087
+ // Create an IN expression with subquery, then wrap in NOT
1088
+ const inExpr: AST.InExpr = {
1089
+ type: 'in',
1090
+ expr,
1091
+ subquery,
1092
+ loc: _createLoc(startToken, endToken),
1093
+ };
1094
+
1095
+ expr = {
1096
+ type: 'unary',
1097
+ operator: 'NOT',
1098
+ expr: inExpr,
1099
+ loc: _createLoc(notStartToken, endToken),
1100
+ };
1101
+ } else {
1102
+ // NOT IN value list: expr NOT IN (value1, value2, ...)
1103
+ const values: AST.Expression[] = [];
1104
+ if (!this.check(TokenType.RPAREN)) {
1105
+ do {
1106
+ values.push(this.expression());
1107
+ } while (this.match(TokenType.COMMA));
1108
+ }
1109
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after NOT IN values.");
1110
+
1111
+ // Create an IN expression with value list, then wrap in NOT
1112
+ const inExpr: AST.InExpr = {
1113
+ type: 'in',
1114
+ expr,
1115
+ values,
1116
+ loc: _createLoc(startToken, endToken),
1117
+ };
1118
+
1119
+ expr = {
1120
+ type: 'unary',
1121
+ operator: 'NOT',
1122
+ expr: inExpr,
1123
+ loc: _createLoc(notStartToken, endToken),
1124
+ };
1125
+ }
1126
+ } else if (this.match(TokenType.BETWEEN)) {
1127
+ // NOT BETWEEN
1128
+ const low = this.term();
1129
+ this.consume(TokenType.AND, "Expected 'AND' after NOT BETWEEN lower bound.");
1130
+ const high = this.term();
1131
+ const endToken = this.previous(); // End token is end of high expr
1132
+
1133
+ // Create a binary AND expression for the bounds
1134
+ const boundsExpr: AST.BinaryExpr = {
1135
+ type: 'binary',
1136
+ operator: 'AND',
1137
+ left: low,
1138
+ right: high,
1139
+ loc: _createLoc(low.loc?.start ? this.tokens.find(t => t.startOffset === low.loc!.start.offset) ?? this.peek() : this.peek(), endToken)
1140
+ };
1141
+
1142
+ // Create the BETWEEN expression as a binary expression, then wrap in NOT
1143
+ const betweenExpr: AST.BinaryExpr = {
1144
+ type: 'binary',
1145
+ operator: 'BETWEEN',
1146
+ left: expr,
1147
+ right: boundsExpr,
1148
+ loc: _createLoc(startToken, endToken),
1149
+ };
1150
+
1151
+ expr = {
1152
+ type: 'unary',
1153
+ operator: 'NOT',
1154
+ expr: betweenExpr,
1155
+ loc: _createLoc(notStartToken, endToken),
1156
+ };
1157
+ } else if (this.match(TokenType.LIKE)) {
1158
+ // NOT LIKE
1159
+ const pattern = this.term();
1160
+ const endToken = this.previous(); // End token is end of pattern expr
1161
+
1162
+ // Create the LIKE expression as a binary expression, then wrap in NOT
1163
+ const likeExpr: AST.BinaryExpr = {
1164
+ type: 'binary',
1165
+ operator: 'LIKE',
1166
+ left: expr,
1167
+ right: pattern,
1168
+ loc: _createLoc(startToken, endToken),
1169
+ };
1170
+
1171
+ expr = {
1172
+ type: 'unary',
1173
+ operator: 'NOT',
1174
+ expr: likeExpr,
1175
+ loc: _createLoc(notStartToken, endToken),
1176
+ };
1177
+ } else {
1178
+ // Put back the NOT token and break out of the loop
1179
+ this.current--;
1180
+ break;
1181
+ }
1182
+ } else if (operatorToken.type === TokenType.LIKE) {
1183
+ // Parse LIKE expression: expr LIKE pattern
1184
+ const pattern = this.term();
1185
+ const endToken = this.previous(); // End token is end of pattern expr
1186
+
1187
+ // Create the LIKE expression as a binary expression
1188
+ expr = {
1189
+ type: 'binary',
1190
+ operator: 'LIKE',
1191
+ left: expr,
1192
+ right: pattern,
1193
+ loc: _createLoc(startToken, endToken),
1194
+ };
1195
+ } else if (operatorToken.type === TokenType.BETWEEN) {
1196
+ // Parse BETWEEN expression: expr BETWEEN low AND high
1197
+ const low = this.term();
1198
+ this.consume(TokenType.AND, "Expected 'AND' after BETWEEN lower bound.");
1199
+ const high = this.term();
1200
+ const endToken = this.previous(); // End token is end of high expr
1201
+
1202
+ // Create a binary AND expression for the bounds
1203
+ const boundsExpr: AST.BinaryExpr = {
1204
+ type: 'binary',
1205
+ operator: 'AND',
1206
+ left: low,
1207
+ right: high,
1208
+ loc: _createLoc(low.loc?.start ? this.tokens.find(t => t.startOffset === low.loc!.start.offset) ?? this.peek() : this.peek(), endToken)
1209
+ };
1210
+
1211
+ // Create the BETWEEN expression as a binary expression
1212
+ expr = {
1213
+ type: 'binary',
1214
+ operator: 'BETWEEN',
1215
+ left: expr,
1216
+ right: boundsExpr,
1217
+ loc: _createLoc(startToken, endToken),
1218
+ };
1219
+ } else if (operatorToken.type === TokenType.IN) {
1220
+ // Parse IN expression: expr IN (value1, value2, ...) or expr IN (subquery)
1221
+ this.consume(TokenType.LPAREN, "Expected '(' after IN.");
1222
+
1223
+ // Check if this is a subquery or value list
1224
+ if (this.check(TokenType.SELECT)) {
1225
+ // IN subquery: expr IN (SELECT ...)
1226
+ const selectToken = this.advance(); // Consume SELECT
1227
+ const subquery = this.selectStatement(selectToken);
1228
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after IN subquery.");
1229
+
1230
+ // Create an IN expression with subquery
1231
+ expr = {
1232
+ type: 'in',
1233
+ expr,
1234
+ subquery,
1235
+ loc: _createLoc(startToken, endToken),
1236
+ };
1237
+ } else {
1238
+ // IN value list: expr IN (value1, value2, ...)
1239
+ const values: AST.Expression[] = [];
1240
+ if (!this.check(TokenType.RPAREN)) {
1241
+ do {
1242
+ values.push(this.expression());
1243
+ } while (this.match(TokenType.COMMA));
1244
+ }
1245
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after IN values.");
1246
+
1247
+ // Create an IN expression with value list
1248
+ expr = {
1249
+ type: 'in',
1250
+ expr,
1251
+ values,
1252
+ loc: _createLoc(startToken, endToken),
1253
+ };
1254
+ }
1255
+ } else {
1256
+ // Handle other comparison operators
1257
+ let operator: string;
1258
+ switch (operatorToken.type) {
1259
+ case TokenType.LESS: operator = '<'; break;
1260
+ case TokenType.LESS_EQUAL: operator = '<='; break;
1261
+ case TokenType.GREATER: operator = '>'; break;
1262
+ case TokenType.GREATER_EQUAL: operator = '>='; break;
1263
+ default: operator = '?';
1264
+ }
1265
+
1266
+ const right = this.term();
1267
+ const endToken = this.previous(); // End token is end of right expr
1268
+ expr = {
1269
+ type: 'binary',
1270
+ operator,
1271
+ left: expr,
1272
+ right,
1273
+ loc: _createLoc(startToken, endToken),
1274
+ };
1275
+ }
1276
+ }
1277
+
1278
+ return expr;
1279
+ }
1280
+
1281
+ /**
1282
+ * Parse addition and subtraction
1283
+ */
1284
+ private term(): AST.Expression {
1285
+ let expr = this.factor();
1286
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
1287
+
1288
+ while (this.match(TokenType.PLUS, TokenType.MINUS)) {
1289
+ const operator = this.previous().type === TokenType.PLUS ? '+' : '-';
1290
+ const right = this.factor();
1291
+ const endToken = this.previous(); // End token is end of right expr
1292
+ expr = {
1293
+ type: 'binary',
1294
+ operator,
1295
+ left: expr,
1296
+ right,
1297
+ loc: _createLoc(startToken, endToken),
1298
+ };
1299
+ }
1300
+
1301
+ return expr;
1302
+ }
1303
+
1304
+ /**
1305
+ * Parse multiplication and division
1306
+ */
1307
+ private factor(): AST.Expression {
1308
+ // First, handle unary operators
1309
+ if (this.match(TokenType.MINUS, TokenType.PLUS, TokenType.TILDE, TokenType.NOT)) { // Added NOT
1310
+ const operatorToken = this.previous();
1311
+ const operatorStartToken = operatorToken; // Start token is the operator itself
1312
+ const operator = operatorToken.lexeme;
1313
+ // Unary operator applies to the result of the *next* precedence level (concatenation)
1314
+ const right = this.concatenation(); // Should call concatenation (higher precedence than factor)
1315
+ const endToken = this.previous(); // End token is end of the operand
1316
+ return { type: 'unary', operator, expr: right, loc: _createLoc(operatorStartToken, endToken) };
1317
+ }
1318
+
1319
+ let expr = this.concatenation(); // Factor operands have higher precedence (concatenation)
1320
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
1321
+
1322
+ while (this.match(TokenType.ASTERISK, TokenType.SLASH, TokenType.PERCENT)) {
1323
+ const operatorToken = this.previous();
1324
+ const operator = operatorToken.lexeme;
1325
+ const right = this.concatenation(); // Factor operands have higher precedence (concatenation)
1326
+ const endToken = this.previous(); // End token is end of right expr
1327
+ expr = { type: 'binary', operator, left: expr, right, loc: _createLoc(startToken, endToken) };
1328
+ }
1329
+
1330
+ return expr;
1331
+ }
1332
+
1333
+ /**
1334
+ * Parse concatenation expression (||)
1335
+ */
1336
+ private concatenation(): AST.Expression {
1337
+ let expr = this.collateExpression(); // Concatenation operands have higher precedence (collate)
1338
+ const startToken = expr.loc ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek(); // Get start token of left expr
1339
+
1340
+ while (this.match(TokenType.PIPE_PIPE)) {
1341
+ const operator = '||';
1342
+ const right = this.collateExpression(); // Concatenation operands have higher precedence (collate)
1343
+ const endToken = this.previous(); // End token is end of right expr
1344
+ expr = {
1345
+ type: 'binary',
1346
+ operator,
1347
+ left: expr,
1348
+ right,
1349
+ loc: _createLoc(startToken, endToken),
1350
+ };
1351
+ }
1352
+
1353
+ return expr;
1354
+ }
1355
+
1356
+ /**
1357
+ * Parse COLLATE expression
1358
+ */
1359
+ private collateExpression(): AST.Expression {
1360
+ const expr = this.primary(); // Parse primary expression first
1361
+
1362
+ if (this.matchKeyword('COLLATE')) {
1363
+ const collationToken = this.consume(TokenType.IDENTIFIER, "Expected collation name after COLLATE.");
1364
+ const collation = collationToken.lexeme;
1365
+ // Use the start of the original expression and end of collation name for location
1366
+ const startLocToken = expr.loc?.start ? this.tokens.find(t => t.startOffset === expr.loc!.start.offset) ?? this.peek() : this.peek();
1367
+ return { type: 'collate', expr, collation, loc: _createLoc(startLocToken, collationToken) };
1368
+ }
1369
+
1370
+ return expr;
1371
+ }
1372
+
1373
+ /**
1374
+ * Parse primary expressions (literals, identifiers, etc.)
1375
+ */
1376
+ private primary(): AST.Expression {
1377
+ const startToken = this.peek();
1378
+
1379
+ // Case expression
1380
+ if (this.matchKeyword('CASE')) {
1381
+ return this.parseCaseExpression(startToken);
1382
+ }
1383
+
1384
+ // CAST expression: CAST(expr AS type)
1385
+ if (this.peekKeyword('CAST') && this.checkNext(1, TokenType.LPAREN)) {
1386
+ const castToken = this.advance(); // Consume CAST
1387
+ this.consume(TokenType.LPAREN, "Expected '(' after CAST.");
1388
+ const expr = this.expression();
1389
+ this.consumeKeyword('AS', "Expected 'AS' in CAST expression.");
1390
+ // Allow type names that might be keywords (e.g., TEXT, INTEGER, REAL, BLOB)
1391
+ // or multi-word type names if supported (e.g., "VARCHAR(255)") - for now, simple identifier
1392
+ if (!this.check(TokenType.IDENTIFIER) &&
1393
+ !this.isTypeNameKeyword(this.peek().lexeme.toUpperCase())) {
1394
+ throw this.error(this.peek(), "Expected type name after 'AS' in CAST expression.");
1395
+ }
1396
+ const typeToken = this.advance(); // Consume type name
1397
+ const targetType = typeToken.lexeme;
1398
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after CAST expression type.");
1399
+ return { type: 'cast', expr, targetType, loc: _createLoc(castToken, endToken) };
1400
+ }
1401
+
1402
+ // EXISTS expression: EXISTS(SELECT ...)
1403
+ if (this.match(TokenType.EXISTS)) {
1404
+ const existsToken = this.previous();
1405
+ this.consume(TokenType.LPAREN, "Expected '(' after EXISTS.");
1406
+ const selectToken = this.consume(TokenType.SELECT, "Expected 'SELECT' in EXISTS subquery.");
1407
+ const subquery = this.selectStatement(selectToken);
1408
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after EXISTS subquery.");
1409
+ return {
1410
+ type: 'exists',
1411
+ subquery,
1412
+ loc: _createLoc(existsToken, endToken)
1413
+ };
1414
+ }
1415
+
1416
+ // Literals
1417
+ if (this.match(TokenType.INTEGER, TokenType.FLOAT, TokenType.STRING, TokenType.NULL, TokenType.TRUE, TokenType.FALSE, TokenType.BLOB)) {
1418
+ const token = this.previous();
1419
+ let value: any;
1420
+ let lexeme: string | undefined = undefined;
1421
+
1422
+ if (token.type === TokenType.NULL) {
1423
+ value = null;
1424
+ lexeme = token.lexeme; // Store original case (NULL vs null)
1425
+ } else if (token.type === TokenType.TRUE) {
1426
+ value = true;
1427
+ lexeme = token.lexeme; // Store original case (TRUE vs true)
1428
+ } else if (token.type === TokenType.FALSE) {
1429
+ value = false;
1430
+ lexeme = token.lexeme; // Store original case (FALSE vs false)
1431
+ } else if (token.type === TokenType.FLOAT) {
1432
+ // For FLOAT, parse the literal (which is the original string)
1433
+ value = parseFloat(token.literal as string);
1434
+ lexeme = token.literal as string; // Store original string as lexeme
1435
+ } else if (token.type === TokenType.INTEGER) {
1436
+ value = token.literal; // Already number or BigInt
1437
+ if (token.lexeme !== String(value)) { // Store lexeme only if different
1438
+ lexeme = token.lexeme;
1439
+ }
1440
+ } else {
1441
+ value = token.literal; // STRING, BLOB
1442
+ }
1443
+
1444
+ const node: AST.LiteralExpr = { type: 'literal', value, loc: _createLoc(startToken, token) };
1445
+ if (lexeme !== undefined) {
1446
+ node.lexeme = lexeme;
1447
+ }
1448
+ return node;
1449
+ }
1450
+
1451
+ // Parameter expressions (?, :name, $name)
1452
+ if (this.match(TokenType.QUESTION)) {
1453
+ const token = this.previous();
1454
+ return { type: 'parameter', index: this.parameterPosition++, loc: _createLoc(startToken, token) };
1455
+ }
1456
+
1457
+ if (this.match(TokenType.COLON, TokenType.DOLLAR)) {
1458
+ // Named parameter (can be identifier like :name or integer like :1)
1459
+ if (!this.check(TokenType.IDENTIFIER) && !this.check(TokenType.INTEGER)) {
1460
+ throw this.error(this.peek(), "Expected identifier or number after parameter prefix.");
1461
+ }
1462
+ const nameToken = this.advance();
1463
+ return { type: 'parameter', name: nameToken.lexeme, loc: _createLoc(startToken, nameToken) };
1464
+ }
1465
+
1466
+ // Function call (with optional window function support)
1467
+ if (this.checkIdentifierLike(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like']) && this.checkNext(1, TokenType.LPAREN)) {
1468
+ const name = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected function name.");
1469
+
1470
+ this.consume(TokenType.LPAREN, "Expected '(' after function name.");
1471
+
1472
+ const args: AST.Expression[] = [];
1473
+ let distinct = false;
1474
+ if (!this.check(TokenType.RPAREN)) {
1475
+ // Handle DISTINCT inside function calls like COUNT(DISTINCT col)
1476
+ distinct = this.matchKeyword('DISTINCT');
1477
+ // Handle * argument AFTER checking for distinct
1478
+ if (this.match(TokenType.ASTERISK)) {
1479
+ // Do not add '*' as an argument to the list for aggregates like COUNT(*)
1480
+ if (args.length > 0 || distinct) {
1481
+ // '*' is only valid as the *only* argument, potentially after DISTINCT
1482
+ // e.g. COUNT(*), COUNT(DISTINCT *) - though DISTINCT * might not be standard SQL?
1483
+ // For now, disallow '*' if other args exist.
1484
+ throw this.error(this.previous(), "'*' cannot be used with other arguments in function call.");
1485
+ }
1486
+ // If we parsed '*', the args list remains empty.
1487
+ } else {
1488
+ // Parse regular arguments if '*' wasn't found
1489
+ do {
1490
+ args.push(this.expression());
1491
+ } while (this.match(TokenType.COMMA));
1492
+ }
1493
+ }
1494
+
1495
+ const endToken = this.consume(TokenType.RPAREN, "Expected ')' after function arguments.");
1496
+
1497
+ const funcExpr: AST.FunctionExpr = {
1498
+ type: 'function',
1499
+ name,
1500
+ args,
1501
+ loc: _createLoc(startToken, endToken)
1502
+ };
1503
+
1504
+ // Add distinct field if it was parsed
1505
+ if (distinct) {
1506
+ funcExpr.distinct = true;
1507
+ }
1508
+
1509
+ // Check for OVER clause (window function)
1510
+ if (this.matchKeyword('OVER')) {
1511
+ const window = this.parseWindowSpecification();
1512
+ const overEndToken = this.previous();
1513
+ return {
1514
+ type: 'windowFunction',
1515
+ function: funcExpr,
1516
+ window,
1517
+ loc: _createLoc(startToken, overEndToken)
1518
+ };
1519
+ }
1520
+
1521
+ return funcExpr;
1522
+ }
1523
+
1524
+ // Column/identifier expressions
1525
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
1526
+ if (this.checkIdentifierLike(contextualKeywords)) {
1527
+ // Schema.table.column
1528
+ if (this.checkNext(1, TokenType.DOT) && this.checkIdentifierLikeAt(2, contextualKeywords) &&
1529
+ this.checkNext(3, TokenType.DOT) && this.checkIdentifierLikeAt(4, contextualKeywords)) {
1530
+ const schema = this.consumeIdentifier(contextualKeywords, "Expected schema name.");
1531
+ this.advance(); // Consume DOT
1532
+ const table = this.consumeIdentifier(contextualKeywords, "Expected table name.");
1533
+ this.advance(); // Consume DOT
1534
+ const name = this.consumeIdentifier(contextualKeywords, "Expected column name.");
1535
+ const nameToken = this.previous();
1536
+
1537
+ return {
1538
+ type: 'column',
1539
+ name,
1540
+ table,
1541
+ schema,
1542
+ loc: _createLoc(startToken, nameToken),
1543
+ };
1544
+ }
1545
+ // table.column
1546
+ else if (this.checkNext(1, TokenType.DOT) && this.checkIdentifierLikeAt(2, contextualKeywords)) {
1547
+ const table = this.consumeIdentifier(contextualKeywords, "Expected table name.");
1548
+ this.advance(); // Consume DOT
1549
+ const name = this.consumeIdentifier(contextualKeywords, "Expected column name.");
1550
+ const nameToken = this.previous();
1551
+
1552
+ return {
1553
+ type: 'column',
1554
+ name,
1555
+ table,
1556
+ loc: _createLoc(startToken, nameToken),
1557
+ };
1558
+ }
1559
+ // just column
1560
+ else {
1561
+ const name = this.consumeIdentifier(contextualKeywords, "Expected column name.");
1562
+ const nameToken = this.previous();
1563
+
1564
+ return {
1565
+ type: 'column',
1566
+ name,
1567
+ loc: _createLoc(startToken, nameToken),
1568
+ };
1569
+ }
1570
+ }
1571
+
1572
+ // Parenthesized expression or scalar subquery
1573
+ if (this.match(TokenType.LPAREN)) {
1574
+ // Look ahead to see if this is a scalar subquery (SELECT ...)
1575
+ if (this.check(TokenType.SELECT)) {
1576
+ const selectToken = this.consume(TokenType.SELECT, "Expected 'SELECT' in subquery.");
1577
+ const subquery = this.selectStatement(selectToken);
1578
+ this.consume(TokenType.RPAREN, "Expected ')' after subquery.");
1579
+ return {
1580
+ type: 'subquery',
1581
+ query: subquery,
1582
+ loc: _createLoc(startToken, this.previous())
1583
+ };
1584
+ } else {
1585
+ // Regular parenthesized expression
1586
+ const expr = this.expression();
1587
+ this.consume(TokenType.RPAREN, "Expected ')' after expression.");
1588
+ return expr;
1589
+ }
1590
+ }
1591
+
1592
+ throw this.error(this.peek(), "Expected expression.");
1593
+ }
1594
+
1595
+ /**
1596
+ * Parses a window specification: (PARTITION BY ... ORDER BY ... [frame])
1597
+ */
1598
+ private parseWindowSpecification(): AST.WindowDefinition {
1599
+ if (this.match(TokenType.LPAREN)) {
1600
+ let partitionBy: AST.Expression[] | undefined;
1601
+ let orderBy: AST.OrderByClause[] | undefined;
1602
+ let frame: AST.WindowFrame | undefined;
1603
+
1604
+ if (this.matchKeyword('PARTITION')) {
1605
+ this.consumeKeyword('BY', "Expected 'BY' after 'PARTITION'.");
1606
+ partitionBy = [];
1607
+ do {
1608
+ partitionBy.push(this.expression());
1609
+ } while (this.match(TokenType.COMMA));
1610
+ }
1611
+
1612
+ if (this.matchKeyword('ORDER')) {
1613
+ this.consumeKeyword('BY', "Expected 'BY' after 'ORDER'.");
1614
+ orderBy = [];
1615
+ do {
1616
+ const expr = this.expression();
1617
+ const direction = this.match(TokenType.DESC) ? 'desc' : (this.match(TokenType.ASC) ? 'asc' : 'asc');
1618
+
1619
+ // Handle NULLS FIRST/LAST
1620
+ let nullsOrdering: 'first' | 'last' | undefined;
1621
+ if (this.matchKeyword('NULLS')) {
1622
+ if (this.matchKeyword('FIRST')) {
1623
+ nullsOrdering = 'first';
1624
+ } else if (this.matchKeyword('LAST')) {
1625
+ nullsOrdering = 'last';
1626
+ } else {
1627
+ throw this.error(this.peek(), "Expected 'FIRST' or 'LAST' after 'NULLS'.");
1628
+ }
1629
+ }
1630
+
1631
+ const orderClause: AST.OrderByClause = { expr, direction };
1632
+ if (nullsOrdering) {
1633
+ (orderClause as any).nullsOrdering = nullsOrdering;
1634
+ }
1635
+ orderBy.push(orderClause);
1636
+ } while (this.match(TokenType.COMMA));
1637
+ }
1638
+
1639
+ // Frame clause (ROWS|RANGE ...)
1640
+ if (this.matchKeyword('ROWS') || this.matchKeyword('RANGE')) {
1641
+ const frameType = this.previous().lexeme.toLowerCase() as 'rows' | 'range';
1642
+
1643
+ // Handle both BETWEEN...AND and single bound syntax
1644
+ if (this.matchKeyword('BETWEEN')) {
1645
+ // ROWS BETWEEN start_bound AND end_bound
1646
+ const start = this.parseWindowFrameBound();
1647
+ this.consumeKeyword('AND', "Expected 'AND' after frame start bound.");
1648
+ const end = this.parseWindowFrameBound();
1649
+ frame = { type: frameType, start, end };
1650
+ } else {
1651
+ // ROWS start_bound (shorthand for ROWS BETWEEN start_bound AND CURRENT ROW)
1652
+ const start = this.parseWindowFrameBound();
1653
+ frame = { type: frameType, start, end: null };
1654
+ }
1655
+ }
1656
+
1657
+ this.consume(TokenType.RPAREN, "Expected ')' after window specification.");
1658
+ return { type: 'windowDefinition', partitionBy, orderBy, frame };
1659
+ } else {
1660
+ // Window name (not implemented)
1661
+ throw this.error(this.peek(), 'Window name references are not yet supported. Use explicit window specs.');
1662
+ }
1663
+ }
1664
+
1665
+ /**
1666
+ * Parses a window frame bound (UNBOUNDED PRECEDING, CURRENT ROW, n PRECEDING/FOLLOWING)
1667
+ */
1668
+ private parseWindowFrameBound(): AST.WindowFrameBound {
1669
+ if (this.matchKeyword('UNBOUNDED')) {
1670
+ if (this.matchKeyword('PRECEDING')) {
1671
+ return { type: 'unboundedPreceding' };
1672
+ } else if (this.matchKeyword('FOLLOWING')) {
1673
+ return { type: 'unboundedFollowing' };
1674
+ } else {
1675
+ throw this.error(this.peek(), "Expected PRECEDING or FOLLOWING after UNBOUNDED.");
1676
+ }
1677
+ } else if (this.matchKeyword('CURRENT')) {
1678
+ this.consumeKeyword('ROW', "Expected 'ROW' after 'CURRENT'.");
1679
+ return { type: 'currentRow' };
1680
+ } else {
1681
+ const value = this.expression();
1682
+ if (this.matchKeyword('PRECEDING')) {
1683
+ return { type: 'preceding', value };
1684
+ } else if (this.matchKeyword('FOLLOWING')) {
1685
+ return { type: 'following', value };
1686
+ } else {
1687
+ throw this.error(this.peek(), "Expected PRECEDING or FOLLOWING after frame value.");
1688
+ }
1689
+ }
1690
+ }
1691
+
1692
+ // Helper methods for token management
1693
+
1694
+ private match(...types: TokenType[]): boolean {
1695
+ for (const type of types) {
1696
+ if (this.check(type)) {
1697
+ this.advance();
1698
+ return true;
1699
+ }
1700
+ }
1701
+ return false;
1702
+ }
1703
+
1704
+ private consume(type: TokenType, message: string): Token {
1705
+ if (this.check(type)) {
1706
+ return this.advance();
1707
+ }
1708
+
1709
+ this.error(this.peek(), message);
1710
+ }
1711
+
1712
+ private check(type: TokenType): boolean {
1713
+ if (this.isAtEnd()) return false;
1714
+ return this.peek().type === type;
1715
+ }
1716
+
1717
+ private checkNext(n: number, type: TokenType): boolean {
1718
+ if (this.current + n >= this.tokens.length) return false;
1719
+ return this.tokens[this.current + n].type === type;
1720
+ }
1721
+
1722
+ private advance(): Token {
1723
+ if (!this.isAtEnd()) this.current++;
1724
+ return this.previous();
1725
+ }
1726
+
1727
+ private isAtEnd(): boolean {
1728
+ return this.peek().type === TokenType.EOF;
1729
+ }
1730
+
1731
+ private peek(): Token {
1732
+ return this.tokens[this.current];
1733
+ }
1734
+
1735
+ private previous(): Token {
1736
+ return this.tokens[this.current - 1];
1737
+ }
1738
+
1739
+ private error(token: Token, message: string): never {
1740
+ quereusError(
1741
+ message,
1742
+ StatusCode.ERROR,
1743
+ undefined,
1744
+ {
1745
+ loc: {
1746
+ start: {
1747
+ line: token.startLine,
1748
+ column: token.startColumn,
1749
+ },
1750
+ end: {
1751
+ line: token.endLine,
1752
+ column: token.endColumn,
1753
+ }
1754
+ }
1755
+ }
1756
+ );
1757
+ }
1758
+
1759
+ private isJoinToken(): boolean {
1760
+ return this.check(TokenType.JOIN) ||
1761
+ this.check(TokenType.INNER) ||
1762
+ this.check(TokenType.LEFT) ||
1763
+ this.check(TokenType.RIGHT) ||
1764
+ this.check(TokenType.FULL) ||
1765
+ this.check(TokenType.CROSS);
1766
+ }
1767
+
1768
+ private isEndOfClause(): boolean {
1769
+ const token = this.peek().type;
1770
+ return token === TokenType.FROM ||
1771
+ token === TokenType.WHERE ||
1772
+ token === TokenType.GROUP ||
1773
+ token === TokenType.HAVING ||
1774
+ token === TokenType.ORDER ||
1775
+ token === TokenType.LIMIT ||
1776
+ token === TokenType.UNION ||
1777
+ token === TokenType.SEMICOLON ||
1778
+ token === TokenType.EOF;
1779
+ }
1780
+
1781
+ // --- Statement Parsing Stubs ---
1782
+
1783
+ /** @internal */
1784
+ private updateStatement(startToken: Token, _withClause?: AST.WithClause): AST.UpdateStmt {
1785
+ const table = this.tableIdentifier();
1786
+ this.consume(TokenType.SET, "Expected 'SET' after table name in UPDATE.");
1787
+ const assignments: { column: string; value: AST.Expression }[] = [];
1788
+ do {
1789
+ const column = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected column name in SET clause.");
1790
+ this.consume(TokenType.EQUAL, "Expected '=' after column name in SET clause.");
1791
+ const value = this.expression();
1792
+ assignments.push({ column, value });
1793
+ } while (this.match(TokenType.COMMA));
1794
+ let where: AST.Expression | undefined;
1795
+ if (this.match(TokenType.WHERE)) {
1796
+ where = this.expression();
1797
+ }
1798
+ // Parse RETURNING clause if present
1799
+ let returning: AST.ResultColumn[] | undefined;
1800
+ if (this.matchKeyword('RETURNING')) {
1801
+ returning = this.columnList();
1802
+ }
1803
+ const endToken = this.previous();
1804
+ return { type: 'update', table, assignments, where, returning, loc: _createLoc(startToken, endToken) };
1805
+ }
1806
+
1807
+ /** @internal */
1808
+ private deleteStatement(startToken: Token, _withClause?: AST.WithClause): AST.DeleteStmt {
1809
+ this.matchKeyword('FROM');
1810
+ const table = this.tableIdentifier();
1811
+ let where: AST.Expression | undefined;
1812
+ if (this.match(TokenType.WHERE)) {
1813
+ where = this.expression();
1814
+ }
1815
+
1816
+ // Parse RETURNING clause if present
1817
+ let returning: AST.ResultColumn[] | undefined;
1818
+ if (this.matchKeyword('RETURNING')) {
1819
+ returning = this.columnList();
1820
+ }
1821
+
1822
+ const endToken = this.previous();
1823
+ return { type: 'delete', table, where, returning, loc: _createLoc(startToken, endToken) };
1824
+ }
1825
+
1826
+ /** @internal */
1827
+ private valuesStatement(startToken: Token): AST.ValuesStmt {
1828
+ const values: AST.Expression[][] = [];
1829
+
1830
+ do {
1831
+ this.consume(TokenType.LPAREN, "Expected '(' before values.");
1832
+ const valueList: AST.Expression[] = [];
1833
+
1834
+ if (!this.check(TokenType.RPAREN)) { // Check for empty value list
1835
+ do {
1836
+ valueList.push(this.expression());
1837
+ } while (this.match(TokenType.COMMA));
1838
+ }
1839
+
1840
+ this.consume(TokenType.RPAREN, "Expected ')' after values.");
1841
+ values.push(valueList);
1842
+ } while (this.match(TokenType.COMMA));
1843
+
1844
+ const endToken = this.previous();
1845
+ return { type: 'values', values, loc: _createLoc(startToken, endToken) };
1846
+ }
1847
+
1848
+ /** @internal */
1849
+ private createStatement(startToken: Token, withClause?: AST.WithClause): AST.CreateTableStmt | AST.CreateIndexStmt | AST.CreateViewStmt {
1850
+ if (this.peekKeyword('TABLE')) {
1851
+ this.consumeKeyword('TABLE', "Expected 'TABLE' after CREATE.");
1852
+ return this.createTableStatement(startToken, withClause);
1853
+ } else if (this.peekKeyword('INDEX')) {
1854
+ this.consumeKeyword('INDEX', "Expected 'INDEX' after CREATE.");
1855
+ return this.createIndexStatement(startToken, false, withClause);
1856
+ } else if (this.peekKeyword('VIEW')) {
1857
+ this.consumeKeyword('VIEW', "Expected 'VIEW' after CREATE.");
1858
+ return this.createViewStatement(startToken, withClause);
1859
+ } else if (this.peekKeyword('UNIQUE')) {
1860
+ this.consumeKeyword('UNIQUE', "Expected 'UNIQUE' after CREATE.");
1861
+ this.consumeKeyword('INDEX', "Expected 'INDEX' after CREATE UNIQUE.");
1862
+ return this.createIndexStatement(startToken, true, withClause);
1863
+ }
1864
+ throw this.error(this.peek(), "Expected TABLE, [UNIQUE] INDEX, VIEW, or VIRTUAL after CREATE.");
1865
+ }
1866
+
1867
+ /**
1868
+ * Parse CREATE TABLE statement
1869
+ * @returns AST for CREATE TABLE
1870
+ */
1871
+ private createTableStatement(startToken: Token, _withClause?: AST.WithClause): AST.CreateTableStmt {
1872
+ let isTemporary = false;
1873
+ if (this.peekKeyword('TEMP') || this.peekKeyword('TEMPORARY')) {
1874
+ isTemporary = true;
1875
+ this.advance();
1876
+ }
1877
+
1878
+ let ifNotExists = false;
1879
+ if (this.matchKeyword('IF')) {
1880
+ this.consumeKeyword('NOT', "Expected 'NOT' after 'IF'.");
1881
+ this.consumeKeyword('EXISTS', "Expected 'EXISTS' after 'IF NOT'.");
1882
+ ifNotExists = true;
1883
+ }
1884
+
1885
+ const table = this.tableIdentifier();
1886
+
1887
+ const columns: AST.ColumnDef[] = [];
1888
+ const constraints: AST.TableConstraint[] = [];
1889
+
1890
+ if (this.check(TokenType.LPAREN)) {
1891
+ this.consume(TokenType.LPAREN, "Expected '(' to start table definition.");
1892
+ do {
1893
+ if (this.peekKeyword('PRIMARY') || this.peekKeyword('UNIQUE') || this.peekKeyword('CHECK') || this.peekKeyword('FOREIGN') || this.peekKeyword('CONSTRAINT')) {
1894
+ constraints.push(this.tableConstraint());
1895
+ } else {
1896
+ columns.push(this.columnDefinition());
1897
+ }
1898
+ } while (this.match(TokenType.COMMA));
1899
+
1900
+ this.consume(TokenType.RPAREN, "Expected ')' after table definition.");
1901
+
1902
+ } else if (this.matchKeyword('AS')) {
1903
+ const token = this.previous();
1904
+ quereusError(
1905
+ 'CREATE TABLE AS SELECT is not supported.',
1906
+ StatusCode.UNSUPPORTED,
1907
+ undefined,
1908
+ { loc: { start: { line: token.startLine, column: token.startColumn } } }
1909
+ );
1910
+ } else {
1911
+ throw this.error(this.peek(), "Expected '(' or 'AS' after table name.");
1912
+ }
1913
+
1914
+ let moduleName: string | undefined;
1915
+ const moduleArgs: Record<string, SqlValue> = {};
1916
+ if (this.matchKeyword('USING')) {
1917
+ moduleName = this.consumeIdentifier("Expected module name after 'USING'.");
1918
+ if (this.matchKeyword('(')) {
1919
+ while (!this.match(TokenType.RPAREN)) {
1920
+ const nameValue = this.nameValueItem("module argument");
1921
+ moduleArgs[nameValue.name] = nameValue.value && nameValue.value.type === 'literal'
1922
+ ? getSyncLiteral(nameValue.value) : nameValue.name;
1923
+ if (!this.match(TokenType.COMMA) || this.check(TokenType.RPAREN)) {
1924
+ throw this.error(this.peek(), "Expected ',' or ')' after module argument.");
1925
+ }
1926
+ }
1927
+ }
1928
+ }
1929
+
1930
+ return {
1931
+ type: 'createTable',
1932
+ table,
1933
+ ifNotExists,
1934
+ columns,
1935
+ constraints,
1936
+ isTemporary,
1937
+ moduleName,
1938
+ moduleArgs,
1939
+ loc: _createLoc(startToken, this.previous()),
1940
+ };
1941
+ }
1942
+
1943
+ /**
1944
+ * Parse CREATE INDEX statement
1945
+ * @param isUnique Flag indicating if UNIQUE keyword was already parsed
1946
+ * @returns AST for CREATE INDEX
1947
+ */
1948
+ private createIndexStatement(startToken: Token, isUnique = false, _withClause?: AST.WithClause): AST.CreateIndexStmt {
1949
+ if (!isUnique && this.peekKeyword('UNIQUE')) {
1950
+ isUnique = true;
1951
+ this.advance();
1952
+ }
1953
+
1954
+ let ifNotExists = false;
1955
+ if (this.matchKeyword('IF')) {
1956
+ this.consumeKeyword('NOT', "Expected 'NOT' after 'IF'.");
1957
+ this.consumeKeyword('EXISTS', "Expected 'EXISTS' after 'IF NOT'.");
1958
+ ifNotExists = true;
1959
+ }
1960
+
1961
+ const index = this.tableIdentifier();
1962
+
1963
+ this.consumeKeyword('ON', "Expected 'ON' after index name.");
1964
+
1965
+ const table = this.tableIdentifier();
1966
+
1967
+ this.consume(TokenType.LPAREN, "Expected '(' before indexed columns.");
1968
+ const columns = this.indexedColumnList();
1969
+ this.consume(TokenType.RPAREN, "Expected ')' after indexed columns.");
1970
+
1971
+ let where: AST.Expression | undefined;
1972
+ if (this.matchKeyword('WHERE')) {
1973
+ where = this.expression();
1974
+ }
1975
+
1976
+ return {
1977
+ type: 'createIndex',
1978
+ index,
1979
+ table,
1980
+ ifNotExists,
1981
+ columns,
1982
+ where,
1983
+ isUnique,
1984
+ loc: _createLoc(startToken, this.previous()),
1985
+ };
1986
+ }
1987
+
1988
+ /**
1989
+ * Parse CREATE VIEW statement
1990
+ * @returns AST for CREATE VIEW
1991
+ */
1992
+ private createViewStatement(startToken: Token, withClause?: AST.WithClause): AST.CreateViewStmt {
1993
+ let isTemporary = false;
1994
+ if (this.peekKeyword('TEMP') || this.peekKeyword('TEMPORARY')) {
1995
+ isTemporary = true;
1996
+ this.advance();
1997
+ }
1998
+
1999
+ let ifNotExists = false;
2000
+ if (this.matchKeyword('IF')) {
2001
+ this.consumeKeyword('NOT', "Expected 'NOT' after 'IF'.");
2002
+ this.consumeKeyword('EXISTS', "Expected 'EXISTS' after 'IF NOT'.");
2003
+ ifNotExists = true;
2004
+ }
2005
+
2006
+ const view = this.tableIdentifier();
2007
+
2008
+ let columns: string[] | undefined;
2009
+ if (this.check(TokenType.LPAREN)) {
2010
+ this.consume(TokenType.LPAREN, "Expected '(' to start view column list.");
2011
+ columns = [];
2012
+ const contextualKeywords = ['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'];
2013
+ if (!this.check(TokenType.RPAREN)) {
2014
+ do {
2015
+ columns.push(this.consumeIdentifier(contextualKeywords, "Expected column name in view column list."));
2016
+ } while (this.match(TokenType.COMMA));
2017
+ }
2018
+ this.consume(TokenType.RPAREN, "Expected ')' after view column list.");
2019
+ }
2020
+
2021
+ this.consumeKeyword('AS', "Expected 'AS' before SELECT statement for CREATE VIEW.");
2022
+
2023
+ const selectStartToken = this.consume(TokenType.SELECT, "Expected 'SELECT' after 'AS' in CREATE VIEW.");
2024
+ const select = this.selectStatement(selectStartToken, withClause);
2025
+
2026
+ return {
2027
+ type: 'createView',
2028
+ view,
2029
+ ifNotExists,
2030
+ columns,
2031
+ select,
2032
+ isTemporary,
2033
+ loc: _createLoc(startToken, this.previous()),
2034
+ };
2035
+ }
2036
+
2037
+ /**
2038
+ * Parse DROP statement
2039
+ * @returns AST for DROP statement
2040
+ */
2041
+ private dropStatement(startToken: Token, _withClause?: AST.WithClause): AST.DropStmt {
2042
+ let objectType: 'table' | 'view' | 'index' | 'trigger';
2043
+
2044
+ if (this.peekKeyword('TABLE')) {
2045
+ this.consumeKeyword('TABLE', "Expected TABLE after DROP.");
2046
+ objectType = 'table';
2047
+ } else if (this.peekKeyword('VIEW')) {
2048
+ this.consumeKeyword('VIEW', "Expected VIEW after DROP.");
2049
+ objectType = 'view';
2050
+ } else if (this.peekKeyword('INDEX')) {
2051
+ this.consumeKeyword('INDEX', "Expected INDEX after DROP.");
2052
+ objectType = 'index';
2053
+ } else {
2054
+ throw this.error(this.peek(), "Expected TABLE, VIEW, or INDEX after DROP.");
2055
+ }
2056
+
2057
+ let ifExists = false;
2058
+ if (this.matchKeyword('IF')) {
2059
+ this.consumeKeyword('EXISTS', "Expected 'EXISTS' after 'IF'.");
2060
+ ifExists = true;
2061
+ }
2062
+
2063
+ const name = this.tableIdentifier();
2064
+
2065
+ return {
2066
+ type: 'drop',
2067
+ objectType,
2068
+ name,
2069
+ ifExists,
2070
+ loc: _createLoc(startToken, this.previous()),
2071
+ };
2072
+ }
2073
+
2074
+ /**
2075
+ * Parse ALTER TABLE statement
2076
+ * @returns AST for ALTER TABLE statement
2077
+ */
2078
+ private alterTableStatement(startToken: Token, _withClause?: AST.WithClause): AST.AlterTableStmt {
2079
+ this.consumeKeyword('TABLE', "Expected 'TABLE' after ALTER.");
2080
+
2081
+ const table = this.tableIdentifier();
2082
+
2083
+ let action: AST.AlterTableAction;
2084
+
2085
+ if (this.peekKeyword('RENAME')) {
2086
+ this.consumeKeyword('RENAME', "Expected RENAME.");
2087
+ if (this.matchKeyword('COLUMN')) {
2088
+ const oldName = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected old column name after RENAME COLUMN.");
2089
+ this.consumeKeyword('TO', "Expected 'TO' after old column name.");
2090
+ const newName = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected new column name after TO.");
2091
+ action = { type: 'renameColumn', oldName, newName };
2092
+ } else {
2093
+ this.consumeKeyword('TO', "Expected 'TO' after RENAME.");
2094
+ const newName = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected new table name after RENAME TO.");
2095
+ action = { type: 'renameTable', newName };
2096
+ }
2097
+ } else if (this.peekKeyword('ADD')) {
2098
+ this.consumeKeyword('ADD', "Expected ADD.");
2099
+ if (this.peekKeyword('CONSTRAINT')) {
2100
+ // ADD CONSTRAINT ... - let tableConstraint parse everything including CONSTRAINT keyword
2101
+ const constraint = this.tableConstraint();
2102
+ action = { type: 'addConstraint', constraint };
2103
+ } else {
2104
+ // ADD [COLUMN] column_def
2105
+ this.matchKeyword('COLUMN');
2106
+ const column = this.columnDefinition();
2107
+ action = { type: 'addColumn', column };
2108
+ }
2109
+ } else if (this.peekKeyword('DROP')) {
2110
+ this.consumeKeyword('DROP', "Expected DROP.");
2111
+ this.matchKeyword('COLUMN');
2112
+ const name = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected column name after DROP COLUMN.");
2113
+ action = { type: 'dropColumn', name };
2114
+ } else {
2115
+ throw this.error(this.peek(), "Expected RENAME, ADD, or DROP after table name in ALTER TABLE.");
2116
+ }
2117
+
2118
+ return {
2119
+ type: 'alterTable',
2120
+ table,
2121
+ action,
2122
+ loc: _createLoc(startToken, this.previous()),
2123
+ };
2124
+ }
2125
+
2126
+ /**
2127
+ * Parse BEGIN statement
2128
+ * @returns AST for BEGIN statement
2129
+ */
2130
+ private beginStatement(startToken: Token, _withClause?: AST.WithClause): AST.BeginStmt {
2131
+ let mode: 'deferred' | 'immediate' | 'exclusive' | undefined;
2132
+ if (this.peekKeyword('DEFERRED')) {
2133
+ this.advance();
2134
+ mode = 'deferred';
2135
+ } else if (this.peekKeyword('IMMEDIATE')) {
2136
+ this.advance();
2137
+ mode = 'immediate';
2138
+ } else if (this.peekKeyword('EXCLUSIVE')) {
2139
+ this.advance();
2140
+ mode = 'exclusive';
2141
+ }
2142
+
2143
+ this.matchKeyword('TRANSACTION');
2144
+
2145
+ return { type: 'begin', mode, loc: _createLoc(startToken, this.previous()) };
2146
+ }
2147
+
2148
+ /**
2149
+ * Parse COMMIT statement
2150
+ * @returns AST for COMMIT statement
2151
+ */
2152
+ private commitStatement(startToken: Token, _withClause?: AST.WithClause): AST.CommitStmt {
2153
+ this.matchKeyword('TRANSACTION');
2154
+ return { type: 'commit', loc: _createLoc(startToken, this.previous()) };
2155
+ }
2156
+
2157
+ /**
2158
+ * Parse ROLLBACK statement
2159
+ * @returns AST for ROLLBACK statement
2160
+ */
2161
+ private rollbackStatement(startToken: Token, _withClause?: AST.WithClause): AST.RollbackStmt {
2162
+ this.matchKeyword('TRANSACTION');
2163
+
2164
+ let savepoint: string | undefined;
2165
+ if (this.matchKeyword('TO')) {
2166
+ this.matchKeyword('SAVEPOINT');
2167
+ if (!this.check(TokenType.IDENTIFIER)) {
2168
+ throw this.error(this.peek(), "Expected savepoint name after ROLLBACK TO.");
2169
+ }
2170
+ savepoint = this.advance().lexeme;
2171
+ }
2172
+ return { type: 'rollback', savepoint, loc: _createLoc(startToken, this.previous()) };
2173
+ }
2174
+
2175
+ /**
2176
+ * Parse SAVEPOINT statement
2177
+ * @returns AST for SAVEPOINT statement
2178
+ */
2179
+ private savepointStatement(startToken: Token, _withClause?: AST.WithClause): AST.SavepointStmt {
2180
+ const name = this.consumeIdentifier("Expected savepoint name after SAVEPOINT.");
2181
+ return { type: 'savepoint', name, loc: _createLoc(startToken, this.previous()) };
2182
+ }
2183
+
2184
+ /**
2185
+ * Parse RELEASE statement
2186
+ * @returns AST for RELEASE statement
2187
+ */
2188
+ private releaseStatement(startToken: Token, _withClause?: AST.WithClause): AST.ReleaseStmt {
2189
+ this.matchKeyword('SAVEPOINT');
2190
+ const name = this.consumeIdentifier("Expected savepoint name after RELEASE [SAVEPOINT].");
2191
+ return { type: 'release', savepoint: name, loc: _createLoc(startToken, this.previous()) };
2192
+ }
2193
+
2194
+ /**
2195
+ * Parse PRAGMA statement
2196
+ * @returns AST for PRAGMA statement
2197
+ */
2198
+ private pragmaStatement(startToken: Token, _withClause?: AST.WithClause): AST.PragmaStmt {
2199
+ const nameValue = this.nameValueItem("pragma");
2200
+ return { type: 'pragma', ...nameValue, loc: _createLoc(startToken, this.previous()) };
2201
+ }
2202
+
2203
+ private nameValueItem(context: string): { name: string, value?: AST.IdentifierExpr | AST.LiteralExpr } {
2204
+ const name = this.consumeIdentifier(`Expected ${context} name.`);
2205
+
2206
+ let value: AST.LiteralExpr | AST.IdentifierExpr | undefined;
2207
+ if (this.match(TokenType.EQUAL)) {
2208
+ if (this.check(TokenType.IDENTIFIER)) {
2209
+ value = { type: 'identifier', name: this.advance().lexeme };
2210
+ } else if (this.match(TokenType.STRING, TokenType.INTEGER, TokenType.FLOAT, TokenType.NULL, TokenType.TRUE, TokenType.FALSE)) {
2211
+ const token = this.previous();
2212
+ let literal_value: SqlValue;
2213
+ if (token.type === TokenType.NULL) {
2214
+ literal_value = null;
2215
+ } else if (token.type === TokenType.TRUE) {
2216
+ literal_value = 1;
2217
+ } else if (token.type === TokenType.FALSE) {
2218
+ literal_value = 0;
2219
+ } else {
2220
+ literal_value = token.literal;
2221
+ }
2222
+ value = { type: 'literal', value: literal_value };
2223
+ } else if (this.match(TokenType.MINUS)) {
2224
+ if (this.check(TokenType.INTEGER) || this.check(TokenType.FLOAT)) {
2225
+ const token = this.advance();
2226
+ value = { type: 'literal', value: -token.literal };
2227
+ } else {
2228
+ throw this.error(this.peek(), "Expected number after '-'.");
2229
+ }
2230
+ } else {
2231
+ throw this.error(this.peek(), `Expected ${context} value (identifier, string, number, or NULL).`);
2232
+ }
2233
+ }
2234
+ // If no '=' is found, value remains undefined (reading mode)
2235
+
2236
+ return { name: name.toLowerCase(), value };
2237
+ }
2238
+
2239
+ // --- Supporting Clause / Definition Parsers ---
2240
+
2241
+ /** @internal Parses a comma-separated list of indexed columns */
2242
+ private indexedColumnList(): AST.IndexedColumn[] {
2243
+ const columns: AST.IndexedColumn[] = [];
2244
+ do {
2245
+ columns.push(this.indexedColumn());
2246
+ } while (this.match(TokenType.COMMA));
2247
+ return columns;
2248
+ }
2249
+
2250
+ /** @internal Parses a single indexed column definition */
2251
+ private indexedColumn(): AST.IndexedColumn {
2252
+ const expr = this.expression();
2253
+
2254
+ let name: string | undefined;
2255
+ if (expr.type === 'column' && !expr.table && !expr.schema) {
2256
+ name = expr.name;
2257
+ }
2258
+
2259
+ let direction: 'asc' | 'desc' | undefined;
2260
+ if (this.match(TokenType.ASC)) {
2261
+ direction = 'asc';
2262
+ } else if (this.match(TokenType.DESC)) {
2263
+ direction = 'desc';
2264
+ }
2265
+
2266
+ if (name) {
2267
+ return { name, direction };
2268
+ } else {
2269
+ return { expr, direction };
2270
+ }
2271
+ }
2272
+
2273
+ /** @internal Helper to consume an IDENTIFIER token and return its lexeme */
2274
+ private consumeIdentifier(errorMessage: string): string;
2275
+ private consumeIdentifier(availableKeywords: string[], errorMessage: string): string;
2276
+ private consumeIdentifier(errorMessageOrKeywords: string | string[], errorMessage?: string): string {
2277
+ if (typeof errorMessageOrKeywords === 'string') {
2278
+ // Single parameter version - no contextual keywords
2279
+ return this.consumeIdentifierOrContextualKeyword([], errorMessageOrKeywords);
2280
+ } else {
2281
+ // Two parameter version - with contextual keywords
2282
+ return this.consumeIdentifierOrContextualKeyword(errorMessageOrKeywords, errorMessage!);
2283
+ }
2284
+ }
2285
+
2286
+ /**
2287
+ * @internal Helper to consume an IDENTIFIER token or specified contextual keywords
2288
+ * @param availableKeywords Array of keyword strings that can be used as identifiers in this context
2289
+ * @param errorMessage Error message if no valid token is found
2290
+ * @returns The lexeme of the consumed token
2291
+ */
2292
+ private consumeIdentifierOrContextualKeyword(availableKeywords: string[], errorMessage: string): string {
2293
+ const token = this.peek();
2294
+
2295
+ // First check for regular identifier
2296
+ if (this.check(TokenType.IDENTIFIER)) {
2297
+ return this.advance().lexeme;
2298
+ }
2299
+
2300
+ // Then check for available contextual keywords
2301
+ for (const keyword of availableKeywords) {
2302
+ const keywordUpper = keyword.toUpperCase();
2303
+ const expectedTokenType = TokenType[keywordUpper as keyof typeof TokenType];
2304
+
2305
+ if (expectedTokenType && token.type === expectedTokenType) {
2306
+ // This keyword token is available as an identifier in this context
2307
+ return this.advance().lexeme;
2308
+ }
2309
+ }
2310
+
2311
+ throw this.error(this.peek(), errorMessage);
2312
+ }
2313
+
2314
+ /**
2315
+ * @internal Helper to check if current token is an identifier or available contextual keyword
2316
+ */
2317
+ private checkIdentifierLike(availableKeywords: string[] = []): boolean {
2318
+ if (this.check(TokenType.IDENTIFIER)) {
2319
+ return true;
2320
+ }
2321
+
2322
+ return this.isContextualKeywordAvailable(availableKeywords);
2323
+ }
2324
+
2325
+ /**
2326
+ * @internal Helper to check if token at offset is an identifier or available contextual keyword
2327
+ */
2328
+ private checkIdentifierLikeAt(offset: number, availableKeywords: string[] = []): boolean {
2329
+ if (this.checkNext(offset, TokenType.IDENTIFIER)) {
2330
+ return true;
2331
+ }
2332
+
2333
+ if (this.current + offset >= this.tokens.length) return false;
2334
+ const token = this.tokens[this.current + offset];
2335
+
2336
+ for (const keyword of availableKeywords) {
2337
+ const keywordUpper = keyword.toUpperCase();
2338
+ const expectedTokenType = TokenType[keywordUpper as keyof typeof TokenType];
2339
+
2340
+ if (expectedTokenType && token.type === expectedTokenType) {
2341
+ return true;
2342
+ }
2343
+ }
2344
+
2345
+ return false;
2346
+ }
2347
+
2348
+ /**
2349
+ * @internal Helper to check if any of the specified contextual keywords are available at current position
2350
+ */
2351
+ private isContextualKeywordAvailable(availableKeywords: string[]): boolean {
2352
+ const token = this.peek();
2353
+
2354
+ for (const keyword of availableKeywords) {
2355
+ const keywordUpper = keyword.toUpperCase();
2356
+ const expectedTokenType = TokenType[keywordUpper as keyof typeof TokenType];
2357
+
2358
+ if (expectedTokenType && token.type === expectedTokenType) {
2359
+ return true;
2360
+ }
2361
+ }
2362
+
2363
+ return false;
2364
+ }
2365
+
2366
+ // --- Stubs for required helpers (implement fully for CREATE TABLE) ---
2367
+
2368
+ /** @internal Parses a column definition */
2369
+ private columnDefinition(): AST.ColumnDef {
2370
+ const name = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected column name.");
2371
+
2372
+ let dataType: string | undefined;
2373
+ if (this.check(TokenType.IDENTIFIER)) {
2374
+ dataType = this.advance().lexeme;
2375
+ if (this.match(TokenType.LPAREN)) {
2376
+ dataType += '(';
2377
+ let parenLevel = 1;
2378
+ while (parenLevel > 0 && !this.isAtEnd()) {
2379
+ const token = this.peek();
2380
+ if (token.type === TokenType.LPAREN) parenLevel++;
2381
+ if (token.type === TokenType.RPAREN) parenLevel--;
2382
+ if (parenLevel > 0) {
2383
+ dataType += this.advance().lexeme;
2384
+ }
2385
+ }
2386
+ dataType += ')';
2387
+ this.consume(TokenType.RPAREN, "Expected ')' after type parameters.");
2388
+ }
2389
+ }
2390
+
2391
+ const constraints = this.columnConstraintList();
2392
+
2393
+ return { name, dataType, constraints };
2394
+ }
2395
+
2396
+ /** @internal Parses column constraints */
2397
+ private columnConstraintList(): AST.ColumnConstraint[] {
2398
+ const constraints: AST.ColumnConstraint[] = [];
2399
+ while (this.isColumnConstraintStart()) {
2400
+ constraints.push(this.columnConstraint());
2401
+ }
2402
+ return constraints;
2403
+ }
2404
+
2405
+ /** @internal Checks if the current token can start a column constraint */
2406
+ private isColumnConstraintStart(): boolean {
2407
+ return this.check(TokenType.CONSTRAINT) ||
2408
+ this.check(TokenType.PRIMARY) ||
2409
+ this.check(TokenType.NOT) ||
2410
+ this.check(TokenType.NULL) ||
2411
+ this.check(TokenType.UNIQUE) ||
2412
+ this.check(TokenType.CHECK) ||
2413
+ this.check(TokenType.DEFAULT) ||
2414
+ this.check(TokenType.COLLATE) ||
2415
+ this.check(TokenType.REFERENCES) ||
2416
+ this.check(TokenType.GENERATED);
2417
+ }
2418
+
2419
+ /** @internal Parses a single column constraint */
2420
+ private columnConstraint(): AST.ColumnConstraint {
2421
+ let name: string | undefined;
2422
+ const startToken = this.peek(); // Capture start token
2423
+ let endToken = startToken; // Initialize end token
2424
+
2425
+ if (this.match(TokenType.CONSTRAINT)) {
2426
+ name = this.consumeIdentifier("Expected constraint name after CONSTRAINT.");
2427
+ endToken = this.previous();
2428
+ }
2429
+
2430
+ if (this.match(TokenType.PRIMARY)) {
2431
+ this.consume(TokenType.KEY, "Expected KEY after PRIMARY.");
2432
+ const direction = this.match(TokenType.ASC) ? 'asc' : this.match(TokenType.DESC) ? 'desc' : undefined;
2433
+ if (direction) endToken = this.previous();
2434
+ const onConflict = this.parseConflictClause();
2435
+ if (onConflict) endToken = this.previous(); // Update endToken if conflict clause was parsed
2436
+ const autoincrement = this.match(TokenType.AUTOINCREMENT);
2437
+ if (autoincrement) endToken = this.previous();
2438
+ return { type: 'primaryKey', name, onConflict, autoincrement, direction, loc: _createLoc(startToken, endToken) };
2439
+ } else if (this.match(TokenType.NOT)) {
2440
+ this.consume(TokenType.NULL, "Expected NULL after NOT.");
2441
+ endToken = this.previous();
2442
+ const onConflict = this.parseConflictClause();
2443
+ if (onConflict) endToken = this.previous(); // Update endToken if conflict clause was parsed
2444
+ return { type: 'notNull', name, onConflict, loc: _createLoc(startToken, endToken) };
2445
+ } else if (this.match(TokenType.NULL)) {
2446
+ endToken = this.previous();
2447
+ const onConflict = this.parseConflictClause();
2448
+ if (onConflict) endToken = this.previous(); // Update endToken if conflict clause was parsed
2449
+ return { type: 'null', name, onConflict, loc: _createLoc(startToken, endToken) };
2450
+ } else if (this.match(TokenType.UNIQUE)) {
2451
+ endToken = this.previous();
2452
+ const onConflict = this.parseConflictClause();
2453
+ if (onConflict) endToken = this.previous(); // Update endToken if conflict clause was parsed
2454
+ return { type: 'unique', name, onConflict, loc: _createLoc(startToken, endToken) };
2455
+ } else if (this.match(TokenType.CHECK)) {
2456
+ // --- Parse optional ON clause before parentheses --- //
2457
+ let operations: AST.RowOp[] | undefined;
2458
+ if (this.matchKeyword('ON')) {
2459
+ operations = this.parseRowOpList();
2460
+ }
2461
+ // --- End Parse ON clause --- //
2462
+ this.consume(TokenType.LPAREN, "Expected '(' after CHECK.");
2463
+ const expr = this.expression();
2464
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after CHECK expression.");
2465
+ return { type: 'check', name, expr, operations, loc: _createLoc(startToken, endToken) };
2466
+ } else if (this.match(TokenType.DEFAULT)) {
2467
+ const expr = this.expression();
2468
+ endToken = this.previous();
2469
+ return { type: 'default', name, expr, loc: _createLoc(startToken, endToken) };
2470
+ } else if (this.match(TokenType.COLLATE)) {
2471
+ if (!this.check(TokenType.IDENTIFIER)) {
2472
+ throw this.error(this.peek(), "Expected collation name after COLLATE.");
2473
+ }
2474
+ const collation = this.advance().lexeme;
2475
+ endToken = this.previous();
2476
+ return { type: 'collate', name, collation, loc: _createLoc(startToken, endToken) };
2477
+ } else if (this.match(TokenType.REFERENCES)) {
2478
+ const fkClause = this.foreignKeyClause();
2479
+ endToken = this.previous(); // End token is end of FK clause
2480
+ return { type: 'foreignKey', name, foreignKey: fkClause, loc: _createLoc(startToken, endToken) };
2481
+ } else if (this.match(TokenType.GENERATED)) {
2482
+ this.consume(TokenType.ALWAYS, "Expected ALWAYS after GENERATED.");
2483
+ this.consume(TokenType.AS, "Expected AS after GENERATED ALWAYS.");
2484
+ this.consume(TokenType.LPAREN, "Expected '(' after AS.");
2485
+ const expr = this.expression();
2486
+ this.consume(TokenType.RPAREN, "Expected ')' after generated expression.");
2487
+ endToken = this.previous();
2488
+ let stored = false;
2489
+ if (this.match(TokenType.STORED)) {
2490
+ stored = true;
2491
+ endToken = this.previous();
2492
+ } else if (this.match(TokenType.VIRTUAL)) {
2493
+ endToken = this.previous();
2494
+ }
2495
+ return { type: 'generated', name, generated: { expr, stored }, loc: _createLoc(startToken, endToken) };
2496
+ }
2497
+
2498
+ throw this.error(this.peek(), "Expected column constraint type (PRIMARY KEY, NOT NULL, UNIQUE, CHECK, DEFAULT, COLLATE, REFERENCES, GENERATED).");
2499
+ }
2500
+
2501
+ /** @internal Parses a table constraint */
2502
+ private tableConstraint(): AST.TableConstraint {
2503
+ let name: string | undefined;
2504
+ const startToken = this.peek(); // Capture start token
2505
+ let endToken = startToken; // Initialize end token
2506
+
2507
+ if (this.match(TokenType.CONSTRAINT)) {
2508
+ name = this.consumeIdentifier("Expected constraint name after CONSTRAINT.");
2509
+ endToken = this.previous();
2510
+ }
2511
+
2512
+ if (this.match(TokenType.PRIMARY)) {
2513
+ this.consume(TokenType.KEY, "Expected KEY after PRIMARY.");
2514
+ this.consume(TokenType.LPAREN, "Expected '(' before PRIMARY KEY columns.");
2515
+
2516
+ // Handle empty PRIMARY KEY () for singleton tables (Third Manifesto feature)
2517
+ let columns: { name: string; direction?: 'asc' | 'desc' }[] = [];
2518
+ if (!this.check(TokenType.RPAREN)) {
2519
+ columns = this.identifierListWithDirection();
2520
+ }
2521
+
2522
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after PRIMARY KEY columns.");
2523
+ const onConflict = this.parseConflictClause();
2524
+ if (onConflict) endToken = this.previous();
2525
+ return { type: 'primaryKey', name, columns, onConflict, loc: _createLoc(startToken, endToken) };
2526
+ } else if (this.match(TokenType.UNIQUE)) {
2527
+ this.consume(TokenType.LPAREN, "Expected '(' before UNIQUE columns.");
2528
+ const columnsSimple = this.identifierList();
2529
+ const columns = columnsSimple.map(name => ({ name }));
2530
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after UNIQUE columns.");
2531
+ const onConflict = this.parseConflictClause();
2532
+ if (onConflict) endToken = this.previous();
2533
+ return { type: 'unique', name, columns, onConflict, loc: _createLoc(startToken, endToken) };
2534
+ } else if (this.match(TokenType.CHECK)) {
2535
+ // --- Parse optional ON clause before parentheses --- //
2536
+ let operations: AST.RowOp[] | undefined;
2537
+ if (this.matchKeyword('ON')) {
2538
+ operations = this.parseRowOpList();
2539
+ }
2540
+ // --- End Parse ON clause --- //
2541
+ this.consume(TokenType.LPAREN, "Expected '(' after CHECK.");
2542
+ const expr = this.expression();
2543
+ endToken = this.consume(TokenType.RPAREN, "Expected ')' after CHECK expression.");
2544
+ return { type: 'check', name, expr, operations, loc: _createLoc(startToken, endToken) };
2545
+ } else if (this.match(TokenType.FOREIGN)) {
2546
+ this.consume(TokenType.KEY, "Expected KEY after FOREIGN.");
2547
+ this.consume(TokenType.LPAREN, "Expected '(' before FOREIGN KEY columns.");
2548
+ const columns = this.identifierList().map(name => ({ name }));
2549
+ this.consume(TokenType.RPAREN, "Expected ')' after FOREIGN KEY columns.");
2550
+ const fkClause = this.foreignKeyClause();
2551
+ endToken = this.previous(); // End token is end of FK clause
2552
+ return { type: 'foreignKey', name, columns, foreignKey: fkClause, loc: _createLoc(startToken, endToken) };
2553
+ }
2554
+
2555
+ throw this.error(this.peek(), "Expected table constraint type (PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY).");
2556
+ }
2557
+
2558
+ /** @internal Parses a foreign key clause */
2559
+ private foreignKeyClause(): AST.ForeignKeyClause {
2560
+ this.consume(TokenType.REFERENCES, "Expected REFERENCES for foreign key.");
2561
+ const table = this.consumeIdentifier("Expected foreign table name.");
2562
+ let columns: string[] | undefined;
2563
+ if (this.match(TokenType.LPAREN)) {
2564
+ columns = this.identifierList();
2565
+ this.consume(TokenType.RPAREN, "Expected ')' after foreign columns.");
2566
+ }
2567
+
2568
+ let onDelete: AST.ForeignKeyAction | undefined;
2569
+ let onUpdate: AST.ForeignKeyAction | undefined;
2570
+ let deferrable: boolean | undefined;
2571
+ let initiallyDeferred: boolean | undefined;
2572
+
2573
+ while (this.check(TokenType.ON) || this.check(TokenType.DEFERRABLE) || this.check(TokenType.NOT)) {
2574
+ if (this.match(TokenType.ON)) {
2575
+ if (this.match(TokenType.DELETE)) {
2576
+ onDelete = this.parseForeignKeyAction();
2577
+ } else if (this.match(TokenType.UPDATE)) {
2578
+ onUpdate = this.parseForeignKeyAction();
2579
+ } else {
2580
+ throw this.error(this.peek(), "Expected DELETE or UPDATE after ON.");
2581
+ }
2582
+ } else if (this.match(TokenType.DEFERRABLE)) {
2583
+ deferrable = true;
2584
+ if (this.match(TokenType.INITIALLY)) {
2585
+ if (this.match(TokenType.DEFERRED)) {
2586
+ initiallyDeferred = true;
2587
+ } else if (this.match(TokenType.IMMEDIATE)) {
2588
+ initiallyDeferred = false;
2589
+ } else {
2590
+ throw this.error(this.peek(), "Expected DEFERRED or IMMEDIATE after INITIALLY.");
2591
+ }
2592
+ }
2593
+ } else if (this.match(TokenType.NOT)) {
2594
+ this.consume(TokenType.DEFERRABLE, "Expected DEFERRABLE after NOT.");
2595
+ deferrable = false;
2596
+ if (this.match(TokenType.INITIALLY)) {
2597
+ if (this.match(TokenType.DEFERRED)) {
2598
+ initiallyDeferred = true;
2599
+ } else if (this.match(TokenType.IMMEDIATE)) {
2600
+ initiallyDeferred = false;
2601
+ } else {
2602
+ throw this.error(this.peek(), "Expected DEFERRED or IMMEDIATE after INITIALLY.");
2603
+ }
2604
+ }
2605
+ } else {
2606
+ break;
2607
+ }
2608
+ }
2609
+
2610
+ return { table, columns, onDelete, onUpdate, deferrable, initiallyDeferred };
2611
+ }
2612
+
2613
+ /** @internal Parses the ON CONFLICT clause */
2614
+ private parseConflictClause(): ConflictResolution | undefined {
2615
+ if (this.match(TokenType.ON)) {
2616
+ this.consume(TokenType.CONFLICT, "Expected CONFLICT after ON.");
2617
+ if (this.match(TokenType.ROLLBACK)) return ConflictResolution.ROLLBACK;
2618
+ if (this.match(TokenType.ABORT)) return ConflictResolution.ABORT;
2619
+ if (this.match(TokenType.FAIL)) return ConflictResolution.FAIL;
2620
+ if (this.match(TokenType.IGNORE)) return ConflictResolution.IGNORE;
2621
+ if (this.match(TokenType.REPLACE)) return ConflictResolution.REPLACE;
2622
+ throw this.error(this.peek(), "Expected conflict resolution algorithm (ROLLBACK, ABORT, FAIL, IGNORE, REPLACE).");
2623
+ }
2624
+ return undefined;
2625
+ }
2626
+
2627
+ /** @internal Parses the foreign key action */
2628
+ private parseForeignKeyAction(): AST.ForeignKeyAction {
2629
+ if (this.match(TokenType.SET)) {
2630
+ if (this.match(TokenType.NULL)) return 'setNull';
2631
+ if (this.match(TokenType.DEFAULT)) return 'setDefault';
2632
+ throw this.error(this.peek(), "Expected NULL or DEFAULT after SET.");
2633
+ } else if (this.match(TokenType.CASCADE)) {
2634
+ return 'cascade';
2635
+ } else if (this.match(TokenType.RESTRICT)) {
2636
+ return 'restrict';
2637
+ } else if (this.match(TokenType.NO)) {
2638
+ this.consume(TokenType.ACTION, "Expected ACTION after NO.");
2639
+ return 'noAction';
2640
+ }
2641
+ throw this.error(this.peek(), "Expected foreign key action (SET NULL, SET DEFAULT, CASCADE, RESTRICT, NO ACTION).");
2642
+ }
2643
+
2644
+ /** @internal Parses a comma-separated list of identifiers, optionally with ASC/DESC */
2645
+ private identifierList(): string[] {
2646
+ const identifiers: string[] = [];
2647
+ do {
2648
+ identifiers.push(this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected identifier in list."));
2649
+ } while (this.match(TokenType.COMMA));
2650
+ return identifiers;
2651
+ }
2652
+
2653
+ /** @internal Parses a comma-separated list of identifiers, optionally with ASC/DESC */
2654
+ private identifierListWithDirection(): { name: string; direction?: 'asc' | 'desc' }[] {
2655
+ const identifiers: { name: string; direction?: 'asc' | 'desc' }[] = [];
2656
+ do {
2657
+ const name = this.consumeIdentifier(['key', 'action', 'set', 'default', 'check', 'unique', 'references', 'on', 'cascade', 'restrict', 'like'], "Expected identifier in list.");
2658
+ const direction = this.match(TokenType.ASC) ? 'asc' : this.match(TokenType.DESC) ? 'desc' : undefined;
2659
+ identifiers.push({ name, direction });
2660
+ } while (this.match(TokenType.COMMA));
2661
+ return identifiers;
2662
+ }
2663
+
2664
+ // --- Helper method to peek keywords case-insensitively ---
2665
+ private peekKeyword(keyword: string): boolean {
2666
+ if (this.isAtEnd()) return false;
2667
+ const token = this.peek();
2668
+
2669
+ // The keyword lookup string should be uppercase to match TokenType enum keys (e.g., TokenType.SELECT)
2670
+ const keywordKey = keyword.toUpperCase();
2671
+ const expectedTokenType = TokenType[keywordKey as keyof typeof TokenType];
2672
+
2673
+ // Check if the current token's type is the expected specific keyword TokenType.
2674
+ // This assumes the lexer has already correctly typed true keywords.
2675
+ if (expectedTokenType !== undefined && token.type === expectedTokenType) {
2676
+ return true;
2677
+ }
2678
+
2679
+ // Fallback: if the token is a generic IDENTIFIER, check if its lexeme matches the keyword.
2680
+ // This handles contextual keywords like FIRST, LAST that aren't reserved keywords.
2681
+ if (token.type === TokenType.IDENTIFIER && token.lexeme.toUpperCase() === keywordKey) {
2682
+ return true;
2683
+ }
2684
+
2685
+ return false;
2686
+ }
2687
+
2688
+ // --- Helper method to match keywords case-insensitively ---
2689
+ private matchKeyword(keyword: string): boolean {
2690
+ if (this.isAtEnd()) return false;
2691
+ if (this.peekKeyword(keyword)) {
2692
+ this.advance();
2693
+ return true;
2694
+ }
2695
+ return false;
2696
+ }
2697
+
2698
+ // --- Helper method to consume keywords case-insensitively ---
2699
+ private consumeKeyword(keyword: string, message: string): Token {
2700
+ if (this.peekKeyword(keyword)) {
2701
+ return this.advance();
2702
+ }
2703
+ throw this.error(this.peek(), message);
2704
+ }
2705
+
2706
+ /** Parses the list of operations for CHECK ON */
2707
+ private parseRowOpList(): AST.RowOp[] {
2708
+ const operations: AST.RowOp[] = [];
2709
+
2710
+ // Parse operations in a comma-separated list
2711
+ do {
2712
+ if (this.match(TokenType.INSERT)) {
2713
+ operations.push('insert');
2714
+ } else if (this.match(TokenType.UPDATE)) {
2715
+ operations.push('update');
2716
+ } else if (this.match(TokenType.DELETE)) {
2717
+ operations.push('delete');
2718
+ } else {
2719
+ throw this.error(this.peek(), "Expected INSERT, UPDATE, or DELETE after ON.");
2720
+ }
2721
+ } while (this.match(TokenType.COMMA));
2722
+
2723
+ // Optional: Check for duplicates? The design allows them but ignores them.
2724
+ return operations;
2725
+ }
2726
+
2727
+ /**
2728
+ * Parses a CASE expression
2729
+ * CASE [base_expr] WHEN cond THEN result ... [ELSE else_result] END
2730
+ * CASE WHEN cond THEN result ... [ELSE else_result] END
2731
+ */
2732
+ private parseCaseExpression(startToken: Token): AST.CaseExpr {
2733
+ let baseExpr: AST.Expression | undefined;
2734
+ const whenThenClauses: AST.CaseExprWhenThenClause[] = [];
2735
+ let elseExpr: AST.Expression | undefined;
2736
+ let endToken = startToken; // Initialize with CASE token
2737
+
2738
+ // Check if it's CASE expr WHEN ... or CASE WHEN ...
2739
+ if (!this.peekKeyword('WHEN')) { // Changed from checkKeyword
2740
+ baseExpr = this.expression();
2741
+ }
2742
+
2743
+ while (this.matchKeyword('WHEN')) {
2744
+ const whenCondition = this.expression();
2745
+ this.consumeKeyword('THEN', "Expected 'THEN' after WHEN condition in CASE expression.");
2746
+ const thenResult = this.expression();
2747
+ whenThenClauses.push({ when: whenCondition, then: thenResult });
2748
+ endToken = this.previous(); // Update endToken to the end of the THEN expression
2749
+ }
2750
+
2751
+ if (whenThenClauses.length === 0) {
2752
+ throw this.error(this.peek(), "CASE expression must have at least one WHEN clause.");
2753
+ }
2754
+
2755
+ if (this.matchKeyword('ELSE')) {
2756
+ elseExpr = this.expression();
2757
+ endToken = this.previous(); // Update endToken to the end of the ELSE expression
2758
+ }
2759
+
2760
+ endToken = this.consumeKeyword('END', "Expected 'END' to terminate CASE expression.");
2761
+
2762
+ return {
2763
+ type: 'case',
2764
+ baseExpr,
2765
+ whenThenClauses,
2766
+ elseExpr,
2767
+ loc: _createLoc(startToken, endToken),
2768
+ };
2769
+ }
2770
+
2771
+ // Helper to check if a token lexeme is a common type name keyword for CAST
2772
+ private isTypeNameKeyword(lexeme: string): boolean {
2773
+ const typeKeywords = ['TEXT', 'INTEGER', 'REAL', 'BLOB', 'NUMERIC', 'VARCHAR', 'CHAR', 'DATE', 'DATETIME', 'BOOLEAN', 'INT'];
2774
+ return typeKeywords.includes(lexeme.toUpperCase());
2775
+ }
2776
+
2777
+ private statementSupportsWithClause(statement: AST.AstNode): boolean {
2778
+ return statement.type === 'select' ||
2779
+ statement.type === 'insert' ||
2780
+ statement.type === 'update' ||
2781
+ statement.type === 'delete';
2782
+ }
2783
+ }