@quereus/quereus 0.2.1 → 0.4.5

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 (760) hide show
  1. package/README.md +12 -1
  2. package/dist/src/common/errors.js.map +1 -1
  3. package/dist/src/common/json-types.d.ts +11 -0
  4. package/dist/src/common/json-types.d.ts.map +1 -0
  5. package/dist/src/common/json-types.js +3 -0
  6. package/dist/src/common/json-types.js.map +1 -0
  7. package/dist/src/common/types.d.ts +1 -0
  8. package/dist/src/common/types.d.ts.map +1 -1
  9. package/dist/src/core/database-options.d.ts +2 -2
  10. package/dist/src/core/database-options.d.ts.map +1 -1
  11. package/dist/src/core/database-options.js.map +1 -1
  12. package/dist/src/core/database.d.ts +61 -14
  13. package/dist/src/core/database.d.ts.map +1 -1
  14. package/dist/src/core/database.js +481 -54
  15. package/dist/src/core/database.js.map +1 -1
  16. package/dist/src/core/statement.d.ts.map +1 -1
  17. package/dist/src/core/statement.js +3 -1
  18. package/dist/src/core/statement.js.map +1 -1
  19. package/dist/src/func/builtins/builtin-window-functions.d.ts.map +1 -1
  20. package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
  21. package/dist/src/func/builtins/datetime.d.ts +2 -0
  22. package/dist/src/func/builtins/datetime.d.ts.map +1 -1
  23. package/dist/src/func/builtins/datetime.js +39 -0
  24. package/dist/src/func/builtins/datetime.js.map +1 -1
  25. package/dist/src/func/builtins/explain.d.ts +1 -0
  26. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  27. package/dist/src/func/builtins/explain.js +159 -36
  28. package/dist/src/func/builtins/explain.js.map +1 -1
  29. package/dist/src/func/builtins/index.d.ts.map +1 -1
  30. package/dist/src/func/builtins/index.js +5 -2
  31. package/dist/src/func/builtins/index.js.map +1 -1
  32. package/dist/src/func/builtins/json-helpers.d.ts +8 -8
  33. package/dist/src/func/builtins/json-helpers.d.ts.map +1 -1
  34. package/dist/src/func/builtins/json-helpers.js +3 -3
  35. package/dist/src/func/builtins/json-helpers.js.map +1 -1
  36. package/dist/src/func/builtins/json-tvf.d.ts.map +1 -1
  37. package/dist/src/func/builtins/json-tvf.js +1 -1
  38. package/dist/src/func/builtins/json-tvf.js.map +1 -1
  39. package/dist/src/func/builtins/json.d.ts.map +1 -1
  40. package/dist/src/func/builtins/json.js +3 -2
  41. package/dist/src/func/builtins/json.js.map +1 -1
  42. package/dist/src/func/builtins/schema.d.ts.map +1 -1
  43. package/dist/src/func/builtins/schema.js +22 -1
  44. package/dist/src/func/builtins/schema.js.map +1 -1
  45. package/dist/src/func/context.d.ts.map +1 -1
  46. package/dist/src/func/context.js +5 -0
  47. package/dist/src/func/context.js.map +1 -1
  48. package/dist/src/func/registration.d.ts +2 -1
  49. package/dist/src/func/registration.d.ts.map +1 -1
  50. package/dist/src/func/registration.js.map +1 -1
  51. package/dist/src/index.d.ts +2 -2
  52. package/dist/src/index.d.ts.map +1 -1
  53. package/dist/src/index.js +2 -2
  54. package/dist/src/index.js.map +1 -1
  55. package/dist/src/parser/ast.d.ts +83 -4
  56. package/dist/src/parser/ast.d.ts.map +1 -1
  57. package/dist/src/parser/lexer.d.ts +11 -0
  58. package/dist/src/parser/lexer.d.ts.map +1 -1
  59. package/dist/src/parser/lexer.js +29 -21
  60. package/dist/src/parser/lexer.js.map +1 -1
  61. package/dist/src/parser/parser.d.ts +16 -0
  62. package/dist/src/parser/parser.d.ts.map +1 -1
  63. package/dist/src/parser/parser.js +542 -26
  64. package/dist/src/parser/parser.js.map +1 -1
  65. package/dist/src/parser/visitor.d.ts.map +1 -1
  66. package/dist/src/parser/visitor.js +1 -0
  67. package/dist/src/parser/visitor.js.map +1 -1
  68. package/dist/src/planner/analysis/binding-collector.d.ts +5 -0
  69. package/dist/src/planner/analysis/binding-collector.d.ts.map +1 -0
  70. package/dist/src/planner/analysis/binding-collector.js +73 -0
  71. package/dist/src/planner/analysis/binding-collector.js.map +1 -0
  72. package/dist/src/planner/analysis/const-evaluator.js +1 -1
  73. package/dist/src/planner/analysis/const-evaluator.js.map +1 -1
  74. package/dist/src/planner/analysis/const-pass.d.ts.map +1 -1
  75. package/dist/src/planner/analysis/const-pass.js +1 -1
  76. package/dist/src/planner/analysis/const-pass.js.map +1 -1
  77. package/dist/src/planner/analysis/constraint-extractor.d.ts +67 -31
  78. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  79. package/dist/src/planner/analysis/constraint-extractor.js +513 -84
  80. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  81. package/dist/src/planner/analysis/predicate-normalizer.d.ts +17 -0
  82. package/dist/src/planner/analysis/predicate-normalizer.d.ts.map +1 -0
  83. package/dist/src/planner/analysis/predicate-normalizer.js +222 -0
  84. package/dist/src/planner/analysis/predicate-normalizer.js.map +1 -0
  85. package/dist/src/planner/building/alter-table.d.ts.map +1 -1
  86. package/dist/src/planner/building/alter-table.js +5 -2
  87. package/dist/src/planner/building/alter-table.js.map +1 -1
  88. package/dist/src/planner/building/block.d.ts.map +1 -1
  89. package/dist/src/planner/building/block.js +16 -0
  90. package/dist/src/planner/building/block.js.map +1 -1
  91. package/dist/src/planner/building/constraint-builder.d.ts +1 -1
  92. package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
  93. package/dist/src/planner/building/constraint-builder.js +52 -3
  94. package/dist/src/planner/building/constraint-builder.js.map +1 -1
  95. package/dist/src/planner/building/create-assertion.d.ts +5 -0
  96. package/dist/src/planner/building/create-assertion.d.ts.map +1 -0
  97. package/dist/src/planner/building/create-assertion.js +5 -0
  98. package/dist/src/planner/building/create-assertion.js.map +1 -0
  99. package/dist/src/planner/building/declare-schema.d.ts +8 -0
  100. package/dist/src/planner/building/declare-schema.d.ts.map +1 -0
  101. package/dist/src/planner/building/declare-schema.js +14 -0
  102. package/dist/src/planner/building/declare-schema.js.map +1 -0
  103. package/dist/src/planner/building/delete.d.ts.map +1 -1
  104. package/dist/src/planner/building/delete.js +37 -5
  105. package/dist/src/planner/building/delete.js.map +1 -1
  106. package/dist/src/planner/building/drop-assertion.d.ts +5 -0
  107. package/dist/src/planner/building/drop-assertion.d.ts.map +1 -0
  108. package/dist/src/planner/building/drop-assertion.js +8 -0
  109. package/dist/src/planner/building/drop-assertion.js.map +1 -0
  110. package/dist/src/planner/building/expression.d.ts.map +1 -1
  111. package/dist/src/planner/building/expression.js +1 -0
  112. package/dist/src/planner/building/expression.js.map +1 -1
  113. package/dist/src/planner/building/function-call.d.ts.map +1 -1
  114. package/dist/src/planner/building/function-call.js +2 -1
  115. package/dist/src/planner/building/function-call.js.map +1 -1
  116. package/dist/src/planner/building/insert.d.ts.map +1 -1
  117. package/dist/src/planner/building/insert.js +67 -10
  118. package/dist/src/planner/building/insert.js.map +1 -1
  119. package/dist/src/planner/building/pragma.d.ts.map +1 -1
  120. package/dist/src/planner/building/pragma.js +1 -0
  121. package/dist/src/planner/building/pragma.js.map +1 -1
  122. package/dist/src/planner/building/schema-resolution.d.ts +2 -2
  123. package/dist/src/planner/building/schema-resolution.d.ts.map +1 -1
  124. package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
  125. package/dist/src/planner/building/select-aggregates.js +3 -2
  126. package/dist/src/planner/building/select-aggregates.js.map +1 -1
  127. package/dist/src/planner/building/select-compound.d.ts +2 -2
  128. package/dist/src/planner/building/select-compound.d.ts.map +1 -1
  129. package/dist/src/planner/building/select-compound.js +10 -1
  130. package/dist/src/planner/building/select-compound.js.map +1 -1
  131. package/dist/src/planner/building/select-context.d.ts +3 -3
  132. package/dist/src/planner/building/select-context.d.ts.map +1 -1
  133. package/dist/src/planner/building/select-context.js.map +1 -1
  134. package/dist/src/planner/building/select-modifiers.d.ts +6 -5
  135. package/dist/src/planner/building/select-modifiers.d.ts.map +1 -1
  136. package/dist/src/planner/building/select-modifiers.js +5 -4
  137. package/dist/src/planner/building/select-modifiers.js.map +1 -1
  138. package/dist/src/planner/building/select-projections.d.ts.map +1 -1
  139. package/dist/src/planner/building/select-projections.js +4 -5
  140. package/dist/src/planner/building/select-projections.js.map +1 -1
  141. package/dist/src/planner/building/select-window.d.ts.map +1 -1
  142. package/dist/src/planner/building/select-window.js +6 -3
  143. package/dist/src/planner/building/select-window.js.map +1 -1
  144. package/dist/src/planner/building/select.d.ts +3 -3
  145. package/dist/src/planner/building/select.d.ts.map +1 -1
  146. package/dist/src/planner/building/select.js +18 -8
  147. package/dist/src/planner/building/select.js.map +1 -1
  148. package/dist/src/planner/building/table-function.d.ts.map +1 -1
  149. package/dist/src/planner/building/table-function.js +1 -1
  150. package/dist/src/planner/building/table-function.js.map +1 -1
  151. package/dist/src/planner/building/table.d.ts +5 -3
  152. package/dist/src/planner/building/table.d.ts.map +1 -1
  153. package/dist/src/planner/building/table.js +7 -2
  154. package/dist/src/planner/building/table.js.map +1 -1
  155. package/dist/src/planner/building/update.d.ts.map +1 -1
  156. package/dist/src/planner/building/update.js +38 -6
  157. package/dist/src/planner/building/update.js.map +1 -1
  158. package/dist/src/planner/building/with.d.ts +3 -3
  159. package/dist/src/planner/building/with.d.ts.map +1 -1
  160. package/dist/src/planner/building/with.js.map +1 -1
  161. package/dist/src/planner/debug.d.ts.map +1 -1
  162. package/dist/src/planner/debug.js.map +1 -1
  163. package/dist/src/planner/framework/characteristics.d.ts +235 -0
  164. package/dist/src/planner/framework/characteristics.d.ts.map +1 -0
  165. package/dist/src/planner/framework/characteristics.js +299 -0
  166. package/dist/src/planner/framework/characteristics.js.map +1 -0
  167. package/dist/src/planner/framework/context.d.ts +16 -5
  168. package/dist/src/planner/framework/context.d.ts.map +1 -1
  169. package/dist/src/planner/framework/context.js +2 -0
  170. package/dist/src/planner/framework/context.js.map +1 -1
  171. package/dist/src/planner/framework/pass.d.ts +116 -0
  172. package/dist/src/planner/framework/pass.d.ts.map +1 -0
  173. package/dist/src/planner/framework/pass.js +236 -0
  174. package/dist/src/planner/framework/pass.js.map +1 -0
  175. package/dist/src/planner/nodes/aggregate-node.d.ts +16 -6
  176. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  177. package/dist/src/planner/nodes/aggregate-node.js +40 -4
  178. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  179. package/dist/src/planner/nodes/array-index-node.js.map +1 -1
  180. package/dist/src/planner/nodes/cache-node.d.ts +5 -2
  181. package/dist/src/planner/nodes/cache-node.d.ts.map +1 -1
  182. package/dist/src/planner/nodes/cache-node.js +6 -0
  183. package/dist/src/planner/nodes/cache-node.js.map +1 -1
  184. package/dist/src/planner/nodes/constraint-check-node.d.ts +10 -2
  185. package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
  186. package/dist/src/planner/nodes/constraint-check-node.js +12 -4
  187. package/dist/src/planner/nodes/constraint-check-node.js.map +1 -1
  188. package/dist/src/planner/nodes/create-assertion-node.d.ts +22 -0
  189. package/dist/src/planner/nodes/create-assertion-node.d.ts.map +1 -0
  190. package/dist/src/planner/nodes/create-assertion-node.js +41 -0
  191. package/dist/src/planner/nodes/create-assertion-node.js.map +1 -0
  192. package/dist/src/planner/nodes/create-index-node.js +2 -2
  193. package/dist/src/planner/nodes/create-index-node.js.map +1 -1
  194. package/dist/src/planner/nodes/create-table-node.js +2 -2
  195. package/dist/src/planner/nodes/create-table-node.js.map +1 -1
  196. package/dist/src/planner/nodes/cte-node.d.ts +17 -2
  197. package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
  198. package/dist/src/planner/nodes/cte-node.js +9 -1
  199. package/dist/src/planner/nodes/cte-node.js.map +1 -1
  200. package/dist/src/planner/nodes/cte-reference-node.js +1 -1
  201. package/dist/src/planner/nodes/cte-reference-node.js.map +1 -1
  202. package/dist/src/planner/nodes/declarative-schema.d.ts +62 -0
  203. package/dist/src/planner/nodes/declarative-schema.d.ts.map +1 -0
  204. package/dist/src/planner/nodes/declarative-schema.js +181 -0
  205. package/dist/src/planner/nodes/declarative-schema.js.map +1 -0
  206. package/dist/src/planner/nodes/delete-node.d.ts +8 -3
  207. package/dist/src/planner/nodes/delete-node.d.ts.map +1 -1
  208. package/dist/src/planner/nodes/delete-node.js +10 -2
  209. package/dist/src/planner/nodes/delete-node.js.map +1 -1
  210. package/dist/src/planner/nodes/distinct-node.d.ts +3 -2
  211. package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
  212. package/dist/src/planner/nodes/distinct-node.js +17 -4
  213. package/dist/src/planner/nodes/distinct-node.js.map +1 -1
  214. package/dist/src/planner/nodes/dml-executor-node.d.ts +1 -1
  215. package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
  216. package/dist/src/planner/nodes/drop-assertion-node.d.ts +21 -0
  217. package/dist/src/planner/nodes/drop-assertion-node.d.ts.map +1 -0
  218. package/dist/src/planner/nodes/drop-assertion-node.js +41 -0
  219. package/dist/src/planner/nodes/drop-assertion-node.js.map +1 -0
  220. package/dist/src/planner/nodes/drop-table-node.d.ts.map +1 -1
  221. package/dist/src/planner/nodes/drop-table-node.js +1 -0
  222. package/dist/src/planner/nodes/drop-table-node.js.map +1 -1
  223. package/dist/src/planner/nodes/filter.d.ts +8 -3
  224. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  225. package/dist/src/planner/nodes/filter.js +44 -0
  226. package/dist/src/planner/nodes/filter.js.map +1 -1
  227. package/dist/src/planner/nodes/insert-node.d.ts +9 -3
  228. package/dist/src/planner/nodes/insert-node.d.ts.map +1 -1
  229. package/dist/src/planner/nodes/insert-node.js +11 -2
  230. package/dist/src/planner/nodes/insert-node.js.map +1 -1
  231. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts +3 -4
  232. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts.map +1 -1
  233. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js +1 -16
  234. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js.map +1 -1
  235. package/dist/src/planner/nodes/join-node.d.ts +12 -3
  236. package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
  237. package/dist/src/planner/nodes/join-node.js +111 -2
  238. package/dist/src/planner/nodes/join-node.js.map +1 -1
  239. package/dist/src/planner/nodes/limit-offset.d.ts +7 -3
  240. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  241. package/dist/src/planner/nodes/limit-offset.js +15 -0
  242. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  243. package/dist/src/planner/nodes/plan-node-type.d.ts +8 -0
  244. package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
  245. package/dist/src/planner/nodes/plan-node-type.js +8 -0
  246. package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
  247. package/dist/src/planner/nodes/plan-node.d.ts +9 -9
  248. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  249. package/dist/src/planner/nodes/plan-node.js +3 -3
  250. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  251. package/dist/src/planner/nodes/pragma.d.ts +2 -1
  252. package/dist/src/planner/nodes/pragma.d.ts.map +1 -1
  253. package/dist/src/planner/nodes/pragma.js +3 -1
  254. package/dist/src/planner/nodes/pragma.js.map +1 -1
  255. package/dist/src/planner/nodes/project-node.d.ts +16 -3
  256. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  257. package/dist/src/planner/nodes/project-node.js +82 -2
  258. package/dist/src/planner/nodes/project-node.js.map +1 -1
  259. package/dist/src/planner/nodes/recursive-cte-node.d.ts +2 -2
  260. package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -1
  261. package/dist/src/planner/nodes/recursive-cte-node.js +1 -1
  262. package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -1
  263. package/dist/src/planner/nodes/reference.d.ts +13 -4
  264. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  265. package/dist/src/planner/nodes/reference.js +16 -0
  266. package/dist/src/planner/nodes/reference.js.map +1 -1
  267. package/dist/src/planner/nodes/remote-query-node.d.ts +37 -0
  268. package/dist/src/planner/nodes/remote-query-node.d.ts.map +1 -0
  269. package/dist/src/planner/nodes/remote-query-node.js +63 -0
  270. package/dist/src/planner/nodes/remote-query-node.js.map +1 -0
  271. package/dist/src/planner/nodes/retrieve-node.d.ts +46 -0
  272. package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -0
  273. package/dist/src/planner/nodes/retrieve-node.js +77 -0
  274. package/dist/src/planner/nodes/retrieve-node.js.map +1 -0
  275. package/dist/src/planner/nodes/returning-node.d.ts +4 -3
  276. package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
  277. package/dist/src/planner/nodes/returning-node.js +44 -3
  278. package/dist/src/planner/nodes/returning-node.js.map +1 -1
  279. package/dist/src/planner/nodes/sequencing-node.d.ts +1 -1
  280. package/dist/src/planner/nodes/sequencing-node.d.ts.map +1 -1
  281. package/dist/src/planner/nodes/sequencing-node.js.map +1 -1
  282. package/dist/src/planner/nodes/set-operation-node.d.ts +1 -1
  283. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  284. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  285. package/dist/src/planner/nodes/sort.d.ts +11 -2
  286. package/dist/src/planner/nodes/sort.d.ts.map +1 -1
  287. package/dist/src/planner/nodes/sort.js +23 -2
  288. package/dist/src/planner/nodes/sort.js.map +1 -1
  289. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  290. package/dist/src/planner/nodes/stream-aggregate.js +4 -1
  291. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  292. package/dist/src/planner/nodes/table-access-nodes.d.ts +7 -1
  293. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  294. package/dist/src/planner/nodes/table-access-nodes.js +22 -4
  295. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  296. package/dist/src/planner/nodes/table-function-call.d.ts +2 -1
  297. package/dist/src/planner/nodes/table-function-call.d.ts.map +1 -1
  298. package/dist/src/planner/nodes/table-function-call.js +12 -5
  299. package/dist/src/planner/nodes/table-function-call.js.map +1 -1
  300. package/dist/src/planner/nodes/transaction-node.js +2 -2
  301. package/dist/src/planner/nodes/transaction-node.js.map +1 -1
  302. package/dist/src/planner/nodes/update-node.d.ts +7 -1
  303. package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
  304. package/dist/src/planner/nodes/update-node.js +11 -2
  305. package/dist/src/planner/nodes/update-node.js.map +1 -1
  306. package/dist/src/planner/nodes/view-reference-node.js.map +1 -1
  307. package/dist/src/planner/nodes/window-function.js.map +1 -1
  308. package/dist/src/planner/nodes/window-node.js.map +1 -1
  309. package/dist/src/planner/optimizer-tuning.d.ts +11 -0
  310. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
  311. package/dist/src/planner/optimizer-tuning.js +6 -0
  312. package/dist/src/planner/optimizer-tuning.js.map +1 -1
  313. package/dist/src/planner/optimizer.d.ts +17 -3
  314. package/dist/src/planner/optimizer.d.ts.map +1 -1
  315. package/dist/src/planner/optimizer.js +159 -67
  316. package/dist/src/planner/optimizer.js.map +1 -1
  317. package/dist/src/planner/planning-context.d.ts +5 -3
  318. package/dist/src/planner/planning-context.d.ts.map +1 -1
  319. package/dist/src/planner/planning-context.js +2 -0
  320. package/dist/src/planner/planning-context.js.map +1 -1
  321. package/dist/src/planner/resolve.d.ts +3 -2
  322. package/dist/src/planner/resolve.d.ts.map +1 -1
  323. package/dist/src/planner/resolve.js +6 -5
  324. package/dist/src/planner/resolve.js.map +1 -1
  325. package/dist/src/planner/rules/access/rule-select-access-path.d.ts +8 -3
  326. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  327. package/dist/src/planner/rules/access/rule-select-access-path.js +206 -47
  328. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  329. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts +10 -3
  330. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
  331. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +95 -87
  332. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
  333. package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts +8 -2
  334. package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts.map +1 -1
  335. package/dist/src/planner/rules/cache/rule-cte-optimization.js +24 -13
  336. package/dist/src/planner/rules/cache/rule-cte-optimization.js.map +1 -1
  337. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts +9 -2
  338. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts.map +1 -1
  339. package/dist/src/planner/rules/cache/rule-materialization-advisory.js +14 -7
  340. package/dist/src/planner/rules/cache/rule-materialization-advisory.js.map +1 -1
  341. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts +9 -3
  342. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts.map +1 -1
  343. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js +34 -37
  344. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js.map +1 -1
  345. package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts +14 -0
  346. package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -0
  347. package/dist/src/planner/rules/join/rule-join-greedy-commute.js +33 -0
  348. package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -0
  349. package/dist/src/planner/rules/join/rule-join-key-inference.d.ts +11 -0
  350. package/dist/src/planner/rules/join/rule-join-key-inference.d.ts.map +1 -0
  351. package/dist/src/planner/rules/join/rule-join-key-inference.js +32 -0
  352. package/dist/src/planner/rules/join/rule-join-key-inference.js.map +1 -0
  353. package/dist/src/planner/rules/join/rule-quickpick-enumeration.d.ts +4 -0
  354. package/dist/src/planner/rules/join/rule-quickpick-enumeration.d.ts.map +1 -0
  355. package/dist/src/planner/rules/join/rule-quickpick-enumeration.js +233 -0
  356. package/dist/src/planner/rules/join/rule-quickpick-enumeration.js.map +1 -0
  357. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts +21 -0
  358. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts.map +1 -0
  359. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js +125 -0
  360. package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +1 -0
  361. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts +21 -0
  362. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -0
  363. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +261 -0
  364. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -0
  365. package/dist/src/planner/scopes/registered.d.ts +1 -0
  366. package/dist/src/planner/scopes/registered.d.ts.map +1 -1
  367. package/dist/src/planner/scopes/registered.js +7 -0
  368. package/dist/src/planner/scopes/registered.js.map +1 -1
  369. package/dist/src/planner/stats/index.d.ts +0 -17
  370. package/dist/src/planner/stats/index.d.ts.map +1 -1
  371. package/dist/src/planner/stats/index.js +0 -58
  372. package/dist/src/planner/stats/index.js.map +1 -1
  373. package/dist/src/planner/util/deferred-constraint.d.ts +14 -0
  374. package/dist/src/planner/util/deferred-constraint.d.ts.map +1 -0
  375. package/dist/src/planner/util/deferred-constraint.js +85 -0
  376. package/dist/src/planner/util/deferred-constraint.js.map +1 -0
  377. package/dist/src/planner/util/key-utils.d.ts +15 -0
  378. package/dist/src/planner/util/key-utils.d.ts.map +1 -0
  379. package/dist/src/planner/util/key-utils.js +43 -0
  380. package/dist/src/planner/util/key-utils.js.map +1 -0
  381. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
  382. package/dist/src/planner/validation/plan-validator.js +1 -0
  383. package/dist/src/planner/validation/plan-validator.js.map +1 -1
  384. package/dist/src/runtime/deferred-constraint-queue.d.ts +33 -0
  385. package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -0
  386. package/dist/src/runtime/deferred-constraint-queue.js +172 -0
  387. package/dist/src/runtime/deferred-constraint-queue.js.map +1 -0
  388. package/dist/src/runtime/emission-context.d.ts +9 -3
  389. package/dist/src/runtime/emission-context.d.ts.map +1 -1
  390. package/dist/src/runtime/emission-context.js +5 -1
  391. package/dist/src/runtime/emission-context.js.map +1 -1
  392. package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -1
  393. package/dist/src/runtime/emit/add-constraint.js +22 -4
  394. package/dist/src/runtime/emit/add-constraint.js.map +1 -1
  395. package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
  396. package/dist/src/runtime/emit/aggregate.js +3 -2
  397. package/dist/src/runtime/emit/aggregate.js.map +1 -1
  398. package/dist/src/runtime/emit/array-index.js.map +1 -1
  399. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  400. package/dist/src/runtime/emit/binary.js +9 -2
  401. package/dist/src/runtime/emit/binary.js.map +1 -1
  402. package/dist/src/runtime/emit/cache.d.ts.map +1 -1
  403. package/dist/src/runtime/emit/cache.js +1 -1
  404. package/dist/src/runtime/emit/cache.js.map +1 -1
  405. package/dist/src/runtime/emit/cast.d.ts.map +1 -1
  406. package/dist/src/runtime/emit/cast.js.map +1 -1
  407. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
  408. package/dist/src/runtime/emit/constraint-check.js +110 -23
  409. package/dist/src/runtime/emit/constraint-check.js.map +1 -1
  410. package/dist/src/runtime/emit/create-assertion.d.ts +5 -0
  411. package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -0
  412. package/dist/src/runtime/emit/create-assertion.js +70 -0
  413. package/dist/src/runtime/emit/create-assertion.js.map +1 -0
  414. package/dist/src/runtime/emit/cte-reference.d.ts.map +1 -1
  415. package/dist/src/runtime/emit/cte-reference.js.map +1 -1
  416. package/dist/src/runtime/emit/cte.d.ts.map +1 -1
  417. package/dist/src/runtime/emit/cte.js.map +1 -1
  418. package/dist/src/runtime/emit/distinct.d.ts.map +1 -1
  419. package/dist/src/runtime/emit/distinct.js.map +1 -1
  420. package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
  421. package/dist/src/runtime/emit/dml-executor.js +17 -9
  422. package/dist/src/runtime/emit/dml-executor.js.map +1 -1
  423. package/dist/src/runtime/emit/drop-assertion.d.ts +5 -0
  424. package/dist/src/runtime/emit/drop-assertion.d.ts.map +1 -0
  425. package/dist/src/runtime/emit/drop-assertion.js +30 -0
  426. package/dist/src/runtime/emit/drop-assertion.js.map +1 -0
  427. package/dist/src/runtime/emit/filter.d.ts.map +1 -1
  428. package/dist/src/runtime/emit/filter.js.map +1 -1
  429. package/dist/src/runtime/emit/join.d.ts.map +1 -1
  430. package/dist/src/runtime/emit/join.js.map +1 -1
  431. package/dist/src/runtime/emit/limit-offset.d.ts.map +1 -1
  432. package/dist/src/runtime/emit/limit-offset.js.map +1 -1
  433. package/dist/src/runtime/emit/pragma.js.map +1 -1
  434. package/dist/src/runtime/emit/project.d.ts.map +1 -1
  435. package/dist/src/runtime/emit/project.js.map +1 -1
  436. package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
  437. package/dist/src/runtime/emit/recursive-cte.js +1 -1
  438. package/dist/src/runtime/emit/recursive-cte.js.map +1 -1
  439. package/dist/src/runtime/emit/remote-query.d.ts +9 -0
  440. package/dist/src/runtime/emit/remote-query.d.ts.map +1 -0
  441. package/dist/src/runtime/emit/remote-query.js +30 -0
  442. package/dist/src/runtime/emit/remote-query.js.map +1 -0
  443. package/dist/src/runtime/emit/retrieve.d.ts +5 -0
  444. package/dist/src/runtime/emit/retrieve.d.ts.map +1 -0
  445. package/dist/src/runtime/emit/retrieve.js +9 -0
  446. package/dist/src/runtime/emit/retrieve.js.map +1 -0
  447. package/dist/src/runtime/emit/returning.d.ts.map +1 -1
  448. package/dist/src/runtime/emit/returning.js +1 -1
  449. package/dist/src/runtime/emit/returning.js.map +1 -1
  450. package/dist/src/runtime/emit/scalar-function.d.ts.map +1 -1
  451. package/dist/src/runtime/emit/scalar-function.js.map +1 -1
  452. package/dist/src/runtime/emit/scan.d.ts.map +1 -1
  453. package/dist/src/runtime/emit/scan.js +20 -5
  454. package/dist/src/runtime/emit/scan.js.map +1 -1
  455. package/dist/src/runtime/emit/schema-declarative.d.ts +8 -0
  456. package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -0
  457. package/dist/src/runtime/emit/schema-declarative.js +163 -0
  458. package/dist/src/runtime/emit/schema-declarative.js.map +1 -0
  459. package/dist/src/runtime/emit/sequencing.d.ts.map +1 -1
  460. package/dist/src/runtime/emit/sequencing.js.map +1 -1
  461. package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
  462. package/dist/src/runtime/emit/set-operation.js +6 -6
  463. package/dist/src/runtime/emit/set-operation.js.map +1 -1
  464. package/dist/src/runtime/emit/sort.d.ts.map +1 -1
  465. package/dist/src/runtime/emit/sort.js.map +1 -1
  466. package/dist/src/runtime/emit/subquery.d.ts +1 -1
  467. package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
  468. package/dist/src/runtime/emit/subquery.js +6 -6
  469. package/dist/src/runtime/emit/subquery.js.map +1 -1
  470. package/dist/src/runtime/emit/transaction.d.ts.map +1 -1
  471. package/dist/src/runtime/emit/transaction.js +48 -8
  472. package/dist/src/runtime/emit/transaction.js.map +1 -1
  473. package/dist/src/runtime/emit/values.d.ts.map +1 -1
  474. package/dist/src/runtime/emit/values.js.map +1 -1
  475. package/dist/src/runtime/emit/window.d.ts.map +1 -1
  476. package/dist/src/runtime/emit/window.js.map +1 -1
  477. package/dist/src/runtime/emitters.d.ts.map +1 -1
  478. package/dist/src/runtime/emitters.js +1 -0
  479. package/dist/src/runtime/emitters.js.map +1 -1
  480. package/dist/src/runtime/register.d.ts.map +1 -1
  481. package/dist/src/runtime/register.js +16 -2
  482. package/dist/src/runtime/register.js.map +1 -1
  483. package/dist/src/runtime/scheduler.js.map +1 -1
  484. package/dist/src/runtime/types.d.ts +2 -2
  485. package/dist/src/runtime/types.d.ts.map +1 -1
  486. package/dist/src/runtime/types.js +4 -1
  487. package/dist/src/runtime/types.js.map +1 -1
  488. package/dist/src/runtime/utils.d.ts +2 -2
  489. package/dist/src/runtime/utils.d.ts.map +1 -1
  490. package/dist/src/runtime/utils.js +1 -0
  491. package/dist/src/runtime/utils.js.map +1 -1
  492. package/dist/src/schema/assertion.d.ts +19 -0
  493. package/dist/src/schema/assertion.d.ts.map +1 -0
  494. package/dist/src/schema/assertion.js +2 -0
  495. package/dist/src/schema/assertion.js.map +1 -0
  496. package/dist/src/schema/catalog.d.ts +44 -0
  497. package/dist/src/schema/catalog.d.ts.map +1 -0
  498. package/dist/src/schema/catalog.js +148 -0
  499. package/dist/src/schema/catalog.js.map +1 -0
  500. package/dist/src/schema/change-events.d.ts +2 -2
  501. package/dist/src/schema/change-events.d.ts.map +1 -1
  502. package/dist/src/schema/column.d.ts +2 -0
  503. package/dist/src/schema/column.d.ts.map +1 -1
  504. package/dist/src/schema/column.js.map +1 -1
  505. package/dist/src/schema/declared-schema-manager.d.ts +42 -0
  506. package/dist/src/schema/declared-schema-manager.d.ts.map +1 -0
  507. package/dist/src/schema/declared-schema-manager.js +71 -0
  508. package/dist/src/schema/declared-schema-manager.js.map +1 -0
  509. package/dist/src/schema/function.d.ts +3 -2
  510. package/dist/src/schema/function.d.ts.map +1 -1
  511. package/dist/src/schema/function.js.map +1 -1
  512. package/dist/src/schema/manager.d.ts +8 -3
  513. package/dist/src/schema/manager.d.ts.map +1 -1
  514. package/dist/src/schema/manager.js +32 -3
  515. package/dist/src/schema/manager.js.map +1 -1
  516. package/dist/src/schema/schema-differ.d.ts +34 -0
  517. package/dist/src/schema/schema-differ.d.ts.map +1 -0
  518. package/dist/src/schema/schema-differ.js +157 -0
  519. package/dist/src/schema/schema-differ.js.map +1 -0
  520. package/dist/src/schema/schema-hasher.d.ts +10 -0
  521. package/dist/src/schema/schema-hasher.d.ts.map +1 -0
  522. package/dist/src/schema/schema-hasher.js +39 -0
  523. package/dist/src/schema/schema-hasher.js.map +1 -0
  524. package/dist/src/schema/schema.d.ts +7 -0
  525. package/dist/src/schema/schema.d.ts.map +1 -1
  526. package/dist/src/schema/schema.js +19 -0
  527. package/dist/src/schema/schema.js.map +1 -1
  528. package/dist/src/schema/table.d.ts +28 -3
  529. package/dist/src/schema/table.d.ts.map +1 -1
  530. package/dist/src/schema/table.js +17 -2
  531. package/dist/src/schema/table.js.map +1 -1
  532. package/dist/src/schema/window-function.d.ts.map +1 -1
  533. package/dist/src/schema/window-function.js.map +1 -1
  534. package/dist/src/util/ast-stringify.d.ts.map +1 -1
  535. package/dist/src/util/ast-stringify.js +116 -3
  536. package/dist/src/util/ast-stringify.js.map +1 -1
  537. package/dist/src/util/environment.js.map +1 -1
  538. package/dist/src/util/plugin-loader.d.ts +25 -2
  539. package/dist/src/util/plugin-loader.d.ts.map +1 -1
  540. package/dist/src/util/plugin-loader.js +180 -2
  541. package/dist/src/util/plugin-loader.js.map +1 -1
  542. package/dist/src/util/row-descriptor.d.ts +1 -1
  543. package/dist/src/util/row-descriptor.d.ts.map +1 -1
  544. package/dist/src/util/row-descriptor.js.map +1 -1
  545. package/dist/src/util/serialization.d.ts +3 -0
  546. package/dist/src/util/serialization.d.ts.map +1 -1
  547. package/dist/src/util/serialization.js +1 -0
  548. package/dist/src/util/serialization.js.map +1 -1
  549. package/dist/src/vtab/best-access-plan.d.ts +1 -1
  550. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  551. package/dist/src/vtab/best-access-plan.js +1 -0
  552. package/dist/src/vtab/best-access-plan.js.map +1 -1
  553. package/dist/src/vtab/manifest.d.ts.map +1 -1
  554. package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
  555. package/dist/src/vtab/memory/layer/base.js +2 -0
  556. package/dist/src/vtab/memory/layer/base.js.map +1 -1
  557. package/dist/src/vtab/memory/layer/manager.d.ts +2 -1
  558. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  559. package/dist/src/vtab/memory/layer/manager.js +24 -6
  560. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  561. package/dist/src/vtab/memory/layer/safe-iterate.d.ts.map +1 -1
  562. package/dist/src/vtab/memory/layer/safe-iterate.js.map +1 -1
  563. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  564. package/dist/src/vtab/memory/module.js +5 -0
  565. package/dist/src/vtab/memory/module.js.map +1 -1
  566. package/dist/src/vtab/memory/table.d.ts +2 -1
  567. package/dist/src/vtab/memory/table.d.ts.map +1 -1
  568. package/dist/src/vtab/memory/table.js +3 -2
  569. package/dist/src/vtab/memory/table.js.map +1 -1
  570. package/dist/src/vtab/memory/utils/logging.d.ts +2 -2
  571. package/dist/src/vtab/memory/utils/logging.d.ts.map +1 -1
  572. package/dist/src/vtab/memory/utils/logging.js +6 -3
  573. package/dist/src/vtab/memory/utils/logging.js.map +1 -1
  574. package/dist/src/vtab/module.d.ts +25 -0
  575. package/dist/src/vtab/module.d.ts.map +1 -1
  576. package/dist/src/vtab/table.d.ts +17 -4
  577. package/dist/src/vtab/table.d.ts.map +1 -1
  578. package/dist/src/vtab/table.js.map +1 -1
  579. package/package.json +4 -2
  580. package/src/common/errors.ts +1 -1
  581. package/src/common/json-types.ts +16 -0
  582. package/src/common/types.ts +2 -0
  583. package/src/core/database-options.ts +8 -8
  584. package/src/core/database.ts +537 -71
  585. package/src/core/statement.ts +3 -1
  586. package/src/func/builtins/builtin-window-functions.ts +11 -10
  587. package/src/func/builtins/datetime.ts +42 -0
  588. package/src/func/builtins/explain.ts +186 -44
  589. package/src/func/builtins/index.ts +5 -2
  590. package/src/func/builtins/json-helpers.ts +21 -21
  591. package/src/func/builtins/json-tvf.ts +8 -9
  592. package/src/func/builtins/json.ts +10 -9
  593. package/src/func/builtins/schema.ts +24 -4
  594. package/src/func/context.ts +7 -0
  595. package/src/func/registration.ts +5 -1
  596. package/src/index.ts +2 -2
  597. package/src/parser/ast.ts +582 -481
  598. package/src/parser/lexer.ts +27 -21
  599. package/src/parser/parser.ts +3336 -2776
  600. package/src/parser/visitor.ts +1 -0
  601. package/src/planner/analysis/binding-collector.ts +83 -0
  602. package/src/planner/analysis/const-evaluator.ts +1 -1
  603. package/src/planner/analysis/const-pass.ts +3 -2
  604. package/src/planner/analysis/constraint-extractor.ts +610 -123
  605. package/src/planner/analysis/predicate-normalizer.ts +237 -0
  606. package/src/planner/building/alter-table.ts +3 -1
  607. package/src/planner/building/block.ts +93 -78
  608. package/src/planner/building/constraint-builder.ts +173 -114
  609. package/src/planner/building/create-assertion.ts +7 -0
  610. package/src/planner/building/declare-schema.ts +22 -0
  611. package/src/planner/building/delete.ts +214 -171
  612. package/src/planner/building/drop-assertion.ts +11 -0
  613. package/src/planner/building/expression.ts +1 -0
  614. package/src/planner/building/function-call.ts +6 -5
  615. package/src/planner/building/insert.ts +428 -349
  616. package/src/planner/building/pragma.ts +1 -0
  617. package/src/planner/building/schema-resolution.ts +176 -176
  618. package/src/planner/building/select-aggregates.ts +5 -3
  619. package/src/planner/building/select-compound.ts +22 -13
  620. package/src/planner/building/select-context.ts +6 -6
  621. package/src/planner/building/select-modifiers.ts +8 -7
  622. package/src/planner/building/select-projections.ts +177 -176
  623. package/src/planner/building/select-window.ts +259 -253
  624. package/src/planner/building/select.ts +531 -520
  625. package/src/planner/building/table-function.ts +49 -48
  626. package/src/planner/building/table.ts +9 -3
  627. package/src/planner/building/update.ts +319 -270
  628. package/src/planner/building/with.ts +7 -7
  629. package/src/planner/debug.ts +1 -0
  630. package/src/planner/framework/characteristics.ts +503 -0
  631. package/src/planner/framework/context.ts +23 -6
  632. package/src/planner/framework/pass.ts +354 -0
  633. package/src/planner/nodes/aggregate-node.ts +52 -7
  634. package/src/planner/nodes/array-index-node.ts +1 -1
  635. package/src/planner/nodes/cache-node.ts +11 -2
  636. package/src/planner/nodes/constraint-check-node.ts +14 -5
  637. package/src/planner/nodes/create-assertion-node.ts +51 -0
  638. package/src/planner/nodes/create-index-node.ts +2 -2
  639. package/src/planner/nodes/create-table-node.ts +2 -2
  640. package/src/planner/nodes/cte-node.ts +30 -4
  641. package/src/planner/nodes/cte-reference-node.ts +2 -2
  642. package/src/planner/nodes/declarative-schema.ts +221 -0
  643. package/src/planner/nodes/delete-node.ts +102 -96
  644. package/src/planner/nodes/distinct-node.ts +20 -6
  645. package/src/planner/nodes/dml-executor-node.ts +1 -1
  646. package/src/planner/nodes/drop-assertion-node.ts +50 -0
  647. package/src/planner/nodes/drop-table-node.ts +1 -0
  648. package/src/planner/nodes/filter.ts +56 -3
  649. package/src/planner/nodes/insert-node.ts +126 -120
  650. package/src/planner/nodes/internal-recursive-cte-ref-node.ts +5 -20
  651. package/src/planner/nodes/join-node.ts +122 -4
  652. package/src/planner/nodes/limit-offset.ts +132 -113
  653. package/src/planner/nodes/plan-node-type.ts +95 -87
  654. package/src/planner/nodes/plan-node.ts +8 -8
  655. package/src/planner/nodes/pragma.ts +6 -3
  656. package/src/planner/nodes/project-node.ts +101 -7
  657. package/src/planner/nodes/recursive-cte-node.ts +6 -6
  658. package/src/planner/nodes/reference.ts +334 -312
  659. package/src/planner/nodes/remote-query-node.ts +73 -0
  660. package/src/planner/nodes/retrieve-node.ts +86 -0
  661. package/src/planner/nodes/returning-node.ts +52 -10
  662. package/src/planner/nodes/sequencing-node.ts +2 -2
  663. package/src/planner/nodes/set-operation-node.ts +3 -3
  664. package/src/planner/nodes/sort.ts +33 -4
  665. package/src/planner/nodes/stream-aggregate.ts +5 -1
  666. package/src/planner/nodes/table-access-nodes.ts +31 -6
  667. package/src/planner/nodes/table-function-call.ts +134 -127
  668. package/src/planner/nodes/transaction-node.ts +2 -2
  669. package/src/planner/nodes/update-node.ts +138 -132
  670. package/src/planner/nodes/view-reference-node.ts +1 -1
  671. package/src/planner/nodes/window-function.ts +2 -2
  672. package/src/planner/nodes/window-node.ts +1 -1
  673. package/src/planner/optimizer-tuning.ts +18 -0
  674. package/src/planner/optimizer.ts +171 -96
  675. package/src/planner/planning-context.ts +10 -3
  676. package/src/planner/resolve.ts +10 -9
  677. package/src/planner/rules/README.md +96 -96
  678. package/src/planner/rules/access/rule-select-access-path.ts +384 -184
  679. package/src/planner/rules/aggregate/rule-aggregate-streaming.ts +118 -104
  680. package/src/planner/rules/cache/rule-cte-optimization.ts +29 -16
  681. package/src/planner/rules/cache/rule-materialization-advisory.ts +14 -7
  682. package/src/planner/rules/cache/rule-mutating-subquery-cache.ts +38 -44
  683. package/src/planner/rules/join/rule-join-greedy-commute.ts +48 -0
  684. package/src/planner/rules/join/rule-join-key-inference.ts +35 -0
  685. package/src/planner/rules/join/rule-quickpick-enumeration.ts +267 -0
  686. package/src/planner/rules/predicate/rule-predicate-pushdown.ts +144 -0
  687. package/src/planner/rules/retrieve/rule-grow-retrieve.ts +337 -0
  688. package/src/planner/scopes/registered.ts +8 -0
  689. package/src/planner/stats/index.ts +0 -65
  690. package/src/planner/util/key-utils.ts +46 -0
  691. package/src/planner/validation/plan-validator.ts +5 -3
  692. package/src/runtime/deferred-constraint-queue.ts +196 -0
  693. package/src/runtime/emission-context.ts +11 -5
  694. package/src/runtime/emit/add-constraint.ts +26 -5
  695. package/src/runtime/emit/aggregate.ts +9 -7
  696. package/src/runtime/emit/array-index.ts +2 -2
  697. package/src/runtime/emit/binary.ts +26 -8
  698. package/src/runtime/emit/cache.ts +2 -2
  699. package/src/runtime/emit/cast.ts +2 -2
  700. package/src/runtime/emit/constraint-check.ts +148 -26
  701. package/src/runtime/emit/create-assertion.ts +82 -0
  702. package/src/runtime/emit/cte-reference.ts +2 -2
  703. package/src/runtime/emit/cte.ts +2 -2
  704. package/src/runtime/emit/distinct.ts +2 -2
  705. package/src/runtime/emit/dml-executor.ts +20 -12
  706. package/src/runtime/emit/drop-assertion.ts +45 -0
  707. package/src/runtime/emit/filter.ts +4 -4
  708. package/src/runtime/emit/join.ts +8 -7
  709. package/src/runtime/emit/limit-offset.ts +2 -2
  710. package/src/runtime/emit/pragma.ts +2 -2
  711. package/src/runtime/emit/project.ts +2 -2
  712. package/src/runtime/emit/recursive-cte.ts +2 -2
  713. package/src/runtime/emit/remote-query.ts +47 -0
  714. package/src/runtime/emit/retrieve.ts +15 -0
  715. package/src/runtime/emit/returning.ts +4 -4
  716. package/src/runtime/emit/scalar-function.ts +2 -2
  717. package/src/runtime/emit/scan.ts +29 -13
  718. package/src/runtime/emit/schema-declarative.ts +205 -0
  719. package/src/runtime/emit/sequencing.ts +3 -3
  720. package/src/runtime/emit/set-operation.ts +7 -7
  721. package/src/runtime/emit/sort.ts +2 -2
  722. package/src/runtime/emit/subquery.ts +10 -10
  723. package/src/runtime/emit/transaction.ts +46 -8
  724. package/src/runtime/emit/values.ts +2 -2
  725. package/src/runtime/emit/window.ts +3 -3
  726. package/src/runtime/emitters.ts +1 -0
  727. package/src/runtime/register.ts +150 -135
  728. package/src/runtime/scheduler.ts +2 -2
  729. package/src/runtime/types.ts +10 -7
  730. package/src/runtime/utils.ts +3 -2
  731. package/src/schema/assertion.ts +21 -0
  732. package/src/schema/catalog.ts +208 -0
  733. package/src/schema/change-events.ts +2 -2
  734. package/src/schema/column.ts +2 -0
  735. package/src/schema/declared-schema-manager.ts +82 -0
  736. package/src/schema/function.ts +5 -2
  737. package/src/schema/manager.ts +742 -709
  738. package/src/schema/schema-differ.ts +214 -0
  739. package/src/schema/schema-hasher.ts +44 -0
  740. package/src/schema/schema.ts +23 -0
  741. package/src/schema/table.ts +398 -364
  742. package/src/schema/window-function.ts +2 -0
  743. package/src/util/ast-stringify.ts +869 -764
  744. package/src/util/environment.ts +2 -2
  745. package/src/util/plugin-loader.ts +232 -7
  746. package/src/util/row-descriptor.ts +1 -1
  747. package/src/util/serialization.ts +2 -0
  748. package/src/vtab/best-access-plan.ts +2 -1
  749. package/src/vtab/manifest.ts +1 -0
  750. package/src/vtab/memory/index.ts +178 -178
  751. package/src/vtab/memory/layer/base.ts +275 -273
  752. package/src/vtab/memory/layer/interface.ts +47 -47
  753. package/src/vtab/memory/layer/manager.ts +33 -11
  754. package/src/vtab/memory/layer/safe-iterate.ts +3 -3
  755. package/src/vtab/memory/layer/transaction.ts +229 -229
  756. package/src/vtab/memory/module.ts +24 -18
  757. package/src/vtab/memory/table.ts +256 -253
  758. package/src/vtab/memory/utils/logging.ts +6 -3
  759. package/src/vtab/module.ts +170 -140
  760. package/src/vtab/table.ts +162 -143
@@ -1,709 +1,742 @@
1
- import { Schema } from './schema.js';
2
- import type { Database } from '../core/database.js';
3
- import type { TableSchema, RowConstraintSchema, IndexSchema } from './table.js';
4
- import type { FunctionSchema } from './function.js';
5
- import { quereusError, QuereusError } from '../common/errors.js';
6
- import { StatusCode, type SqlValue } from '../common/types.js';
7
- import type { VirtualTableModule, BaseModuleConfig } from '../vtab/module.js';
8
- import type { VirtualTable } from '../vtab/table.js';
9
- import type { ColumnSchema } from './column.js';
10
- import { buildColumnIndexMap, columnDefToSchema, findPKDefinition, opsToMask } from './table.js';
11
- import type { ViewSchema } from './view.js';
12
- import { createLogger } from '../common/logger.js';
13
- import type * as AST from '../parser/ast.js';
14
- import { SchemaChangeNotifier } from './change-events.js';
15
-
16
- const log = createLogger('schema:manager');
17
- const warnLog = log.extend('warn');
18
- const errorLog = log.extend('error');
19
-
20
- /**
21
- * Generic options passed to VTab modules during CREATE TABLE.
22
- * Modules are responsible for interpreting these.
23
- */
24
- export interface GenericModuleCallOptions extends BaseModuleConfig {
25
- moduleArgs?: readonly string[];
26
- statementColumns?: readonly AST.ColumnDef[];
27
- statementConstraints?: readonly AST.TableConstraint[];
28
- isTemporary?: boolean;
29
- }
30
-
31
- /**
32
- * Manages all schemas associated with a database connection (main, temp, attached).
33
- * Handles lookup resolution according to SQLite's rules.
34
- */
35
- export class SchemaManager {
36
- private schemas: Map<string, Schema> = new Map();
37
- private currentSchemaName: string = 'main';
38
- private modules: Map<string, { module: VirtualTableModule<any, any>, auxData?: unknown }> = new Map();
39
- private defaultVTabModuleName: string = 'memory';
40
- private defaultVTabModuleArgs: Record<string, SqlValue> = {};
41
- private db: Database;
42
- private changeNotifier = new SchemaChangeNotifier();
43
-
44
- /**
45
- * Creates a new schema manager
46
- *
47
- * @param db Reference to the parent Database instance
48
- */
49
- constructor(db: Database) {
50
- this.db = db;
51
- // Ensure 'main' and 'temp' schemas always exist
52
- this.schemas.set('main', new Schema('main'));
53
- this.schemas.set('temp', new Schema('temp'));
54
- }
55
-
56
- /**
57
- * Sets the current default schema for unqualified names
58
- *
59
- * @param name Schema name to set as current
60
- */
61
- setCurrentSchema(name: string): void {
62
- if (this.schemas.has(name.toLowerCase())) {
63
- this.currentSchemaName = name.toLowerCase();
64
- } else {
65
- warnLog(`Attempted to set current schema to non-existent schema: %s`, name);
66
- }
67
- }
68
-
69
- /**
70
- * Gets the name of the current default schema
71
- *
72
- * @returns Current schema name
73
- */
74
- getCurrentSchemaName(): string {
75
- return this.currentSchemaName;
76
- }
77
-
78
- /**
79
- * Registers a virtual table module
80
- *
81
- * @param name Module name
82
- * @param module Module implementation
83
- * @param auxData Optional client data associated with the module registration
84
- */
85
- registerModule(name: string, module: VirtualTableModule<any, any>, auxData?: unknown): void {
86
- const lowerName = name.toLowerCase();
87
- if (this.modules.has(lowerName)) {
88
- warnLog(`Replacing existing virtual table module: %s`, lowerName);
89
- }
90
- this.modules.set(lowerName, { module, auxData });
91
- log(`Registered VTab module: %s`, lowerName);
92
- }
93
-
94
- /**
95
- * Retrieves a registered virtual table module by name
96
- *
97
- * @param name Module name to look up
98
- * @returns The module and its auxData, or undefined if not found
99
- */
100
- getModule(name: string): { module: VirtualTableModule<any, any>, auxData?: unknown } | undefined {
101
- return this.modules.get(name.toLowerCase());
102
- }
103
-
104
- /**
105
- * Sets the default virtual table module to use when USING is omitted
106
- *
107
- * @param name Module name. Must be a registered module.
108
- * @throws QuereusError if the module name is not registered
109
- */
110
- setDefaultVTabModuleName(name: string): void {
111
- const lowerName = name.toLowerCase();
112
- if (this.modules.has(lowerName)) {
113
- this.defaultVTabModuleName = lowerName;
114
- log(`Default VTab module name set to: %s`, lowerName);
115
- } else {
116
- warnLog(`Setting default VTab module to '${lowerName}', which is not currently registered in SchemaManager. Ensure it gets registered.`);
117
- this.defaultVTabModuleName = lowerName;
118
- }
119
- }
120
-
121
- /**
122
- * Gets the currently configured default virtual table module name
123
- *
124
- * @returns The default module name
125
- */
126
- getDefaultVTabModuleName(): string {
127
- return this.defaultVTabModuleName;
128
- }
129
-
130
- /** @internal Sets the default VTab args directly */
131
- setDefaultVTabArgs(args: Record<string, SqlValue>): void {
132
- this.defaultVTabModuleArgs = args;
133
- log('Default VTab module args set to: %o', args);
134
- }
135
-
136
- /** @internal Sets the default VTab args by parsing a JSON string */
137
- setDefaultVTabArgsFromJson(argsJsonString: string): void {
138
- try {
139
- const parsedArgs = JSON.parse(argsJsonString);
140
- if (typeof parsedArgs !== 'object') {
141
- quereusError("JSON value must be an object.", StatusCode.MISUSE);
142
- }
143
- this.setDefaultVTabArgs(parsedArgs);
144
- } catch (e) {
145
- const msg = e instanceof Error ? e.message : String(e);
146
- quereusError(`Invalid JSON for default_vtab_args: ${msg}`, StatusCode.ERROR);
147
- }
148
- }
149
-
150
- /**
151
- * Gets the default virtual table module arguments.
152
- * @returns A copy of the default arguments array.
153
- */
154
- getDefaultVTabArgs(): Record<string, SqlValue> {
155
- return { ...this.defaultVTabModuleArgs };
156
- }
157
-
158
- /**
159
- * Gets the default virtual table module name and arguments.
160
- * @returns An object containing the module name and arguments.
161
- */
162
- getDefaultVTabModule(): { name: string; args: Record<string, SqlValue> } {
163
- return {
164
- name: this.defaultVTabModuleName,
165
- args: this.defaultVTabModuleArgs,
166
- };
167
- }
168
-
169
- /**
170
- * Gets a specific schema by name
171
- *
172
- * @param name Schema name to retrieve
173
- * @returns The schema or undefined if not found
174
- */
175
- getSchema(name: string): Schema | undefined {
176
- return this.schemas.get(name.toLowerCase());
177
- }
178
-
179
- /**
180
- * Gets the 'main' schema
181
- *
182
- * @returns The main schema
183
- */
184
- getMainSchema(): Schema {
185
- return this.schemas.get('main')!;
186
- }
187
-
188
- /**
189
- * Gets the 'temp' schema
190
- *
191
- * @returns The temp schema
192
- */
193
- getTempSchema(): Schema {
194
- return this.schemas.get('temp')!;
195
- }
196
-
197
- /**
198
- * @internal Returns iterator over all managed schemas
199
- */
200
- _getAllSchemas(): IterableIterator<Schema> {
201
- return this.schemas.values();
202
- }
203
-
204
- /**
205
- * Gets the schema change notifier for listening to schema changes
206
- */
207
- getChangeNotifier(): SchemaChangeNotifier {
208
- return this.changeNotifier;
209
- }
210
-
211
- /**
212
- * Adds a new schema (e.g., for ATTACH)
213
- *
214
- * @param name Name of the schema to add
215
- * @returns The newly created schema
216
- * @throws QuereusError if the name conflicts with an existing schema
217
- */
218
- addSchema(name: string): Schema {
219
- const lowerName = name.toLowerCase();
220
- if (this.schemas.has(lowerName)) {
221
- throw new QuereusError(`Schema '${name}' already exists`, StatusCode.ERROR);
222
- }
223
- const schema = new Schema(name);
224
- this.schemas.set(lowerName, schema);
225
- log(`Added schema '%s'`, name);
226
- return schema;
227
- }
228
-
229
- /**
230
- * Removes a schema (e.g., for DETACH)
231
- *
232
- * @param name Name of the schema to remove
233
- * @returns true if found and removed, false otherwise
234
- * @throws QuereusError if attempting to remove 'main' or 'temp'
235
- */
236
- removeSchema(name: string): boolean {
237
- const lowerName = name.toLowerCase();
238
- if (lowerName === 'main' || lowerName === 'temp') {
239
- throw new QuereusError(`Cannot detach schema '${name}'`, StatusCode.ERROR);
240
- }
241
- const schema = this.schemas.get(lowerName);
242
- if (schema) {
243
- schema.clearFunctions();
244
- schema.clearTables();
245
- schema.clearViews();
246
- this.schemas.delete(lowerName);
247
- log(`Removed schema '%s'`, name);
248
- return true;
249
- }
250
- return false;
251
- }
252
-
253
- /**
254
- * @internal Finds a table or virtual table by name across schemas
255
- */
256
- _findTable(tableName: string, dbName?: string): TableSchema | undefined {
257
- const lowerTableName = tableName.toLowerCase();
258
-
259
-
260
-
261
- if (dbName) {
262
- // Search specific schema
263
- const schema = this.schemas.get(dbName.toLowerCase());
264
- return schema?.getTable(lowerTableName);
265
- } else {
266
- // Search order: main, then temp (and attached later)
267
- const mainSchema = this.schemas.get('main');
268
- let table = mainSchema?.getTable(lowerTableName);
269
- if (table) return table;
270
-
271
- const tempSchema = this.schemas.get('temp');
272
- table = tempSchema?.getTable(lowerTableName);
273
- return table;
274
- }
275
- }
276
-
277
- /**
278
- * Finds a table by name, searching schemas according to SQLite rules
279
- *
280
- * @param tableName Name of the table
281
- * @param dbName Optional specific schema name to search
282
- * @returns The TableSchema or undefined if not found
283
- */
284
- findTable(tableName: string, dbName?: string): TableSchema | undefined {
285
- return this._findTable(tableName, dbName);
286
- }
287
-
288
- /**
289
- * Finds a function by name and arg count, searching schemas
290
- *
291
- * @param funcName Name of the function
292
- * @param nArg Number of arguments
293
- * @returns The FunctionSchema or undefined if not found
294
- */
295
- findFunction(funcName: string, nArg: number): FunctionSchema | undefined {
296
- return this.getMainSchema().getFunction(funcName, nArg);
297
- }
298
-
299
- /**
300
- * Retrieves a view schema definition
301
- *
302
- * @param schemaName The name of the schema ('main', 'temp', etc.). Defaults to current schema
303
- * @param viewName The name of the view
304
- * @returns The ViewSchema or undefined if not found
305
- */
306
- getView(schemaName: string | null, viewName: string): ViewSchema | undefined {
307
- const targetSchemaName = schemaName ?? this.currentSchemaName;
308
- const schema = this.schemas.get(targetSchemaName);
309
- return schema?.getView(viewName);
310
- }
311
-
312
- /**
313
- * Retrieves any schema item (table or view) by name. Checks views first
314
- *
315
- * @param schemaName The name of the schema ('main', 'temp', etc.). Defaults to current schema
316
- * @param itemName The name of the table or view
317
- * @returns The TableSchema or ViewSchema, or undefined if not found
318
- */
319
- getSchemaItem(schemaName: string | null, itemName: string): TableSchema | ViewSchema | undefined {
320
- const targetSchemaName = schemaName ?? this.currentSchemaName;
321
- const schema = this.schemas.get(targetSchemaName);
322
- if (!schema) return undefined;
323
-
324
- // Prioritize views over tables if names conflict
325
- const view = schema.getView(itemName);
326
- if (view) return view;
327
- return schema.getTable(itemName);
328
- }
329
-
330
- /**
331
- * Drops a table from the specified schema
332
- *
333
- * @param schemaName The name of the schema
334
- * @param tableName The name of the table to drop
335
- * @param ifExists If true, do not throw an error if the table does not exist.
336
- * @returns True if the table was found and dropped, false otherwise.
337
- */
338
- dropTable(schemaName: string, tableName: string, ifExists: boolean = false): boolean {
339
- const schema = this.schemas.get(schemaName.toLowerCase()); // Ensure schemaName is lowercased for lookup
340
- if (!schema) {
341
- if (ifExists) return false; // Schema not found, but IF EXISTS specified
342
- throw new QuereusError(`Schema not found: ${schemaName}`, StatusCode.ERROR);
343
- }
344
-
345
- const tableSchema = schema.getTable(tableName); // getTable should handle case-insensitivity
346
-
347
- if (!tableSchema) {
348
- if (ifExists) {
349
- log(`Table %s.%s not found, but IF EXISTS was specified.`, schemaName, tableName);
350
- return false; // Not found, but IF EXISTS means no error, not dropped.
351
- }
352
- throw new QuereusError(`Table ${tableName} not found in schema ${schemaName}`, StatusCode.NOTFOUND);
353
- }
354
-
355
- let destroyPromise: Promise<void> | null = null;
356
-
357
- // Call xDestroy on the module, providing table details
358
- if (tableSchema.vtabModuleName) { // tableSchema is guaranteed to be defined here
359
- const moduleRegistration = this.getModule(tableSchema.vtabModuleName);
360
- if (moduleRegistration && moduleRegistration.module && moduleRegistration.module.xDestroy) {
361
- log(`Calling xDestroy for VTab %s.%s via module %s`, schemaName, tableName, tableSchema.vtabModuleName);
362
- destroyPromise = moduleRegistration.module.xDestroy(
363
- this.db,
364
- moduleRegistration.auxData,
365
- tableSchema.vtabModuleName,
366
- schemaName,
367
- tableName
368
- ).catch(err => {
369
- errorLog(`Error during VTab module xDestroy for %s.%s: %O`, schemaName, tableName, err);
370
- // Potentially re-throw or handle as a critical error if xDestroy failure is problematic
371
- });
372
- } else {
373
- warnLog(`VTab module %s (for table %s.%s) or its xDestroy method not found during dropTable.`, tableSchema.vtabModuleName, schemaName, tableName);
374
- }
375
- }
376
-
377
- // Remove from schema map immediately
378
- const removed = schema.removeTable(tableName);
379
- if (!removed && !ifExists) {
380
- // This should ideally not be reached if tableSchema was found above.
381
- // But as a safeguard if removeTable could fail for other reasons.
382
- throw new QuereusError(`Failed to remove table ${tableName} from schema ${schemaName}, though it was initially found.`, StatusCode.INTERNAL);
383
- }
384
-
385
- // Notify schema change listeners if table was removed
386
- if (removed) {
387
- this.changeNotifier.notifyChange({
388
- type: 'table_removed',
389
- schemaName: schemaName,
390
- objectName: tableName,
391
- oldObject: tableSchema
392
- });
393
- }
394
-
395
- // Process destruction asynchronously
396
- if (destroyPromise) {
397
- void destroyPromise.then(() => log(`xDestroy completed for VTab %s.%s`, schemaName, tableName));
398
- }
399
-
400
- return removed; // True if removed from schema, false if not found and ifExists was true.
401
- }
402
-
403
- /**
404
- * Drops a view from the specified schema
405
- *
406
- * @param schemaName The name of the schema
407
- * @param viewName The name of the view to drop
408
- * @returns True if the view was found and dropped, false otherwise
409
- */
410
- dropView(schemaName: string, viewName: string): boolean {
411
- const schema = this.schemas.get(schemaName);
412
- if (!schema) return false;
413
- return schema.removeView(viewName);
414
- }
415
-
416
- /**
417
- * Clears all schema items (tables, functions, views)
418
- */
419
- clearAll(): void {
420
- this.schemas.forEach(schema => {
421
- schema.clearTables();
422
- schema.clearFunctions();
423
- schema.clearViews();
424
- });
425
- log("Cleared all schemas.");
426
- }
427
-
428
- /**
429
- * Retrieves a schema object, throwing if it doesn't exist
430
- *
431
- * @param name Schema name ('main', 'temp', or custom). Case-insensitive
432
- * @returns The Schema object
433
- * @throws QuereusError if the schema does not exist
434
- */
435
- getSchemaOrFail(name: string): Schema {
436
- const schema = this.schemas.get(name.toLowerCase());
437
- if (!schema) {
438
- throw new QuereusError(`Schema not found: ${name}`);
439
- }
440
- return schema;
441
- }
442
-
443
- /**
444
- * Retrieves a table from the specified schema
445
- *
446
- * @param schemaName The name of the schema ('main', 'temp', etc.). Defaults to current schema
447
- * @param tableName The name of the table
448
- * @returns The TableSchema or undefined if not found
449
- */
450
- getTable(schemaName: string | undefined, tableName: string): TableSchema | undefined {
451
- const targetSchemaName = schemaName ?? this.currentSchemaName;
452
- const schema = this.schemas.get(targetSchemaName);
453
- return schema?.getTable(tableName);
454
- }
455
-
456
- /**
457
- * Creates a new index on an existing table based on an AST.CreateIndexStmt.
458
- * This method validates the index definition and calls the virtual table's xCreateIndex method.
459
- *
460
- * @param stmt The AST node for the CREATE INDEX statement.
461
- * @returns A Promise that resolves when the index is created.
462
- * @throws QuereusError on errors (e.g., table not found, column not found, xCreateIndex fails).
463
- */
464
- async createIndex(stmt: AST.CreateIndexStmt): Promise<void> {
465
- const targetSchemaName = stmt.table.schema || this.getCurrentSchemaName();
466
- const tableName = stmt.table.name;
467
- const indexName = stmt.index.name;
468
-
469
- // Find the table schema
470
- const tableSchema = this.getTable(targetSchemaName, tableName);
471
- if (!tableSchema) {
472
- throw new QuereusError(`no such table: ${tableName}`, StatusCode.ERROR, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
473
- }
474
-
475
- // Check if the virtual table module supports xCreateIndex
476
- if (!tableSchema.vtabModule.xCreateIndex) {
477
- throw new QuereusError(`Virtual table module '${tableSchema.vtabModuleName}' for table '${tableName}' does not support CREATE INDEX.`, StatusCode.ERROR, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
478
- }
479
-
480
- // Check if index already exists (if not IF NOT EXISTS)
481
- const existingIndex = tableSchema.indexes?.find(idx => idx.name.toLowerCase() === indexName.toLowerCase());
482
- if (existingIndex) {
483
- if (stmt.ifNotExists) {
484
- log(`Skipping CREATE INDEX: Index %s.%s already exists (IF NOT EXISTS).`, targetSchemaName, indexName);
485
- return;
486
- } else {
487
- throw new QuereusError(`Index ${indexName} already exists on table ${tableName}`, StatusCode.CONSTRAINT, undefined, stmt.index.loc?.start.line, stmt.index.loc?.start.column);
488
- }
489
- }
490
-
491
- // Convert AST columns to IndexSchema columns
492
- const indexColumns = stmt.columns.map((indexedCol: AST.IndexedColumn) => {
493
- if (indexedCol.expr) {
494
- throw new QuereusError(`Indices on expressions are not supported yet.`, StatusCode.ERROR, undefined, indexedCol.expr.loc?.start.line, indexedCol.expr.loc?.start.column);
495
- }
496
- const colName = indexedCol.name;
497
- if (!colName) {
498
- // Should not happen if expr is checked first
499
- throw new QuereusError(`Indexed column must be a simple column name.`, StatusCode.ERROR);
500
- }
501
- const tableColIndex = tableSchema.columnIndexMap.get(colName.toLowerCase());
502
- if (tableColIndex === undefined) {
503
- throw new QuereusError(`Column '${colName}' not found in table '${tableName}'`, StatusCode.ERROR, undefined, stmt.loc?.start.line, stmt.loc?.start.column);
504
- }
505
- const tableColSchema = tableSchema.columns[tableColIndex];
506
- return {
507
- index: tableColIndex,
508
- desc: indexedCol.direction === 'desc',
509
- collation: indexedCol.collation || tableColSchema.collation // Use specified collation or inherit from table column
510
- };
511
- });
512
-
513
- // Construct the IndexSchema object
514
- const indexSchema: IndexSchema = {
515
- name: indexName,
516
- columns: Object.freeze(indexColumns),
517
- };
518
-
519
- try {
520
- // Call xCreateIndex on the virtual table module
521
- await tableSchema.vtabModule.xCreateIndex(
522
- this.db,
523
- targetSchemaName,
524
- tableName,
525
- indexSchema
526
- );
527
-
528
- // Update the table schema with the new index by creating a new schema object
529
- const updatedIndexes = [...(tableSchema.indexes || []), indexSchema];
530
- const updatedTableSchema: TableSchema = {
531
- ...tableSchema,
532
- indexes: Object.freeze(updatedIndexes),
533
- };
534
-
535
- // Replace the table schema in the schema
536
- const schema = this.getSchemaOrFail(targetSchemaName);
537
- schema.addTable(updatedTableSchema);
538
-
539
- log(`Successfully created index %s on table %s.%s`, indexName, targetSchemaName, tableName);
540
- } catch (e: unknown) {
541
- const message = e instanceof Error ? e.message : String(e);
542
- const code = e instanceof QuereusError ? e.code : StatusCode.ERROR;
543
- throw new QuereusError(`xCreateIndex failed for index '${indexName}' on table '${tableName}': ${message}`, code, e instanceof Error ? e : undefined, stmt.loc?.start.line, stmt.loc?.start.column);
544
- }
545
- }
546
-
547
- /**
548
- * Defines a new table in the schema based on an AST.CreateTableStmt.
549
- * This method encapsulates the logic for interacting with VTab modules (xCreate)
550
- * and registering the new table schema.
551
- *
552
- * @param stmt The AST node for the CREATE TABLE statement.
553
- * @returns A Promise that resolves to the created TableSchema.
554
- * @throws QuereusError on errors (e.g., module not found, xCreate fails, table exists).
555
- */
556
- async createTable(stmt: AST.CreateTableStmt): Promise<TableSchema> {
557
- const targetSchemaName = stmt.table.schema || this.getCurrentSchemaName();
558
- const tableName = stmt.table.name;
559
- let moduleName: string;
560
- let effectiveModuleArgs: Record<string, SqlValue>;
561
-
562
- if (stmt.moduleName) {
563
- moduleName = stmt.moduleName;
564
- effectiveModuleArgs = Object.freeze(stmt.moduleArgs || {});
565
- } else {
566
- const defaultVtab = this.getDefaultVTabModule();
567
- moduleName = defaultVtab.name;
568
- effectiveModuleArgs = Object.freeze(defaultVtab.args || {});
569
- }
570
-
571
- const moduleInfo = this.getModule(moduleName);
572
- if (!moduleInfo || !moduleInfo.module) {
573
- throw new QuereusError(`No virtual table module named '${moduleName}'`, StatusCode.ERROR, undefined, stmt.loc?.start.line, stmt.loc?.start.column);
574
- }
575
-
576
- const astColumnsToProcess = stmt.columns || [];
577
- const astConstraintsToProcess = stmt.constraints;
578
-
579
- // Get default nullability setting from database options
580
- const defaultNullability = this.db.options.getStringOption('default_column_nullability');
581
- const defaultNotNull = defaultNullability === 'not_null';
582
-
583
- const preliminaryColumnSchemas: ColumnSchema[] = astColumnsToProcess.map(colDef => columnDefToSchema(colDef, defaultNotNull));
584
- const pkDefinition = findPKDefinition(preliminaryColumnSchemas, astConstraintsToProcess);
585
-
586
- const finalColumnSchemas = preliminaryColumnSchemas.map((col, idx) => {
587
- const isPkColumn = pkDefinition.some(pkCol => pkCol.index === idx);
588
- let pkOrder = 0;
589
- if (isPkColumn) {
590
- pkOrder = pkDefinition.findIndex(pkC => pkC.index === idx) + 1;
591
- }
592
- return {
593
- ...col,
594
- primaryKey: isPkColumn,
595
- pkOrder: pkOrder,
596
- notNull: isPkColumn ? true : col.notNull,
597
- };
598
- });
599
-
600
- const checkConstraintsSchema: RowConstraintSchema[] = [];
601
- astColumnsToProcess.forEach(colDef => {
602
- colDef.constraints?.forEach(con => {
603
- if (con.type === 'check' && con.expr) {
604
- checkConstraintsSchema.push({
605
- name: con.name ?? `_check_${colDef.name}`,
606
- expr: con.expr,
607
- operations: opsToMask(con.operations)
608
- });
609
- }
610
- });
611
- });
612
- (astConstraintsToProcess || []).forEach(con => {
613
- if (con.type === 'check' && con.expr) {
614
- checkConstraintsSchema.push({
615
- name: con.name,
616
- expr: con.expr,
617
- operations: opsToMask(con.operations)
618
- });
619
- }
620
- });
621
-
622
- const baseTableSchema: TableSchema = {
623
- name: tableName,
624
- schemaName: targetSchemaName,
625
- columns: Object.freeze(finalColumnSchemas),
626
- columnIndexMap: buildColumnIndexMap(finalColumnSchemas),
627
- primaryKeyDefinition: pkDefinition,
628
- checkConstraints: Object.freeze(checkConstraintsSchema),
629
- isTemporary: !!stmt.isTemporary,
630
- isView: false,
631
- vtabModuleName: moduleName,
632
- vtabArgs: effectiveModuleArgs,
633
- vtabModule: moduleInfo.module,
634
- vtabAuxData: moduleInfo.auxData,
635
- estimatedRows: 0,
636
- };
637
-
638
- let tableInstance: VirtualTable;
639
- try {
640
- tableInstance = moduleInfo.module.xCreate(
641
- this.db,
642
- baseTableSchema
643
- );
644
- } catch (e: unknown) {
645
- const message = e instanceof Error ? e.message : String(e);
646
- const code = e instanceof QuereusError ? e.code : StatusCode.ERROR;
647
- throw new QuereusError(`Module '${moduleName}' xCreate failed for table '${tableName}': ${message}`, code, e instanceof Error ? e : undefined, stmt.loc?.start.line, stmt.loc?.start.column);
648
- }
649
-
650
- const schema = this.getSchema(targetSchemaName);
651
- if (!schema) {
652
- throw new QuereusError(`Internal error: Schema '${targetSchemaName}' not found.`, StatusCode.INTERNAL);
653
- }
654
-
655
- const finalRegisteredSchema = tableInstance.tableSchema;
656
- if (!finalRegisteredSchema) {
657
- throw new QuereusError(`Module '${moduleName}' xCreate did not provide a tableSchema for '${tableName}'.`, StatusCode.INTERNAL);
658
- }
659
-
660
- // Create a properly typed schema object instead of mutating properties
661
- let correctedSchema = finalRegisteredSchema;
662
- if (finalRegisteredSchema.name.toLowerCase() !== tableName.toLowerCase() ||
663
- finalRegisteredSchema.schemaName.toLowerCase() !== targetSchemaName.toLowerCase()) {
664
- warnLog(`Module ${moduleName} returned schema for ${finalRegisteredSchema.schemaName}.${finalRegisteredSchema.name} but expected ${targetSchemaName}.${tableName}. Correcting name/schemaName.`);
665
- correctedSchema = {
666
- ...finalRegisteredSchema,
667
- name: tableName,
668
- schemaName: targetSchemaName,
669
- };
670
- }
671
-
672
- // Ensure all required properties are properly set
673
- const completeTableSchema: TableSchema = {
674
- ...correctedSchema,
675
- vtabModuleName: moduleName,
676
- vtabArgs: effectiveModuleArgs,
677
- vtabModule: moduleInfo.module,
678
- vtabAuxData: moduleInfo.auxData,
679
- estimatedRows: correctedSchema.estimatedRows ?? 0,
680
- };
681
-
682
- const existingTable = schema.getTable(tableName);
683
- const existingView = schema.getView(tableName);
684
-
685
- if (existingTable || existingView) {
686
- if (stmt.ifNotExists) {
687
- log(`Skipping CREATE TABLE: Item %s.%s already exists (IF NOT EXISTS).`, targetSchemaName, tableName);
688
- if (existingTable) return existingTable;
689
- throw new QuereusError(`Cannot CREATE TABLE ${targetSchemaName}.${tableName}: a VIEW with the same name already exists.`, StatusCode.CONSTRAINT, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
690
- } else {
691
- const itemType = existingTable ? 'Table' : 'View';
692
- throw new QuereusError(`${itemType} ${targetSchemaName}.${tableName} already exists`, StatusCode.CONSTRAINT, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
693
- }
694
- }
695
-
696
- schema.addTable(completeTableSchema);
697
- log(`Successfully created table %s.%s using module %s`, targetSchemaName, tableName, moduleName);
698
-
699
- // Notify schema change listeners
700
- this.changeNotifier.notifyChange({
701
- type: 'table_added',
702
- schemaName: targetSchemaName,
703
- objectName: tableName,
704
- newObject: completeTableSchema
705
- });
706
-
707
- return completeTableSchema;
708
- }
709
- }
1
+ import { Schema } from './schema.js';
2
+ import type { IntegrityAssertionSchema } from './assertion.js';
3
+ import type { Database } from '../core/database.js';
4
+ import type { TableSchema, RowConstraintSchema, IndexSchema } from './table.js';
5
+ import type { FunctionSchema } from './function.js';
6
+ import { quereusError, QuereusError } from '../common/errors.js';
7
+ import { StatusCode, type SqlValue } from '../common/types.js';
8
+ import type { AnyVirtualTableModule, BaseModuleConfig } from '../vtab/module.js';
9
+ import type { VirtualTable } from '../vtab/table.js';
10
+ import type { ColumnSchema } from './column.js';
11
+ import { buildColumnIndexMap, columnDefToSchema, findPKDefinition, opsToMask, mutationContextVarToSchema } from './table.js';
12
+ import type { ViewSchema } from './view.js';
13
+ import { createLogger } from '../common/logger.js';
14
+ import type * as AST from '../parser/ast.js';
15
+ import { SchemaChangeNotifier } from './change-events.js';
16
+
17
+ const log = createLogger('schema:manager');
18
+ const warnLog = log.extend('warn');
19
+ const errorLog = log.extend('error');
20
+
21
+ /**
22
+ * Generic options passed to VTab modules during CREATE TABLE.
23
+ * Modules are responsible for interpreting these.
24
+ */
25
+ export interface GenericModuleCallOptions extends BaseModuleConfig {
26
+ moduleArgs?: readonly string[];
27
+ statementColumns?: readonly AST.ColumnDef[];
28
+ statementConstraints?: readonly AST.TableConstraint[];
29
+ isTemporary?: boolean;
30
+ }
31
+
32
+ /**
33
+ * Manages all schemas associated with a database connection (main, temp, attached).
34
+ * Handles lookup resolution according to SQLite's rules.
35
+ */
36
+ export class SchemaManager {
37
+ private schemas: Map<string, Schema> = new Map();
38
+ private currentSchemaName: string = 'main';
39
+ private modules: Map<string, { module: AnyVirtualTableModule, auxData?: unknown }> = new Map();
40
+ private defaultVTabModuleName: string = 'memory';
41
+ private defaultVTabModuleArgs: Record<string, SqlValue> = {};
42
+ private db: Database;
43
+ private changeNotifier = new SchemaChangeNotifier();
44
+
45
+ /**
46
+ * Creates a new schema manager
47
+ *
48
+ * @param db Reference to the parent Database instance
49
+ */
50
+ constructor(db: Database) {
51
+ this.db = db;
52
+ // Ensure 'main' and 'temp' schemas always exist
53
+ this.schemas.set('main', new Schema('main'));
54
+ this.schemas.set('temp', new Schema('temp'));
55
+ }
56
+
57
+ /**
58
+ * Sets the current default schema for unqualified names
59
+ *
60
+ * @param name Schema name to set as current
61
+ */
62
+ setCurrentSchema(name: string): void {
63
+ if (this.schemas.has(name.toLowerCase())) {
64
+ this.currentSchemaName = name.toLowerCase();
65
+ } else {
66
+ warnLog(`Attempted to set current schema to non-existent schema: %s`, name);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Gets the name of the current default schema
72
+ *
73
+ * @returns Current schema name
74
+ */
75
+ getCurrentSchemaName(): string {
76
+ return this.currentSchemaName;
77
+ }
78
+
79
+ /**
80
+ * Registers a virtual table module
81
+ *
82
+ * @param name Module name
83
+ * @param module Module implementation
84
+ * @param auxData Optional client data associated with the module registration
85
+ */
86
+ registerModule(name: string, module: AnyVirtualTableModule, auxData?: unknown): void {
87
+ const lowerName = name.toLowerCase();
88
+ if (this.modules.has(lowerName)) {
89
+ warnLog(`Replacing existing virtual table module: %s`, lowerName);
90
+ }
91
+ this.modules.set(lowerName, { module, auxData });
92
+ log(`Registered VTab module: %s`, lowerName);
93
+ }
94
+
95
+ /**
96
+ * Retrieves a registered virtual table module by name
97
+ *
98
+ * @param name Module name to look up
99
+ * @returns The module and its auxData, or undefined if not found
100
+ */
101
+ getModule(name: string): { module: AnyVirtualTableModule, auxData?: unknown } | undefined {
102
+ return this.modules.get(name.toLowerCase());
103
+ }
104
+
105
+ /**
106
+ * Sets the default virtual table module to use when USING is omitted
107
+ *
108
+ * @param name Module name. Must be a registered module.
109
+ * @throws QuereusError if the module name is not registered
110
+ */
111
+ setDefaultVTabModuleName(name: string): void {
112
+ const lowerName = name.toLowerCase();
113
+ if (this.modules.has(lowerName)) {
114
+ this.defaultVTabModuleName = lowerName;
115
+ log(`Default VTab module name set to: %s`, lowerName);
116
+ } else {
117
+ warnLog(`Setting default VTab module to '${lowerName}', which is not currently registered in SchemaManager. Ensure it gets registered.`);
118
+ this.defaultVTabModuleName = lowerName;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Gets the currently configured default virtual table module name
124
+ *
125
+ * @returns The default module name
126
+ */
127
+ getDefaultVTabModuleName(): string {
128
+ return this.defaultVTabModuleName;
129
+ }
130
+
131
+ /** @internal Sets the default VTab args directly */
132
+ setDefaultVTabArgs(args: Record<string, SqlValue>): void {
133
+ this.defaultVTabModuleArgs = args;
134
+ log('Default VTab module args set to: %o', args);
135
+ }
136
+
137
+ /** @internal Sets the default VTab args by parsing a JSON string */
138
+ setDefaultVTabArgsFromJson(argsJsonString: string): void {
139
+ try {
140
+ const parsedArgs = JSON.parse(argsJsonString);
141
+ if (typeof parsedArgs !== 'object') {
142
+ quereusError("JSON value must be an object.", StatusCode.MISUSE);
143
+ }
144
+ this.setDefaultVTabArgs(parsedArgs);
145
+ } catch (e) {
146
+ const msg = e instanceof Error ? e.message : String(e);
147
+ quereusError(`Invalid JSON for default_vtab_args: ${msg}`, StatusCode.ERROR);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Gets the default virtual table module arguments.
153
+ * @returns A copy of the default arguments array.
154
+ */
155
+ getDefaultVTabArgs(): Record<string, SqlValue> {
156
+ return { ...this.defaultVTabModuleArgs };
157
+ }
158
+
159
+ /**
160
+ * Gets the default virtual table module name and arguments.
161
+ * @returns An object containing the module name and arguments.
162
+ */
163
+ getDefaultVTabModule(): { name: string; args: Record<string, SqlValue> } {
164
+ return {
165
+ name: this.defaultVTabModuleName,
166
+ args: this.defaultVTabModuleArgs,
167
+ };
168
+ }
169
+
170
+ /**
171
+ * Gets a specific schema by name
172
+ *
173
+ * @param name Schema name to retrieve
174
+ * @returns The schema or undefined if not found
175
+ */
176
+ getSchema(name: string): Schema | undefined {
177
+ return this.schemas.get(name.toLowerCase());
178
+ }
179
+
180
+ /**
181
+ * Gets the 'main' schema
182
+ *
183
+ * @returns The main schema
184
+ */
185
+ getMainSchema(): Schema {
186
+ return this.schemas.get('main')!;
187
+ }
188
+
189
+ /**
190
+ * Gets the 'temp' schema
191
+ *
192
+ * @returns The temp schema
193
+ */
194
+ getTempSchema(): Schema {
195
+ return this.schemas.get('temp')!;
196
+ }
197
+
198
+ /**
199
+ * @internal Returns iterator over all managed schemas
200
+ */
201
+ _getAllSchemas(): IterableIterator<Schema> {
202
+ return this.schemas.values();
203
+ }
204
+
205
+ /**
206
+ * Returns all assertions across all schemas
207
+ */
208
+ getAllAssertions(): IntegrityAssertionSchema[] {
209
+ const result: IntegrityAssertionSchema[] = [];
210
+ for (const schema of this._getAllSchemas()) {
211
+ for (const a of schema.getAllAssertions()) {
212
+ result.push(a);
213
+ }
214
+ }
215
+ return result;
216
+ }
217
+
218
+ /**
219
+ * Gets the schema change notifier for listening to schema changes
220
+ */
221
+ getChangeNotifier(): SchemaChangeNotifier {
222
+ return this.changeNotifier;
223
+ }
224
+
225
+ /**
226
+ * Adds a new schema (e.g., for ATTACH)
227
+ *
228
+ * @param name Name of the schema to add
229
+ * @returns The newly created schema
230
+ * @throws QuereusError if the name conflicts with an existing schema
231
+ */
232
+ addSchema(name: string): Schema {
233
+ const lowerName = name.toLowerCase();
234
+ if (this.schemas.has(lowerName)) {
235
+ throw new QuereusError(`Schema '${name}' already exists`, StatusCode.ERROR);
236
+ }
237
+ const schema = new Schema(name);
238
+ this.schemas.set(lowerName, schema);
239
+ log(`Added schema '%s'`, name);
240
+ return schema;
241
+ }
242
+
243
+ /**
244
+ * Removes a schema (e.g., for DETACH)
245
+ *
246
+ * @param name Name of the schema to remove
247
+ * @returns true if found and removed, false otherwise
248
+ * @throws QuereusError if attempting to remove 'main' or 'temp'
249
+ */
250
+ removeSchema(name: string): boolean {
251
+ const lowerName = name.toLowerCase();
252
+ if (lowerName === 'main' || lowerName === 'temp') {
253
+ throw new QuereusError(`Cannot detach schema '${name}'`, StatusCode.ERROR);
254
+ }
255
+ const schema = this.schemas.get(lowerName);
256
+ if (schema) {
257
+ schema.clearFunctions();
258
+ schema.clearTables();
259
+ schema.clearViews();
260
+ this.schemas.delete(lowerName);
261
+ log(`Removed schema '%s'`, name);
262
+ return true;
263
+ }
264
+ return false;
265
+ }
266
+
267
+ /**
268
+ * @internal Finds a table or virtual table by name across schemas
269
+ */
270
+ _findTable(tableName: string, dbName?: string): TableSchema | undefined {
271
+ const lowerTableName = tableName.toLowerCase();
272
+
273
+
274
+
275
+ if (dbName) {
276
+ // Search specific schema
277
+ const schema = this.schemas.get(dbName.toLowerCase());
278
+ return schema?.getTable(lowerTableName);
279
+ } else {
280
+ // Search order: main, then temp (and attached later)
281
+ const mainSchema = this.schemas.get('main');
282
+ let table = mainSchema?.getTable(lowerTableName);
283
+ if (table) return table;
284
+
285
+ const tempSchema = this.schemas.get('temp');
286
+ table = tempSchema?.getTable(lowerTableName);
287
+ return table;
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Finds a table by name, searching schemas according to SQLite rules
293
+ *
294
+ * @param tableName Name of the table
295
+ * @param dbName Optional specific schema name to search
296
+ * @returns The TableSchema or undefined if not found
297
+ */
298
+ findTable(tableName: string, dbName?: string): TableSchema | undefined {
299
+ return this._findTable(tableName, dbName);
300
+ }
301
+
302
+ /**
303
+ * Finds a function by name and arg count, searching schemas
304
+ *
305
+ * @param funcName Name of the function
306
+ * @param nArg Number of arguments
307
+ * @returns The FunctionSchema or undefined if not found
308
+ */
309
+ findFunction(funcName: string, nArg: number): FunctionSchema | undefined {
310
+ return this.getMainSchema().getFunction(funcName, nArg);
311
+ }
312
+
313
+ /**
314
+ * Retrieves a view schema definition
315
+ *
316
+ * @param schemaName The name of the schema ('main', 'temp', etc.). Defaults to current schema
317
+ * @param viewName The name of the view
318
+ * @returns The ViewSchema or undefined if not found
319
+ */
320
+ getView(schemaName: string | null, viewName: string): ViewSchema | undefined {
321
+ const targetSchemaName = schemaName ?? this.currentSchemaName;
322
+ const schema = this.schemas.get(targetSchemaName);
323
+ return schema?.getView(viewName);
324
+ }
325
+
326
+ /**
327
+ * Retrieves any schema item (table or view) by name. Checks views first
328
+ *
329
+ * @param schemaName The name of the schema ('main', 'temp', etc.). Defaults to current schema
330
+ * @param itemName The name of the table or view
331
+ * @returns The TableSchema or ViewSchema, or undefined if not found
332
+ */
333
+ getSchemaItem(schemaName: string | null, itemName: string): TableSchema | ViewSchema | undefined {
334
+ const targetSchemaName = schemaName ?? this.currentSchemaName;
335
+ const schema = this.schemas.get(targetSchemaName);
336
+ if (!schema) return undefined;
337
+
338
+ // Prioritize views over tables if names conflict
339
+ const view = schema.getView(itemName);
340
+ if (view) return view;
341
+ return schema.getTable(itemName);
342
+ }
343
+
344
+ /**
345
+ * Drops a table from the specified schema
346
+ *
347
+ * @param schemaName The name of the schema
348
+ * @param tableName The name of the table to drop
349
+ * @param ifExists If true, do not throw an error if the table does not exist.
350
+ * @returns True if the table was found and dropped, false otherwise.
351
+ */
352
+ dropTable(schemaName: string, tableName: string, ifExists: boolean = false): boolean {
353
+ const schema = this.schemas.get(schemaName.toLowerCase()); // Ensure schemaName is lowercased for lookup
354
+ if (!schema) {
355
+ if (ifExists) return false; // Schema not found, but IF EXISTS specified
356
+ throw new QuereusError(`Schema not found: ${schemaName}`, StatusCode.ERROR);
357
+ }
358
+
359
+ const tableSchema = schema.getTable(tableName); // getTable should handle case-insensitivity
360
+
361
+ if (!tableSchema) {
362
+ if (ifExists) {
363
+ log(`Table %s.%s not found, but IF EXISTS was specified.`, schemaName, tableName);
364
+ return false; // Not found, but IF EXISTS means no error, not dropped.
365
+ }
366
+ throw new QuereusError(`Table ${tableName} not found in schema ${schemaName}`, StatusCode.NOTFOUND);
367
+ }
368
+
369
+ let destroyPromise: Promise<void> | null = null;
370
+
371
+ // Call xDestroy on the module, providing table details
372
+ if (tableSchema.vtabModuleName) { // tableSchema is guaranteed to be defined here
373
+ const moduleRegistration = this.getModule(tableSchema.vtabModuleName);
374
+ if (moduleRegistration && moduleRegistration.module && moduleRegistration.module.xDestroy) {
375
+ log(`Calling xDestroy for VTab %s.%s via module %s`, schemaName, tableName, tableSchema.vtabModuleName);
376
+ destroyPromise = moduleRegistration.module.xDestroy(
377
+ this.db,
378
+ moduleRegistration.auxData,
379
+ tableSchema.vtabModuleName,
380
+ schemaName,
381
+ tableName
382
+ ).catch(err => {
383
+ errorLog(`Error during VTab module xDestroy for %s.%s: %O`, schemaName, tableName, err);
384
+ // Potentially re-throw or handle as a critical error if xDestroy failure is problematic
385
+ });
386
+ } else {
387
+ warnLog(`VTab module %s (for table %s.%s) or its xDestroy method not found during dropTable.`, tableSchema.vtabModuleName, schemaName, tableName);
388
+ }
389
+ }
390
+
391
+ // Remove from schema map immediately
392
+ const removed = schema.removeTable(tableName);
393
+ if (!removed && !ifExists) {
394
+ // This should ideally not be reached if tableSchema was found above.
395
+ // But as a safeguard if removeTable could fail for other reasons.
396
+ throw new QuereusError(`Failed to remove table ${tableName} from schema ${schemaName}, though it was initially found.`, StatusCode.INTERNAL);
397
+ }
398
+
399
+ // Notify schema change listeners if table was removed
400
+ if (removed) {
401
+ this.changeNotifier.notifyChange({
402
+ type: 'table_removed',
403
+ schemaName: schemaName,
404
+ objectName: tableName,
405
+ oldObject: tableSchema
406
+ });
407
+ }
408
+
409
+ // Process destruction asynchronously
410
+ if (destroyPromise) {
411
+ void destroyPromise.then(() => log(`xDestroy completed for VTab %s.%s`, schemaName, tableName));
412
+ }
413
+
414
+ return removed; // True if removed from schema, false if not found and ifExists was true.
415
+ }
416
+
417
+ /**
418
+ * Drops a view from the specified schema
419
+ *
420
+ * @param schemaName The name of the schema
421
+ * @param viewName The name of the view to drop
422
+ * @returns True if the view was found and dropped, false otherwise
423
+ */
424
+ dropView(schemaName: string, viewName: string): boolean {
425
+ const schema = this.schemas.get(schemaName);
426
+ if (!schema) return false;
427
+ return schema.removeView(viewName);
428
+ }
429
+
430
+ /**
431
+ * Clears all schema items (tables, functions, views)
432
+ */
433
+ clearAll(): void {
434
+ this.schemas.forEach(schema => {
435
+ schema.clearTables();
436
+ schema.clearFunctions();
437
+ schema.clearViews();
438
+ });
439
+ log("Cleared all schemas.");
440
+ }
441
+
442
+ /**
443
+ * Retrieves a schema object, throwing if it doesn't exist
444
+ *
445
+ * @param name Schema name ('main', 'temp', or custom). Case-insensitive
446
+ * @returns The Schema object
447
+ * @throws QuereusError if the schema does not exist
448
+ */
449
+ getSchemaOrFail(name: string): Schema {
450
+ const schema = this.schemas.get(name.toLowerCase());
451
+ if (!schema) {
452
+ throw new QuereusError(`Schema not found: ${name}`);
453
+ }
454
+ return schema;
455
+ }
456
+
457
+ /**
458
+ * Retrieves a table from the specified schema
459
+ *
460
+ * @param schemaName The name of the schema ('main', 'temp', etc.). Defaults to current schema
461
+ * @param tableName The name of the table
462
+ * @returns The TableSchema or undefined if not found
463
+ */
464
+ getTable(schemaName: string | undefined, tableName: string): TableSchema | undefined {
465
+ const targetSchemaName = schemaName ?? this.currentSchemaName;
466
+ const schema = this.schemas.get(targetSchemaName);
467
+ return schema?.getTable(tableName);
468
+ }
469
+
470
+ /**
471
+ * Creates a new index on an existing table based on an AST.CreateIndexStmt.
472
+ * This method validates the index definition and calls the virtual table's xCreateIndex method.
473
+ *
474
+ * @param stmt The AST node for the CREATE INDEX statement.
475
+ * @returns A Promise that resolves when the index is created.
476
+ * @throws QuereusError on errors (e.g., table not found, column not found, xCreateIndex fails).
477
+ */
478
+ async createIndex(stmt: AST.CreateIndexStmt): Promise<void> {
479
+ const targetSchemaName = stmt.table.schema || this.getCurrentSchemaName();
480
+ const tableName = stmt.table.name;
481
+ const indexName = stmt.index.name;
482
+
483
+ // Find the table schema
484
+ const tableSchema = this.getTable(targetSchemaName, tableName);
485
+ if (!tableSchema) {
486
+ throw new QuereusError(`no such table: ${tableName}`, StatusCode.ERROR, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
487
+ }
488
+
489
+ // Check if the virtual table module supports xCreateIndex
490
+ if (!tableSchema.vtabModule.xCreateIndex) {
491
+ throw new QuereusError(`Virtual table module '${tableSchema.vtabModuleName}' for table '${tableName}' does not support CREATE INDEX.`, StatusCode.ERROR, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
492
+ }
493
+
494
+ // Check if index already exists (if not IF NOT EXISTS)
495
+ const existingIndex = tableSchema.indexes?.find(idx => idx.name.toLowerCase() === indexName.toLowerCase());
496
+ if (existingIndex) {
497
+ if (stmt.ifNotExists) {
498
+ log(`Skipping CREATE INDEX: Index %s.%s already exists (IF NOT EXISTS).`, targetSchemaName, indexName);
499
+ return;
500
+ } else {
501
+ throw new QuereusError(`Index ${indexName} already exists on table ${tableName}`, StatusCode.CONSTRAINT, undefined, stmt.index.loc?.start.line, stmt.index.loc?.start.column);
502
+ }
503
+ }
504
+
505
+ // Convert AST columns to IndexSchema columns
506
+ const indexColumns = stmt.columns.map((indexedCol: AST.IndexedColumn) => {
507
+ if (indexedCol.expr) {
508
+ throw new QuereusError(`Indices on expressions are not supported yet.`, StatusCode.ERROR, undefined, indexedCol.expr.loc?.start.line, indexedCol.expr.loc?.start.column);
509
+ }
510
+ const colName = indexedCol.name;
511
+ if (!colName) {
512
+ // Should not happen if expr is checked first
513
+ throw new QuereusError(`Indexed column must be a simple column name.`, StatusCode.ERROR);
514
+ }
515
+ const tableColIndex = tableSchema.columnIndexMap.get(colName.toLowerCase());
516
+ if (tableColIndex === undefined) {
517
+ throw new QuereusError(`Column '${colName}' not found in table '${tableName}'`, StatusCode.ERROR, undefined, stmt.loc?.start.line, stmt.loc?.start.column);
518
+ }
519
+ const tableColSchema = tableSchema.columns[tableColIndex];
520
+ return {
521
+ index: tableColIndex,
522
+ desc: indexedCol.direction === 'desc',
523
+ collation: indexedCol.collation || tableColSchema.collation // Use specified collation or inherit from table column
524
+ };
525
+ });
526
+
527
+ // Construct the IndexSchema object
528
+ const indexSchema: IndexSchema = {
529
+ name: indexName,
530
+ columns: Object.freeze(indexColumns),
531
+ };
532
+
533
+ try {
534
+ // Call xCreateIndex on the virtual table module
535
+ await tableSchema.vtabModule.xCreateIndex(
536
+ this.db,
537
+ targetSchemaName,
538
+ tableName,
539
+ indexSchema
540
+ );
541
+
542
+ // Update the table schema with the new index by creating a new schema object
543
+ const updatedIndexes = [...(tableSchema.indexes || []), indexSchema];
544
+ const updatedTableSchema: TableSchema = {
545
+ ...tableSchema,
546
+ indexes: Object.freeze(updatedIndexes),
547
+ };
548
+
549
+ // Replace the table schema in the schema
550
+ const schema = this.getSchemaOrFail(targetSchemaName);
551
+ schema.addTable(updatedTableSchema);
552
+
553
+ // Notify schema change listeners that the table was modified
554
+ this.changeNotifier.notifyChange({
555
+ type: 'table_modified',
556
+ schemaName: targetSchemaName,
557
+ objectName: tableName,
558
+ oldObject: tableSchema,
559
+ newObject: updatedTableSchema
560
+ });
561
+
562
+ log(`Successfully created index %s on table %s.%s`, indexName, targetSchemaName, tableName);
563
+ } catch (e: unknown) {
564
+ const message = e instanceof Error ? e.message : String(e);
565
+ const code = e instanceof QuereusError ? e.code : StatusCode.ERROR;
566
+ throw new QuereusError(`xCreateIndex failed for index '${indexName}' on table '${tableName}': ${message}`, code, e instanceof Error ? e : undefined, stmt.loc?.start.line, stmt.loc?.start.column);
567
+ }
568
+ }
569
+
570
+ /**
571
+ * Defines a new table in the schema based on an AST.CreateTableStmt.
572
+ * This method encapsulates the logic for interacting with VTab modules (xCreate)
573
+ * and registering the new table schema.
574
+ *
575
+ * @param stmt The AST node for the CREATE TABLE statement.
576
+ * @returns A Promise that resolves to the created TableSchema.
577
+ * @throws QuereusError on errors (e.g., module not found, xCreate fails, table exists).
578
+ */
579
+ async createTable(stmt: AST.CreateTableStmt): Promise<TableSchema> {
580
+ const targetSchemaName = stmt.table.schema || this.getCurrentSchemaName();
581
+ const tableName = stmt.table.name;
582
+ let moduleName: string;
583
+ let effectiveModuleArgs: Record<string, SqlValue>;
584
+
585
+ if (stmt.moduleName) {
586
+ moduleName = stmt.moduleName;
587
+ effectiveModuleArgs = Object.freeze(stmt.moduleArgs || {});
588
+ } else {
589
+ const defaultVtab = this.getDefaultVTabModule();
590
+ moduleName = defaultVtab.name;
591
+ effectiveModuleArgs = Object.freeze(defaultVtab.args || {});
592
+ }
593
+
594
+ const moduleInfo = this.getModule(moduleName);
595
+ if (!moduleInfo || !moduleInfo.module) {
596
+ throw new QuereusError(`No virtual table module named '${moduleName}'`, StatusCode.ERROR, undefined, stmt.loc?.start.line, stmt.loc?.start.column);
597
+ }
598
+
599
+ const astColumnsToProcess = stmt.columns || [];
600
+ const astConstraintsToProcess = stmt.constraints;
601
+
602
+ // Get default nullability setting from database options
603
+ const defaultNullability = this.db.options.getStringOption('default_column_nullability');
604
+ const defaultNotNull = defaultNullability === 'not_null';
605
+
606
+ const preliminaryColumnSchemas: ColumnSchema[] = astColumnsToProcess.map(colDef => columnDefToSchema(colDef, defaultNotNull));
607
+ const pkDefinition = findPKDefinition(preliminaryColumnSchemas, astConstraintsToProcess);
608
+
609
+ const finalColumnSchemas = preliminaryColumnSchemas.map((col, idx) => {
610
+ const isPkColumn = pkDefinition.some(pkCol => pkCol.index === idx);
611
+ let pkOrder = 0;
612
+ if (isPkColumn) {
613
+ pkOrder = pkDefinition.findIndex(pkC => pkC.index === idx) + 1;
614
+ }
615
+ return {
616
+ ...col,
617
+ primaryKey: isPkColumn,
618
+ pkOrder: pkOrder,
619
+ notNull: isPkColumn ? true : col.notNull,
620
+ };
621
+ });
622
+
623
+ const checkConstraintsSchema: RowConstraintSchema[] = [];
624
+ astColumnsToProcess.forEach(colDef => {
625
+ colDef.constraints?.forEach(con => {
626
+ if (con.type === 'check' && con.expr) {
627
+ checkConstraintsSchema.push({
628
+ name: con.name ?? `_check_${colDef.name}`,
629
+ expr: con.expr,
630
+ operations: opsToMask(con.operations),
631
+ deferrable: con.deferrable,
632
+ initiallyDeferred: con.initiallyDeferred
633
+ });
634
+ }
635
+ });
636
+ });
637
+ (astConstraintsToProcess || []).forEach(con => {
638
+ if (con.type === 'check' && con.expr) {
639
+ checkConstraintsSchema.push({
640
+ name: con.name,
641
+ expr: con.expr,
642
+ operations: opsToMask(con.operations),
643
+ deferrable: con.deferrable,
644
+ initiallyDeferred: con.initiallyDeferred
645
+ });
646
+ }
647
+ });
648
+
649
+ // Process mutation context definitions if present
650
+ const mutationContextSchemas = stmt.contextDefinitions
651
+ ? stmt.contextDefinitions.map(varDef => mutationContextVarToSchema(varDef, defaultNotNull))
652
+ : undefined;
653
+
654
+ const baseTableSchema: TableSchema = {
655
+ name: tableName,
656
+ schemaName: targetSchemaName,
657
+ columns: Object.freeze(finalColumnSchemas),
658
+ columnIndexMap: buildColumnIndexMap(finalColumnSchemas),
659
+ primaryKeyDefinition: pkDefinition,
660
+ checkConstraints: Object.freeze(checkConstraintsSchema),
661
+ isTemporary: !!stmt.isTemporary,
662
+ isView: false,
663
+ vtabModuleName: moduleName,
664
+ vtabArgs: effectiveModuleArgs,
665
+ vtabModule: moduleInfo.module,
666
+ vtabAuxData: moduleInfo.auxData,
667
+ estimatedRows: 0,
668
+ mutationContext: mutationContextSchemas ? Object.freeze(mutationContextSchemas) : undefined,
669
+ };
670
+
671
+ let tableInstance: VirtualTable;
672
+ try {
673
+ tableInstance = moduleInfo.module.xCreate(
674
+ this.db,
675
+ baseTableSchema
676
+ );
677
+ } catch (e: unknown) {
678
+ const message = e instanceof Error ? e.message : String(e);
679
+ const code = e instanceof QuereusError ? e.code : StatusCode.ERROR;
680
+ throw new QuereusError(`Module '${moduleName}' xCreate failed for table '${tableName}': ${message}`, code, e instanceof Error ? e : undefined, stmt.loc?.start.line, stmt.loc?.start.column);
681
+ }
682
+
683
+ const schema = this.getSchema(targetSchemaName);
684
+ if (!schema) {
685
+ throw new QuereusError(`Internal error: Schema '${targetSchemaName}' not found.`, StatusCode.INTERNAL);
686
+ }
687
+
688
+ const finalRegisteredSchema = tableInstance.tableSchema;
689
+ if (!finalRegisteredSchema) {
690
+ throw new QuereusError(`Module '${moduleName}' xCreate did not provide a tableSchema for '${tableName}'.`, StatusCode.INTERNAL);
691
+ }
692
+
693
+ // Create a properly typed schema object instead of mutating properties
694
+ let correctedSchema = finalRegisteredSchema;
695
+ if (finalRegisteredSchema.name.toLowerCase() !== tableName.toLowerCase() ||
696
+ finalRegisteredSchema.schemaName.toLowerCase() !== targetSchemaName.toLowerCase()) {
697
+ warnLog(`Module ${moduleName} returned schema for ${finalRegisteredSchema.schemaName}.${finalRegisteredSchema.name} but expected ${targetSchemaName}.${tableName}. Correcting name/schemaName.`);
698
+ correctedSchema = {
699
+ ...finalRegisteredSchema,
700
+ name: tableName,
701
+ schemaName: targetSchemaName,
702
+ };
703
+ }
704
+
705
+ // Ensure all required properties are properly set
706
+ const completeTableSchema: TableSchema = {
707
+ ...correctedSchema,
708
+ vtabModuleName: moduleName,
709
+ vtabArgs: effectiveModuleArgs,
710
+ vtabModule: moduleInfo.module,
711
+ vtabAuxData: moduleInfo.auxData,
712
+ estimatedRows: correctedSchema.estimatedRows ?? 0,
713
+ };
714
+
715
+ const existingTable = schema.getTable(tableName);
716
+ const existingView = schema.getView(tableName);
717
+
718
+ if (existingTable || existingView) {
719
+ if (stmt.ifNotExists) {
720
+ log(`Skipping CREATE TABLE: Item %s.%s already exists (IF NOT EXISTS).`, targetSchemaName, tableName);
721
+ if (existingTable) return existingTable;
722
+ throw new QuereusError(`Cannot CREATE TABLE ${targetSchemaName}.${tableName}: a VIEW with the same name already exists.`, StatusCode.CONSTRAINT, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
723
+ } else {
724
+ const itemType = existingTable ? 'Table' : 'View';
725
+ throw new QuereusError(`${itemType} ${targetSchemaName}.${tableName} already exists`, StatusCode.CONSTRAINT, undefined, stmt.table.loc?.start.line, stmt.table.loc?.start.column);
726
+ }
727
+ }
728
+
729
+ schema.addTable(completeTableSchema);
730
+ log(`Successfully created table %s.%s using module %s`, targetSchemaName, tableName, moduleName);
731
+
732
+ // Notify schema change listeners
733
+ this.changeNotifier.notifyChange({
734
+ type: 'table_added',
735
+ schemaName: targetSchemaName,
736
+ objectName: tableName,
737
+ newObject: completeTableSchema
738
+ });
739
+
740
+ return completeTableSchema;
741
+ }
742
+ }