@quereus/quereus 4.20.0 → 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 (400) hide show
  1. package/README.md +2 -0
  2. package/dist/src/common/types.d.ts +4 -4
  3. package/dist/src/index.d.ts +1 -1
  4. package/dist/src/index.d.ts.map +1 -1
  5. package/dist/src/index.js +3 -2
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/src/schema/catalog-rendering.js +13 -1
  8. package/dist/src/schema/catalog-rendering.js.map +1 -1
  9. package/dist/src/schema/catalog.d.ts +35 -2
  10. package/dist/src/schema/catalog.d.ts.map +1 -1
  11. package/dist/src/schema/catalog.js +42 -33
  12. package/dist/src/schema/catalog.js.map +1 -1
  13. package/dist/src/schema/schema-differ.d.ts +1 -1
  14. package/dist/src/schema/schema-differ.d.ts.map +1 -1
  15. package/dist/src/schema/schema-differ.js +195 -33
  16. package/dist/src/schema/schema-differ.js.map +1 -1
  17. package/dist/src/schema/unique-enforcement.d.ts +23 -1
  18. package/dist/src/schema/unique-enforcement.d.ts.map +1 -1
  19. package/dist/src/schema/unique-enforcement.js +43 -1
  20. package/dist/src/schema/unique-enforcement.js.map +1 -1
  21. package/dist/src/vtab/memory/layer/manager.d.ts +15 -12
  22. package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
  23. package/dist/src/vtab/memory/layer/manager.js +87 -100
  24. package/dist/src/vtab/memory/layer/manager.js.map +1 -1
  25. package/package.json +7 -4
  26. package/test/README.md +173 -0
  27. package/test/logic/01-basic.sqllogic +39 -0
  28. package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
  29. package/test/logic/01.2-strings.sqllogic +43 -0
  30. package/test/logic/01.5-insert-select.sqllogic +237 -0
  31. package/test/logic/01.6-update-extras.sqllogic +118 -0
  32. package/test/logic/01.7-update-from.sqllogic +67 -0
  33. package/test/logic/01.8-delete-extras.sqllogic +122 -0
  34. package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
  35. package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
  36. package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
  37. package/test/logic/01.9-query-expr-values.sqllogic +111 -0
  38. package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
  39. package/test/logic/02-filters.sqllogic +54 -0
  40. package/test/logic/02-smoke.sqllogic +62 -0
  41. package/test/logic/02.1-bind-parameters.sqllogic +223 -0
  42. package/test/logic/03-expressions.sqllogic +190 -0
  43. package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
  44. package/test/logic/03.4-defaults.sqllogic +554 -0
  45. package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
  46. package/test/logic/03.5-tvf.sqllogic +61 -0
  47. package/test/logic/03.6-type-system.sqllogic +544 -0
  48. package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
  49. package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
  50. package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
  51. package/test/logic/03.8-not-precedence.sqllogic +255 -0
  52. package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
  53. package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
  54. package/test/logic/04-order-by.sqllogic +38 -0
  55. package/test/logic/04-transactions.sqllogic +239 -0
  56. package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
  57. package/test/logic/05-vtab_memory.sqllogic +50 -0
  58. package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
  59. package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
  60. package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
  61. package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
  62. package/test/logic/06-builtin_functions.sqllogic +149 -0
  63. package/test/logic/06.1-string-functions.sqllogic +92 -0
  64. package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
  65. package/test/logic/06.2-math-functions.sqllogic +82 -0
  66. package/test/logic/06.3-schema.sqllogic +48 -0
  67. package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
  68. package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
  69. package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
  70. package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
  71. package/test/logic/06.3.4-view-info.sqllogic +378 -0
  72. package/test/logic/06.3.5-column-info.sqllogic +347 -0
  73. package/test/logic/06.3.6-schema-views.sqllogic +29 -0
  74. package/test/logic/06.4-schema-search-path.sqllogic +354 -0
  75. package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
  76. package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
  77. package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
  78. package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
  79. package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
  80. package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
  81. package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
  82. package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
  83. package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
  84. package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
  85. package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
  86. package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
  87. package/test/logic/06.7-json-extended.sqllogic +53 -0
  88. package/test/logic/06.8-json-path-operators.sqllogic +99 -0
  89. package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
  90. package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
  91. package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
  92. package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
  93. package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
  94. package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
  95. package/test/logic/07-aggregates.sqllogic +193 -0
  96. package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
  97. package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
  98. package/test/logic/07.3-group-by-extras.sqllogic +602 -0
  99. package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
  100. package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
  101. package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
  102. package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
  103. package/test/logic/07.5-window.sqllogic +1941 -0
  104. package/test/logic/07.5.1-window-named.sqllogic +13 -0
  105. package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
  106. package/test/logic/07.6-subqueries.sqllogic +78 -0
  107. package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
  108. package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
  109. package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
  110. package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
  111. package/test/logic/07.7.1-in-extras.sqllogic +158 -0
  112. package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
  113. package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
  114. package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
  115. package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
  116. package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
  117. package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
  118. package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
  119. package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
  120. package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
  121. package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
  122. package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
  123. package/test/logic/07.9-in-value-list.sqllogic +154 -0
  124. package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
  125. package/test/logic/08-views.sqllogic +64 -0
  126. package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
  127. package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
  128. package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
  129. package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
  130. package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
  131. package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
  132. package/test/logic/09-set_operations.sqllogic +244 -0
  133. package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
  134. package/test/logic/10-distinct_datatypes.sqllogic +127 -0
  135. package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
  136. package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
  137. package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
  138. package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
  139. package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
  140. package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
  141. package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
  142. package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
  143. package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
  144. package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
  145. package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
  146. package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
  147. package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
  148. package/test/logic/10.2-column-features.sqllogic +365 -0
  149. package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
  150. package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
  151. package/test/logic/10.3-function-features.sqllogic +247 -0
  152. package/test/logic/10.4-schema-scale.sqllogic +168 -0
  153. package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
  154. package/test/logic/10.5-indexes.sqllogic +164 -0
  155. package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
  156. package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
  157. package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
  158. package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
  159. package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
  160. package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
  161. package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
  162. package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
  163. package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
  164. package/test/logic/100.1-where-extras.sqllogic +163 -0
  165. package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
  166. package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
  167. package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
  168. package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
  169. package/test/logic/102-unique-constraints.sqllogic +145 -0
  170. package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
  171. package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
  172. package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
  173. package/test/logic/102.2-unique-collation.sqllogic +181 -0
  174. package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
  175. package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
  176. package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
  177. package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
  178. package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
  179. package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
  180. package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
  181. package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
  182. package/test/logic/108-cardinality-estimation.sqllogic +146 -0
  183. package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
  184. package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
  185. package/test/logic/11-joins.sqllogic +86 -0
  186. package/test/logic/11.1-join-using.sqllogic +267 -0
  187. package/test/logic/11.2-comma-join.sqllogic +35 -0
  188. package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
  189. package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
  190. package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
  191. package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
  192. package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
  193. package/test/logic/12-empty-primary-key.sqllogic +124 -0
  194. package/test/logic/12-join_padding_order.sqllogic +58 -0
  195. package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
  196. package/test/logic/13-cte.sqllogic +137 -0
  197. package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
  198. package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
  199. package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
  200. package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
  201. package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
  202. package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
  203. package/test/logic/13.4-cte-extras.sqllogic +98 -0
  204. package/test/logic/13.5-cte-join-order.sqllogic +166 -0
  205. package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
  206. package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
  207. package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
  208. package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
  209. package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
  210. package/test/logic/14-utilities.sqllogic +168 -0
  211. package/test/logic/15-timespan.sqllogic +279 -0
  212. package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
  213. package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
  214. package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
  215. package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
  216. package/test/logic/16-epoch.sqllogic +187 -0
  217. package/test/logic/17-weekday-modifier.sqllogic +78 -0
  218. package/test/logic/18-json-string-escapes.sqllogic +86 -0
  219. package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
  220. package/test/logic/20-empty-single-row.sqllogic +261 -0
  221. package/test/logic/21-null-edge-cases.sqllogic +227 -0
  222. package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
  223. package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
  224. package/test/logic/21.2-between-edges.sqllogic +157 -0
  225. package/test/logic/22-boundary-values.sqllogic +175 -0
  226. package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
  227. package/test/logic/24-builtin-branches.sqllogic +611 -0
  228. package/test/logic/24.1-substr-extras.sqllogic +75 -0
  229. package/test/logic/24.2-random-extras.sqllogic +39 -0
  230. package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
  231. package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
  232. package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
  233. package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
  234. package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
  235. package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
  236. package/test/logic/26-join-edge-cases.sqllogic +333 -0
  237. package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
  238. package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
  239. package/test/logic/26.3-join-on-constants.sqllogic +61 -0
  240. package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
  241. package/test/logic/27-window-edge-cases.sqllogic +206 -0
  242. package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
  243. package/test/logic/27.2-window-exclude.sqllogic +13 -0
  244. package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
  245. package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
  246. package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
  247. package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
  248. package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
  249. package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
  250. package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
  251. package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
  252. package/test/logic/40-constraints.sqllogic +418 -0
  253. package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
  254. package/test/logic/40.2-check-extras.sqllogic +683 -0
  255. package/test/logic/41-alter-table.sqllogic +191 -0
  256. package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
  257. package/test/logic/41-fk-cross-schema.sqllogic +155 -0
  258. package/test/logic/41-fk-extended-targets.sqllogic +173 -0
  259. package/test/logic/41-foreign-keys.sqllogic +1001 -0
  260. package/test/logic/41-generated-column-errors.sqllogic +225 -0
  261. package/test/logic/41-generated-column-extras.sqllogic +598 -0
  262. package/test/logic/41-generated-column-scope.sqllogic +329 -0
  263. package/test/logic/41-generated-columns.sqllogic +361 -0
  264. package/test/logic/41.1-alter-pk.sqllogic +230 -0
  265. package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
  266. package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
  267. package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
  268. package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
  269. package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
  270. package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
  271. package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
  272. package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
  273. package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
  274. package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
  275. package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
  276. package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
  277. package/test/logic/41.2-alter-column.sqllogic +382 -0
  278. package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
  279. package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
  280. package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
  281. package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
  282. package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
  283. package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
  284. package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
  285. package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
  286. package/test/logic/41.5-alter-misc.sqllogic +48 -0
  287. package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
  288. package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
  289. package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
  290. package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
  291. package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
  292. package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
  293. package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
  294. package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
  295. package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
  296. package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
  297. package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
  298. package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
  299. package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
  300. package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
  301. package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
  302. package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
  303. package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
  304. package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
  305. package/test/logic/42-committed-snapshot.sqllogic +254 -0
  306. package/test/logic/42-returning.sqllogic +159 -0
  307. package/test/logic/42.1-returning-extras.sqllogic +232 -0
  308. package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
  309. package/test/logic/43-default-nullability.sqllogic +131 -0
  310. package/test/logic/43-transition-constraints.sqllogic +341 -0
  311. package/test/logic/43.1-default-collation.sqllogic +140 -0
  312. package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
  313. package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
  314. package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
  315. package/test/logic/44-determinism-validation.sqllogic +164 -0
  316. package/test/logic/44-orthogonality.sqllogic +146 -0
  317. package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
  318. package/test/logic/45-udf-determinism.sqllogic +39 -0
  319. package/test/logic/46-mutation-context.sqllogic +595 -0
  320. package/test/logic/47-upsert.sqllogic +255 -0
  321. package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
  322. package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
  323. package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
  324. package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
  325. package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
  326. package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
  327. package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
  328. package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
  329. package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
  330. package/test/logic/49-reference-graph.sqllogic +84 -0
  331. package/test/logic/50-declarative-schema.sqllogic +2550 -0
  332. package/test/logic/50-metadata-tags.sqllogic +1033 -0
  333. package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
  334. package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
  335. package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
  336. package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +173 -0
  337. package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
  338. package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
  339. package/test/logic/51-lens-foundation.sqllogic +147 -0
  340. package/test/logic/51-materialized-views.sqllogic +376 -0
  341. package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
  342. package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
  343. package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
  344. package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
  345. package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
  346. package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
  347. package/test/logic/52-lens-overrides.sqllogic +566 -0
  348. package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
  349. package/test/logic/53-reserved-tags.sqllogic +252 -0
  350. package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
  351. package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
  352. package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
  353. package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
  354. package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
  355. package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
  356. package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
  357. package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
  358. package/test/logic/55-lens-prover.sqllogic +202 -0
  359. package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
  360. package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
  361. package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
  362. package/test/logic/81-quickpick.sqllogic +24 -0
  363. package/test/logic/82-bloom-join.sqllogic +185 -0
  364. package/test/logic/83-merge-join.sqllogic +280 -0
  365. package/test/logic/84-asof-scan.sqllogic +238 -0
  366. package/test/logic/84-key-cardinality.sqllogic +50 -0
  367. package/test/logic/85-relational-const-folding.sqllogic +51 -0
  368. package/test/logic/86-scalar-cse.sqllogic +42 -0
  369. package/test/logic/90-error_paths.sqllogic +114 -0
  370. package/test/logic/90.1-parse-errors.sqllogic +77 -0
  371. package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
  372. package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
  373. package/test/logic/90.3-expression-errors.sqllogic +43 -0
  374. package/test/logic/90.4-dml-errors.sqllogic +47 -0
  375. package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
  376. package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
  377. package/test/logic/90.6-select-error-paths.sqllogic +57 -0
  378. package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
  379. package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
  380. package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
  381. package/test/logic/93.1-view-error-paths.sqllogic +74 -0
  382. package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
  383. package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
  384. package/test/logic/93.4-view-mutation.sqllogic +4881 -0
  385. package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
  386. package/test/logic/93.5-authored-inverse.sqllogic +415 -0
  387. package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
  388. package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
  389. package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
  390. package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
  391. package/test/logic/95-assertions.sqllogic +1417 -0
  392. package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
  393. package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
  394. package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
  395. package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
  396. package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
  397. package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
  398. package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
  399. package/test/logic/drop-unique-index.sqllogic +88 -0
  400. package/test/logic/pushdown-test.sqllogic +36 -0
@@ -0,0 +1,587 @@
1
+ -- PRIMARY KEY does not imply NOT NULL.
2
+ --
3
+ -- `primary key` names the row identity and nothing more; a key column keeps the nullability it
4
+ -- declared, or the one `pragma default_column_nullability` gave it. That is one rule for both
5
+ -- spellings: a declared `primary key (x, y)` and the all-columns key Quereus synthesizes for a
6
+ -- table with no PRIMARY KEY produce identical schemas.
7
+ --
8
+ -- Under the shipped `not_null` default this is mostly invisible — every column is NOT NULL unless
9
+ -- it says otherwise, so `id integer primary key` is still non-nullable. The nullable case needs an
10
+ -- explicit `null` on the column or the `nullable` session default.
11
+ --
12
+ -- NULL is an ordinary, self-equal value in key position on both backends (memory compares
13
+ -- NULL == NULL as equal and orders NULL first; the store's key codec encodes TYPE_NULL first), so
14
+ -- two rows with an all-NULL key collide as a duplicate primary key. `UNIQUE` still answers NULL
15
+ -- the other way — NULLs stay distinct there and never collide. See docs/schema.md
16
+ -- § "Primary-key nullability".
17
+ --
18
+ -- Key columns are INTEGER throughout: the store defaults an undecorated TEXT primary-key column to
19
+ -- NOCASE while memory uses BINARY (see the 10.2.2 note in logic.spec.ts), which would make this
20
+ -- file diverge between backends for reasons that have nothing to do with nullability.
21
+
22
+ -- ===================================
23
+ -- 1. The shipped default is unchanged: an undecorated key column is still NOT NULL.
24
+ -- This is most of the existing corpus and must NOT move.
25
+ -- ===================================
26
+
27
+ pragma default_column_nullability;
28
+ → [{"name": "default_column_nullability", "value": "not_null"}]
29
+
30
+ create table t_default_pk (id integer primary key, val text);
31
+
32
+ select name, "notnull", pk from table_info('t_default_pk') where name = 'id';
33
+ → [{"name":"id","notnull":1,"pk":1}]
34
+
35
+ insert into t_default_pk values (null, 'nope');
36
+ -- error: NOT NULL constraint failed: t_default_pk.id
37
+
38
+ drop table t_default_pk;
39
+
40
+ -- ===================================
41
+ -- 2. The headline case: `x integer null primary key` is nullable and accepts NULL.
42
+ -- ===================================
43
+
44
+ create table t_null_pk (x integer null primary key, val text null);
45
+
46
+ select name, "notnull", pk from table_info('t_null_pk') where name = 'x';
47
+ → [{"name":"x","notnull":0,"pk":1}]
48
+
49
+ insert into t_null_pk values (null, 'first');
50
+
51
+ select x, val from t_null_pk;
52
+ → [{"x":null,"val":"first"}]
53
+
54
+ -- The NULL key is a real identity: a second all-NULL key is a duplicate, not a new row.
55
+ insert into t_null_pk values (null, 'second');
56
+ -- error: UNIQUE constraint failed
57
+
58
+ select count(*) as n from t_null_pk;
59
+ → [{"n":1}]
60
+
61
+ -- Non-NULL keys coexist with the NULL one and are addressable by value.
62
+ insert into t_null_pk values (1, 'one'), (2, 'two');
63
+
64
+ select x, val from t_null_pk order by x;
65
+ → [{"x":null,"val":"first"},{"x":1,"val":"one"},{"x":2,"val":"two"}]
66
+
67
+ select val from t_null_pk where x is null;
68
+ → [{"val":"first"}]
69
+
70
+ -- SQL comparison stays three-valued in key position: `= null` is UNKNOWN and matches
71
+ -- nothing, even though key EQUALITY (which decides duplicates above) is NULL-self-equal.
72
+ -- The two rules coexist; only `is null` reaches the row. This also pins the point-seek
73
+ -- arm that short-circuits a literal-NULL key equality to an empty result.
74
+ select val from t_null_pk where x = null;
75
+ → []
76
+
77
+ -- The same reason an equi-join never reaches a NULL-keyed row.
78
+ select p.val as pval from t_null_pk p join t_null_pk c on p.x = c.x where c.val = 'first';
79
+ → []
80
+
81
+ delete from t_null_pk where x is null;
82
+
83
+ select count(*) as n from t_null_pk;
84
+ → [{"n":2}]
85
+
86
+ drop table t_null_pk;
87
+
88
+ -- ===================================
89
+ -- 3. Same outcome via the session default rather than an explicit `null`.
90
+ -- ===================================
91
+
92
+ pragma default_column_nullability='nullable';
93
+
94
+ create table t_sess_pk (x integer, val text, primary key (x));
95
+
96
+ select name, "notnull", pk from table_info('t_sess_pk') where name = 'x';
97
+ → [{"name":"x","notnull":0,"pk":1}]
98
+
99
+ insert into t_sess_pk values (null, 'first');
100
+
101
+ select x, val from t_sess_pk;
102
+ → [{"x":null,"val":"first"}]
103
+
104
+ insert into t_sess_pk values (null, 'second');
105
+ -- error: UNIQUE constraint failed
106
+
107
+ drop table t_sess_pk;
108
+
109
+ -- A declared key and the synthesized all-columns key are now the same key: identical column
110
+ -- nullability for the same declaration, differing only in which columns the key covers.
111
+ create table t_declared (x integer, y integer, primary key (x, y));
112
+ create table t_synth (x integer, y integer);
113
+
114
+ select name, "notnull" from table_info('t_declared') order by cid;
115
+ → [{"name":"x","notnull":0},{"name":"y","notnull":0}]
116
+
117
+ select name, "notnull" from table_info('t_synth') order by cid;
118
+ → [{"name":"x","notnull":0},{"name":"y","notnull":0}]
119
+
120
+ drop table t_declared;
121
+ drop table t_synth;
122
+
123
+ pragma default_column_nullability='not_null';
124
+
125
+ -- ===================================
126
+ -- 4. Composite declared key with nullable members.
127
+ -- ===================================
128
+
129
+ create table t_comp (a integer null, b integer null, val text null, primary key (a, b));
130
+
131
+ insert into t_comp values (null, null, 'both null');
132
+ insert into t_comp values (null, 1, 'a null');
133
+ insert into t_comp values (1, null, 'b null');
134
+
135
+ select a, b, val from t_comp order by a, b;
136
+ → [{"a":null,"b":null,"val":"both null"},{"a":null,"b":1,"val":"a null"},{"a":1,"b":null,"val":"b null"}]
137
+
138
+ -- Each of those keys is distinct from the others but equal to itself.
139
+ insert into t_comp values (null, null, 'dup');
140
+ -- error: UNIQUE constraint failed
141
+
142
+ insert into t_comp values (null, 1, 'dup');
143
+ -- error: UNIQUE constraint failed
144
+
145
+ select count(*) as n from t_comp;
146
+ → [{"n":3}]
147
+
148
+ drop table t_comp;
149
+
150
+ -- ===================================
151
+ -- 5. Key equality and UNIQUE answer NULL differently — deliberately, and unchanged by the above.
152
+ -- Two rows with y = null are legal; two rows with x = null are not.
153
+ -- ===================================
154
+
155
+ create table t_vs_unique (x integer null primary key, y integer null unique);
156
+
157
+ insert into t_vs_unique values (1, null);
158
+ insert into t_vs_unique values (2, null);
159
+
160
+ -- UNIQUE is NULL-distinct: both rows stand.
161
+ select count(*) as n from t_vs_unique where y is null;
162
+ → [{"n":2}]
163
+
164
+ insert into t_vs_unique values (null, 1);
165
+ insert into t_vs_unique values (null, 2);
166
+ -- error: UNIQUE constraint failed
167
+
168
+ select count(*) as n from t_vs_unique;
169
+ → [{"n":3}]
170
+
171
+ drop table t_vs_unique;
172
+
173
+ -- ===================================
174
+ -- 6. Conflict resolution against a NULL-containing key resolves to the EXISTING row.
175
+ -- ===================================
176
+
177
+ create table t_conflict (x integer null primary key, val text null);
178
+
179
+ insert into t_conflict values (null, 'original');
180
+
181
+ insert or replace into t_conflict values (null, 'replaced');
182
+
183
+ select x, val from t_conflict;
184
+ → [{"x":null,"val":"replaced"}]
185
+
186
+ select count(*) as n from t_conflict;
187
+ → [{"n":1}]
188
+
189
+ insert or ignore into t_conflict values (null, 'ignored');
190
+
191
+ select x, val from t_conflict;
192
+ → [{"x":null,"val":"replaced"}]
193
+
194
+ insert into t_conflict values (null, 'upserted') on conflict do update set val = 'upserted';
195
+
196
+ select x, val from t_conflict;
197
+ → [{"x":null,"val":"upserted"}]
198
+
199
+ select count(*) as n from t_conflict;
200
+ → [{"n":1}]
201
+
202
+ drop table t_conflict;
203
+
204
+ -- ===================================
205
+ -- 7. UPDATE moving a key column to NULL and back.
206
+ -- ===================================
207
+
208
+ create table t_move (x integer null primary key, val text null);
209
+
210
+ insert into t_move values (1, 'a'), (2, 'b');
211
+
212
+ update t_move set x = null where x = 1;
213
+
214
+ select x, val from t_move order by x;
215
+ → [{"x":null,"val":"a"},{"x":2,"val":"b"}]
216
+
217
+ -- Addressable by its NEW key, and no longer by the old one.
218
+ select val from t_move where x is null;
219
+ → [{"val":"a"}]
220
+
221
+ select count(*) as n from t_move where x = 1;
222
+ → [{"n":0}]
223
+
224
+ -- Moving the second row onto the NULL key now collides with the first.
225
+ update t_move set x = null where x = 2;
226
+ -- error: UNIQUE constraint failed
227
+
228
+ select count(*) as n from t_move;
229
+ → [{"n":2}]
230
+
231
+ -- And back out of NULL.
232
+ update t_move set x = 3 where x is null;
233
+
234
+ select x, val from t_move order by x;
235
+ → [{"x":2,"val":"b"},{"x":3,"val":"a"}]
236
+
237
+ select count(*) as n from t_move where x is null;
238
+ → [{"n":0}]
239
+
240
+ drop table t_move;
241
+
242
+ -- ===================================
243
+ -- 8. Foreign keys: a parent key tuple containing NULL is unreferenceable (MATCH SIMPLE).
244
+ -- `references par` with no column list resolves to the parent's primary key.
245
+ -- ===================================
246
+
247
+ create table fk_par (id integer null primary key, label text null);
248
+ create table fk_child (cid integer primary key, parent_id integer null references fk_par on delete restrict);
249
+
250
+ insert into fk_par values (null, 'null-keyed'), (1, 'one');
251
+
252
+ -- A child row with a non-NULL FK value matches the non-NULL parent key.
253
+ insert into fk_child values (10, 1);
254
+
255
+ -- Nothing can point AT the NULL-keyed parent: `=` against NULL is never true, so a non-NULL
256
+ -- child value finds no parent...
257
+ insert into fk_child values (11, 99);
258
+ -- error: CHECK constraint failed: _fk_fk_child_parent_id
259
+
260
+ -- ...and a NULL child value is admitted unchecked (MATCH SIMPLE), which is not a reference to
261
+ -- the NULL-keyed parent row either.
262
+ insert into fk_child values (12, null);
263
+
264
+ select cid, parent_id from fk_child order by cid;
265
+ → [{"cid":10,"parent_id":1},{"cid":12,"parent_id":null}]
266
+
267
+ -- `on delete restrict` does not fire for a parent tuple containing NULL: nothing can reference it.
268
+ delete from fk_par where id is null;
269
+
270
+ select id, label from fk_par;
271
+ → [{"id":1,"label":"one"}]
272
+
273
+ -- ...while the genuinely referenced parent is still protected.
274
+ delete from fk_par where id = 1;
275
+ -- error: violates RESTRICT from 'fk_child'
276
+
277
+ drop table fk_child;
278
+ drop table fk_par;
279
+
280
+ -- Parent side, cascade: deleting a NULL-keyed parent propagates to nothing.
281
+ create table fk_par_c (id integer null primary key, label text null);
282
+ create table fk_child_c (cid integer primary key, parent_id integer null references fk_par_c on delete cascade);
283
+
284
+ insert into fk_par_c values (null, 'null-keyed'), (1, 'one');
285
+ insert into fk_child_c values (20, 1), (21, null);
286
+
287
+ delete from fk_par_c where id is null;
288
+
289
+ -- Neither child was touched: the NULL-FK child is not a reference, and the id=1 child's parent
290
+ -- is still there.
291
+ select cid, parent_id from fk_child_c order by cid;
292
+ → [{"cid":20,"parent_id":1},{"cid":21,"parent_id":null}]
293
+
294
+ delete from fk_par_c where id = 1;
295
+
296
+ -- Only the genuine reference cascaded.
297
+ select cid, parent_id from fk_child_c order by cid;
298
+ → [{"cid":21,"parent_id":null}]
299
+
300
+ drop table fk_child_c;
301
+ drop table fk_par_c;
302
+
303
+ -- ===================================
304
+ -- 9. ALTER TABLE ... ALTER COLUMN <key column> DROP NOT NULL is permitted and metadata-only.
305
+ -- ===================================
306
+
307
+ create table t_drop_nn (a integer, b integer null, primary key (a));
308
+
309
+ select name, "notnull", pk from table_info('t_drop_nn') where name = 'a';
310
+ → [{"name":"a","notnull":1,"pk":1}]
311
+
312
+ insert into t_drop_nn values (1, 10), (2, 20);
313
+
314
+ alter table t_drop_nn alter column a drop not null;
315
+
316
+ select name, "notnull", pk from table_info('t_drop_nn') where name = 'a';
317
+ → [{"name":"a","notnull":0,"pk":1}]
318
+
319
+ -- No row was rewritten: both existing rows survive unchanged and stay addressable by key.
320
+ select a, b from t_drop_nn order by a;
321
+ → [{"a":1,"b":10},{"a":2,"b":20}]
322
+
323
+ select b from t_drop_nn where a = 2;
324
+ → [{"b":20}]
325
+
326
+ -- The loosening took effect.
327
+ insert into t_drop_nn values (null, 30);
328
+
329
+ select a, b from t_drop_nn order by a;
330
+ → [{"a":null,"b":30},{"a":1,"b":10},{"a":2,"b":20}]
331
+
332
+ insert into t_drop_nn values (null, 40);
333
+ -- error: UNIQUE constraint failed
334
+
335
+ -- SET DATA TYPE on a key column is a DIFFERENT rule and is still refused.
336
+ alter table t_drop_nn alter column a set data type text;
337
+ -- error: Cannot SET DATA TYPE on PRIMARY KEY column
338
+
339
+ drop table t_drop_nn;
340
+
341
+ -- ===================================
342
+ -- 10. ALTER TABLE ... ALTER COLUMN <key column> SET NOT NULL — the tightening direction.
343
+ -- The collision semantics belong to 41.2.3; this only pins that a DECLARED key column
344
+ -- takes the same path a synthesized one does, so the two stay in lock-step.
345
+ -- ===================================
346
+
347
+ -- No visible NULL: metadata-only, moves no key.
348
+ create table t_set_nn (a integer null default 0, b integer null, primary key (a));
349
+ insert into t_set_nn values (1, 10), (2, 20);
350
+
351
+ alter table t_set_nn alter column a set not null;
352
+
353
+ select name, "notnull", pk from table_info('t_set_nn') where name = 'a';
354
+ → [{"name":"a","notnull":1,"pk":1}]
355
+
356
+ select a, b from t_set_nn order by a;
357
+ → [{"a":1,"b":10},{"a":2,"b":20}]
358
+
359
+ insert into t_set_nn values (null, 30);
360
+ -- error: NOT NULL constraint failed
361
+
362
+ drop table t_set_nn;
363
+
364
+ -- A visible NULL backfills from DEFAULT and physically re-keys the row.
365
+ create table t_set_nn2 (a integer null default 0, b integer null, primary key (a));
366
+ insert into t_set_nn2 values (null, 10), (1, 20);
367
+
368
+ alter table t_set_nn2 alter column a set not null;
369
+
370
+ select a, b from t_set_nn2 order by a;
371
+ → [{"a":0,"b":10},{"a":1,"b":20}]
372
+
373
+ -- The backfilled row is addressable by its NEW key.
374
+ select b from t_set_nn2 where a = 0;
375
+ → [{"b":10}]
376
+
377
+ drop table t_set_nn2;
378
+
379
+ -- Two rows converging on one key under the backfill: refused, nothing changes.
380
+ create table t_set_nn3 (a integer null default 0, b integer null, primary key (a));
381
+ insert into t_set_nn3 values (null, 10), (0, 20);
382
+
383
+ alter table t_set_nn3 alter column a set not null;
384
+ -- error: collides under the new key definition
385
+
386
+ select name, "notnull" from table_info('t_set_nn3') where name = 'a';
387
+ → [{"name":"a","notnull":0}]
388
+
389
+ select count(*) as n from t_set_nn3;
390
+ → [{"n":2}]
391
+
392
+ drop table t_set_nn3;
393
+
394
+ -- ===================================
395
+ -- 11. ALTER TABLE ... ALTER PRIMARY KEY onto a nullable column.
396
+ -- ===================================
397
+
398
+ create table t_repk (a integer primary key, b integer null);
399
+
400
+ insert into t_repk values (1, 10), (2, 20);
401
+
402
+ alter table t_repk alter primary key (b);
403
+
404
+ select name, "notnull", pk from table_info('t_repk') order by cid;
405
+ → [{"name":"a","notnull":1,"pk":0},{"name":"b","notnull":0,"pk":1}]
406
+
407
+ -- Existing rows are present and addressable under the new key.
408
+ select a, b from t_repk order by b;
409
+ → [{"a":1,"b":10},{"a":2,"b":20}]
410
+
411
+ select a from t_repk where b = 20;
412
+ → [{"a":2}]
413
+
414
+ -- The new key accepts NULL, once.
415
+ insert into t_repk values (3, null);
416
+
417
+ select a, b from t_repk order by b;
418
+ → [{"a":3,"b":null},{"a":1,"b":10},{"a":2,"b":20}]
419
+
420
+ insert into t_repk values (4, null);
421
+ -- error: UNIQUE constraint failed
422
+
423
+ drop table t_repk;
424
+
425
+ -- Re-keying ONTO a column that already holds a collision among its NULLs must be reported as a
426
+ -- duplicate key, not silently merged.
427
+ create table t_repk2 (a integer primary key, b integer null);
428
+
429
+ insert into t_repk2 values (1, null), (2, null);
430
+
431
+ alter table t_repk2 alter primary key (b);
432
+ -- error: UNIQUE constraint failed
433
+
434
+ -- Nothing moved: the old key and both rows are intact.
435
+ select name, pk from table_info('t_repk2') order by cid;
436
+ → [{"name":"a","pk":1},{"name":"b","pk":0}]
437
+
438
+ select count(*) as n from t_repk2;
439
+ → [{"n":2}]
440
+
441
+ drop table t_repk2;
442
+
443
+ -- ===================================
444
+ -- 12. A nullable declared key through an explicit transaction and a secondary-index read.
445
+ -- Meets the isolation-layer coverage in bug-isolation-null-pk-shadow-key from the other side:
446
+ -- there the key was synthesized, here it is declared.
447
+ -- ===================================
448
+
449
+ -- Table-level `unique` (not a standalone `create unique index`) so the file needs no
450
+ -- `-- requires-capability: standalone-index-ddl` and runs on every backend.
451
+ create table t_txn (x integer null primary key, tag integer null unique);
452
+
453
+ insert into t_txn values (null, 1);
454
+
455
+ begin;
456
+
457
+ insert into t_txn values (5, 2);
458
+
459
+ -- Read-your-own-writes across both the primary key and the secondary index.
460
+ select x, tag from t_txn order by x;
461
+ → [{"x":null,"tag":1},{"x":5,"tag":2}]
462
+
463
+ select x from t_txn where tag = 1;
464
+ → [{"x":null}]
465
+
466
+ -- The staged transaction still sees the committed NULL key as occupied.
467
+ insert into t_txn values (null, 3);
468
+ -- error: UNIQUE constraint failed
469
+
470
+ update t_txn set tag = 7 where x is null;
471
+
472
+ select x, tag from t_txn order by x;
473
+ → [{"x":null,"tag":7},{"x":5,"tag":2}]
474
+
475
+ commit;
476
+
477
+ select x, tag from t_txn order by x;
478
+ → [{"x":null,"tag":7},{"x":5,"tag":2}]
479
+
480
+ select x from t_txn where tag = 7;
481
+ → [{"x":null}]
482
+
483
+ -- Rollback restores the NULL-keyed row's committed value.
484
+ begin;
485
+ update t_txn set tag = 99 where x is null;
486
+ select tag from t_txn where x is null;
487
+ → [{"tag":99}]
488
+ rollback;
489
+
490
+ select tag from t_txn where x is null;
491
+ → [{"tag":7}]
492
+
493
+ drop table t_txn;
494
+
495
+ -- ===================================
496
+ -- 13. A NULL-keyed row is addressable through a writable JOIN VIEW. The multi-source
497
+ -- write substrate captures each side's key columns up front (`__vmupd_keys`) and
498
+ -- correlates every base op back to them — NULL-safely per nullable key column, with
499
+ -- an explicit match marker deciding the outer-join matched/null-extended partition
500
+ -- (never "captured key is all NULL", which a real partner keyed NULL satisfies too).
501
+ -- The full corpus lives in 93.4-view-mutation.sqllogic (§ NULL key columns through a
502
+ -- writable join view); this section pins the shapes from the nullable-key side.
503
+ -- ===================================
504
+ pragma foreign_keys = false;
505
+
506
+ -- Inner join: update, RETURNING, and the both-sides delete all reach the NULL-keyed side.
507
+ create table jp (pp integer null primary key, jk integer null, pv integer null);
508
+ create table jc (cc integer primary key, pr integer null, cv integer null);
509
+ create view jv as select c.cc as cc, c.cv as cv, p.pv as pv from jc c join jp p on p.jk = c.pr;
510
+ insert into jp values (null, 7, 10);
511
+ insert into jc values (1, 7, 100);
512
+
513
+ update jv set pv = 42 where cc = 1;
514
+ select pp, jk, pv from jp;
515
+ → [{"pp":null,"jk":7,"pv":42}]
516
+
517
+ update jv set cv = 55 where cc = 1 returning cc, cv, pv;
518
+ → [{"cc":1,"cv":55,"pv":42}]
519
+
520
+ delete from jv where cc = 1;
521
+ select count(*) as n from jp;
522
+ → [{"n":0}]
523
+ select count(*) as n from jc;
524
+ → [{"n":0}]
525
+
526
+ drop view jv; drop table jc; drop table jp;
527
+
528
+ -- Left join: a MATCHED partner keyed NULL updates in place; a row with truly no
529
+ -- partner still materializes one (the marker, not the NULL key, partitions).
530
+ create table ljp (pp integer null primary key
531
+ default (coalesce((select max(pp) from ljp), 0) + 1),
532
+ jk integer null, pv integer null);
533
+ create table ljc (cc integer primary key, pr integer null, cv integer null);
534
+ create view ljv as select c.cc as cc, c.cv as cv, p.pv as pv from ljc c left join ljp p on p.jk = c.pr;
535
+ insert into ljp (pp, jk, pv) values (null, 7, 10);
536
+ insert into ljc values (1, 7, 100);
537
+ insert into ljc values (2, 8, 200);
538
+
539
+ update ljv set pv = 99 where cc = 1;
540
+ update ljv set pv = 55 where cc = 2;
541
+ -- cc=1's NULL-keyed partner updated in place; cc=2 minted a new partner for jk=8.
542
+ select jk, pv from ljp order by jk;
543
+ → [{"jk":7,"pv":99},{"jk":8,"pv":55}]
544
+
545
+ update ljv set pv = 77 where cc = 1 returning cc, cv, pv;
546
+ → [{"cc":1,"cv":100,"pv":77}]
547
+ select count(*) as n from ljp;
548
+ → [{"n":2}]
549
+
550
+ delete from ljv where cc = 1;
551
+ select cc from ljv order by cc;
552
+ → [{"cc":2}]
553
+
554
+ drop view ljv; drop table ljc; drop table ljp;
555
+
556
+ -- Composite key holding NULL in only some members — both join shapes.
557
+ create table cjp (a integer null, b integer null, jk integer null, pv integer null, primary key (a, b));
558
+ create table cjc (cc integer primary key, pr integer null, cv integer null);
559
+ create view cjv as select c.cc as cc, c.cv as cv, p.pv as pv from cjc c join cjp p on p.jk = c.pr;
560
+ insert into cjp values (1, null, 7, 10);
561
+ insert into cjc values (1, 7, 100);
562
+
563
+ update cjv set pv = 42 where cc = 1;
564
+ select a, b, pv from cjp;
565
+ → [{"a":1,"b":null,"pv":42}]
566
+
567
+ delete from cjv where cc = 1 returning cc, cv, pv;
568
+ → [{"cc":1,"cv":100,"pv":42}]
569
+ select count(*) as n from cjp;
570
+ → [{"n":0}]
571
+
572
+ drop view cjv; drop table cjc;
573
+ create table cjc (cc integer primary key, pr integer null, cv integer null);
574
+ create view cjlv as select c.cc as cc, c.cv as cv, p.pv as pv from cjc c left join cjp p on p.jk = c.pr;
575
+ insert into cjp values (1, null, 7, 10);
576
+ insert into cjc values (1, 7, 100);
577
+
578
+ update cjlv set pv = 42 where cc = 1;
579
+ select a, b, pv from cjp;
580
+ → [{"a":1,"b":null,"pv":42}]
581
+ select count(*) as n from cjp;
582
+ → [{"n":1}]
583
+
584
+ update cjlv set pv = 43 where cc = 1 returning cc, cv, pv;
585
+ → [{"cc":1,"cv":100,"pv":43}]
586
+
587
+ drop view cjlv; drop table cjc; drop table cjp;