@quereus/quereus 4.20.1 → 4.20.2

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 (377) hide show
  1. package/README.md +2 -0
  2. package/package.json +7 -4
  3. package/test/README.md +173 -0
  4. package/test/logic/01-basic.sqllogic +39 -0
  5. package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
  6. package/test/logic/01.2-strings.sqllogic +43 -0
  7. package/test/logic/01.5-insert-select.sqllogic +237 -0
  8. package/test/logic/01.6-update-extras.sqllogic +118 -0
  9. package/test/logic/01.7-update-from.sqllogic +67 -0
  10. package/test/logic/01.8-delete-extras.sqllogic +122 -0
  11. package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
  12. package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
  13. package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
  14. package/test/logic/01.9-query-expr-values.sqllogic +111 -0
  15. package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
  16. package/test/logic/02-filters.sqllogic +54 -0
  17. package/test/logic/02-smoke.sqllogic +62 -0
  18. package/test/logic/02.1-bind-parameters.sqllogic +223 -0
  19. package/test/logic/03-expressions.sqllogic +190 -0
  20. package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
  21. package/test/logic/03.4-defaults.sqllogic +554 -0
  22. package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
  23. package/test/logic/03.5-tvf.sqllogic +61 -0
  24. package/test/logic/03.6-type-system.sqllogic +544 -0
  25. package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
  26. package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
  27. package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
  28. package/test/logic/03.8-not-precedence.sqllogic +255 -0
  29. package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
  30. package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
  31. package/test/logic/04-order-by.sqllogic +38 -0
  32. package/test/logic/04-transactions.sqllogic +239 -0
  33. package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
  34. package/test/logic/05-vtab_memory.sqllogic +50 -0
  35. package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
  36. package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
  37. package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
  38. package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
  39. package/test/logic/06-builtin_functions.sqllogic +149 -0
  40. package/test/logic/06.1-string-functions.sqllogic +92 -0
  41. package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
  42. package/test/logic/06.2-math-functions.sqllogic +82 -0
  43. package/test/logic/06.3-schema.sqllogic +48 -0
  44. package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
  45. package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
  46. package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
  47. package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
  48. package/test/logic/06.3.4-view-info.sqllogic +378 -0
  49. package/test/logic/06.3.5-column-info.sqllogic +347 -0
  50. package/test/logic/06.3.6-schema-views.sqllogic +29 -0
  51. package/test/logic/06.4-schema-search-path.sqllogic +354 -0
  52. package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
  53. package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
  54. package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
  55. package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
  56. package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
  57. package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
  58. package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
  59. package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
  60. package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
  61. package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
  62. package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
  63. package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
  64. package/test/logic/06.7-json-extended.sqllogic +53 -0
  65. package/test/logic/06.8-json-path-operators.sqllogic +99 -0
  66. package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
  67. package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
  68. package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
  69. package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
  70. package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
  71. package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
  72. package/test/logic/07-aggregates.sqllogic +193 -0
  73. package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
  74. package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
  75. package/test/logic/07.3-group-by-extras.sqllogic +602 -0
  76. package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
  77. package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
  78. package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
  79. package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
  80. package/test/logic/07.5-window.sqllogic +1941 -0
  81. package/test/logic/07.5.1-window-named.sqllogic +13 -0
  82. package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
  83. package/test/logic/07.6-subqueries.sqllogic +78 -0
  84. package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
  85. package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
  86. package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
  87. package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
  88. package/test/logic/07.7.1-in-extras.sqllogic +158 -0
  89. package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
  90. package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
  91. package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
  92. package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
  93. package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
  94. package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
  95. package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
  96. package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
  97. package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
  98. package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
  99. package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
  100. package/test/logic/07.9-in-value-list.sqllogic +154 -0
  101. package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
  102. package/test/logic/08-views.sqllogic +64 -0
  103. package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
  104. package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
  105. package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
  106. package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
  107. package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
  108. package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
  109. package/test/logic/09-set_operations.sqllogic +244 -0
  110. package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
  111. package/test/logic/10-distinct_datatypes.sqllogic +127 -0
  112. package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
  113. package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
  114. package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
  115. package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
  116. package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
  117. package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
  118. package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
  119. package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
  120. package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
  121. package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
  122. package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
  123. package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
  124. package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
  125. package/test/logic/10.2-column-features.sqllogic +365 -0
  126. package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
  127. package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
  128. package/test/logic/10.3-function-features.sqllogic +247 -0
  129. package/test/logic/10.4-schema-scale.sqllogic +168 -0
  130. package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
  131. package/test/logic/10.5-indexes.sqllogic +164 -0
  132. package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
  133. package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
  134. package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
  135. package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
  136. package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
  137. package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
  138. package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
  139. package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
  140. package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
  141. package/test/logic/100.1-where-extras.sqllogic +163 -0
  142. package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
  143. package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
  144. package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
  145. package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
  146. package/test/logic/102-unique-constraints.sqllogic +145 -0
  147. package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
  148. package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
  149. package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
  150. package/test/logic/102.2-unique-collation.sqllogic +181 -0
  151. package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
  152. package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
  153. package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
  154. package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
  155. package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
  156. package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
  157. package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
  158. package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
  159. package/test/logic/108-cardinality-estimation.sqllogic +146 -0
  160. package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
  161. package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
  162. package/test/logic/11-joins.sqllogic +86 -0
  163. package/test/logic/11.1-join-using.sqllogic +267 -0
  164. package/test/logic/11.2-comma-join.sqllogic +35 -0
  165. package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
  166. package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
  167. package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
  168. package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
  169. package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
  170. package/test/logic/12-empty-primary-key.sqllogic +124 -0
  171. package/test/logic/12-join_padding_order.sqllogic +58 -0
  172. package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
  173. package/test/logic/13-cte.sqllogic +137 -0
  174. package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
  175. package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
  176. package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
  177. package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
  178. package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
  179. package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
  180. package/test/logic/13.4-cte-extras.sqllogic +98 -0
  181. package/test/logic/13.5-cte-join-order.sqllogic +166 -0
  182. package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
  183. package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
  184. package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
  185. package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
  186. package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
  187. package/test/logic/14-utilities.sqllogic +168 -0
  188. package/test/logic/15-timespan.sqllogic +279 -0
  189. package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
  190. package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
  191. package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
  192. package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
  193. package/test/logic/16-epoch.sqllogic +187 -0
  194. package/test/logic/17-weekday-modifier.sqllogic +78 -0
  195. package/test/logic/18-json-string-escapes.sqllogic +86 -0
  196. package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
  197. package/test/logic/20-empty-single-row.sqllogic +261 -0
  198. package/test/logic/21-null-edge-cases.sqllogic +227 -0
  199. package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
  200. package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
  201. package/test/logic/21.2-between-edges.sqllogic +157 -0
  202. package/test/logic/22-boundary-values.sqllogic +175 -0
  203. package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
  204. package/test/logic/24-builtin-branches.sqllogic +611 -0
  205. package/test/logic/24.1-substr-extras.sqllogic +75 -0
  206. package/test/logic/24.2-random-extras.sqllogic +39 -0
  207. package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
  208. package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
  209. package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
  210. package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
  211. package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
  212. package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
  213. package/test/logic/26-join-edge-cases.sqllogic +333 -0
  214. package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
  215. package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
  216. package/test/logic/26.3-join-on-constants.sqllogic +61 -0
  217. package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
  218. package/test/logic/27-window-edge-cases.sqllogic +206 -0
  219. package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
  220. package/test/logic/27.2-window-exclude.sqllogic +13 -0
  221. package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
  222. package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
  223. package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
  224. package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
  225. package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
  226. package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
  227. package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
  228. package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
  229. package/test/logic/40-constraints.sqllogic +418 -0
  230. package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
  231. package/test/logic/40.2-check-extras.sqllogic +683 -0
  232. package/test/logic/41-alter-table.sqllogic +191 -0
  233. package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
  234. package/test/logic/41-fk-cross-schema.sqllogic +155 -0
  235. package/test/logic/41-fk-extended-targets.sqllogic +173 -0
  236. package/test/logic/41-foreign-keys.sqllogic +1001 -0
  237. package/test/logic/41-generated-column-errors.sqllogic +225 -0
  238. package/test/logic/41-generated-column-extras.sqllogic +598 -0
  239. package/test/logic/41-generated-column-scope.sqllogic +329 -0
  240. package/test/logic/41-generated-columns.sqllogic +361 -0
  241. package/test/logic/41.1-alter-pk.sqllogic +230 -0
  242. package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
  243. package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
  244. package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
  245. package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
  246. package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
  247. package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
  248. package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
  249. package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
  250. package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
  251. package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
  252. package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
  253. package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
  254. package/test/logic/41.2-alter-column.sqllogic +382 -0
  255. package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
  256. package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
  257. package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
  258. package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
  259. package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
  260. package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
  261. package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
  262. package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
  263. package/test/logic/41.5-alter-misc.sqllogic +48 -0
  264. package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
  265. package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
  266. package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
  267. package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
  268. package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
  269. package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
  270. package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
  271. package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
  272. package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
  273. package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
  274. package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
  275. package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
  276. package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
  277. package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
  278. package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
  279. package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
  280. package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
  281. package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
  282. package/test/logic/42-committed-snapshot.sqllogic +254 -0
  283. package/test/logic/42-returning.sqllogic +159 -0
  284. package/test/logic/42.1-returning-extras.sqllogic +232 -0
  285. package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
  286. package/test/logic/43-default-nullability.sqllogic +131 -0
  287. package/test/logic/43-transition-constraints.sqllogic +341 -0
  288. package/test/logic/43.1-default-collation.sqllogic +140 -0
  289. package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
  290. package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
  291. package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
  292. package/test/logic/44-determinism-validation.sqllogic +164 -0
  293. package/test/logic/44-orthogonality.sqllogic +146 -0
  294. package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
  295. package/test/logic/45-udf-determinism.sqllogic +39 -0
  296. package/test/logic/46-mutation-context.sqllogic +595 -0
  297. package/test/logic/47-upsert.sqllogic +255 -0
  298. package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
  299. package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
  300. package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
  301. package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
  302. package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
  303. package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
  304. package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
  305. package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
  306. package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
  307. package/test/logic/49-reference-graph.sqllogic +84 -0
  308. package/test/logic/50-declarative-schema.sqllogic +2550 -0
  309. package/test/logic/50-metadata-tags.sqllogic +1033 -0
  310. package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
  311. package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
  312. package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
  313. package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +173 -0
  314. package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
  315. package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
  316. package/test/logic/51-lens-foundation.sqllogic +147 -0
  317. package/test/logic/51-materialized-views.sqllogic +376 -0
  318. package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
  319. package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
  320. package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
  321. package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
  322. package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
  323. package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
  324. package/test/logic/52-lens-overrides.sqllogic +566 -0
  325. package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
  326. package/test/logic/53-reserved-tags.sqllogic +252 -0
  327. package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
  328. package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
  329. package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
  330. package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
  331. package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
  332. package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
  333. package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
  334. package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
  335. package/test/logic/55-lens-prover.sqllogic +202 -0
  336. package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
  337. package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
  338. package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
  339. package/test/logic/81-quickpick.sqllogic +24 -0
  340. package/test/logic/82-bloom-join.sqllogic +185 -0
  341. package/test/logic/83-merge-join.sqllogic +280 -0
  342. package/test/logic/84-asof-scan.sqllogic +238 -0
  343. package/test/logic/84-key-cardinality.sqllogic +50 -0
  344. package/test/logic/85-relational-const-folding.sqllogic +51 -0
  345. package/test/logic/86-scalar-cse.sqllogic +42 -0
  346. package/test/logic/90-error_paths.sqllogic +114 -0
  347. package/test/logic/90.1-parse-errors.sqllogic +77 -0
  348. package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
  349. package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
  350. package/test/logic/90.3-expression-errors.sqllogic +43 -0
  351. package/test/logic/90.4-dml-errors.sqllogic +47 -0
  352. package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
  353. package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
  354. package/test/logic/90.6-select-error-paths.sqllogic +57 -0
  355. package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
  356. package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
  357. package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
  358. package/test/logic/93.1-view-error-paths.sqllogic +74 -0
  359. package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
  360. package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
  361. package/test/logic/93.4-view-mutation.sqllogic +4881 -0
  362. package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
  363. package/test/logic/93.5-authored-inverse.sqllogic +415 -0
  364. package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
  365. package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
  366. package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
  367. package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
  368. package/test/logic/95-assertions.sqllogic +1417 -0
  369. package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
  370. package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
  371. package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
  372. package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
  373. package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
  374. package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
  375. package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
  376. package/test/logic/drop-unique-index.sqllogic +88 -0
  377. package/test/logic/pushdown-test.sqllogic +36 -0
@@ -0,0 +1,64 @@
1
+ -- views.sqllogic - Testing VIEW functionality
2
+
3
+ -- -- Setup base table
4
+ CREATE TABLE base_data (id INTEGER PRIMARY KEY, name TEXT, category TEXT, value INTEGER);
5
+ INSERT INTO base_data VALUES (1, 'Alpha', 'A', 100), (2, 'Beta', 'B', 200), (3, 'Gamma', 'A', 150), (4, 'Delta', 'B', 300);
6
+
7
+ -- Basic view creation
8
+ CREATE VIEW category_a_view AS SELECT id, name, value FROM base_data WHERE category = 'A';
9
+
10
+ -- Query the view
11
+ SELECT * FROM category_a_view ORDER BY id;
12
+ → [{"id":1,"name":"Alpha","value":100},{"id":3,"name":"Gamma","value":150}]
13
+
14
+ -- View with computed columns
15
+ CREATE VIEW summary_view AS SELECT category, count(*) as item_count, sum(value) as total_value FROM base_data GROUP BY category;
16
+
17
+ SELECT * FROM summary_view ORDER BY category;
18
+ → [{"category":"A","item_count":2,"total_value":250},{"category":"B","item_count":2,"total_value":500}]
19
+
20
+ -- View with complex WHERE clause
21
+ CREATE VIEW high_value_view AS SELECT name, value FROM base_data WHERE value > 150;
22
+
23
+ SELECT * FROM high_value_view ORDER BY value;
24
+ → [{"name":"Beta","value":200},{"name":"Delta","value":300}]
25
+
26
+ -- Verify view reflects changes to underlying table
27
+ INSERT INTO base_data VALUES (5, 'Zeta', 'A', 125);
28
+ SELECT * FROM category_a_view ORDER BY id;
29
+ → [{"id":1,"name":"Alpha","value":100},{"id":3,"name":"Gamma","value":150},{"id":5,"name":"Zeta","value":125}]
30
+
31
+ -- Test view with alias and qualified SELECT *
32
+ SELECT v.* FROM category_a_view v ORDER BY id;
33
+ → [{"id":1,"name":"Alpha","value":100},{"id":3,"name":"Gamma","value":150},{"id":5,"name":"Zeta","value":125}]
34
+
35
+ -- Filter merge: view WHERE + outer WHERE should produce correct results
36
+ CREATE VIEW filtered_items AS SELECT id, name, value FROM base_data WHERE category = 'A';
37
+ SELECT * FROM filtered_items WHERE value > 100 ORDER BY id;
38
+ → [{"id":3,"name":"Gamma","value":150},{"id":5,"name":"Zeta","value":125}]
39
+ DROP VIEW filtered_items;
40
+
41
+ -- Predicate pushdown through view alias boundary
42
+ -- id = 1 should push through AliasNode into the view's underlying plan (index seek, no residual FILTER)
43
+ SELECT * FROM category_a_view WHERE id = 1;
44
+ → [{"id":1,"name":"Alpha","value":100}]
45
+
46
+ -- Qualified column references should also work after pushdown
47
+ SELECT v.name FROM category_a_view v WHERE v.id = 3;
48
+ → [{"name":"Gamma"}]
49
+
50
+ -- Projection pruning: selecting a subset of a wide view should return correct results
51
+ CREATE VIEW wide_view AS SELECT id, name, category, value FROM base_data;
52
+ SELECT name FROM wide_view ORDER BY name;
53
+ → [{"name":"Alpha"},{"name":"Beta"},{"name":"Delta"},{"name":"Gamma"},{"name":"Zeta"}]
54
+
55
+ SELECT name, value FROM wide_view WHERE id = 2;
56
+ → [{"name":"Beta","value":200}]
57
+ DROP VIEW wide_view;
58
+
59
+ -- Drop views
60
+ DROP VIEW category_a_view;
61
+ DROP VIEW summary_view;
62
+ DROP VIEW high_value_view;
63
+
64
+ DROP TABLE base_data;
@@ -0,0 +1,191 @@
1
+ -- semi-anti-join.sqllogic - Semi/anti join decorrelation tests
2
+
3
+ -- Setup tables
4
+ CREATE TABLE departments (id INTEGER PRIMARY KEY, name TEXT);
5
+ CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, dept_id INTEGER NULL, salary INTEGER);
6
+ CREATE TABLE projects (id INTEGER PRIMARY KEY, title TEXT, lead_id INTEGER NULL);
7
+
8
+ INSERT INTO departments VALUES (1, 'Engineering'), (2, 'Sales'), (3, 'Marketing'), (4, 'HR');
9
+ INSERT INTO employees VALUES (10, 'Alice', 1, 100), (20, 'Bob', 1, 120), (30, 'Carol', 2, 90), (40, 'Dave', 3, 110), (50, 'Eve', null, 80);
10
+ INSERT INTO projects VALUES (100, 'Alpha', 10), (200, 'Beta', 30), (300, 'Gamma', null);
11
+
12
+ -- ===== Correlated EXISTS → Semi Join =====
13
+
14
+ -- Basic correlated EXISTS
15
+ SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id) ORDER BY d.name;
16
+ → [{"name":"Engineering"},{"name":"Marketing"},{"name":"Sales"}]
17
+
18
+ -- EXISTS with inner-only filter (residual preserved)
19
+ SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id AND e.salary > 100) ORDER BY d.name;
20
+ → [{"name":"Engineering"},{"name":"Marketing"}]
21
+
22
+ -- EXISTS returning no matches
23
+ SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id AND e.salary > 1000) ORDER BY d.name;
24
+ → []
25
+
26
+ -- ===== NOT EXISTS → Anti Join =====
27
+
28
+ -- Basic NOT EXISTS
29
+ SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id) ORDER BY d.name;
30
+ → [{"name":"HR"}]
31
+
32
+ -- NOT EXISTS with inner filter
33
+ SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id AND e.salary > 100) ORDER BY d.name;
34
+ → [{"name":"HR"},{"name":"Sales"}]
35
+
36
+ -- NOT EXISTS where all rows match (empty result for anti)
37
+ SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id AND e.salary > 0) ORDER BY d.name;
38
+ → [{"name":"HR"}]
39
+
40
+ -- ===== IN (correlated subquery) → Semi Join =====
41
+
42
+ -- Basic correlated IN subquery
43
+ SELECT e.name FROM employees e WHERE e.dept_id IN (SELECT d.id FROM departments d WHERE d.id = e.dept_id) ORDER BY e.name;
44
+ → [{"name":"Alice"},{"name":"Bob"},{"name":"Carol"},{"name":"Dave"}]
45
+
46
+ -- IN with additional inner filter
47
+ SELECT e.name FROM employees e WHERE e.dept_id IN (SELECT d.id FROM departments d WHERE d.id = e.dept_id AND d.name = 'Engineering') ORDER BY e.name;
48
+ → [{"name":"Alice"},{"name":"Bob"}]
49
+
50
+ -- ===== Multi-column correlation predicates =====
51
+
52
+ -- Multiple equi-join columns (not yet decorrelated if inner filter isn't simple equi)
53
+ -- Using a self-join pattern
54
+ CREATE TABLE t1 (a INTEGER, b INTEGER, PRIMARY KEY(a, b));
55
+ CREATE TABLE t2 (x INTEGER, y INTEGER, PRIMARY KEY(x, y));
56
+ INSERT INTO t1 VALUES (1, 10), (2, 20), (3, 30);
57
+ INSERT INTO t2 VALUES (1, 10), (2, 99), (3, 30);
58
+
59
+ SELECT a, b FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.x = t1.a AND t2.y = t1.b) ORDER BY a;
60
+ → [{"a":1,"b":10},{"a":3,"b":30}]
61
+
62
+ SELECT a, b FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t2.x = t1.a AND t2.y = t1.b) ORDER BY a;
63
+ → [{"a":2,"b":20}]
64
+
65
+ DROP TABLE t1;
66
+ DROP TABLE t2;
67
+
68
+ -- ===== NULL handling edge cases =====
69
+
70
+ -- EXISTS with NULLs in correlation column (NULLs don't match)
71
+ SELECT e.name FROM employees e WHERE EXISTS (SELECT 1 FROM departments d WHERE d.id = e.dept_id) ORDER BY e.name;
72
+ → [{"name":"Alice"},{"name":"Bob"},{"name":"Carol"},{"name":"Dave"}]
73
+
74
+ -- Eve has NULL dept_id, so she should not appear
75
+ SELECT e.name FROM employees e WHERE NOT EXISTS (SELECT 1 FROM departments d WHERE d.id = e.dept_id) ORDER BY e.name;
76
+ → [{"name":"Eve"}]
77
+
78
+ -- Projects with NULL lead_id
79
+ SELECT p.title FROM projects p WHERE EXISTS (SELECT 1 FROM employees e WHERE e.id = p.lead_id) ORDER BY p.title;
80
+ → [{"title":"Alpha"},{"title":"Beta"}]
81
+
82
+ SELECT p.title FROM projects p WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.id = p.lead_id) ORDER BY p.title;
83
+ → [{"title":"Gamma"}]
84
+
85
+ -- ===== Mixed predicates: EXISTS AND other_condition =====
86
+
87
+ SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id) AND d.id > 1 ORDER BY d.name;
88
+ → [{"name":"Marketing"},{"name":"Sales"}]
89
+
90
+ SELECT d.name FROM departments d WHERE d.id < 4 AND EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id AND e.salary >= 100) ORDER BY d.name;
91
+ → [{"name":"Engineering"},{"name":"Marketing"}]
92
+
93
+ -- NOT EXISTS AND other_condition
94
+ SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id) AND d.name != 'HR';
95
+ → []
96
+
97
+ -- ===== Uncorrelated subqueries NOT decorrelated =====
98
+
99
+ -- Uncorrelated EXISTS should remain as-is (not transformed to a join)
100
+ SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.salary > 1000) ORDER BY d.name;
101
+ → []
102
+
103
+ SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.salary > 50) ORDER BY d.name;
104
+ → [{"name":"Engineering"},{"name":"HR"},{"name":"Marketing"},{"name":"Sales"}]
105
+
106
+ -- Uncorrelated IN subquery should not be decorrelated
107
+ SELECT d.name FROM departments d WHERE d.id IN (SELECT dept_id FROM employees WHERE salary > 100) ORDER BY d.name;
108
+ → [{"name":"Engineering"},{"name":"Marketing"}]
109
+
110
+ -- ===== Scalar subqueries NOT affected =====
111
+
112
+ -- Scalar subquery in WHERE (not EXISTS/IN pattern)
113
+ SELECT d.name FROM departments d WHERE d.id = (SELECT min(dept_id) FROM employees WHERE dept_id IS NOT NULL);
114
+ → [{"name":"Engineering"}]
115
+
116
+ -- ===== query_plan() introspection: verify semi/anti join appears =====
117
+
118
+ -- Verify correlated EXISTS produces a semi join. The physical node is
119
+ -- backend-dependent: under the memory vtab rule-key-set-seek rewrites the hash
120
+ -- semi join into a KeySetSemiJoin (the module accepts a runtime key-set
121
+ -- multi-seek on the primary key), while the store module declines the
122
+ -- runtime-set probe on its PK arm and keeps the HashJoin. Either way the
123
+ -- joinType stays 'semi', which is what this pins.
124
+ SELECT json_extract(properties, '$.joinType') as jt FROM query_plan('SELECT d.name FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id)') WHERE node_type IN ('Join', 'HashJoin', 'KeySetSemiJoin') ORDER BY id;
125
+ → [{"jt":"semi"}]
126
+
127
+ -- Verify NOT EXISTS produces an anti join
128
+ SELECT node_type, json_extract(properties, '$.joinType') as jt FROM query_plan('SELECT d.name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id)') WHERE node_type IN ('Join', 'HashJoin') ORDER BY id;
129
+ → [{"node_type":"HashJoin","jt":"anti"}]
130
+
131
+ DROP TABLE projects;
132
+ DROP TABLE employees;
133
+ DROP TABLE departments;
134
+
135
+ -- ===== Type-coerced correlation: must NOT be decorrelated =====
136
+
137
+ -- Correlation `outer.real = inner.text` is rewritten as `outer.real = cast(inner.text as real)`.
138
+ -- The cast hides the equi-pattern; the rule must abort decorrelation rather than
139
+ -- leave the correlation conjunct as a residual filter on the inner side
140
+ -- (which would fail at runtime with "no row context for outer column").
141
+ create table tt1 (c_text0 text unique, c_text1 text not null unique);
142
+ create table tt2 (c_int0 integer unique, c_real1 real, c_text2 text not null primary key);
143
+ insert into tt1 values ('a','x'),('b','y');
144
+ insert into tt2 values (1, 1.5, 'p'),(2, 2.5, 'q');
145
+
146
+ select count(*) as n from tt2 left join tt1 on c_real1 in (select c_text1 from tt1 where tt2.c_real1 = tt1.c_text1) where c_real1 in (select c_text1 from tt1 where tt2.c_real1 = tt1.c_text1) limit 50;
147
+ → [{"n":0}]
148
+
149
+ drop table tt1;
150
+ drop table tt2;
151
+
152
+ -- ===== FK-backed folds through a derived parent table =====
153
+
154
+ -- rule-anti-join-fk-empty and rule-semi-join-fk-trivial peel a projection off
155
+ -- the parent side and translate the equi columns back to the parent's own
156
+ -- column indices. These pin the ANSWERS; the plan shapes are pinned in
157
+ -- test/plan/subquery-decorrelation.spec.ts.
158
+
159
+ create table fkp (id integer primary key, other integer);
160
+ create table fkc (id integer primary key, p_id integer not null references fkp(id));
161
+ insert into fkp values (1, 99), (2, 98);
162
+ insert into fkc values (10, 1), (20, 2);
163
+
164
+ -- Every child row has a parent, so NOT EXISTS is empty — the fold must agree.
165
+ select id from fkc where not exists (select 1 from (select other, id from fkp) d where d.id = fkc.p_id) order by id;
166
+ → []
167
+
168
+ -- The same shape equating a NON-referenced parent column. `other` sits at the
169
+ -- derived table's output index 0 — the index the FK references — so an
170
+ -- untranslated comparison would fold to empty and drop every row.
171
+ select id from fkc where not exists (select 1 from (select other, id from fkp) d where d.other = fkc.p_id) order by id;
172
+ → [{"id":10},{"id":20}]
173
+
174
+ -- Composite FK: both equi columns translate, and the FK's declared (fa→a,
175
+ -- fb→b) pairing must survive the reordering derived table.
176
+ create table fkp2 (a integer, b integer, extra text, primary key (a, b));
177
+ create table fkc2 (id integer primary key, fa integer not null, fb integer not null, foreign key (fa, fb) references fkp2(a, b));
178
+ insert into fkp2 values (1, 2, 'x'), (3, 4, 'y');
179
+ insert into fkc2 values (10, 1, 2), (20, 3, 4);
180
+
181
+ select id from fkc2 where exists (select 1 from (select b, a, extra from fkp2) q where q.a = fkc2.fa and q.b = fkc2.fb) order by id;
182
+ → [{"id":10},{"id":20}]
183
+
184
+ -- Permuted against the FK's pairing: a different, uncovered inclusion.
185
+ select id from fkc2 where exists (select 1 from (select b, a, extra from fkp2) q where q.a = fkc2.fb and q.b = fkc2.fa) order by id;
186
+ → []
187
+
188
+ drop table fkc2;
189
+ drop table fkp2;
190
+ drop table fkc;
191
+ drop table fkp;
@@ -0,0 +1,118 @@
1
+ -- adapted from SQLite test/view.test
2
+ -- View-feature scenarios beyond basic 08-views.sqllogic.
3
+
4
+ -- ===================================
5
+ -- 1. Multi-level views (view referencing another view)
6
+ -- ===================================
7
+
8
+ create table base_v (id integer primary key, cat text, val integer);
9
+ insert into base_v values (1, 'a', 10), (2, 'b', 20), (3, 'a', 30), (4, 'b', 40);
10
+
11
+ -- v1 filters; v2 aggregates over v1
12
+ create view v1 as select id, cat, val from base_v where val > 15;
13
+ create view v2 as select cat, count(*) as n, sum(val) as s from v1 group by cat;
14
+
15
+ select * from v2 order by cat;
16
+ → [{"cat":"a","n":1,"s":30},{"cat":"b","n":2,"s":60}]
17
+
18
+ -- three-level chain
19
+ create view v3 as select cat from v2 where n > 1;
20
+
21
+ select * from v3;
22
+ → [{"cat":"b"}]
23
+
24
+ drop view v3;
25
+ drop view v2;
26
+ drop view v1;
27
+ drop table base_v;
28
+
29
+ -- ===================================
30
+ -- 2. View with explicit column-list rename
31
+ -- ===================================
32
+
33
+ create table cr_base (id integer primary key, name text, val integer);
34
+ insert into cr_base values (1, 'x', 5), (2, 'y', 7);
35
+
36
+ create view cr_v (k, label, amount) as select id, name, val from cr_base;
37
+
38
+ select k, label, amount from cr_v order by k;
39
+ → [{"k":1,"label":"x","amount":5},{"k":2,"label":"y","amount":7}]
40
+
41
+ drop view cr_v;
42
+
43
+ create view cr_bad (a, b) as select id, name, val from cr_base;
44
+ -- error: declared columns
45
+ drop view if exists cr_bad;
46
+
47
+ drop table cr_base;
48
+
49
+ -- ===================================
50
+ -- 3. View lifecycle
51
+ -- ===================================
52
+
53
+ create table tv_base (id integer primary key, val integer);
54
+ insert into tv_base values (1, 10), (2, 20);
55
+
56
+ create view tv_t as select id, val from tv_base where val > 10;
57
+
58
+ select * from tv_t;
59
+ → [{"id":2,"val":20}]
60
+
61
+ drop view tv_t;
62
+ drop table tv_base;
63
+
64
+ -- ===================================
65
+ -- 4. View over UNION ALL / compound select
66
+ -- ===================================
67
+
68
+ create table cs_a (id integer primary key, label text);
69
+ create table cs_b (id integer primary key, label text);
70
+ insert into cs_a values (1, 'a1'), (2, 'a2');
71
+ insert into cs_b values (3, 'b1'), (4, 'b2');
72
+
73
+ create view cs_v as
74
+ select id, label from cs_a
75
+ union all
76
+ select id, label from cs_b;
77
+
78
+ select * from cs_v order by id;
79
+ → [{"id":1,"label":"a1"},{"id":2,"label":"a2"},{"id":3,"label":"b1"},{"id":4,"label":"b2"}]
80
+
81
+ drop view cs_v;
82
+ drop table cs_a;
83
+ drop table cs_b;
84
+
85
+ -- ===================================
86
+ -- 5. Schema-qualified view (main / temp)
87
+ -- ===================================
88
+
89
+ create table sq_base (id integer primary key, val integer);
90
+ insert into sq_base values (1, 10), (2, 20);
91
+
92
+ create view main.sq_v as select id, val from sq_base where val > 10;
93
+
94
+ select * from main.sq_v;
95
+ → [{"id":2,"val":20}]
96
+
97
+ create view temp.sq_tv as select id from sq_base;
98
+
99
+ drop view temp.sq_tv;
100
+ drop view main.sq_v;
101
+ drop table sq_base;
102
+
103
+ -- ===================================
104
+ -- 6. View aliases / self-join in view body
105
+ -- ===================================
106
+
107
+ create table tsj (id integer primary key, parent_id integer null);
108
+ insert into tsj values (1, null), (2, 1), (3, 1);
109
+
110
+ create view v_sj as
111
+ select c.id as child, p.id as parent
112
+ from tsj c left join tsj p on c.parent_id = p.id;
113
+
114
+ select * from v_sj order by child;
115
+ → [{"child":1,"parent":null},{"child":2,"parent":1},{"child":3,"parent":1}]
116
+
117
+ drop view v_sj;
118
+ drop table tsj;
@@ -0,0 +1,251 @@
1
+ -- 08.1.1-uncorrelated-in-semijoin.sqllogic — uncorrelated filter-position
2
+ -- `col IN (subquery)` rewritten to a semi join (rule-subquery-decorrelation,
3
+ -- uncorrelated arm).
4
+ --
5
+ -- All columns here are deliberately NON-indexed, so these cases ride the plain
6
+ -- hash semi join (the sibling 08.4-key-set-semi-join.sqllogic covers the
7
+ -- secondary-indexed KeySetSemiJoin path, including TIMESPAN semantic equality
8
+ -- and NOCASE-indexed targets). Every answer must be identical to what the
9
+ -- runtime set-probe path returns — the rewrite is sound under WHERE only
10
+ -- because a filter collapses IN's NULL result to "drop the row", which is
11
+ -- exactly what a semi join does.
12
+
13
+ -- Setup: nullable non-indexed columns on both sides.
14
+ CREATE TABLE souter (id INTEGER PRIMARY KEY, x INTEGER NULL, s TEXT NULL);
15
+ CREATE TABLE sinner (id INTEGER PRIMARY KEY, v INTEGER NULL);
16
+
17
+ INSERT INTO souter VALUES (1, 10, 'p'), (2, 20, 'q'), (3, 30, 'r'), (4, NULL, 's');
18
+ -- 10 appears twice (fan-out check) and one member is NULL.
19
+ INSERT INTO sinner VALUES (1, 10), (2, 10), (3, 99), (4, NULL);
20
+
21
+ -- ===== NULL and emptiness =====
22
+
23
+ -- Match against a non-NULL member is kept; NULL outer x (id 4) is dropped;
24
+ -- no-match rows (ids 2, 3) are dropped even though the inner contains a NULL
25
+ -- (IN yields NULL there — WHERE drops it, same as the semi join).
26
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner) ORDER BY id;
27
+ → [{"id":1}]
28
+
29
+ -- Duplicate inner members must not fan the outer out: exactly one row.
30
+ SELECT count(*) AS c FROM souter WHERE x IN (SELECT v FROM sinner);
31
+ → [{"c":1}]
32
+
33
+ -- Empty inner ⇒ no rows survive.
34
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner WHERE v > 1000);
35
+ → []
36
+
37
+ -- All-NULL inner ⇒ no rows survive.
38
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner WHERE v IS NULL);
39
+ → []
40
+
41
+ -- ===== Inner shapes used verbatim as the join's right side =====
42
+
43
+ -- Inner WHERE.
44
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner WHERE v < 50) ORDER BY id;
45
+ → [{"id":1}]
46
+
47
+ -- Inner DISTINCT.
48
+ SELECT id FROM souter WHERE x IN (SELECT DISTINCT v FROM sinner) ORDER BY id;
49
+ → [{"id":1}]
50
+
51
+ -- Inner ORDER BY + LIMIT (deterministic subset: the two smallest non-NULL v).
52
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner WHERE v IS NOT NULL ORDER BY v LIMIT 2) ORDER BY id;
53
+ → [{"id":1}]
54
+
55
+ -- VALUES list as the subquery.
56
+ SELECT id FROM souter WHERE x IN (VALUES (10), (20)) ORDER BY id;
57
+ → [{"id":1},{"id":2}]
58
+
59
+ -- Set operations.
60
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner UNION SELECT 20) ORDER BY id;
61
+ → [{"id":1},{"id":2}]
62
+
63
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner UNION ALL SELECT 30) ORDER BY id;
64
+ → [{"id":1},{"id":3}]
65
+
66
+ -- CTE reference as the subquery body.
67
+ WITH w AS (SELECT v FROM sinner) SELECT id FROM souter WHERE x IN (SELECT v FROM w) ORDER BY id;
68
+ → [{"id":1}]
69
+
70
+ -- Computed single output column (the shape the correlated arm cannot take).
71
+ SELECT id FROM souter WHERE x IN (SELECT v + 10 FROM sinner) ORDER BY id;
72
+ → [{"id":2}]
73
+
74
+ -- ===== Multiple conjuncts =====
75
+
76
+ -- Two uncorrelated IN conjuncts in one WHERE (two stacked semi joins).
77
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner) AND s IN (SELECT 'p') ORDER BY id;
78
+ → [{"id":1}]
79
+
80
+ -- Mixed correlated + uncorrelated IN conjuncts.
81
+ SELECT o.id FROM souter o WHERE o.x IN (SELECT v FROM sinner) AND o.x IN (SELECT i2.v FROM sinner i2 WHERE i2.v = o.x) ORDER BY o.id;
82
+ → [{"id":1}]
83
+
84
+ -- IN conjunct next to an ordinary predicate (residual re-wrapped above the join).
85
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner) AND id < 10 ORDER BY id;
86
+ → [{"id":1}]
87
+
88
+ -- ===== Shapes that must NOT rewrite (three-valued answers preserved) =====
89
+
90
+ -- NOT IN with a NULL in the inner: NULL result for every non-member ⇒ no rows.
91
+ SELECT id FROM souter WHERE x NOT IN (SELECT v FROM sinner) ORDER BY id;
92
+ → []
93
+
94
+ -- IN under OR is not a top-level conjunct.
95
+ SELECT id FROM souter WHERE x IN (SELECT v FROM sinner) OR id = 4 ORDER BY id;
96
+ → [{"id":1},{"id":4}]
97
+
98
+ -- IS NULL over the IN result observes the three-valued answer:
99
+ -- id 2, 3 (no match, inner has NULL) and id 4 (NULL x) yield NULL.
100
+ SELECT id FROM souter WHERE (x IN (SELECT v FROM sinner)) IS NULL ORDER BY id;
101
+ → [{"id":2},{"id":3},{"id":4}]
102
+
103
+ -- Projection position keeps the full three-valued result per row.
104
+ SELECT id, x IN (SELECT v FROM sinner) AS m FROM souter ORDER BY id;
105
+ → [{"id":1,"m":true},{"id":2,"m":null},{"id":3,"m":null},{"id":4,"m":null}]
106
+
107
+ -- Expression (non-column) left side stays on the set-probe path; same rows.
108
+ SELECT id FROM souter WHERE x + 0 IN (SELECT v FROM sinner) ORDER BY id;
109
+ → [{"id":1}]
110
+
111
+ -- ===== Types and collation =====
112
+
113
+ -- NOCASE outer column against a default-BINARY inner: resolves NOCASE.
114
+ CREATE TABLE nco (id INTEGER PRIMARY KEY, t TEXT COLLATE NOCASE);
115
+ CREATE TABLE ncb (id INTEGER PRIMARY KEY, t TEXT);
116
+ INSERT INTO nco VALUES (1, 'Apple'), (2, 'BANANA');
117
+ INSERT INTO ncb VALUES (1, 'apple'), (2, 'cherry');
118
+
119
+ SELECT id FROM nco WHERE t IN (SELECT t FROM ncb) ORDER BY id;
120
+ → [{"id":1}]
121
+
122
+ -- And the reverse: default-BINARY outer against a NOCASE inner column.
123
+ SELECT id FROM ncb WHERE t IN (SELECT t FROM nco) ORDER BY id;
124
+ → [{"id":1}]
125
+
126
+ -- INTEGER outer against REAL inner: numeric equality, 10 matches 10.0.
127
+ CREATE TABLE reals (id INTEGER PRIMARY KEY, r REAL);
128
+ INSERT INTO reals VALUES (1, 10.0), (2, 20.5);
129
+ SELECT id FROM souter WHERE x IN (SELECT r FROM reals) ORDER BY id;
130
+ → [{"id":1}]
131
+
132
+ -- TEXT inner against INTEGER outer matches on the numeric reading, exactly as
133
+ -- `x = '10'` does. The synthesized `=` is reconciled through the same coercion
134
+ -- a hand-written one gets, so the cast wrapper fails the equi-pair gate and the
135
+ -- conjunct declines to the set probe, whose own numeric ↔ textual arm answers.
136
+ -- Pinned so the rewrite and the set probe cannot silently split.
137
+ CREATE TABLE texts (id INTEGER PRIMARY KEY, t TEXT);
138
+ INSERT INTO texts VALUES (1, '10'), (2, '20');
139
+ SELECT id FROM souter WHERE x IN (SELECT t FROM texts) ORDER BY id;
140
+ → [{"id":1},{"id":2}]
141
+
142
+ -- Mixed semantic-ordering pair (TIMESPAN outer, TEXT inner): the equi-pair
143
+ -- gate declines, the set probe answers, and its semantic key transform still
144
+ -- matches 'PT1H' against 'PT60M'. (Same-type TIMESPAN pairs go through the
145
+ -- semi join and are pinned in 08.4-key-set-semi-join.sqllogic.)
146
+ CREATE TABLE spans (id INTEGER PRIMARY KEY, d TIMESPAN);
147
+ CREATE TABLE spantext (id INTEGER PRIMARY KEY, t TEXT);
148
+ INSERT INTO spans VALUES (1, timespan('PT1H')), (2, timespan('P1D'));
149
+ INSERT INTO spantext VALUES (1, 'PT60M');
150
+ SELECT id FROM spans WHERE d IN (SELECT t FROM spantext) ORDER BY id;
151
+ → [{"id":1}]
152
+
153
+ -- ===== FK-backed IN =====
154
+
155
+ -- A declared NOT NULL FK covering the join key: rule-semi-join-fk-trivial drops
156
+ -- the semi join (the plan shape is pinned in test/plan/subquery-decorrelation),
157
+ -- so every child row survives without the parent ever being read.
158
+ CREATE TABLE fkdept (id INTEGER PRIMARY KEY, dname TEXT);
159
+ CREATE TABLE fkemp (id INTEGER PRIMARY KEY, dept_id INTEGER NOT NULL REFERENCES fkdept(id));
160
+ INSERT INTO fkdept VALUES (1, 'eng'), (2, 'sales');
161
+ INSERT INTO fkemp VALUES (10, 1), (20, 2);
162
+ SELECT id FROM fkemp WHERE dept_id IN (SELECT id FROM fkdept) ORDER BY id;
163
+ → [{"id":10},{"id":20}]
164
+
165
+ -- A nullable FK column folds to `WHERE fk IS NOT NULL` instead: a NULL never
166
+ -- matches under `=`, so the NULL row must not survive.
167
+ CREATE TABLE fkemp_opt (id INTEGER PRIMARY KEY, dept_id INTEGER NULL REFERENCES fkdept(id));
168
+ INSERT INTO fkemp_opt VALUES (10, 1), (20, NULL), (30, 2);
169
+ SELECT id FROM fkemp_opt WHERE dept_id IN (SELECT id FROM fkdept) ORDER BY id;
170
+ → [{"id":10},{"id":30}]
171
+
172
+ -- A projection that reorders the parent's columns still folds — the equi
173
+ -- column is translated back to the parent's own column index first.
174
+ SELECT id FROM fkemp WHERE dept_id IN (SELECT id FROM (SELECT dname, id FROM fkdept)) ORDER BY id;
175
+ → [{"id":10},{"id":20}]
176
+
177
+ -- ...but a filtered parent must NOT fold: the FK guarantees the parent row
178
+ -- exists, not that it survives the subquery's WHERE.
179
+ SELECT id FROM fkemp WHERE dept_id IN (SELECT id FROM fkdept WHERE dname = 'eng') ORDER BY id;
180
+ → [{"id":10}]
181
+
182
+ -- Nor may an equality against a NON-referenced parent column fold. dname is the
183
+ -- subquery's output column 0 — the same index as the referenced column
184
+ -- fkdept.id — so an untranslated index comparison would spuriously align.
185
+ SELECT id FROM fkemp WHERE dept_id IN (SELECT dname FROM fkdept) ORDER BY id;
186
+ → []
187
+
188
+ -- Same hazard on the child side: the IN is on fkemp.id, which a reordering
189
+ -- derived table puts at the index the FK column occupies in fkemp.
190
+ SELECT e.id FROM (SELECT dept_id, id FROM fkemp) e WHERE e.id IN (SELECT id FROM fkdept) ORDER BY e.id;
191
+ → []
192
+
193
+ -- ===== The one other place an IN decides row fate: CHECK =====
194
+
195
+ -- A CHECK constraint's IN is a scalar expression on a constraint node, not a
196
+ -- Filter predicate, so the rewrite can never reach it — and must not, because
197
+ -- a CHECK passes on IN's three-valued "unknown". A NULL value is accepted; a
198
+ -- non-member is rejected.
199
+ CREATE TABLE chk_allowed (id INTEGER PRIMARY KEY, code INTEGER);
200
+ INSERT INTO chk_allowed VALUES (1, 1), (2, 2);
201
+ CREATE TABLE chk_t (id INTEGER PRIMARY KEY, code INTEGER NULL, CHECK (code IN (SELECT code FROM chk_allowed)));
202
+
203
+ INSERT INTO chk_t VALUES (1, NULL), (2, 2);
204
+ SELECT id, code FROM chk_t ORDER BY id;
205
+ → [{"id":1,"code":null},{"id":2,"code":2}]
206
+
207
+ INSERT INTO chk_t VALUES (3, 9);
208
+ -- error: CHECK constraint failed
209
+
210
+ -- ===== DML with the semi join as the mutation source =====
211
+
212
+ CREATE TABLE dml_t (id INTEGER PRIMARY KEY, x INTEGER NULL, mark INTEGER);
213
+ CREATE TABLE dml_keys (id INTEGER PRIMARY KEY, k INTEGER NULL);
214
+ INSERT INTO dml_t VALUES (1, 10, 0), (2, 20, 0), (3, 30, 0), (4, NULL, 0);
215
+ INSERT INTO dml_keys VALUES (1, 10), (2, 30), (3, NULL);
216
+
217
+ UPDATE dml_t SET mark = 1 WHERE x IN (SELECT k FROM dml_keys);
218
+ SELECT id, mark FROM dml_t ORDER BY id;
219
+ → [{"id":1,"mark":1},{"id":2,"mark":0},{"id":3,"mark":1},{"id":4,"mark":0}]
220
+
221
+ DELETE FROM dml_t WHERE x IN (SELECT k FROM dml_keys);
222
+ SELECT id FROM dml_t ORDER BY id;
223
+ → [{"id":2},{"id":4}]
224
+
225
+ -- Self-referencing DELETE on a non-indexed column: the hash build drains the
226
+ -- inner fully before any probe, so membership is decided by the
227
+ -- pre-statement snapshot (same semantics the set probe pinned in
228
+ -- 07.7-in-subquery-caching.sqllogic).
229
+ CREATE TABLE selfd (id INTEGER PRIMARY KEY, x INTEGER NULL, keep INTEGER);
230
+ INSERT INTO selfd VALUES (1, 100, 1), (2, 200, 0), (3, 300, 1), (4, 400, 0);
231
+ DELETE FROM selfd WHERE x IN (SELECT x FROM selfd WHERE keep = 0);
232
+ SELECT id FROM selfd ORDER BY id;
233
+ → [{"id":1},{"id":3}]
234
+
235
+ -- Cleanup
236
+ DROP TABLE chk_t;
237
+ DROP TABLE chk_allowed;
238
+ DROP TABLE selfd;
239
+ DROP TABLE dml_keys;
240
+ DROP TABLE dml_t;
241
+ DROP TABLE fkemp_opt;
242
+ DROP TABLE fkemp;
243
+ DROP TABLE fkdept;
244
+ DROP TABLE spantext;
245
+ DROP TABLE spans;
246
+ DROP TABLE texts;
247
+ DROP TABLE reals;
248
+ DROP TABLE ncb;
249
+ DROP TABLE nco;
250
+ DROP TABLE sinner;
251
+ DROP TABLE souter;