@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,519 @@
|
|
|
1
|
+
-- 15.1.3-declared-form-write-contract.sqllogic
|
|
2
|
+
--
|
|
3
|
+
-- THE CONTRACT: every expression evaluated against a row being written sees that
|
|
4
|
+
-- row in its columns' DECLARED form — the values that will be stored — never the
|
|
5
|
+
-- form the statement spelled. That covers CHECK (immediate and deferred), DEFAULT
|
|
6
|
+
-- (including one reading a sibling through `new.<column>`), and GENERATED ALWAYS
|
|
7
|
+
-- AS, at every write site: INSERT, UPDATE, `ON CONFLICT ... DO UPDATE`, and the
|
|
8
|
+
-- `ALTER TABLE ... ADD COLUMN` backfill.
|
|
9
|
+
--
|
|
10
|
+
-- Why it needs pinning: each of those sites converts the row at a different place
|
|
11
|
+
-- in its own pipeline (docs/types.md § Where coercion happens (and why exactly
|
|
12
|
+
-- once) enumerates them), and they are easy to drift apart. INSERT used to
|
|
13
|
+
-- evaluate DEFAULT and GENERATED expressions against the UNCONVERTED row while
|
|
14
|
+
-- UPDATE evaluated them against the converted one, so the same value produced two
|
|
15
|
+
-- different computed results depending on which statement wrote it. The
|
|
16
|
+
-- `-- agreement` sections below are the assertions that caught that.
|
|
17
|
+
--
|
|
18
|
+
-- DATETIME is the witness because the split is visible in one character:
|
|
19
|
+
-- '2099-01-01T00:00:00.000Z' is accepted, canonicalized through UTC, and STORED
|
|
20
|
+
-- as '2099-01-01T00:00:00'. Any expression that still sees the trailing `Z` (or
|
|
21
|
+
-- the `.000` fraction) is reading the written form and is wrong.
|
|
22
|
+
--
|
|
23
|
+
-- Scope note: whether a DATETIME column should preserve a `Z` suffix at all is a
|
|
24
|
+
-- separate question, tracked as bug-datetime-literal-with-timezone-never-matches.
|
|
25
|
+
-- This file pins only that every write-path expression agrees with storage on
|
|
26
|
+
-- whatever the declared form turns out to be.
|
|
27
|
+
--
|
|
28
|
+
-- The same contract for JSON — where the split is between raw JSON text and the
|
|
29
|
+
-- parsed document — lives in 15.1.1-json-check-coercion.sqllogic, and
|
|
30
|
+
-- 06.9.1-json-coerce-once.sqllogic pins that the conversion happens exactly once.
|
|
31
|
+
-- Do not duplicate those here.
|
|
32
|
+
--
|
|
33
|
+
-- Runs under both the memory module (`yarn test`) and the store module
|
|
34
|
+
-- (`yarn test:store`).
|
|
35
|
+
--
|
|
36
|
+
-- NOTE: the witness here is DATETIME only, and JSON's is in 15.1.1 — DATE, TIME
|
|
37
|
+
-- and TIMESPAN also rewrite a value on the way in but have no contract coverage,
|
|
38
|
+
-- and nothing forces a new logical type whose `parse` rewrites values to acquire
|
|
39
|
+
-- any. Fine while the write sites share `buildCellCoercion`, since one witness
|
|
40
|
+
-- exercises the shared path. If a type ever converts through its own route, add a
|
|
41
|
+
-- section here for it rather than trusting the DATETIME case to cover it.
|
|
42
|
+
|
|
43
|
+
-- ============================================================
|
|
44
|
+
-- 1. Baseline: what the declared form of a DATETIME actually is
|
|
45
|
+
--
|
|
46
|
+
-- Everything below compares against this one value. If this section changes,
|
|
47
|
+
-- every expectation in the file changes with it.
|
|
48
|
+
-- ============================================================
|
|
49
|
+
|
|
50
|
+
create table wf_base (id integer primary key, d datetime null);
|
|
51
|
+
-- run
|
|
52
|
+
|
|
53
|
+
insert into wf_base values (1, '2099-01-01T00:00:00.000Z');
|
|
54
|
+
-- run
|
|
55
|
+
|
|
56
|
+
-- The written form is NOT what is stored.
|
|
57
|
+
select d from wf_base;
|
|
58
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
59
|
+
|
|
60
|
+
drop table wf_base;
|
|
61
|
+
-- run
|
|
62
|
+
|
|
63
|
+
-- ============================================================
|
|
64
|
+
-- 2. An immediate CHECK sees the declared form
|
|
65
|
+
--
|
|
66
|
+
-- A CHECK with no subquery evaluates inline, during the writing statement.
|
|
67
|
+
-- ============================================================
|
|
68
|
+
|
|
69
|
+
create table wf_chk (id integer primary key, d datetime null, check (d = '2099-01-01T00:00:00'));
|
|
70
|
+
-- run
|
|
71
|
+
|
|
72
|
+
-- The CHECK compares against the DECLARED spelling and admits the row, even
|
|
73
|
+
-- though the INSERT spelled the value differently.
|
|
74
|
+
insert into wf_chk values (1, '2099-01-01T00:00:00.000Z');
|
|
75
|
+
-- run
|
|
76
|
+
|
|
77
|
+
select d from wf_chk;
|
|
78
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
79
|
+
|
|
80
|
+
-- The read path agrees with the CHECK that admitted the row.
|
|
81
|
+
select count(*) as c from wf_chk where d = '2099-01-01T00:00:00';
|
|
82
|
+
→ [{"c":1}]
|
|
83
|
+
|
|
84
|
+
-- UPDATE goes through the same coerced NEW section: the CHECK is not vacuous.
|
|
85
|
+
update wf_chk set d = '2098-01-01T00:00:00' where id = 1;
|
|
86
|
+
-- error: CHECK
|
|
87
|
+
|
|
88
|
+
select d from wf_chk;
|
|
89
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
90
|
+
|
|
91
|
+
-- An UPDATE that re-supplies the WRITTEN form still satisfies the CHECK, because
|
|
92
|
+
-- the CHECK sees the converted value.
|
|
93
|
+
update wf_chk set d = '2099-01-01T00:00:00.000Z' where id = 1;
|
|
94
|
+
-- run
|
|
95
|
+
|
|
96
|
+
select d from wf_chk;
|
|
97
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
98
|
+
|
|
99
|
+
drop table wf_chk;
|
|
100
|
+
-- run
|
|
101
|
+
|
|
102
|
+
-- Control: a CHECK written against the WRITTEN form matches nothing. This is the
|
|
103
|
+
-- sharp end of the contract — if the CHECK saw the raw statement text this row
|
|
104
|
+
-- would be admitted.
|
|
105
|
+
create table wf_chk_raw (id integer primary key, d datetime null, check (d = '2099-01-01T00:00:00.000Z'));
|
|
106
|
+
-- run
|
|
107
|
+
|
|
108
|
+
insert into wf_chk_raw values (1, '2099-01-01T00:00:00.000Z');
|
|
109
|
+
-- error: CHECK
|
|
110
|
+
|
|
111
|
+
select count(*) as c from wf_chk_raw;
|
|
112
|
+
→ [{"c":0}]
|
|
113
|
+
|
|
114
|
+
drop table wf_chk_raw;
|
|
115
|
+
-- run
|
|
116
|
+
|
|
117
|
+
-- ============================================================
|
|
118
|
+
-- 3. A deferred (subquery-bearing) CHECK reaches the same verdict
|
|
119
|
+
--
|
|
120
|
+
-- A CHECK containing a subquery auto-defers to the DeferredConstraintQueue, which
|
|
121
|
+
-- is handed the same coerced row. Same comparison, same accept/reject decisions.
|
|
122
|
+
-- ============================================================
|
|
123
|
+
|
|
124
|
+
create table wf_def (id integer primary key, d datetime null, check ((select d = '2099-01-01T00:00:00')));
|
|
125
|
+
-- run
|
|
126
|
+
|
|
127
|
+
insert into wf_def values (1, '2099-01-01T00:00:00.000Z');
|
|
128
|
+
-- run
|
|
129
|
+
|
|
130
|
+
select d from wf_def;
|
|
131
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
132
|
+
|
|
133
|
+
drop table wf_def;
|
|
134
|
+
-- run
|
|
135
|
+
|
|
136
|
+
create table wf_def_raw (id integer primary key, d datetime null, check ((select d = '2099-01-01T00:00:00.000Z')));
|
|
137
|
+
-- run
|
|
138
|
+
|
|
139
|
+
insert into wf_def_raw values (1, '2099-01-01T00:00:00.000Z');
|
|
140
|
+
-- error: CHECK
|
|
141
|
+
|
|
142
|
+
select count(*) as c from wf_def_raw;
|
|
143
|
+
→ [{"c":0}]
|
|
144
|
+
|
|
145
|
+
drop table wf_def_raw;
|
|
146
|
+
-- run
|
|
147
|
+
|
|
148
|
+
-- The shape that motivated the contract: a deferred CHECK whose subquery compares
|
|
149
|
+
-- `new.<column>` against a value ALREADY STORED in another table — i.e. already in
|
|
150
|
+
-- declared form. If the CHECK saw the unconverted `new.d` the two would never
|
|
151
|
+
-- compare equal and a perfectly valid row would be rejected.
|
|
152
|
+
create table wf_seen (k integer primary key, d datetime null);
|
|
153
|
+
-- run
|
|
154
|
+
|
|
155
|
+
insert into wf_seen values (1, '2099-01-01T00:00:00.000Z');
|
|
156
|
+
-- run
|
|
157
|
+
|
|
158
|
+
create table wf_ref (id integer primary key, d datetime null, check ((select count(*) from wf_seen where wf_seen.d = new.d) = 1));
|
|
159
|
+
-- run
|
|
160
|
+
|
|
161
|
+
insert into wf_ref values (1, '2099-01-01T00:00:00.000Z');
|
|
162
|
+
-- run
|
|
163
|
+
|
|
164
|
+
select d from wf_ref;
|
|
165
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
166
|
+
|
|
167
|
+
-- UPDATE re-supplies the written form and must still match the stored row.
|
|
168
|
+
update wf_ref set d = '2099-01-01T00:00:00.000Z' where id = 1;
|
|
169
|
+
-- run
|
|
170
|
+
|
|
171
|
+
select d from wf_ref;
|
|
172
|
+
→ [{"d":"2099-01-01T00:00:00"}]
|
|
173
|
+
|
|
174
|
+
-- Not vacuous: a value with no counterpart in wf_seen is rejected.
|
|
175
|
+
insert into wf_ref values (2, '2050-06-15T12:00:00');
|
|
176
|
+
-- error: CHECK
|
|
177
|
+
|
|
178
|
+
drop table wf_ref;
|
|
179
|
+
-- run
|
|
180
|
+
|
|
181
|
+
drop table wf_seen;
|
|
182
|
+
-- run
|
|
183
|
+
|
|
184
|
+
-- ============================================================
|
|
185
|
+
-- 4. A DEFAULT reading a sibling through `new.<column>` sees the declared form
|
|
186
|
+
--
|
|
187
|
+
-- The DEFAULT lands in a TEXT column, so whatever it read is visible verbatim.
|
|
188
|
+
-- ============================================================
|
|
189
|
+
|
|
190
|
+
create table wf_dflt (id integer primary key, d datetime null, c text null default ('<' || new.d || '>'));
|
|
191
|
+
-- run
|
|
192
|
+
|
|
193
|
+
insert into wf_dflt (id, d) values (1, '2099-01-01T00:00:00.000Z');
|
|
194
|
+
-- run
|
|
195
|
+
|
|
196
|
+
select d, c from wf_dflt;
|
|
197
|
+
→ [{"d":"2099-01-01T00:00:00","c":"<2099-01-01T00:00:00>"}]
|
|
198
|
+
|
|
199
|
+
drop table wf_dflt;
|
|
200
|
+
-- run
|
|
201
|
+
|
|
202
|
+
-- A DEFAULT that is itself a literal in the written form converts too, and a
|
|
203
|
+
-- generated column reading that column sees the converted result.
|
|
204
|
+
create table wf_dflt_lit (id integer primary key, d datetime null default ('2099-01-01T00:00:00.000Z'), g text null generated always as ('<' || d || '>'));
|
|
205
|
+
-- run
|
|
206
|
+
|
|
207
|
+
insert into wf_dflt_lit (id) values (1);
|
|
208
|
+
-- run
|
|
209
|
+
|
|
210
|
+
select d, g from wf_dflt_lit;
|
|
211
|
+
→ [{"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
212
|
+
|
|
213
|
+
drop table wf_dflt_lit;
|
|
214
|
+
-- run
|
|
215
|
+
|
|
216
|
+
-- ============================================================
|
|
217
|
+
-- 5. A GENERATED ALWAYS AS expression sees the declared form
|
|
218
|
+
-- ============================================================
|
|
219
|
+
|
|
220
|
+
create table wf_gen (id integer primary key, d datetime null, g text null generated always as ('<' || d || '>'));
|
|
221
|
+
-- run
|
|
222
|
+
|
|
223
|
+
insert into wf_gen (id, d) values (1, '2099-01-01T00:00:00.000Z');
|
|
224
|
+
-- run
|
|
225
|
+
|
|
226
|
+
select d, g from wf_gen;
|
|
227
|
+
→ [{"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
228
|
+
|
|
229
|
+
drop table wf_gen;
|
|
230
|
+
-- run
|
|
231
|
+
|
|
232
|
+
-- ============================================================
|
|
233
|
+
-- 6. agreement — INSERT and UPDATE compute the same value
|
|
234
|
+
--
|
|
235
|
+
-- This is the assertion that caught the divergence: INSERT evaluated the
|
|
236
|
+
-- generated expression against the unconverted row, UPDATE against the converted
|
|
237
|
+
-- one, so the same value written two ways produced two different `g` values.
|
|
238
|
+
-- Stated as `count(distinct g)` so the test names the property, not the value.
|
|
239
|
+
-- ============================================================
|
|
240
|
+
|
|
241
|
+
create table wf_agree (id integer primary key, d datetime null, g text null generated always as ('<' || d || '>'));
|
|
242
|
+
-- run
|
|
243
|
+
|
|
244
|
+
-- Row 1 gets the value through INSERT.
|
|
245
|
+
insert into wf_agree (id, d) values (1, '2099-01-01T00:00:00.000Z');
|
|
246
|
+
-- run
|
|
247
|
+
|
|
248
|
+
-- Row 2 arrives holding something else, then gets the same value through UPDATE.
|
|
249
|
+
insert into wf_agree (id, d) values (2, '1970-01-01T00:00:00');
|
|
250
|
+
-- run
|
|
251
|
+
|
|
252
|
+
update wf_agree set d = '2099-01-01T00:00:00.000Z' where id = 2;
|
|
253
|
+
-- run
|
|
254
|
+
|
|
255
|
+
-- One value written two ways ⇒ one computed result.
|
|
256
|
+
select count(distinct g) as c from wf_agree;
|
|
257
|
+
→ [{"c":1}]
|
|
258
|
+
|
|
259
|
+
select id, d, g from wf_agree order by id;
|
|
260
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"},{"id":2,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
261
|
+
|
|
262
|
+
drop table wf_agree;
|
|
263
|
+
-- run
|
|
264
|
+
|
|
265
|
+
-- ============================================================
|
|
266
|
+
-- 7. agreement — touching an unrelated column does not move a computed column
|
|
267
|
+
--
|
|
268
|
+
-- UPDATE carries the untouched `d` over from storage, where it is already in
|
|
269
|
+
-- declared form. Re-converting it (or evaluating against a stale written form)
|
|
270
|
+
-- would show up here as `g` changing under a write that never mentioned `d`.
|
|
271
|
+
-- ============================================================
|
|
272
|
+
|
|
273
|
+
create table wf_touch (id integer primary key, d datetime null, other integer null, g text null generated always as ('<' || d || '>'));
|
|
274
|
+
-- run
|
|
275
|
+
|
|
276
|
+
insert into wf_touch (id, d, other) values (1, '2099-01-01T00:00:00.000Z', 1);
|
|
277
|
+
-- run
|
|
278
|
+
|
|
279
|
+
select d, other, g from wf_touch;
|
|
280
|
+
→ [{"d":"2099-01-01T00:00:00","other":1,"g":"<2099-01-01T00:00:00>"}]
|
|
281
|
+
|
|
282
|
+
update wf_touch set other = 2 where id = 1;
|
|
283
|
+
-- run
|
|
284
|
+
|
|
285
|
+
select d, other, g from wf_touch;
|
|
286
|
+
→ [{"d":"2099-01-01T00:00:00","other":2,"g":"<2099-01-01T00:00:00>"}]
|
|
287
|
+
|
|
288
|
+
drop table wf_touch;
|
|
289
|
+
-- run
|
|
290
|
+
|
|
291
|
+
-- ============================================================
|
|
292
|
+
-- 8. agreement — `add column ... generated` backfill equals a later INSERT
|
|
293
|
+
--
|
|
294
|
+
-- The backfill evaluates the generated expression per existing row, through a
|
|
295
|
+
-- different code path than INSERT. Both must land on the same value. (The
|
|
296
|
+
-- backfill's own mechanics — every spelling, constant expressions, chained
|
|
297
|
+
-- generated columns — are covered by 41.13-alter-add-column-generated-backfill;
|
|
298
|
+
-- what is pinned here is only that it agrees with INSERT on the declared form.)
|
|
299
|
+
-- ============================================================
|
|
300
|
+
|
|
301
|
+
create table wf_bf_gen (id integer primary key, d datetime null);
|
|
302
|
+
-- run
|
|
303
|
+
|
|
304
|
+
insert into wf_bf_gen values (1, '2099-01-01T00:00:00.000Z');
|
|
305
|
+
-- run
|
|
306
|
+
|
|
307
|
+
alter table wf_bf_gen add column g text null generated always as ('<' || d || '>');
|
|
308
|
+
-- run
|
|
309
|
+
|
|
310
|
+
-- Row 2 arrives AFTER the ALTER, through the ordinary INSERT path.
|
|
311
|
+
insert into wf_bf_gen (id, d) values (2, '2099-01-01T00:00:00.000Z');
|
|
312
|
+
-- run
|
|
313
|
+
|
|
314
|
+
select count(distinct g) as c from wf_bf_gen;
|
|
315
|
+
→ [{"c":1}]
|
|
316
|
+
|
|
317
|
+
select id, d, g from wf_bf_gen order by id;
|
|
318
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"},{"id":2,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
319
|
+
|
|
320
|
+
drop table wf_bf_gen;
|
|
321
|
+
-- run
|
|
322
|
+
|
|
323
|
+
-- ============================================================
|
|
324
|
+
-- 9. agreement — `add column ... default (new.<col>)` backfill equals a later INSERT
|
|
325
|
+
--
|
|
326
|
+
-- This is the parity claim docs/sql-alter.md § ADD COLUMN makes: "a backfilled row
|
|
327
|
+
-- and a row inserted afterwards under the same DEFAULT hold the same value".
|
|
328
|
+
-- ============================================================
|
|
329
|
+
|
|
330
|
+
create table wf_bf_dflt (id integer primary key, d datetime null);
|
|
331
|
+
-- run
|
|
332
|
+
|
|
333
|
+
insert into wf_bf_dflt values (1, '2099-01-01T00:00:00.000Z');
|
|
334
|
+
-- run
|
|
335
|
+
|
|
336
|
+
alter table wf_bf_dflt add column c text null default ('<' || new.d || '>');
|
|
337
|
+
-- run
|
|
338
|
+
|
|
339
|
+
insert into wf_bf_dflt (id, d) values (2, '2099-01-01T00:00:00.000Z');
|
|
340
|
+
-- run
|
|
341
|
+
|
|
342
|
+
select count(distinct c) as c from wf_bf_dflt;
|
|
343
|
+
→ [{"c":1}]
|
|
344
|
+
|
|
345
|
+
select id, d, c from wf_bf_dflt order by id;
|
|
346
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","c":"<2099-01-01T00:00:00>"},{"id":2,"d":"2099-01-01T00:00:00","c":"<2099-01-01T00:00:00>"}]
|
|
347
|
+
|
|
348
|
+
drop table wf_bf_dflt;
|
|
349
|
+
-- run
|
|
350
|
+
|
|
351
|
+
-- ============================================================
|
|
352
|
+
-- 10. agreement — `on conflict ... do update` recompute equals a plain UPDATE
|
|
353
|
+
--
|
|
354
|
+
-- The DO UPDATE arm assigns its cells AFTER the emitters' conversion pass and
|
|
355
|
+
-- converts each one itself (docs/types.md, the two single-cell injectors), so it
|
|
356
|
+
-- is a genuinely separate path from both INSERT and UPDATE.
|
|
357
|
+
-- ============================================================
|
|
358
|
+
|
|
359
|
+
create table wf_upsert (id integer primary key, d datetime null, g text null generated always as ('<' || d || '>'));
|
|
360
|
+
-- run
|
|
361
|
+
|
|
362
|
+
insert into wf_upsert (id, d) values (1, '1970-01-01T00:00:00');
|
|
363
|
+
-- run
|
|
364
|
+
|
|
365
|
+
insert into wf_upsert (id, d) values (2, '1970-01-01T00:00:00');
|
|
366
|
+
-- run
|
|
367
|
+
|
|
368
|
+
-- Row 1: the value arrives through a DO UPDATE assignment of a written-form literal.
|
|
369
|
+
insert into wf_upsert (id, d) values (1, '2000-01-01T00:00:00') on conflict (id) do update set d = '2099-01-01T00:00:00.000Z';
|
|
370
|
+
-- run
|
|
371
|
+
|
|
372
|
+
-- Row 2: the same value through a plain UPDATE.
|
|
373
|
+
update wf_upsert set d = '2099-01-01T00:00:00.000Z' where id = 2;
|
|
374
|
+
-- run
|
|
375
|
+
|
|
376
|
+
select count(distinct g) as c from wf_upsert;
|
|
377
|
+
→ [{"c":1}]
|
|
378
|
+
|
|
379
|
+
select id, d, g from wf_upsert order by id;
|
|
380
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"},{"id":2,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
381
|
+
|
|
382
|
+
drop table wf_upsert;
|
|
383
|
+
-- run
|
|
384
|
+
|
|
385
|
+
-- `excluded.<col>` reaches the DO UPDATE arm already converted too, so routing the
|
|
386
|
+
-- proposed value through it lands on the same computed result.
|
|
387
|
+
create table wf_excluded (id integer primary key, d datetime null, g text null generated always as ('<' || d || '>'));
|
|
388
|
+
-- run
|
|
389
|
+
|
|
390
|
+
insert into wf_excluded (id, d) values (1, '1970-01-01T00:00:00');
|
|
391
|
+
-- run
|
|
392
|
+
|
|
393
|
+
insert into wf_excluded (id, d) values (1, '2099-01-01T00:00:00.000Z') on conflict (id) do update set d = excluded.d;
|
|
394
|
+
-- run
|
|
395
|
+
|
|
396
|
+
select id, d, g from wf_excluded;
|
|
397
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
398
|
+
|
|
399
|
+
drop table wf_excluded;
|
|
400
|
+
-- run
|
|
401
|
+
|
|
402
|
+
-- ============================================================
|
|
403
|
+
-- 11. The `OR REPLACE` NOT NULL DEFAULT substitution is not an exception
|
|
404
|
+
--
|
|
405
|
+
-- This is the last write-path expression, and the most out-of-band one: it fires
|
|
406
|
+
-- during constraint checking, after the emitters' conversion pass, when NOT NULL
|
|
407
|
+
-- catches a NULL and the column has a DEFAULT to substitute. It reads the row it
|
|
408
|
+
-- is handed — which is the converted one — and converts its own injected cell
|
|
409
|
+
-- separately. So it agrees with every site above.
|
|
410
|
+
--
|
|
411
|
+
-- (15.1.1-json-check-coercion covers why that separate conversion of its OWN cell
|
|
412
|
+
-- must not double-apply for JSON. Here the point is only which form it READS.)
|
|
413
|
+
-- ============================================================
|
|
414
|
+
|
|
415
|
+
create table wf_repl (id integer primary key, d datetime null, c text not null default ('<' || new.d || '>'));
|
|
416
|
+
-- run
|
|
417
|
+
|
|
418
|
+
insert or replace into wf_repl values (1, '2099-01-01T00:00:00.000Z', null);
|
|
419
|
+
-- run
|
|
420
|
+
|
|
421
|
+
select id, d, c from wf_repl;
|
|
422
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","c":"<2099-01-01T00:00:00>"}]
|
|
423
|
+
|
|
424
|
+
-- A second row, this one conflicting with nothing — the OR REPLACE resolves the
|
|
425
|
+
-- NOT NULL violation, not a key collision — takes the same substitution and agrees.
|
|
426
|
+
insert or replace into wf_repl values (2, '2099-01-01T00:00:00.000Z', null);
|
|
427
|
+
-- run
|
|
428
|
+
|
|
429
|
+
select count(distinct c) as c from wf_repl;
|
|
430
|
+
→ [{"c":1}]
|
|
431
|
+
|
|
432
|
+
-- Without REPLACE the substitution never fires at all; NOT NULL simply rejects the
|
|
433
|
+
-- row. The contract is about which form the DEFAULT reads, not about when it runs.
|
|
434
|
+
insert into wf_repl values (3, '2099-01-01T00:00:00.000Z', null);
|
|
435
|
+
-- error: NOT NULL constraint failed: wf_repl.c
|
|
436
|
+
|
|
437
|
+
drop table wf_repl;
|
|
438
|
+
-- run
|
|
439
|
+
|
|
440
|
+
-- ============================================================
|
|
441
|
+
-- 12. agreement — a multi-row `insert ... select` agrees with `values`
|
|
442
|
+
--
|
|
443
|
+
-- Sections 1-11 all write through `values`, which is the row-expansion path.
|
|
444
|
+
-- A relational source reaches the same expansion, but when its static type is
|
|
445
|
+
-- ALREADY the declared type the per-cell conversion is provably inert and
|
|
446
|
+
-- `coerceToDeclared` skips the wrap, leaving `emitInsert`'s pass as a bare
|
|
447
|
+
-- conformance probe. Both source spellings must land on the stored form.
|
|
448
|
+
-- ============================================================
|
|
449
|
+
|
|
450
|
+
create table wf_sel_dt (id integer primary key, d datetime null);
|
|
451
|
+
-- run
|
|
452
|
+
|
|
453
|
+
create table wf_sel_txt (id integer primary key, d text null);
|
|
454
|
+
-- run
|
|
455
|
+
|
|
456
|
+
-- Source A is already DATETIME: it holds the declared form, and the conversion on
|
|
457
|
+
-- the way into wf_sel_tgt is the skipped one.
|
|
458
|
+
insert into wf_sel_dt values (1, '2099-01-01T00:00:00.000Z'), (2, '2099-01-01T00:00:00.000Z');
|
|
459
|
+
-- run
|
|
460
|
+
|
|
461
|
+
-- Source B is TEXT holding the WRITTEN form: the conversion is live.
|
|
462
|
+
insert into wf_sel_txt values (3, '2099-01-01T00:00:00.000Z');
|
|
463
|
+
-- run
|
|
464
|
+
|
|
465
|
+
create table wf_sel_tgt (id integer primary key, d datetime null, g text null generated always as ('<' || d || '>'), check (d = '2099-01-01T00:00:00'));
|
|
466
|
+
-- run
|
|
467
|
+
|
|
468
|
+
insert into wf_sel_tgt (id, d) select id, d from wf_sel_dt;
|
|
469
|
+
-- run
|
|
470
|
+
|
|
471
|
+
insert into wf_sel_tgt (id, d) select id, d from wf_sel_txt;
|
|
472
|
+
-- run
|
|
473
|
+
|
|
474
|
+
-- Row 4 through the ordinary `values` path, for comparison.
|
|
475
|
+
insert into wf_sel_tgt (id, d) values (4, '2099-01-01T00:00:00.000Z');
|
|
476
|
+
-- run
|
|
477
|
+
|
|
478
|
+
-- Four rows, three source spellings ⇒ one computed result.
|
|
479
|
+
select count(distinct g) as c from wf_sel_tgt;
|
|
480
|
+
→ [{"c":1}]
|
|
481
|
+
|
|
482
|
+
select id, d, g from wf_sel_tgt order by id;
|
|
483
|
+
→ [{"id":1,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"},{"id":2,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"},{"id":3,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"},{"id":4,"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
484
|
+
|
|
485
|
+
drop table wf_sel_tgt;
|
|
486
|
+
-- run
|
|
487
|
+
|
|
488
|
+
drop table wf_sel_txt;
|
|
489
|
+
-- run
|
|
490
|
+
|
|
491
|
+
drop table wf_sel_dt;
|
|
492
|
+
-- run
|
|
493
|
+
|
|
494
|
+
-- ============================================================
|
|
495
|
+
-- 13. RETURNING hands back the same declared form the row was written in
|
|
496
|
+
--
|
|
497
|
+
-- RETURNING reads the written row rather than re-evaluating anything, so it is
|
|
498
|
+
-- the observable end of the contract: what the caller is handed must match what a
|
|
499
|
+
-- later SELECT finds, at every write site that can carry a RETURNING clause.
|
|
500
|
+
-- ============================================================
|
|
501
|
+
|
|
502
|
+
create table wf_ret (id integer primary key, d datetime null, g text null generated always as ('<' || d || '>'));
|
|
503
|
+
-- run
|
|
504
|
+
|
|
505
|
+
insert into wf_ret (id, d) values (1, '2099-01-01T00:00:00.000Z') returning d, g;
|
|
506
|
+
→ [{"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
507
|
+
|
|
508
|
+
update wf_ret set d = '2099-01-01T00:00:00.000Z' where id = 1 returning d, g;
|
|
509
|
+
→ [{"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
510
|
+
|
|
511
|
+
insert into wf_ret (id, d) values (1, '2099-01-01T00:00:00.000Z') on conflict (id) do update set d = excluded.d returning d, g;
|
|
512
|
+
→ [{"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
513
|
+
|
|
514
|
+
-- A later read agrees with every RETURNING above.
|
|
515
|
+
select d, g from wf_ret;
|
|
516
|
+
→ [{"d":"2099-01-01T00:00:00","g":"<2099-01-01T00:00:00>"}]
|
|
517
|
+
|
|
518
|
+
drop table wf_ret;
|
|
519
|
+
-- run
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
-- Epoch functions: epoch_s, epoch_ms, epoch_s_frac
|
|
2
|
+
-- Tests cover known-value conversions, round-trips, modifiers, strict parsing,
|
|
3
|
+
-- subsec modifier on datetime/time, and strftime epoch specifiers.
|
|
4
|
+
|
|
5
|
+
-- ============================================================
|
|
6
|
+
-- epoch_s: known conversions
|
|
7
|
+
-- ============================================================
|
|
8
|
+
|
|
9
|
+
SELECT epoch_s('1970-01-01 00:00:00');
|
|
10
|
+
→ [0]
|
|
11
|
+
|
|
12
|
+
SELECT epoch_s('1970-01-01T00:00:00');
|
|
13
|
+
→ [0]
|
|
14
|
+
|
|
15
|
+
SELECT epoch_s('2000-01-01 00:00:00');
|
|
16
|
+
→ [946684800]
|
|
17
|
+
|
|
18
|
+
SELECT epoch_s('2024-07-26 12:30:45');
|
|
19
|
+
→ [1721997045]
|
|
20
|
+
|
|
21
|
+
-- Date-only input (time defaults to 00:00:00)
|
|
22
|
+
SELECT epoch_s('2024-01-01');
|
|
23
|
+
→ [1704067200]
|
|
24
|
+
|
|
25
|
+
-- With timezone offset in the string
|
|
26
|
+
SELECT epoch_s('2024-01-01T00:00:00Z');
|
|
27
|
+
→ [1704067200]
|
|
28
|
+
|
|
29
|
+
SELECT epoch_s('2024-01-01T01:00:00+01:00');
|
|
30
|
+
→ [1704067200]
|
|
31
|
+
|
|
32
|
+
-- ============================================================
|
|
33
|
+
-- epoch_ms: known conversions
|
|
34
|
+
-- ============================================================
|
|
35
|
+
|
|
36
|
+
SELECT epoch_ms('1970-01-01 00:00:00');
|
|
37
|
+
→ [0]
|
|
38
|
+
|
|
39
|
+
SELECT epoch_ms('2024-01-01 00:00:00');
|
|
40
|
+
→ [1704067200000]
|
|
41
|
+
|
|
42
|
+
SELECT epoch_ms('2024-07-26 12:30:45.123');
|
|
43
|
+
→ [1721997045123]
|
|
44
|
+
|
|
45
|
+
-- Sub-second precision preserved
|
|
46
|
+
SELECT epoch_ms('2024-07-26 12:30:45.999');
|
|
47
|
+
→ [1721997045999]
|
|
48
|
+
|
|
49
|
+
-- ============================================================
|
|
50
|
+
-- epoch_s_frac: fractional seconds
|
|
51
|
+
-- ============================================================
|
|
52
|
+
|
|
53
|
+
SELECT epoch_s_frac('1970-01-01 00:00:00');
|
|
54
|
+
→ [0]
|
|
55
|
+
|
|
56
|
+
SELECT epoch_s_frac('2024-07-26 12:30:45.5');
|
|
57
|
+
→ [1721997045.5]
|
|
58
|
+
|
|
59
|
+
SELECT epoch_s_frac('2024-07-26 12:30:45.123');
|
|
60
|
+
→ [1721997045.123]
|
|
61
|
+
|
|
62
|
+
-- ============================================================
|
|
63
|
+
-- epoch_s with modifiers
|
|
64
|
+
-- ============================================================
|
|
65
|
+
|
|
66
|
+
SELECT epoch_s('2024-01-01', '+1 day');
|
|
67
|
+
→ [1704153600]
|
|
68
|
+
|
|
69
|
+
SELECT epoch_s('2024-01-15', 'start of month');
|
|
70
|
+
→ [1704067200]
|
|
71
|
+
|
|
72
|
+
SELECT epoch_s('2024-06-15 12:00:00', 'start of day');
|
|
73
|
+
→ [1718409600]
|
|
74
|
+
|
|
75
|
+
-- ============================================================
|
|
76
|
+
-- Strict parsing: bare numbers are rejected
|
|
77
|
+
-- ============================================================
|
|
78
|
+
|
|
79
|
+
SELECT epoch_s(1704067200);
|
|
80
|
+
→ [null]
|
|
81
|
+
|
|
82
|
+
SELECT epoch_ms(1704067200000);
|
|
83
|
+
→ [null]
|
|
84
|
+
|
|
85
|
+
SELECT epoch_s_frac(1704067200.5);
|
|
86
|
+
→ [null]
|
|
87
|
+
|
|
88
|
+
-- Time-only strings are rejected
|
|
89
|
+
SELECT epoch_s('12:30:45');
|
|
90
|
+
→ [null]
|
|
91
|
+
|
|
92
|
+
-- YYYYMMDD format is rejected (not strict ISO)
|
|
93
|
+
SELECT epoch_s('20240101');
|
|
94
|
+
→ [null]
|
|
95
|
+
|
|
96
|
+
-- NULL input
|
|
97
|
+
SELECT epoch_s(NULL);
|
|
98
|
+
→ [null]
|
|
99
|
+
|
|
100
|
+
-- ============================================================
|
|
101
|
+
-- 'now' returns non-null values
|
|
102
|
+
-- ============================================================
|
|
103
|
+
|
|
104
|
+
SELECT epoch_s('now') IS NOT NULL;
|
|
105
|
+
→ [true]
|
|
106
|
+
|
|
107
|
+
SELECT epoch_ms('now') IS NOT NULL;
|
|
108
|
+
→ [true]
|
|
109
|
+
|
|
110
|
+
SELECT epoch_s_frac('now') IS NOT NULL;
|
|
111
|
+
→ [true]
|
|
112
|
+
|
|
113
|
+
-- ============================================================
|
|
114
|
+
-- Round-trip: epoch_s → datetime via unixepoch modifier
|
|
115
|
+
-- ============================================================
|
|
116
|
+
|
|
117
|
+
SELECT datetime(epoch_s('2024-07-26 12:30:45'), 'unixepoch');
|
|
118
|
+
→ ["2024-07-26 12:30:45"]
|
|
119
|
+
|
|
120
|
+
SELECT date(epoch_s('2024-01-15 08:00:00'), 'unixepoch');
|
|
121
|
+
→ ["2024-01-15"]
|
|
122
|
+
|
|
123
|
+
-- ============================================================
|
|
124
|
+
-- Relationship between epoch_s and epoch_ms
|
|
125
|
+
-- ============================================================
|
|
126
|
+
|
|
127
|
+
-- epoch_ms / 1000 equals epoch_s for whole-second datetimes
|
|
128
|
+
SELECT epoch_ms('2024-01-01 00:00:00') - epoch_s('2024-01-01 00:00:00') * 1000;
|
|
129
|
+
→ [0]
|
|
130
|
+
|
|
131
|
+
-- Milliseconds capture sub-second precision that seconds truncate
|
|
132
|
+
SELECT epoch_ms('2024-07-26 12:30:45.500') - epoch_s('2024-07-26 12:30:45.500') * 1000;
|
|
133
|
+
→ [500]
|
|
134
|
+
|
|
135
|
+
-- ============================================================
|
|
136
|
+
-- subsec modifier on datetime/time
|
|
137
|
+
-- ============================================================
|
|
138
|
+
|
|
139
|
+
SELECT datetime('2024-07-26 12:30:45.123', 'subsec');
|
|
140
|
+
→ ["2024-07-26 12:30:45.123"]
|
|
141
|
+
|
|
142
|
+
SELECT time('12:30:45.456', 'subsec');
|
|
143
|
+
→ ["12:30:45.456"]
|
|
144
|
+
|
|
145
|
+
-- Without subsec, fractional seconds are truncated (2+ args to use datetime.ts path)
|
|
146
|
+
SELECT datetime('2024-07-26 12:30:45.999', '+0 seconds');
|
|
147
|
+
→ ["2024-07-26 12:30:45"]
|
|
148
|
+
|
|
149
|
+
SELECT time('12:30:45.999', '+0 seconds');
|
|
150
|
+
→ ["12:30:45"]
|
|
151
|
+
|
|
152
|
+
-- subsec with unixepoch
|
|
153
|
+
SELECT datetime(1721997045.123, 'unixepoch', 'subsec');
|
|
154
|
+
→ ["2024-07-26 12:30:45.123"]
|
|
155
|
+
|
|
156
|
+
-- subsec with arithmetic modifiers
|
|
157
|
+
SELECT datetime('2024-07-26 12:30:45.500', '+1 second', 'subsec');
|
|
158
|
+
→ ["2024-07-26 12:30:46.500"]
|
|
159
|
+
|
|
160
|
+
-- ============================================================
|
|
161
|
+
-- strftime epoch specifiers: %E (seconds) and %Q (milliseconds)
|
|
162
|
+
-- ============================================================
|
|
163
|
+
|
|
164
|
+
SELECT strftime('%E', '2024-01-01 00:00:00');
|
|
165
|
+
→ ["1704067200"]
|
|
166
|
+
|
|
167
|
+
SELECT strftime('%Q', '2024-01-01 00:00:00');
|
|
168
|
+
→ ["1704067200000"]
|
|
169
|
+
|
|
170
|
+
SELECT strftime('%Q', '2024-07-26 12:30:45.123');
|
|
171
|
+
→ ["1721997045123"]
|
|
172
|
+
|
|
173
|
+
-- Epoch specifiers work with modifiers
|
|
174
|
+
SELECT strftime('%E', '2024-01-01', '+1 day');
|
|
175
|
+
→ ["1704153600"]
|
|
176
|
+
|
|
177
|
+
-- ============================================================
|
|
178
|
+
-- Arithmetic with epoch values
|
|
179
|
+
-- ============================================================
|
|
180
|
+
|
|
181
|
+
-- Difference in seconds between two datetimes
|
|
182
|
+
SELECT epoch_s('2024-01-02 00:00:00') - epoch_s('2024-01-01 00:00:00');
|
|
183
|
+
→ [86400]
|
|
184
|
+
|
|
185
|
+
-- Difference in milliseconds
|
|
186
|
+
SELECT epoch_ms('2024-01-02 00:00:00') - epoch_ms('2024-01-01 00:00:00');
|
|
187
|
+
→ [86400000]
|