@quereus/quereus 4.3.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (788) hide show
  1. package/README.md +25 -7
  2. package/dist/src/common/types.d.ts +9 -59
  3. package/dist/src/common/types.d.ts.map +1 -1
  4. package/dist/src/common/types.js.map +1 -1
  5. package/dist/src/core/database-assertions.d.ts +2 -2
  6. package/dist/src/core/database-assertions.d.ts.map +1 -1
  7. package/dist/src/core/database-assertions.js +4 -3
  8. package/dist/src/core/database-assertions.js.map +1 -1
  9. package/dist/src/core/database-external-changes.d.ts +3 -3
  10. package/dist/src/core/database-external-changes.d.ts.map +1 -1
  11. package/dist/src/core/database-external-changes.js +13 -10
  12. package/dist/src/core/database-external-changes.js.map +1 -1
  13. package/dist/src/core/database-internal.d.ts.map +1 -1
  14. package/dist/src/core/database-materialized-views-analysis.d.ts +199 -0
  15. package/dist/src/core/database-materialized-views-analysis.d.ts.map +1 -0
  16. package/dist/src/core/database-materialized-views-analysis.js +502 -0
  17. package/dist/src/core/database-materialized-views-analysis.js.map +1 -0
  18. package/dist/src/core/database-materialized-views-apply.d.ts +422 -0
  19. package/dist/src/core/database-materialized-views-apply.d.ts.map +1 -0
  20. package/dist/src/core/database-materialized-views-apply.js +929 -0
  21. package/dist/src/core/database-materialized-views-apply.js.map +1 -0
  22. package/dist/src/core/database-materialized-views-plan-builders.d.ts +267 -0
  23. package/dist/src/core/database-materialized-views-plan-builders.d.ts.map +1 -0
  24. package/dist/src/core/database-materialized-views-plan-builders.js +1423 -0
  25. package/dist/src/core/database-materialized-views-plan-builders.js.map +1 -0
  26. package/dist/src/core/database-materialized-views-plans.d.ts +641 -0
  27. package/dist/src/core/database-materialized-views-plans.d.ts.map +1 -0
  28. package/dist/src/core/database-materialized-views-plans.js +13 -0
  29. package/dist/src/core/database-materialized-views-plans.js.map +1 -0
  30. package/dist/src/core/database-materialized-views.d.ts +108 -860
  31. package/dist/src/core/database-materialized-views.d.ts.map +1 -1
  32. package/dist/src/core/database-materialized-views.js +212 -2165
  33. package/dist/src/core/database-materialized-views.js.map +1 -1
  34. package/dist/src/core/database-transaction.d.ts +10 -1
  35. package/dist/src/core/database-transaction.d.ts.map +1 -1
  36. package/dist/src/core/database-transaction.js +16 -4
  37. package/dist/src/core/database-transaction.js.map +1 -1
  38. package/dist/src/core/database-watchers.d.ts.map +1 -1
  39. package/dist/src/core/database-watchers.js +2 -1
  40. package/dist/src/core/database-watchers.js.map +1 -1
  41. package/dist/src/core/database.d.ts +99 -13
  42. package/dist/src/core/database.d.ts.map +1 -1
  43. package/dist/src/core/database.js +270 -50
  44. package/dist/src/core/database.js.map +1 -1
  45. package/dist/src/core/derived-row-validator.d.ts +1 -1
  46. package/dist/src/core/derived-row-validator.d.ts.map +1 -1
  47. package/dist/src/core/derived-row-validator.js +5 -3
  48. package/dist/src/core/derived-row-validator.js.map +1 -1
  49. package/dist/src/core/statement.d.ts +8 -0
  50. package/dist/src/core/statement.d.ts.map +1 -1
  51. package/dist/src/core/statement.js +98 -18
  52. package/dist/src/core/statement.js.map +1 -1
  53. package/dist/src/emit/ast-stringify.d.ts.map +1 -1
  54. package/dist/src/emit/ast-stringify.js +24 -13
  55. package/dist/src/emit/ast-stringify.js.map +1 -1
  56. package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
  57. package/dist/src/func/builtins/aggregate.js +127 -21
  58. package/dist/src/func/builtins/aggregate.js.map +1 -1
  59. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  60. package/dist/src/func/builtins/explain.js +2 -1
  61. package/dist/src/func/builtins/explain.js.map +1 -1
  62. package/dist/src/func/builtins/json.d.ts.map +1 -1
  63. package/dist/src/func/builtins/json.js +2 -1
  64. package/dist/src/func/builtins/json.js.map +1 -1
  65. package/dist/src/func/builtins/mutation.d.ts.map +1 -1
  66. package/dist/src/func/builtins/mutation.js +3 -2
  67. package/dist/src/func/builtins/mutation.js.map +1 -1
  68. package/dist/src/func/registration.d.ts +6 -1
  69. package/dist/src/func/registration.d.ts.map +1 -1
  70. package/dist/src/func/registration.js +16 -0
  71. package/dist/src/func/registration.js.map +1 -1
  72. package/dist/src/index.d.ts +16 -6
  73. package/dist/src/index.d.ts.map +1 -1
  74. package/dist/src/index.js +33 -7
  75. package/dist/src/index.js.map +1 -1
  76. package/dist/src/parser/ast.d.ts +2 -2
  77. package/dist/src/parser/lexer.d.ts +11 -1
  78. package/dist/src/parser/lexer.d.ts.map +1 -1
  79. package/dist/src/parser/lexer.js +40 -34
  80. package/dist/src/parser/lexer.js.map +1 -1
  81. package/dist/src/parser/parser.d.ts.map +1 -1
  82. package/dist/src/parser/parser.js +16 -9
  83. package/dist/src/parser/parser.js.map +1 -1
  84. package/dist/src/planner/analysis/authored-inverse.js +1 -1
  85. package/dist/src/planner/analysis/comparison-collation.d.ts +52 -0
  86. package/dist/src/planner/analysis/comparison-collation.d.ts.map +1 -1
  87. package/dist/src/planner/analysis/comparison-collation.js +84 -7
  88. package/dist/src/planner/analysis/comparison-collation.js.map +1 -1
  89. package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
  90. package/dist/src/planner/analysis/constraint-extractor.js +64 -17
  91. package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
  92. package/dist/src/planner/analysis/coverage-prover.d.ts +1 -1
  93. package/dist/src/planner/analysis/coverage-prover.js +1 -1
  94. package/dist/src/planner/analysis/equi-correlation.d.ts +26 -0
  95. package/dist/src/planner/analysis/equi-correlation.d.ts.map +1 -0
  96. package/dist/src/planner/analysis/equi-correlation.js +62 -0
  97. package/dist/src/planner/analysis/equi-correlation.js.map +1 -0
  98. package/dist/src/planner/analysis/query-rewrite-matcher.d.ts +54 -18
  99. package/dist/src/planner/analysis/query-rewrite-matcher.d.ts.map +1 -1
  100. package/dist/src/planner/analysis/query-rewrite-matcher.js +86 -42
  101. package/dist/src/planner/analysis/query-rewrite-matcher.js.map +1 -1
  102. package/dist/src/planner/analysis/sat-checker.d.ts +8 -1
  103. package/dist/src/planner/analysis/sat-checker.d.ts.map +1 -1
  104. package/dist/src/planner/analysis/sat-checker.js +117 -22
  105. package/dist/src/planner/analysis/sat-checker.js.map +1 -1
  106. package/dist/src/planner/analysis/scalar-invertibility.d.ts +13 -4
  107. package/dist/src/planner/analysis/scalar-invertibility.d.ts.map +1 -1
  108. package/dist/src/planner/analysis/scalar-invertibility.js +12 -3
  109. package/dist/src/planner/analysis/scalar-invertibility.js.map +1 -1
  110. package/dist/src/planner/analysis/scalar-subqueries.d.ts +28 -0
  111. package/dist/src/planner/analysis/scalar-subqueries.d.ts.map +1 -0
  112. package/dist/src/planner/analysis/scalar-subqueries.js +60 -0
  113. package/dist/src/planner/analysis/scalar-subqueries.js.map +1 -0
  114. package/dist/src/planner/analysis/update-lineage.d.ts +1 -1
  115. package/dist/src/planner/analysis/update-lineage.js +1 -1
  116. package/dist/src/planner/analysis/update-lineage.js.map +1 -1
  117. package/dist/src/planner/analysis/view-complement.d.ts +2 -2
  118. package/dist/src/planner/building/delete.js +2 -2
  119. package/dist/src/planner/building/delete.js.map +1 -1
  120. package/dist/src/planner/building/dml-target.d.ts +2 -2
  121. package/dist/src/planner/building/dml-target.js +2 -2
  122. package/dist/src/planner/building/insert.d.ts.map +1 -1
  123. package/dist/src/planner/building/insert.js +53 -2
  124. package/dist/src/planner/building/insert.js.map +1 -1
  125. package/dist/src/planner/building/schema-resolution.d.ts +3 -0
  126. package/dist/src/planner/building/schema-resolution.d.ts.map +1 -1
  127. package/dist/src/planner/building/schema-resolution.js +4 -5
  128. package/dist/src/planner/building/schema-resolution.js.map +1 -1
  129. package/dist/src/planner/building/select.d.ts.map +1 -1
  130. package/dist/src/planner/building/select.js +18 -4
  131. package/dist/src/planner/building/select.js.map +1 -1
  132. package/dist/src/planner/building/update.js +2 -2
  133. package/dist/src/planner/building/update.js.map +1 -1
  134. package/dist/src/planner/building/view-mutation-builder.js +7 -7
  135. package/dist/src/planner/building/view-mutation-builder.js.map +1 -1
  136. package/dist/src/planner/building/with.d.ts.map +1 -1
  137. package/dist/src/planner/building/with.js +5 -8
  138. package/dist/src/planner/building/with.js.map +1 -1
  139. package/dist/src/planner/cache/materialization-advisory.d.ts +34 -2
  140. package/dist/src/planner/cache/materialization-advisory.d.ts.map +1 -1
  141. package/dist/src/planner/cache/materialization-advisory.js +185 -42
  142. package/dist/src/planner/cache/materialization-advisory.js.map +1 -1
  143. package/dist/src/planner/cache/reference-graph.d.ts +14 -5
  144. package/dist/src/planner/cache/reference-graph.d.ts.map +1 -1
  145. package/dist/src/planner/cache/reference-graph.js +31 -39
  146. package/dist/src/planner/cache/reference-graph.js.map +1 -1
  147. package/dist/src/planner/cost/index.d.ts +30 -5
  148. package/dist/src/planner/cost/index.d.ts.map +1 -1
  149. package/dist/src/planner/cost/index.js +26 -0
  150. package/dist/src/planner/cost/index.js.map +1 -1
  151. package/dist/src/planner/debug.d.ts +3 -2
  152. package/dist/src/planner/debug.d.ts.map +1 -1
  153. package/dist/src/planner/debug.js +9 -3
  154. package/dist/src/planner/debug.js.map +1 -1
  155. package/dist/src/planner/framework/characteristics.d.ts +46 -19
  156. package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
  157. package/dist/src/planner/framework/characteristics.js +50 -134
  158. package/dist/src/planner/framework/characteristics.js.map +1 -1
  159. package/dist/src/planner/framework/context.d.ts +8 -44
  160. package/dist/src/planner/framework/context.d.ts.map +1 -1
  161. package/dist/src/planner/framework/context.js +0 -91
  162. package/dist/src/planner/framework/context.js.map +1 -1
  163. package/dist/src/planner/framework/pass.d.ts +7 -0
  164. package/dist/src/planner/framework/pass.d.ts.map +1 -1
  165. package/dist/src/planner/framework/pass.js +84 -0
  166. package/dist/src/planner/framework/pass.js.map +1 -1
  167. package/dist/src/planner/framework/registry.d.ts +13 -42
  168. package/dist/src/planner/framework/registry.d.ts.map +1 -1
  169. package/dist/src/planner/framework/registry.js +14 -182
  170. package/dist/src/planner/framework/registry.js.map +1 -1
  171. package/dist/src/planner/mutation/backward-body.d.ts +2 -2
  172. package/dist/src/planner/mutation/cte-flatten.js +1 -1
  173. package/dist/src/planner/mutation/decomposition.d.ts +2 -2
  174. package/dist/src/planner/mutation/decomposition.js +1 -1
  175. package/dist/src/planner/mutation/lens-enforcement.d.ts.map +1 -1
  176. package/dist/src/planner/mutation/lens-enforcement.js +2 -1
  177. package/dist/src/planner/mutation/lens-enforcement.js.map +1 -1
  178. package/dist/src/planner/mutation/multi-source.d.ts +8 -8
  179. package/dist/src/planner/mutation/multi-source.js +11 -11
  180. package/dist/src/planner/mutation/multi-source.js.map +1 -1
  181. package/dist/src/planner/mutation/propagate.d.ts +1 -1
  182. package/dist/src/planner/mutation/propagate.js +1 -1
  183. package/dist/src/planner/mutation/scope-transform.d.ts +2 -2
  184. package/dist/src/planner/mutation/scope-transform.js +3 -3
  185. package/dist/src/planner/mutation/scope-transform.js.map +1 -1
  186. package/dist/src/planner/mutation/set-op.d.ts +1 -1
  187. package/dist/src/planner/mutation/set-op.d.ts.map +1 -1
  188. package/dist/src/planner/mutation/set-op.js +3 -2
  189. package/dist/src/planner/mutation/set-op.js.map +1 -1
  190. package/dist/src/planner/mutation/single-source.d.ts +3 -3
  191. package/dist/src/planner/mutation/single-source.js +9 -9
  192. package/dist/src/planner/mutation/single-source.js.map +1 -1
  193. package/dist/src/planner/nodes/aggregate-function.d.ts +3 -1
  194. package/dist/src/planner/nodes/aggregate-function.d.ts.map +1 -1
  195. package/dist/src/planner/nodes/aggregate-function.js +1 -0
  196. package/dist/src/planner/nodes/aggregate-function.js.map +1 -1
  197. package/dist/src/planner/nodes/aggregate-node.d.ts +1 -0
  198. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  199. package/dist/src/planner/nodes/aggregate-node.js +8 -1
  200. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  201. package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
  202. package/dist/src/planner/nodes/alias-node.js +3 -1
  203. package/dist/src/planner/nodes/alias-node.js.map +1 -1
  204. package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -1
  205. package/dist/src/planner/nodes/asof-scan-node.js +3 -2
  206. package/dist/src/planner/nodes/asof-scan-node.js.map +1 -1
  207. package/dist/src/planner/nodes/asserted-keys-node.d.ts +1 -1
  208. package/dist/src/planner/nodes/asserted-keys-node.d.ts.map +1 -1
  209. package/dist/src/planner/nodes/asserted-keys-node.js +5 -2
  210. package/dist/src/planner/nodes/asserted-keys-node.js.map +1 -1
  211. package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -1
  212. package/dist/src/planner/nodes/async-gather-node.js +3 -1
  213. package/dist/src/planner/nodes/async-gather-node.js.map +1 -1
  214. package/dist/src/planner/nodes/block.js +3 -3
  215. package/dist/src/planner/nodes/block.js.map +1 -1
  216. package/dist/src/planner/nodes/bloom-join-node.d.ts +2 -0
  217. package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
  218. package/dist/src/planner/nodes/bloom-join-node.js +5 -1
  219. package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
  220. package/dist/src/planner/nodes/cache-node.d.ts +19 -2
  221. package/dist/src/planner/nodes/cache-node.d.ts.map +1 -1
  222. package/dist/src/planner/nodes/cache-node.js +43 -3
  223. package/dist/src/planner/nodes/cache-node.js.map +1 -1
  224. package/dist/src/planner/nodes/cte-node.d.ts +16 -1
  225. package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
  226. package/dist/src/planner/nodes/cte-node.js +16 -3
  227. package/dist/src/planner/nodes/cte-node.js.map +1 -1
  228. package/dist/src/planner/nodes/distinct-node.js +3 -3
  229. package/dist/src/planner/nodes/distinct-node.js.map +1 -1
  230. package/dist/src/planner/nodes/dml-executor-node.d.ts +21 -0
  231. package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
  232. package/dist/src/planner/nodes/dml-executor-node.js.map +1 -1
  233. package/dist/src/planner/nodes/envelope-scan-node.d.ts +1 -1
  234. package/dist/src/planner/nodes/envelope-scan-node.js +1 -1
  235. package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts.map +1 -1
  236. package/dist/src/planner/nodes/fanout-lookup-join-node.js +4 -2
  237. package/dist/src/planner/nodes/fanout-lookup-join-node.js.map +1 -1
  238. package/dist/src/planner/nodes/filter.d.ts +10 -2
  239. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  240. package/dist/src/planner/nodes/filter.js +81 -14
  241. package/dist/src/planner/nodes/filter.js.map +1 -1
  242. package/dist/src/planner/nodes/hash-aggregate.d.ts +12 -1
  243. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
  244. package/dist/src/planner/nodes/hash-aggregate.js +28 -1
  245. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
  246. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts +3 -1
  247. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts.map +1 -1
  248. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js +1 -0
  249. package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js.map +1 -1
  250. package/dist/src/planner/nodes/join-node.d.ts +3 -1
  251. package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
  252. package/dist/src/planner/nodes/join-node.js +5 -5
  253. package/dist/src/planner/nodes/join-node.js.map +1 -1
  254. package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts.map +1 -1
  255. package/dist/src/planner/nodes/lens-auxiliary-access-node.js +4 -1
  256. package/dist/src/planner/nodes/lens-auxiliary-access-node.js.map +1 -1
  257. package/dist/src/planner/nodes/limit-offset.d.ts +1 -0
  258. package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
  259. package/dist/src/planner/nodes/limit-offset.js +4 -3
  260. package/dist/src/planner/nodes/limit-offset.js.map +1 -1
  261. package/dist/src/planner/nodes/merge-join-node.d.ts +2 -0
  262. package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
  263. package/dist/src/planner/nodes/merge-join-node.js +6 -1
  264. package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
  265. package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -1
  266. package/dist/src/planner/nodes/ordinal-slice-node.js +3 -1
  267. package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
  268. package/dist/src/planner/nodes/plan-node.d.ts +68 -5
  269. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  270. package/dist/src/planner/nodes/plan-node.js +137 -24
  271. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  272. package/dist/src/planner/nodes/project-node.d.ts +3 -2
  273. package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
  274. package/dist/src/planner/nodes/project-node.js +1 -0
  275. package/dist/src/planner/nodes/project-node.js.map +1 -1
  276. package/dist/src/planner/nodes/recursive-cte-node.d.ts +30 -1
  277. package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -1
  278. package/dist/src/planner/nodes/recursive-cte-node.js +38 -5
  279. package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -1
  280. package/dist/src/planner/nodes/reference.d.ts +5 -1
  281. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  282. package/dist/src/planner/nodes/reference.js +3 -0
  283. package/dist/src/planner/nodes/reference.js.map +1 -1
  284. package/dist/src/planner/nodes/remote-query-node.d.ts.map +1 -1
  285. package/dist/src/planner/nodes/remote-query-node.js +3 -1
  286. package/dist/src/planner/nodes/remote-query-node.js.map +1 -1
  287. package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
  288. package/dist/src/planner/nodes/retrieve-node.js +3 -1
  289. package/dist/src/planner/nodes/retrieve-node.js.map +1 -1
  290. package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
  291. package/dist/src/planner/nodes/set-operation-node.js +3 -1
  292. package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
  293. package/dist/src/planner/nodes/sink-node.d.ts.map +1 -1
  294. package/dist/src/planner/nodes/sink-node.js +3 -1
  295. package/dist/src/planner/nodes/sink-node.js.map +1 -1
  296. package/dist/src/planner/nodes/sort.d.ts +2 -1
  297. package/dist/src/planner/nodes/sort.d.ts.map +1 -1
  298. package/dist/src/planner/nodes/sort.js +9 -5
  299. package/dist/src/planner/nodes/sort.js.map +1 -1
  300. package/dist/src/planner/nodes/stream-aggregate.d.ts +12 -1
  301. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  302. package/dist/src/planner/nodes/stream-aggregate.js +32 -3
  303. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  304. package/dist/src/planner/nodes/table-access-nodes.d.ts +2 -1
  305. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  306. package/dist/src/planner/nodes/table-access-nodes.js +2 -0
  307. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  308. package/dist/src/planner/nodes/view-mutation-node.d.ts +2 -2
  309. package/dist/src/planner/nodes/view-mutation-node.d.ts.map +1 -1
  310. package/dist/src/planner/nodes/view-mutation-node.js +5 -1
  311. package/dist/src/planner/nodes/view-mutation-node.js.map +1 -1
  312. package/dist/src/planner/nodes/window-function.d.ts +3 -1
  313. package/dist/src/planner/nodes/window-function.d.ts.map +1 -1
  314. package/dist/src/planner/nodes/window-function.js +1 -0
  315. package/dist/src/planner/nodes/window-function.js.map +1 -1
  316. package/dist/src/planner/optimizer.d.ts +52 -8
  317. package/dist/src/planner/optimizer.d.ts.map +1 -1
  318. package/dist/src/planner/optimizer.js +1014 -895
  319. package/dist/src/planner/optimizer.js.map +1 -1
  320. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  321. package/dist/src/planner/rules/access/rule-select-access-path.js +235 -202
  322. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  323. package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts.map +1 -1
  324. package/dist/src/planner/rules/cache/rule-cte-optimization.js +8 -1
  325. package/dist/src/planner/rules/cache/rule-cte-optimization.js.map +1 -1
  326. package/dist/src/planner/rules/cache/rule-in-subquery-cache.d.ts +7 -0
  327. package/dist/src/planner/rules/cache/rule-in-subquery-cache.d.ts.map +1 -1
  328. package/dist/src/planner/rules/cache/rule-in-subquery-cache.js +14 -1
  329. package/dist/src/planner/rules/cache/rule-in-subquery-cache.js.map +1 -1
  330. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts +2 -2
  331. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts.map +1 -1
  332. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js +55 -56
  333. package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js.map +1 -1
  334. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts.map +1 -1
  335. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js +6 -0
  336. package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js.map +1 -1
  337. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.d.ts +25 -0
  338. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.d.ts.map +1 -0
  339. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js +176 -0
  340. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js.map +1 -0
  341. package/dist/src/planner/rules/cache/rule-scalar-cse.d.ts +1 -1
  342. package/dist/src/planner/rules/cache/rule-scalar-cse.js +1 -1
  343. package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.d.ts +29 -0
  344. package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.d.ts.map +1 -0
  345. package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.js +66 -0
  346. package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.js.map +1 -0
  347. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts +1 -1
  348. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +1 -1
  349. package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts.map +1 -1
  350. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +1 -54
  351. package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -1
  352. package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.d.ts +1 -1
  353. package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.js +1 -1
  354. package/dist/src/planner/rules/join/rule-join-elimination.d.ts +1 -1
  355. package/dist/src/planner/rules/join/rule-join-elimination.js +1 -1
  356. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js +5 -6
  357. package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js.map +1 -1
  358. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts +1 -1
  359. package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +1 -1
  360. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts +2 -2
  361. package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -1
  362. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +4 -3
  363. package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -1
  364. package/dist/src/planner/rules/predicate/rule-filter-selectivity.d.ts +19 -0
  365. package/dist/src/planner/rules/predicate/rule-filter-selectivity.d.ts.map +1 -0
  366. package/dist/src/planner/rules/predicate/rule-filter-selectivity.js +48 -0
  367. package/dist/src/planner/rules/predicate/rule-filter-selectivity.js.map +1 -0
  368. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js +12 -1
  369. package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js.map +1 -1
  370. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -1
  371. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +22 -20
  372. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
  373. package/dist/src/planner/rules/shared/index-style-context.d.ts +39 -0
  374. package/dist/src/planner/rules/shared/index-style-context.d.ts.map +1 -0
  375. package/dist/src/planner/rules/shared/index-style-context.js +26 -0
  376. package/dist/src/planner/rules/shared/index-style-context.js.map +1 -0
  377. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +1 -1
  378. package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +1 -1
  379. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts +1 -1
  380. package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +1 -1
  381. package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.d.ts +191 -0
  382. package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.d.ts.map +1 -0
  383. package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.js +623 -0
  384. package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.js.map +1 -0
  385. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts +10 -1
  386. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
  387. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +242 -51
  388. package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
  389. package/dist/src/planner/stats/analyze.d.ts.map +1 -1
  390. package/dist/src/planner/stats/analyze.js +2 -20
  391. package/dist/src/planner/stats/analyze.js.map +1 -1
  392. package/dist/src/planner/stats/histogram.d.ts.map +1 -1
  393. package/dist/src/planner/stats/histogram.js +4 -0
  394. package/dist/src/planner/stats/histogram.js.map +1 -1
  395. package/dist/src/planner/util/fd-utils.d.ts +2 -3
  396. package/dist/src/planner/util/fd-utils.d.ts.map +1 -1
  397. package/dist/src/planner/util/fd-utils.js +2 -3
  398. package/dist/src/planner/util/fd-utils.js.map +1 -1
  399. package/dist/src/planner/validation/plan-validator.d.ts +16 -0
  400. package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
  401. package/dist/src/planner/validation/plan-validator.js +36 -0
  402. package/dist/src/planner/validation/plan-validator.js.map +1 -1
  403. package/dist/src/runtime/async-util.d.ts +26 -0
  404. package/dist/src/runtime/async-util.d.ts.map +1 -1
  405. package/dist/src/runtime/async-util.js +139 -55
  406. package/dist/src/runtime/async-util.js.map +1 -1
  407. package/dist/src/runtime/cache/shared-cache.d.ts +7 -0
  408. package/dist/src/runtime/cache/shared-cache.d.ts.map +1 -1
  409. package/dist/src/runtime/cache/shared-cache.js +34 -1
  410. package/dist/src/runtime/cache/shared-cache.js.map +1 -1
  411. package/dist/src/runtime/context-helpers.d.ts +32 -4
  412. package/dist/src/runtime/context-helpers.d.ts.map +1 -1
  413. package/dist/src/runtime/context-helpers.js +26 -9
  414. package/dist/src/runtime/context-helpers.js.map +1 -1
  415. package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
  416. package/dist/src/runtime/deferred-constraint-queue.js +2 -1
  417. package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
  418. package/dist/src/runtime/emission-context.d.ts +27 -3
  419. package/dist/src/runtime/emission-context.d.ts.map +1 -1
  420. package/dist/src/runtime/emission-context.js +38 -7
  421. package/dist/src/runtime/emission-context.js.map +1 -1
  422. package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -1
  423. package/dist/src/runtime/emit/add-constraint.js +7 -1
  424. package/dist/src/runtime/emit/add-constraint.js.map +1 -1
  425. package/dist/src/runtime/emit/aggregate.d.ts +2 -3
  426. package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
  427. package/dist/src/runtime/emit/aggregate.js +23 -28
  428. package/dist/src/runtime/emit/aggregate.js.map +1 -1
  429. package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
  430. package/dist/src/runtime/emit/alter-table.js +98 -9
  431. package/dist/src/runtime/emit/alter-table.js.map +1 -1
  432. package/dist/src/runtime/emit/analyze.d.ts.map +1 -1
  433. package/dist/src/runtime/emit/analyze.js +2 -1
  434. package/dist/src/runtime/emit/analyze.js.map +1 -1
  435. package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -1
  436. package/dist/src/runtime/emit/asof-scan.js +13 -10
  437. package/dist/src/runtime/emit/asof-scan.js.map +1 -1
  438. package/dist/src/runtime/emit/async-gather.d.ts.map +1 -1
  439. package/dist/src/runtime/emit/async-gather.js +4 -3
  440. package/dist/src/runtime/emit/async-gather.js.map +1 -1
  441. package/dist/src/runtime/emit/between.d.ts.map +1 -1
  442. package/dist/src/runtime/emit/between.js +2 -1
  443. package/dist/src/runtime/emit/between.js.map +1 -1
  444. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  445. package/dist/src/runtime/emit/binary.js +122 -14
  446. package/dist/src/runtime/emit/binary.js.map +1 -1
  447. package/dist/src/runtime/emit/block.d.ts.map +1 -1
  448. package/dist/src/runtime/emit/block.js +2 -1
  449. package/dist/src/runtime/emit/block.js.map +1 -1
  450. package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
  451. package/dist/src/runtime/emit/bloom-join.js +20 -8
  452. package/dist/src/runtime/emit/bloom-join.js.map +1 -1
  453. package/dist/src/runtime/emit/cache.d.ts +7 -3
  454. package/dist/src/runtime/emit/cache.d.ts.map +1 -1
  455. package/dist/src/runtime/emit/cache.js +25 -7
  456. package/dist/src/runtime/emit/cache.js.map +1 -1
  457. package/dist/src/runtime/emit/case.d.ts.map +1 -1
  458. package/dist/src/runtime/emit/case.js +66 -45
  459. package/dist/src/runtime/emit/case.js.map +1 -1
  460. package/dist/src/runtime/emit/cast.d.ts.map +1 -1
  461. package/dist/src/runtime/emit/cast.js +2 -1
  462. package/dist/src/runtime/emit/cast.js.map +1 -1
  463. package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
  464. package/dist/src/runtime/emit/constraint-check.js +13 -7
  465. package/dist/src/runtime/emit/constraint-check.js.map +1 -1
  466. package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
  467. package/dist/src/runtime/emit/create-assertion.js +2 -1
  468. package/dist/src/runtime/emit/create-assertion.js.map +1 -1
  469. package/dist/src/runtime/emit/create-index.d.ts.map +1 -1
  470. package/dist/src/runtime/emit/create-index.js +12 -1
  471. package/dist/src/runtime/emit/create-index.js.map +1 -1
  472. package/dist/src/runtime/emit/create-table.d.ts.map +1 -1
  473. package/dist/src/runtime/emit/create-table.js +12 -1
  474. package/dist/src/runtime/emit/create-table.js.map +1 -1
  475. package/dist/src/runtime/emit/cte-reference.d.ts.map +1 -1
  476. package/dist/src/runtime/emit/cte-reference.js +2 -1
  477. package/dist/src/runtime/emit/cte-reference.js.map +1 -1
  478. package/dist/src/runtime/emit/cte.d.ts.map +1 -1
  479. package/dist/src/runtime/emit/cte.js +45 -21
  480. package/dist/src/runtime/emit/cte.js.map +1 -1
  481. package/dist/src/runtime/emit/ddl-transaction-policy.d.ts +50 -0
  482. package/dist/src/runtime/emit/ddl-transaction-policy.d.ts.map +1 -0
  483. package/dist/src/runtime/emit/ddl-transaction-policy.js +69 -0
  484. package/dist/src/runtime/emit/ddl-transaction-policy.js.map +1 -0
  485. package/dist/src/runtime/emit/delete.d.ts.map +1 -1
  486. package/dist/src/runtime/emit/delete.js +2 -1
  487. package/dist/src/runtime/emit/delete.js.map +1 -1
  488. package/dist/src/runtime/emit/distinct.d.ts.map +1 -1
  489. package/dist/src/runtime/emit/distinct.js +2 -1
  490. package/dist/src/runtime/emit/distinct.js.map +1 -1
  491. package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
  492. package/dist/src/runtime/emit/dml-executor.js +138 -74
  493. package/dist/src/runtime/emit/dml-executor.js.map +1 -1
  494. package/dist/src/runtime/emit/drop-assertion.d.ts.map +1 -1
  495. package/dist/src/runtime/emit/drop-assertion.js +2 -1
  496. package/dist/src/runtime/emit/drop-assertion.js.map +1 -1
  497. package/dist/src/runtime/emit/drop-index.d.ts.map +1 -1
  498. package/dist/src/runtime/emit/drop-index.js +17 -1
  499. package/dist/src/runtime/emit/drop-index.js.map +1 -1
  500. package/dist/src/runtime/emit/drop-table.d.ts.map +1 -1
  501. package/dist/src/runtime/emit/drop-table.js +11 -1
  502. package/dist/src/runtime/emit/drop-table.js.map +1 -1
  503. package/dist/src/runtime/emit/eager-prefetch.d.ts.map +1 -1
  504. package/dist/src/runtime/emit/eager-prefetch.js +2 -1
  505. package/dist/src/runtime/emit/eager-prefetch.js.map +1 -1
  506. package/dist/src/runtime/emit/envelope-scan.d.ts.map +1 -1
  507. package/dist/src/runtime/emit/envelope-scan.js +2 -1
  508. package/dist/src/runtime/emit/envelope-scan.js.map +1 -1
  509. package/dist/src/runtime/emit/fanout-lookup-join.d.ts.map +1 -1
  510. package/dist/src/runtime/emit/fanout-lookup-join.js +3 -2
  511. package/dist/src/runtime/emit/fanout-lookup-join.js.map +1 -1
  512. package/dist/src/runtime/emit/filter.d.ts.map +1 -1
  513. package/dist/src/runtime/emit/filter.js +8 -3
  514. package/dist/src/runtime/emit/filter.js.map +1 -1
  515. package/dist/src/runtime/emit/hash-aggregate.d.ts.map +1 -1
  516. package/dist/src/runtime/emit/hash-aggregate.js +16 -11
  517. package/dist/src/runtime/emit/hash-aggregate.js.map +1 -1
  518. package/dist/src/runtime/emit/insert.d.ts.map +1 -1
  519. package/dist/src/runtime/emit/insert.js +2 -1
  520. package/dist/src/runtime/emit/insert.js.map +1 -1
  521. package/dist/src/runtime/emit/join.d.ts.map +1 -1
  522. package/dist/src/runtime/emit/join.js +20 -6
  523. package/dist/src/runtime/emit/join.js.map +1 -1
  524. package/dist/src/runtime/emit/limit-offset.d.ts.map +1 -1
  525. package/dist/src/runtime/emit/limit-offset.js +2 -1
  526. package/dist/src/runtime/emit/limit-offset.js.map +1 -1
  527. package/dist/src/runtime/emit/literal.d.ts.map +1 -1
  528. package/dist/src/runtime/emit/literal.js +2 -1
  529. package/dist/src/runtime/emit/literal.js.map +1 -1
  530. package/dist/src/runtime/emit/materialized-view-helpers.d.ts +22 -0
  531. package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -1
  532. package/dist/src/runtime/emit/materialized-view-helpers.js +128 -16
  533. package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -1
  534. package/dist/src/runtime/emit/materialized-view.d.ts.map +1 -1
  535. package/dist/src/runtime/emit/materialized-view.js +6 -0
  536. package/dist/src/runtime/emit/materialized-view.js.map +1 -1
  537. package/dist/src/runtime/emit/merge-join.d.ts.map +1 -1
  538. package/dist/src/runtime/emit/merge-join.js +14 -4
  539. package/dist/src/runtime/emit/merge-join.js.map +1 -1
  540. package/dist/src/runtime/emit/ordinal-slice.d.ts.map +1 -1
  541. package/dist/src/runtime/emit/ordinal-slice.js +2 -1
  542. package/dist/src/runtime/emit/ordinal-slice.js.map +1 -1
  543. package/dist/src/runtime/emit/pragma.d.ts.map +1 -1
  544. package/dist/src/runtime/emit/pragma.js +2 -1
  545. package/dist/src/runtime/emit/pragma.js.map +1 -1
  546. package/dist/src/runtime/emit/project.d.ts.map +1 -1
  547. package/dist/src/runtime/emit/project.js +7 -2
  548. package/dist/src/runtime/emit/project.js.map +1 -1
  549. package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
  550. package/dist/src/runtime/emit/recursive-cte.js +61 -2
  551. package/dist/src/runtime/emit/recursive-cte.js.map +1 -1
  552. package/dist/src/runtime/emit/returning.d.ts.map +1 -1
  553. package/dist/src/runtime/emit/returning.js +7 -2
  554. package/dist/src/runtime/emit/returning.js.map +1 -1
  555. package/dist/src/runtime/emit/scalar-function.d.ts.map +1 -1
  556. package/dist/src/runtime/emit/scalar-function.js +2 -1
  557. package/dist/src/runtime/emit/scalar-function.js.map +1 -1
  558. package/dist/src/runtime/emit/scan.d.ts.map +1 -1
  559. package/dist/src/runtime/emit/scan.js +55 -17
  560. package/dist/src/runtime/emit/scan.js.map +1 -1
  561. package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
  562. package/dist/src/runtime/emit/schema-declarative.js +6 -5
  563. package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
  564. package/dist/src/runtime/emit/sequencing.d.ts.map +1 -1
  565. package/dist/src/runtime/emit/sequencing.js +2 -1
  566. package/dist/src/runtime/emit/sequencing.js.map +1 -1
  567. package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
  568. package/dist/src/runtime/emit/set-operation.js +6 -5
  569. package/dist/src/runtime/emit/set-operation.js.map +1 -1
  570. package/dist/src/runtime/emit/sink.d.ts.map +1 -1
  571. package/dist/src/runtime/emit/sink.js +2 -1
  572. package/dist/src/runtime/emit/sink.js.map +1 -1
  573. package/dist/src/runtime/emit/sort.d.ts.map +1 -1
  574. package/dist/src/runtime/emit/sort.js +2 -1
  575. package/dist/src/runtime/emit/sort.js.map +1 -1
  576. package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
  577. package/dist/src/runtime/emit/subquery.js +42 -23
  578. package/dist/src/runtime/emit/subquery.js.map +1 -1
  579. package/dist/src/runtime/emit/table-valued-function.d.ts.map +1 -1
  580. package/dist/src/runtime/emit/table-valued-function.js +2 -1
  581. package/dist/src/runtime/emit/table-valued-function.js.map +1 -1
  582. package/dist/src/runtime/emit/temporal-arithmetic.d.ts.map +1 -1
  583. package/dist/src/runtime/emit/temporal-arithmetic.js +2 -1
  584. package/dist/src/runtime/emit/temporal-arithmetic.js.map +1 -1
  585. package/dist/src/runtime/emit/transaction.d.ts.map +1 -1
  586. package/dist/src/runtime/emit/transaction.js +2 -1
  587. package/dist/src/runtime/emit/transaction.js.map +1 -1
  588. package/dist/src/runtime/emit/unary.d.ts.map +1 -1
  589. package/dist/src/runtime/emit/unary.js +2 -1
  590. package/dist/src/runtime/emit/unary.js.map +1 -1
  591. package/dist/src/runtime/emit/update.d.ts.map +1 -1
  592. package/dist/src/runtime/emit/update.js +2 -1
  593. package/dist/src/runtime/emit/update.js.map +1 -1
  594. package/dist/src/runtime/emit/values.d.ts.map +1 -1
  595. package/dist/src/runtime/emit/values.js +2 -1
  596. package/dist/src/runtime/emit/values.js.map +1 -1
  597. package/dist/src/runtime/emit/view-mutation.d.ts +1 -1
  598. package/dist/src/runtime/emit/view-mutation.d.ts.map +1 -1
  599. package/dist/src/runtime/emit/view-mutation.js +6 -3
  600. package/dist/src/runtime/emit/view-mutation.js.map +1 -1
  601. package/dist/src/runtime/emit/window.d.ts.map +1 -1
  602. package/dist/src/runtime/emit/window.js +26 -9
  603. package/dist/src/runtime/emit/window.js.map +1 -1
  604. package/dist/src/runtime/emitters.d.ts +11 -3
  605. package/dist/src/runtime/emitters.d.ts.map +1 -1
  606. package/dist/src/runtime/emitters.js +13 -22
  607. package/dist/src/runtime/emitters.js.map +1 -1
  608. package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
  609. package/dist/src/runtime/foreign-key-actions.js +39 -13
  610. package/dist/src/runtime/foreign-key-actions.js.map +1 -1
  611. package/dist/src/runtime/parallel-driver.d.ts +32 -4
  612. package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
  613. package/dist/src/runtime/parallel-driver.js +88 -18
  614. package/dist/src/runtime/parallel-driver.js.map +1 -1
  615. package/dist/src/runtime/scheduler.d.ts +56 -7
  616. package/dist/src/runtime/scheduler.d.ts.map +1 -1
  617. package/dist/src/runtime/scheduler.js +223 -200
  618. package/dist/src/runtime/scheduler.js.map +1 -1
  619. package/dist/src/runtime/strict-flags.d.ts +22 -0
  620. package/dist/src/runtime/strict-flags.d.ts.map +1 -0
  621. package/dist/src/runtime/strict-flags.js +26 -0
  622. package/dist/src/runtime/strict-flags.js.map +1 -0
  623. package/dist/src/runtime/strict-fork.d.ts +4 -4
  624. package/dist/src/runtime/strict-fork.d.ts.map +1 -1
  625. package/dist/src/runtime/strict-fork.js +175 -31
  626. package/dist/src/runtime/strict-fork.js.map +1 -1
  627. package/dist/src/runtime/types.d.ts +102 -4
  628. package/dist/src/runtime/types.d.ts.map +1 -1
  629. package/dist/src/runtime/types.js +37 -0
  630. package/dist/src/runtime/types.js.map +1 -1
  631. package/dist/src/runtime/utils.d.ts.map +1 -1
  632. package/dist/src/runtime/utils.js +8 -17
  633. package/dist/src/runtime/utils.js.map +1 -1
  634. package/dist/src/schema/column.d.ts +8 -0
  635. package/dist/src/schema/column.d.ts.map +1 -1
  636. package/dist/src/schema/column.js.map +1 -1
  637. package/dist/src/schema/ddl-generator.js +5 -0
  638. package/dist/src/schema/ddl-generator.js.map +1 -1
  639. package/dist/src/schema/function.d.ts +79 -0
  640. package/dist/src/schema/function.d.ts.map +1 -1
  641. package/dist/src/schema/function.js.map +1 -1
  642. package/dist/src/schema/lens-compiler.js +2 -2
  643. package/dist/src/schema/lens-compiler.js.map +1 -1
  644. package/dist/src/schema/lens-prover.d.ts.map +1 -1
  645. package/dist/src/schema/lens-prover.js +2 -3
  646. package/dist/src/schema/lens-prover.js.map +1 -1
  647. package/dist/src/schema/lens.d.ts +1 -1
  648. package/dist/src/schema/manager.d.ts.map +1 -1
  649. package/dist/src/schema/manager.js +7 -2
  650. package/dist/src/schema/manager.js.map +1 -1
  651. package/dist/src/schema/rename-rewriter.d.ts +61 -0
  652. package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
  653. package/dist/src/schema/rename-rewriter.js +77 -0
  654. package/dist/src/schema/rename-rewriter.js.map +1 -1
  655. package/dist/src/schema/table.d.ts +36 -8
  656. package/dist/src/schema/table.d.ts.map +1 -1
  657. package/dist/src/schema/table.js +61 -11
  658. package/dist/src/schema/table.js.map +1 -1
  659. package/dist/src/schema/unique-enforcement.d.ts +28 -5
  660. package/dist/src/schema/unique-enforcement.d.ts.map +1 -1
  661. package/dist/src/schema/unique-enforcement.js +37 -5
  662. package/dist/src/schema/unique-enforcement.js.map +1 -1
  663. package/dist/src/schema/view.d.ts +1 -1
  664. package/dist/src/schema/view.js +1 -1
  665. package/dist/src/types/json-type.d.ts.map +1 -1
  666. package/dist/src/types/json-type.js +18 -8
  667. package/dist/src/types/json-type.js.map +1 -1
  668. package/dist/src/types/logical-type.d.ts +26 -0
  669. package/dist/src/types/logical-type.d.ts.map +1 -1
  670. package/dist/src/types/logical-type.js.map +1 -1
  671. package/dist/src/util/comparison.d.ts +83 -59
  672. package/dist/src/util/comparison.d.ts.map +1 -1
  673. package/dist/src/util/comparison.js +191 -131
  674. package/dist/src/util/comparison.js.map +1 -1
  675. package/dist/src/util/json-canonical.d.ts +34 -0
  676. package/dist/src/util/json-canonical.d.ts.map +1 -0
  677. package/dist/src/util/json-canonical.js +32 -0
  678. package/dist/src/util/json-canonical.js.map +1 -0
  679. package/dist/src/util/key-serializer.d.ts +10 -3
  680. package/dist/src/util/key-serializer.d.ts.map +1 -1
  681. package/dist/src/util/key-serializer.js +43 -17
  682. package/dist/src/util/key-serializer.js.map +1 -1
  683. package/dist/src/util/key-tuple-codec.d.ts +37 -0
  684. package/dist/src/util/key-tuple-codec.d.ts.map +1 -0
  685. package/dist/src/util/key-tuple-codec.js +65 -0
  686. package/dist/src/util/key-tuple-codec.js.map +1 -0
  687. package/dist/src/util/latches.d.ts +29 -3
  688. package/dist/src/util/latches.d.ts.map +1 -1
  689. package/dist/src/util/latches.js +60 -6
  690. package/dist/src/util/latches.js.map +1 -1
  691. package/dist/src/util/patterns.d.ts +22 -8
  692. package/dist/src/util/patterns.d.ts.map +1 -1
  693. package/dist/src/util/patterns.js +87 -16
  694. package/dist/src/util/patterns.js.map +1 -1
  695. package/dist/src/util/qualified-name.d.ts +10 -0
  696. package/dist/src/util/qualified-name.d.ts.map +1 -0
  697. package/dist/src/util/qualified-name.js +15 -0
  698. package/dist/src/util/qualified-name.js.map +1 -0
  699. package/dist/src/vtab/backing-host.d.ts +8 -1
  700. package/dist/src/vtab/backing-host.d.ts.map +1 -1
  701. package/dist/src/vtab/backing-host.js +7 -0
  702. package/dist/src/vtab/backing-host.js.map +1 -1
  703. package/dist/src/vtab/best-access-plan.d.ts +18 -0
  704. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  705. package/dist/src/vtab/best-access-plan.js +15 -0
  706. package/dist/src/vtab/best-access-plan.js.map +1 -1
  707. package/dist/src/vtab/capabilities.d.ts +44 -0
  708. package/dist/src/vtab/capabilities.d.ts.map +1 -1
  709. package/dist/src/vtab/filter-info.d.ts +42 -0
  710. package/dist/src/vtab/filter-info.d.ts.map +1 -1
  711. package/dist/src/vtab/filter-info.js +137 -1
  712. package/dist/src/vtab/filter-info.js.map +1 -1
  713. package/dist/src/vtab/idx-str.d.ts +62 -0
  714. package/dist/src/vtab/idx-str.d.ts.map +1 -0
  715. package/dist/src/vtab/idx-str.js +130 -0
  716. package/dist/src/vtab/idx-str.js.map +1 -0
  717. package/dist/src/vtab/index-descriptor.d.ts +122 -0
  718. package/dist/src/vtab/index-descriptor.d.ts.map +1 -0
  719. package/dist/src/vtab/index-descriptor.js +104 -0
  720. package/dist/src/vtab/index-descriptor.js.map +1 -0
  721. package/dist/src/vtab/mapping-advertisement.d.ts +1 -1
  722. package/dist/src/vtab/memory/index.d.ts +12 -4
  723. package/dist/src/vtab/memory/index.d.ts.map +1 -1
  724. package/dist/src/vtab/memory/index.js +17 -9
  725. package/dist/src/vtab/memory/index.js.map +1 -1
  726. package/dist/src/vtab/memory/layer/base.d.ts +85 -31
  727. package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
  728. package/dist/src/vtab/memory/layer/base.js +127 -86
  729. package/dist/src/vtab/memory/layer/base.js.map +1 -1
  730. package/dist/src/vtab/memory/layer/connection.d.ts +27 -0
  731. package/dist/src/vtab/memory/layer/connection.d.ts.map +1 -1
  732. package/dist/src/vtab/memory/layer/connection.js +36 -1
  733. package/dist/src/vtab/memory/layer/connection.js.map +1 -1
  734. package/dist/src/vtab/memory/layer/interface.d.ts +24 -4
  735. package/dist/src/vtab/memory/layer/interface.d.ts.map +1 -1
  736. package/dist/src/vtab/memory/layer/manager.d.ts +212 -16
  737. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  738. package/dist/src/vtab/memory/layer/manager.js +754 -170
  739. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  740. package/dist/src/vtab/memory/layer/plan-filter.d.ts +26 -1
  741. package/dist/src/vtab/memory/layer/plan-filter.d.ts.map +1 -1
  742. package/dist/src/vtab/memory/layer/plan-filter.js +29 -11
  743. package/dist/src/vtab/memory/layer/plan-filter.js.map +1 -1
  744. package/dist/src/vtab/memory/layer/safe-iterate.d.ts +2 -2
  745. package/dist/src/vtab/memory/layer/safe-iterate.d.ts.map +1 -1
  746. package/dist/src/vtab/memory/layer/safe-iterate.js +2 -2
  747. package/dist/src/vtab/memory/layer/safe-iterate.js.map +1 -1
  748. package/dist/src/vtab/memory/layer/scan-layer.d.ts +5 -1
  749. package/dist/src/vtab/memory/layer/scan-layer.d.ts.map +1 -1
  750. package/dist/src/vtab/memory/layer/scan-layer.js +59 -24
  751. package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
  752. package/dist/src/vtab/memory/layer/scan-plan.d.ts.map +1 -1
  753. package/dist/src/vtab/memory/layer/scan-plan.js +13 -21
  754. package/dist/src/vtab/memory/layer/scan-plan.js.map +1 -1
  755. package/dist/src/vtab/memory/layer/transaction.d.ts +169 -7
  756. package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
  757. package/dist/src/vtab/memory/layer/transaction.js +334 -9
  758. package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
  759. package/dist/src/vtab/memory/module.d.ts +11 -4
  760. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  761. package/dist/src/vtab/memory/module.js +35 -16
  762. package/dist/src/vtab/memory/module.js.map +1 -1
  763. package/dist/src/vtab/memory/table.d.ts +30 -4
  764. package/dist/src/vtab/memory/table.d.ts.map +1 -1
  765. package/dist/src/vtab/memory/table.js +63 -15
  766. package/dist/src/vtab/memory/table.js.map +1 -1
  767. package/dist/src/vtab/memory/utils/predicate.d.ts +9 -1
  768. package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
  769. package/dist/src/vtab/memory/utils/predicate.js +35 -14
  770. package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
  771. package/dist/src/vtab/memory/utils/primary-key-encode.d.ts.map +1 -1
  772. package/dist/src/vtab/memory/utils/primary-key-encode.js +12 -6
  773. package/dist/src/vtab/memory/utils/primary-key-encode.js.map +1 -1
  774. package/dist/src/vtab/memory/utils/primary-key.d.ts +6 -1
  775. package/dist/src/vtab/memory/utils/primary-key.d.ts.map +1 -1
  776. package/dist/src/vtab/memory/utils/primary-key.js +12 -8
  777. package/dist/src/vtab/memory/utils/primary-key.js.map +1 -1
  778. package/dist/src/vtab/module.d.ts +38 -14
  779. package/dist/src/vtab/module.d.ts.map +1 -1
  780. package/dist/src/vtab/table.d.ts +41 -2
  781. package/dist/src/vtab/table.d.ts.map +1 -1
  782. package/dist/src/vtab/table.js +19 -0
  783. package/dist/src/vtab/table.js.map +1 -1
  784. package/package.json +5 -4
  785. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts +0 -18
  786. package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts.map +0 -1
  787. package/dist/src/planner/rules/cache/rule-materialization-advisory.js +0 -65
  788. package/dist/src/planner/rules/cache/rule-materialization-advisory.js.map +0 -1
@@ -16,6 +16,9 @@ import { RetrieveNode } from '../../nodes/retrieve-node.js';
16
16
  import { RemoteQueryNode } from '../../nodes/remote-query-node.js';
17
17
  import { SeqScanNode, IndexScanNode, IndexSeekNode, EmptyResultNode } from '../../nodes/table-access-nodes.js';
18
18
  import { seqScanCost } from '../../cost/index.js';
19
+ import { makeEmptyFilterInfo, makeFullScanFilterInfo } from '../../../vtab/filter-info.js';
20
+ import { PRIMARY_INDEX_NAME, PRIMARY_PHYSICAL_INDEX_NAME, resolveIndexDescriptor } from '../../../vtab/index-descriptor.js';
21
+ import { encodeIdxStr, makeIdxStrSpec } from '../../../vtab/idx-str.js';
19
22
  import { compareSqlValues, normalizeCollationName } from '../../../util/comparison.js';
20
23
  import { FilterNode } from '../../nodes/filter.js';
21
24
  import { extractConstraintsForTable, createTableInfoFromNode } from '../../analysis/constraint-extractor.js';
@@ -23,7 +26,64 @@ import { LiteralNode, BinaryOpNode, BetweenNode } from '../../nodes/scalar.js';
23
26
  import { InNode } from '../../nodes/subquery.js';
24
27
  import { effectiveBetweenBoundCollation, effectiveComparisonCollation, effectiveInCollation } from '../../analysis/comparison-collation.js';
25
28
  import { IndexConstraintOp } from '../../../common/constants.js';
29
+ import { isIndexStyleContext } from '../shared/index-style-context.js';
26
30
  const log = createLogger('optimizer:rule:select-access-path');
31
+ const warnLog = createLogger('optimizer:rule:select-access-path').extend('warn');
32
+ /**
33
+ * Resolve the structured {@link AccessPath} for an index arm.
34
+ *
35
+ * `indexName` is the name that lands in `idxStr` — `accessPlan.indexName` for a seek,
36
+ * `accessPlan.orderingIndexName` for an ordering-only walk, `_primary_` for the legacy
37
+ * arms. When the engine cannot resolve it (a per-plan alias the module minted without
38
+ * supplying an `indexDescriptor`) we record `unresolvedIndex` and warn, rather than
39
+ * guessing: an order-sensitive consumer must be able to refuse the plan.
40
+ */
41
+ function buildIndexAccessPath(tableSchema, accessPlan, indexName, plan) {
42
+ const index = resolveIndexDescriptor(tableSchema, accessPlan, indexName);
43
+ if (index)
44
+ return { kind: 'index', index, plan };
45
+ warnLog('access plan for table %s named index %s which the engine cannot resolve; module should return indexDescriptor', tableSchema.name, indexName);
46
+ return { kind: 'unresolvedIndex', indexName, plan };
47
+ }
48
+ /**
49
+ * Derive a seek/scan FilterInfo from the arm's shared `base`: the encoded `idxStr` and
50
+ * the structured `accessPath` are both projections of the same (indexName, plan, params)
51
+ * triple, so they cannot drift.
52
+ */
53
+ function makeIndexFilterInfo(base, tableSchema, accessPlan, indexName, plan, constraints, params) {
54
+ const idxStr = encodeIdxStr(makeIdxStrSpec(indexName, plan, params));
55
+ return {
56
+ ...base,
57
+ constraints,
58
+ idxStr,
59
+ accessPath: buildIndexAccessPath(tableSchema, accessPlan, indexName, plan),
60
+ indexInfoOutput: {
61
+ ...base.indexInfoOutput,
62
+ idxStr,
63
+ // Reflect the seek's consumed constraints so EXPLAIN's matchedClauses
64
+ // counts them; `base` is seeded from a full scan and carries none.
65
+ aConstraintUsage: constraints.map(c => ({ argvIndex: c.argvIndex, omit: true })),
66
+ },
67
+ };
68
+ }
69
+ /**
70
+ * Derive the FilterInfo for an ordering-only index walk (`plan=0`). Unlike a seek this
71
+ * also stamps `indexInfoOutput.idxStr` and `orderByConsumed`, because the runtime reads
72
+ * the consumed-ordering flag off the IndexInfo rather than the FilterInfo.
73
+ */
74
+ function makeOrderedScanFilterInfo(base, tableSchema, accessPlan, indexName) {
75
+ const idxStr = encodeIdxStr(makeIdxStrSpec(indexName, 'scan'));
76
+ return {
77
+ ...base,
78
+ idxStr,
79
+ accessPath: buildIndexAccessPath(tableSchema, accessPlan, indexName, 'scan'),
80
+ indexInfoOutput: {
81
+ ...base.indexInfoOutput,
82
+ idxStr,
83
+ orderByConsumed: true,
84
+ },
85
+ };
86
+ }
27
87
  /**
28
88
  * Extract the monotonic-ordering advertisement from a `BestAccessPlanResult`,
29
89
  * or return undefined when nothing is advertised. The result is forwarded to
@@ -117,7 +177,7 @@ function createIndexBasedAccess(retrieveNode, context) {
117
177
  // Use pre-computed access plan from grow rule
118
178
  log('Using pre-computed access plan from grow rule');
119
179
  accessPlan = retrieveNode.moduleCtx.accessPlan;
120
- constraints = retrieveNode.moduleCtx.originalConstraints || [];
180
+ constraints = retrieveNode.moduleCtx.originalConstraints;
121
181
  residualPredicate = retrieveNode.moduleCtx.residualPredicate;
122
182
  }
123
183
  else {
@@ -141,7 +201,14 @@ function createIndexBasedAccess(retrieveNode, context) {
141
201
  }
142
202
  // Choose physical node based on access plan
143
203
  const physicalLeaf = selectPhysicalNode(retrieveNode.tableRef, accessPlan, constraints);
144
- // If the Retrieve source contained a pipeline (e.g., Filter/Sort/Project), rebuild it above the physical leaf
204
+ // If the Retrieve source contained a pipeline (e.g., Filter/Sort/Project), rebuild it above the physical leaf.
205
+ //
206
+ // NOTE: on this path (no index-style moduleCtx) an absorbed `Filter` in `source` is
207
+ // preserved verbatim, so a constraint that `reattachUnconsumedConstraints` recovers is
208
+ // already applied above — the reattached `Filter` is then redundant, not wrong. Only
209
+ // reachable for a module exposing BOTH `supports()` (declining here) and
210
+ // `getBestAccessPlan()`. If that ever shows up as a duplicated predicate in EXPLAIN,
211
+ // pass the consumed set out and skip the reattach when `source !== tableRef`.
145
212
  let rebuiltPipeline = physicalLeaf;
146
213
  if (retrieveNode.source !== retrieveNode.tableRef) {
147
214
  log('Rebuilding Retrieve pipeline above physical access node');
@@ -173,6 +240,45 @@ function rebuildPipelineWithNewLeaf(pipelineRoot, oldLeaf, newLeaf) {
173
240
  });
174
241
  return pipelineRoot.withChildren(newChildren);
175
242
  }
243
+ /**
244
+ * The constraint operators this rule can turn into seek bounds, and therefore the
245
+ * only ones {@link reattachUnconsumedConstraints} can recover when a module claims
246
+ * a filter the rule never consumes.
247
+ *
248
+ * NOTE: ops outside this set (IS NULL / IS NOT NULL / LIKE / GLOB / MATCH / NOT IN) are never
249
+ * pushed into FilterInfo by this rule, so a module claiming one is taken at its word.
250
+ * Sound today: the only such claim is memory's tautological IS NOT NULL on a NOT NULL
251
+ * column. If a module ever claims a non-tautological non-seek op, its predicate is lost
252
+ * — widen this set, or make grow-retrieve refuse the claim.
253
+ */
254
+ const RECLAIMABLE_OPS = new Set(['=', 'IN', '>', '>=', '<', '<=', 'OR_RANGE']);
255
+ /**
256
+ * `handledFilters[i] === true` is a module's promise that filter `i` will be enforced
257
+ * somewhere else — and the only "somewhere else" available is `FilterInfo.constraints`
258
+ * (the seek bounds this rule builds). This rule consumes at most one constraint per
259
+ * column per role: the first `=`/`IN`, the first lower bound, the first upper bound.
260
+ * A module that claims a redundant same-column same-role filter (`v > 10 and v > 30`)
261
+ * therefore hands the planner a predicate that is seeked nowhere and — because
262
+ * `rule-grow-retrieve` residualizes only *unhandled* constraints — filtered nowhere.
263
+ *
264
+ * Reattach those as a residual `Filter` so an over-claiming module costs a redundant
265
+ * predicate evaluation, never a wrong answer. Skipped for an `EmptyResultNode` leaf
266
+ * (filtering an empty relation is dead weight) and restricted to {@link RECLAIMABLE_OPS}.
267
+ */
268
+ function reattachUnconsumedConstraints(tableRef, accessPlan, constraints, consumed, leaf) {
269
+ if (leaf instanceof EmptyResultNode)
270
+ return leaf;
271
+ const lost = constraints.filter((c, i) => accessPlan.handledFilters[i] === true
272
+ && !consumed.has(c)
273
+ && RECLAIMABLE_OPS.has(c.op));
274
+ if (lost.length === 0)
275
+ return leaf;
276
+ const predicate = combineResidualExpressions(lost.map(c => c.sourceExpression));
277
+ if (!predicate)
278
+ return leaf;
279
+ log('Reattaching %d handled-but-unconsumed constraint(s) as a residual filter', lost.length);
280
+ return new FilterNode(tableRef.scope, leaf, predicate);
281
+ }
176
282
  /**
177
283
  * Select the appropriate physical node based on access plan
178
284
  */
@@ -182,51 +288,34 @@ function selectPhysicalNode(tableRef, accessPlan, constraints) {
182
288
  log('Using empty result (impossible predicate detected)');
183
289
  return createEmptyResultNode(tableRef);
184
290
  }
185
- // Create a default FilterInfo for the physical nodes
186
- const filterInfo = {
187
- idxNum: 0,
188
- idxStr: 'fullscan',
189
- constraints: [],
190
- args: [],
191
- indexInfoOutput: {
192
- nConstraint: 0,
193
- aConstraint: [],
194
- nOrderBy: 0,
195
- aOrderBy: [],
196
- aConstraintUsage: [],
197
- idxNum: 0,
198
- idxStr: 'fullscan',
199
- orderByConsumed: false,
200
- estimatedCost: accessPlan.cost,
201
- estimatedRows: BigInt(accessPlan.rows || 1000),
202
- idxFlags: 0,
203
- colUsed: 0n,
204
- }
205
- };
291
+ // Default FilterInfo for the physical nodes. Each index arm below spreads this and
292
+ // overrides `idxStr` / `accessPath` for the index it chose.
293
+ const filterInfo = makeFullScanFilterInfo(accessPlan.cost, accessPlan.rows || 1000);
206
294
  // Convert OrderingSpec[] to the format expected by physical nodes
207
295
  const providesOrdering = accessPlan.providesOrdering?.map(spec => ({
208
296
  column: spec.columnIndex,
209
297
  desc: spec.desc
210
298
  }));
299
+ const consumed = new Set();
211
300
  // --- Index-aware path: use module-provided index identity ---
212
- if (accessPlan.indexName && accessPlan.seekColumnIndexes && accessPlan.seekColumnIndexes.length > 0) {
213
- return selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInfo, providesOrdering);
214
- }
215
301
  // --- Legacy fallback: infer access method from constraints and PK definition ---
216
- return selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo, providesOrdering);
302
+ const leaf = (accessPlan.indexName && accessPlan.seekColumnIndexes && accessPlan.seekColumnIndexes.length > 0)
303
+ ? selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInfo, providesOrdering, consumed)
304
+ : selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo, providesOrdering, consumed);
305
+ return reattachUnconsumedConstraints(tableRef, accessPlan, constraints, consumed, leaf);
217
306
  }
218
307
  /**
219
308
  * Index-aware physical node selection using module-provided indexName and seekColumnIndexes.
220
309
  * Works for both primary key and secondary indexes.
221
310
  */
222
- function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInfo, providesOrdering) {
311
+ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInfo, providesOrdering, consumed) {
223
312
  const advertisement = extractAdvertisement(accessPlan);
224
313
  // Whether this module's runtime honours the index collation for range bounds —
225
314
  // gates the collation-matched non-BINARY range/prefix seek (see classifyConstraintCover).
226
315
  const honorsCollatedRangeBounds = accessPlan.honorsCollatedRangeBounds === true;
227
316
  const seekCols = accessPlan.seekColumnIndexes;
228
317
  // Map accessPlan.indexName to physical node indexName ('_primary_' → 'primary')
229
- const physicalIndexName = accessPlan.indexName === '_primary_' ? 'primary' : accessPlan.indexName;
318
+ const physicalIndexName = accessPlan.indexName === PRIMARY_INDEX_NAME ? PRIMARY_PHYSICAL_INDEX_NAME : accessPlan.indexName;
230
319
  // idxStr uses the raw name (scan-plan builder maps '_primary_' → 'primary')
231
320
  const idxStrName = accessPlan.indexName;
232
321
  // Build a map of constraints by column index for quick lookup
@@ -242,6 +331,14 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
242
331
  if (accessPlan.handledFilters[i] === true)
243
332
  handledByCol.add(c.columnIndex);
244
333
  });
334
+ // Per-column, per-role pickers. Each returns the FIRST constraint in `constraints`
335
+ // order filling that role — the positional contract module authors must claim
336
+ // against (see docs/module-authoring.md). Redundant same-role duplicates are never
337
+ // picked and are recovered by `reattachUnconsumedConstraints`.
338
+ const isHandled = (c) => handledByCol.has(c.columnIndex);
339
+ const findPrefixEq = (colIdx) => (constraintsByCol.get(colIdx) ?? []).find(c => (c.op === '=' || (c.op === 'IN' && Array.isArray(c.value) && c.value.length === 1)) && isHandled(c));
340
+ const findLower = (colIdx) => (constraintsByCol.get(colIdx) ?? []).find(c => (c.op === '>' || c.op === '>=') && isHandled(c));
341
+ const findUpper = (colIdx) => (constraintsByCol.get(colIdx) ?? []).find(c => (c.op === '<' || c.op === '<=') && isHandled(c));
245
342
  // Check if all seek columns have equality constraints (=, single-value IN, or multi-value IN)
246
343
  const eqBySeekCol = new Map();
247
344
  let allEquality = true;
@@ -258,6 +355,11 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
258
355
  }
259
356
  }
260
357
  if (allEquality && eqBySeekCol.size === seekCols.length) {
358
+ // Every arm below returns, and each consumes exactly the per-seek-column
359
+ // equality constraints — as seek keys, or (on a collation decline) as the
360
+ // residual re-applied above the scan.
361
+ for (const c of eqBySeekCol.values())
362
+ consumed.add(c);
261
363
  // Collation-cover analysis: a seek over an index whose per-column collation
262
364
  // differs from the predicate's effective comparison collation is NOT a
263
365
  // complete substitute for the predicate. Decline (scan + residual) on an
@@ -302,11 +404,7 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
302
404
  constraint: { iColumn: colIdx, op: IndexConstraintOp.EQ, usable: true },
303
405
  argvIndex: i + 1,
304
406
  }));
305
- const fi = {
306
- ...filterInfo,
307
- constraints: inConstraints,
308
- idxStr: `idx=${idxStrName}(0);plan=5;inCount=${seekKeys.length}`,
309
- };
407
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'multiSeek', inConstraints, new Map([['inCount', String(seekKeys.length)]]));
310
408
  log('Using index multi-seek on %s (IN with %d values)', physicalIndexName, seekKeys.length);
311
409
  return finishSeek(new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, false, providesOrdering, accessPlan.cost, advertisement));
312
410
  }
@@ -357,11 +455,7 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
357
455
  constraint: { iColumn: seekCols[i % seekWidth], op: IndexConstraintOp.EQ, usable: true },
358
456
  argvIndex: i + 1,
359
457
  }));
360
- const fi = {
361
- ...filterInfo,
362
- constraints: seekConstraints,
363
- idxStr: `idx=${idxStrName}(0);plan=5;inCount=${effectiveTuples.length};seekWidth=${seekWidth}`,
364
- };
458
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'multiSeek', seekConstraints, new Map([['inCount', String(effectiveTuples.length)], ['seekWidth', String(seekWidth)]]));
365
459
  log('Using composite index multi-seek on %s (cross-product of %d distinct non-null seeks, width %d)', physicalIndexName, effectiveTuples.length, seekWidth);
366
460
  return finishSeek(new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, false, providesOrdering, accessPlan.cost, advertisement));
367
461
  }
@@ -381,11 +475,7 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
381
475
  constraint: { iColumn: seekCols[i % seekWidth], op: IndexConstraintOp.EQ, usable: true },
382
476
  argvIndex: i + 1,
383
477
  }));
384
- const fi = {
385
- ...filterInfo,
386
- constraints: seekConstraints,
387
- idxStr: `idx=${idxStrName}(0);plan=5;inCount=${crossProduct.length};seekWidth=${seekWidth}`,
388
- };
478
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'multiSeek', seekConstraints, new Map([['inCount', String(crossProduct.length)], ['seekWidth', String(seekWidth)]]));
389
479
  log('Using composite index multi-seek on %s (cross-product of %d seeks, width %d)', physicalIndexName, crossProduct.length, seekWidth);
390
480
  return finishSeek(new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, false, providesOrdering, accessPlan.cost, advertisement));
391
481
  }
@@ -403,11 +493,7 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
403
493
  constraint: { iColumn: colIdx, op: IndexConstraintOp.EQ, usable: true },
404
494
  argvIndex: i + 1,
405
495
  }));
406
- const fi = {
407
- ...filterInfo,
408
- constraints: eqConstraints,
409
- idxStr: `idx=${idxStrName}(0);plan=2`,
410
- };
496
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'eqSeek', eqConstraints);
411
497
  log('Using index seek on %s (equality)', physicalIndexName);
412
498
  return finishSeek(new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, false, providesOrdering, accessPlan.cost, advertisement));
413
499
  }
@@ -416,31 +502,34 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
416
502
  const prefixEqCols = [];
417
503
  let trailingRangeCol;
418
504
  for (const colIdx of seekCols) {
419
- const colConstraints = constraintsByCol.get(colIdx) ?? [];
420
- const eqConstraint = colConstraints.find(c => (c.op === '=' || (c.op === 'IN' && Array.isArray(c.value) && c.value.length === 1)) &&
421
- handledByCol.has(c.columnIndex));
422
- if (eqConstraint) {
505
+ if (findPrefixEq(colIdx)) {
423
506
  prefixEqCols.push(colIdx);
424
507
  }
425
508
  else {
426
- const hasRange = colConstraints.some(c => ['>', '>=', '<', '<='].includes(c.op) && handledByCol.has(c.columnIndex));
427
- if (hasRange)
509
+ if (findLower(colIdx) || findUpper(colIdx))
428
510
  trailingRangeCol = colIdx;
429
511
  break;
430
512
  }
431
513
  }
432
514
  if (prefixEqCols.length > 0 && trailingRangeCol !== undefined) {
515
+ const prefixConstraints = prefixEqCols.map(colIdx => ({ colIdx, constraint: findPrefixEq(colIdx) }));
516
+ const lower = findLower(trailingRangeCol);
517
+ const upper = findUpper(trailingRangeCol);
518
+ // Every arm below returns, consuming the prefix equalities plus the first
519
+ // lower/upper trailing bound — as seek keys, or (on a collation decline) as
520
+ // the residual re-applied above the scan.
521
+ for (const { constraint } of prefixConstraints)
522
+ consumed.add(constraint);
523
+ if (lower)
524
+ consumed.add(lower);
525
+ if (upper)
526
+ consumed.add(upper);
433
527
  // A literal NULL in any prefix-equality column makes every row-value
434
528
  // comparison UNKNOWN ⇒ no match. Emit an empty result rather than relying
435
529
  // on the runtime prefix walk breaking on the first row. Part A does not
436
530
  // cover this path (it walks via `equalityPrefix`, not `equalityKey`), so
437
531
  // the plan-time check is the robustness guarantee here.
438
- const prefixHasLiteralNull = prefixEqCols.some(colIdx => {
439
- const c = (constraintsByCol.get(colIdx) ?? []).find(c => (c.op === '=' || (c.op === 'IN' && Array.isArray(c.value) && c.value.length === 1)) &&
440
- handledByCol.has(c.columnIndex));
441
- return c !== undefined && isLiteralNullEquality(c);
442
- });
443
- if (prefixHasLiteralNull) {
532
+ if (prefixConstraints.some(({ constraint }) => isLiteralNullEquality(constraint))) {
444
533
  log('Prefix-range seek on %s has a literal NULL prefix key — using empty result', physicalIndexName);
445
534
  return createEmptyResultNode(tableRef);
446
535
  }
@@ -448,20 +537,12 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
448
537
  // the walked index window (it is no longer a contiguous superset), so it
449
538
  // cannot be salvaged with a residual — decline to a scan + residual.
450
539
  {
451
- const consumed = [];
452
- for (const colIdx of prefixEqCols) {
453
- const c = (constraintsByCol.get(colIdx) ?? []).find(c => (c.op === '=' || (c.op === 'IN' && Array.isArray(c.value) && c.value.length === 1)) &&
454
- handledByCol.has(c.columnIndex));
455
- consumed.push({ colIdx, constraint: c });
456
- }
457
- const trailing = constraintsByCol.get(trailingRangeCol) ?? [];
458
- const lo = trailing.find(c => (c.op === '>' || c.op === '>=') && handledByCol.has(c.columnIndex));
459
- const hi = trailing.find(c => (c.op === '<' || c.op === '<=') && handledByCol.has(c.columnIndex));
460
- if (lo)
461
- consumed.push({ colIdx: trailingRangeCol, constraint: lo });
462
- if (hi)
463
- consumed.push({ colIdx: trailingRangeCol, constraint: hi });
464
- const cover = classifyCollationCover(consumed, false, indexColumnCollationLookup(tableRef.tableSchema, accessPlan), honorsCollatedRangeBounds);
540
+ const coverConstraints = [...prefixConstraints];
541
+ if (lower)
542
+ coverConstraints.push({ colIdx: trailingRangeCol, constraint: lower });
543
+ if (upper)
544
+ coverConstraints.push({ colIdx: trailingRangeCol, constraint: upper });
545
+ const cover = classifyCollationCover(coverConstraints, false, indexColumnCollationLookup(tableRef.tableSchema, accessPlan), honorsCollatedRangeBounds);
465
546
  if (!cover.useIndex) {
466
547
  log('Declining prefix-range seek on %s (collation mismatch) — sequential scan + residual', physicalIndexName);
467
548
  const scan = createSeqScan(tableRef);
@@ -472,17 +553,12 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
472
553
  const allConstraints = [];
473
554
  let argv = 1;
474
555
  // Add prefix equality values
475
- for (const colIdx of prefixEqCols) {
476
- const c = (constraintsByCol.get(colIdx) ?? []).find(c => (c.op === '=' || (c.op === 'IN' && Array.isArray(c.value) && c.value.length === 1)) &&
477
- handledByCol.has(c.columnIndex));
478
- seekKeys.push(equalitySeekKey(tableRef.scope, c));
556
+ for (const { colIdx, constraint } of prefixConstraints) {
557
+ seekKeys.push(equalitySeekKey(tableRef.scope, constraint));
479
558
  allConstraints.push({ constraint: { iColumn: colIdx, op: IndexConstraintOp.EQ, usable: true }, argvIndex: argv });
480
559
  argv++;
481
560
  }
482
561
  // Add trailing range values
483
- const trailingConstraints = constraintsByCol.get(trailingRangeCol) ?? [];
484
- const lower = trailingConstraints.find(c => (c.op === '>' || c.op === '>=') && handledByCol.has(c.columnIndex));
485
- const upper = trailingConstraints.find(c => (c.op === '<' || c.op === '<=') && handledByCol.has(c.columnIndex));
486
562
  if (lower) {
487
563
  allConstraints.push({ constraint: { iColumn: trailingRangeCol, op: opToIndexOp(lower.op), usable: true }, argvIndex: argv });
488
564
  seekKeys.push(lower.valueExpr && !Array.isArray(lower.valueExpr) ? lower.valueExpr : literalFromValue(tableRef.scope, lower.value));
@@ -493,35 +569,43 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
493
569
  seekKeys.push(upper.valueExpr && !Array.isArray(upper.valueExpr) ? upper.valueExpr : literalFromValue(tableRef.scope, upper.value));
494
570
  argv++;
495
571
  }
496
- const fi = {
497
- ...filterInfo,
498
- constraints: allConstraints,
499
- idxStr: `idx=${idxStrName}(0);plan=7;prefixLen=${prefixEqCols.length}`,
500
- };
572
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'prefixRangeSeek', allConstraints, new Map([['prefixLen', String(prefixEqCols.length)]]));
501
573
  log('Using index prefix-range seek on %s (prefix=%d cols)', physicalIndexName, prefixEqCols.length);
502
574
  return new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, true, providesOrdering, accessPlan.cost, advertisement);
503
575
  }
504
576
  }
505
- // Check for range constraints on the seek columns
506
- // Use the first (or only) seek column that has range constraints
507
- const rangeCol = seekCols.find(colIdx => {
508
- const colConstraints = constraintsByCol.get(colIdx) ?? [];
509
- return colConstraints.some(c => ['>', '>=', '<', '<='].includes(c.op) && handledByCol.has(c.columnIndex));
510
- });
577
+ // Check for range constraints on the LEADING seek column only. A standalone range
578
+ // seek emits its bounds positionally into `seekKeys` and the runtime applies them to
579
+ // the index's leading column, so a range on a *later* seek column is usable only via
580
+ // the prefix-range path above — which requires every preceding seek column to be
581
+ // pinned by a single-valued equality. Picking a later column here would bound the
582
+ // leading column with the wrong value and silently drop rows (`a in (1,2) and b > 15`
583
+ // over an index on `(a, b)`: the multi-value IN is not a prefix key, so `b`'s bound
584
+ // would be seeked against `a`). When the leading column carries no bound we decline;
585
+ // `reattachUnconsumedConstraints` re-applies the claimed range as a residual.
586
+ const leadingSeekCol = seekCols[0];
587
+ const rangeCol = (leadingSeekCol !== undefined && (findLower(leadingSeekCol) || findUpper(leadingSeekCol)))
588
+ ? leadingSeekCol
589
+ : undefined;
511
590
  if (rangeCol !== undefined) {
512
- const colConstraints = constraintsByCol.get(rangeCol) ?? [];
513
- const lower = colConstraints.find(c => (c.op === '>' || c.op === '>=') && handledByCol.has(c.columnIndex));
514
- const upper = colConstraints.find(c => (c.op === '<' || c.op === '<=') && handledByCol.has(c.columnIndex));
591
+ const lower = findLower(rangeCol);
592
+ const upper = findUpper(rangeCol);
593
+ // Both arms below return, consuming the first lower/upper bound as seek
594
+ // bounds, or (on a collation decline) as the residual above the scan.
595
+ if (lower)
596
+ consumed.add(lower);
597
+ if (upper)
598
+ consumed.add(upper);
515
599
  // Collation-cover: a range seek under a collation that differs from the
516
600
  // predicate's reorders the index window, so it is never a superset — decline
517
601
  // to a scan + residual on any mismatch.
518
602
  {
519
- const consumed = [];
603
+ const coverConstraints = [];
520
604
  if (lower)
521
- consumed.push({ colIdx: rangeCol, constraint: lower });
605
+ coverConstraints.push({ colIdx: rangeCol, constraint: lower });
522
606
  if (upper)
523
- consumed.push({ colIdx: rangeCol, constraint: upper });
524
- const cover = classifyCollationCover(consumed, false, indexColumnCollationLookup(tableRef.tableSchema, accessPlan), honorsCollatedRangeBounds);
607
+ coverConstraints.push({ colIdx: rangeCol, constraint: upper });
608
+ const cover = classifyCollationCover(coverConstraints, false, indexColumnCollationLookup(tableRef.tableSchema, accessPlan), honorsCollatedRangeBounds);
525
609
  if (!cover.useIndex) {
526
610
  log('Declining range seek on %s (collation mismatch) — sequential scan + residual', physicalIndexName);
527
611
  const scan = createSeqScan(tableRef);
@@ -541,11 +625,7 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
541
625
  seekKeys.push(upper.valueExpr && !Array.isArray(upper.valueExpr) ? upper.valueExpr : literalFromValue(tableRef.scope, upper.value));
542
626
  argv++;
543
627
  }
544
- const fi = {
545
- ...filterInfo,
546
- constraints: rangeConstraints,
547
- idxStr: `idx=${idxStrName}(0);plan=3`,
548
- };
628
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'rangeSeek', rangeConstraints);
549
629
  log('Using index seek (range) on %s', physicalIndexName);
550
630
  return new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, true, providesOrdering, accessPlan.cost, advertisement);
551
631
  }
@@ -554,6 +634,9 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
554
634
  seekCols.includes(c.columnIndex) && handledByCol.has(c.columnIndex));
555
635
  if (orRangeConstraint && orRangeConstraint.ranges) {
556
636
  const ranges = orRangeConstraint.ranges;
637
+ // Both arms below return, consuming this OR_RANGE — as the multi-range seek's
638
+ // bounds, or (on a collation decline) as the residual above the scan.
639
+ consumed.add(orRangeConstraint);
557
640
  // Collation-cover: an OR_RANGE seek walks multiple index windows whose order
558
641
  // follows the index collation; any mismatch makes them non-supersets, so
559
642
  // decline to a scan + residual.
@@ -589,28 +672,16 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
589
672
  constraint: { iColumn: orRangeConstraint.columnIndex, op: IndexConstraintOp.GE, usable: true },
590
673
  argvIndex: i + 1,
591
674
  }));
592
- const fi = {
593
- ...filterInfo,
594
- constraints: orRangeConstraints,
595
- idxStr: `idx=${idxStrName}(0);plan=6;rangeCount=${ranges.length};rangeOps=${rangeOps.join(',')}`,
596
- };
675
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, idxStrName, 'multiRangeSeek', orRangeConstraints, new Map([['rangeCount', String(ranges.length)], ['rangeOps', rangeOps.join(',')]]));
597
676
  log('Using index multi-range seek on %s (%d ranges)', physicalIndexName, ranges.length);
598
677
  return new IndexSeekNode(tableRef.scope, tableRef, fi, physicalIndexName, seekKeys, true, providesOrdering, accessPlan.cost, advertisement);
599
678
  }
600
679
  // Ordering-only index scan
601
680
  if (providesOrdering) {
602
681
  const orderingIndexName = accessPlan.orderingIndexName ?? physicalIndexName;
603
- const orderingIdxStr = orderingIndexName === 'primary' ? '_primary_' : orderingIndexName;
682
+ const orderingIdxStr = orderingIndexName === PRIMARY_PHYSICAL_INDEX_NAME ? PRIMARY_INDEX_NAME : orderingIndexName;
604
683
  log('Using index scan (ordering provided by %s)', orderingIndexName);
605
- const orderingFilterInfo = {
606
- ...filterInfo,
607
- idxStr: `idx=${orderingIdxStr}(0);plan=0`,
608
- indexInfoOutput: {
609
- ...filterInfo.indexInfoOutput,
610
- idxStr: `idx=${orderingIdxStr}(0);plan=0`,
611
- orderByConsumed: true,
612
- }
613
- };
684
+ const orderingFilterInfo = makeOrderedScanFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, orderingIdxStr);
614
685
  return new IndexScanNode(tableRef.scope, tableRef, orderingFilterInfo, orderingIndexName, providesOrdering, accessPlan.cost, advertisement);
615
686
  }
616
687
  // Fall back to sequential scan
@@ -621,7 +692,7 @@ function selectPhysicalNodeFromPlan(tableRef, accessPlan, constraints, filterInf
621
692
  * Legacy physical node selection for backward compatibility when module
622
693
  * doesn't provide indexName/seekColumnIndexes (PK-based heuristics).
623
694
  */
624
- function selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo, providesOrdering) {
695
+ function selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo, providesOrdering, consumed) {
625
696
  const advertisement = extractAdvertisement(accessPlan);
626
697
  const honorsCollatedRangeBounds = accessPlan.honorsCollatedRangeBounds === true;
627
698
  // Analyze the access plan to determine node type
@@ -630,17 +701,27 @@ function selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo,
630
701
  if (accessPlan.handledFilters[i] === true)
631
702
  handledByCol.add(c.columnIndex);
632
703
  });
633
- const eqHandled = constraints.filter(c => c.op === '=');
634
- const hasEqualityConstraints = eqHandled.length > 0;
704
+ // Every '=' constraint, handled or not: an unhandled one still makes a sound seek key
705
+ // (grow-retrieve keeps it in the residual), so it may complete a PK cover.
706
+ const eqConstraints = constraints.filter(c => c.op === '=');
707
+ const hasEqualityConstraints = eqConstraints.length > 0;
635
708
  const hasRangeConstraints = constraints.some(c => ['>', '>=', '<', '<='].includes(c.op) && handledByCol.has(c.columnIndex));
636
709
  const maybeRows = accessPlan.rows || 0;
637
710
  const pkCols = tableRef.tableSchema.primaryKeyDefinition ?? [];
711
+ // FIRST '=' per column, matching the positional contract the index-aware path and
712
+ // `docs/module-authoring.md` state. Keeping the last would seek on a constraint a
713
+ // module claiming positionally never expected to be consumed.
638
714
  const eqByCol = new Map();
639
- for (const c of eqHandled)
640
- eqByCol.set(c.columnIndex, c);
715
+ for (const c of eqConstraints)
716
+ if (!eqByCol.has(c.columnIndex))
717
+ eqByCol.set(c.columnIndex, c);
641
718
  const coversPk = pkCols.length > 0 && pkCols.every(pk => eqByCol.has(pk.index));
642
719
  const treatAsHandledPk = coversPk && pkCols.every(pk => handledByCol.has(pk.index) || eqByCol.has(pk.index));
643
720
  if ((hasEqualityConstraints && coversPk || treatAsHandledPk) && maybeRows <= 10) {
721
+ // Every arm below returns, consuming the per-PK-column equality — as a seek
722
+ // key, or (on a collation decline) as the residual re-applied above the scan.
723
+ for (const pk of pkCols)
724
+ consumed.add(eqByCol.get(pk.index));
644
725
  // A literal NULL in any PK column makes the point-seek UNKNOWN ⇒ no row can
645
726
  // match. Emit an empty result instead of a doomed seek (mirrors the
646
727
  // index-aware path; the scan-layer runtime guard covers the dynamic case).
@@ -665,31 +746,38 @@ function selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo,
665
746
  constraint: { iColumn: pk.index, op: IndexConstraintOp.EQ, usable: true },
666
747
  argvIndex: i + 1,
667
748
  }));
668
- const fi = {
669
- ...filterInfo,
670
- constraints: eqConstraints,
671
- idxStr: 'idx=_primary_(0);plan=2',
672
- };
749
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, PRIMARY_INDEX_NAME, 'eqSeek', eqConstraints);
673
750
  log('Using index seek on primary key (legacy)');
674
751
  const pkSeek = new IndexSeekNode(tableRef.scope, tableRef, fi, 'primary', seekKeys, false, providesOrdering, accessPlan.cost, advertisement);
675
752
  return cover.residual ? new FilterNode(tableRef.scope, pkSeek, cover.residual) : pkSeek;
676
753
  }
677
- if (hasRangeConstraints) {
678
- const rangeCols = constraints
679
- .filter(c => ['>', '>=', '<', '<='].includes(c.op) && handledByCol.has(c.columnIndex))
680
- .sort((a, b) => a.columnIndex - b.columnIndex);
681
- const primaryFirstCol = (tableRef.tableSchema.primaryKeyDefinition?.[0]?.index) ?? (rangeCols[0]?.columnIndex ?? 0);
682
- const lower = rangeCols.find(c => c.columnIndex === primaryFirstCol && (c.op === '>' || c.op === '>='));
683
- const upper = rangeCols.find(c => c.columnIndex === primaryFirstCol && (c.op === '<' || c.op === '<='));
754
+ const rangeCols = constraints
755
+ .filter(c => ['>', '>=', '<', '<='].includes(c.op) && handledByCol.has(c.columnIndex))
756
+ .sort((a, b) => a.columnIndex - b.columnIndex);
757
+ const primaryFirstCol = (tableRef.tableSchema.primaryKeyDefinition?.[0]?.index) ?? (rangeCols[0]?.columnIndex ?? 0);
758
+ const lower = rangeCols.find(c => c.columnIndex === primaryFirstCol && (c.op === '>' || c.op === '>='));
759
+ const upper = rangeCols.find(c => c.columnIndex === primaryFirstCol && (c.op === '<' || c.op === '<='));
760
+ // A PK range seek needs at least one bound on the LEADING PK column: seek keys are
761
+ // positional and the runtime walks the primary key. When every handled range sits on
762
+ // a later PK column there is nothing to seek with, and a zero-key `IndexSeekNode`
763
+ // would be a full index walk dressed up as a seek. Decline instead — the claimed
764
+ // range comes back as a residual via `reattachUnconsumedConstraints`.
765
+ if (hasRangeConstraints && (lower || upper)) {
766
+ // Both arms below return, consuming the first lower/upper bound on the leading
767
+ // PK column — as seek bounds, or (on a collation decline) as the scan residual.
768
+ if (lower)
769
+ consumed.add(lower);
770
+ if (upper)
771
+ consumed.add(upper);
684
772
  // Collation-cover: a PK range seek under a mismatched collation reorders the
685
773
  // walked window, so decline to a scan + residual on any mismatch.
686
774
  {
687
- const consumed = [];
775
+ const coverConstraints = [];
688
776
  if (lower)
689
- consumed.push({ colIdx: primaryFirstCol, constraint: lower });
777
+ coverConstraints.push({ colIdx: primaryFirstCol, constraint: lower });
690
778
  if (upper)
691
- consumed.push({ colIdx: primaryFirstCol, constraint: upper });
692
- const cover = classifyCollationCover(consumed, false, primaryKeyCollationLookup(tableRef.tableSchema), honorsCollatedRangeBounds);
779
+ coverConstraints.push({ colIdx: primaryFirstCol, constraint: upper });
780
+ const cover = classifyCollationCover(coverConstraints, false, primaryKeyCollationLookup(tableRef.tableSchema), honorsCollatedRangeBounds);
693
781
  if (!cover.useIndex) {
694
782
  log('Declining PK range seek (collation mismatch) — sequential scan + residual (legacy)');
695
783
  const scan = createSeqScan(tableRef);
@@ -709,36 +797,20 @@ function selectPhysicalNodeLegacy(tableRef, accessPlan, constraints, filterInfo,
709
797
  seekKeys.push(upper.valueExpr && !Array.isArray(upper.valueExpr) ? upper.valueExpr : literalFromValue(tableRef.scope, upper.value));
710
798
  argv++;
711
799
  }
712
- const fi = {
713
- ...filterInfo,
714
- constraints: rangeConstraints,
715
- idxStr: 'idx=_primary_(0);plan=3',
716
- };
800
+ const fi = makeIndexFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, PRIMARY_INDEX_NAME, 'rangeSeek', rangeConstraints);
717
801
  log('Using index seek (range) on primary key (legacy)');
718
802
  return new IndexSeekNode(tableRef.scope, tableRef, fi, 'primary', seekKeys, true, providesOrdering, accessPlan.cost, advertisement);
719
803
  }
720
804
  if (providesOrdering) {
721
- const indexName = accessPlan.orderingIndexName ?? 'primary';
805
+ const indexName = accessPlan.orderingIndexName ?? PRIMARY_PHYSICAL_INDEX_NAME;
722
806
  log('Using index scan (ordering provided by %s)', indexName);
723
- const indexIdxStr = indexName === 'primary' ? '_primary_' : indexName;
724
- const orderingFilterInfo = {
725
- ...filterInfo,
726
- idxStr: `idx=${indexIdxStr}(0);plan=0`,
727
- indexInfoOutput: {
728
- ...filterInfo.indexInfoOutput,
729
- idxStr: `idx=${indexIdxStr}(0);plan=0`,
730
- orderByConsumed: true,
731
- }
732
- };
807
+ const indexIdxStr = indexName === PRIMARY_PHYSICAL_INDEX_NAME ? PRIMARY_INDEX_NAME : indexName;
808
+ const orderingFilterInfo = makeOrderedScanFilterInfo(filterInfo, tableRef.tableSchema, accessPlan, indexIdxStr);
733
809
  return new IndexScanNode(tableRef.scope, tableRef, orderingFilterInfo, indexName, providesOrdering, accessPlan.cost, advertisement);
734
810
  }
735
811
  log('Using sequential scan (no beneficial index access)');
736
812
  return createSeqScan(tableRef, filterInfo, accessPlan.cost);
737
813
  }
738
- // Narrow module context originating from grow-retrieve index-style fallback
739
- function isIndexStyleContext(ctx) {
740
- return !!ctx && typeof ctx === 'object' && ctx.kind === 'index-style';
741
- }
742
814
  /**
743
815
  * Create a sequential scan node
744
816
  */
@@ -746,26 +818,7 @@ function createSeqScan(tableRef, filterInfo, cost) {
746
818
  const tableRows = tableRef.estimatedRows || 1000;
747
819
  const scanCost = cost ?? seqScanCost(tableRows);
748
820
  // Create default FilterInfo if not provided
749
- const effectiveFilterInfo = filterInfo || {
750
- idxNum: 0,
751
- idxStr: 'fullscan',
752
- constraints: [],
753
- args: [],
754
- indexInfoOutput: {
755
- nConstraint: 0,
756
- aConstraint: [],
757
- nOrderBy: 0,
758
- aOrderBy: [],
759
- aConstraintUsage: [],
760
- idxNum: 0,
761
- idxStr: 'fullscan',
762
- orderByConsumed: false,
763
- estimatedCost: scanCost,
764
- estimatedRows: BigInt(tableRows),
765
- idxFlags: 0,
766
- colUsed: 0n,
767
- }
768
- };
821
+ const effectiveFilterInfo = filterInfo ?? makeFullScanFilterInfo(scanCost, tableRows);
769
822
  const seqScan = new SeqScanNode(tableRef.scope, tableRef, effectiveFilterInfo, scanCost);
770
823
  return seqScan;
771
824
  }
@@ -824,27 +877,7 @@ function equalitySeekKey(scope, c) {
824
877
  * the literal-IN reduction below.
825
878
  */
826
879
  function createEmptyResultNode(tableRef) {
827
- const emptyFilterInfo = {
828
- idxNum: 0,
829
- idxStr: 'empty',
830
- constraints: [],
831
- args: [],
832
- indexInfoOutput: {
833
- nConstraint: 0,
834
- aConstraint: [],
835
- nOrderBy: 0,
836
- aOrderBy: [],
837
- aConstraintUsage: [],
838
- idxNum: 0,
839
- idxStr: 'empty',
840
- orderByConsumed: false,
841
- estimatedCost: 0,
842
- estimatedRows: 0n,
843
- idxFlags: 0,
844
- colUsed: 0n,
845
- }
846
- };
847
- return new EmptyResultNode(tableRef.scope, tableRef, emptyFilterInfo, 0);
880
+ return new EmptyResultNode(tableRef.scope, tableRef, makeEmptyFilterInfo(), 0);
848
881
  }
849
882
  /**
850
883
  * True when an equality constraint resolves to a *literal* SQL NULL — `col = null`