@quereus/quereus 4.20.1 → 4.20.3

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 (380) hide show
  1. package/README.md +2 -0
  2. package/dist/src/schema/schema-differ.d.ts.map +1 -1
  3. package/dist/src/schema/schema-differ.js +17 -69
  4. package/dist/src/schema/schema-differ.js.map +1 -1
  5. package/package.json +7 -4
  6. package/test/README.md +173 -0
  7. package/test/logic/01-basic.sqllogic +39 -0
  8. package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
  9. package/test/logic/01.2-strings.sqllogic +43 -0
  10. package/test/logic/01.5-insert-select.sqllogic +237 -0
  11. package/test/logic/01.6-update-extras.sqllogic +118 -0
  12. package/test/logic/01.7-update-from.sqllogic +67 -0
  13. package/test/logic/01.8-delete-extras.sqllogic +122 -0
  14. package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
  15. package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
  16. package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
  17. package/test/logic/01.9-query-expr-values.sqllogic +111 -0
  18. package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
  19. package/test/logic/02-filters.sqllogic +54 -0
  20. package/test/logic/02-smoke.sqllogic +62 -0
  21. package/test/logic/02.1-bind-parameters.sqllogic +223 -0
  22. package/test/logic/03-expressions.sqllogic +190 -0
  23. package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
  24. package/test/logic/03.4-defaults.sqllogic +554 -0
  25. package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
  26. package/test/logic/03.5-tvf.sqllogic +61 -0
  27. package/test/logic/03.6-type-system.sqllogic +544 -0
  28. package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
  29. package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
  30. package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
  31. package/test/logic/03.8-not-precedence.sqllogic +255 -0
  32. package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
  33. package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
  34. package/test/logic/04-order-by.sqllogic +38 -0
  35. package/test/logic/04-transactions.sqllogic +239 -0
  36. package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
  37. package/test/logic/05-vtab_memory.sqllogic +50 -0
  38. package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
  39. package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
  40. package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
  41. package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
  42. package/test/logic/06-builtin_functions.sqllogic +149 -0
  43. package/test/logic/06.1-string-functions.sqllogic +92 -0
  44. package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
  45. package/test/logic/06.2-math-functions.sqllogic +82 -0
  46. package/test/logic/06.3-schema.sqllogic +48 -0
  47. package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
  48. package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
  49. package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
  50. package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
  51. package/test/logic/06.3.4-view-info.sqllogic +378 -0
  52. package/test/logic/06.3.5-column-info.sqllogic +347 -0
  53. package/test/logic/06.3.6-schema-views.sqllogic +29 -0
  54. package/test/logic/06.4-schema-search-path.sqllogic +354 -0
  55. package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
  56. package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
  57. package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
  58. package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
  59. package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
  60. package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
  61. package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
  62. package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
  63. package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
  64. package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
  65. package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
  66. package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
  67. package/test/logic/06.7-json-extended.sqllogic +53 -0
  68. package/test/logic/06.8-json-path-operators.sqllogic +99 -0
  69. package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
  70. package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
  71. package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
  72. package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
  73. package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
  74. package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
  75. package/test/logic/07-aggregates.sqllogic +193 -0
  76. package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
  77. package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
  78. package/test/logic/07.3-group-by-extras.sqllogic +602 -0
  79. package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
  80. package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
  81. package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
  82. package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
  83. package/test/logic/07.5-window.sqllogic +1941 -0
  84. package/test/logic/07.5.1-window-named.sqllogic +13 -0
  85. package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
  86. package/test/logic/07.6-subqueries.sqllogic +78 -0
  87. package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
  88. package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
  89. package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
  90. package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
  91. package/test/logic/07.7.1-in-extras.sqllogic +158 -0
  92. package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
  93. package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
  94. package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
  95. package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
  96. package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
  97. package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
  98. package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
  99. package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
  100. package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
  101. package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
  102. package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
  103. package/test/logic/07.9-in-value-list.sqllogic +154 -0
  104. package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
  105. package/test/logic/08-views.sqllogic +64 -0
  106. package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
  107. package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
  108. package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
  109. package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
  110. package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
  111. package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
  112. package/test/logic/09-set_operations.sqllogic +244 -0
  113. package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
  114. package/test/logic/10-distinct_datatypes.sqllogic +127 -0
  115. package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
  116. package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
  117. package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
  118. package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
  119. package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
  120. package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
  121. package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
  122. package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
  123. package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
  124. package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
  125. package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
  126. package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
  127. package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
  128. package/test/logic/10.2-column-features.sqllogic +365 -0
  129. package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
  130. package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
  131. package/test/logic/10.3-function-features.sqllogic +247 -0
  132. package/test/logic/10.4-schema-scale.sqllogic +168 -0
  133. package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
  134. package/test/logic/10.5-indexes.sqllogic +164 -0
  135. package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
  136. package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
  137. package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
  138. package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
  139. package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
  140. package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
  141. package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
  142. package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
  143. package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
  144. package/test/logic/100.1-where-extras.sqllogic +163 -0
  145. package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
  146. package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
  147. package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
  148. package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
  149. package/test/logic/102-unique-constraints.sqllogic +145 -0
  150. package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
  151. package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
  152. package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
  153. package/test/logic/102.2-unique-collation.sqllogic +181 -0
  154. package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
  155. package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
  156. package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
  157. package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
  158. package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
  159. package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
  160. package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
  161. package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
  162. package/test/logic/108-cardinality-estimation.sqllogic +146 -0
  163. package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
  164. package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
  165. package/test/logic/11-joins.sqllogic +86 -0
  166. package/test/logic/11.1-join-using.sqllogic +267 -0
  167. package/test/logic/11.2-comma-join.sqllogic +35 -0
  168. package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
  169. package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
  170. package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
  171. package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
  172. package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
  173. package/test/logic/12-empty-primary-key.sqllogic +124 -0
  174. package/test/logic/12-join_padding_order.sqllogic +58 -0
  175. package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
  176. package/test/logic/13-cte.sqllogic +137 -0
  177. package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
  178. package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
  179. package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
  180. package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
  181. package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
  182. package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
  183. package/test/logic/13.4-cte-extras.sqllogic +98 -0
  184. package/test/logic/13.5-cte-join-order.sqllogic +166 -0
  185. package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
  186. package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
  187. package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
  188. package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
  189. package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
  190. package/test/logic/14-utilities.sqllogic +168 -0
  191. package/test/logic/15-timespan.sqllogic +279 -0
  192. package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
  193. package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
  194. package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
  195. package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
  196. package/test/logic/16-epoch.sqllogic +187 -0
  197. package/test/logic/17-weekday-modifier.sqllogic +78 -0
  198. package/test/logic/18-json-string-escapes.sqllogic +86 -0
  199. package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
  200. package/test/logic/20-empty-single-row.sqllogic +261 -0
  201. package/test/logic/21-null-edge-cases.sqllogic +227 -0
  202. package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
  203. package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
  204. package/test/logic/21.2-between-edges.sqllogic +157 -0
  205. package/test/logic/22-boundary-values.sqllogic +175 -0
  206. package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
  207. package/test/logic/24-builtin-branches.sqllogic +611 -0
  208. package/test/logic/24.1-substr-extras.sqllogic +75 -0
  209. package/test/logic/24.2-random-extras.sqllogic +39 -0
  210. package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
  211. package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
  212. package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
  213. package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
  214. package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
  215. package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
  216. package/test/logic/26-join-edge-cases.sqllogic +333 -0
  217. package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
  218. package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
  219. package/test/logic/26.3-join-on-constants.sqllogic +61 -0
  220. package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
  221. package/test/logic/27-window-edge-cases.sqllogic +206 -0
  222. package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
  223. package/test/logic/27.2-window-exclude.sqllogic +13 -0
  224. package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
  225. package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
  226. package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
  227. package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
  228. package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
  229. package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
  230. package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
  231. package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
  232. package/test/logic/40-constraints.sqllogic +418 -0
  233. package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
  234. package/test/logic/40.2-check-extras.sqllogic +683 -0
  235. package/test/logic/41-alter-table.sqllogic +191 -0
  236. package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
  237. package/test/logic/41-fk-cross-schema.sqllogic +155 -0
  238. package/test/logic/41-fk-extended-targets.sqllogic +173 -0
  239. package/test/logic/41-foreign-keys.sqllogic +1001 -0
  240. package/test/logic/41-generated-column-errors.sqllogic +225 -0
  241. package/test/logic/41-generated-column-extras.sqllogic +598 -0
  242. package/test/logic/41-generated-column-scope.sqllogic +329 -0
  243. package/test/logic/41-generated-columns.sqllogic +361 -0
  244. package/test/logic/41.1-alter-pk.sqllogic +230 -0
  245. package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
  246. package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
  247. package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
  248. package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
  249. package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
  250. package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
  251. package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
  252. package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
  253. package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
  254. package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
  255. package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
  256. package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
  257. package/test/logic/41.2-alter-column.sqllogic +382 -0
  258. package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
  259. package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
  260. package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
  261. package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
  262. package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
  263. package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
  264. package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
  265. package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
  266. package/test/logic/41.5-alter-misc.sqllogic +48 -0
  267. package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
  268. package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
  269. package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
  270. package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
  271. package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
  272. package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
  273. package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
  274. package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
  275. package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
  276. package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
  277. package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
  278. package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
  279. package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
  280. package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
  281. package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
  282. package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
  283. package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
  284. package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
  285. package/test/logic/42-committed-snapshot.sqllogic +254 -0
  286. package/test/logic/42-returning.sqllogic +159 -0
  287. package/test/logic/42.1-returning-extras.sqllogic +232 -0
  288. package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
  289. package/test/logic/43-default-nullability.sqllogic +131 -0
  290. package/test/logic/43-transition-constraints.sqllogic +341 -0
  291. package/test/logic/43.1-default-collation.sqllogic +140 -0
  292. package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
  293. package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
  294. package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
  295. package/test/logic/44-determinism-validation.sqllogic +164 -0
  296. package/test/logic/44-orthogonality.sqllogic +146 -0
  297. package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
  298. package/test/logic/45-udf-determinism.sqllogic +39 -0
  299. package/test/logic/46-mutation-context.sqllogic +595 -0
  300. package/test/logic/47-upsert.sqllogic +255 -0
  301. package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
  302. package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
  303. package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
  304. package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
  305. package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
  306. package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
  307. package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
  308. package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
  309. package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
  310. package/test/logic/49-reference-graph.sqllogic +84 -0
  311. package/test/logic/50-declarative-schema.sqllogic +2550 -0
  312. package/test/logic/50-metadata-tags.sqllogic +1033 -0
  313. package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
  314. package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
  315. package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
  316. package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +210 -0
  317. package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
  318. package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
  319. package/test/logic/51-lens-foundation.sqllogic +147 -0
  320. package/test/logic/51-materialized-views.sqllogic +376 -0
  321. package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
  322. package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
  323. package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
  324. package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
  325. package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
  326. package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
  327. package/test/logic/52-lens-overrides.sqllogic +566 -0
  328. package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
  329. package/test/logic/53-reserved-tags.sqllogic +252 -0
  330. package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
  331. package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
  332. package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
  333. package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
  334. package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
  335. package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
  336. package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
  337. package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
  338. package/test/logic/55-lens-prover.sqllogic +202 -0
  339. package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
  340. package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
  341. package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
  342. package/test/logic/81-quickpick.sqllogic +24 -0
  343. package/test/logic/82-bloom-join.sqllogic +185 -0
  344. package/test/logic/83-merge-join.sqllogic +280 -0
  345. package/test/logic/84-asof-scan.sqllogic +238 -0
  346. package/test/logic/84-key-cardinality.sqllogic +50 -0
  347. package/test/logic/85-relational-const-folding.sqllogic +51 -0
  348. package/test/logic/86-scalar-cse.sqllogic +42 -0
  349. package/test/logic/90-error_paths.sqllogic +114 -0
  350. package/test/logic/90.1-parse-errors.sqllogic +77 -0
  351. package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
  352. package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
  353. package/test/logic/90.3-expression-errors.sqllogic +43 -0
  354. package/test/logic/90.4-dml-errors.sqllogic +47 -0
  355. package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
  356. package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
  357. package/test/logic/90.6-select-error-paths.sqllogic +57 -0
  358. package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
  359. package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
  360. package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
  361. package/test/logic/93.1-view-error-paths.sqllogic +74 -0
  362. package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
  363. package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
  364. package/test/logic/93.4-view-mutation.sqllogic +4881 -0
  365. package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
  366. package/test/logic/93.5-authored-inverse.sqllogic +415 -0
  367. package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
  368. package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
  369. package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
  370. package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
  371. package/test/logic/95-assertions.sqllogic +1417 -0
  372. package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
  373. package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
  374. package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
  375. package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
  376. package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
  377. package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
  378. package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
  379. package/test/logic/drop-unique-index.sqllogic +88 -0
  380. package/test/logic/pushdown-test.sqllogic +36 -0
@@ -0,0 +1,59 @@
1
+ -- ON CONFLICT (cols) DO UPDATE / DO NOTHING must match an AFFINITY-coerced
2
+ -- conflict: a proposed value of a different storage class that the target
3
+ -- column's affinity coerces onto the stored key (e.g. TEXT '1' inserted into an
4
+ -- INTEGER key holding 1). matchUpsertClause applies the column's affinity to the
5
+ -- proposed value before comparing, so the conflict routes to the UPSERT arm
6
+ -- instead of aborting. Ticket bug-upsert-conflict-target-collation-match.
7
+ --
8
+ -- Runs in BOTH memory and store mode. The isolation overlay
9
+ -- (createIsolatedStoreModule, the store-mode harness) coerces the proposed row
10
+ -- to the declared column types before probing for a conflict, same as the
11
+ -- plain store and in-memory engine (bug-store-isolation-upsert-affinity-coerced-pk),
12
+ -- so a cross-storage-class proposed PK value (e.g. TEXT '1' into an INTEGER key
13
+ -- holding 1) matches the stored key instead of shadowing it with a fresh row.
14
+ -- The collation-variant (same-storage-class) corners of this fix run in BOTH
15
+ -- modes in the sibling file 47.3-upsert-conflict-target-collation.sqllogic.
16
+
17
+ -- ===================================
18
+ -- 1. Affinity coercion — proposed TEXT '1' into an INTEGER PK holding 1.
19
+ -- The proposed value reaches the match pre-affinity-coercion; applying the
20
+ -- column's INTEGER affinity turns '1' into 1, matching the stored key, so the
21
+ -- existing row's DO UPDATE runs (n = 100 + 1).
22
+ -- ===================================
23
+
24
+ create table aff_pk (id integer primary key, n integer);
25
+ insert into aff_pk values (1, 100);
26
+
27
+ insert into aff_pk values ('1', 0) on conflict (id) do update set n = n + 1;
28
+ select id, n, typeof(id) as t from aff_pk order by id;
29
+ → [{"id":1,"n":101,"t":"integer"}]
30
+
31
+ drop table aff_pk;
32
+
33
+ -- ===================================
34
+ -- 2. Affinity coercion, DO NOTHING arm — the coerced conflict is SKIPPED, not
35
+ -- aborted, and the existing row is left intact.
36
+ -- ===================================
37
+
38
+ create table aff_pk2 (id integer primary key, n integer);
39
+ insert into aff_pk2 values (1, 100);
40
+
41
+ insert into aff_pk2 values ('1', 999) on conflict (id) do nothing;
42
+ select id, n from aff_pk2 order by id;
43
+ → [{"id":1,"n":100}]
44
+
45
+ drop table aff_pk2;
46
+
47
+ -- ===================================
48
+ -- 3. Affinity coercion on a UNIQUE constraint (not the PK): TEXT '7' collides
49
+ -- with a stored INTEGER 7 under the column's INTEGER affinity.
50
+ -- ===================================
51
+
52
+ create table aff_uc (id integer primary key, code integer unique, hits integer);
53
+ insert into aff_uc values (1, 7, 1);
54
+
55
+ insert into aff_uc values (2, '7', 0) on conflict (code) do update set hits = hits + 1;
56
+ select id, code, hits from aff_uc order by id;
57
+ → [{"id":1,"code":7,"hits":2}]
58
+
59
+ drop table aff_uc;
@@ -0,0 +1,440 @@
1
+ -- An INSERT's `on conflict ... do update` arm composes the row it writes inside
2
+ -- the DML executor and hands it straight to the storage layer, so that row never
3
+ -- passes through the statement's ConstraintCheckNode (which is INSERT-shaped and
4
+ -- only ever sees the PROPOSED insert row). Before the fix the arm could therefore
5
+ -- store a row that broke a CHECK, a NOT NULL, or a foreign key — one the equivalent
6
+ -- plain `UPDATE` refuses.
7
+ --
8
+ -- The contract this file pins: the DO UPDATE arm validates the composed row under
9
+ -- UPDATE-scoped constraints, identically to the equivalent plain `UPDATE`, and the
10
+ -- per-constraint `on conflict <action>` defaults apply to a violation raised there.
11
+ -- Every violating case asserts the error AND then selects to prove nothing was
12
+ -- written. Ticket bug-upsert-do-update-skips-constraint-checks.
13
+ --
14
+ -- Not a case here: `insert or ignore ... on conflict ... do update`. The parser
15
+ -- rejects that combination outright ("Cannot use both 'INSERT OR ...' and
16
+ -- 'ON CONFLICT' in the same statement", covered in 47-upsert.sqllogic). The
17
+ -- per-constraint `on conflict <action>` defaults below carry that semantics.
18
+
19
+ -- ===================================
20
+ -- 1. Row-level CHECK: the composed row is refused, and the message matches what
21
+ -- the plain UPDATE of the same row produces.
22
+ -- ===================================
23
+
24
+ create table ck_row (a integer primary key, b integer, check (b < 10));
25
+ insert into ck_row values (1, 1);
26
+
27
+ insert into ck_row values (1, 2) on conflict (a) do update set b = 99;
28
+ -- error: CHECK constraint failed: _check_0 (b < 10)
29
+
30
+ -- nothing was written — not the proposed row, not the composed one.
31
+ select a, b from ck_row;
32
+ → [{"a":1,"b":1}]
33
+
34
+ -- the plain UPDATE spelling of the same write, for message parity.
35
+ update ck_row set b = 99 where a = 1;
36
+ -- error: CHECK constraint failed: _check_0 (b < 10)
37
+
38
+ -- a satisfying DO UPDATE still succeeds — no over-rejection.
39
+ insert into ck_row values (1, 2) on conflict (a) do update set b = 5;
40
+ select a, b from ck_row;
41
+ → [{"a":1,"b":5}]
42
+
43
+ drop table ck_row;
44
+
45
+ -- ===================================
46
+ -- 2. Column-level CHECK — attributed to the column's generated constraint name,
47
+ -- same as the plain UPDATE.
48
+ -- ===================================
49
+
50
+ create table ck_col (a integer primary key, b integer check (b < 10));
51
+ insert into ck_col values (1, 1);
52
+
53
+ insert into ck_col values (1, 2) on conflict (a) do update set b = 99;
54
+ -- error: CHECK constraint failed: _check_b (b < 10)
55
+
56
+ select a, b from ck_col;
57
+ → [{"a":1,"b":1}]
58
+
59
+ update ck_col set b = 99 where a = 1;
60
+ -- error: CHECK constraint failed: _check_b (b < 10)
61
+
62
+ drop table ck_col;
63
+
64
+ -- ===================================
65
+ -- 3. NOT NULL on the composed row.
66
+ -- ===================================
67
+
68
+ create table nn_t (a integer primary key, b integer not null);
69
+ insert into nn_t values (1, 1);
70
+
71
+ insert into nn_t values (1, 2) on conflict (a) do update set b = null;
72
+ -- error: NOT NULL constraint failed: nn_t.b
73
+
74
+ select a, b from nn_t;
75
+ → [{"a":1,"b":1}]
76
+
77
+ update nn_t set b = null where a = 1;
78
+ -- error: NOT NULL constraint failed: nn_t.b
79
+
80
+ drop table nn_t;
81
+
82
+ -- ===================================
83
+ -- 4. A clause WHERE that skips the row short-circuits before any validation: no
84
+ -- error is raised for the (violating) row it would have composed, and nothing
85
+ -- is written.
86
+ -- ===================================
87
+
88
+ create table wh_t (a integer primary key, b integer, check (b < 10));
89
+ insert into wh_t values (1, 1);
90
+
91
+ insert into wh_t values (1, 2) on conflict (a) do update set b = 99 where false;
92
+ select a, b from wh_t;
93
+ → [{"a":1,"b":1}]
94
+
95
+ drop table wh_t;
96
+
97
+ -- ===================================
98
+ -- 5. DO NOTHING writes nothing and gains no validation.
99
+ -- ===================================
100
+
101
+ create table dn_t (a integer primary key, b integer, check (b < 10));
102
+ insert into dn_t values (1, 1);
103
+
104
+ insert into dn_t values (1, 2) on conflict (a) do nothing;
105
+ select a, b from dn_t;
106
+ → [{"a":1,"b":1}]
107
+
108
+ drop table dn_t;
109
+
110
+ -- ===================================
111
+ -- 6. Op-scoped constraints are filtered by the UPDATE mask, exactly as they are
112
+ -- for a plain UPDATE: an `on insert`-only CHECK must NOT fire on this arm, an
113
+ -- `on update`-only CHECK must.
114
+ -- ===================================
115
+
116
+ create table op_ins (a integer primary key, b integer, constraint only_ins check on insert (b < 10));
117
+ insert into op_ins values (1, 1);
118
+
119
+ -- the composed value 99 breaks the predicate, but the constraint is INSERT-scoped
120
+ -- so the DO UPDATE arm does not enforce it.
121
+ insert into op_ins values (1, 2) on conflict (a) do update set b = 99;
122
+ select a, b from op_ins;
123
+ → [{"a":1,"b":99}]
124
+
125
+ drop table op_ins;
126
+
127
+ create table op_upd (a integer primary key, b integer, constraint only_upd check on update (b < 10));
128
+ insert into op_upd values (1, 1);
129
+
130
+ -- proposed row (b = 20) sails past the INSERT-shaped pass (the constraint is
131
+ -- UPDATE-scoped); the composed row (b = 99) is caught by the arm.
132
+ insert into op_upd values (1, 20) on conflict (a) do update set b = 99;
133
+ -- error: CHECK constraint failed: only_upd (b < 10)
134
+
135
+ select a, b from op_upd;
136
+ → [{"a":1,"b":1}]
137
+
138
+ drop table op_upd;
139
+
140
+ -- ===================================
141
+ -- 7. A transition CHECK reading `old.<col>` sees the CONFLICTING STORED ROW as
142
+ -- OLD — not the all-NULL OLD an INSERT would present.
143
+ -- ===================================
144
+
145
+ create table tr_t (a integer primary key, b integer, constraint monotonic check on update (b >= old.b));
146
+ insert into tr_t values (1, 5);
147
+
148
+ insert into tr_t values (1, 2) on conflict (a) do update set b = 1;
149
+ -- error: CHECK constraint failed: monotonic (b >= old.b)
150
+
151
+ select a, b from tr_t;
152
+ → [{"a":1,"b":5}]
153
+
154
+ -- a non-decreasing composed value passes, which proves OLD really bound to the
155
+ -- stored 5 rather than to NULL (a NULL OLD would make both directions pass).
156
+ insert into tr_t values (1, 2) on conflict (a) do update set b = 9;
157
+ select a, b from tr_t;
158
+ → [{"a":1,"b":9}]
159
+
160
+ drop table tr_t;
161
+
162
+ -- ===================================
163
+ -- 8. Generated columns: the phase-2 recompute runs BEFORE validation, so a
164
+ -- recomputed value is what the CHECK / NOT NULL sees.
165
+ -- ===================================
166
+
167
+ create table gen_ck (
168
+ a integer primary key,
169
+ x integer,
170
+ y integer generated always as (x * 10) stored,
171
+ check (y < 20)
172
+ );
173
+ insert into gen_ck (a, x) values (1, 1);
174
+
175
+ insert into gen_ck (a, x) values (1, 5) on conflict (a) do update set x = 10;
176
+ -- error: CHECK constraint failed: _check_0 (y < 20)
177
+
178
+ select a, x, y from gen_ck;
179
+ → [{"a":1,"x":1,"y":10}]
180
+
181
+ drop table gen_ck;
182
+
183
+ create table gen_nn (
184
+ a integer primary key,
185
+ x integer,
186
+ y integer not null generated always as (case when x > 5 then null else x end) stored
187
+ );
188
+ insert into gen_nn (a, x) values (1, 1);
189
+
190
+ insert into gen_nn (a, x) values (1, 2) on conflict (a) do update set x = 9;
191
+ -- error: NOT NULL constraint failed: gen_nn.y
192
+
193
+ select a, x, y from gen_nn;
194
+ → [{"a":1,"x":1,"y":1}]
195
+
196
+ drop table gen_nn;
197
+
198
+ -- ===================================
199
+ -- 9. Per-constraint conflict defaults compose with the arm.
200
+ -- `check (...) on conflict ignore` → the row is skipped silently: no error,
201
+ -- nothing written.
202
+ -- ===================================
203
+
204
+ create table pc_ign (a integer primary key, b integer check (b < 10) on conflict ignore);
205
+ insert into pc_ign values (1, 1);
206
+
207
+ insert into pc_ign values (1, 2) on conflict (a) do update set b = 99;
208
+ select a, b from pc_ign;
209
+ → [{"a":1,"b":1}]
210
+
211
+ drop table pc_ign;
212
+
213
+ -- `not null on conflict replace default <expr>` → the DEFAULT is substituted into
214
+ -- the composed row, and that substituted row is what gets stored.
215
+ create table pc_rep (a integer primary key, b integer not null on conflict replace default 7);
216
+ insert into pc_rep values (1, 1);
217
+
218
+ insert into pc_rep values (1, 2) on conflict (a) do update set b = null;
219
+ select a, b from pc_rep;
220
+ → [{"a":1,"b":7}]
221
+
222
+ drop table pc_rep;
223
+
224
+ -- ===================================
225
+ -- 10. Multi-row: row 1 updates cleanly, row 2 violates. Under the default ABORT
226
+ -- the WHOLE statement rolls back — row 1's clean update is undone too.
227
+ -- ===================================
228
+
229
+ create table mr_t (id integer primary key, a integer, check (a < 10));
230
+ insert into mr_t values (1, 1), (2, 2);
231
+
232
+ insert into mr_t values (1, 0), (2, 0)
233
+ on conflict (id) do update set a = case when id = 1 then 3 else 99 end;
234
+ -- error: CHECK constraint failed: _check_0 (a < 10)
235
+
236
+ select id, a from mr_t order by id;
237
+ → [{"id":1,"a":1},{"id":2,"a":2}]
238
+
239
+ drop table mr_t;
240
+
241
+ -- ===================================
242
+ -- 11. Multi-clause: both arms of one statement validate. The clause that matches
243
+ -- is chosen by conflict target; whichever composes the row, the same
244
+ -- UPDATE-shaped check set runs against it.
245
+ -- ===================================
246
+
247
+ create table mc_t (a integer primary key, e text unique, b integer, check (b < 10));
248
+ insert into mc_t values (1, 'x', 1);
249
+
250
+ -- conflicts on the PK → first clause composes b = 99.
251
+ insert into mc_t values (1, 'y', 1)
252
+ on conflict (a) do update set b = 99
253
+ on conflict (e) do update set b = 5;
254
+ -- error: CHECK constraint failed: _check_0 (b < 10)
255
+
256
+ select a, e, b from mc_t;
257
+ → [{"a":1,"e":"x","b":1}]
258
+
259
+ -- conflicts on the UNIQUE column → second clause composes b = 98.
260
+ insert into mc_t values (2, 'x', 1)
261
+ on conflict (a) do update set b = 5
262
+ on conflict (e) do update set b = 98;
263
+ -- error: CHECK constraint failed: _check_0 (b < 10)
264
+
265
+ select a, e, b from mc_t;
266
+ → [{"a":1,"e":"x","b":1}]
267
+
268
+ drop table mc_t;
269
+
270
+ -- ===================================
271
+ -- 12. Child-side foreign key: the composed row must still reference a live parent.
272
+ -- ===================================
273
+
274
+ pragma foreign_keys = true;
275
+
276
+ create table fk_par (p integer primary key, n integer);
277
+ create table fk_chi (c integer primary key, p integer references fk_par(p));
278
+ insert into fk_par values (1, 0);
279
+ insert into fk_chi values (1, 1);
280
+
281
+ insert into fk_chi values (1, 1) on conflict (c) do update set p = 99;
282
+ -- error: CHECK constraint failed: _fk_fk_chi_p
283
+
284
+ select c, p from fk_chi;
285
+ → [{"c":1,"p":1}]
286
+
287
+ update fk_chi set p = 99 where c = 1;
288
+ -- error: CHECK constraint failed: _fk_fk_chi_p
289
+
290
+ -- a composed value that DOES reference a live parent is accepted.
291
+ insert into fk_par values (2, 0);
292
+ insert into fk_chi values (1, 1) on conflict (c) do update set p = 2;
293
+ select c, p from fk_chi;
294
+ → [{"c":1,"p":2}]
295
+
296
+ drop table fk_chi;
297
+ drop table fk_par;
298
+
299
+ -- ===================================
300
+ -- 13. Parent-side `on update restrict`: a DO UPDATE that changes a referenced
301
+ -- column while a child still points at the old value is refused, with the SAME
302
+ -- message the plain UPDATE of that parent row produces.
303
+ --
304
+ -- `rs_par` clears the batchability gate (one inbound FK, RESTRICT, not
305
+ -- self-referencing), so a plain UPDATE skips the plan-time `not exists` probe and
306
+ -- reports through the RESTRICT scan. The arm is gated the same way, and its own
307
+ -- per-row `assertTransitiveRestrictsForParentMutation` pre-walk raises the same
308
+ -- error. Section 13b covers the other side of that gate.
309
+ -- ===================================
310
+
311
+ create table rs_par (p integer primary key, n integer);
312
+ create table rs_chi (c integer primary key, p integer references rs_par(p) on update restrict);
313
+ insert into rs_par values (1, 0);
314
+ insert into rs_chi values (1, 1);
315
+
316
+ insert into rs_par values (1, 5) on conflict (p) do update set p = 2;
317
+ -- error: FOREIGN KEY constraint failed: UPDATE on 'rs_par' violates RESTRICT from 'rs_chi'
318
+
319
+ -- neither parent nor child moved: no dangling child was left behind.
320
+ select p, n from rs_par;
321
+ → [{"p":1,"n":0}]
322
+ select c, p from rs_chi;
323
+ → [{"c":1,"p":1}]
324
+
325
+ -- the plain UPDATE spelling reports identically.
326
+ update rs_par set p = 2 where p = 1;
327
+ -- error: FOREIGN KEY constraint failed: UPDATE on 'rs_par' violates RESTRICT from 'rs_chi'
328
+
329
+ -- changing a NON-referenced column through the same arm is fine.
330
+ insert into rs_par values (1, 5) on conflict (p) do update set n = 5;
331
+ select p, n from rs_par;
332
+ → [{"p":1,"n":5}]
333
+
334
+ drop table rs_chi;
335
+ drop table rs_par;
336
+
337
+ -- ===================================
338
+ -- 13b. The non-batchable side of the same gate: a parent with a mix of RESTRICT and
339
+ -- CASCADE inbound FKs. A plain UPDATE keeps its plan-time `not exists` probe and
340
+ -- reports through it; the DO UPDATE arm must do the same, so the two spellings
341
+ -- stay in step on BOTH sides of the gate.
342
+ -- ===================================
343
+
344
+ create table mx_par (p integer primary key, n integer);
345
+ create table mx_res (c integer primary key, p integer references mx_par(p) on update restrict);
346
+ create table mx_cas (c integer primary key, p integer references mx_par(p) on update cascade);
347
+ insert into mx_par values (1, 0);
348
+ insert into mx_res values (1, 1);
349
+ insert into mx_cas values (1, 1);
350
+
351
+ insert into mx_par values (1, 5) on conflict (p) do update set p = 2;
352
+ -- error: CHECK constraint failed: _fk_mx_res_p
353
+
354
+ select p, n from mx_par;
355
+ → [{"p":1,"n":0}]
356
+ select c, p from mx_res;
357
+ → [{"c":1,"p":1}]
358
+
359
+ update mx_par set p = 2 where p = 1;
360
+ -- error: CHECK constraint failed: _fk_mx_res_p
361
+
362
+ drop table mx_cas;
363
+ drop table mx_res;
364
+ drop table mx_par;
365
+
366
+ -- ===================================
367
+ -- 14. Parent-side `on update cascade` still cascades through the DO UPDATE arm —
368
+ -- regression guard; FK ACTIONS already fired before this fix, only the
369
+ -- validation half was missing.
370
+ -- ===================================
371
+
372
+ create table cs_par (p integer primary key, n integer);
373
+ create table cs_chi (c integer primary key, p integer references cs_par(p) on update cascade);
374
+ insert into cs_par values (1, 0);
375
+ insert into cs_chi values (1, 1);
376
+
377
+ insert into cs_par values (1, 5) on conflict (p) do update set p = 2;
378
+ select p, n from cs_par;
379
+ → [{"p":2,"n":0}]
380
+ select c, p from cs_chi;
381
+ → [{"c":1,"p":2}]
382
+
383
+ drop table cs_chi;
384
+ drop table cs_par;
385
+
386
+ pragma foreign_keys = false;
387
+
388
+ -- ===================================
389
+ -- 15. A CHECK carrying a subquery is auto-deferred, so the arm's check on the
390
+ -- COMPOSED row is queued and evaluated at COMMIT — matching the plain UPDATE
391
+ -- of the same row exactly. The proposed row here is legal (a = 5 < 10), so the
392
+ -- failure can only come from the composed row (a = 99).
393
+ -- ===================================
394
+
395
+ create table df_t (id integer primary key, a integer, check (a < (select 10)));
396
+ insert into df_t values (1, 1);
397
+
398
+ begin;
399
+ insert into df_t values (1, 5) on conflict (id) do update set a = 99;
400
+ commit;
401
+ -- error: CHECK constraint failed: _check_0 (a < (select 10))
402
+ rollback;
403
+
404
+ select id, a from df_t;
405
+ → [{"id":1,"a":1}]
406
+
407
+ -- the plain UPDATE twin defers and fails at the same boundary with the same message.
408
+ begin;
409
+ update df_t set a = 99 where id = 1;
410
+ commit;
411
+ -- error: CHECK constraint failed: _check_0 (a < (select 10))
412
+ rollback;
413
+
414
+ select id, a from df_t;
415
+ → [{"id":1,"a":1}]
416
+
417
+ drop table df_t;
418
+
419
+ -- ===================================
420
+ -- 16. Mutation-context variables resolve inside the arm's checks: an UPDATE-scoped
421
+ -- CHECK referencing a context variable binds the value the executor evaluated
422
+ -- for this statement.
423
+ -- ===================================
424
+
425
+ create table cx_t (a integer primary key, b integer, constraint under_who check on update (b < who))
426
+ with context (who integer);
427
+ insert into cx_t values (1, 1) with context who = 100;
428
+
429
+ insert into cx_t values (1, 2) on conflict (a) do update set b = 99 with context who = 10;
430
+ -- error: CHECK constraint failed: under_who (b < who)
431
+
432
+ select a, b from cx_t;
433
+ → [{"a":1,"b":1}]
434
+
435
+ -- same statement, a context value the composed row satisfies.
436
+ insert into cx_t values (1, 2) on conflict (a) do update set b = 99 with context who = 1000;
437
+ select a, b from cx_t;
438
+ → [{"a":1,"b":99}]
439
+
440
+ drop table cx_t;
@@ -0,0 +1,100 @@
1
+ -- The `on conflict ... do update` arm is also reached by writes nobody spelled as an
2
+ -- UPSERT. An UPDATE through a logical (lens) table whose columns are split across
3
+ -- decomposition members lowers an optional member's anchor-resolvable assignment to a
4
+ -- synthesized `insert into <member> (...) select ... on conflict (<key>) do update set
5
+ -- <col> = excluded.<col>` (planner/mutation/decomposition.ts,
6
+ -- buildOptionalMemberInsertSelect with action 'update'). Rows whose member tuple already
7
+ -- exists take the DO UPDATE arm, so the arm's validation has to hold there too.
8
+ --
9
+ -- Companion to 47.5, which pins the user-spelled arm. Ticket
10
+ -- bug-upsert-do-update-skips-constraint-checks.
11
+ --
12
+ -- The member CHECK is UPDATE-scoped on purpose: an unscoped one would already be caught
13
+ -- by the INSERT-shaped pass over the proposed row, so only an `on update` CHECK proves
14
+ -- the ARM is what refused the write.
15
+
16
+ -- ===================================
17
+ -- Basis: anchor Car_core + optional Car_perf, sharing logical key `id`, advertised
18
+ -- through quereus.lens.decomp.* tags (same construction as 51-lens-foundation § 4).
19
+ -- ===================================
20
+
21
+ create table Car_core (id integer primary key, make text) with tags (
22
+ "quereus.lens.decomp.logical.d1" = 'Car',
23
+ "quereus.lens.decomp.role.d1" = 'primary-storage',
24
+ "quereus.lens.decomp.anchor.d1" = 'Car_core',
25
+ "quereus.lens.decomp.presence.d1" = 'mandatory',
26
+ "quereus.lens.decomp.keykind.d1" = 'logical-tuple',
27
+ "quereus.lens.decomp.key.d1" = 'id',
28
+ "quereus.lens.decomp.col.d1.id" = 'id',
29
+ "quereus.lens.decomp.col.d1.make" = 'make'
30
+ );
31
+
32
+ create table Car_perf (
33
+ id integer primary key,
34
+ speed integer null,
35
+ constraint slow_only check on update (speed < 100)
36
+ ) with tags (
37
+ "quereus.lens.decomp.logical.d1" = 'Car',
38
+ "quereus.lens.decomp.role.d1" = 'primary-storage',
39
+ "quereus.lens.decomp.anchor.d1" = 'Car_core',
40
+ "quereus.lens.decomp.presence.d1" = 'optional',
41
+ "quereus.lens.decomp.keykind.d1" = 'logical-tuple',
42
+ "quereus.lens.decomp.key.d1" = 'id',
43
+ "quereus.lens.decomp.col.d1.maxSpeed" = 'speed'
44
+ );
45
+
46
+ -- run
47
+
48
+ insert into Car_core values (1, 'Honda'), (2, 'Mazda');
49
+ insert into Car_perf values (1, 10);
50
+
51
+ -- run
52
+
53
+ declare logical schema appcar {
54
+ table Car {
55
+ id integer primary key,
56
+ make text,
57
+ maxSpeed integer null
58
+ }
59
+ }
60
+
61
+ -- run
62
+
63
+ declare lens for appcar over main { }
64
+
65
+ -- run
66
+
67
+ apply schema appcar;
68
+
69
+ -- run
70
+
71
+ select * from appcar.Car order by id;
72
+ → [{"id": 1, "make": "Honda", "maxSpeed": 10}, {"id": 2, "make": "Mazda", "maxSpeed": null}]
73
+
74
+ -- ===================================
75
+ -- An anchor-resolvable assignment (`id * 1000`, computable over the anchor scan) takes
76
+ -- the single-statement flavour: absent member rows insert, present ones take DO UPDATE.
77
+ -- Car 1's member row exists, so its composed row is the arm's, and the UPDATE-scoped
78
+ -- CHECK refuses it.
79
+ -- ===================================
80
+
81
+ update appcar.Car set maxSpeed = id * 1000 where id = 1;
82
+ -- error: CHECK constraint failed: slow_only (speed < 100)
83
+
84
+ -- nothing moved on either member.
85
+ select id, speed from Car_perf order by id;
86
+ → [{"id": 1, "speed": 10}]
87
+ select * from appcar.Car order by id;
88
+ → [{"id": 1, "make": "Honda", "maxSpeed": 10}, {"id": 2, "make": "Mazda", "maxSpeed": null}]
89
+
90
+ -- ===================================
91
+ -- The same statement shape with a value the CHECK admits writes through: car 1 takes the
92
+ -- DO UPDATE arm, car 2 (no member row) materializes through the INSERT branch — where
93
+ -- the UPDATE-scoped CHECK correctly does NOT apply.
94
+ -- ===================================
95
+
96
+ update appcar.Car set maxSpeed = id * 10;
97
+ select id, speed from Car_perf order by id;
98
+ → [{"id": 1, "speed": 10}, {"id": 2, "speed": 20}]
99
+ select * from appcar.Car order by id;
100
+ → [{"id": 1, "make": "Honda", "maxSpeed": 10}, {"id": 2, "make": "Mazda", "maxSpeed": 20}]
@@ -0,0 +1,84 @@
1
+ -- Test Reference Graph and Materialization Advisory
2
+
3
+ -- Basic setup
4
+ CREATE TABLE t1 (id INTEGER PRIMARY KEY, value INTEGER);
5
+ CREATE TABLE t2 (id INTEGER PRIMARY KEY, t1_id INTEGER);
6
+ INSERT INTO t1 VALUES (1, 10), (2, 20), (3, 30);
7
+ INSERT INTO t2 VALUES (1, 1), (2, 1), (3, 2), (4, 2), (5, 3);
8
+
9
+ -- Test 1: Multiple references to same subquery should trigger caching
10
+ -- The subquery (SELECT * FROM t1 WHERE value > 15) is referenced twice
11
+ SELECT
12
+ (SELECT COUNT(*) FROM (SELECT * FROM t1 WHERE value > 15) AS sub1) AS count1,
13
+ (SELECT SUM(value) FROM (SELECT * FROM t1 WHERE value > 15) AS sub2) AS sum1
14
+ → [{"count1": 2, "sum1": 50}]
15
+
16
+ -- Test 2: Nested loop join - right side should be cached
17
+ -- This tests loop context detection
18
+ SELECT t1.id, COUNT(t2.id) AS cnt
19
+ FROM t1
20
+ JOIN t2 ON t1.id = t2.t1_id
21
+ GROUP BY t1.id
22
+ ORDER BY t1.id
23
+ → [{"id": 1, "cnt": 2}, {"id": 2, "cnt": 2}, {"id": 3, "cnt": 1}]
24
+
25
+ -- Test 3: Correlated subquery pattern
26
+ -- The subquery executes once per outer row
27
+ SELECT
28
+ t1.id,
29
+ (SELECT COUNT(*) FROM t2 WHERE t2.t1_id = t1.id) AS count
30
+ FROM t1
31
+ ORDER BY t1.id
32
+ → [{"id": 1, "count": 2}, {"id": 2, "count": 2}, {"id": 3, "count": 1}]
33
+
34
+ -- Test 4: EXISTS subquery pattern
35
+ SELECT COUNT(*) AS cnt
36
+ FROM t1
37
+ WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.t1_id = t1.id)
38
+ → [{"cnt": 3}]
39
+
40
+ -- Test 5: IN subquery pattern
41
+ SELECT COUNT(*) AS cnt
42
+ FROM t1
43
+ WHERE id IN (SELECT DISTINCT t1_id FROM t2)
44
+ → [{"cnt": 3}]
45
+
46
+ -- Test 6: CTE with multiple references
47
+ -- The CTE is referenced twice and should be cached
48
+ WITH high_values AS (
49
+ SELECT * FROM t1 WHERE value >= 20
50
+ )
51
+ SELECT
52
+ (SELECT COUNT(*) FROM high_values) AS count,
53
+ (SELECT SUM(value) FROM high_values) AS sum
54
+ → [{"count": 2, "sum": 50}]
55
+
56
+ -- Test 7: Complex query with multiple caching opportunities
57
+ WITH base AS (
58
+ SELECT t1.*, COUNT(t2.id) AS ref_count
59
+ FROM t1
60
+ LEFT JOIN t2 ON t1.id = t2.t1_id
61
+ GROUP BY t1.id, t1.value
62
+ )
63
+ SELECT
64
+ b1.id,
65
+ b1.ref_count,
66
+ (SELECT COUNT(*) FROM base b2 WHERE b2.ref_count > b1.ref_count) AS higher_count
67
+ FROM base b1
68
+ ORDER BY b1.id
69
+ → [{"id": 1, "ref_count": 2, "higher_count": 0}, {"id": 2, "ref_count": 2, "higher_count": 0}, {"id": 3, "ref_count": 1, "higher_count": 2}]
70
+
71
+ -- Test 8: Non-deterministic functions should not be cached
72
+ -- Verify that query plans with random() do not contain cache nodes
73
+ CREATE TABLE t3 (id INTEGER PRIMARY KEY);
74
+ INSERT INTO t3 VALUES (1), (2), (3);
75
+
76
+ -- Check that no Cache nodes are present in the plan for non-deterministic subquery
77
+ SELECT COUNT(*) AS cache_count FROM query_plan('SELECT (SELECT id FROM t3 ORDER BY random() LIMIT 1) AS x FROM t3') WHERE op = 'CACHE'
78
+ → [{"cache_count": 0}]
79
+
80
+ -- Test 9: CTE with MATERIALIZED hint buffers via the `materialize` mark, not a CACHE node
81
+ -- This CTE has an explicit materialization hint; emitCTE buffers it once per execution
82
+ -- (CTENode.materialize), so no separate CacheNode wrap is injected.
83
+ SELECT COUNT(*) AS cache_count FROM query_plan('WITH high_values AS MATERIALIZED (SELECT * FROM t1 WHERE value >= 20) SELECT COUNT(*) FROM high_values') WHERE op = 'CACHE'
84
+ → [{"cache_count": 0}]