@quereus/quereus 4.20.1 → 4.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- 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,1468 @@
|
|
|
1
|
+
-- Authored inverses at the lens boundary (docs/lens.md § Computed and
|
|
2
|
+
-- Generated Columns; docs/vu-inverses.md § Authored inverses;
|
|
3
|
+
-- ticket `authored-inverse-lens-prover`).
|
|
4
|
+
--
|
|
5
|
+
-- Covers the prover's law treatment for `with inverse` columns through the full
|
|
6
|
+
-- SQL pipeline: the acknowledgeable `lens.getput-lossy` advisory (+ ack and
|
|
7
|
+
-- escalation governance), the `lens.putget-violation` hard error for an inverse
|
|
8
|
+
-- the forward provably does not reproduce, the bijective-enumeration advisory
|
|
9
|
+
-- suppression, the `inverse` disposition column on quereus_effective_lens, and
|
|
10
|
+
-- writable-intent satisfaction by an authored inverse. (Fingerprint mechanics
|
|
11
|
+
-- are unit-tested in test/lens-ack.spec.ts.)
|
|
12
|
+
|
|
13
|
+
-- ===================================
|
|
14
|
+
-- 1. Code-collapse lens: a non-injective forward with an authored inverse
|
|
15
|
+
-- deploys with the lens.getput-lossy advisory; PutGet holds by enumeration;
|
|
16
|
+
-- write-through normalizes the basis value (GetPut surrendered).
|
|
17
|
+
-- ===================================
|
|
18
|
+
|
|
19
|
+
declare schema ai1b {
|
|
20
|
+
table Item (
|
|
21
|
+
id integer primary key,
|
|
22
|
+
code text not null check (code in ('A1', 'A2', 'B1', 'B2', 'C1'))
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
-- run
|
|
27
|
+
|
|
28
|
+
apply schema ai1b;
|
|
29
|
+
|
|
30
|
+
-- run
|
|
31
|
+
|
|
32
|
+
insert into ai1b.Item values (1, 'A2'), (2, 'B2');
|
|
33
|
+
|
|
34
|
+
-- run
|
|
35
|
+
|
|
36
|
+
declare logical schema ai1x {
|
|
37
|
+
table Item (
|
|
38
|
+
id integer primary key,
|
|
39
|
+
grp text null check (grp in ('A', 'B', 'C'))
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
-- run
|
|
44
|
+
|
|
45
|
+
declare lens for ai1x over ai1b {
|
|
46
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
47
|
+
with inverse (code = new.grp || '1')
|
|
48
|
+
from ai1b.Item
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
-- run
|
|
52
|
+
|
|
53
|
+
apply schema ai1x;
|
|
54
|
+
|
|
55
|
+
-- run
|
|
56
|
+
|
|
57
|
+
-- The advisory fires, sited at the authored column.
|
|
58
|
+
select code, "column", status from quereus_lens_advisories('ai1x') where code = 'lens.getput-lossy';
|
|
59
|
+
→ [{"code": "lens.getput-lossy", "column": "grp", "status": "active"}]
|
|
60
|
+
|
|
61
|
+
-- Reads collapse the basis codes through the forward.
|
|
62
|
+
select * from ai1x.Item order by id;
|
|
63
|
+
→ [{"id": 1, "grp": "A"}, {"id": 2, "grp": "B"}]
|
|
64
|
+
|
|
65
|
+
-- effective-lens reports the authored disposition.
|
|
66
|
+
select logical_column, inverse from quereus_effective_lens('ai1x', 'Item') order by logical_column;
|
|
67
|
+
→ [{"logical_column": "grp", "inverse": "authored"}, {"logical_column": "id", "inverse": "inferred"}]
|
|
68
|
+
|
|
69
|
+
-- run
|
|
70
|
+
|
|
71
|
+
-- UPDATE lowers through the authored put.
|
|
72
|
+
update ai1x.Item set grp = 'C' where id = 1;
|
|
73
|
+
select code from ai1b.Item where id = 1;
|
|
74
|
+
→ [{"code": "C1"}]
|
|
75
|
+
|
|
76
|
+
-- GetPut surrendered: writing the read value back normalizes B2 → B1 (the
|
|
77
|
+
-- inverse's representative) — exactly what the advisory warns about.
|
|
78
|
+
update ai1x.Item set grp = grp where id = 2;
|
|
79
|
+
select code from ai1b.Item where id = 2;
|
|
80
|
+
→ [{"code": "B1"}]
|
|
81
|
+
|
|
82
|
+
-- INSERT evaluates the put per supplied row.
|
|
83
|
+
insert into ai1x.Item (id, grp) values (3, 'A');
|
|
84
|
+
select code from ai1b.Item where id = 3;
|
|
85
|
+
→ [{"code": "A1"}]
|
|
86
|
+
|
|
87
|
+
-- run
|
|
88
|
+
|
|
89
|
+
-- The logical CHECK is enforced at the lens boundary over the written image.
|
|
90
|
+
insert into ai1x.Item (id, grp) values (4, 'Z');
|
|
91
|
+
-- error: check
|
|
92
|
+
|
|
93
|
+
-- ===================================
|
|
94
|
+
-- 2. An in-source ack suppresses the advisory (unconditional — no fingerprint)
|
|
95
|
+
-- ===================================
|
|
96
|
+
|
|
97
|
+
declare logical schema ai2x {
|
|
98
|
+
table Item (
|
|
99
|
+
id integer primary key,
|
|
100
|
+
grp text null check (grp in ('A', 'B', 'C'))
|
|
101
|
+
) with tags (
|
|
102
|
+
"quereus.lens.ack.getput-lossy:grp" = 'collapse to the 1-suffix representative is intentional'
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
-- run
|
|
107
|
+
|
|
108
|
+
declare lens for ai2x over ai1b {
|
|
109
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
110
|
+
with inverse (code = new.grp || '1')
|
|
111
|
+
from ai1b.Item
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
-- run
|
|
115
|
+
|
|
116
|
+
apply schema ai2x;
|
|
117
|
+
|
|
118
|
+
-- run
|
|
119
|
+
|
|
120
|
+
select code, status, rationale from quereus_lens_advisories('ai2x') where code = 'lens.getput-lossy';
|
|
121
|
+
→ [{"code": "lens.getput-lossy", "status": "acknowledged-unconditional", "rationale": "collapse to the 1-suffix representative is intentional"}]
|
|
122
|
+
|
|
123
|
+
-- ===================================
|
|
124
|
+
-- 3. Escalation: require-ack makes the un-acknowledged advisory a deploy error
|
|
125
|
+
-- ===================================
|
|
126
|
+
|
|
127
|
+
declare logical schema ai3x {
|
|
128
|
+
table Item (
|
|
129
|
+
id integer primary key,
|
|
130
|
+
grp text null check (grp in ('A', 'B', 'C'))
|
|
131
|
+
) with tags (
|
|
132
|
+
"quereus.lens.policy.require-ack" = 'lens.getput-lossy'
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
-- run
|
|
137
|
+
|
|
138
|
+
declare lens for ai3x over ai1b {
|
|
139
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
140
|
+
with inverse (code = new.grp || '1')
|
|
141
|
+
from ai1b.Item
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
-- run
|
|
145
|
+
|
|
146
|
+
apply schema ai3x;
|
|
147
|
+
-- error: lens.getput-lossy
|
|
148
|
+
|
|
149
|
+
-- ===================================
|
|
150
|
+
-- 4. Escalation: error-on is a hard error an ack cannot suppress
|
|
151
|
+
-- ===================================
|
|
152
|
+
|
|
153
|
+
declare logical schema ai4x {
|
|
154
|
+
table Item (
|
|
155
|
+
id integer primary key,
|
|
156
|
+
grp text null check (grp in ('A', 'B', 'C'))
|
|
157
|
+
) with tags (
|
|
158
|
+
"quereus.lens.policy.error-on" = 'lens.getput-lossy',
|
|
159
|
+
"quereus.lens.ack.getput-lossy:grp" = 'attempted suppression of a hard policy'
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
-- run
|
|
164
|
+
|
|
165
|
+
declare lens for ai4x over ai1b {
|
|
166
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
167
|
+
with inverse (code = new.grp || '1')
|
|
168
|
+
from ai1b.Item
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
-- run
|
|
172
|
+
|
|
173
|
+
apply schema ai4x;
|
|
174
|
+
-- error: lens.getput-lossy
|
|
175
|
+
|
|
176
|
+
-- ===================================
|
|
177
|
+
-- 5. A deliberately wrong inverse reds lens.putget-violation at deploy:
|
|
178
|
+
-- inverse('A') = 'B1' but forward('B1') = 'B' ≠ 'A'.
|
|
179
|
+
-- ===================================
|
|
180
|
+
|
|
181
|
+
declare logical schema ai5x {
|
|
182
|
+
table Item (
|
|
183
|
+
id integer primary key,
|
|
184
|
+
grp text null check (grp in ('A', 'B'))
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
-- run
|
|
189
|
+
|
|
190
|
+
declare lens for ai5x over ai1b {
|
|
191
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
192
|
+
with inverse (code = case new.grp when 'A' then 'B1' else new.grp || '1' end)
|
|
193
|
+
from ai1b.Item
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
-- run
|
|
197
|
+
|
|
198
|
+
apply schema ai5x;
|
|
199
|
+
-- error: lens.putget-violation
|
|
200
|
+
|
|
201
|
+
-- ===================================
|
|
202
|
+
-- 6. A bijective enumerable mapping emits no advisory (forward proved injective
|
|
203
|
+
-- over the basis CHECK domain, image inside the logical domain) — and GetPut
|
|
204
|
+
-- operationally holds: write-back leaves the basis unchanged.
|
|
205
|
+
-- ===================================
|
|
206
|
+
|
|
207
|
+
declare schema ai6b {
|
|
208
|
+
table Item (
|
|
209
|
+
id integer primary key,
|
|
210
|
+
code text not null check (code in ('a', 'b', 'c'))
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
-- run
|
|
215
|
+
|
|
216
|
+
apply schema ai6b;
|
|
217
|
+
|
|
218
|
+
-- run
|
|
219
|
+
|
|
220
|
+
insert into ai6b.Item values (1, 'b');
|
|
221
|
+
|
|
222
|
+
-- run
|
|
223
|
+
|
|
224
|
+
declare logical schema ai6x {
|
|
225
|
+
table Item (
|
|
226
|
+
id integer primary key,
|
|
227
|
+
grp text null check (grp in ('A', 'B', 'C'))
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
-- run
|
|
232
|
+
|
|
233
|
+
declare lens for ai6x over ai6b {
|
|
234
|
+
view Item as select id, upper(code) as grp
|
|
235
|
+
with inverse (code = lower(new.grp))
|
|
236
|
+
from ai6b.Item
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
-- run
|
|
240
|
+
|
|
241
|
+
apply schema ai6x;
|
|
242
|
+
|
|
243
|
+
-- run
|
|
244
|
+
|
|
245
|
+
select count(*) as n from quereus_lens_advisories('ai6x') where code = 'lens.getput-lossy';
|
|
246
|
+
→ [{"n": 0}]
|
|
247
|
+
|
|
248
|
+
-- GetPut: writing the read value back leaves the basis byte-identical.
|
|
249
|
+
update ai6x.Item set grp = grp where id = 1;
|
|
250
|
+
select code from ai6b.Item where id = 1;
|
|
251
|
+
→ [{"code": "b"}]
|
|
252
|
+
|
|
253
|
+
-- PutGet write-through.
|
|
254
|
+
update ai6x.Item set grp = 'C' where id = 1;
|
|
255
|
+
select code from ai6b.Item where id = 1;
|
|
256
|
+
→ [{"code": "c"}]
|
|
257
|
+
|
|
258
|
+
-- ===================================
|
|
259
|
+
-- 7. effective-lens `inverse` dispositions across a mixed table:
|
|
260
|
+
-- authored / inferred (covered + gap-filled) / none (computed, read-only).
|
|
261
|
+
-- ===================================
|
|
262
|
+
|
|
263
|
+
declare schema ai7b {
|
|
264
|
+
table T (
|
|
265
|
+
id integer primary key,
|
|
266
|
+
name text null,
|
|
267
|
+
code text not null check (code in ('a', 'b'))
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
-- run
|
|
272
|
+
|
|
273
|
+
apply schema ai7b;
|
|
274
|
+
|
|
275
|
+
-- run
|
|
276
|
+
|
|
277
|
+
insert into ai7b.T values (1, 'ada', 'a');
|
|
278
|
+
|
|
279
|
+
-- run
|
|
280
|
+
|
|
281
|
+
declare logical schema ai7x {
|
|
282
|
+
table T (
|
|
283
|
+
id integer primary key,
|
|
284
|
+
name text null,
|
|
285
|
+
grp text null check (grp in ('A', 'B')),
|
|
286
|
+
shout text null
|
|
287
|
+
)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
-- run
|
|
291
|
+
|
|
292
|
+
-- `name` is gap-filled (identity ⇒ inferred); `shout` is computed with no
|
|
293
|
+
-- inverse (none); `grp` carries the authored put (authored).
|
|
294
|
+
declare lens for ai7x over ai7b {
|
|
295
|
+
view T as select id, upper(code) as grp
|
|
296
|
+
with inverse (code = lower(new.grp)),
|
|
297
|
+
upper(name) as shout
|
|
298
|
+
from ai7b.T
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
-- run
|
|
302
|
+
|
|
303
|
+
apply schema ai7x;
|
|
304
|
+
|
|
305
|
+
-- run
|
|
306
|
+
|
|
307
|
+
select logical_column, source, inverse from quereus_effective_lens('ai7x', 'T') order by logical_column;
|
|
308
|
+
→ [{"logical_column": "grp", "source": "override", "inverse": "authored"}, {"logical_column": "id", "source": "override", "inverse": "inferred"}, {"logical_column": "name", "source": "default", "inverse": "inferred"}, {"logical_column": "shout", "source": "override", "inverse": "none"}]
|
|
309
|
+
|
|
310
|
+
-- run
|
|
311
|
+
|
|
312
|
+
select * from ai7x.T;
|
|
313
|
+
→ [{"id": 1, "name": "ada", "grp": "A", "shout": "ADA"}]
|
|
314
|
+
|
|
315
|
+
-- ===================================
|
|
316
|
+
-- 8. quereus.lens.writable = true is satisfied by an authored inverse — no
|
|
317
|
+
-- lens.non-invertible (the column is writable through the supplied put).
|
|
318
|
+
-- ===================================
|
|
319
|
+
|
|
320
|
+
declare schema ai8b {
|
|
321
|
+
table Core (
|
|
322
|
+
id integer primary key,
|
|
323
|
+
speed integer not null
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
-- run
|
|
328
|
+
|
|
329
|
+
apply schema ai8b;
|
|
330
|
+
|
|
331
|
+
-- run
|
|
332
|
+
|
|
333
|
+
insert into ai8b.Core values (1, 30);
|
|
334
|
+
|
|
335
|
+
-- run
|
|
336
|
+
|
|
337
|
+
declare logical schema ai8x {
|
|
338
|
+
table Car (
|
|
339
|
+
id integer primary key,
|
|
340
|
+
mph integer null with tags ("quereus.lens.writable" = true)
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
-- run
|
|
345
|
+
|
|
346
|
+
declare lens for ai8x over ai8b {
|
|
347
|
+
view Car as select id, speed * 3 as mph
|
|
348
|
+
with inverse (speed = new.mph / 3)
|
|
349
|
+
from ai8b.Core
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
-- run
|
|
353
|
+
|
|
354
|
+
apply schema ai8x;
|
|
355
|
+
|
|
356
|
+
-- run
|
|
357
|
+
|
|
358
|
+
select * from ai8x.Car;
|
|
359
|
+
→ [{"id": 1, "mph": 90}]
|
|
360
|
+
|
|
361
|
+
update ai8x.Car set mph = 120 where id = 1;
|
|
362
|
+
select speed from ai8b.Core where id = 1;
|
|
363
|
+
→ [{"speed": 40}]
|
|
364
|
+
|
|
365
|
+
-- ===================================
|
|
366
|
+
-- 9. Out-of-fragment body (join) + authored inverse + writable intent:
|
|
367
|
+
-- degrade-to-safe holds — no branch fires (no lens.non-invertible, no
|
|
368
|
+
-- advisory), the documented completeness gap is not regressed.
|
|
369
|
+
-- ===================================
|
|
370
|
+
|
|
371
|
+
declare schema ai9b {
|
|
372
|
+
table Core (
|
|
373
|
+
id integer primary key,
|
|
374
|
+
code text not null
|
|
375
|
+
)
|
|
376
|
+
table Aux (
|
|
377
|
+
id integer primary key,
|
|
378
|
+
tag text null
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
-- run
|
|
383
|
+
|
|
384
|
+
apply schema ai9b;
|
|
385
|
+
|
|
386
|
+
-- run
|
|
387
|
+
|
|
388
|
+
insert into ai9b.Core values (1, 'x');
|
|
389
|
+
insert into ai9b.Aux values (1, 't');
|
|
390
|
+
|
|
391
|
+
-- run
|
|
392
|
+
|
|
393
|
+
declare logical schema ai9x {
|
|
394
|
+
table V (
|
|
395
|
+
id integer primary key,
|
|
396
|
+
label text null with tags ("quereus.lens.writable" = true)
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
-- run
|
|
401
|
+
|
|
402
|
+
declare lens for ai9x over ai9b {
|
|
403
|
+
view V as select Core.id as id, upper(Core.code) as label
|
|
404
|
+
with inverse (code = lower(new.label))
|
|
405
|
+
from ai9b.Core inner join ai9b.Aux on Core.id = Aux.id
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
-- run
|
|
409
|
+
|
|
410
|
+
apply schema ai9x;
|
|
411
|
+
|
|
412
|
+
-- run
|
|
413
|
+
|
|
414
|
+
select count(*) as n from quereus_lens_advisories('ai9x') where code = 'lens.getput-lossy';
|
|
415
|
+
→ [{"n": 0}]
|
|
416
|
+
|
|
417
|
+
select * from ai9x.V;
|
|
418
|
+
→ [{"id": 1, "label": "X"}]
|
|
419
|
+
|
|
420
|
+
-- ===================================
|
|
421
|
+
-- 10. A non-constant-foldable inverse (subquery) over an enumerable domain
|
|
422
|
+
-- degrades to safe — deploys with the advisory, never a crash; the
|
|
423
|
+
-- mutation-time lowering still consumes the subquery put.
|
|
424
|
+
-- ===================================
|
|
425
|
+
|
|
426
|
+
declare schema ai10b {
|
|
427
|
+
table Item (
|
|
428
|
+
id integer primary key,
|
|
429
|
+
code text not null
|
|
430
|
+
)
|
|
431
|
+
table Lk (
|
|
432
|
+
grp text primary key,
|
|
433
|
+
rep text not null
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
-- run
|
|
438
|
+
|
|
439
|
+
apply schema ai10b;
|
|
440
|
+
|
|
441
|
+
-- run
|
|
442
|
+
|
|
443
|
+
insert into ai10b.Item values (1, 'A1');
|
|
444
|
+
insert into ai10b.Lk values ('A', 'A1'), ('B', 'B1');
|
|
445
|
+
|
|
446
|
+
-- run
|
|
447
|
+
|
|
448
|
+
declare logical schema ai10x {
|
|
449
|
+
table Item (
|
|
450
|
+
id integer primary key,
|
|
451
|
+
grp text null check (grp in ('A', 'B'))
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
-- run
|
|
456
|
+
|
|
457
|
+
declare lens for ai10x over ai10b {
|
|
458
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
459
|
+
with inverse (code = (select rep from ai10b.Lk where Lk.grp = new.grp))
|
|
460
|
+
from ai10b.Item
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
-- run
|
|
464
|
+
|
|
465
|
+
apply schema ai10x;
|
|
466
|
+
|
|
467
|
+
-- run
|
|
468
|
+
|
|
469
|
+
-- Degrade-to-safe: the composition is not const-foldable, so PutGet is
|
|
470
|
+
-- unverified (no error) and the advisory stands (not proved bijective).
|
|
471
|
+
select code, status from quereus_lens_advisories('ai10x') where code = 'lens.getput-lossy';
|
|
472
|
+
→ [{"code": "lens.getput-lossy", "status": "active"}]
|
|
473
|
+
|
|
474
|
+
-- The mutation-time put still evaluates the subquery per write.
|
|
475
|
+
update ai10x.Item set grp = 'B' where id = 1;
|
|
476
|
+
select code from ai10b.Item where id = 1;
|
|
477
|
+
→ [{"code": "B1"}]
|
|
478
|
+
|
|
479
|
+
-- ===================================
|
|
480
|
+
-- 11. Bijectivity suppression requires the inverse's images to land INSIDE the
|
|
481
|
+
-- basis domain. Here PutGet holds ('z' hits the forward's else arm) and the
|
|
482
|
+
-- forward alone is injective over the basis domain ('a'→'A', 'b'→'B'), but
|
|
483
|
+
-- inverse('B') = 'z' escapes the basis CHECK — the pair is not a bijection
|
|
484
|
+
-- (GetPut fails for stored 'b'), so the advisory must stand.
|
|
485
|
+
-- ===================================
|
|
486
|
+
|
|
487
|
+
declare schema ai11b {
|
|
488
|
+
table Item (
|
|
489
|
+
id integer primary key,
|
|
490
|
+
code text not null check (code in ('a', 'b'))
|
|
491
|
+
)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
-- run
|
|
495
|
+
|
|
496
|
+
apply schema ai11b;
|
|
497
|
+
|
|
498
|
+
-- run
|
|
499
|
+
|
|
500
|
+
insert into ai11b.Item values (1, 'b');
|
|
501
|
+
|
|
502
|
+
-- run
|
|
503
|
+
|
|
504
|
+
declare logical schema ai11x {
|
|
505
|
+
table Item (
|
|
506
|
+
id integer primary key,
|
|
507
|
+
grp text null check (grp in ('A', 'B'))
|
|
508
|
+
)
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
-- run
|
|
512
|
+
|
|
513
|
+
declare lens for ai11x over ai11b {
|
|
514
|
+
view Item as select id, case code when 'a' then 'A' else 'B' end as grp
|
|
515
|
+
with inverse (code = case new.grp when 'A' then 'a' else 'z' end)
|
|
516
|
+
from ai11b.Item
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
-- run
|
|
520
|
+
|
|
521
|
+
apply schema ai11x;
|
|
522
|
+
|
|
523
|
+
-- run
|
|
524
|
+
|
|
525
|
+
select code, "column", status from quereus_lens_advisories('ai11x') where code = 'lens.getput-lossy';
|
|
526
|
+
→ [{"code": "lens.getput-lossy", "column": "grp", "status": "active"}]
|
|
527
|
+
|
|
528
|
+
-- The surrendered GetPut is operationally visible: write-back of the read
|
|
529
|
+
-- value puts 'z', which the basis CHECK rejects.
|
|
530
|
+
update ai11x.Item set grp = grp where id = 1;
|
|
531
|
+
-- error: check
|
|
532
|
+
|
|
533
|
+
-- ===================================
|
|
534
|
+
-- 12. A logical CHECK over an authored column on a join body reds
|
|
535
|
+
-- lens.unrealizable-constraint at deploy: the forward substitution is
|
|
536
|
+
-- row-local only on a single-source body. (Here the forward happens to read
|
|
537
|
+
-- only the put member — a conservative over-block — but the slot AST cannot
|
|
538
|
+
-- prove that, and a cross-side forward would otherwise deploy a CHECK that
|
|
539
|
+
-- silently never enforces; see the next scenario's shape.)
|
|
540
|
+
-- ===================================
|
|
541
|
+
|
|
542
|
+
declare schema ai12b {
|
|
543
|
+
table Core (
|
|
544
|
+
id integer primary key,
|
|
545
|
+
code text not null
|
|
546
|
+
)
|
|
547
|
+
table Aux (
|
|
548
|
+
id integer primary key,
|
|
549
|
+
tag text null
|
|
550
|
+
)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
-- run
|
|
554
|
+
|
|
555
|
+
apply schema ai12b;
|
|
556
|
+
|
|
557
|
+
-- run
|
|
558
|
+
|
|
559
|
+
insert into ai12b.Core values (1, 'x');
|
|
560
|
+
insert into ai12b.Aux values (1, 't');
|
|
561
|
+
|
|
562
|
+
-- run
|
|
563
|
+
|
|
564
|
+
declare logical schema ai12x {
|
|
565
|
+
table V (
|
|
566
|
+
id integer primary key,
|
|
567
|
+
label text null check (label in ('X', 'Y'))
|
|
568
|
+
)
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
-- run
|
|
572
|
+
|
|
573
|
+
declare lens for ai12x over ai12b {
|
|
574
|
+
view V as select Core.id as id, upper(Core.code) as label
|
|
575
|
+
with inverse (code = lower(new.label))
|
|
576
|
+
from ai12b.Core inner join ai12b.Aux on Core.id = Aux.id
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
-- run
|
|
580
|
+
|
|
581
|
+
apply schema ai12x;
|
|
582
|
+
-- error: lens.unrealizable-constraint
|
|
583
|
+
|
|
584
|
+
-- ===================================
|
|
585
|
+
-- 13. Read-only gate: a NON-injective authored inverse as the logical PK keeps
|
|
586
|
+
-- the table read-only. The reconstructibility verdict is now the bijection
|
|
587
|
+
-- check, not the bare-column test: substr(code,1,1) collapses A1/A2 so the
|
|
588
|
+
-- forward is not injective — the authored PK column is neither bare-
|
|
589
|
+
-- reconstructible nor bijective-authored, so the PK is not reconstructible and
|
|
590
|
+
-- the table deploys read-only (contrast scenario 18, where a *proven*
|
|
591
|
+
-- bijection makes the authored PK reconstructible ⇒ writable). The lossy
|
|
592
|
+
-- advisory is suppressed because the put never runs on a read-only table.
|
|
593
|
+
-- ===================================
|
|
594
|
+
|
|
595
|
+
declare schema ai13b {
|
|
596
|
+
table Item (
|
|
597
|
+
code text primary key check (code in ('A1', 'A2', 'B1'))
|
|
598
|
+
)
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
-- run
|
|
602
|
+
|
|
603
|
+
apply schema ai13b;
|
|
604
|
+
|
|
605
|
+
-- run
|
|
606
|
+
|
|
607
|
+
declare logical schema ai13x {
|
|
608
|
+
table Item (
|
|
609
|
+
grp text primary key check (grp in ('A', 'B'))
|
|
610
|
+
)
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
-- run
|
|
614
|
+
|
|
615
|
+
-- substr collapses A1/A2 — NOT injective over the basis domain, so absent the
|
|
616
|
+
-- read-only gate the advisory would fire (scenario 1 pins exactly that).
|
|
617
|
+
declare lens for ai13x over ai13b {
|
|
618
|
+
view Item as select substr(code, 1, 1) as grp
|
|
619
|
+
with inverse (code = new.grp || '1')
|
|
620
|
+
from ai13b.Item
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
-- run
|
|
624
|
+
|
|
625
|
+
apply schema ai13x;
|
|
626
|
+
|
|
627
|
+
-- run
|
|
628
|
+
|
|
629
|
+
select count(*) as n from quereus_lens_advisories('ai13x') where code = 'lens.getput-lossy';
|
|
630
|
+
→ [{"n": 0}]
|
|
631
|
+
|
|
632
|
+
-- run
|
|
633
|
+
|
|
634
|
+
insert into ai13x.Item values ('A');
|
|
635
|
+
-- error: read-only
|
|
636
|
+
|
|
637
|
+
-- ===================================
|
|
638
|
+
-- 14. The PutGet error is NOT read-only-gated: the same read-only shape with a
|
|
639
|
+
-- provably wrong inverse still blocks the deploy (a declared write path
|
|
640
|
+
-- that loses the written value is an authoring error regardless).
|
|
641
|
+
-- ===================================
|
|
642
|
+
|
|
643
|
+
declare logical schema ai14x {
|
|
644
|
+
table Item (
|
|
645
|
+
grp text primary key check (grp in ('A', 'B'))
|
|
646
|
+
)
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
-- run
|
|
650
|
+
|
|
651
|
+
declare lens for ai14x over ai13b {
|
|
652
|
+
view Item as select substr(code, 1, 1) as grp
|
|
653
|
+
with inverse (code = case new.grp when 'A' then 'B1' else new.grp || '1' end)
|
|
654
|
+
from ai13b.Item
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
-- run
|
|
658
|
+
|
|
659
|
+
apply schema ai14x;
|
|
660
|
+
-- error: lens.putget-violation
|
|
661
|
+
|
|
662
|
+
-- ===================================
|
|
663
|
+
-- 15. The motivating leak for the single-source gate above: a cross-side
|
|
664
|
+
-- forward (reads Aux.tag, put writes Core.code). Were the CHECK admitted,
|
|
665
|
+
-- the substituted NEW.tag would resolve NULL on the Core-member write and
|
|
666
|
+
-- the CHECK would pass vacuously — an out-of-domain write would land
|
|
667
|
+
-- silently. The deploy must reject instead.
|
|
668
|
+
-- ===================================
|
|
669
|
+
|
|
670
|
+
declare logical schema ai15x {
|
|
671
|
+
table V (
|
|
672
|
+
id integer primary key,
|
|
673
|
+
label text null check (label in ('Xt', 'Yt'))
|
|
674
|
+
)
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
-- run
|
|
678
|
+
|
|
679
|
+
declare lens for ai15x over ai12b {
|
|
680
|
+
view V as select Core.id as id, upper(Core.code) || Aux.tag as label
|
|
681
|
+
with inverse (code = lower(substr(new.label, 1, 1)))
|
|
682
|
+
from ai12b.Core inner join ai12b.Aux on Core.id = Aux.id
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
-- run
|
|
686
|
+
|
|
687
|
+
apply schema ai15x;
|
|
688
|
+
-- error: lens.unrealizable-constraint
|
|
689
|
+
|
|
690
|
+
-- ===================================
|
|
691
|
+
-- 16. Without a logical CHECK on the authored column, the same join-body
|
|
692
|
+
-- authored inverse still deploys and writes through (the single-source gate
|
|
693
|
+
-- constrains only CHECK realizability, not the write path).
|
|
694
|
+
-- ===================================
|
|
695
|
+
|
|
696
|
+
declare logical schema ai16x {
|
|
697
|
+
table V (
|
|
698
|
+
id integer primary key,
|
|
699
|
+
label text null
|
|
700
|
+
)
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
-- run
|
|
704
|
+
|
|
705
|
+
declare lens for ai16x over ai12b {
|
|
706
|
+
view V as select Core.id as id, upper(Core.code) as label
|
|
707
|
+
with inverse (code = lower(new.label))
|
|
708
|
+
from ai12b.Core inner join ai12b.Aux on Core.id = Aux.id
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
-- run
|
|
712
|
+
|
|
713
|
+
apply schema ai16x;
|
|
714
|
+
|
|
715
|
+
-- run
|
|
716
|
+
|
|
717
|
+
update ai16x.V set label = 'Y' where id = 1;
|
|
718
|
+
select code from ai12b.Core where id = 1;
|
|
719
|
+
→ [{"code": "y"}]
|
|
720
|
+
|
|
721
|
+
-- ===================================
|
|
722
|
+
-- 17. The enumeration honors the column's full declared CHECK surface: a range
|
|
723
|
+
-- CHECK narrows the in-list (3 is excluded), so an inverse that is only
|
|
724
|
+
-- correct for the surviving values {1, 2} deploys clean — enumerating the
|
|
725
|
+
-- excluded value would red a false lens.putget-violation. Integer domain.
|
|
726
|
+
-- ===================================
|
|
727
|
+
|
|
728
|
+
declare schema ai17b {
|
|
729
|
+
table Item (
|
|
730
|
+
id integer primary key,
|
|
731
|
+
k integer not null
|
|
732
|
+
)
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
-- run
|
|
736
|
+
|
|
737
|
+
apply schema ai17b;
|
|
738
|
+
|
|
739
|
+
-- run
|
|
740
|
+
|
|
741
|
+
insert into ai17b.Item values (1, 0);
|
|
742
|
+
|
|
743
|
+
-- run
|
|
744
|
+
|
|
745
|
+
declare logical schema ai17x {
|
|
746
|
+
table Item (
|
|
747
|
+
id integer primary key,
|
|
748
|
+
n integer null check (n in (1, 2, 3)),
|
|
749
|
+
check (n < 3)
|
|
750
|
+
)
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
-- run
|
|
754
|
+
|
|
755
|
+
-- inverse(3) would store 99 and read back 100 ≠ 3 — but 3 is outside the
|
|
756
|
+
-- effective domain, so the composition is never evaluated for it.
|
|
757
|
+
declare lens for ai17x over ai17b {
|
|
758
|
+
view Item as select id, k + 1 as n
|
|
759
|
+
with inverse (k = case when new.n < 3 then new.n - 1 else 99 end)
|
|
760
|
+
from ai17b.Item
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
-- run
|
|
764
|
+
|
|
765
|
+
apply schema ai17x;
|
|
766
|
+
|
|
767
|
+
-- run
|
|
768
|
+
|
|
769
|
+
-- No basis-side CHECK domain ⇒ bijectivity unproven ⇒ the advisory stands.
|
|
770
|
+
select code, "column", status from quereus_lens_advisories('ai17x') where code = 'lens.getput-lossy';
|
|
771
|
+
→ [{"code": "lens.getput-lossy", "column": "n", "status": "active"}]
|
|
772
|
+
|
|
773
|
+
-- run
|
|
774
|
+
|
|
775
|
+
update ai17x.Item set n = 2 where id = 1;
|
|
776
|
+
select k from ai17b.Item where id = 1;
|
|
777
|
+
→ [{"k": 1}]
|
|
778
|
+
|
|
779
|
+
-- Both declared CHECKs enforce over the written image (NEW.k + 1).
|
|
780
|
+
update ai17x.Item set n = 3 where id = 1;
|
|
781
|
+
-- error: check
|
|
782
|
+
|
|
783
|
+
-- ===================================
|
|
784
|
+
-- 18. PK over a PROVEN-BIJECTIVE authored inverse → WRITABLE. The logical PK is
|
|
785
|
+
-- the authored column itself; the forward/inverse pair is proved a bijection
|
|
786
|
+
-- between the basis and logical CHECK domains, AND the put-target basis column
|
|
787
|
+
-- is a declared basis key, so the key is `proved` by bijection transport. The
|
|
788
|
+
-- table deploys writable (no lens.pk-not-reconstructible), with zero runtime
|
|
789
|
+
-- key enforcement (no lens.no-backing-index) and no lens.getput-lossy. Full
|
|
790
|
+
-- keyed CRUD goes through the authored put: the forward in WHERE locates the
|
|
791
|
+
-- row, the inverse in SET/VALUES writes the basis cell.
|
|
792
|
+
--
|
|
793
|
+
-- Integer keys (not text) so the behaviour is identical under the memory and
|
|
794
|
+
-- LevelDB-store backends: the store assigns a single-column TEXT primary key
|
|
795
|
+
-- NOCASE collation, under which a text CHECK in-list is not value-discriminating
|
|
796
|
+
-- and so cannot witness a bijection — the integer-keyed shape proves cleanly on
|
|
797
|
+
-- both. (The text upper/lower bijection is covered by scenario 6 and the unit
|
|
798
|
+
-- specs.)
|
|
799
|
+
-- ===================================
|
|
800
|
+
|
|
801
|
+
declare schema bpk_b {
|
|
802
|
+
table Item (
|
|
803
|
+
k integer primary key check (k in (1, 2, 3))
|
|
804
|
+
)
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
-- run
|
|
808
|
+
|
|
809
|
+
apply schema bpk_b;
|
|
810
|
+
|
|
811
|
+
-- run
|
|
812
|
+
|
|
813
|
+
insert into bpk_b.Item values (2);
|
|
814
|
+
|
|
815
|
+
-- run
|
|
816
|
+
|
|
817
|
+
declare logical schema bpk_x {
|
|
818
|
+
table Item (
|
|
819
|
+
n integer primary key check (n in (11, 12, 13))
|
|
820
|
+
)
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
-- run
|
|
824
|
+
|
|
825
|
+
declare lens for bpk_x over bpk_b {
|
|
826
|
+
view Item as select k + 10 as n
|
|
827
|
+
with inverse (k = new.n - 10)
|
|
828
|
+
from bpk_b.Item
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
-- run
|
|
832
|
+
|
|
833
|
+
apply schema bpk_x;
|
|
834
|
+
|
|
835
|
+
-- run
|
|
836
|
+
|
|
837
|
+
-- No advisories at all: bijective (no getput-lossy), reconstructible (no
|
|
838
|
+
-- pk-not-reconstructible), proved by transport (no no-backing-index).
|
|
839
|
+
select count(*) as n from quereus_lens_advisories('bpk_x');
|
|
840
|
+
→ [{"n": 0}]
|
|
841
|
+
|
|
842
|
+
-- Read transports the basis key through the forward.
|
|
843
|
+
select * from bpk_x.Item;
|
|
844
|
+
→ [{"n": 12}]
|
|
845
|
+
|
|
846
|
+
-- run
|
|
847
|
+
|
|
848
|
+
-- INSERT through the authored put: 11 stores k = 1.
|
|
849
|
+
insert into bpk_x.Item values (11);
|
|
850
|
+
select k from bpk_b.Item order by k;
|
|
851
|
+
→ [{"k": 1}, {"k": 2}]
|
|
852
|
+
|
|
853
|
+
-- run
|
|
854
|
+
|
|
855
|
+
-- UPDATE by the authored key: forward in WHERE (k + 10 = 12), put in SET (k = 13 - 10).
|
|
856
|
+
update bpk_x.Item set n = 13 where n = 12;
|
|
857
|
+
select k from bpk_b.Item where k = 3;
|
|
858
|
+
→ [{"k": 3}]
|
|
859
|
+
|
|
860
|
+
-- run
|
|
861
|
+
|
|
862
|
+
-- DELETE by the authored key.
|
|
863
|
+
delete from bpk_x.Item where n = 11;
|
|
864
|
+
select count(*) as cnt from bpk_b.Item where k = 1;
|
|
865
|
+
→ [{"cnt": 0}]
|
|
866
|
+
|
|
867
|
+
-- run
|
|
868
|
+
|
|
869
|
+
-- GetPut still byte-stable (bijection): writing the read value back leaves the
|
|
870
|
+
-- basis unchanged.
|
|
871
|
+
update bpk_x.Item set n = n where n = 13;
|
|
872
|
+
select k from bpk_b.Item where k = 3;
|
|
873
|
+
→ [{"k": 3}]
|
|
874
|
+
|
|
875
|
+
-- ===================================
|
|
876
|
+
-- 19. A bijective authored inverse whose put-target basis column is NOT a basis
|
|
877
|
+
-- key keeps the table writable (the bijection still proves, so the PK column
|
|
878
|
+
-- is reconstructible — no lens.pk-not-reconstructible) but does NOT classify
|
|
879
|
+
-- `proved`: two basis rows could share the value (`k` is NOT NULL + CHECK, but
|
|
880
|
+
-- the basis PK is the unrelated `id`), so the logical key is not intrinsically
|
|
881
|
+
-- unique. It enforces commit-time and emits lens.no-backing-index. The
|
|
882
|
+
-- columnsFormDeclaredKey gate over the put target is load-bearing here.
|
|
883
|
+
-- ===================================
|
|
884
|
+
|
|
885
|
+
declare schema nbk_b {
|
|
886
|
+
table Item (
|
|
887
|
+
id integer primary key,
|
|
888
|
+
k integer not null check (k in (1, 2, 3))
|
|
889
|
+
)
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
-- run
|
|
893
|
+
|
|
894
|
+
apply schema nbk_b;
|
|
895
|
+
|
|
896
|
+
-- run
|
|
897
|
+
|
|
898
|
+
declare logical schema nbk_x {
|
|
899
|
+
table Item (
|
|
900
|
+
n integer primary key check (n in (11, 12, 13))
|
|
901
|
+
)
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
-- run
|
|
905
|
+
|
|
906
|
+
declare lens for nbk_x over nbk_b {
|
|
907
|
+
view Item as select k + 10 as n
|
|
908
|
+
with inverse (k = new.n - 10)
|
|
909
|
+
from nbk_b.Item
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
-- run
|
|
913
|
+
|
|
914
|
+
apply schema nbk_x;
|
|
915
|
+
|
|
916
|
+
-- run
|
|
917
|
+
|
|
918
|
+
-- Writable (bijective ⇒ reconstructible): no read-only advisory.
|
|
919
|
+
select count(*) as cnt from quereus_lens_advisories('nbk_x') where code = 'lens.pk-not-reconstructible';
|
|
920
|
+
→ [{"cnt": 0}]
|
|
921
|
+
|
|
922
|
+
-- Not proved (put-target is not a basis key): commit-time enforcement, so the
|
|
923
|
+
-- no-backing-index advisory fires, sited at the primary key.
|
|
924
|
+
select code, "constraint", "column" from quereus_lens_advisories('nbk_x') where code = 'lens.no-backing-index';
|
|
925
|
+
→ [{"code": "lens.no-backing-index", "constraint": "primary key", "column": null}]
|
|
926
|
+
|
|
927
|
+
-- Bijection still proved ⇒ no getput-lossy.
|
|
928
|
+
select count(*) as cnt from quereus_lens_advisories('nbk_x') where code = 'lens.getput-lossy';
|
|
929
|
+
→ [{"cnt": 0}]
|
|
930
|
+
|
|
931
|
+
-- ===================================
|
|
932
|
+
-- 20. A logical UNIQUE over a PROVEN-BIJECTIVE authored inverse is REALIZABLE.
|
|
933
|
+
-- The authored column is not the PK (the table is keyed and writable via the
|
|
934
|
+
-- real PK `id`), so the UNIQUE classifies on its own. The forward/inverse pair
|
|
935
|
+
-- is proved a bijection, AND the put-target basis column `code` carries a
|
|
936
|
+
-- declared basis UNIQUE — so the logical UNIQUE is `proved` by bijection
|
|
937
|
+
-- transport: zero runtime enforcement, no lens.unrealizable-constraint, no
|
|
938
|
+
-- lens.no-backing-index, no lens.getput-lossy. A duplicate is forbidden by the
|
|
939
|
+
-- basis UNIQUE through the write-through (the proved key relies on it, exactly
|
|
940
|
+
-- as the design intends). Integer +10 affine bijection (backend-agnostic, like
|
|
941
|
+
-- scenario 18). The logical UNIQUE column is NOT NULL: the bijection-transport
|
|
942
|
+
-- proof requires it (a nullable key would be conditionally unique and defers to
|
|
943
|
+
-- commit-time per the prereq's transport guard).
|
|
944
|
+
-- ===================================
|
|
945
|
+
|
|
946
|
+
declare schema buprv_b {
|
|
947
|
+
table Item (
|
|
948
|
+
id integer primary key,
|
|
949
|
+
code integer not null unique check (code in (1, 2, 3))
|
|
950
|
+
)
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
-- run
|
|
954
|
+
|
|
955
|
+
apply schema buprv_b;
|
|
956
|
+
|
|
957
|
+
-- run
|
|
958
|
+
|
|
959
|
+
insert into buprv_b.Item values (1, 1);
|
|
960
|
+
|
|
961
|
+
-- run
|
|
962
|
+
|
|
963
|
+
declare logical schema buprv_x {
|
|
964
|
+
table Item (
|
|
965
|
+
id integer primary key,
|
|
966
|
+
grp integer not null check (grp in (11, 12, 13)),
|
|
967
|
+
unique (grp)
|
|
968
|
+
)
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
-- run
|
|
972
|
+
|
|
973
|
+
declare lens for buprv_x over buprv_b {
|
|
974
|
+
view Item as select id, code + 10 as grp
|
|
975
|
+
with inverse (code = new.grp - 10)
|
|
976
|
+
from buprv_b.Item
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
-- run
|
|
980
|
+
|
|
981
|
+
apply schema buprv_x;
|
|
982
|
+
|
|
983
|
+
-- run
|
|
984
|
+
|
|
985
|
+
-- Clean deploy: proved by transport (no unrealizable, no no-backing-index, no
|
|
986
|
+
-- getput-lossy), reconstructible PK (no pk-not-reconstructible).
|
|
987
|
+
select count(*) as n from quereus_lens_advisories('buprv_x');
|
|
988
|
+
→ [{"n": 0}]
|
|
989
|
+
|
|
990
|
+
-- run
|
|
991
|
+
|
|
992
|
+
-- Read transports the basis key through the forward.
|
|
993
|
+
select * from buprv_x.Item order by id;
|
|
994
|
+
→ [{"id": 1, "grp": 11}]
|
|
995
|
+
|
|
996
|
+
-- run
|
|
997
|
+
|
|
998
|
+
-- A second row whose grp maps to an existing code (grp 11 → code 1) is forbidden by
|
|
999
|
+
-- the basis UNIQUE through the write-through — distinct id, so the basis PK does not
|
|
1000
|
+
-- catch it. The proved logical UNIQUE adds no runtime scan; the basis UNIQUE is the
|
|
1001
|
+
-- enforcer.
|
|
1002
|
+
insert into buprv_x.Item values (2, 11);
|
|
1003
|
+
-- error: unique
|
|
1004
|
+
|
|
1005
|
+
-- run
|
|
1006
|
+
|
|
1007
|
+
-- A distinct grp lands.
|
|
1008
|
+
insert into buprv_x.Item values (3, 12);
|
|
1009
|
+
select code from buprv_b.Item order by code;
|
|
1010
|
+
→ [{"code": 1}, {"code": 2}]
|
|
1011
|
+
|
|
1012
|
+
-- ===================================
|
|
1013
|
+
-- 21. Commit-time fallback: the same bijective authored UNIQUE, but the put-target
|
|
1014
|
+
-- basis column has a CHECK + NOT NULL yet NO basis UNIQUE/PK over it — so the
|
|
1015
|
+
-- bijection-transport proof fails (no declared basis key) and findBasisCovering
|
|
1016
|
+
-- finds nothing (the authored projection has no bare basis column to map). The
|
|
1017
|
+
-- UNIQUE is still REALIZABLE: it enforces commit-time over the logical forward
|
|
1018
|
+
-- image, deploying with lens.no-backing-index (NOT lens.unrealizable-constraint).
|
|
1019
|
+
-- A logical-key duplicate ABORTs via the O(n) count scan.
|
|
1020
|
+
-- ===================================
|
|
1021
|
+
|
|
1022
|
+
declare schema buct_b {
|
|
1023
|
+
table Item (
|
|
1024
|
+
id integer primary key,
|
|
1025
|
+
code integer not null check (code in (1, 2, 3))
|
|
1026
|
+
)
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
-- run
|
|
1030
|
+
|
|
1031
|
+
apply schema buct_b;
|
|
1032
|
+
|
|
1033
|
+
-- run
|
|
1034
|
+
|
|
1035
|
+
insert into buct_b.Item values (1, 1);
|
|
1036
|
+
|
|
1037
|
+
-- run
|
|
1038
|
+
|
|
1039
|
+
declare logical schema buct_x {
|
|
1040
|
+
table Item (
|
|
1041
|
+
id integer primary key,
|
|
1042
|
+
grp integer not null check (grp in (11, 12, 13)),
|
|
1043
|
+
unique (grp)
|
|
1044
|
+
)
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
-- run
|
|
1048
|
+
|
|
1049
|
+
declare lens for buct_x over buct_b {
|
|
1050
|
+
view Item as select id, code + 10 as grp
|
|
1051
|
+
with inverse (code = new.grp - 10)
|
|
1052
|
+
from buct_b.Item
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
-- run
|
|
1056
|
+
|
|
1057
|
+
apply schema buct_x;
|
|
1058
|
+
|
|
1059
|
+
-- run
|
|
1060
|
+
|
|
1061
|
+
-- Realizable, not proved: exactly one active no-backing-index advisory, sited at the
|
|
1062
|
+
-- unique constraint (the put target is not a basis key).
|
|
1063
|
+
select code, "constraint", status from quereus_lens_advisories('buct_x') where code = 'lens.no-backing-index';
|
|
1064
|
+
→ [{"code": "lens.no-backing-index", "constraint": "unique", "status": "active"}]
|
|
1065
|
+
|
|
1066
|
+
-- run
|
|
1067
|
+
|
|
1068
|
+
-- Neither unrealizable nor lossy: the bijection still proves the round-trip.
|
|
1069
|
+
select count(*) as n from quereus_lens_advisories('buct_x') where code in ('lens.unrealizable-constraint', 'lens.getput-lossy');
|
|
1070
|
+
→ [{"n": 0}]
|
|
1071
|
+
|
|
1072
|
+
-- run
|
|
1073
|
+
|
|
1074
|
+
-- Read transports the basis key.
|
|
1075
|
+
select * from buct_x.Item order by id;
|
|
1076
|
+
→ [{"id": 1, "grp": 11}]
|
|
1077
|
+
|
|
1078
|
+
-- run
|
|
1079
|
+
|
|
1080
|
+
-- A logical-key duplicate (grp 11 → code 1, distinct id) ABORTs via the commit-time
|
|
1081
|
+
-- count scan — the basis has no UNIQUE on code, so only the logical scan catches it.
|
|
1082
|
+
insert into buct_x.Item values (2, 11);
|
|
1083
|
+
-- error: constraint
|
|
1084
|
+
|
|
1085
|
+
-- run
|
|
1086
|
+
|
|
1087
|
+
-- A distinct grp lands (grp 12 → code 2).
|
|
1088
|
+
insert into buct_x.Item values (3, 12);
|
|
1089
|
+
select code from buct_b.Item order by code;
|
|
1090
|
+
→ [{"code": 1}, {"code": 2}]
|
|
1091
|
+
|
|
1092
|
+
-- run
|
|
1093
|
+
|
|
1094
|
+
-- A key-changing UPDATE that creates a duplicate (grp 12 → 11, colliding with id 1)
|
|
1095
|
+
-- also ABORTs via the commit-time scan (the constraint fires on INSERT|UPDATE; the
|
|
1096
|
+
-- NEW side is the authored forward image NEW.code + 10). The row is unchanged.
|
|
1097
|
+
update buct_x.Item set grp = 11 where grp = 12;
|
|
1098
|
+
-- error: constraint
|
|
1099
|
+
|
|
1100
|
+
-- run
|
|
1101
|
+
|
|
1102
|
+
select grp from buct_x.Item order by grp;
|
|
1103
|
+
→ [{"grp": 11}, {"grp": 12}]
|
|
1104
|
+
|
|
1105
|
+
-- ===================================
|
|
1106
|
+
-- 22. A NON-INJECTIVE (lossy) authored UNIQUE still reds lens.unrealizable-constraint
|
|
1107
|
+
-- — the motivating safety case. substr(code,1,1) collapses A1/A2 → A, so the
|
|
1108
|
+
-- forward is not injective and the authored column is NOT in the bijective set;
|
|
1109
|
+
-- uniqueness over a value with no proven write path is neither provable nor
|
|
1110
|
+
-- enforceable, so the gate stays closed for it.
|
|
1111
|
+
-- ===================================
|
|
1112
|
+
|
|
1113
|
+
declare schema bunj_b {
|
|
1114
|
+
table Item (
|
|
1115
|
+
id integer primary key,
|
|
1116
|
+
code text not null check (code in ('A1', 'A2', 'B1'))
|
|
1117
|
+
)
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
-- run
|
|
1121
|
+
|
|
1122
|
+
apply schema bunj_b;
|
|
1123
|
+
|
|
1124
|
+
-- run
|
|
1125
|
+
|
|
1126
|
+
declare logical schema bunj_x {
|
|
1127
|
+
table Item (
|
|
1128
|
+
id integer primary key,
|
|
1129
|
+
grp text null check (grp in ('A', 'B')),
|
|
1130
|
+
unique (grp)
|
|
1131
|
+
)
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
-- run
|
|
1135
|
+
|
|
1136
|
+
declare lens for bunj_x over bunj_b {
|
|
1137
|
+
view Item as select id, substr(code, 1, 1) as grp
|
|
1138
|
+
with inverse (code = new.grp || '1')
|
|
1139
|
+
from bunj_b.Item
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
-- run
|
|
1143
|
+
|
|
1144
|
+
apply schema bunj_x;
|
|
1145
|
+
-- error: lens.unrealizable-constraint
|
|
1146
|
+
|
|
1147
|
+
-- ===================================
|
|
1148
|
+
-- 23. Conflict-action rejection: a bijective authored UNIQUE that classifies
|
|
1149
|
+
-- commit-time (no basis key over the put target) with `on conflict replace`
|
|
1150
|
+
-- still reds lens.unenforceable-conflict-action — the commit-time count scan can
|
|
1151
|
+
-- only ABORT, never REPLACE. The realizability gate is lifted, but the
|
|
1152
|
+
-- conflict-action gate downstream still fires.
|
|
1153
|
+
-- ===================================
|
|
1154
|
+
|
|
1155
|
+
declare schema buca_b {
|
|
1156
|
+
table Item (
|
|
1157
|
+
id integer primary key,
|
|
1158
|
+
code integer not null check (code in (1, 2, 3))
|
|
1159
|
+
)
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
-- run
|
|
1163
|
+
|
|
1164
|
+
apply schema buca_b;
|
|
1165
|
+
|
|
1166
|
+
-- run
|
|
1167
|
+
|
|
1168
|
+
declare logical schema buca_x {
|
|
1169
|
+
table Item (
|
|
1170
|
+
id integer primary key,
|
|
1171
|
+
grp integer not null check (grp in (11, 12, 13)),
|
|
1172
|
+
unique (grp) on conflict replace
|
|
1173
|
+
)
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
-- run
|
|
1177
|
+
|
|
1178
|
+
declare lens for buca_x over buca_b {
|
|
1179
|
+
view Item as select id, code + 10 as grp
|
|
1180
|
+
with inverse (code = new.grp - 10)
|
|
1181
|
+
from buca_b.Item
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
-- run
|
|
1185
|
+
|
|
1186
|
+
apply schema buca_x;
|
|
1187
|
+
-- error: lens.unenforceable-conflict-action
|
|
1188
|
+
|
|
1189
|
+
-- ===================================
|
|
1190
|
+
-- 24. Multi-column commit-time UNIQUE mixing a bare-reconstructible column and a
|
|
1191
|
+
-- bijective authored column. unique(tag, grp): `tag` is a plain rename (bare,
|
|
1192
|
+
-- NEW.tag) and `grp` is the +10 affine bijection (authored, NEW.code + 10). No
|
|
1193
|
+
-- basis key over the put targets ⇒ commit-time. Exercises the per-column NEW-side
|
|
1194
|
+
-- synthesis: the count predicate must read `_u.tag = NEW.tag and _u.grp =
|
|
1195
|
+
-- NEW.code + 10` so a logical-domain tuple is compared to a logical-domain tuple.
|
|
1196
|
+
-- Distinct tuples land; a duplicate logical tuple ABORTs.
|
|
1197
|
+
-- ===================================
|
|
1198
|
+
|
|
1199
|
+
declare schema bumix_b {
|
|
1200
|
+
table Item (
|
|
1201
|
+
id integer primary key,
|
|
1202
|
+
tag text not null,
|
|
1203
|
+
code integer not null check (code in (1, 2, 3))
|
|
1204
|
+
)
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
-- run
|
|
1208
|
+
|
|
1209
|
+
apply schema bumix_b;
|
|
1210
|
+
|
|
1211
|
+
-- run
|
|
1212
|
+
|
|
1213
|
+
declare logical schema bumix_x {
|
|
1214
|
+
table Item (
|
|
1215
|
+
id integer primary key,
|
|
1216
|
+
tag text not null,
|
|
1217
|
+
grp integer not null check (grp in (11, 12, 13)),
|
|
1218
|
+
unique (tag, grp)
|
|
1219
|
+
)
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
-- run
|
|
1223
|
+
|
|
1224
|
+
declare lens for bumix_x over bumix_b {
|
|
1225
|
+
view Item as select id, tag, code + 10 as grp
|
|
1226
|
+
with inverse (code = new.grp - 10)
|
|
1227
|
+
from bumix_b.Item
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
-- run
|
|
1231
|
+
|
|
1232
|
+
apply schema bumix_x;
|
|
1233
|
+
|
|
1234
|
+
-- run
|
|
1235
|
+
|
|
1236
|
+
-- Commit-time (mixed bare + authored key): one no-backing-index, no unrealizable.
|
|
1237
|
+
select code, "constraint", status from quereus_lens_advisories('bumix_x') where code = 'lens.no-backing-index';
|
|
1238
|
+
→ [{"code": "lens.no-backing-index", "constraint": "unique", "status": "active"}]
|
|
1239
|
+
|
|
1240
|
+
-- run
|
|
1241
|
+
|
|
1242
|
+
-- Distinct logical tuples all land: (a,11), (a,12) differ in grp; (b,11) differs in tag.
|
|
1243
|
+
insert into bumix_x.Item values (1, 'a', 11), (2, 'a', 12), (3, 'b', 11);
|
|
1244
|
+
select id, tag, code from bumix_b.Item order by id;
|
|
1245
|
+
→ [{"id": 1, "tag": "a", "code": 1}, {"id": 2, "tag": "a", "code": 2}, {"id": 3, "tag": "b", "code": 1}]
|
|
1246
|
+
|
|
1247
|
+
-- run
|
|
1248
|
+
|
|
1249
|
+
-- A duplicate logical tuple (a, 11) → (tag a, code 1) ABORTs via the commit-time scan
|
|
1250
|
+
-- over the mixed NEW side (NEW.tag and NEW.code + 10).
|
|
1251
|
+
insert into bumix_x.Item values (4, 'a', 11);
|
|
1252
|
+
-- error: constraint
|
|
1253
|
+
|
|
1254
|
+
-- ===================================
|
|
1255
|
+
-- 25. Conflict-action rejection on a PROVED-by-TRANSPORT key — the headline repro.
|
|
1256
|
+
-- A bare-reconstructible rename (`code as grp`) whose put-target basis column
|
|
1257
|
+
-- carries a declared basis UNIQUE classifies `proved` (a basis NOT-NULL UNIQUE is
|
|
1258
|
+
-- itself a relation key, so the body proves the logical key directly). But the
|
|
1259
|
+
-- basis UNIQUE — not the logical key — governs a write-through: a duplicate `grp`
|
|
1260
|
+
-- maps to a duplicate `code`, which the basis UNIQUE resolves by its OWN action
|
|
1261
|
+
-- (here ABORT). So a logical `unique (grp) on conflict replace` the basis UNIQUE
|
|
1262
|
+
-- does not carry would be silently dropped — it reds lens.unenforceable-conflict-
|
|
1263
|
+
-- action. (Before the fix this deployed clean, dropping the declared REPLACE.)
|
|
1264
|
+
-- ===================================
|
|
1265
|
+
|
|
1266
|
+
declare schema tca25_b {
|
|
1267
|
+
table t (
|
|
1268
|
+
id integer primary key,
|
|
1269
|
+
code integer not null unique check (code in (1, 2, 3))
|
|
1270
|
+
)
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
-- run
|
|
1274
|
+
|
|
1275
|
+
apply schema tca25_b;
|
|
1276
|
+
|
|
1277
|
+
-- run
|
|
1278
|
+
|
|
1279
|
+
declare logical schema tca25_x {
|
|
1280
|
+
table t (
|
|
1281
|
+
id integer primary key,
|
|
1282
|
+
grp integer not null check (grp in (1, 2, 3)),
|
|
1283
|
+
unique (grp) on conflict replace
|
|
1284
|
+
)
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
-- run
|
|
1288
|
+
|
|
1289
|
+
declare lens for tca25_x over tca25_b {
|
|
1290
|
+
view t as select id, code as grp from tca25_b.t
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
-- run
|
|
1294
|
+
|
|
1295
|
+
apply schema tca25_x;
|
|
1296
|
+
-- error: lens.unenforceable-conflict-action
|
|
1297
|
+
|
|
1298
|
+
-- ===================================
|
|
1299
|
+
-- 26. The same rejection over an AUTHORED-bijective transport key (+10 affine), to
|
|
1300
|
+
-- pin the authored arm of the transport proof too (the body cannot prove a `code
|
|
1301
|
+
-- + 10` key, so this reaches the transport classification, not the body-proved
|
|
1302
|
+
-- one). Basis UNIQUE on the put target (ABORT), logical `unique (grp) on conflict
|
|
1303
|
+
-- replace` ⇒ red.
|
|
1304
|
+
-- ===================================
|
|
1305
|
+
|
|
1306
|
+
declare schema tca26_b {
|
|
1307
|
+
table t (
|
|
1308
|
+
id integer primary key,
|
|
1309
|
+
code integer not null unique check (code in (1, 2, 3))
|
|
1310
|
+
)
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
-- run
|
|
1314
|
+
|
|
1315
|
+
apply schema tca26_b;
|
|
1316
|
+
|
|
1317
|
+
-- run
|
|
1318
|
+
|
|
1319
|
+
declare logical schema tca26_x {
|
|
1320
|
+
table t (
|
|
1321
|
+
id integer primary key,
|
|
1322
|
+
grp integer not null check (grp in (11, 12, 13)),
|
|
1323
|
+
unique (grp) on conflict replace
|
|
1324
|
+
)
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
-- run
|
|
1328
|
+
|
|
1329
|
+
declare lens for tca26_x over tca26_b {
|
|
1330
|
+
view t as select id, code + 10 as grp
|
|
1331
|
+
with inverse (code = new.grp - 10)
|
|
1332
|
+
from tca26_b.t
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
-- run
|
|
1336
|
+
|
|
1337
|
+
apply schema tca26_x;
|
|
1338
|
+
-- error: lens.unenforceable-conflict-action
|
|
1339
|
+
|
|
1340
|
+
-- ===================================
|
|
1341
|
+
-- 27. A MATCHING basis-UNIQUE action deploys clean and the write-through honors
|
|
1342
|
+
-- REPLACE for free — the positive case the rejecter must NOT block. Basis UNIQUE
|
|
1343
|
+
-- `on conflict replace`, logical `unique (grp) on conflict replace`: the actions
|
|
1344
|
+
-- agree, so the key stays `proved` with zero advisories, and a duplicate `code`
|
|
1345
|
+
-- REPLACES via the basis UNIQUE (not ABORT). This is the documented remediation.
|
|
1346
|
+
-- ===================================
|
|
1347
|
+
|
|
1348
|
+
declare schema tca27_b {
|
|
1349
|
+
table t (
|
|
1350
|
+
id integer primary key,
|
|
1351
|
+
code integer not null unique on conflict replace check (code in (1, 2, 3))
|
|
1352
|
+
)
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
-- run
|
|
1356
|
+
|
|
1357
|
+
apply schema tca27_b;
|
|
1358
|
+
|
|
1359
|
+
-- run
|
|
1360
|
+
|
|
1361
|
+
declare logical schema tca27_x {
|
|
1362
|
+
table t (
|
|
1363
|
+
id integer primary key,
|
|
1364
|
+
grp integer not null check (grp in (1, 2, 3)),
|
|
1365
|
+
unique (grp) on conflict replace
|
|
1366
|
+
)
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
-- run
|
|
1370
|
+
|
|
1371
|
+
declare lens for tca27_x over tca27_b {
|
|
1372
|
+
view t as select id, code as grp from tca27_b.t
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
-- run
|
|
1376
|
+
|
|
1377
|
+
apply schema tca27_x;
|
|
1378
|
+
|
|
1379
|
+
-- run
|
|
1380
|
+
|
|
1381
|
+
-- Clean deploy: matching actions ⇒ proved transport, no advisories.
|
|
1382
|
+
select count(*) as n from quereus_lens_advisories('tca27_x');
|
|
1383
|
+
→ [{"n": 0}]
|
|
1384
|
+
|
|
1385
|
+
-- run
|
|
1386
|
+
|
|
1387
|
+
-- The write honors REPLACE through the basis UNIQUE: (2, 1) replaces (1, 1) on the
|
|
1388
|
+
-- duplicate code, leaving one basis row (the later id) rather than ABORTing.
|
|
1389
|
+
insert into tca27_x.t (id, grp) values (1, 1);
|
|
1390
|
+
insert into tca27_x.t (id, grp) values (2, 1);
|
|
1391
|
+
select id, code from tca27_b.t order by id;
|
|
1392
|
+
→ [{"id": 2, "code": 1}]
|
|
1393
|
+
|
|
1394
|
+
-- ===================================
|
|
1395
|
+
-- 28. PK transport variant. A logical PK over an authored-bijective column mapping to
|
|
1396
|
+
-- the basis PK is `proved` by transport — the basis PK governs a write-through.
|
|
1397
|
+
-- 28a: a logical PK `on conflict replace` over a plain-ABORT basis PK reds.
|
|
1398
|
+
-- ===================================
|
|
1399
|
+
|
|
1400
|
+
declare schema tca28a_b {
|
|
1401
|
+
table t (
|
|
1402
|
+
k integer primary key check (k in (1, 2, 3))
|
|
1403
|
+
)
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
-- run
|
|
1407
|
+
|
|
1408
|
+
apply schema tca28a_b;
|
|
1409
|
+
|
|
1410
|
+
-- run
|
|
1411
|
+
|
|
1412
|
+
declare logical schema tca28a_x {
|
|
1413
|
+
table t (
|
|
1414
|
+
n integer primary key on conflict replace check (n in (11, 12, 13))
|
|
1415
|
+
)
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
-- run
|
|
1419
|
+
|
|
1420
|
+
declare lens for tca28a_x over tca28a_b {
|
|
1421
|
+
view t as select k + 10 as n
|
|
1422
|
+
with inverse (k = new.n - 10)
|
|
1423
|
+
from tca28a_b.t
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
-- run
|
|
1427
|
+
|
|
1428
|
+
apply schema tca28a_x;
|
|
1429
|
+
-- error: lens.unenforceable-conflict-action
|
|
1430
|
+
|
|
1431
|
+
-- ===================================
|
|
1432
|
+
-- 28b. A matching basis PK action deploys clean — confirms the PK arm's positive case.
|
|
1433
|
+
-- ===================================
|
|
1434
|
+
|
|
1435
|
+
declare schema tca28b_b {
|
|
1436
|
+
table t (
|
|
1437
|
+
k integer primary key on conflict replace check (k in (1, 2, 3))
|
|
1438
|
+
)
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
-- run
|
|
1442
|
+
|
|
1443
|
+
apply schema tca28b_b;
|
|
1444
|
+
|
|
1445
|
+
-- run
|
|
1446
|
+
|
|
1447
|
+
declare logical schema tca28b_x {
|
|
1448
|
+
table t (
|
|
1449
|
+
n integer primary key on conflict replace check (n in (11, 12, 13))
|
|
1450
|
+
)
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
-- run
|
|
1454
|
+
|
|
1455
|
+
declare lens for tca28b_x over tca28b_b {
|
|
1456
|
+
view t as select k + 10 as n
|
|
1457
|
+
with inverse (k = new.n - 10)
|
|
1458
|
+
from tca28b_b.t
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
-- run
|
|
1462
|
+
|
|
1463
|
+
apply schema tca28b_x;
|
|
1464
|
+
|
|
1465
|
+
-- run
|
|
1466
|
+
|
|
1467
|
+
select count(*) as n from quereus_lens_advisories('tca28b_x');
|
|
1468
|
+
→ [{"n": 0}]
|