@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,329 @@
|
|
|
1
|
+
-- Scope-aware reference analysis for GENERATED ALWAYS AS expressions.
|
|
2
|
+
--
|
|
3
|
+
-- A name in a generated expression resolves against the table being defined unless a
|
|
4
|
+
-- FROM clause inside the expression binds it — the same rule a CHECK constraint
|
|
5
|
+
-- follows. The dependency analysis (extractGeneratedColumnDependencies) and the ALTER
|
|
6
|
+
-- ADD COLUMN pre-flight (validateAddColumnGeneratedRefs) share one scope-aware
|
|
7
|
+
-- collector (src/schema/generated-column-refs.ts), so a subquery's own FROM sources
|
|
8
|
+
-- bind their columns and the owning table neither falsely rejects the name nor
|
|
9
|
+
-- records a false dependency edge. Genuine typos and genuine cycles still raise the
|
|
10
|
+
-- same errors as before.
|
|
11
|
+
|
|
12
|
+
-- ===================================
|
|
13
|
+
-- 1. Subquery over another table, inner name UNQUALIFIED — accepted, correct value.
|
|
14
|
+
-- (Previously: "Column 'v' referenced by generated column 'g' not found in table 't'".)
|
|
15
|
+
-- ===================================
|
|
16
|
+
|
|
17
|
+
create table d (k integer primary key, v integer);
|
|
18
|
+
insert into d values (1, 42);
|
|
19
|
+
|
|
20
|
+
create table t (
|
|
21
|
+
id integer primary key,
|
|
22
|
+
g integer generated always as ((select v from d where d.k = id limit 1))
|
|
23
|
+
);
|
|
24
|
+
insert into t (id) values (1);
|
|
25
|
+
|
|
26
|
+
select id, g from t;
|
|
27
|
+
→ [{"id":1,"g":42}]
|
|
28
|
+
|
|
29
|
+
drop table t;
|
|
30
|
+
drop table d;
|
|
31
|
+
|
|
32
|
+
-- ===================================
|
|
33
|
+
-- 2. Two generated columns each reading ANOTHER table's like-named column —
|
|
34
|
+
-- no false cycle, both values correct.
|
|
35
|
+
-- ===================================
|
|
36
|
+
|
|
37
|
+
create table d2 (k integer primary key, w integer, g integer);
|
|
38
|
+
insert into d2 values (1, 10, 20);
|
|
39
|
+
|
|
40
|
+
create table t2 (
|
|
41
|
+
id integer primary key,
|
|
42
|
+
w integer generated always as ((select g from d2 where d2.k = id limit 1)),
|
|
43
|
+
g integer generated always as ((select w from d2 where d2.k = id limit 1))
|
|
44
|
+
);
|
|
45
|
+
insert into t2 (id) values (1);
|
|
46
|
+
|
|
47
|
+
select id, w, g from t2;
|
|
48
|
+
→ [{"id":1,"w":20,"g":10}]
|
|
49
|
+
|
|
50
|
+
drop table t2;
|
|
51
|
+
drop table d2;
|
|
52
|
+
|
|
53
|
+
-- ===================================
|
|
54
|
+
-- 3. Generated column whose subquery selects another table's column with the SAME
|
|
55
|
+
-- name as itself — no false self-cycle.
|
|
56
|
+
-- ===================================
|
|
57
|
+
|
|
58
|
+
create table l0 (k integer primary key, g integer);
|
|
59
|
+
insert into l0 values (1, 7);
|
|
60
|
+
|
|
61
|
+
create table l1 (
|
|
62
|
+
id integer primary key,
|
|
63
|
+
g integer generated always as ((select g from l0 where l0.k = id limit 1))
|
|
64
|
+
);
|
|
65
|
+
insert into l1 (id) values (1);
|
|
66
|
+
|
|
67
|
+
select id, g from l1;
|
|
68
|
+
→ [{"id":1,"g":7}]
|
|
69
|
+
|
|
70
|
+
drop table l1;
|
|
71
|
+
drop table l0;
|
|
72
|
+
|
|
73
|
+
-- ===================================
|
|
74
|
+
-- 4. Common table expression binds the inner name — accepted.
|
|
75
|
+
-- ===================================
|
|
76
|
+
|
|
77
|
+
create table j1 (
|
|
78
|
+
id integer primary key,
|
|
79
|
+
g integer generated always as ((with c(v) as (select 7) select v from c))
|
|
80
|
+
);
|
|
81
|
+
insert into j1 (id) values (1);
|
|
82
|
+
|
|
83
|
+
select id, g from j1;
|
|
84
|
+
→ [{"id":1,"g":7}]
|
|
85
|
+
|
|
86
|
+
drop table j1;
|
|
87
|
+
|
|
88
|
+
-- ===================================
|
|
89
|
+
-- 5. Aliased self source: the alias binds the subquery's FROM, so the inner bare `a`
|
|
90
|
+
-- is that source's column, not the row being computed. Nullable because the
|
|
91
|
+
-- subquery finds no row while the table is still empty.
|
|
92
|
+
-- ===================================
|
|
93
|
+
|
|
94
|
+
create table s1 (
|
|
95
|
+
id integer primary key,
|
|
96
|
+
a integer,
|
|
97
|
+
g integer null generated always as ((select a from s1 x where x.id = 1 limit 1))
|
|
98
|
+
);
|
|
99
|
+
insert into s1 (id, a) values (1, 5);
|
|
100
|
+
insert into s1 (id, a) values (2, 6);
|
|
101
|
+
|
|
102
|
+
select id, g from s1 order by id;
|
|
103
|
+
→ [{"id":1,"g":null},{"id":2,"g":5}]
|
|
104
|
+
|
|
105
|
+
drop table s1;
|
|
106
|
+
|
|
107
|
+
-- ===================================
|
|
108
|
+
-- 6. A real table named "new": the FROM binding wins over the row-image reading
|
|
109
|
+
-- (`new` is not a reserved word).
|
|
110
|
+
-- ===================================
|
|
111
|
+
|
|
112
|
+
create table "new" (a integer primary key);
|
|
113
|
+
insert into "new" values (3);
|
|
114
|
+
|
|
115
|
+
create table tn (
|
|
116
|
+
id integer primary key,
|
|
117
|
+
g integer generated always as ((select max("new".a) from "new"))
|
|
118
|
+
);
|
|
119
|
+
insert into tn (id) values (1);
|
|
120
|
+
|
|
121
|
+
select id, g from tn;
|
|
122
|
+
→ [{"id":1,"g":3}]
|
|
123
|
+
|
|
124
|
+
drop table tn;
|
|
125
|
+
drop table "new";
|
|
126
|
+
|
|
127
|
+
-- ===================================
|
|
128
|
+
-- 7. Subquery over the table's OWN pre-insert rows — the in-flight column set
|
|
129
|
+
-- answers for the table before the catalog holds it. Nullable: the subquery
|
|
130
|
+
-- sees no rows while inserting the first one.
|
|
131
|
+
-- ===================================
|
|
132
|
+
|
|
133
|
+
create table own1 (
|
|
134
|
+
id integer primary key,
|
|
135
|
+
g integer null generated always as ((select max(id) from own1))
|
|
136
|
+
);
|
|
137
|
+
insert into own1 (id) values (5);
|
|
138
|
+
|
|
139
|
+
select id, g from own1;
|
|
140
|
+
→ [{"id":5,"g":null}]
|
|
141
|
+
|
|
142
|
+
drop table own1;
|
|
143
|
+
|
|
144
|
+
-- ===================================
|
|
145
|
+
-- 8. Dependency edges survive the scope awareness: an unrebound `new.<col>` and a
|
|
146
|
+
-- schema-qualified self reference both bind the owning row, so DROP COLUMN of the
|
|
147
|
+
-- referenced column is still refused.
|
|
148
|
+
-- ===================================
|
|
149
|
+
|
|
150
|
+
create table tnew (id integer primary key, a integer, g integer generated always as (new.a * 2));
|
|
151
|
+
alter table tnew drop column a;
|
|
152
|
+
-- error: Cannot drop column 'a' from 'tnew': it is referenced by generated column 'g'
|
|
153
|
+
drop table tnew;
|
|
154
|
+
|
|
155
|
+
create table sq3 (id integer primary key, a integer, g integer generated always as (main.sq3.a + 1));
|
|
156
|
+
alter table sq3 drop column a;
|
|
157
|
+
-- error: Cannot drop column 'a' from 'sq3': it is referenced by generated column 'g'
|
|
158
|
+
drop table sq3;
|
|
159
|
+
|
|
160
|
+
-- A qualifier naming ANOTHER schema is not a self reference even though the bare
|
|
161
|
+
-- names collide — and nothing else binds it either, so CREATE TABLE rejects the
|
|
162
|
+
-- declaration up front (see 41-generated-column-errors.sqllogic § 4).
|
|
163
|
+
create table sqm (id integer primary key, a integer, g integer generated always as ("temp".sqm.a + 1));
|
|
164
|
+
-- error: binds nothing
|
|
165
|
+
|
|
166
|
+
-- ===================================
|
|
167
|
+
-- 9. The name a subquery's FROM binds is a reference to THAT table, so the
|
|
168
|
+
-- cross-table column guards see it: dropping the referenced column is refused,
|
|
169
|
+
-- and renaming it rewrites the generated body (the value still computes).
|
|
170
|
+
-- ===================================
|
|
171
|
+
|
|
172
|
+
create table dref (k integer primary key, v integer);
|
|
173
|
+
insert into dref values (1, 42);
|
|
174
|
+
create table tref (id integer primary key, g integer generated always as ((select v from dref where dref.k = id limit 1)));
|
|
175
|
+
|
|
176
|
+
alter table dref drop column v;
|
|
177
|
+
-- error: Cannot drop column 'v' from 'dref': it is referenced by the GENERATED expression of column 'g' on table 'tref'
|
|
178
|
+
|
|
179
|
+
alter table dref rename column v to v2;
|
|
180
|
+
-- run
|
|
181
|
+
|
|
182
|
+
insert into tref (id) values (1);
|
|
183
|
+
select id, g from tref;
|
|
184
|
+
→ [{"id":1,"g":42}]
|
|
185
|
+
|
|
186
|
+
drop table tref;
|
|
187
|
+
drop table dref;
|
|
188
|
+
|
|
189
|
+
-- ===================================
|
|
190
|
+
-- 10. An inner name that ALSO names a column of the table being defined belongs to
|
|
191
|
+
-- the subquery's source — analysis and evaluation agree on that reading.
|
|
192
|
+
-- ===================================
|
|
193
|
+
|
|
194
|
+
create table dsh (k integer primary key, id integer);
|
|
195
|
+
insert into dsh values (1, 99);
|
|
196
|
+
|
|
197
|
+
create table tsh (id integer primary key);
|
|
198
|
+
insert into tsh values (1);
|
|
199
|
+
alter table tsh add column h integer generated always as ((select id from dsh where dsh.k = 1 limit 1));
|
|
200
|
+
-- run
|
|
201
|
+
|
|
202
|
+
insert into tsh (id) values (7);
|
|
203
|
+
select id, h from tsh order by id;
|
|
204
|
+
→ [{"id":1,"h":99},{"id":7,"h":99}]
|
|
205
|
+
|
|
206
|
+
drop table tsh;
|
|
207
|
+
drop table dsh;
|
|
208
|
+
|
|
209
|
+
-- ===================================
|
|
210
|
+
-- 11. Negative arms — genuine mistakes still raise the original messages.
|
|
211
|
+
-- ===================================
|
|
212
|
+
|
|
213
|
+
create table n1 (id integer primary key, g integer generated always as (nosuch + 1));
|
|
214
|
+
-- error: Column 'nosuch' referenced by generated column 'g' not found in table 'n1'
|
|
215
|
+
|
|
216
|
+
-- A typo INSIDE a subquery whose FROM does not expose the name is still a typo.
|
|
217
|
+
create table dz (k integer primary key);
|
|
218
|
+
create table nz (id integer primary key, g integer generated always as ((select nosuch from dz limit 1)));
|
|
219
|
+
-- error: Column 'nosuch' referenced by generated column 'g' not found in table 'nz'
|
|
220
|
+
drop table dz;
|
|
221
|
+
|
|
222
|
+
create table n2 (id integer primary key);
|
|
223
|
+
alter table n2 add column g integer generated always as (g + 1);
|
|
224
|
+
-- error: Cyclic dependency in generated columns: 'g'
|
|
225
|
+
drop table n2;
|
|
226
|
+
|
|
227
|
+
create table n3 (
|
|
228
|
+
id integer primary key,
|
|
229
|
+
a integer generated always as (b + 1),
|
|
230
|
+
b integer generated always as (a + 1)
|
|
231
|
+
);
|
|
232
|
+
-- error: Cyclic dependency in generated columns
|
|
233
|
+
|
|
234
|
+
-- An unrebound `new.` names the row being computed, so an unknown name behind it is a
|
|
235
|
+
-- typo like any other. (Behavior change: this was accepted at DDL time before the
|
|
236
|
+
-- scope-aware analysis and only failed at the first write.)
|
|
237
|
+
create table n4 (id integer primary key, g integer generated always as (new.nosuch + 1));
|
|
238
|
+
-- error: Column 'nosuch' referenced by generated column 'g' not found in table 'n4'
|
|
239
|
+
|
|
240
|
+
-- ===================================
|
|
241
|
+
-- 12. An unbound qualifier reached only through an OPAQUE frame (a derived
|
|
242
|
+
-- table's body) is undecidable, not rejected. The walk cannot see what such
|
|
243
|
+
-- a body binds, so it defers rather than refusing a declaration it cannot
|
|
244
|
+
-- prove wrong — contrast 41-generated-column-errors.sqllogic § 4, where no
|
|
245
|
+
-- opaque frame intervenes and CREATE TABLE rejects up front. Documented
|
|
246
|
+
-- residual (see the NOTE in src/schema/generated-column-refs.ts): the
|
|
247
|
+
-- declaration is accepted and the first write is what reports the name.
|
|
248
|
+
-- ===================================
|
|
249
|
+
|
|
250
|
+
create table dop (k integer primary key, v integer);
|
|
251
|
+
|
|
252
|
+
create table sop (
|
|
253
|
+
id integer primary key,
|
|
254
|
+
a integer,
|
|
255
|
+
g integer generated always as ((select y from (select zz.v as y from dop) s limit 1))
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
drop table sop;
|
|
259
|
+
drop table dop;
|
|
260
|
+
|
|
261
|
+
-- ===================================
|
|
262
|
+
-- 13. Each leg of a compound builds its OWN FROM scope: a bare name in the second
|
|
263
|
+
-- leg is NOT captured by the first leg's sources. Here `cs_src` exposes a
|
|
264
|
+
-- column named `b` and the second leg's source does not, so the second leg's
|
|
265
|
+
-- bare `b` binds the row being computed — which means `g` depends on `b` and
|
|
266
|
+
-- must be computed after it. `g` is declared FIRST, so declaration order alone
|
|
267
|
+
-- would compute it while `b` is still null; only the recorded dependency edge
|
|
268
|
+
-- gets the right value. (Before the compound legs were split out of the
|
|
269
|
+
-- leading leg's frame, `b` read as `cs_src`'s column, no edge was recorded,
|
|
270
|
+
-- `g` computed against `b`'s NULL placeholder, and the insert failed
|
|
271
|
+
-- `NOT NULL constraint failed: cs.g` — verified by reverting the split.)
|
|
272
|
+
-- ===================================
|
|
273
|
+
|
|
274
|
+
create table cs_src (k integer primary key, b integer);
|
|
275
|
+
insert into cs_src values (1, 999);
|
|
276
|
+
|
|
277
|
+
create table cs_probe (k integer primary key);
|
|
278
|
+
insert into cs_probe values (1);
|
|
279
|
+
|
|
280
|
+
create table cs (
|
|
281
|
+
id integer primary key,
|
|
282
|
+
g integer generated always as ((select b from cs_src where 1 = 0 union all select b from cs_probe where k = 1)),
|
|
283
|
+
b integer generated always as (id * 10)
|
|
284
|
+
);
|
|
285
|
+
insert into cs (id) values (7);
|
|
286
|
+
|
|
287
|
+
select id, g, b from cs;
|
|
288
|
+
→ [{"id":7,"g":70,"b":70}]
|
|
289
|
+
|
|
290
|
+
drop table cs;
|
|
291
|
+
drop table cs_probe;
|
|
292
|
+
drop table cs_src;
|
|
293
|
+
|
|
294
|
+
-- ===================================
|
|
295
|
+
-- 14. View write-through metadata inside a generated body records NO dependency
|
|
296
|
+
-- edge. `with inverse (…)` on a result column and a trailing `with defaults (…)`
|
|
297
|
+
-- are evaluated against the row written THROUGH A VIEW — an inverse expression
|
|
298
|
+
-- may only name that select's OWN output columns as `new.<column>` — so nothing
|
|
299
|
+
-- in them can name the row being computed here, and in a read-only generated
|
|
300
|
+
-- body they are never evaluated at all. Both bodies below spell a name that is
|
|
301
|
+
-- ALSO the generated column being defined; classifying a sealed reference as
|
|
302
|
+
-- undecidable instead would record a self-edge and raise a false
|
|
303
|
+
-- `Cyclic dependency in generated columns: 'g'`.
|
|
304
|
+
-- ===================================
|
|
305
|
+
|
|
306
|
+
create table gi_src (k integer primary key, x integer);
|
|
307
|
+
insert into gi_src values (1, 5);
|
|
308
|
+
|
|
309
|
+
create table gi (
|
|
310
|
+
id integer primary key,
|
|
311
|
+
g integer generated always as ((select x as g with inverse (x = new.g) from gi_src limit 1))
|
|
312
|
+
);
|
|
313
|
+
insert into gi (id) values (2);
|
|
314
|
+
|
|
315
|
+
select id, g from gi;
|
|
316
|
+
→ [{"id":2,"g":5}]
|
|
317
|
+
|
|
318
|
+
create table gd (
|
|
319
|
+
id integer primary key,
|
|
320
|
+
g integer generated always as ((select x from gi_src limit 1 with defaults (x = g)))
|
|
321
|
+
);
|
|
322
|
+
insert into gd (id) values (3);
|
|
323
|
+
|
|
324
|
+
select id, g from gd;
|
|
325
|
+
→ [{"id":3,"g":5}]
|
|
326
|
+
|
|
327
|
+
drop table gd;
|
|
328
|
+
drop table gi;
|
|
329
|
+
drop table gi_src;
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
-- generated-columns.sqllogic - Testing GENERATED ALWAYS AS computed columns
|
|
2
|
+
|
|
3
|
+
-- === STORED Generated Columns ===
|
|
4
|
+
|
|
5
|
+
-- Basic STORED generated column (use integers to avoid floating point)
|
|
6
|
+
CREATE TABLE t_gen_stored (
|
|
7
|
+
id INTEGER PRIMARY KEY,
|
|
8
|
+
base_price INTEGER NOT NULL,
|
|
9
|
+
multiplier INTEGER NOT NULL DEFAULT 2,
|
|
10
|
+
total_price INTEGER GENERATED ALWAYS AS (base_price * multiplier) STORED
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
-- INSERT with generated column computed automatically (named columns)
|
|
14
|
+
INSERT INTO t_gen_stored (id, base_price, multiplier) VALUES (1, 100, 3);
|
|
15
|
+
SELECT id, base_price, multiplier, total_price FROM t_gen_stored WHERE id = 1;
|
|
16
|
+
→ [{"id":1,"base_price":100,"multiplier":3,"total_price":300}]
|
|
17
|
+
|
|
18
|
+
-- INSERT with default multiplier
|
|
19
|
+
INSERT INTO t_gen_stored (id, base_price) VALUES (2, 200);
|
|
20
|
+
SELECT id, total_price FROM t_gen_stored WHERE id = 2;
|
|
21
|
+
→ [{"id":2,"total_price":400}]
|
|
22
|
+
|
|
23
|
+
-- UPDATE triggers recomputation of stored generated column
|
|
24
|
+
UPDATE t_gen_stored SET base_price = 50 WHERE id = 1;
|
|
25
|
+
SELECT id, base_price, total_price FROM t_gen_stored WHERE id = 1;
|
|
26
|
+
→ [{"id":1,"base_price":50,"total_price":150}]
|
|
27
|
+
|
|
28
|
+
-- UPDATE multiplier also triggers recomputation
|
|
29
|
+
UPDATE t_gen_stored SET multiplier = 5 WHERE id = 1;
|
|
30
|
+
SELECT id, total_price FROM t_gen_stored WHERE id = 1;
|
|
31
|
+
→ [{"id":1,"total_price":250}]
|
|
32
|
+
|
|
33
|
+
-- Cannot INSERT into generated column (explicit column list)
|
|
34
|
+
INSERT INTO t_gen_stored (id, base_price, multiplier, total_price) VALUES (3, 100, 2, 999);
|
|
35
|
+
-- error: Cannot INSERT into generated column 'total_price'
|
|
36
|
+
|
|
37
|
+
-- Cannot UPDATE a generated column
|
|
38
|
+
UPDATE t_gen_stored SET total_price = 999 WHERE id = 1;
|
|
39
|
+
-- error: Cannot UPDATE generated column 'total_price'
|
|
40
|
+
|
|
41
|
+
-- SELECT * includes generated columns
|
|
42
|
+
SELECT * FROM t_gen_stored WHERE id = 2;
|
|
43
|
+
→ [{"id":2,"base_price":200,"multiplier":2,"total_price":400}]
|
|
44
|
+
|
|
45
|
+
DROP TABLE t_gen_stored;
|
|
46
|
+
|
|
47
|
+
-- === STORED generated column with string concatenation ===
|
|
48
|
+
|
|
49
|
+
CREATE TABLE t_gen_concat (
|
|
50
|
+
id INTEGER PRIMARY KEY,
|
|
51
|
+
first_name TEXT NOT NULL,
|
|
52
|
+
last_name TEXT NOT NULL,
|
|
53
|
+
full_name TEXT GENERATED ALWAYS AS (first_name || ' ' || last_name) STORED
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
INSERT INTO t_gen_concat (id, first_name, last_name) VALUES (1, 'John', 'Doe');
|
|
57
|
+
SELECT full_name FROM t_gen_concat WHERE id = 1;
|
|
58
|
+
→ [{"full_name":"John Doe"}]
|
|
59
|
+
|
|
60
|
+
UPDATE t_gen_concat SET first_name = 'Jane' WHERE id = 1;
|
|
61
|
+
SELECT full_name FROM t_gen_concat WHERE id = 1;
|
|
62
|
+
→ [{"full_name":"Jane Doe"}]
|
|
63
|
+
|
|
64
|
+
DROP TABLE t_gen_concat;
|
|
65
|
+
|
|
66
|
+
-- === Interaction with NOT NULL ===
|
|
67
|
+
|
|
68
|
+
CREATE TABLE t_gen_notnull (
|
|
69
|
+
id INTEGER PRIMARY KEY,
|
|
70
|
+
a INTEGER NULL,
|
|
71
|
+
b INTEGER GENERATED ALWAYS AS (a * 2) STORED NOT NULL
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
-- NULL input causes generated column to be NULL, violating NOT NULL
|
|
75
|
+
INSERT INTO t_gen_notnull (id, a) VALUES (1, NULL);
|
|
76
|
+
-- error: NOT NULL constraint failed: t_gen_notnull.b
|
|
77
|
+
|
|
78
|
+
-- Non-null input succeeds
|
|
79
|
+
INSERT INTO t_gen_notnull (id, a) VALUES (1, 5);
|
|
80
|
+
SELECT b FROM t_gen_notnull WHERE id = 1;
|
|
81
|
+
→ [{"b":10}]
|
|
82
|
+
|
|
83
|
+
DROP TABLE t_gen_notnull;
|
|
84
|
+
|
|
85
|
+
-- === Interaction with CHECK constraints ===
|
|
86
|
+
|
|
87
|
+
CREATE TABLE t_gen_check (
|
|
88
|
+
id INTEGER PRIMARY KEY,
|
|
89
|
+
price INTEGER NOT NULL,
|
|
90
|
+
discount INTEGER NOT NULL DEFAULT 0,
|
|
91
|
+
final_price INTEGER GENERATED ALWAYS AS (price - discount) STORED,
|
|
92
|
+
CHECK (final_price >= 0)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
-- Valid: final_price = 100 - 10 = 90
|
|
96
|
+
INSERT INTO t_gen_check (id, price, discount) VALUES (1, 100, 10);
|
|
97
|
+
SELECT final_price FROM t_gen_check WHERE id = 1;
|
|
98
|
+
→ [{"final_price":90}]
|
|
99
|
+
|
|
100
|
+
-- Invalid: final_price = 50 - 100 = -50 violates CHECK
|
|
101
|
+
INSERT INTO t_gen_check (id, price, discount) VALUES (2, 50, 100);
|
|
102
|
+
-- error: CHECK constraint failed
|
|
103
|
+
|
|
104
|
+
DROP TABLE t_gen_check;
|
|
105
|
+
|
|
106
|
+
-- === Cannot have both DEFAULT and GENERATED ===
|
|
107
|
+
|
|
108
|
+
CREATE TABLE t_gen_default_err (
|
|
109
|
+
id INTEGER PRIMARY KEY,
|
|
110
|
+
a INTEGER DEFAULT 5 GENERATED ALWAYS AS (id * 2) STORED
|
|
111
|
+
);
|
|
112
|
+
-- error: cannot have both DEFAULT and GENERATED
|
|
113
|
+
|
|
114
|
+
-- === Multiple generated columns ===
|
|
115
|
+
|
|
116
|
+
CREATE TABLE t_gen_multi (
|
|
117
|
+
id INTEGER PRIMARY KEY,
|
|
118
|
+
a INTEGER NOT NULL,
|
|
119
|
+
b INTEGER NOT NULL,
|
|
120
|
+
sum_ab INTEGER GENERATED ALWAYS AS (a + b) STORED,
|
|
121
|
+
diff_ab INTEGER GENERATED ALWAYS AS (a - b) STORED
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
INSERT INTO t_gen_multi (id, a, b) VALUES (1, 10, 3);
|
|
125
|
+
SELECT sum_ab, diff_ab FROM t_gen_multi WHERE id = 1;
|
|
126
|
+
→ [{"sum_ab":13,"diff_ab":7}]
|
|
127
|
+
|
|
128
|
+
UPDATE t_gen_multi SET a = 20 WHERE id = 1;
|
|
129
|
+
SELECT sum_ab, diff_ab FROM t_gen_multi WHERE id = 1;
|
|
130
|
+
→ [{"sum_ab":23,"diff_ab":17}]
|
|
131
|
+
|
|
132
|
+
DROP TABLE t_gen_multi;
|
|
133
|
+
|
|
134
|
+
-- === RETURNING with generated columns ===
|
|
135
|
+
|
|
136
|
+
CREATE TABLE t_gen_returning (
|
|
137
|
+
id INTEGER PRIMARY KEY,
|
|
138
|
+
x INTEGER NOT NULL,
|
|
139
|
+
y INTEGER GENERATED ALWAYS AS (x * x) STORED
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
INSERT INTO t_gen_returning (id, x) VALUES (1, 5) RETURNING id, x, y;
|
|
143
|
+
→ [{"id":1,"x":5,"y":25}]
|
|
144
|
+
|
|
145
|
+
UPDATE t_gen_returning SET x = 7 WHERE id = 1 RETURNING id, y;
|
|
146
|
+
→ [{"id":1,"y":49}]
|
|
147
|
+
|
|
148
|
+
DROP TABLE t_gen_returning;
|
|
149
|
+
|
|
150
|
+
-- === VIRTUAL Generated Columns ===
|
|
151
|
+
-- Note: VIRTUAL columns currently behave like STORED (storage optimization deferred).
|
|
152
|
+
-- The semantic behavior is correct: cannot INSERT/UPDATE, expression is evaluated.
|
|
153
|
+
|
|
154
|
+
CREATE TABLE t_gen_virtual (
|
|
155
|
+
id INTEGER PRIMARY KEY,
|
|
156
|
+
width INTEGER NOT NULL,
|
|
157
|
+
height INTEGER NOT NULL,
|
|
158
|
+
area INTEGER GENERATED ALWAYS AS (width * height) VIRTUAL
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
-- INSERT computes the virtual column
|
|
162
|
+
INSERT INTO t_gen_virtual (id, width, height) VALUES (1, 5, 10);
|
|
163
|
+
SELECT id, width, height, area FROM t_gen_virtual WHERE id = 1;
|
|
164
|
+
→ [{"id":1,"width":5,"height":10,"area":50}]
|
|
165
|
+
|
|
166
|
+
-- Cannot INSERT into virtual column
|
|
167
|
+
INSERT INTO t_gen_virtual (id, width, height, area) VALUES (2, 3, 4, 99);
|
|
168
|
+
-- error: Cannot INSERT into generated column 'area'
|
|
169
|
+
|
|
170
|
+
-- Cannot UPDATE virtual column
|
|
171
|
+
UPDATE t_gen_virtual SET area = 100 WHERE id = 1;
|
|
172
|
+
-- error: Cannot UPDATE generated column 'area'
|
|
173
|
+
|
|
174
|
+
-- UPDATE recalculates virtual column
|
|
175
|
+
UPDATE t_gen_virtual SET width = 8 WHERE id = 1;
|
|
176
|
+
SELECT area FROM t_gen_virtual WHERE id = 1;
|
|
177
|
+
→ [{"area":80}]
|
|
178
|
+
|
|
179
|
+
-- Default VIRTUAL (no STORED/VIRTUAL keyword defaults to VIRTUAL per SQL standard)
|
|
180
|
+
CREATE TABLE t_gen_default_mode (
|
|
181
|
+
id INTEGER PRIMARY KEY,
|
|
182
|
+
x INTEGER NOT NULL,
|
|
183
|
+
doubled INTEGER GENERATED ALWAYS AS (x * 2)
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
INSERT INTO t_gen_default_mode (id, x) VALUES (1, 7);
|
|
187
|
+
SELECT doubled FROM t_gen_default_mode WHERE id = 1;
|
|
188
|
+
→ [{"doubled":14}]
|
|
189
|
+
|
|
190
|
+
DROP TABLE t_gen_default_mode;
|
|
191
|
+
DROP TABLE t_gen_virtual;
|
|
192
|
+
|
|
193
|
+
-- ============================================================
|
|
194
|
+
-- === Row-scope spellings: one meaning at every write site ===
|
|
195
|
+
--
|
|
196
|
+
-- A `generated always as (...)` body is compiled by four different statements —
|
|
197
|
+
-- the INSERT row expansion, the `on conflict do update` recompute, the UPDATE
|
|
198
|
+
-- recompute, and the `alter table ... add column` backfill. All four go through
|
|
199
|
+
-- one builder (`planner/building/generated-column-scope.ts`), so a declaration
|
|
200
|
+
-- the engine accepts is one every subsequent write accepts.
|
|
201
|
+
--
|
|
202
|
+
-- Accepted: bare `col`, `table.col`, `schema.table.col`, `new.col`.
|
|
203
|
+
-- Rejected: `old.col` (see 41-generated-column-errors.sqllogic) and any other
|
|
204
|
+
-- qualifier. The ALTER arms live in
|
|
205
|
+
-- 41.13-alter-add-column-generated-backfill.sqllogic.
|
|
206
|
+
-- ============================================================
|
|
207
|
+
|
|
208
|
+
-- --- bare `col` ---
|
|
209
|
+
|
|
210
|
+
create table t_spell_bare (id integer primary key, a integer,
|
|
211
|
+
g integer generated always as (a * 2) stored);
|
|
212
|
+
insert into t_spell_bare (id, a) values (1, 1);
|
|
213
|
+
select id, a, g from t_spell_bare order by id;
|
|
214
|
+
→ [{"id":1,"a":1,"g":2}]
|
|
215
|
+
|
|
216
|
+
update t_spell_bare set a = 5 where id = 1;
|
|
217
|
+
select id, a, g from t_spell_bare order by id;
|
|
218
|
+
→ [{"id":1,"a":5,"g":10}]
|
|
219
|
+
|
|
220
|
+
insert into t_spell_bare (id, a) values (1, 9) on conflict (id) do update set a = 9;
|
|
221
|
+
select id, a, g from t_spell_bare order by id;
|
|
222
|
+
→ [{"id":1,"a":9,"g":18}]
|
|
223
|
+
|
|
224
|
+
drop table t_spell_bare;
|
|
225
|
+
|
|
226
|
+
-- --- `table.col` — the body qualifies its own table ---
|
|
227
|
+
|
|
228
|
+
create table t_spell_tbl (id integer primary key, a integer,
|
|
229
|
+
g integer generated always as (t_spell_tbl.a * 2) stored);
|
|
230
|
+
insert into t_spell_tbl (id, a) values (1, 1);
|
|
231
|
+
select id, a, g from t_spell_tbl order by id;
|
|
232
|
+
→ [{"id":1,"a":1,"g":2}]
|
|
233
|
+
|
|
234
|
+
update t_spell_tbl set a = 5 where id = 1;
|
|
235
|
+
select id, a, g from t_spell_tbl order by id;
|
|
236
|
+
→ [{"id":1,"a":5,"g":10}]
|
|
237
|
+
|
|
238
|
+
insert into t_spell_tbl (id, a) values (1, 9) on conflict (id) do update set a = 9;
|
|
239
|
+
select id, a, g from t_spell_tbl order by id;
|
|
240
|
+
→ [{"id":1,"a":9,"g":18}]
|
|
241
|
+
|
|
242
|
+
drop table t_spell_tbl;
|
|
243
|
+
|
|
244
|
+
-- --- `schema.table.col` — the body qualifies its own schema and table ---
|
|
245
|
+
|
|
246
|
+
create table t_spell_sch (id integer primary key, a integer,
|
|
247
|
+
g integer generated always as (main.t_spell_sch.a * 2) stored);
|
|
248
|
+
insert into t_spell_sch (id, a) values (1, 1);
|
|
249
|
+
select id, a, g from t_spell_sch order by id;
|
|
250
|
+
→ [{"id":1,"a":1,"g":2}]
|
|
251
|
+
|
|
252
|
+
update t_spell_sch set a = 5 where id = 1;
|
|
253
|
+
select id, a, g from t_spell_sch order by id;
|
|
254
|
+
→ [{"id":1,"a":5,"g":10}]
|
|
255
|
+
|
|
256
|
+
insert into t_spell_sch (id, a) values (1, 9) on conflict (id) do update set a = 9;
|
|
257
|
+
select id, a, g from t_spell_sch order by id;
|
|
258
|
+
→ [{"id":1,"a":9,"g":18}]
|
|
259
|
+
|
|
260
|
+
drop table t_spell_sch;
|
|
261
|
+
|
|
262
|
+
-- --- `new.col` — an exact alias for the bare form ---
|
|
263
|
+
|
|
264
|
+
create table t_spell_new (id integer primary key, a integer,
|
|
265
|
+
g integer generated always as (new.a * 2) stored);
|
|
266
|
+
insert into t_spell_new (id, a) values (1, 1);
|
|
267
|
+
select id, a, g from t_spell_new order by id;
|
|
268
|
+
→ [{"id":1,"a":1,"g":2}]
|
|
269
|
+
|
|
270
|
+
update t_spell_new set a = 5 where id = 1;
|
|
271
|
+
select id, a, g from t_spell_new order by id;
|
|
272
|
+
→ [{"id":1,"a":5,"g":10}]
|
|
273
|
+
|
|
274
|
+
insert into t_spell_new (id, a) values (1, 9) on conflict (id) do update set a = 9;
|
|
275
|
+
select id, a, g from t_spell_new order by id;
|
|
276
|
+
→ [{"id":1,"a":9,"g":18}]
|
|
277
|
+
|
|
278
|
+
drop table t_spell_new;
|
|
279
|
+
|
|
280
|
+
-- --- `new.<other generated column>` sees the freshly computed value ---
|
|
281
|
+
-- The generated columns are computed in dependency order, so g2 reads g1's new
|
|
282
|
+
-- value, not the NULL placeholder the row expansion starts from.
|
|
283
|
+
|
|
284
|
+
create table t_spell_chain (id integer primary key, a integer,
|
|
285
|
+
g1 integer generated always as (a * 2) stored,
|
|
286
|
+
g2 integer generated always as (new.g1 + 1) stored);
|
|
287
|
+
insert into t_spell_chain (id, a) values (1, 5);
|
|
288
|
+
select id, a, g1, g2 from t_spell_chain order by id;
|
|
289
|
+
→ [{"id":1,"a":5,"g1":10,"g2":11}]
|
|
290
|
+
|
|
291
|
+
update t_spell_chain set a = 10 where id = 1;
|
|
292
|
+
select id, a, g1, g2 from t_spell_chain order by id;
|
|
293
|
+
→ [{"id":1,"a":10,"g1":20,"g2":21}]
|
|
294
|
+
|
|
295
|
+
insert into t_spell_chain (id, a) values (1, 3) on conflict (id) do update set a = 3;
|
|
296
|
+
select id, a, g1, g2 from t_spell_chain order by id;
|
|
297
|
+
→ [{"id":1,"a":3,"g1":6,"g2":7}]
|
|
298
|
+
|
|
299
|
+
drop table t_spell_chain;
|
|
300
|
+
|
|
301
|
+
-- --- a real table named `new` is still reachable from a generated body ---
|
|
302
|
+
-- `new` is not a reserved word. The row scope is an ANCESTOR of every subquery
|
|
303
|
+
-- planned inside the body, so the subquery's own FROM binds the name first and
|
|
304
|
+
-- `"new".a` reads the table, not the row being written.
|
|
305
|
+
|
|
306
|
+
create table "new" (a integer primary key);
|
|
307
|
+
insert into "new" values (7);
|
|
308
|
+
|
|
309
|
+
create table t_spell_newtbl (id integer primary key,
|
|
310
|
+
g integer generated always as ((select max("new".a) from "new")) stored);
|
|
311
|
+
insert into t_spell_newtbl (id) values (1);
|
|
312
|
+
select id, g from t_spell_newtbl order by id;
|
|
313
|
+
→ [{"id":1,"g":7}]
|
|
314
|
+
|
|
315
|
+
drop table t_spell_newtbl;
|
|
316
|
+
drop table "new";
|
|
317
|
+
|
|
318
|
+
-- --- a mutation-context variable does NOT shadow a column here ---
|
|
319
|
+
-- In a CHECK or a column DEFAULT a `with context` variable claims the bare name.
|
|
320
|
+
-- A generated body is different on purpose: its value is a pure function of the
|
|
321
|
+
-- row being written and must compute identically at all four sites, and the
|
|
322
|
+
-- `alter table ... add column` backfill has no context envelope to read. So the
|
|
323
|
+
-- bare name always means the column. `g` below is a + 1 = 4, NOT ctx + 1 = 101.
|
|
324
|
+
|
|
325
|
+
create table t_spell_ctx (id integer primary key, a integer,
|
|
326
|
+
g integer generated always as (a + 1) stored) with context (a integer);
|
|
327
|
+
insert into t_spell_ctx (id, a) values (1, 3) with context a = 100;
|
|
328
|
+
select id, a, g from t_spell_ctx order by id;
|
|
329
|
+
→ [{"id":1,"a":3,"g":4}]
|
|
330
|
+
|
|
331
|
+
drop table t_spell_ctx;
|
|
332
|
+
|
|
333
|
+
-- --- the row's columns resolve at their DECLARED type, so a declared COLLATE
|
|
334
|
+
-- --- applies inside the body — identically at all three write sites ---
|
|
335
|
+
-- The shared builder resolves each column reference against
|
|
336
|
+
-- `columnSchemaToScalarType(column)`, which carries the column's declared
|
|
337
|
+
-- collation, rather than against the type of whatever expression produced the
|
|
338
|
+
-- row attribute. A `collate nocase` column therefore compares case-insensitively
|
|
339
|
+
-- inside a generated body, the same way it does in a CHECK and on the read path.
|
|
340
|
+
|
|
341
|
+
create table t_spell_coll (id integer primary key, a text collate nocase,
|
|
342
|
+
g integer generated always as (case when a = 'ABC' then 1 else 0 end) stored);
|
|
343
|
+
|
|
344
|
+
insert into t_spell_coll (id, a) values (1, 'abc');
|
|
345
|
+
select id, a, g from t_spell_coll order by id;
|
|
346
|
+
→ [{"id":1,"a":"abc","g":1}]
|
|
347
|
+
|
|
348
|
+
update t_spell_coll set a = 'AbC' where id = 1;
|
|
349
|
+
select id, g from t_spell_coll order by id;
|
|
350
|
+
→ [{"id":1,"g":1}]
|
|
351
|
+
|
|
352
|
+
insert into t_spell_coll (id, a) values (1, 'zzz') on conflict (id) do update set a = 'ABc';
|
|
353
|
+
select id, g from t_spell_coll order by id;
|
|
354
|
+
→ [{"id":1,"g":1}]
|
|
355
|
+
|
|
356
|
+
-- a value the collation does NOT equate still yields 0, so the arm is not vacuous
|
|
357
|
+
update t_spell_coll set a = 'abd' where id = 1;
|
|
358
|
+
select id, g from t_spell_coll order by id;
|
|
359
|
+
→ [{"id":1,"g":0}]
|
|
360
|
+
|
|
361
|
+
drop table t_spell_coll;
|