@quereus/quereus 4.20.0 → 4.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/src/common/types.d.ts +4 -4
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/schema/catalog-rendering.js +13 -1
- package/dist/src/schema/catalog-rendering.js.map +1 -1
- package/dist/src/schema/catalog.d.ts +35 -2
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +42 -33
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/schema-differ.d.ts +1 -1
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +195 -33
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/schema/unique-enforcement.d.ts +23 -1
- package/dist/src/schema/unique-enforcement.d.ts.map +1 -1
- package/dist/src/schema/unique-enforcement.js +43 -1
- package/dist/src/schema/unique-enforcement.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +15 -12
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +87 -100
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/package.json +7 -4
- package/test/README.md +173 -0
- package/test/logic/01-basic.sqllogic +39 -0
- package/test/logic/01.1-select-projection-extras.sqllogic +130 -0
- package/test/logic/01.2-strings.sqllogic +43 -0
- package/test/logic/01.5-insert-select.sqllogic +237 -0
- package/test/logic/01.6-update-extras.sqllogic +118 -0
- package/test/logic/01.7-update-from.sqllogic +67 -0
- package/test/logic/01.8-delete-extras.sqllogic +122 -0
- package/test/logic/01.8.1-delete-range-cow.sqllogic +115 -0
- package/test/logic/01.9-query-expr-dml-gates.sqllogic +32 -0
- package/test/logic/01.9-query-expr-dml.sqllogic +171 -0
- package/test/logic/01.9-query-expr-values.sqllogic +111 -0
- package/test/logic/01.9.1-limit-over-dml-subquery.sqllogic +119 -0
- package/test/logic/02-filters.sqllogic +54 -0
- package/test/logic/02-smoke.sqllogic +62 -0
- package/test/logic/02.1-bind-parameters.sqllogic +223 -0
- package/test/logic/03-expressions.sqllogic +190 -0
- package/test/logic/03.1-quoted-identifiers.sqllogic +55 -0
- package/test/logic/03.4-defaults.sqllogic +554 -0
- package/test/logic/03.4.1-default-edge-cases.sqllogic +99 -0
- package/test/logic/03.5-tvf.sqllogic +61 -0
- package/test/logic/03.6-type-system.sqllogic +544 -0
- package/test/logic/03.6.1-numeric-text-comparison-coercion.sqllogic +244 -0
- package/test/logic/03.6.2-value-to-text.sqllogic +224 -0
- package/test/logic/03.7-bigint-mixed-arithmetic.sqllogic +65 -0
- package/test/logic/03.8-not-precedence.sqllogic +255 -0
- package/test/logic/03.9-is-bool-predicate.sqllogic +150 -0
- package/test/logic/03.9.1-is-bool-predicate-partial-index.sqllogic +34 -0
- package/test/logic/04-order-by.sqllogic +38 -0
- package/test/logic/04-transactions.sqllogic +239 -0
- package/test/logic/04a-savepoint-lazy-attach.sqllogic +122 -0
- package/test/logic/05-vtab_memory.sqllogic +50 -0
- package/test/logic/05.0.1-vtab-memory-unique-index-collation.sqllogic +34 -0
- package/test/logic/05.1-composite-pk-range-scan.sqllogic +147 -0
- package/test/logic/05.1.1-secondary-index-range-scan.sqllogic +56 -0
- package/test/logic/05.2-cast-seek-correctness.sqllogic +124 -0
- package/test/logic/06-builtin_functions.sqllogic +149 -0
- package/test/logic/06.1-string-functions.sqllogic +92 -0
- package/test/logic/06.1.3-like-glob-edges.sqllogic +53 -0
- package/test/logic/06.2-math-functions.sqllogic +82 -0
- package/test/logic/06.3-schema.sqllogic +48 -0
- package/test/logic/06.3.1-schema-all-schemas.sqllogic +39 -0
- package/test/logic/06.3.2-schema-foreign-keys.sqllogic +208 -0
- package/test/logic/06.3.3-introspection-tags.sqllogic +202 -0
- package/test/logic/06.3.3.1-introspection-tags-index.sqllogic +74 -0
- package/test/logic/06.3.4-view-info.sqllogic +378 -0
- package/test/logic/06.3.5-column-info.sqllogic +347 -0
- package/test/logic/06.3.6-schema-views.sqllogic +29 -0
- package/test/logic/06.4-schema-search-path.sqllogic +354 -0
- package/test/logic/06.4.1-schema-case-insensitive.sqllogic +83 -0
- package/test/logic/06.4.2-collation-extras.sqllogic +472 -0
- package/test/logic/06.4.2.1-collation-index-access-paths.sqllogic +140 -0
- package/test/logic/06.4.3-write-path-collation.sqllogic +99 -0
- package/test/logic/06.4.4-comparison-collation-precedence.sqllogic +342 -0
- package/test/logic/06.4.5-any-collate-declared-keys.sqllogic +92 -0
- package/test/logic/06.5-polymorphic-types.sqllogic +169 -0
- package/test/logic/06.5.1-conversion-functions.sqllogic +173 -0
- package/test/logic/06.5.2-scalar-minmax.sqllogic +16 -0
- package/test/logic/06.5.3-undeclared-return-type-comparison.sqllogic +244 -0
- package/test/logic/06.5.4-declared-return-type-builtins.sqllogic +288 -0
- package/test/logic/06.6-aggregate-extended.sqllogic +78 -0
- package/test/logic/06.7-json-extended.sqllogic +53 -0
- package/test/logic/06.8-json-path-operators.sqllogic +99 -0
- package/test/logic/06.9-json-canonical-key.sqllogic +65 -0
- package/test/logic/06.9.1-json-coerce-once.sqllogic +417 -0
- package/test/logic/06.9.1.1-json-coerce-once-index.sqllogic +39 -0
- package/test/logic/06.9.2-json-structural-equality.sqllogic +382 -0
- package/test/logic/06.9.2.1-json-structural-equality-index.sqllogic +76 -0
- package/test/logic/06.9.3-json-index-range-seek.sqllogic +205 -0
- package/test/logic/07-aggregates.sqllogic +193 -0
- package/test/logic/07.1-aggregate-filter-clause.sqllogic +12 -0
- package/test/logic/07.2-aggregate-order-by.sqllogic +11 -0
- package/test/logic/07.3-group-by-extras.sqllogic +602 -0
- package/test/logic/07.3.1-group-by-order-by-key.sqllogic +164 -0
- package/test/logic/07.3.2-grouped-select-list-shape.sqllogic +231 -0
- package/test/logic/07.4-group-by-filter-composite-pk.sqllogic +120 -0
- package/test/logic/07.5-sum-mixed-exact-and-float.sqllogic +151 -0
- package/test/logic/07.5-window.sqllogic +1941 -0
- package/test/logic/07.5.1-window-named.sqllogic +13 -0
- package/test/logic/07.5.2-window-nth-value.sqllogic +13 -0
- package/test/logic/07.6-subqueries.sqllogic +78 -0
- package/test/logic/07.6.1-subquery-extras.sqllogic +93 -0
- package/test/logic/07.7-and-or-short-circuit.sqllogic +58 -0
- package/test/logic/07.7-in-subquery-caching.sqllogic +174 -0
- package/test/logic/07.7-scalar-agg-decorrelation.sqllogic +197 -0
- package/test/logic/07.7.1-in-extras.sqllogic +158 -0
- package/test/logic/07.7.1-scalar-agg-decorrelation-filter.sqllogic +105 -0
- package/test/logic/07.7.2-scalar-agg-decorrelation-nested.sqllogic +115 -0
- package/test/logic/07.7.3-exists-in-select-decorrelation.sqllogic +107 -0
- package/test/logic/07.7.4-where-conjunct-ordering.sqllogic +121 -0
- package/test/logic/07.7.5-filter-lost-under-index-order.sqllogic +134 -0
- package/test/logic/07.7.6-correlated-predicate-scope.sqllogic +178 -0
- package/test/logic/07.7.7-join-source-scope-shadowing.sqllogic +137 -0
- package/test/logic/07.7.8-correlated-ref-to-computed-column.sqllogic +165 -0
- package/test/logic/07.7.9-conjunct-monotonicity.sqllogic +200 -0
- package/test/logic/07.8-correlated-subquery-edges.sqllogic +71 -0
- package/test/logic/07.8.1-correlated-in-decorrelation-gates.sqllogic +156 -0
- package/test/logic/07.9-in-value-list.sqllogic +154 -0
- package/test/logic/07.9.1-in-value-list-composite-index.sqllogic +38 -0
- package/test/logic/08-views.sqllogic +64 -0
- package/test/logic/08.1-semi-anti-join.sqllogic +191 -0
- package/test/logic/08.1-view-edge-cases.sqllogic +118 -0
- package/test/logic/08.1.1-uncorrelated-in-semijoin.sqllogic +251 -0
- package/test/logic/08.2-existence-flag-semijoin-recovery.sqllogic +197 -0
- package/test/logic/08.3-existence-flag-inner-recovery.sqllogic +102 -0
- package/test/logic/08.4-key-set-semi-join.sqllogic +447 -0
- package/test/logic/09-set_operations.sqllogic +244 -0
- package/test/logic/09.1-set-op-cross-collation.sqllogic +230 -0
- package/test/logic/10-distinct_datatypes.sqllogic +127 -0
- package/test/logic/10.1-ddl-lifecycle.sqllogic +203 -0
- package/test/logic/10.1.1-create-table-syntax-edges.sqllogic +47 -0
- package/test/logic/10.1.2-ddl-in-transaction.sqllogic +143 -0
- package/test/logic/10.1.2.1-add-constraint-in-transaction.sqllogic +59 -0
- package/test/logic/10.1.3-ddl-drop-in-transaction.sqllogic +187 -0
- package/test/logic/10.1.3.1-drop-constraint-in-transaction.sqllogic +45 -0
- package/test/logic/10.1.4-create-table-duplicate-constraint-names.sqllogic +149 -0
- package/test/logic/10.1.4-ddl-transaction-policy.sqllogic +314 -0
- package/test/logic/10.1.5-alter-add-constraint-minted-name-disambiguation.sqllogic +219 -0
- package/test/logic/10.1.5-create-index-lifecycle.sqllogic +72 -0
- package/test/logic/10.1.6-ddl-transaction-policy-index.sqllogic +143 -0
- package/test/logic/10.1.7-create-table-default-type-check.sqllogic +119 -0
- package/test/logic/10.1.8-alter-add-check-existing-rows.sqllogic +117 -0
- package/test/logic/10.2-column-features.sqllogic +365 -0
- package/test/logic/10.2.1-table-options-rejection.sqllogic +63 -0
- package/test/logic/10.2.2-default-collation-memory.sqllogic +30 -0
- package/test/logic/10.3-function-features.sqllogic +247 -0
- package/test/logic/10.4-schema-scale.sqllogic +168 -0
- package/test/logic/10.4.1-schema-scale-indexes.sqllogic +121 -0
- package/test/logic/10.5-indexes.sqllogic +164 -0
- package/test/logic/10.5.1-partial-indexes.sqllogic +526 -0
- package/test/logic/10.5.2-expression-indexes.sqllogic +34 -0
- package/test/logic/10.5.3-desc-index-ordering.sqllogic +130 -0
- package/test/logic/10.5.4-composite-pk-index-update-phantom.sqllogic +55 -0
- package/test/logic/10.5.5-index-name-uniqueness.sqllogic +76 -0
- package/test/logic/10.5.6-minmax-index-boundary.sqllogic +204 -0
- package/test/logic/10.5.7-implicit-unique-index-lifecycle.sqllogic +1216 -0
- package/test/logic/10.6-distinct-edge-cases.sqllogic +119 -0
- package/test/logic/100-predicate-normalization-edge-cases.sqllogic +238 -0
- package/test/logic/100.1-where-extras.sqllogic +163 -0
- package/test/logic/100.1.1-where-join-on-order-indexed.sqllogic +35 -0
- package/test/logic/101-builtin-mutation-kills.sqllogic +974 -0
- package/test/logic/101-transaction-edge-cases.sqllogic +395 -0
- package/test/logic/102-schema-catalog-edge-cases.sqllogic +252 -0
- package/test/logic/102-unique-constraints.sqllogic +145 -0
- package/test/logic/102.0.1-schema-catalog-indexed-table.sqllogic +32 -0
- package/test/logic/102.1-unique-edge-cases.sqllogic +111 -0
- package/test/logic/102.1.1-unique-index-creation-edge-cases.sqllogic +75 -0
- package/test/logic/102.2-unique-collation.sqllogic +181 -0
- package/test/logic/102.2.1-unique-collation-index-derived.sqllogic +305 -0
- package/test/logic/103-database-options-edge-cases.sqllogic +108 -0
- package/test/logic/103.1-pragma-boolean-values.sqllogic +126 -0
- package/test/logic/104-emit-mutation-kills.sqllogic +236 -0
- package/test/logic/105-vtab-memory-mutation-kills.sqllogic +754 -0
- package/test/logic/105.1-vtab-memory-index-mutation-kills.sqllogic +540 -0
- package/test/logic/106-constraint-extractor-mutation-kills.sqllogic +350 -0
- package/test/logic/107-temporal-arithmetic-mutation-kills.sqllogic +833 -0
- package/test/logic/108-cardinality-estimation.sqllogic +146 -0
- package/test/logic/108.1-analyze-name-resolution.sqllogic +102 -0
- package/test/logic/109-aggregate-physical-selection.sqllogic +103 -0
- package/test/logic/11-joins.sqllogic +86 -0
- package/test/logic/11.1-join-using.sqllogic +267 -0
- package/test/logic/11.2-comma-join.sqllogic +35 -0
- package/test/logic/11.3-index-nested-loop-join.sqllogic +305 -0
- package/test/logic/11.3-mismatched-collation-join.sqllogic +74 -0
- package/test/logic/11.4-hash-join-side-swap.sqllogic +118 -0
- package/test/logic/110-scan-emitter-mutation-kills.sqllogic +121 -0
- package/test/logic/110.1-scan-emitter-index-scan-kills.sqllogic +47 -0
- package/test/logic/12-empty-primary-key.sqllogic +124 -0
- package/test/logic/12-join_padding_order.sqllogic +58 -0
- package/test/logic/12.1-orderby-index-consumption.sqllogic +40 -0
- package/test/logic/13-cte.sqllogic +137 -0
- package/test/logic/13.1-cte-multiple-recursive.sqllogic +104 -0
- package/test/logic/13.10-cte-qualified-name.sqllogic +136 -0
- package/test/logic/13.11-unreferenced-dml-cte.sqllogic +414 -0
- package/test/logic/13.12-nested-dml-cte-rejected.sqllogic +280 -0
- package/test/logic/13.2-cte-bind-params.sqllogic +98 -0
- package/test/logic/13.3-cte-edge-cases.sqllogic +120 -0
- package/test/logic/13.4-cte-extras.sqllogic +98 -0
- package/test/logic/13.5-cte-join-order.sqllogic +166 -0
- package/test/logic/13.6-cte-dml-runs-once.sqllogic +318 -0
- package/test/logic/13.7-cte-sibling-visibility.sqllogic +227 -0
- package/test/logic/13.8-insert-with-clause-visibility.sqllogic +254 -0
- package/test/logic/13.9-schema-authored-cte-isolation.sqllogic +328 -0
- package/test/logic/13.9.1-schema-authored-schema-path-isolation.sqllogic +408 -0
- package/test/logic/14-utilities.sqllogic +168 -0
- package/test/logic/15-timespan.sqllogic +279 -0
- package/test/logic/15.1-semantic-ordering.sqllogic +960 -0
- package/test/logic/15.1.1-json-check-coercion.sqllogic +178 -0
- package/test/logic/15.1.2-semantic-ordering-index.sqllogic +41 -0
- package/test/logic/15.1.3-declared-form-write-contract.sqllogic +519 -0
- package/test/logic/16-epoch.sqllogic +187 -0
- package/test/logic/17-weekday-modifier.sqllogic +78 -0
- package/test/logic/18-json-string-escapes.sqllogic +86 -0
- package/test/logic/18-strftime-extended-formats.sqllogic +68 -0
- package/test/logic/20-empty-single-row.sqllogic +261 -0
- package/test/logic/21-null-edge-cases.sqllogic +227 -0
- package/test/logic/21.1-where-null-comparisons.sqllogic +151 -0
- package/test/logic/21.1.1-where-null-comparisons-secondary-index.sqllogic +35 -0
- package/test/logic/21.2-between-edges.sqllogic +157 -0
- package/test/logic/22-boundary-values.sqllogic +175 -0
- package/test/logic/23-self-joins-duplicates.sqllogic +74 -0
- package/test/logic/24-builtin-branches.sqllogic +611 -0
- package/test/logic/24.1-substr-extras.sqllogic +75 -0
- package/test/logic/24.2-random-extras.sqllogic +39 -0
- package/test/logic/25-aggregate-edge-cases.sqllogic +289 -0
- package/test/logic/25.1-nested-aggregates.sqllogic +74 -0
- package/test/logic/25.2-having-edge-cases.sqllogic +318 -0
- package/test/logic/25.3-aggregate-isnull-empty.sqllogic +16 -0
- package/test/logic/25.4-groupby-fd-constant-empty.sqllogic +55 -0
- package/test/logic/25.5-ungrouped-aggregate-column-free-select-item.sqllogic +196 -0
- package/test/logic/26-join-edge-cases.sqllogic +333 -0
- package/test/logic/26.1-left-join-isnull-on-notnull.sqllogic +26 -0
- package/test/logic/26.2-left-join-on-vs-where.sqllogic +67 -0
- package/test/logic/26.3-join-on-constants.sqllogic +61 -0
- package/test/logic/26.4-join-on-is-null-nullable.sqllogic +44 -0
- package/test/logic/27-window-edge-cases.sqllogic +206 -0
- package/test/logic/27.1-window-groups-frame.sqllogic +13 -0
- package/test/logic/27.2-window-exclude.sqllogic +13 -0
- package/test/logic/27.3-window-json-aggregation.sqllogic +66 -0
- package/test/logic/28-set-ops-sort-edge-cases.sqllogic +444 -0
- package/test/logic/28.1-compound-limit-offset.sqllogic +143 -0
- package/test/logic/28.2-orderby-expression-extras.sqllogic +698 -0
- package/test/logic/28.2-set-op-branch-types.sqllogic +217 -0
- package/test/logic/29-constraint-edge-cases.sqllogic +442 -0
- package/test/logic/29.1-column-level-conflict-clause.sqllogic +171 -0
- package/test/logic/29.2-table-level-pk-conflict-clause.sqllogic +113 -0
- package/test/logic/40-constraints.sqllogic +418 -0
- package/test/logic/40.1-pk-desc-direction.sqllogic +76 -0
- package/test/logic/40.2-check-extras.sqllogic +683 -0
- package/test/logic/41-alter-table.sqllogic +191 -0
- package/test/logic/41-fk-cascade-conflict-and-self-ref.sqllogic +263 -0
- package/test/logic/41-fk-cross-schema.sqllogic +155 -0
- package/test/logic/41-fk-extended-targets.sqllogic +173 -0
- package/test/logic/41-foreign-keys.sqllogic +1001 -0
- package/test/logic/41-generated-column-errors.sqllogic +225 -0
- package/test/logic/41-generated-column-extras.sqllogic +598 -0
- package/test/logic/41-generated-column-scope.sqllogic +329 -0
- package/test/logic/41-generated-columns.sqllogic +361 -0
- package/test/logic/41.1-alter-pk.sqllogic +230 -0
- package/test/logic/41.1-fk-collation-conflict.sqllogic +277 -0
- package/test/logic/41.10-alter-drop-column-foreign-key.sqllogic +274 -0
- package/test/logic/41.10.1-alter-drop-column-unique-index.sqllogic +169 -0
- package/test/logic/41.10.2-alter-drop-column-check-and-assertion.sqllogic +1616 -0
- package/test/logic/41.10.3-alter-drop-column-referencing-fk.sqllogic +292 -0
- package/test/logic/41.10.4-drop-object-expression-dependents.sqllogic +602 -0
- package/test/logic/41.11-deferred-fk-with-rename.sqllogic +232 -0
- package/test/logic/41.12-alter-default-coercion.sqllogic +200 -0
- package/test/logic/41.13-alter-add-column-generated-backfill.sqllogic +566 -0
- package/test/logic/41.14-alter-add-column-subquery-backfill.sqllogic +129 -0
- package/test/logic/41.15-alter-column-default-type-check.sqllogic +178 -0
- package/test/logic/41.16-fk-unenforceable.sqllogic +364 -0
- package/test/logic/41.2-alter-column.sqllogic +382 -0
- package/test/logic/41.2.1-alter-column-retype-deleted-row-memory.sqllogic +32 -0
- package/test/logic/41.2.2-alter-column-retype-index-rebuild.sqllogic +77 -0
- package/test/logic/41.2.3-alter-column-set-not-null-pk-backfill.sqllogic +310 -0
- package/test/logic/41.2.3.1-alter-column-set-not-null-pk-backfill-secondary-index.sqllogic +37 -0
- package/test/logic/41.3-alter-add-column-unique.sqllogic +184 -0
- package/test/logic/41.3-alter-rename-propagation.sqllogic +2352 -0
- package/test/logic/41.3.1-alter-rename-index-propagation.sqllogic +94 -0
- package/test/logic/41.4-alter-add-column-constraints.sqllogic +855 -0
- package/test/logic/41.5-alter-misc.sqllogic +48 -0
- package/test/logic/41.5-cross-schema-foreign-keys.sqllogic +253 -0
- package/test/logic/41.6-alter-drop-rename-constraint.sqllogic +354 -0
- package/test/logic/41.6.1-alter-drop-constraint-index-derived.sqllogic +22 -0
- package/test/logic/41.7-alter-column-collate.sqllogic +105 -0
- package/test/logic/41.7.1-alter-column-collate-unique.sqllogic +45 -0
- package/test/logic/41.7.2-alter-column-collate-unique-store.sqllogic +208 -0
- package/test/logic/41.7.2.1-alter-column-collate-unique-index-store.sqllogic +114 -0
- package/test/logic/41.7.3-alter-column-retype-unique.sqllogic +293 -0
- package/test/logic/41.7.3.1-alter-column-retype-staged-rows-memory.sqllogic +41 -0
- package/test/logic/41.7.3.2-alter-column-retype-unique-index.sqllogic +72 -0
- package/test/logic/41.7.4-alter-column-retype-semantic-memory.sqllogic +445 -0
- package/test/logic/41.7.4.1-alter-column-retype-semantic-index-memory.sqllogic +91 -0
- package/test/logic/41.7.5-alter-column-collate-pk-staged-delete-memory.sqllogic +106 -0
- package/test/logic/41.8-alter-add-constraint-unique-fk.sqllogic +275 -0
- package/test/logic/41.8-alter-savepoint-staged-rows.sqllogic +443 -0
- package/test/logic/41.8.1-alter-rename-savepoint-staged-rows.sqllogic +408 -0
- package/test/logic/41.9-alter-constraint-body-change.sqllogic +180 -0
- package/test/logic/41.9-fk-restrict-batched.sqllogic +290 -0
- package/test/logic/42-committed-snapshot.sqllogic +254 -0
- package/test/logic/42-returning.sqllogic +159 -0
- package/test/logic/42.1-returning-extras.sqllogic +232 -0
- package/test/logic/42.2-returning-stored-row.sqllogic +165 -0
- package/test/logic/43-default-nullability.sqllogic +131 -0
- package/test/logic/43-transition-constraints.sqllogic +341 -0
- package/test/logic/43.1-default-collation.sqllogic +140 -0
- package/test/logic/43.1-notnull-or-conflict.sqllogic +79 -0
- package/test/logic/43.2-deferred-check-new-on-delete.sqllogic +95 -0
- package/test/logic/43.3-nullable-primary-key.sqllogic +587 -0
- package/test/logic/44-determinism-validation.sqllogic +164 -0
- package/test/logic/44-orthogonality.sqllogic +146 -0
- package/test/logic/44.1-nondeterministic-schema.sqllogic +316 -0
- package/test/logic/45-udf-determinism.sqllogic +39 -0
- package/test/logic/46-mutation-context.sqllogic +595 -0
- package/test/logic/47-upsert.sqllogic +255 -0
- package/test/logic/47.1-upsert-conflict-targets.sqllogic +169 -0
- package/test/logic/47.2-replace-and-or-clauses.sqllogic +164 -0
- package/test/logic/47.2.1-pk-replace-secondary-unique.sqllogic +374 -0
- package/test/logic/47.3-engine-or-fail.sqllogic +122 -0
- package/test/logic/47.3-upsert-conflict-target-collation.sqllogic +139 -0
- package/test/logic/47.3.1-upsert-conflict-index-derived-collation.sqllogic +25 -0
- package/test/logic/47.4-upsert-conflict-target-affinity.sqllogic +59 -0
- package/test/logic/47.5-upsert-do-update-constraints.sqllogic +440 -0
- package/test/logic/47.6-upsert-do-update-decomposed.sqllogic +100 -0
- package/test/logic/49-reference-graph.sqllogic +84 -0
- package/test/logic/50-declarative-schema.sqllogic +2550 -0
- package/test/logic/50-metadata-tags.sqllogic +1033 -0
- package/test/logic/50.0.1-metadata-tags-index.sqllogic +141 -0
- package/test/logic/50.1-declare-schema-pk.sqllogic +150 -0
- package/test/logic/50.2-declare-schema-renames.sqllogic +949 -0
- package/test/logic/50.2.1-declare-schema-index-renames.sqllogic +173 -0
- package/test/logic/50.3-declare-schema-duplicate-names.sqllogic +280 -0
- package/test/logic/50.4-declare-schema-apply-restore.sqllogic +192 -0
- package/test/logic/51-lens-foundation.sqllogic +147 -0
- package/test/logic/51-materialized-views.sqllogic +376 -0
- package/test/logic/51.5-materialized-views-coarsened-key.sqllogic +198 -0
- package/test/logic/51.7-maintained-table-attach-detach.sqllogic +468 -0
- package/test/logic/51.8-maintained-table-declared-constraints.sqllogic +440 -0
- package/test/logic/51.85-maintained-table-parent-fk.sqllogic +103 -0
- package/test/logic/51.9-maintained-table-secondary-unique.sqllogic +237 -0
- package/test/logic/51.9.1-maintained-table-partial-unique.sqllogic +36 -0
- package/test/logic/52-lens-overrides.sqllogic +566 -0
- package/test/logic/53-materialized-views-rowtime.sqllogic +1601 -0
- package/test/logic/53-reserved-tags.sqllogic +252 -0
- package/test/logic/53.1-materialized-view-write-through.sqllogic +329 -0
- package/test/logic/53.2-materialized-view-rename-propagation.sqllogic +483 -0
- package/test/logic/53.3-materialized-view-constraint-only-ddl.sqllogic +409 -0
- package/test/logic/53.3.1-materialized-view-index-ddl-irrelevance.sqllogic +29 -0
- package/test/logic/53.4-materialized-view-structural-alter-restore.sqllogic +436 -0
- package/test/logic/54-covering-mv-enforcement.sqllogic +314 -0
- package/test/logic/54.1-covering-mv-partial-enforcement.sqllogic +34 -0
- package/test/logic/55-internal-eviction-reporting.sqllogic +89 -0
- package/test/logic/55-lens-prover.sqllogic +202 -0
- package/test/logic/55.1-eviction-restrict-fk.sqllogic +148 -0
- package/test/logic/55.5-lens-authored-inverse.sqllogic +1468 -0
- package/test/logic/80-grow-retrieve-pass.sqllogic +79 -0
- package/test/logic/81-quickpick.sqllogic +24 -0
- package/test/logic/82-bloom-join.sqllogic +185 -0
- package/test/logic/83-merge-join.sqllogic +280 -0
- package/test/logic/84-asof-scan.sqllogic +238 -0
- package/test/logic/84-key-cardinality.sqllogic +50 -0
- package/test/logic/85-relational-const-folding.sqllogic +51 -0
- package/test/logic/86-scalar-cse.sqllogic +42 -0
- package/test/logic/90-error_paths.sqllogic +114 -0
- package/test/logic/90.1-parse-errors.sqllogic +77 -0
- package/test/logic/90.2-alter-table-errors.sqllogic +53 -0
- package/test/logic/90.2.1-alter-extra-errors.sqllogic +51 -0
- package/test/logic/90.3-expression-errors.sqllogic +43 -0
- package/test/logic/90.4-dml-errors.sqllogic +47 -0
- package/test/logic/90.5-unsupported-join-types.sqllogic +37 -0
- package/test/logic/90.5.1-right-full-join-read.sqllogic +157 -0
- package/test/logic/90.6-select-error-paths.sqllogic +57 -0
- package/test/logic/91-merge-join-edge-cases.sqllogic +159 -0
- package/test/logic/92-hash-aggregate-edge-cases.sqllogic +139 -0
- package/test/logic/93-ddl-view-edge-cases.sqllogic +104 -0
- package/test/logic/93.1-view-error-paths.sqllogic +74 -0
- package/test/logic/93.2-view-mutation-pending.sqllogic +108 -0
- package/test/logic/93.3-view-mutation-or-clause.sqllogic +60 -0
- package/test/logic/93.4-view-mutation.sqllogic +4881 -0
- package/test/logic/93.4.1-view-mutation-partial-unique-cardinality.sqllogic +31 -0
- package/test/logic/93.5-authored-inverse.sqllogic +415 -0
- package/test/logic/93.6-set-op-flagless-write.sqllogic +862 -0
- package/test/logic/94-tvf-edge-cases.sqllogic +58 -0
- package/test/logic/94.1-limit-offset-edge-cases.sqllogic +109 -0
- package/test/logic/94.2-limit-offset-extras.sqllogic +98 -0
- package/test/logic/95-assertions.sqllogic +1417 -0
- package/test/logic/96-subquery-edge-cases.sqllogic +276 -0
- package/test/logic/97-json-function-edge-cases.sqllogic +633 -0
- package/test/logic/97.1-json-blob-and-special-values.sqllogic +92 -0
- package/test/logic/98-temporal-edge-cases.sqllogic +515 -0
- package/test/logic/99-conversion-edge-cases.sqllogic +325 -0
- package/test/logic/99.0.1-schema-index-listing.sqllogic +21 -0
- package/test/logic/99.1-cast-syntax-extras.sqllogic +167 -0
- package/test/logic/drop-unique-index.sqllogic +88 -0
- package/test/logic/pushdown-test.sqllogic +36 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- 90.3-expression-errors.sqllogic - Expression, subquery, and aggregate error paths
|
|
2
|
+
|
|
3
|
+
-- Scalar subquery with multiple columns
|
|
4
|
+
SELECT (SELECT 1, 2);
|
|
5
|
+
-- error: Scalar subquery must return exactly one column
|
|
6
|
+
|
|
7
|
+
-- IN subquery with multiple columns
|
|
8
|
+
SELECT 1 WHERE 1 IN (SELECT 1, 2);
|
|
9
|
+
-- error: IN subquery must return exactly one column
|
|
10
|
+
|
|
11
|
+
-- Duplicate CTE name
|
|
12
|
+
WITH c AS (SELECT 1 AS x), c AS (SELECT 2 AS x) SELECT * FROM c;
|
|
13
|
+
-- error: Duplicate CTE name 'c' in WITH clause
|
|
14
|
+
|
|
15
|
+
-- Aggregate function in WHERE clause
|
|
16
|
+
CREATE TABLE t_agg_ctx (id INTEGER PRIMARY KEY, val INTEGER);
|
|
17
|
+
INSERT INTO t_agg_ctx VALUES (1, 10), (2, 20);
|
|
18
|
+
-- run
|
|
19
|
+
|
|
20
|
+
SELECT * FROM t_agg_ctx WHERE count(*) > 1;
|
|
21
|
+
-- error: not allowed in this context
|
|
22
|
+
|
|
23
|
+
-- Window function requiring ORDER BY
|
|
24
|
+
SELECT rank() OVER () FROM t_agg_ctx;
|
|
25
|
+
-- error: requires ORDER BY clause
|
|
26
|
+
|
|
27
|
+
-- OLD qualifier in INSERT RETURNING
|
|
28
|
+
INSERT INTO t_agg_ctx VALUES (3, 30) RETURNING OLD.id;
|
|
29
|
+
-- error: OLD qualifier cannot be used in INSERT RETURNING clause
|
|
30
|
+
|
|
31
|
+
-- Cleanup
|
|
32
|
+
DROP TABLE t_agg_ctx;
|
|
33
|
+
-- run
|
|
34
|
+
|
|
35
|
+
-- NEW qualifier in DELETE RETURNING
|
|
36
|
+
CREATE TABLE t_del_ret (id INTEGER PRIMARY KEY, val INTEGER);
|
|
37
|
+
INSERT INTO t_del_ret VALUES (1, 10);
|
|
38
|
+
-- run
|
|
39
|
+
|
|
40
|
+
DELETE FROM t_del_ret WHERE id = 1 RETURNING NEW.id;
|
|
41
|
+
-- error: NEW qualifier cannot be used in DELETE RETURNING clause
|
|
42
|
+
|
|
43
|
+
DROP TABLE t_del_ret;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- 90.4-dml-errors.sqllogic - DML error paths (INSERT, UPDATE, DELETE edge cases)
|
|
2
|
+
|
|
3
|
+
-- VALUES clause column count mismatch (fewer values than columns)
|
|
4
|
+
CREATE TABLE t_vals (a INTEGER, b INTEGER, c INTEGER);
|
|
5
|
+
-- run
|
|
6
|
+
|
|
7
|
+
INSERT INTO t_vals VALUES (1, 2);
|
|
8
|
+
-- error: Column count mismatch
|
|
9
|
+
|
|
10
|
+
-- VALUES clause column count mismatch (more values than columns)
|
|
11
|
+
INSERT INTO t_vals VALUES (1, 2, 3, 4);
|
|
12
|
+
-- error: Column count mismatch
|
|
13
|
+
|
|
14
|
+
DROP TABLE t_vals;
|
|
15
|
+
-- run
|
|
16
|
+
|
|
17
|
+
-- INSERT with explicit column referencing non-existent column
|
|
18
|
+
CREATE TABLE t_insert_col (id INTEGER PRIMARY KEY, name TEXT);
|
|
19
|
+
-- run
|
|
20
|
+
|
|
21
|
+
INSERT INTO t_insert_col (id, missing_col) VALUES (1, 'x');
|
|
22
|
+
-- error: not found
|
|
23
|
+
|
|
24
|
+
DROP TABLE t_insert_col;
|
|
25
|
+
-- run
|
|
26
|
+
|
|
27
|
+
-- ON CONFLICT target with non-existent column
|
|
28
|
+
CREATE TABLE t_upsert_bad (id INTEGER PRIMARY KEY, val INTEGER);
|
|
29
|
+
-- run
|
|
30
|
+
|
|
31
|
+
INSERT INTO t_upsert_bad (id, val) VALUES (1, 10) ON CONFLICT (missing_col) DO NOTHING;
|
|
32
|
+
-- error: not found
|
|
33
|
+
|
|
34
|
+
DROP TABLE t_upsert_bad;
|
|
35
|
+
-- run
|
|
36
|
+
|
|
37
|
+
-- Mutating subquery without RETURNING clause
|
|
38
|
+
CREATE TABLE t_mut_src (id INTEGER PRIMARY KEY, val INTEGER);
|
|
39
|
+
CREATE TABLE t_mut_dst (id INTEGER PRIMARY KEY, val INTEGER);
|
|
40
|
+
INSERT INTO t_mut_src VALUES (1, 10);
|
|
41
|
+
-- run
|
|
42
|
+
|
|
43
|
+
INSERT INTO t_mut_dst SELECT * FROM (DELETE FROM t_mut_src WHERE id = 1);
|
|
44
|
+
-- error: must have a RETURNING clause
|
|
45
|
+
|
|
46
|
+
DROP TABLE t_mut_src;
|
|
47
|
+
DROP TABLE t_mut_dst;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
-- adapted from SQLite test/join.test, join7.test, joinB.test, joinH.test
|
|
2
|
+
-- RIGHT [OUTER] JOIN and FULL [OUTER] JOIN now execute in the nested-loop join
|
|
3
|
+
-- emitter (read path). NATURAL JOIN remains unparsed and is pinned as an error.
|
|
4
|
+
|
|
5
|
+
create table uj_l (id integer primary key, val text);
|
|
6
|
+
create table uj_r (id integer primary key, val text);
|
|
7
|
+
|
|
8
|
+
insert into uj_l values (1, 'L1'), (2, 'L2');
|
|
9
|
+
insert into uj_r values (1, 'R1'), (3, 'R3');
|
|
10
|
+
-- run
|
|
11
|
+
|
|
12
|
+
-- RIGHT JOIN: every right row appears; right id=3 has no left match → null-left.
|
|
13
|
+
select uj_l.id as l, uj_r.id as r from uj_l right join uj_r on uj_l.id = uj_r.id order by uj_r.id;
|
|
14
|
+
→ [{"l":1,"r":1},{"l":null,"r":3}]
|
|
15
|
+
|
|
16
|
+
-- RIGHT OUTER JOIN: same path, same rows.
|
|
17
|
+
select uj_l.id as l, uj_r.id as r from uj_l right outer join uj_r on uj_l.id = uj_r.id order by uj_r.id;
|
|
18
|
+
→ [{"l":1,"r":1},{"l":null,"r":3}]
|
|
19
|
+
|
|
20
|
+
-- FULL OUTER JOIN: matched (1,1), left id=2 unmatched (2,NULL), right id=3 unmatched (NULL,3).
|
|
21
|
+
select uj_l.id as l, uj_r.id as r from uj_l full outer join uj_r on uj_l.id = uj_r.id order by coalesce(uj_l.id, uj_r.id);
|
|
22
|
+
→ [{"l":1,"r":1},{"l":2,"r":null},{"l":null,"r":3}]
|
|
23
|
+
|
|
24
|
+
-- FULL JOIN (no OUTER keyword): same path, same rows.
|
|
25
|
+
select uj_l.id as l, uj_r.id as r from uj_l full join uj_r on uj_l.id = uj_r.id order by coalesce(uj_l.id, uj_r.id);
|
|
26
|
+
→ [{"l":1,"r":1},{"l":2,"r":null},{"l":null,"r":3}]
|
|
27
|
+
|
|
28
|
+
-- NATURAL JOIN: still not parsed (out of scope for this ticket).
|
|
29
|
+
select * from uj_l natural join uj_r;
|
|
30
|
+
-- error: NATURAL
|
|
31
|
+
|
|
32
|
+
-- NATURAL LEFT JOIN: still not parsed.
|
|
33
|
+
select * from uj_l natural left join uj_r;
|
|
34
|
+
-- error: NATURAL
|
|
35
|
+
|
|
36
|
+
drop table uj_l;
|
|
37
|
+
drop table uj_r;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
-- Read-path coverage for RIGHT / FULL outer joins in the nested-loop emitter
|
|
2
|
+
-- (runtime/emit/join.ts). Companion to 90.5, which flips the basic RIGHT/FULL
|
|
3
|
+
-- cases; this file pins column order, the empty-side matrix, no-match, many-to-many
|
|
4
|
+
-- (fan-out), USING, and existence (`exists … as`) flag semantics.
|
|
5
|
+
|
|
6
|
+
-- ===== select * column order: left columns first, then right columns =====
|
|
7
|
+
-- `a right/full join b` returns `a.*` then `b.*` (the JoinNode attribute order),
|
|
8
|
+
-- not the scan/drive order. Distinct column names avoid `:N` disambiguation so the
|
|
9
|
+
-- per-name values directly confirm left attrs occupy the left positions.
|
|
10
|
+
|
|
11
|
+
create table so_l (lid integer primary key, lval text);
|
|
12
|
+
create table so_r (rid integer primary key, rval text);
|
|
13
|
+
insert into so_l values (1, 'L1'), (2, 'L2');
|
|
14
|
+
insert into so_r values (1, 'R1'), (3, 'R3');
|
|
15
|
+
-- run
|
|
16
|
+
|
|
17
|
+
-- RIGHT: matched (1) plus right id=3 null-extended on the left.
|
|
18
|
+
select * from so_l right join so_r on so_l.lid = so_r.rid order by so_r.rid;
|
|
19
|
+
→ [{"lid":1,"lval":"L1","rid":1,"rval":"R1"},{"lid":null,"lval":null,"rid":3,"rval":"R3"}]
|
|
20
|
+
|
|
21
|
+
-- FULL: matched (1), left id=2 null-right, right id=3 null-left.
|
|
22
|
+
select * from so_l full join so_r on so_l.lid = so_r.rid order by coalesce(so_l.lid, so_r.rid);
|
|
23
|
+
→ [{"lid":1,"lval":"L1","rid":1,"rval":"R1"},{"lid":2,"lval":"L2","rid":null,"rval":null},{"lid":null,"lval":null,"rid":3,"rval":"R3"}]
|
|
24
|
+
|
|
25
|
+
drop table so_l;
|
|
26
|
+
drop table so_r;
|
|
27
|
+
-- run
|
|
28
|
+
|
|
29
|
+
-- ===== Empty-side matrix =====
|
|
30
|
+
|
|
31
|
+
create table es_full (k integer primary key, v text);
|
|
32
|
+
create table es_empty (k integer primary key, v text);
|
|
33
|
+
create table es_empty2 (k integer primary key, v text);
|
|
34
|
+
insert into es_full values (1, 'a'), (2, 'b');
|
|
35
|
+
-- run
|
|
36
|
+
|
|
37
|
+
-- left empty + RIGHT: every right row appears, null-extended on the left.
|
|
38
|
+
select es_empty.k as lk, es_full.k as rk from es_empty right join es_full on es_empty.k = es_full.k order by es_full.k;
|
|
39
|
+
→ [{"lk":null,"rk":1},{"lk":null,"rk":2}]
|
|
40
|
+
|
|
41
|
+
-- right empty + RIGHT: no rows at all.
|
|
42
|
+
select es_full.k as lk, es_empty.k as rk from es_full right join es_empty on es_full.k = es_empty.k order by es_empty.k;
|
|
43
|
+
→ []
|
|
44
|
+
|
|
45
|
+
-- both empty + FULL: no rows.
|
|
46
|
+
select a.k as lk, b.k as rk from es_empty a full join es_empty2 b on a.k = b.k;
|
|
47
|
+
→ []
|
|
48
|
+
|
|
49
|
+
-- left non-empty + right empty + FULL: every left row null-extended on the right (trailing pass only).
|
|
50
|
+
select es_full.k as lk, es_empty.k as rk from es_full full join es_empty on es_full.k = es_empty.k order by es_full.k;
|
|
51
|
+
→ [{"lk":1,"rk":null},{"lk":2,"rk":null}]
|
|
52
|
+
|
|
53
|
+
-- left empty + FULL: every right row null-extended on the left (no trailing rows).
|
|
54
|
+
select es_empty.k as lk, es_full.k as rk from es_empty full join es_full on es_empty.k = es_full.k order by es_full.k;
|
|
55
|
+
→ [{"lk":null,"rk":1},{"lk":null,"rk":2}]
|
|
56
|
+
|
|
57
|
+
drop table es_full;
|
|
58
|
+
drop table es_empty;
|
|
59
|
+
drop table es_empty2;
|
|
60
|
+
-- run
|
|
61
|
+
|
|
62
|
+
-- ===== No match at all =====
|
|
63
|
+
|
|
64
|
+
create table nm_l (id integer primary key);
|
|
65
|
+
create table nm_r (id integer primary key);
|
|
66
|
+
insert into nm_l values (1), (2);
|
|
67
|
+
insert into nm_r values (3), (4);
|
|
68
|
+
-- run
|
|
69
|
+
|
|
70
|
+
-- RIGHT, predicate matches nothing: all right rows null-left.
|
|
71
|
+
select nm_l.id as l, nm_r.id as r from nm_l right join nm_r on nm_l.id = nm_r.id order by nm_r.id;
|
|
72
|
+
→ [{"l":null,"r":3},{"l":null,"r":4}]
|
|
73
|
+
|
|
74
|
+
-- FULL, predicate matches nothing: all right null-left AND all left null-right.
|
|
75
|
+
select nm_l.id as l, nm_r.id as r from nm_l full join nm_r on nm_l.id = nm_r.id order by coalesce(nm_l.id, nm_r.id);
|
|
76
|
+
→ [{"l":1,"r":null},{"l":2,"r":null},{"l":null,"r":3},{"l":null,"r":4}]
|
|
77
|
+
|
|
78
|
+
drop table nm_l;
|
|
79
|
+
drop table nm_r;
|
|
80
|
+
-- run
|
|
81
|
+
|
|
82
|
+
-- ===== Many-to-many (duplicate join keys): one row per match, no spurious null-extension =====
|
|
83
|
+
|
|
84
|
+
create table mm_l (id integer primary key, k integer);
|
|
85
|
+
create table mm_r (id integer primary key, k integer);
|
|
86
|
+
-- k=1 twice on each side; k=2 only on right; k=3 only on left.
|
|
87
|
+
insert into mm_l values (1, 1), (2, 1), (3, 3);
|
|
88
|
+
insert into mm_r values (10, 1), (11, 1), (12, 2);
|
|
89
|
+
-- run
|
|
90
|
+
|
|
91
|
+
-- RIGHT: right rows 10 & 11 (k=1) each match BOTH left k=1 rows (2 each); right row
|
|
92
|
+
-- 12 (k=2) has no match → one null-left row. No matched right row is null-extended.
|
|
93
|
+
select mm_l.id as lid, mm_r.id as rid from mm_l right join mm_r on mm_l.k = mm_r.k order by mm_r.id, mm_l.id;
|
|
94
|
+
→ [{"lid":1,"rid":10},{"lid":2,"rid":10},{"lid":1,"rid":11},{"lid":2,"rid":11},{"lid":null,"rid":12}]
|
|
95
|
+
|
|
96
|
+
-- FULL: the same matched/null-left rows, plus left row 3 (k=3) null-right exactly once.
|
|
97
|
+
select mm_l.id as lid, mm_r.id as rid from mm_l full join mm_r on mm_l.k = mm_r.k order by coalesce(mm_r.id, 999), coalesce(mm_l.id, 999);
|
|
98
|
+
→ [{"lid":1,"rid":10},{"lid":2,"rid":10},{"lid":1,"rid":11},{"lid":2,"rid":11},{"lid":null,"rid":12},{"lid":3,"rid":null}]
|
|
99
|
+
|
|
100
|
+
drop table mm_l;
|
|
101
|
+
drop table mm_r;
|
|
102
|
+
-- run
|
|
103
|
+
|
|
104
|
+
-- ===== USING join (order-agnostic equality in the right-driven loop) =====
|
|
105
|
+
|
|
106
|
+
create table us_l (id integer primary key, val text);
|
|
107
|
+
create table us_r (id integer primary key, val text);
|
|
108
|
+
insert into us_l values (1, 'L1'), (2, 'L2');
|
|
109
|
+
insert into us_r values (1, 'R1'), (3, 'R3');
|
|
110
|
+
-- run
|
|
111
|
+
|
|
112
|
+
-- right join … using (id): same shape as the ON form; right id=3 null-left.
|
|
113
|
+
select us_l.id as l, us_r.id as r from us_l right join us_r using (id) order by us_r.id;
|
|
114
|
+
→ [{"l":1,"r":1},{"l":null,"r":3}]
|
|
115
|
+
|
|
116
|
+
-- full join … using (id): both unmatched sides surface.
|
|
117
|
+
select us_l.id as l, us_r.id as r from us_l full join us_r using (id) order by coalesce(us_l.id, us_r.id);
|
|
118
|
+
→ [{"l":1,"r":1},{"l":2,"r":null},{"l":null,"r":3}]
|
|
119
|
+
|
|
120
|
+
drop table us_l;
|
|
121
|
+
drop table us_r;
|
|
122
|
+
-- run
|
|
123
|
+
|
|
124
|
+
-- ===== Existence flags on RIGHT (non-preserved side = left) =====
|
|
125
|
+
-- `exists as h` resolves to the only null-extendable side (left) of a RIGHT join.
|
|
126
|
+
-- A matched row sets h=true; a left-null-extended row sets h=false.
|
|
127
|
+
|
|
128
|
+
create table ex_l (id integer primary key, val text);
|
|
129
|
+
create table ex_r (id integer primary key, val text);
|
|
130
|
+
insert into ex_l values (1, 'L1');
|
|
131
|
+
insert into ex_r values (1, 'R1'), (2, 'R2');
|
|
132
|
+
-- run
|
|
133
|
+
|
|
134
|
+
select ex_r.id as r, h from ex_l right join ex_r on ex_l.id = ex_r.id exists as h order by ex_r.id;
|
|
135
|
+
→ [{"r":1,"h":true},{"r":2,"h":false}]
|
|
136
|
+
|
|
137
|
+
drop table ex_l;
|
|
138
|
+
drop table ex_r;
|
|
139
|
+
-- run
|
|
140
|
+
|
|
141
|
+
-- ===== Existence flags on FULL (both sides null-extendable) =====
|
|
142
|
+
-- fl = "left present", fr = "right present". Matched → both true; right-only row →
|
|
143
|
+
-- fl false, fr true; left-only row → fl true, fr false.
|
|
144
|
+
|
|
145
|
+
create table fe_l (id integer primary key);
|
|
146
|
+
create table fe_r (id integer primary key);
|
|
147
|
+
insert into fe_l values (1), (2);
|
|
148
|
+
insert into fe_r values (1), (3);
|
|
149
|
+
-- run
|
|
150
|
+
|
|
151
|
+
select fe_l.id as l, fe_r.id as r, fl, fr
|
|
152
|
+
from fe_l full join fe_r on fe_l.id = fe_r.id exists left as fl, exists right as fr
|
|
153
|
+
order by coalesce(fe_l.id, fe_r.id);
|
|
154
|
+
→ [{"l":1,"r":1,"fl":true,"fr":true},{"l":2,"r":null,"fl":true,"fr":false},{"l":null,"r":3,"fl":false,"fr":true}]
|
|
155
|
+
|
|
156
|
+
drop table fe_l;
|
|
157
|
+
drop table fe_r;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
-- adapted from SQLite test/select1.test, test/select5.test, test/e_select.test
|
|
2
|
+
-- SELECT-side error paths: wrong-arity aggregate calls, ORDER BY positional
|
|
3
|
+
-- references that are out of range, and aggregate references in disallowed
|
|
4
|
+
-- contexts.
|
|
5
|
+
|
|
6
|
+
create table eptab (id integer primary key, a integer, b integer);
|
|
7
|
+
insert into eptab values (1, 11, 22), (2, 33, 44);
|
|
8
|
+
|
|
9
|
+
-- count() with two arguments is rejected
|
|
10
|
+
select count(a, b) from eptab;
|
|
11
|
+
-- error: count
|
|
12
|
+
|
|
13
|
+
-- sum() with two arguments is rejected
|
|
14
|
+
select sum(a, b) from eptab;
|
|
15
|
+
-- error: sum
|
|
16
|
+
|
|
17
|
+
-- min(*) and max(*) — the star form is reserved for count() only
|
|
18
|
+
select min(*) from eptab;
|
|
19
|
+
-- error: min
|
|
20
|
+
|
|
21
|
+
select max(*) from eptab;
|
|
22
|
+
-- error: max
|
|
23
|
+
|
|
24
|
+
-- Out-of-range / zero / negative ordinal references in GROUP BY and ORDER BY
|
|
25
|
+
-- raise an error at planning time.
|
|
26
|
+
select a from eptab group by 0;
|
|
27
|
+
-- error: GROUP BY position 0
|
|
28
|
+
|
|
29
|
+
select a from eptab group by 2;
|
|
30
|
+
-- error: GROUP BY position 2
|
|
31
|
+
|
|
32
|
+
select a from eptab order by -1;
|
|
33
|
+
-- error: ORDER BY position -1
|
|
34
|
+
|
|
35
|
+
select a from eptab order by 99;
|
|
36
|
+
-- error: ORDER BY position 99
|
|
37
|
+
|
|
38
|
+
drop table eptab;
|
|
39
|
+
|
|
40
|
+
-- =============================================================================
|
|
41
|
+
-- Compound SELECT column-count mismatch — branches must agree
|
|
42
|
+
-- =============================================================================
|
|
43
|
+
|
|
44
|
+
select 1
|
|
45
|
+
union
|
|
46
|
+
select 1, 2;
|
|
47
|
+
-- error: column
|
|
48
|
+
|
|
49
|
+
select 1, 2
|
|
50
|
+
intersect
|
|
51
|
+
select 1;
|
|
52
|
+
-- error: column
|
|
53
|
+
|
|
54
|
+
select 1, 2
|
|
55
|
+
except
|
|
56
|
+
select 1;
|
|
57
|
+
-- error: column
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
-- merge-join-edge-cases.sqllogic - Edge cases for join emitters (merge/hash)
|
|
2
|
+
-- Targets: merge-join.ts branches — self-joins, residual conditions, NULL keys, many-to-many
|
|
3
|
+
|
|
4
|
+
-- Self-join: cross-product within each group
|
|
5
|
+
CREATE TABLE mj_self (id INTEGER PRIMARY KEY, grp INTEGER, label TEXT);
|
|
6
|
+
INSERT INTO mj_self VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 2, 'd'), (5, 3, 'e');
|
|
7
|
+
|
|
8
|
+
SELECT a.id AS aid, b.id AS bid
|
|
9
|
+
FROM mj_self a JOIN mj_self b ON a.grp = b.grp
|
|
10
|
+
ORDER BY aid, bid;
|
|
11
|
+
→ [{"aid":1,"bid":1},{"aid":1,"bid":2},{"aid":2,"bid":1},{"aid":2,"bid":2},{"aid":3,"bid":3},{"aid":3,"bid":4},{"aid":4,"bid":3},{"aid":4,"bid":4},{"aid":5,"bid":5}]
|
|
12
|
+
|
|
13
|
+
-- Self LEFT JOIN with residual condition: equi on grp, residual a.id != b.id
|
|
14
|
+
-- id=5 (grp=3) is the only row in its group, so residual filters out the self-match → NULL padded
|
|
15
|
+
SELECT a.id AS aid, b.id AS bid
|
|
16
|
+
FROM mj_self a LEFT JOIN mj_self b ON a.grp = b.grp AND a.id != b.id
|
|
17
|
+
ORDER BY aid, bid;
|
|
18
|
+
→ [{"aid":1,"bid":2},{"aid":2,"bid":1},{"aid":3,"bid":4},{"aid":4,"bid":3},{"aid":5,"bid":null}]
|
|
19
|
+
|
|
20
|
+
-- JOIN with residual inequality: only pairs where left label < right label
|
|
21
|
+
SELECT a.id AS aid, b.id AS bid
|
|
22
|
+
FROM mj_self a JOIN mj_self b ON a.grp = b.grp AND a.label < b.label
|
|
23
|
+
ORDER BY aid, bid;
|
|
24
|
+
→ [{"aid":1,"bid":2},{"aid":3,"bid":4}]
|
|
25
|
+
|
|
26
|
+
-- All-NULL join keys: NULLs never match per SQL standard
|
|
27
|
+
CREATE TABLE mj_allnull (id INTEGER PRIMARY KEY, val INTEGER NULL);
|
|
28
|
+
INSERT INTO mj_allnull VALUES (1, null), (2, null), (3, null);
|
|
29
|
+
|
|
30
|
+
SELECT a.id, b.id FROM mj_allnull a JOIN mj_allnull b ON a.val = b.val;
|
|
31
|
+
→ []
|
|
32
|
+
|
|
33
|
+
-- LEFT JOIN with all-NULL keys: every left row is unmatched
|
|
34
|
+
SELECT a.id, b.id FROM mj_allnull a LEFT JOIN mj_allnull b ON a.val = b.val ORDER BY a.id;
|
|
35
|
+
→ [{"id":1,"id:1":null},{"id":2,"id:1":null},{"id":3,"id:1":null}]
|
|
36
|
+
|
|
37
|
+
-- Mixed NULL and non-NULL join keys
|
|
38
|
+
CREATE TABLE mj_mixed (id INTEGER PRIMARY KEY, val INTEGER NULL);
|
|
39
|
+
INSERT INTO mj_mixed VALUES (1, 10), (2, null), (3, 20), (4, null), (5, 10);
|
|
40
|
+
|
|
41
|
+
-- INNER JOIN: NULLs excluded, matching non-NULLs produce cross-product
|
|
42
|
+
SELECT a.id AS aid, b.id AS bid
|
|
43
|
+
FROM mj_mixed a JOIN mj_mixed b ON a.val = b.val
|
|
44
|
+
ORDER BY aid, bid;
|
|
45
|
+
→ [{"aid":1,"bid":1},{"aid":1,"bid":5},{"aid":3,"bid":3},{"aid":5,"bid":1},{"aid":5,"bid":5}]
|
|
46
|
+
|
|
47
|
+
-- LEFT JOIN: NULL-keyed rows get NULL padding, matched rows get cross-product
|
|
48
|
+
SELECT a.id AS aid, b.id AS bid
|
|
49
|
+
FROM mj_mixed a LEFT JOIN mj_mixed b ON a.val = b.val
|
|
50
|
+
ORDER BY aid, bid;
|
|
51
|
+
→ [{"aid":1,"bid":1},{"aid":1,"bid":5},{"aid":2,"bid":null},{"aid":3,"bid":3},{"aid":4,"bid":null},{"aid":5,"bid":1},{"aid":5,"bid":5}]
|
|
52
|
+
|
|
53
|
+
-- Many-to-many with asymmetric cardinality
|
|
54
|
+
CREATE TABLE mj_m2m_l (id INTEGER PRIMARY KEY, key INTEGER);
|
|
55
|
+
CREATE TABLE mj_m2m_r (id INTEGER PRIMARY KEY, key INTEGER);
|
|
56
|
+
INSERT INTO mj_m2m_l VALUES (1, 10), (2, 10), (3, 10), (4, 20);
|
|
57
|
+
INSERT INTO mj_m2m_r VALUES (10, 10), (20, 10), (30, 20), (40, 20), (50, 20);
|
|
58
|
+
|
|
59
|
+
-- 3×2=6 for key=10, 1×3=3 for key=20 → total 9
|
|
60
|
+
SELECT count(*) AS cnt FROM mj_m2m_l l JOIN mj_m2m_r r ON l.key = r.key;
|
|
61
|
+
→ [{"cnt":9}]
|
|
62
|
+
|
|
63
|
+
-- LEFT JOIN preserves all left rows with correct match counts
|
|
64
|
+
SELECT l.id, count(r.id) AS matches
|
|
65
|
+
FROM mj_m2m_l l LEFT JOIN mj_m2m_r r ON l.key = r.key
|
|
66
|
+
GROUP BY l.id ORDER BY l.id;
|
|
67
|
+
→ [{"id":1,"matches":2},{"id":2,"matches":2},{"id":3,"matches":2},{"id":4,"matches":3}]
|
|
68
|
+
|
|
69
|
+
-- Join where one side is empty (inner and left)
|
|
70
|
+
CREATE TABLE mj_populated (id INTEGER PRIMARY KEY, val INTEGER);
|
|
71
|
+
CREATE TABLE mj_empty (id INTEGER PRIMARY KEY, val INTEGER);
|
|
72
|
+
INSERT INTO mj_populated VALUES (1, 10), (2, 20);
|
|
73
|
+
|
|
74
|
+
SELECT p.id FROM mj_populated p JOIN mj_empty e ON p.val = e.val;
|
|
75
|
+
→ []
|
|
76
|
+
|
|
77
|
+
SELECT p.id, e.id AS eid FROM mj_populated p LEFT JOIN mj_empty e ON p.val = e.val ORDER BY p.id;
|
|
78
|
+
→ [{"id":1,"eid":null},{"id":2,"eid":null}]
|
|
79
|
+
|
|
80
|
+
-- Both sides empty
|
|
81
|
+
SELECT a.id FROM mj_empty a JOIN mj_empty b ON a.val = b.val;
|
|
82
|
+
→ []
|
|
83
|
+
|
|
84
|
+
-- Multi-column join with partial key matches
|
|
85
|
+
CREATE TABLE mj_mc_l (a INTEGER, b INTEGER, v TEXT, PRIMARY KEY (a, b));
|
|
86
|
+
CREATE TABLE mj_mc_r (x INTEGER, y INTEGER, w TEXT, PRIMARY KEY (x, y));
|
|
87
|
+
|
|
88
|
+
INSERT INTO mj_mc_l VALUES (1, 10, 'p'), (1, 20, 'q'), (2, 10, 'r');
|
|
89
|
+
INSERT INTO mj_mc_r VALUES (1, 10, 's'), (1, 30, 't'), (2, 10, 'u');
|
|
90
|
+
|
|
91
|
+
-- Only (1,10) and (2,10) match on both columns
|
|
92
|
+
SELECT l.v, r.w FROM mj_mc_l l JOIN mj_mc_r r ON l.a = r.x AND l.b = r.y ORDER BY l.a, l.b;
|
|
93
|
+
→ [{"v":"p","w":"s"},{"v":"r","w":"u"}]
|
|
94
|
+
|
|
95
|
+
-- LEFT JOIN: (1,20) has no match on both columns → NULL padded
|
|
96
|
+
SELECT l.a, l.b, r.w FROM mj_mc_l l LEFT JOIN mj_mc_r r ON l.a = r.x AND l.b = r.y ORDER BY l.a, l.b;
|
|
97
|
+
→ [{"a":1,"b":10,"w":"s"},{"a":1,"b":20,"w":null},{"a":2,"b":10,"w":"u"}]
|
|
98
|
+
|
|
99
|
+
-- DESC primary key: the scan's advertised ordering must carry the declared
|
|
100
|
+
-- direction, or a merge join built on it drops all but one matching row.
|
|
101
|
+
-- (bug-desc-pk-scan-advertises-ascending-order)
|
|
102
|
+
CREATE TABLE mj_dpk (id INTEGER, v TEXT, PRIMARY KEY (id DESC));
|
|
103
|
+
CREATE TABLE mj_small (id INTEGER PRIMARY KEY);
|
|
104
|
+
INSERT INTO mj_dpk VALUES (1, 'a'), (2, 'b'), (3, 'c');
|
|
105
|
+
INSERT INTO mj_small VALUES (1), (2), (3);
|
|
106
|
+
|
|
107
|
+
SELECT id FROM mj_dpk WHERE id IN (SELECT id FROM mj_small) ORDER BY id;
|
|
108
|
+
→ [{"id":1},{"id":2},{"id":3}]
|
|
109
|
+
|
|
110
|
+
SELECT id FROM mj_dpk d WHERE EXISTS (SELECT 1 FROM mj_small s WHERE s.id = d.id) ORDER BY id;
|
|
111
|
+
→ [{"id":1},{"id":2},{"id":3}]
|
|
112
|
+
|
|
113
|
+
SELECT d.id FROM mj_dpk d JOIN mj_small s ON s.id = d.id ORDER BY d.id;
|
|
114
|
+
→ [{"id":1},{"id":2},{"id":3}]
|
|
115
|
+
|
|
116
|
+
SELECT d.id AS did, s.id AS sid FROM mj_dpk d LEFT JOIN mj_small s ON s.id = d.id ORDER BY d.id;
|
|
117
|
+
→ [{"did":1,"sid":1},{"did":2,"sid":2},{"did":3,"sid":3}]
|
|
118
|
+
|
|
119
|
+
-- Sort absorption over the same advertisement: an ORDER BY must not be elided
|
|
120
|
+
-- against a stream that runs the other way.
|
|
121
|
+
SELECT id FROM mj_dpk ORDER BY id;
|
|
122
|
+
→ [{"id":1},{"id":2},{"id":3}]
|
|
123
|
+
|
|
124
|
+
SELECT id FROM mj_dpk ORDER BY id DESC;
|
|
125
|
+
→ [{"id":3},{"id":2},{"id":1}]
|
|
126
|
+
|
|
127
|
+
-- Composite PK with mixed directions: the advertisement is per-column, so the
|
|
128
|
+
-- ASC member and the DESC member must each carry their own direction.
|
|
129
|
+
CREATE TABLE mj_mixdir (a INTEGER, b INTEGER, v TEXT, PRIMARY KEY (a ASC, b DESC));
|
|
130
|
+
CREATE TABLE mj_mixdir_r (a INTEGER, b INTEGER, w TEXT, PRIMARY KEY (a ASC, b DESC));
|
|
131
|
+
INSERT INTO mj_mixdir VALUES (1, 10, 'p'), (1, 20, 'q'), (2, 10, 'r');
|
|
132
|
+
INSERT INTO mj_mixdir_r VALUES (1, 10, 's'), (1, 20, 't'), (2, 10, 'u');
|
|
133
|
+
|
|
134
|
+
SELECT l.v, r.w FROM mj_mixdir l JOIN mj_mixdir_r r ON l.a = r.a AND l.b = r.b ORDER BY l.a, l.b;
|
|
135
|
+
→ [{"v":"p","w":"s"},{"v":"q","w":"t"},{"v":"r","w":"u"}]
|
|
136
|
+
|
|
137
|
+
SELECT l.a, l.b, r.w FROM mj_mixdir l LEFT JOIN mj_mixdir_r r ON l.a = r.a AND l.b = r.b ORDER BY l.a, l.b;
|
|
138
|
+
→ [{"a":1,"b":10,"w":"s"},{"a":1,"b":20,"w":"t"},{"a":2,"b":10,"w":"u"}]
|
|
139
|
+
|
|
140
|
+
SELECT a, b FROM mj_mixdir ORDER BY a, b;
|
|
141
|
+
→ [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":10}]
|
|
142
|
+
|
|
143
|
+
SELECT a, b FROM mj_mixdir ORDER BY a, b DESC;
|
|
144
|
+
→ [{"a":1,"b":20},{"a":1,"b":10},{"a":2,"b":10}]
|
|
145
|
+
|
|
146
|
+
-- Cleanup
|
|
147
|
+
DROP TABLE mj_self;
|
|
148
|
+
DROP TABLE mj_allnull;
|
|
149
|
+
DROP TABLE mj_mixed;
|
|
150
|
+
DROP TABLE mj_m2m_l;
|
|
151
|
+
DROP TABLE mj_m2m_r;
|
|
152
|
+
DROP TABLE mj_populated;
|
|
153
|
+
DROP TABLE mj_empty;
|
|
154
|
+
DROP TABLE mj_mc_l;
|
|
155
|
+
DROP TABLE mj_mc_r;
|
|
156
|
+
DROP TABLE mj_dpk;
|
|
157
|
+
DROP TABLE mj_small;
|
|
158
|
+
DROP TABLE mj_mixdir;
|
|
159
|
+
DROP TABLE mj_mixdir_r;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
-- hash-aggregate-edge-cases.sqllogic - Edge cases for hash aggregate emitter
|
|
2
|
+
-- Targets: hash-aggregate.ts — empty input, NULL groups, DISTINCT aggregates, expression keys
|
|
3
|
+
|
|
4
|
+
-- Empty table with GROUP BY → no rows (not a single NULL row)
|
|
5
|
+
CREATE TABLE ha_empty (id INTEGER PRIMARY KEY, grp TEXT, val INTEGER NULL);
|
|
6
|
+
|
|
7
|
+
SELECT grp, count(*) AS cnt FROM ha_empty GROUP BY grp;
|
|
8
|
+
→ []
|
|
9
|
+
|
|
10
|
+
SELECT grp, sum(val) AS total FROM ha_empty GROUP BY grp;
|
|
11
|
+
→ []
|
|
12
|
+
|
|
13
|
+
DROP TABLE ha_empty;
|
|
14
|
+
|
|
15
|
+
-- All-NULL group key → single NULL group
|
|
16
|
+
CREATE TABLE ha_null_grp (id INTEGER PRIMARY KEY, grp TEXT NULL, val INTEGER);
|
|
17
|
+
INSERT INTO ha_null_grp VALUES (1, null, 10), (2, null, 20), (3, null, 30);
|
|
18
|
+
|
|
19
|
+
SELECT grp, count(*) AS cnt, sum(val) AS total FROM ha_null_grp GROUP BY grp;
|
|
20
|
+
→ [{"grp":null,"cnt":3,"total":60}]
|
|
21
|
+
|
|
22
|
+
-- Multiple NULL groups and non-NULL groups coexist
|
|
23
|
+
INSERT INTO ha_null_grp VALUES (4, 'x', 40), (5, 'x', 50);
|
|
24
|
+
|
|
25
|
+
SELECT grp, count(*) AS cnt FROM ha_null_grp GROUP BY grp ORDER BY grp NULLS FIRST;
|
|
26
|
+
→ [{"grp":null,"cnt":3},{"grp":"x","cnt":2}]
|
|
27
|
+
|
|
28
|
+
DROP TABLE ha_null_grp;
|
|
29
|
+
|
|
30
|
+
-- SUM(DISTINCT col) with NULLs: NULLs excluded from distinct tracking
|
|
31
|
+
CREATE TABLE ha_dist (id INTEGER PRIMARY KEY, val INTEGER NULL);
|
|
32
|
+
INSERT INTO ha_dist VALUES (1, 10), (2, 20), (3, 10), (4, null), (5, 20), (6, null);
|
|
33
|
+
|
|
34
|
+
SELECT sum(distinct val) AS sd FROM ha_dist;
|
|
35
|
+
→ [{"sd":30}]
|
|
36
|
+
|
|
37
|
+
-- count(*) vs count(col) vs count(distinct col) with NULLs
|
|
38
|
+
SELECT count(*) AS c_star, count(val) AS c_val, count(distinct val) AS c_dval FROM ha_dist;
|
|
39
|
+
→ [{"c_star":6,"c_val":4,"c_dval":2}]
|
|
40
|
+
|
|
41
|
+
-- AVG(DISTINCT col)
|
|
42
|
+
SELECT avg(distinct val) AS ad FROM ha_dist;
|
|
43
|
+
→ [{"ad":15}]
|
|
44
|
+
|
|
45
|
+
-- Multiple DISTINCT aggregates in same query
|
|
46
|
+
SELECT count(distinct val) AS cd, sum(distinct val) AS sd, avg(distinct val) AS ad FROM ha_dist;
|
|
47
|
+
→ [{"cd":2,"sd":30,"ad":15}]
|
|
48
|
+
|
|
49
|
+
DROP TABLE ha_dist;
|
|
50
|
+
|
|
51
|
+
-- SUM(DISTINCT) with GROUP BY
|
|
52
|
+
CREATE TABLE ha_dist_grp (id INTEGER PRIMARY KEY, grp TEXT, val INTEGER NULL);
|
|
53
|
+
INSERT INTO ha_dist_grp VALUES (1, 'a', 10), (2, 'a', 10), (3, 'a', 20), (4, 'b', 30), (5, 'b', null);
|
|
54
|
+
|
|
55
|
+
SELECT grp, sum(distinct val) AS sd, count(distinct val) AS cd FROM ha_dist_grp GROUP BY grp ORDER BY grp;
|
|
56
|
+
→ [{"grp":"a","sd":30,"cd":2},{"grp":"b","sd":30,"cd":1}]
|
|
57
|
+
|
|
58
|
+
DROP TABLE ha_dist_grp;
|
|
59
|
+
|
|
60
|
+
-- All-NULL value column: aggregates return null (except count(*) and count)
|
|
61
|
+
CREATE TABLE ha_allnull (id INTEGER PRIMARY KEY, val INTEGER NULL);
|
|
62
|
+
INSERT INTO ha_allnull VALUES (1, null), (2, null), (3, null);
|
|
63
|
+
|
|
64
|
+
SELECT count(*) AS c_star, count(val) AS c_val, sum(val) AS s, avg(val) AS a, min(val) AS mn, max(val) AS mx FROM ha_allnull;
|
|
65
|
+
→ [{"c_star":3,"c_val":0,"s":null,"a":null,"mn":null,"mx":null}]
|
|
66
|
+
|
|
67
|
+
DROP TABLE ha_allnull;
|
|
68
|
+
|
|
69
|
+
-- GROUP BY on expression
|
|
70
|
+
CREATE TABLE ha_expr (id INTEGER PRIMARY KEY, name TEXT, val INTEGER);
|
|
71
|
+
INSERT INTO ha_expr VALUES (1, 'a', 10), (2, 'bb', 20), (3, 'ccc', 30), (4, 'dd', 40);
|
|
72
|
+
|
|
73
|
+
SELECT length(name) AS name_len, sum(val) AS total FROM ha_expr GROUP BY length(name) ORDER BY length(name);
|
|
74
|
+
→ [{"name_len":1,"total":10},{"name_len":2,"total":60},{"name_len":3,"total":30}]
|
|
75
|
+
|
|
76
|
+
DROP TABLE ha_expr;
|
|
77
|
+
|
|
78
|
+
-- Single-row groups (each row is its own group)
|
|
79
|
+
CREATE TABLE ha_single (id INTEGER PRIMARY KEY, val INTEGER);
|
|
80
|
+
INSERT INTO ha_single VALUES (1, 100), (2, 200), (3, 300);
|
|
81
|
+
|
|
82
|
+
SELECT id, count(*) AS cnt, sum(val) AS total FROM ha_single GROUP BY id ORDER BY id;
|
|
83
|
+
→ [{"id":1,"cnt":1,"total":100},{"id":2,"cnt":1,"total":200},{"id":3,"cnt":1,"total":300}]
|
|
84
|
+
|
|
85
|
+
DROP TABLE ha_single;
|
|
86
|
+
|
|
87
|
+
-- HAVING that filters all groups → empty result
|
|
88
|
+
CREATE TABLE ha_having (id INTEGER PRIMARY KEY, grp TEXT, val INTEGER);
|
|
89
|
+
INSERT INTO ha_having VALUES (1, 'a', 10), (2, 'b', 20);
|
|
90
|
+
|
|
91
|
+
SELECT grp, sum(val) AS total FROM ha_having GROUP BY grp HAVING sum(val) > 1000;
|
|
92
|
+
→ []
|
|
93
|
+
|
|
94
|
+
-- HAVING with DISTINCT aggregate
|
|
95
|
+
SELECT grp, count(distinct val) AS cd FROM ha_having GROUP BY grp HAVING count(distinct val) > 5;
|
|
96
|
+
→ []
|
|
97
|
+
|
|
98
|
+
DROP TABLE ha_having;
|
|
99
|
+
|
|
100
|
+
-- Aggregate without GROUP BY on empty table: returns single row with initial values
|
|
101
|
+
CREATE TABLE ha_empty_agg (id INTEGER PRIMARY KEY, val INTEGER NULL);
|
|
102
|
+
|
|
103
|
+
SELECT count(*) AS cnt, sum(val) AS s, min(val) AS mn, max(val) AS mx FROM ha_empty_agg;
|
|
104
|
+
→ [{"cnt":0,"s":null,"mn":null,"mx":null}]
|
|
105
|
+
|
|
106
|
+
DROP TABLE ha_empty_agg;
|
|
107
|
+
|
|
108
|
+
-- GROUP BY with multiple columns including NULL
|
|
109
|
+
CREATE TABLE ha_multi_grp (id INTEGER PRIMARY KEY, a TEXT NULL, b INTEGER NULL, val INTEGER);
|
|
110
|
+
INSERT INTO ha_multi_grp VALUES (1, 'x', 1, 10), (2, 'x', 1, 20), (3, 'x', null, 30), (4, null, 1, 40), (5, null, null, 50);
|
|
111
|
+
|
|
112
|
+
SELECT a, b, count(*) AS cnt, sum(val) AS total
|
|
113
|
+
FROM ha_multi_grp GROUP BY a, b ORDER BY a NULLS FIRST, b NULLS FIRST;
|
|
114
|
+
→ [{"a":null,"b":null,"cnt":1,"total":50},{"a":null,"b":1,"cnt":1,"total":40},{"a":"x","b":null,"cnt":1,"total":30},{"a":"x","b":1,"cnt":2,"total":30}]
|
|
115
|
+
|
|
116
|
+
DROP TABLE ha_multi_grp;
|
|
117
|
+
|
|
118
|
+
-- group_concat(DISTINCT) — distinct string aggregation
|
|
119
|
+
CREATE TABLE ha_gc (id INTEGER PRIMARY KEY, grp TEXT, tag TEXT NULL);
|
|
120
|
+
INSERT INTO ha_gc VALUES (1, 'a', 'x'), (2, 'a', 'y'), (3, 'a', 'x'), (4, 'b', null), (5, 'b', 'z');
|
|
121
|
+
|
|
122
|
+
SELECT grp, group_concat(distinct tag) AS tags FROM ha_gc GROUP BY grp ORDER BY grp;
|
|
123
|
+
→ [{"grp":"a","tags":"x,y"},{"grp":"b","tags":"z"}]
|
|
124
|
+
|
|
125
|
+
DROP TABLE ha_gc;
|
|
126
|
+
|
|
127
|
+
-- count(distinct blob_col) with GROUP BY — the DISTINCT tree's entry is the
|
|
128
|
+
-- bare BLOB scalar (a Uint8Array), which inheritree's default freeze-on-insert
|
|
129
|
+
-- could not store (bug-in-subquery-blob-values-crash). Exercises the shared
|
|
130
|
+
-- distinct-tree factory used by hash-aggregate's grouped path.
|
|
131
|
+
CREATE TABLE ha_blob_grp (id INTEGER PRIMARY KEY, grp TEXT, b BLOB NULL);
|
|
132
|
+
INSERT INTO ha_blob_grp VALUES
|
|
133
|
+
(1, 'a', x'6162'), (2, 'a', x'6162'), (3, 'a', x'6164'),
|
|
134
|
+
(4, 'b', x'6162'), (5, 'b', null);
|
|
135
|
+
|
|
136
|
+
SELECT grp, count(distinct b) AS cd FROM ha_blob_grp GROUP BY grp ORDER BY grp;
|
|
137
|
+
→ [{"grp":"a","cd":2},{"grp":"b","cd":1}]
|
|
138
|
+
|
|
139
|
+
DROP TABLE ha_blob_grp;
|