@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.
- package/README.md +2 -0
- package/dist/src/common/types.d.ts +4 -4
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/schema/catalog-rendering.js +13 -1
- package/dist/src/schema/catalog-rendering.js.map +1 -1
- package/dist/src/schema/catalog.d.ts +35 -2
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +42 -33
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/schema-differ.d.ts +1 -1
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +195 -33
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/schema/unique-enforcement.d.ts +23 -1
- package/dist/src/schema/unique-enforcement.d.ts.map +1 -1
- package/dist/src/schema/unique-enforcement.js +43 -1
- package/dist/src/schema/unique-enforcement.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +15 -12
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +87 -100
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/package.json +7 -4
- package/test/README.md +173 -0
- package/test/logic/01-basic.sqllogic +39 -0
- package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
- package/test/logic/01.2-strings.sqllogic +43 -0
- package/test/logic/01.5-insert-select.sqllogic +237 -0
- package/test/logic/01.6-update-extras.sqllogic +118 -0
- package/test/logic/01.7-update-from.sqllogic +67 -0
- package/test/logic/01.8-delete-extras.sqllogic +122 -0
- package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
- package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
- package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
- package/test/logic/01.9-query-expr-values.sqllogic +111 -0
- package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
- package/test/logic/02-filters.sqllogic +54 -0
- package/test/logic/02-smoke.sqllogic +62 -0
- package/test/logic/02.1-bind-parameters.sqllogic +223 -0
- package/test/logic/03-expressions.sqllogic +190 -0
- package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
- package/test/logic/03.4-defaults.sqllogic +554 -0
- package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
- package/test/logic/03.5-tvf.sqllogic +61 -0
- package/test/logic/03.6-type-system.sqllogic +544 -0
- package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
- package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
- package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
- package/test/logic/03.8-not-precedence.sqllogic +255 -0
- package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
- package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
- package/test/logic/04-order-by.sqllogic +38 -0
- package/test/logic/04-transactions.sqllogic +239 -0
- package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
- package/test/logic/05-vtab_memory.sqllogic +50 -0
- package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
- package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
- package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
- package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
- package/test/logic/06-builtin_functions.sqllogic +149 -0
- package/test/logic/06.1-string-functions.sqllogic +92 -0
- package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
- package/test/logic/06.2-math-functions.sqllogic +82 -0
- package/test/logic/06.3-schema.sqllogic +48 -0
- package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
- package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
- package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
- package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
- package/test/logic/06.3.4-view-info.sqllogic +378 -0
- package/test/logic/06.3.5-column-info.sqllogic +347 -0
- package/test/logic/06.3.6-schema-views.sqllogic +29 -0
- package/test/logic/06.4-schema-search-path.sqllogic +354 -0
- package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
- package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
- package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
- package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
- package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
- package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
- package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
- package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
- package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
- package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
- package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
- package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
- package/test/logic/06.7-json-extended.sqllogic +53 -0
- package/test/logic/06.8-json-path-operators.sqllogic +99 -0
- package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
- package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
- package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
- package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
- package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
- package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
- package/test/logic/07-aggregates.sqllogic +193 -0
- package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
- package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
- package/test/logic/07.3-group-by-extras.sqllogic +602 -0
- package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
- package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
- package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
- package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
- package/test/logic/07.5-window.sqllogic +1941 -0
- package/test/logic/07.5.1-window-named.sqllogic +13 -0
- package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
- package/test/logic/07.6-subqueries.sqllogic +78 -0
- package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
- package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
- package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
- package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
- package/test/logic/07.7.1-in-extras.sqllogic +158 -0
- package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
- package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
- package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
- package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
- package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
- package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
- package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
- package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
- package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
- package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
- package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
- package/test/logic/07.9-in-value-list.sqllogic +154 -0
- package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
- package/test/logic/08-views.sqllogic +64 -0
- package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
- package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
- package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
- package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
- package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
- package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
- package/test/logic/09-set_operations.sqllogic +244 -0
- package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
- package/test/logic/10-distinct_datatypes.sqllogic +127 -0
- package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
- package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
- package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
- package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
- package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
- package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
- package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
- package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
- package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
- package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
- package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
- package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
- package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
- package/test/logic/10.2-column-features.sqllogic +365 -0
- package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
- package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
- package/test/logic/10.3-function-features.sqllogic +247 -0
- package/test/logic/10.4-schema-scale.sqllogic +168 -0
- package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
- package/test/logic/10.5-indexes.sqllogic +164 -0
- package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
- package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
- package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
- package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
- package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
- package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
- package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
- package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
- package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
- package/test/logic/100.1-where-extras.sqllogic +163 -0
- package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
- package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
- package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
- package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
- package/test/logic/102-unique-constraints.sqllogic +145 -0
- package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
- package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
- package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
- package/test/logic/102.2-unique-collation.sqllogic +181 -0
- package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
- package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
- package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
- package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
- package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
- package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
- package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
- package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
- package/test/logic/108-cardinality-estimation.sqllogic +146 -0
- package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
- package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
- package/test/logic/11-joins.sqllogic +86 -0
- package/test/logic/11.1-join-using.sqllogic +267 -0
- package/test/logic/11.2-comma-join.sqllogic +35 -0
- package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
- package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
- package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
- package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
- package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
- package/test/logic/12-empty-primary-key.sqllogic +124 -0
- package/test/logic/12-join_padding_order.sqllogic +58 -0
- package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
- package/test/logic/13-cte.sqllogic +137 -0
- package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
- package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
- package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
- package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
- package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
- package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
- package/test/logic/13.4-cte-extras.sqllogic +98 -0
- package/test/logic/13.5-cte-join-order.sqllogic +166 -0
- package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
- package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
- package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
- package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
- package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
- package/test/logic/14-utilities.sqllogic +168 -0
- package/test/logic/15-timespan.sqllogic +279 -0
- package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
- package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
- package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
- package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
- package/test/logic/16-epoch.sqllogic +187 -0
- package/test/logic/17-weekday-modifier.sqllogic +78 -0
- package/test/logic/18-json-string-escapes.sqllogic +86 -0
- package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
- package/test/logic/20-empty-single-row.sqllogic +261 -0
- package/test/logic/21-null-edge-cases.sqllogic +227 -0
- package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
- package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
- package/test/logic/21.2-between-edges.sqllogic +157 -0
- package/test/logic/22-boundary-values.sqllogic +175 -0
- package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
- package/test/logic/24-builtin-branches.sqllogic +611 -0
- package/test/logic/24.1-substr-extras.sqllogic +75 -0
- package/test/logic/24.2-random-extras.sqllogic +39 -0
- package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
- package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
- package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
- package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
- package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
- package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
- package/test/logic/26-join-edge-cases.sqllogic +333 -0
- package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
- package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
- package/test/logic/26.3-join-on-constants.sqllogic +61 -0
- package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
- package/test/logic/27-window-edge-cases.sqllogic +206 -0
- package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
- package/test/logic/27.2-window-exclude.sqllogic +13 -0
- package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
- package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
- package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
- package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
- package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
- package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
- package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
- package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
- package/test/logic/40-constraints.sqllogic +418 -0
- package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
- package/test/logic/40.2-check-extras.sqllogic +683 -0
- package/test/logic/41-alter-table.sqllogic +191 -0
- package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
- package/test/logic/41-fk-cross-schema.sqllogic +155 -0
- package/test/logic/41-fk-extended-targets.sqllogic +173 -0
- package/test/logic/41-foreign-keys.sqllogic +1001 -0
- package/test/logic/41-generated-column-errors.sqllogic +225 -0
- package/test/logic/41-generated-column-extras.sqllogic +598 -0
- package/test/logic/41-generated-column-scope.sqllogic +329 -0
- package/test/logic/41-generated-columns.sqllogic +361 -0
- package/test/logic/41.1-alter-pk.sqllogic +230 -0
- package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
- package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
- package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
- package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
- package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
- package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
- package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
- package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
- package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
- package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
- package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
- package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
- package/test/logic/41.2-alter-column.sqllogic +382 -0
- package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
- package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
- package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
- package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
- package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
- package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
- package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
- package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
- package/test/logic/41.5-alter-misc.sqllogic +48 -0
- package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
- package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
- package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
- package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
- package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
- package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
- package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
- package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
- package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
- package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
- package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
- package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
- package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
- package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
- package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
- package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
- package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
- package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
- package/test/logic/42-committed-snapshot.sqllogic +254 -0
- package/test/logic/42-returning.sqllogic +159 -0
- package/test/logic/42.1-returning-extras.sqllogic +232 -0
- package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
- package/test/logic/43-default-nullability.sqllogic +131 -0
- package/test/logic/43-transition-constraints.sqllogic +341 -0
- package/test/logic/43.1-default-collation.sqllogic +140 -0
- package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
- package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
- package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
- package/test/logic/44-determinism-validation.sqllogic +164 -0
- package/test/logic/44-orthogonality.sqllogic +146 -0
- package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
- package/test/logic/45-udf-determinism.sqllogic +39 -0
- package/test/logic/46-mutation-context.sqllogic +595 -0
- package/test/logic/47-upsert.sqllogic +255 -0
- package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
- package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
- package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
- package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
- package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
- package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
- package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
- package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
- package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
- package/test/logic/49-reference-graph.sqllogic +84 -0
- package/test/logic/50-declarative-schema.sqllogic +2550 -0
- package/test/logic/50-metadata-tags.sqllogic +1033 -0
- package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
- package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
- package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
- package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +173 -0
- package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
- package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
- package/test/logic/51-lens-foundation.sqllogic +147 -0
- package/test/logic/51-materialized-views.sqllogic +376 -0
- package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
- package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
- package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
- package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
- package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
- package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
- package/test/logic/52-lens-overrides.sqllogic +566 -0
- package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
- package/test/logic/53-reserved-tags.sqllogic +252 -0
- package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
- package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
- package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
- package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
- package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
- package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
- package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
- package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
- package/test/logic/55-lens-prover.sqllogic +202 -0
- package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
- package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
- package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
- package/test/logic/81-quickpick.sqllogic +24 -0
- package/test/logic/82-bloom-join.sqllogic +185 -0
- package/test/logic/83-merge-join.sqllogic +280 -0
- package/test/logic/84-asof-scan.sqllogic +238 -0
- package/test/logic/84-key-cardinality.sqllogic +50 -0
- package/test/logic/85-relational-const-folding.sqllogic +51 -0
- package/test/logic/86-scalar-cse.sqllogic +42 -0
- package/test/logic/90-error_paths.sqllogic +114 -0
- package/test/logic/90.1-parse-errors.sqllogic +77 -0
- package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
- package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
- package/test/logic/90.3-expression-errors.sqllogic +43 -0
- package/test/logic/90.4-dml-errors.sqllogic +47 -0
- package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
- package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
- package/test/logic/90.6-select-error-paths.sqllogic +57 -0
- package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
- package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
- package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
- package/test/logic/93.1-view-error-paths.sqllogic +74 -0
- package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
- package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
- package/test/logic/93.4-view-mutation.sqllogic +4881 -0
- package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
- package/test/logic/93.5-authored-inverse.sqllogic +415 -0
- package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
- package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
- package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
- package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
- package/test/logic/95-assertions.sqllogic +1417 -0
- package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
- package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
- package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
- package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
- package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
- package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
- package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
- package/test/logic/drop-unique-index.sqllogic +88 -0
- 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}]
|