@quereus/quereus 4.20.1 → 4.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +17 -69
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/package.json +7 -4
- package/test/README.md +173 -0
- package/test/logic/01-basic.sqllogic +39 -0
- package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
- package/test/logic/01.2-strings.sqllogic +43 -0
- package/test/logic/01.5-insert-select.sqllogic +237 -0
- package/test/logic/01.6-update-extras.sqllogic +118 -0
- package/test/logic/01.7-update-from.sqllogic +67 -0
- package/test/logic/01.8-delete-extras.sqllogic +122 -0
- package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
- package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
- package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
- package/test/logic/01.9-query-expr-values.sqllogic +111 -0
- package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
- package/test/logic/02-filters.sqllogic +54 -0
- package/test/logic/02-smoke.sqllogic +62 -0
- package/test/logic/02.1-bind-parameters.sqllogic +223 -0
- package/test/logic/03-expressions.sqllogic +190 -0
- package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
- package/test/logic/03.4-defaults.sqllogic +554 -0
- package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
- package/test/logic/03.5-tvf.sqllogic +61 -0
- package/test/logic/03.6-type-system.sqllogic +544 -0
- package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
- package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
- package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
- package/test/logic/03.8-not-precedence.sqllogic +255 -0
- package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
- package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
- package/test/logic/04-order-by.sqllogic +38 -0
- package/test/logic/04-transactions.sqllogic +239 -0
- package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
- package/test/logic/05-vtab_memory.sqllogic +50 -0
- package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
- package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
- package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
- package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
- package/test/logic/06-builtin_functions.sqllogic +149 -0
- package/test/logic/06.1-string-functions.sqllogic +92 -0
- package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
- package/test/logic/06.2-math-functions.sqllogic +82 -0
- package/test/logic/06.3-schema.sqllogic +48 -0
- package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
- package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
- package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
- package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
- package/test/logic/06.3.4-view-info.sqllogic +378 -0
- package/test/logic/06.3.5-column-info.sqllogic +347 -0
- package/test/logic/06.3.6-schema-views.sqllogic +29 -0
- package/test/logic/06.4-schema-search-path.sqllogic +354 -0
- package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
- package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
- package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
- package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
- package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
- package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
- package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
- package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
- package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
- package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
- package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
- package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
- package/test/logic/06.7-json-extended.sqllogic +53 -0
- package/test/logic/06.8-json-path-operators.sqllogic +99 -0
- package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
- package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
- package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
- package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
- package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
- package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
- package/test/logic/07-aggregates.sqllogic +193 -0
- package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
- package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
- package/test/logic/07.3-group-by-extras.sqllogic +602 -0
- package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
- package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
- package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
- package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
- package/test/logic/07.5-window.sqllogic +1941 -0
- package/test/logic/07.5.1-window-named.sqllogic +13 -0
- package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
- package/test/logic/07.6-subqueries.sqllogic +78 -0
- package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
- package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
- package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
- package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
- package/test/logic/07.7.1-in-extras.sqllogic +158 -0
- package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
- package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
- package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
- package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
- package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
- package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
- package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
- package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
- package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
- package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
- package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
- package/test/logic/07.9-in-value-list.sqllogic +154 -0
- package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
- package/test/logic/08-views.sqllogic +64 -0
- package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
- package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
- package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
- package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
- package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
- package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
- package/test/logic/09-set_operations.sqllogic +244 -0
- package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
- package/test/logic/10-distinct_datatypes.sqllogic +127 -0
- package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
- package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
- package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
- package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
- package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
- package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
- package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
- package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
- package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
- package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
- package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
- package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
- package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
- package/test/logic/10.2-column-features.sqllogic +365 -0
- package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
- package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
- package/test/logic/10.3-function-features.sqllogic +247 -0
- package/test/logic/10.4-schema-scale.sqllogic +168 -0
- package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
- package/test/logic/10.5-indexes.sqllogic +164 -0
- package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
- package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
- package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
- package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
- package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
- package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
- package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
- package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
- package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
- package/test/logic/100.1-where-extras.sqllogic +163 -0
- package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
- package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
- package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
- package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
- package/test/logic/102-unique-constraints.sqllogic +145 -0
- package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
- package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
- package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
- package/test/logic/102.2-unique-collation.sqllogic +181 -0
- package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
- package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
- package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
- package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
- package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
- package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
- package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
- package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
- package/test/logic/108-cardinality-estimation.sqllogic +146 -0
- package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
- package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
- package/test/logic/11-joins.sqllogic +86 -0
- package/test/logic/11.1-join-using.sqllogic +267 -0
- package/test/logic/11.2-comma-join.sqllogic +35 -0
- package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
- package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
- package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
- package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
- package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
- package/test/logic/12-empty-primary-key.sqllogic +124 -0
- package/test/logic/12-join_padding_order.sqllogic +58 -0
- package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
- package/test/logic/13-cte.sqllogic +137 -0
- package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
- package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
- package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
- package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
- package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
- package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
- package/test/logic/13.4-cte-extras.sqllogic +98 -0
- package/test/logic/13.5-cte-join-order.sqllogic +166 -0
- package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
- package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
- package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
- package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
- package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
- package/test/logic/14-utilities.sqllogic +168 -0
- package/test/logic/15-timespan.sqllogic +279 -0
- package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
- package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
- package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
- package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
- package/test/logic/16-epoch.sqllogic +187 -0
- package/test/logic/17-weekday-modifier.sqllogic +78 -0
- package/test/logic/18-json-string-escapes.sqllogic +86 -0
- package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
- package/test/logic/20-empty-single-row.sqllogic +261 -0
- package/test/logic/21-null-edge-cases.sqllogic +227 -0
- package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
- package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
- package/test/logic/21.2-between-edges.sqllogic +157 -0
- package/test/logic/22-boundary-values.sqllogic +175 -0
- package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
- package/test/logic/24-builtin-branches.sqllogic +611 -0
- package/test/logic/24.1-substr-extras.sqllogic +75 -0
- package/test/logic/24.2-random-extras.sqllogic +39 -0
- package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
- package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
- package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
- package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
- package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
- package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
- package/test/logic/26-join-edge-cases.sqllogic +333 -0
- package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
- package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
- package/test/logic/26.3-join-on-constants.sqllogic +61 -0
- package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
- package/test/logic/27-window-edge-cases.sqllogic +206 -0
- package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
- package/test/logic/27.2-window-exclude.sqllogic +13 -0
- package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
- package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
- package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
- package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
- package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
- package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
- package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
- package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
- package/test/logic/40-constraints.sqllogic +418 -0
- package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
- package/test/logic/40.2-check-extras.sqllogic +683 -0
- package/test/logic/41-alter-table.sqllogic +191 -0
- package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
- package/test/logic/41-fk-cross-schema.sqllogic +155 -0
- package/test/logic/41-fk-extended-targets.sqllogic +173 -0
- package/test/logic/41-foreign-keys.sqllogic +1001 -0
- package/test/logic/41-generated-column-errors.sqllogic +225 -0
- package/test/logic/41-generated-column-extras.sqllogic +598 -0
- package/test/logic/41-generated-column-scope.sqllogic +329 -0
- package/test/logic/41-generated-columns.sqllogic +361 -0
- package/test/logic/41.1-alter-pk.sqllogic +230 -0
- package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
- package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
- package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
- package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
- package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
- package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
- package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
- package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
- package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
- package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
- package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
- package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
- package/test/logic/41.2-alter-column.sqllogic +382 -0
- package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
- package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
- package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
- package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
- package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
- package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
- package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
- package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
- package/test/logic/41.5-alter-misc.sqllogic +48 -0
- package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
- package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
- package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
- package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
- package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
- package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
- package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
- package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
- package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
- package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
- package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
- package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
- package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
- package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
- package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
- package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
- package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
- package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
- package/test/logic/42-committed-snapshot.sqllogic +254 -0
- package/test/logic/42-returning.sqllogic +159 -0
- package/test/logic/42.1-returning-extras.sqllogic +232 -0
- package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
- package/test/logic/43-default-nullability.sqllogic +131 -0
- package/test/logic/43-transition-constraints.sqllogic +341 -0
- package/test/logic/43.1-default-collation.sqllogic +140 -0
- package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
- package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
- package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
- package/test/logic/44-determinism-validation.sqllogic +164 -0
- package/test/logic/44-orthogonality.sqllogic +146 -0
- package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
- package/test/logic/45-udf-determinism.sqllogic +39 -0
- package/test/logic/46-mutation-context.sqllogic +595 -0
- package/test/logic/47-upsert.sqllogic +255 -0
- package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
- package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
- package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
- package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
- package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
- package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
- package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
- package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
- package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
- package/test/logic/49-reference-graph.sqllogic +84 -0
- package/test/logic/50-declarative-schema.sqllogic +2550 -0
- package/test/logic/50-metadata-tags.sqllogic +1033 -0
- package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
- package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
- package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
- package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +210 -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,197 @@
|
|
|
1
|
+
-- 08.2-existence-flag-semijoin-recovery.sqllogic
|
|
2
|
+
-- A probe-only outer-join `exists … as` flag (`where flag` / `where not flag`)
|
|
3
|
+
-- is recovered to an equivalent semi / anti join. Pure optimization — these
|
|
4
|
+
-- assert end-to-end result correctness against real data.
|
|
5
|
+
|
|
6
|
+
-- ===== No declared FK: probe-only flag recovers to a hash semi / anti join =====
|
|
7
|
+
|
|
8
|
+
create table ec (cc integer primary key, pr integer null, cv integer);
|
|
9
|
+
create table ep (pp integer primary key, pv integer);
|
|
10
|
+
insert into ep values (1, 10), (2, 20);
|
|
11
|
+
-- cc 1 (pr 1) matches; cc 2 (pr 9) no match; cc 3 (pr 2) matches; cc 4 (pr null) no match
|
|
12
|
+
insert into ec values (1, 1, 100), (2, 9, 200), (3, 2, 300), (4, null, 400);
|
|
13
|
+
|
|
14
|
+
-- semi: keep child rows WITH a matching parent
|
|
15
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP order by cc;
|
|
16
|
+
→ [{"cc":1},{"cc":3}]
|
|
17
|
+
|
|
18
|
+
-- anti: keep child rows with NO matching parent
|
|
19
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where not hasP order by cc;
|
|
20
|
+
→ [{"cc":2},{"cc":4}]
|
|
21
|
+
|
|
22
|
+
-- double negation collapses to a semi probe
|
|
23
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where not not hasP order by cc;
|
|
24
|
+
→ [{"cc":1},{"cc":3}]
|
|
25
|
+
|
|
26
|
+
-- literal probe forms: `= true` → semi, `= false` → anti
|
|
27
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP = true order by cc;
|
|
28
|
+
→ [{"cc":1},{"cc":3}]
|
|
29
|
+
|
|
30
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP = false order by cc;
|
|
31
|
+
→ [{"cc":2},{"cc":4}]
|
|
32
|
+
|
|
33
|
+
-- IS [NOT] TRUE/FALSE probe forms over the non-null flag.
|
|
34
|
+
-- `is true` → semi (rows WITH a match)
|
|
35
|
+
-- `is not false` → semi (≡ = true, exact because the flag is never null)
|
|
36
|
+
-- `is false` → anti (rows with NO match)
|
|
37
|
+
-- `is not true` → anti (≡ = false, exact because the flag is never null)
|
|
38
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is true order by cc;
|
|
39
|
+
→ [{"cc":1},{"cc":3}]
|
|
40
|
+
|
|
41
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is not false order by cc;
|
|
42
|
+
→ [{"cc":1},{"cc":3}]
|
|
43
|
+
|
|
44
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is false order by cc;
|
|
45
|
+
→ [{"cc":2},{"cc":4}]
|
|
46
|
+
|
|
47
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is not true order by cc;
|
|
48
|
+
→ [{"cc":2},{"cc":4}]
|
|
49
|
+
|
|
50
|
+
-- `is not null` over the never-null flag is a constant TRUE — NOT a probe; the rule
|
|
51
|
+
-- abstains and every left row survives (semi/anti recovery must not fire).
|
|
52
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is not null order by cc;
|
|
53
|
+
→ [{"cc":1},{"cc":2},{"cc":3},{"cc":4}]
|
|
54
|
+
|
|
55
|
+
-- `is null` over the never-null flag is a constant FALSE — likewise not a probe; the
|
|
56
|
+
-- rule abstains and the (always-false) filter keeps no rows.
|
|
57
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is null order by cc;
|
|
58
|
+
→ []
|
|
59
|
+
|
|
60
|
+
-- residual AND-conjunct is retained above the semi join (cv > 150 keeps only cc 3)
|
|
61
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP and c.cv > 150 order by cc;
|
|
62
|
+
→ [{"cc":3}]
|
|
63
|
+
|
|
64
|
+
-- OR-probe: the flag's truth does not partition rows, so recovery abstains — still correct
|
|
65
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP or c.cv > 150 order by cc;
|
|
66
|
+
→ [{"cc":1},{"cc":2},{"cc":3},{"cc":4}]
|
|
67
|
+
|
|
68
|
+
-- flag also selected: retained (not a probe-only shape) and reads back correctly
|
|
69
|
+
select cc, hasP from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP order by cc;
|
|
70
|
+
→ [{"cc":1,"hasP":true},{"cc":3,"hasP":true}]
|
|
71
|
+
|
|
72
|
+
drop table ec;
|
|
73
|
+
drop table ep;
|
|
74
|
+
|
|
75
|
+
-- ===== Declared nullable FK (referential integrity holds): folding cascade =====
|
|
76
|
+
|
|
77
|
+
create table par (pid integer primary key, pname text);
|
|
78
|
+
create table chi (cid integer primary key, pref integer null references par(pid), cval integer);
|
|
79
|
+
insert into par values (1, 'P1'), (2, 'P2');
|
|
80
|
+
insert into chi values (10, 1, 100), (20, null, 200), (30, 2, 300), (40, null, 400);
|
|
81
|
+
|
|
82
|
+
-- semi over a nullable FK folds to Filter(child, pref IS NOT NULL)
|
|
83
|
+
select cid from chi left join par on par.pid = chi.pref exists right as hasP where hasP order by cid;
|
|
84
|
+
→ [{"cid":10},{"cid":30}]
|
|
85
|
+
|
|
86
|
+
-- anti over a nullable FK keeps the NULL-pref (unmatched) rows
|
|
87
|
+
select cid from chi left join par on par.pid = chi.pref exists right as hasP where not hasP order by cid;
|
|
88
|
+
→ [{"cid":20},{"cid":40}]
|
|
89
|
+
|
|
90
|
+
drop table chi;
|
|
91
|
+
drop table par;
|
|
92
|
+
|
|
93
|
+
-- ===== Declared NOT NULL FK: semi folds to L, anti folds to Empty =====
|
|
94
|
+
|
|
95
|
+
create table custs (id integer primary key, nm text);
|
|
96
|
+
create table ords (oid integer primary key, cust integer not null references custs(id), amt real);
|
|
97
|
+
insert into custs values (1, 'Acme'), (2, 'Beta');
|
|
98
|
+
insert into ords values (10, 1, 99.0), (11, 2, 49.5), (12, 1, 12.0);
|
|
99
|
+
|
|
100
|
+
-- every order has a matching customer → semi keeps all rows
|
|
101
|
+
select oid from ords left join custs on ords.cust = custs.id exists right as hasC where hasC order by oid;
|
|
102
|
+
→ [{"oid":10},{"oid":11},{"oid":12}]
|
|
103
|
+
|
|
104
|
+
-- … so the anti is empty
|
|
105
|
+
select oid from ords left join custs on ords.cust = custs.id exists right as hasC where not hasC order by oid;
|
|
106
|
+
→ []
|
|
107
|
+
|
|
108
|
+
drop table ords;
|
|
109
|
+
drop table custs;
|
|
110
|
+
|
|
111
|
+
-- ===== Fan-out guard: right side NOT unique on the join column =====
|
|
112
|
+
-- A plain `left join … exists right as` yields one row per MATCHING right row,
|
|
113
|
+
-- so `where flag` fans out (K rows per matched left row). Recovery to a semi
|
|
114
|
+
-- join (1 row per left) would silently drop the duplicates — so the SEMI rule
|
|
115
|
+
-- must abstain on the positive side. (The fanned-out positive cases are instead
|
|
116
|
+
-- recovered to a fan-out-safe INNER join by `inner-join-existence-recovery`,
|
|
117
|
+
-- which does NOT collapse K→1; see 08.3. Either way the rows below are identical,
|
|
118
|
+
-- which is exactly what these assertions pin.) The anti side is immune (unmatched
|
|
119
|
+
-- rows never fan out) and still recovers via the semi rule. These assert the
|
|
120
|
+
-- fanned-out row counts directly.
|
|
121
|
+
|
|
122
|
+
create table fc (cc integer primary key);
|
|
123
|
+
create table fp (id integer primary key, pp integer);
|
|
124
|
+
insert into fc values (1), (2);
|
|
125
|
+
-- cc 1 matches THREE fp rows (pp=1); cc 2 matches none.
|
|
126
|
+
insert into fp values (10, 1), (11, 1), (12, 1);
|
|
127
|
+
|
|
128
|
+
-- semi probe over fan-out: SEMI rule abstains (would collapse to one); the inner
|
|
129
|
+
-- fallback recovers an inner join that keeps all three fanned-out cc=1 rows.
|
|
130
|
+
select cc from fc c left join fp p on p.pp = c.cc exists right as h where h order by cc;
|
|
131
|
+
→ [{"cc":1},{"cc":1},{"cc":1}]
|
|
132
|
+
|
|
133
|
+
-- `is true` is also a SEMI probe and rides the same fan-out guard — the semi rule
|
|
134
|
+
-- abstains, the inner fallback recovers, keeping all three fanned-out cc=1 rows.
|
|
135
|
+
select cc from fc c left join fp p on p.pp = c.cc exists right as h where h is true order by cc;
|
|
136
|
+
→ [{"cc":1},{"cc":1},{"cc":1}]
|
|
137
|
+
|
|
138
|
+
-- anti probe: one row per unmatched left row, fan-out irrelevant
|
|
139
|
+
select cc from fc c left join fp p on p.pp = c.cc exists right as h where not h order by cc;
|
|
140
|
+
→ [{"cc":2}]
|
|
141
|
+
|
|
142
|
+
drop table fc;
|
|
143
|
+
drop table fp;
|
|
144
|
+
|
|
145
|
+
-- ===== Aggregate anchor: bare `count(*) … where flag` (no enclosing Project) =====
|
|
146
|
+
-- A flag-bearing left join under a `count(*)` / `group by` with NO enclosing Project
|
|
147
|
+
-- is recovered by the AggregateNode entrypoint (`semijoin-existence-recovery-aggregate`)
|
|
148
|
+
-- exactly like the Project shape — the probe Filter sits between the Aggregate and the
|
|
149
|
+
-- Join, so the same probe-detection + chain-rewrite machinery applies. These assert the
|
|
150
|
+
-- end-to-end counts against real data.
|
|
151
|
+
|
|
152
|
+
create table ac (cc integer primary key, pr integer null);
|
|
153
|
+
create table ap (pp integer primary key, pv integer);
|
|
154
|
+
insert into ap values (1, 10), (2, 20);
|
|
155
|
+
-- cc 1 (pr 1) matches; cc 2 (pr 9) no match; cc 3 (pr 2) matches; cc 4 (pr null) no match
|
|
156
|
+
insert into ac values (1, 1), (2, 9), (3, 2), (4, null);
|
|
157
|
+
|
|
158
|
+
-- semi: count of child rows WITH a matching parent
|
|
159
|
+
select count(*) as n from ac c left join ap p on p.pp = c.pr exists right as hasP where hasP;
|
|
160
|
+
→ [{"n":2}]
|
|
161
|
+
|
|
162
|
+
-- anti: count of child rows with NO matching parent
|
|
163
|
+
select count(*) as n from ac c left join ap p on p.pp = c.pr exists right as hasP where not hasP;
|
|
164
|
+
→ [{"n":2}]
|
|
165
|
+
|
|
166
|
+
-- HAVING above the aggregate references only the count output — it does not block recovery
|
|
167
|
+
select count(*) as n from ac c left join ap p on p.pp = c.pr exists right as hasP where hasP having count(*) >= 0;
|
|
168
|
+
→ [{"n":2}]
|
|
169
|
+
|
|
170
|
+
-- flag grouped on: retained (genuinely demanded), one group per flag value
|
|
171
|
+
select hasP, count(*) as n from ac c left join ap p on p.pp = c.pr exists right as hasP group by hasP order by hasP;
|
|
172
|
+
→ [{"hasP":false,"n":2},{"hasP":true,"n":2}]
|
|
173
|
+
|
|
174
|
+
drop table ac;
|
|
175
|
+
drop table ap;
|
|
176
|
+
|
|
177
|
+
-- ===== Aggregate anchor fan-out: NO inner fallback, so count is the fanned-out value =====
|
|
178
|
+
-- Unlike the Project anchor (which hands the fan-out positive probe to a fan-out-safe
|
|
179
|
+
-- inner join), the aggregate anchor has no inner fallback: the SEMI rule abstains and the
|
|
180
|
+
-- join stays a flag-bearing left join, so `count(*)` reflects the fanned-out rows.
|
|
181
|
+
|
|
182
|
+
create table afc (cc integer primary key);
|
|
183
|
+
create table afp (id integer primary key, pp integer);
|
|
184
|
+
insert into afc values (1), (2);
|
|
185
|
+
-- cc 1 matches THREE afp rows (pp=1); cc 2 matches none.
|
|
186
|
+
insert into afp values (10, 1), (11, 1), (12, 1);
|
|
187
|
+
|
|
188
|
+
-- positive probe over fan-out: stays left; count(*) is the fanned-out 3, NOT a collapsed 1
|
|
189
|
+
select count(*) as n from afc c left join afp p on p.pp = c.cc exists right as h where h;
|
|
190
|
+
→ [{"n":3}]
|
|
191
|
+
|
|
192
|
+
-- anti probe: one row per unmatched left row — fan-out irrelevant, recovers an anti join
|
|
193
|
+
select count(*) as n from afc c left join afp p on p.pp = c.cc exists right as h where not h;
|
|
194
|
+
→ [{"n":1}]
|
|
195
|
+
|
|
196
|
+
drop table afc;
|
|
197
|
+
drop table afp;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
-- 08.3-existence-flag-inner-recovery.sqllogic
|
|
2
|
+
-- The fallback complement of 08.2: a POSITIVE probe-only outer-join `exists … as`
|
|
3
|
+
-- flag (`where flag`) is recovered to a plain INNER join (flag dropped, both sides
|
|
4
|
+
-- kept) whenever a semi join would be wrong or impossible — either a right-side
|
|
5
|
+
-- column is demanded above the join, OR R fans out (non-unique on the join column,
|
|
6
|
+
-- where a semi join would collapse duplicates). Pure optimization — these assert
|
|
7
|
+
-- end-to-end result correctness against real data.
|
|
8
|
+
|
|
9
|
+
-- ===== No declared FK: positive probe + right column recovers to an inner join =====
|
|
10
|
+
|
|
11
|
+
create table ec (cc integer primary key, pr integer null, cv integer);
|
|
12
|
+
create table ep (pp integer primary key, pv integer);
|
|
13
|
+
insert into ep values (1, 10), (2, 20);
|
|
14
|
+
-- cc 1 (pr 1) matches pv 10; cc 2 (pr 9) no match; cc 3 (pr 2) matches pv 20; cc 4 (pr null) no match
|
|
15
|
+
insert into ec values (1, 1, 100), (2, 9, 200), (3, 2, 300), (4, null, 400);
|
|
16
|
+
|
|
17
|
+
-- bare probe: keep matched rows, carry the demanded right column p.pv
|
|
18
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP order by cc;
|
|
19
|
+
→ [{"cc":1,"pv":10},{"cc":3,"pv":20}]
|
|
20
|
+
|
|
21
|
+
-- double negation collapses to a positive probe ⇒ inner
|
|
22
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where not not hasP order by cc;
|
|
23
|
+
→ [{"cc":1,"pv":10},{"cc":3,"pv":20}]
|
|
24
|
+
|
|
25
|
+
-- literal `= true` probe ⇒ inner
|
|
26
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP = true order by cc;
|
|
27
|
+
→ [{"cc":1,"pv":10},{"cc":3,"pv":20}]
|
|
28
|
+
|
|
29
|
+
-- `is true` / `is not false` probe forms over the non-null flag ⇒ inner
|
|
30
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is true order by cc;
|
|
31
|
+
→ [{"cc":1,"pv":10},{"cc":3,"pv":20}]
|
|
32
|
+
|
|
33
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP is not false order by cc;
|
|
34
|
+
→ [{"cc":1,"pv":10},{"cc":3,"pv":20}]
|
|
35
|
+
|
|
36
|
+
-- residual AND-conjunct retained above the inner join (cv > 150 keeps only cc 3)
|
|
37
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP and c.cv > 150 order by cc;
|
|
38
|
+
→ [{"cc":3,"pv":20}]
|
|
39
|
+
|
|
40
|
+
-- negative probe + right column must NOT convert (anti rows have a NULL right side);
|
|
41
|
+
-- stays a left join and the unmatched rows carry NULL pv.
|
|
42
|
+
select cc, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where not hasP order by cc;
|
|
43
|
+
→ [{"cc":2,"pv":null},{"cc":4,"pv":null}]
|
|
44
|
+
|
|
45
|
+
-- no right column demanded ⇒ defers to the semi recovery (rows WITH a match)
|
|
46
|
+
select cc from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP order by cc;
|
|
47
|
+
→ [{"cc":1},{"cc":3}]
|
|
48
|
+
|
|
49
|
+
-- flag also selected ⇒ retained (not a probe-only shape) and reads back correctly
|
|
50
|
+
select cc, hasP, pv from ec c left join ep p on p.pp = c.pr exists right as hasP where hasP order by cc;
|
|
51
|
+
→ [{"cc":1,"hasP":true,"pv":10},{"cc":3,"hasP":true,"pv":20}]
|
|
52
|
+
|
|
53
|
+
drop table ec;
|
|
54
|
+
drop table ep;
|
|
55
|
+
|
|
56
|
+
-- ===== Fan-out: the case the semi rule cannot handle =====
|
|
57
|
+
-- A plain `left join … exists right as` yields one row per MATCHING right row, so
|
|
58
|
+
-- a left row with K matches fans out to K rows. An inner join keeps all K (no
|
|
59
|
+
-- collapse), unlike a semi join — this is the headline capability of this rule.
|
|
60
|
+
|
|
61
|
+
create table fc (cc integer primary key);
|
|
62
|
+
create table fp (id integer primary key, pp integer);
|
|
63
|
+
insert into fc values (1), (2);
|
|
64
|
+
-- cc 1 matches THREE fp rows (pp=1); cc 2 matches none.
|
|
65
|
+
insert into fp values (10, 1), (11, 1), (12, 1);
|
|
66
|
+
|
|
67
|
+
-- with a right column demanded ⇒ inner join, all three fanned rows kept
|
|
68
|
+
select cc, id from fc c left join fp p on p.pp = c.cc exists right as h where h order by cc, id;
|
|
69
|
+
→ [{"cc":1,"id":10},{"cc":1,"id":11},{"cc":1,"id":12}]
|
|
70
|
+
|
|
71
|
+
-- NO right column demanded, but R fans out (non-unique): the semi rule abstains on
|
|
72
|
+
-- its fan-out guard, so the inner fallback recovers a fan-out-safe inner join that
|
|
73
|
+
-- keeps all three rows (a semi join would have collapsed them to one).
|
|
74
|
+
select cc from fc c left join fp p on p.pp = c.cc exists right as h where h order by cc;
|
|
75
|
+
→ [{"cc":1},{"cc":1},{"cc":1}]
|
|
76
|
+
|
|
77
|
+
-- `is true` positive probe over the fan-out rides the same fallback
|
|
78
|
+
select cc from fc c left join fp p on p.pp = c.cc exists right as h where h is true order by cc;
|
|
79
|
+
→ [{"cc":1},{"cc":1},{"cc":1}]
|
|
80
|
+
|
|
81
|
+
-- negative probe stays anti (fan-out-immune; unmatched rows never duplicate)
|
|
82
|
+
select cc from fc c left join fp p on p.pp = c.cc exists right as h where not h order by cc;
|
|
83
|
+
→ [{"cc":2}]
|
|
84
|
+
|
|
85
|
+
drop table fc;
|
|
86
|
+
drop table fp;
|
|
87
|
+
|
|
88
|
+
-- ===== Declared nullable FK with a NULL FK row: no orphan leaks =====
|
|
89
|
+
-- A NULL FK never satisfies the ON condition, so it is unmatched under both the
|
|
90
|
+
-- flag (false, dropped by `where flag`) and the inner join (no match).
|
|
91
|
+
|
|
92
|
+
create table par (pid integer primary key, pname text);
|
|
93
|
+
create table chi (cid integer primary key, pref integer null references par(pid), cval integer);
|
|
94
|
+
insert into par values (1, 'P1'), (2, 'P2');
|
|
95
|
+
insert into chi values (10, 1, 100), (20, null, 200), (30, 2, 300), (40, null, 400);
|
|
96
|
+
|
|
97
|
+
-- positive probe + right column (par.pname) ⇒ inner join; NULL-pref rows absent
|
|
98
|
+
select cid, pname from chi left join par on par.pid = chi.pref exists right as hasP where hasP order by cid;
|
|
99
|
+
→ [{"cid":10,"pname":"P1"},{"cid":30,"pname":"P2"}]
|
|
100
|
+
|
|
101
|
+
drop table chi;
|
|
102
|
+
drop table par;
|