@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,378 @@
|
|
|
1
|
+
-- 06.3.4-view-info.sqllogic — view_info() per-view updateability surface.
|
|
2
|
+
-- The engine-idiomatic realization of docs/view-updateability.md
|
|
3
|
+
-- § Information Schema Surface (information_schema.views → view_info() TVF).
|
|
4
|
+
-- Columns: schema, name, is_insertable_into, is_updatable, is_deletable,
|
|
5
|
+
-- effective_targets (JSON array of base-table names). Values are 'YES'/'NO'.
|
|
6
|
+
|
|
7
|
+
-- ===================================================================
|
|
8
|
+
-- Identity single-source view: every column projected → fully mutable.
|
|
9
|
+
-- ===================================================================
|
|
10
|
+
|
|
11
|
+
create table t (id integer primary key, name text);
|
|
12
|
+
create view v_identity as select id, name from t;
|
|
13
|
+
|
|
14
|
+
select schema, name from view_info('v_identity');
|
|
15
|
+
→ [{"schema":"main","name":"v_identity"}]
|
|
16
|
+
|
|
17
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('v_identity');
|
|
18
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"t\"]"}]
|
|
19
|
+
|
|
20
|
+
-- ===================================================================
|
|
21
|
+
-- Rename projection: base lineage survives the alias rename.
|
|
22
|
+
-- ===================================================================
|
|
23
|
+
|
|
24
|
+
create view v_rename as select id as user_id, name as full_name from t;
|
|
25
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('v_rename');
|
|
26
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"t\"]"}]
|
|
27
|
+
|
|
28
|
+
-- ===================================================================
|
|
29
|
+
-- Projected-away PK: still updatable, but not deletable (no row identity)
|
|
30
|
+
-- and not insertable (the not-null PK has no recoverable value).
|
|
31
|
+
-- ===================================================================
|
|
32
|
+
|
|
33
|
+
create view v_no_pk as select name from t;
|
|
34
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('v_no_pk');
|
|
35
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"NO","effective_targets":"[\"t\"]"}]
|
|
36
|
+
|
|
37
|
+
-- ===================================================================
|
|
38
|
+
-- Constant-FD default for a PROJECTED-AWAY column: `country` is dropped by
|
|
39
|
+
-- the projection but pinned to 'US' by the selection predicate, so an insert
|
|
40
|
+
-- can recover it → insertable even though it is omitted.
|
|
41
|
+
-- ===================================================================
|
|
42
|
+
|
|
43
|
+
create table adults (name text primary key, age integer, country text);
|
|
44
|
+
create view adults_bare as select name, age from adults where country = 'US';
|
|
45
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('adults_bare');
|
|
46
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"adults\"]"}]
|
|
47
|
+
|
|
48
|
+
-- The crux, load-bearing: the projected-away pinned column is NOT NULL with no
|
|
49
|
+
-- declared default, so insertability hinges ENTIRELY on the whole-spine
|
|
50
|
+
-- constant-FD recovery (the pin lives on the Filter, below the projection that
|
|
51
|
+
-- drops the column). Without it, this would be 'NO' — contrast nn_unpinned below.
|
|
52
|
+
create table nn_adults (name text primary key, age integer, country text not null);
|
|
53
|
+
create view nn_pinned as select name, age from nn_adults where country = 'US';
|
|
54
|
+
select is_insertable_into, is_deletable, effective_targets from view_info('nn_pinned');
|
|
55
|
+
→ [{"is_insertable_into":"YES","is_deletable":"YES","effective_targets":"[\"nn_adults\"]"}]
|
|
56
|
+
|
|
57
|
+
-- Negative control: same not-null projected-away column, but UNPINNED (no
|
|
58
|
+
-- predicate) → no recoverable value → not insertable. Isolates the pin as the
|
|
59
|
+
-- sole cause of the 'YES' above.
|
|
60
|
+
create view nn_unpinned as select name, age from nn_adults;
|
|
61
|
+
select is_insertable_into, is_deletable, effective_targets from view_info('nn_unpinned');
|
|
62
|
+
→ [{"is_insertable_into":"NO","is_deletable":"YES","effective_targets":"[\"nn_adults\"]"}]
|
|
63
|
+
|
|
64
|
+
-- ===================================================================
|
|
65
|
+
-- Constant-FD default with `select *` (the column survives the projection).
|
|
66
|
+
-- ===================================================================
|
|
67
|
+
|
|
68
|
+
create table men (name text primary key, color text);
|
|
69
|
+
create view greenmen as select * from men where color = 'green';
|
|
70
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('greenmen');
|
|
71
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"men\"]"}]
|
|
72
|
+
|
|
73
|
+
-- ===================================================================
|
|
74
|
+
-- Declared base-column default survives projection: the omitted `name`
|
|
75
|
+
-- column has a DEFAULT, so it is not a not-null-without-default worry.
|
|
76
|
+
-- ===================================================================
|
|
77
|
+
|
|
78
|
+
create table u (id integer primary key, name text default 'unknown');
|
|
79
|
+
create view u_v as select id from u;
|
|
80
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('u_v');
|
|
81
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"u\"]"}]
|
|
82
|
+
|
|
83
|
+
-- ===================================================================
|
|
84
|
+
-- Not-null-without-default base column not projected → not insertable.
|
|
85
|
+
-- (`extra` is not projected, has no default, and no predicate pin.)
|
|
86
|
+
-- ===================================================================
|
|
87
|
+
|
|
88
|
+
create table req (id integer primary key, name text, extra text);
|
|
89
|
+
create view req_v as select id, name from req;
|
|
90
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('req_v');
|
|
91
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"req\"]"}]
|
|
92
|
+
|
|
93
|
+
-- ===================================================================
|
|
94
|
+
-- Correlated scalar subquery in the projection: the inner table is reached
|
|
95
|
+
-- only through a SCALAR child, never `getRelations()`, so it must NOT appear
|
|
96
|
+
-- in effective_targets nor rescue the outer not-null `req` via the whole-spine
|
|
97
|
+
-- defaultable walk (its base id is distinct and never an effective target).
|
|
98
|
+
-- Only the outer `subq_outer` is a target; `req` stays unrecoverable → NO.
|
|
99
|
+
-- ===================================================================
|
|
100
|
+
create table subq_outer (id integer primary key, req text not null);
|
|
101
|
+
create table subq_inner (k integer primary key, v text);
|
|
102
|
+
create view subq_v as
|
|
103
|
+
select id, (select v from subq_inner where k = id) as note from subq_outer;
|
|
104
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('subq_v');
|
|
105
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"subq_outer\"]"}]
|
|
106
|
+
|
|
107
|
+
-- ===================================================================
|
|
108
|
+
-- Computed-only body: a non-invertible expression → wholly read-only.
|
|
109
|
+
-- ===================================================================
|
|
110
|
+
|
|
111
|
+
create view computed_v as select name || '!' as banner from t;
|
|
112
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('computed_v');
|
|
113
|
+
→ [{"is_insertable_into":"NO","is_updatable":"NO","is_deletable":"NO","effective_targets":"[]"}]
|
|
114
|
+
|
|
115
|
+
-- ===================================================================
|
|
116
|
+
-- VALUES body: no base-table lineage → wholly read-only.
|
|
117
|
+
-- ===================================================================
|
|
118
|
+
|
|
119
|
+
create view values_v as values (1, 2), (3, 4);
|
|
120
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('values_v');
|
|
121
|
+
→ [{"is_insertable_into":"NO","is_updatable":"NO","is_deletable":"NO","effective_targets":"[]"}]
|
|
122
|
+
|
|
123
|
+
-- ===================================================================
|
|
124
|
+
-- Aggregate body: aggregate output is read-only at the column level.
|
|
125
|
+
-- ===================================================================
|
|
126
|
+
|
|
127
|
+
create view agg_v as select count(*) as n from t;
|
|
128
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('agg_v');
|
|
129
|
+
→ [{"is_insertable_into":"NO","is_updatable":"NO","is_deletable":"NO","effective_targets":"[]"}]
|
|
130
|
+
|
|
131
|
+
-- ===================================================================
|
|
132
|
+
-- Recursive-CTE body: read-only; no recoverable base lineage.
|
|
133
|
+
-- ===================================================================
|
|
134
|
+
|
|
135
|
+
create view rec_v as
|
|
136
|
+
with recursive c(n) as (select 1 union all select n + 1 from c where n < 3)
|
|
137
|
+
select n from c;
|
|
138
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('rec_v');
|
|
139
|
+
→ [{"is_insertable_into":"NO","is_updatable":"NO","is_deletable":"NO","effective_targets":"[]"}]
|
|
140
|
+
|
|
141
|
+
-- ===================================================================
|
|
142
|
+
-- Multi-source key-preserving inner join: both base tables are effective
|
|
143
|
+
-- targets and the view is updatable; but the parent PK (pid) is hidden by
|
|
144
|
+
-- the projection → not deletable at every base, and the child's not-null
|
|
145
|
+
-- `pref` is unrecoverable → not insertable. (per-base rules)
|
|
146
|
+
-- ===================================================================
|
|
147
|
+
|
|
148
|
+
create table ms_parent (pid integer primary key, label text);
|
|
149
|
+
create table ms_child (cid integer primary key, pref integer, note text,
|
|
150
|
+
foreign key (pref) references ms_parent(pid));
|
|
151
|
+
create view ms_jv as
|
|
152
|
+
select c.cid as cid, c.note as note, p.label as label
|
|
153
|
+
from ms_child c join ms_parent p on p.pid = c.pref;
|
|
154
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('ms_jv');
|
|
155
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"NO","effective_targets":"[\"ms_child\",\"ms_parent\"]"}]
|
|
156
|
+
|
|
157
|
+
-- Surface agrees with propagate(): the two-table inner equi-join accepts a write
|
|
158
|
+
-- (the positive control for the Divergence 3 shape gate below — isDecomposableJoinBody
|
|
159
|
+
-- keeps this exact shape writable, unlike the cross / > 2-table shapes). No row
|
|
160
|
+
-- matches, so the routed base update is a clean no-op rather than an error.
|
|
161
|
+
update ms_jv set note = 'x' where cid = 999;
|
|
162
|
+
|
|
163
|
+
-- ===================================================================
|
|
164
|
+
-- Multi-source inner join exposing an INVERSE-profile column (`nv1 = c.nv + 1`):
|
|
165
|
+
-- still is_updatable='YES' (its `base`-with-`inverse` site is writable, like any
|
|
166
|
+
-- base site), effective_targets both bases. Same per-base shape as ms_jv: the
|
|
167
|
+
-- parent PK is hidden → not deletable at every base, and the child's not-null
|
|
168
|
+
-- `pref` is unrecoverable → not insertable (the inverse column is not insertable
|
|
169
|
+
-- through the multi-source envelope, but `pref` already forces NO here). The
|
|
170
|
+
-- multi-source UPDATE path consumes the inverse — see column_info goldens for the
|
|
171
|
+
-- per-column write. docs § Scalar Invertibility, § Inner Join.
|
|
172
|
+
-- ===================================================================
|
|
173
|
+
|
|
174
|
+
create table iv_parent (pid integer primary key, label text);
|
|
175
|
+
create table iv_child (cid integer primary key, pref integer, nv integer,
|
|
176
|
+
foreign key (pref) references iv_parent(pid));
|
|
177
|
+
create view iv_jv as
|
|
178
|
+
select c.cid as cid, c.nv + 1 as nv1, p.label as label
|
|
179
|
+
from iv_child c join iv_parent p on p.pid = c.pref;
|
|
180
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets from view_info('iv_jv');
|
|
181
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"NO","effective_targets":"[\"iv_child\",\"iv_parent\"]"}]
|
|
182
|
+
|
|
183
|
+
-- ===================================================================
|
|
184
|
+
-- Divergence 1 — a view-declared insert default rescues insertability. `created`
|
|
185
|
+
-- is a not-null, no-declared-default base column projected away by the view; the
|
|
186
|
+
-- `with defaults (created = …)` clause recovers it → insertable. The default
|
|
187
|
+
-- provenance is never threaded onto the physical surface (consumed only in the
|
|
188
|
+
-- rewrite), so deriveViewInfo folds the view's declared defaults in directly.
|
|
189
|
+
-- Cross-checked by a real insert through the view — the dynamic truth the
|
|
190
|
+
-- surface now matches.
|
|
191
|
+
-- ===================================================================
|
|
192
|
+
|
|
193
|
+
create table dfi (id integer primary key, name text, created integer not null);
|
|
194
|
+
create view dfi_v as select id, name from dfi with defaults (created = 999);
|
|
195
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
196
|
+
from view_info('dfi_v');
|
|
197
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"dfi\"]"}]
|
|
198
|
+
|
|
199
|
+
-- The omitted not-null column is supplied by the declared default at insert time.
|
|
200
|
+
insert into dfi_v (id, name) values (1, 'x');
|
|
201
|
+
select * from dfi order by id;
|
|
202
|
+
→ [{"id":1,"name":"x","created":999}]
|
|
203
|
+
|
|
204
|
+
-- Negative control: same table+view shape WITHOUT a declared default → not
|
|
205
|
+
-- insertable (isolates the clause as the sole cause of the YES above).
|
|
206
|
+
create view dfi_v_nodefault as select id, name from dfi;
|
|
207
|
+
select is_insertable_into from view_info('dfi_v_nodefault');
|
|
208
|
+
→ [{"is_insertable_into":"NO"}]
|
|
209
|
+
|
|
210
|
+
-- An unresolvable insert-default name (a typo) is silently skipped, NOT raised: a
|
|
211
|
+
-- read-only introspection surface stays conservative (the column simply does
|
|
212
|
+
-- not contribute insertability). The not-null `created` is still unrecovered → NO.
|
|
213
|
+
-- (At write time the same name is a hard sited error — see 93.4.)
|
|
214
|
+
create view dfi_v_typo as select id, name from dfi with defaults (nope = 0);
|
|
215
|
+
select is_insertable_into from view_info('dfi_v_typo');
|
|
216
|
+
→ [{"is_insertable_into":"NO"}]
|
|
217
|
+
|
|
218
|
+
-- ===================================================================
|
|
219
|
+
-- Divergence 2 — outer-join bodies report PER-SIDE and agree with propagate().
|
|
220
|
+
-- A LEFT (or RIGHT) outer join is partially writable: the preserved side's columns are
|
|
221
|
+
-- base-updatable, the view is insertable (preserved-only / both-side routing) and
|
|
222
|
+
-- deletable (delete-to-preserved). The non-preserved (`null-extended`) side's columns are
|
|
223
|
+
-- now ALSO updatable (the matched-update / null-extended-insert materialization keyed off
|
|
224
|
+
-- the preserved anchor — `view-write-optional-member-transitions`), so the view-level
|
|
225
|
+
-- is_updatable stays YES. RIGHT is the exact mirror of LEFT (the right operand is the
|
|
226
|
+
-- preserved side) and the runtime now executes it (outer-join-right-full-runtime), so it
|
|
227
|
+
-- is re-admitted (view-write-right-join-readmit). FULL stays conservative all-`NO`: it has
|
|
228
|
+
-- no preserved side, hence no anchor to materialize off, so every write rejects.
|
|
229
|
+
-- ===================================================================
|
|
230
|
+
|
|
231
|
+
create table oj_a (aid integer primary key, av text);
|
|
232
|
+
create table oj_b (bid integer primary key, bv text);
|
|
233
|
+
insert into oj_a values (1, 'a1');
|
|
234
|
+
|
|
235
|
+
-- LEFT: oj_a preserved, oj_b non-preserved. aid/av updatable; the view is
|
|
236
|
+
-- insertable (preserved-only insert always works — oj_a's PK is projected) and
|
|
237
|
+
-- deletable (delete routes to oj_a, whose PK is exposed). Both bases are effective
|
|
238
|
+
-- targets (a both-side insert reaches oj_b).
|
|
239
|
+
create view oj_left as
|
|
240
|
+
select a.aid as aid, a.av as av, b.bv as bv
|
|
241
|
+
from oj_a a left join oj_b b on b.bid = a.aid;
|
|
242
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
243
|
+
from view_info('oj_left');
|
|
244
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"oj_a\",\"oj_b\"]"}]
|
|
245
|
+
|
|
246
|
+
-- Surface agrees with propagate(): a preserved-side update is accepted, and a
|
|
247
|
+
-- non-preserved-side update is now accepted too — aid=1 has no oj_b match, so this
|
|
248
|
+
-- materializes oj_b(bid=1, bv='z') via the EC join key (bid = aid) and the row reads
|
|
249
|
+
-- back joined.
|
|
250
|
+
update oj_left set av = 'z' where aid = 1;
|
|
251
|
+
update oj_left set bv = 'z' where aid = 1;
|
|
252
|
+
select aid, av, bv from oj_left where aid = 1;
|
|
253
|
+
→ [{"aid":1,"av":"z","bv":"z"}]
|
|
254
|
+
|
|
255
|
+
-- RIGHT: oj_b is preserved (the right operand of a `right` join), oj_a is non-preserved
|
|
256
|
+
-- (null-extended) — the exact mirror of oj_left above. bid/bv (oj_b) are base-updatable;
|
|
257
|
+
-- the preserved PK `bid` is projected, so the view is insertable (preserved-only /
|
|
258
|
+
-- both-side routing) and deletable (delete routes to oj_b). The non-preserved `av` (oj_a)
|
|
259
|
+
-- is updatable too (matched-update / null-extended-insert materialization keyed off the
|
|
260
|
+
-- preserved oj_b anchor). Both bases are effective targets (a both-side insert reaches
|
|
261
|
+
-- oj_a). The runtime now executes a RIGHT join (outer-join-right-full-runtime) and
|
|
262
|
+
-- write-through recognition admits it (view-write-right-join-readmit).
|
|
263
|
+
create view oj_right as
|
|
264
|
+
select a.av as av, b.bid as bid, b.bv as bv
|
|
265
|
+
from oj_a a right join oj_b b on b.bid = a.aid;
|
|
266
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
267
|
+
from view_info('oj_right');
|
|
268
|
+
→ [{"is_insertable_into":"YES","is_updatable":"YES","is_deletable":"YES","effective_targets":"[\"oj_a\",\"oj_b\"]"}]
|
|
269
|
+
|
|
270
|
+
-- Surface agrees with propagate(): both a preserved-side (oj_b) update and a
|
|
271
|
+
-- non-preserved-side (oj_a) update are accepted. Seed a preserved oj_b row whose bid has
|
|
272
|
+
-- no matching oj_a (bid=2; oj_a only has aid=1), so updating the preserved `bv` writes
|
|
273
|
+
-- oj_b directly, while updating the non-preserved `av` materializes oj_a(aid=2, av='zz')
|
|
274
|
+
-- via the EC join key (aid = bid) — the exact mirror of oj_left's `set bv` above.
|
|
275
|
+
insert into oj_b values (2, 'b2');
|
|
276
|
+
update oj_right set bv = 'zz' where bid = 2;
|
|
277
|
+
update oj_right set av = 'zz' where bid = 2;
|
|
278
|
+
select av, bid, bv from oj_right where bid = 2;
|
|
279
|
+
→ [{"av":"zz","bid":2,"bv":"zz"}]
|
|
280
|
+
|
|
281
|
+
-- FULL: every side null-extended ⇒ no preserved anchor ⇒ conservative all-`NO`. FULL is
|
|
282
|
+
-- still gated (no preserved anchor); RIGHT is now admitted (view-write-right-join-readmit).
|
|
283
|
+
create view oj_full as
|
|
284
|
+
select a.aid as aid, a.av as av, b.bid as bid, b.bv as bv
|
|
285
|
+
from oj_a a full join oj_b b on b.bid = a.aid;
|
|
286
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
287
|
+
from view_info('oj_full');
|
|
288
|
+
→ [{"is_insertable_into":"NO","is_updatable":"NO","is_deletable":"NO","effective_targets":"[]"}]
|
|
289
|
+
|
|
290
|
+
-- Surface agrees with propagate(): a write through the full-outer view is deferred.
|
|
291
|
+
update oj_full set av = 'z' where aid = 1;
|
|
292
|
+
-- error: cannot write through view
|
|
293
|
+
|
|
294
|
+
-- ===================================================================
|
|
295
|
+
-- Divergence 3 — non-inner join bodies report conservative and agree with
|
|
296
|
+
-- propagate(). A cross join (and a comma/implicit join) never null-extends (only
|
|
297
|
+
-- LEFT/RIGHT/FULL do — deriveJoinUpdateLineage), so it carries strict-`base`
|
|
298
|
+
-- lineage and slips past the Divergence-2 outer-join gate above. Without the AST
|
|
299
|
+
-- shape gate (isJoinBody && !isDecomposableJoinBody) deriveViewInfo would resolve
|
|
300
|
+
-- its bases and over-report is_updatable='YES'. propagate() rejects a cross join
|
|
301
|
+
-- (collectInnerJoinSources requires an ON/USING predicate), so the surface must
|
|
302
|
+
-- report the conservative all-`NO`/`[]` row — cross-checked below against a real
|
|
303
|
+
-- (rejected) mutation.
|
|
304
|
+
--
|
|
305
|
+
-- n-way (≥2) inner equi-joins — composite-PK sides and self-joins included — are
|
|
306
|
+
-- now DECOMPOSABLE (isDecomposableJoinBody accepts them), so they report writable
|
|
307
|
+
-- and agree with propagate() accepting the write (covered after the cross join).
|
|
308
|
+
--
|
|
309
|
+
-- Comma / implicit join bodies are NOT tested here: a multi-source comma FROM
|
|
310
|
+
-- never produces a buildable view — with aliases (from a x, b y) it is a parse
|
|
311
|
+
-- error, and without aliases the select builder rejects multiple FROM sources —
|
|
312
|
+
-- so such a body is never introspected with base lineage; there is no buildable
|
|
313
|
+
-- case. The shape gate still covers it defensively (isDecomposableJoinBody
|
|
314
|
+
-- requires a single JOIN FROM), so it stays conservative if that ever becomes
|
|
315
|
+
-- plannable.
|
|
316
|
+
-- ===================================================================
|
|
317
|
+
|
|
318
|
+
create table xj_a (aid integer primary key, av text);
|
|
319
|
+
create table xj_b (bid integer primary key, bv text);
|
|
320
|
+
create table xj_c (cid integer primary key, cv text);
|
|
321
|
+
|
|
322
|
+
-- Cross join (two-table, no ON): strict-`base` lineage, but unwritable.
|
|
323
|
+
create view xj_cross as
|
|
324
|
+
select a.aid as aid, a.av as av, b.bv as bv
|
|
325
|
+
from xj_a a cross join xj_b b;
|
|
326
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
327
|
+
from view_info('xj_cross');
|
|
328
|
+
→ [{"is_insertable_into":"NO","is_updatable":"NO","is_deletable":"NO","effective_targets":"[]"}]
|
|
329
|
+
|
|
330
|
+
-- Surface agrees with propagate(): a write through the cross-join view is rejected.
|
|
331
|
+
update xj_cross set av = 'z' where aid = 1;
|
|
332
|
+
-- error: cannot write through view
|
|
333
|
+
|
|
334
|
+
-- Three-table inner join (> 2 base tables): now decomposable ⇒ updatable, with all
|
|
335
|
+
-- three bases in effective_targets. Not deletable (xj_b/xj_c PKs are not projected,
|
|
336
|
+
-- so a per-base row identity is not constructible from the view image) and not
|
|
337
|
+
-- insertable (their not-null PKs are unrecoverable). Agrees with propagate().
|
|
338
|
+
create view xj_three as
|
|
339
|
+
select a.aid as aid, a.av as av, b.bv as bv, c.cv as cv
|
|
340
|
+
from xj_a a join xj_b b on b.bid = a.aid join xj_c c on c.cid = a.aid;
|
|
341
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
342
|
+
from view_info('xj_three');
|
|
343
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"NO","effective_targets":"[\"xj_a\",\"xj_b\",\"xj_c\"]"}]
|
|
344
|
+
|
|
345
|
+
-- Surface agrees with propagate(): a write through the 3-table-join view is accepted
|
|
346
|
+
-- (no row matches the empty bases, so it is a clean no-op rather than an error).
|
|
347
|
+
update xj_three set av = 'z' where aid = 1;
|
|
348
|
+
|
|
349
|
+
-- Self-join (two alias-bound sites on one table): now decomposable ⇒ updatable. Both
|
|
350
|
+
-- aliases resolve to xj_a, so effective_targets collapses to the single base name.
|
|
351
|
+
-- Not deletable (alias b's PK `aid` is not exposed — only b.av is projected) and not
|
|
352
|
+
-- insertable (b's not-null PK is unrecoverable). Agrees with propagate() accepting.
|
|
353
|
+
create view xj_self as
|
|
354
|
+
select a.aid as aid, a.av as av, b.av as av2
|
|
355
|
+
from xj_a a join xj_a b on b.aid = a.aid;
|
|
356
|
+
select is_insertable_into, is_updatable, is_deletable, effective_targets
|
|
357
|
+
from view_info('xj_self');
|
|
358
|
+
→ [{"is_insertable_into":"NO","is_updatable":"YES","is_deletable":"NO","effective_targets":"[\"xj_a\"]"}]
|
|
359
|
+
|
|
360
|
+
-- Surface agrees with propagate(): a write through the self-join view is accepted
|
|
361
|
+
-- (empty base ⇒ clean no-op).
|
|
362
|
+
update xj_self set av = 'z' where aid = 1;
|
|
363
|
+
|
|
364
|
+
-- ===================================================================
|
|
365
|
+
-- Name filter vs. full enumeration.
|
|
366
|
+
-- ===================================================================
|
|
367
|
+
|
|
368
|
+
-- A name filter returns exactly the one matching row.
|
|
369
|
+
select count(*) as c from view_info('ms_jv');
|
|
370
|
+
→ [{"c":1}]
|
|
371
|
+
|
|
372
|
+
-- An unknown name filter returns nothing.
|
|
373
|
+
select count(*) as c from view_info('does_not_exist');
|
|
374
|
+
→ [{"c":0}]
|
|
375
|
+
|
|
376
|
+
-- The 0-arg form enumerates every view (spot-check two distinct names).
|
|
377
|
+
select name from view_info() where name in ('v_identity', 'ms_jv') order by name;
|
|
378
|
+
→ [{"name":"ms_jv"},{"name":"v_identity"}]
|