@quereus/quereus 4.5.0 → 4.7.0
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 +5 -4
- package/dist/src/common/errors.d.ts +17 -0
- package/dist/src/common/errors.d.ts.map +1 -1
- package/dist/src/common/errors.js +21 -0
- package/dist/src/common/errors.js.map +1 -1
- package/dist/src/core/database-assertions.d.ts +4 -3
- package/dist/src/core/database-assertions.d.ts.map +1 -1
- package/dist/src/core/database-assertions.js +44 -14
- package/dist/src/core/database-assertions.js.map +1 -1
- package/dist/src/core/database-events.d.ts +161 -1
- package/dist/src/core/database-events.d.ts.map +1 -1
- package/dist/src/core/database-events.js +307 -5
- package/dist/src/core/database-events.js.map +1 -1
- package/dist/src/core/database-internal.d.ts +5 -2
- package/dist/src/core/database-internal.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views-plan-builders.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views-plan-builders.js +33 -4
- package/dist/src/core/database-materialized-views-plan-builders.js.map +1 -1
- package/dist/src/core/database-materialized-views-plans.d.ts +12 -2
- package/dist/src/core/database-materialized-views-plans.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views.d.ts +46 -0
- package/dist/src/core/database-materialized-views.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views.js +75 -4
- package/dist/src/core/database-materialized-views.js.map +1 -1
- package/dist/src/core/database-transaction.d.ts +9 -0
- package/dist/src/core/database-transaction.d.ts.map +1 -1
- package/dist/src/core/database-transaction.js +9 -0
- package/dist/src/core/database-transaction.js.map +1 -1
- package/dist/src/core/database.d.ts +16 -2
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +56 -15
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/derived-row-validator.d.ts.map +1 -1
- package/dist/src/core/derived-row-validator.js +7 -1
- package/dist/src/core/derived-row-validator.js.map +1 -1
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +15 -5
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/emit/ast-stringify.d.ts +18 -2
- package/dist/src/emit/ast-stringify.d.ts.map +1 -1
- package/dist/src/emit/ast-stringify.js +22 -4
- package/dist/src/emit/ast-stringify.js.map +1 -1
- package/dist/src/func/builtins/aggregate.js +11 -11
- package/dist/src/func/builtins/aggregate.js.map +1 -1
- package/dist/src/func/builtins/builtin-window-functions.d.ts.map +1 -1
- package/dist/src/func/builtins/builtin-window-functions.js +15 -85
- package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
- package/dist/src/func/builtins/conversion.d.ts.map +1 -1
- package/dist/src/func/builtins/conversion.js +10 -9
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/datetime.d.ts.map +1 -1
- package/dist/src/func/builtins/datetime.js +28 -10
- package/dist/src/func/builtins/datetime.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +19 -5
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/json.d.ts.map +1 -1
- package/dist/src/func/builtins/json.js +23 -17
- package/dist/src/func/builtins/json.js.map +1 -1
- package/dist/src/func/builtins/mutation.js +2 -2
- package/dist/src/func/builtins/mutation.js.map +1 -1
- package/dist/src/func/builtins/return-types.d.ts +327 -0
- package/dist/src/func/builtins/return-types.d.ts.map +1 -0
- package/dist/src/func/builtins/return-types.js +43 -0
- package/dist/src/func/builtins/return-types.js.map +1 -0
- package/dist/src/func/builtins/scalar.d.ts.map +1 -1
- package/dist/src/func/builtins/scalar.js +150 -79
- package/dist/src/func/builtins/scalar.js.map +1 -1
- package/dist/src/func/builtins/schema.d.ts.map +1 -1
- package/dist/src/func/builtins/schema.js +43 -8
- package/dist/src/func/builtins/schema.js.map +1 -1
- package/dist/src/func/builtins/string.d.ts.map +1 -1
- package/dist/src/func/builtins/string.js +4 -2
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/func/builtins/timespan.d.ts +3 -0
- package/dist/src/func/builtins/timespan.d.ts.map +1 -1
- package/dist/src/func/builtins/timespan.js +15 -11
- package/dist/src/func/builtins/timespan.js.map +1 -1
- package/dist/src/func/registration.d.ts +35 -1
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +235 -41
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/index.d.ts +14 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +15 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/ast.d.ts +58 -1
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/parser.d.ts +46 -0
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +161 -45
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/utils.d.ts +13 -1
- package/dist/src/parser/utils.d.ts.map +1 -1
- package/dist/src/parser/utils.js +14 -0
- package/dist/src/parser/utils.js.map +1 -1
- package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -1
- package/dist/src/planner/analysis/assertion-classifier.js +7 -2
- package/dist/src/planner/analysis/assertion-classifier.js.map +1 -1
- package/dist/src/planner/analysis/assertion-hoist-cache.d.ts.map +1 -1
- package/dist/src/planner/analysis/assertion-hoist-cache.js +5 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -1
- package/dist/src/planner/analysis/change-scope.d.ts +11 -3
- package/dist/src/planner/analysis/change-scope.d.ts.map +1 -1
- package/dist/src/planner/analysis/change-scope.js +5 -4
- package/dist/src/planner/analysis/change-scope.js.map +1 -1
- package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -1
- package/dist/src/planner/analysis/check-extraction.js +37 -4
- package/dist/src/planner/analysis/check-extraction.js.map +1 -1
- package/dist/src/planner/analysis/comparison-collation.d.ts +20 -22
- package/dist/src/planner/analysis/comparison-collation.d.ts.map +1 -1
- package/dist/src/planner/analysis/comparison-collation.js +29 -26
- package/dist/src/planner/analysis/comparison-collation.js.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.d.ts +0 -7
- package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.js +59 -59
- package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
- package/dist/src/planner/analysis/coverage-prover.d.ts.map +1 -1
- package/dist/src/planner/analysis/coverage-prover.js +13 -5
- package/dist/src/planner/analysis/coverage-prover.js.map +1 -1
- package/dist/src/planner/analysis/equi-correlation.d.ts +6 -1
- package/dist/src/planner/analysis/equi-correlation.d.ts.map +1 -1
- package/dist/src/planner/analysis/equi-correlation.js +8 -1
- package/dist/src/planner/analysis/equi-correlation.js.map +1 -1
- package/dist/src/planner/analysis/predicate-dependencies.d.ts +34 -0
- package/dist/src/planner/analysis/predicate-dependencies.d.ts.map +1 -0
- package/dist/src/planner/analysis/predicate-dependencies.js +60 -0
- package/dist/src/planner/analysis/predicate-dependencies.js.map +1 -0
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts +1 -1
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts.map +1 -1
- package/dist/src/planner/analysis/query-rewrite-matcher.js +0 -26
- package/dist/src/planner/analysis/query-rewrite-matcher.js.map +1 -1
- package/dist/src/planner/building/alter-table.d.ts.map +1 -1
- package/dist/src/planner/building/alter-table.js +117 -43
- package/dist/src/planner/building/alter-table.js.map +1 -1
- package/dist/src/planner/building/coercion.d.ts +21 -45
- package/dist/src/planner/building/coercion.d.ts.map +1 -1
- package/dist/src/planner/building/coercion.js +42 -91
- package/dist/src/planner/building/coercion.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +9 -5
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/building/create-assertion.d.ts.map +1 -1
- package/dist/src/planner/building/create-assertion.js +72 -1
- package/dist/src/planner/building/create-assertion.js.map +1 -1
- package/dist/src/planner/building/create-view.d.ts +6 -1
- package/dist/src/planner/building/create-view.d.ts.map +1 -1
- package/dist/src/planner/building/create-view.js +12 -3
- package/dist/src/planner/building/create-view.js.map +1 -1
- package/dist/src/planner/building/ddl.d.ts.map +1 -1
- package/dist/src/planner/building/ddl.js +6 -2
- package/dist/src/planner/building/ddl.js.map +1 -1
- package/dist/src/planner/building/delete.d.ts.map +1 -1
- package/dist/src/planner/building/delete.js +23 -10
- package/dist/src/planner/building/delete.js.map +1 -1
- package/dist/src/planner/building/dml-target.d.ts.map +1 -1
- package/dist/src/planner/building/dml-target.js +4 -0
- package/dist/src/planner/building/dml-target.js.map +1 -1
- package/dist/src/planner/building/drop-assertion.d.ts.map +1 -1
- package/dist/src/planner/building/drop-assertion.js +3 -1
- package/dist/src/planner/building/drop-assertion.js.map +1 -1
- package/dist/src/planner/building/expression.d.ts +17 -0
- package/dist/src/planner/building/expression.d.ts.map +1 -1
- package/dist/src/planner/building/expression.js +28 -17
- package/dist/src/planner/building/expression.js.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.d.ts.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.js +7 -5
- package/dist/src/planner/building/foreign-key-builder.js.map +1 -1
- package/dist/src/planner/building/function-call.d.ts +35 -0
- package/dist/src/planner/building/function-call.d.ts.map +1 -1
- package/dist/src/planner/building/function-call.js +60 -42
- package/dist/src/planner/building/function-call.js.map +1 -1
- package/dist/src/planner/building/insert.d.ts.map +1 -1
- package/dist/src/planner/building/insert.js +185 -48
- package/dist/src/planner/building/insert.js.map +1 -1
- package/dist/src/planner/building/materialized-view.d.ts.map +1 -1
- package/dist/src/planner/building/materialized-view.js +3 -1
- package/dist/src/planner/building/materialized-view.js.map +1 -1
- package/dist/src/planner/building/schema-authored-context.d.ts +69 -0
- package/dist/src/planner/building/schema-authored-context.d.ts.map +1 -0
- package/dist/src/planner/building/schema-authored-context.js +75 -0
- package/dist/src/planner/building/schema-authored-context.js.map +1 -0
- package/dist/src/planner/building/schema-resolution.d.ts.map +1 -1
- package/dist/src/planner/building/schema-resolution.js +7 -4
- package/dist/src/planner/building/schema-resolution.js.map +1 -1
- package/dist/src/planner/building/select-aggregates.d.ts +188 -3
- package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
- package/dist/src/planner/building/select-aggregates.js +449 -65
- package/dist/src/planner/building/select-aggregates.js.map +1 -1
- package/dist/src/planner/building/select-compound.js +2 -2
- package/dist/src/planner/building/select-compound.js.map +1 -1
- package/dist/src/planner/building/select-context.d.ts +98 -0
- package/dist/src/planner/building/select-context.d.ts.map +1 -1
- package/dist/src/planner/building/select-context.js +120 -37
- package/dist/src/planner/building/select-context.js.map +1 -1
- package/dist/src/planner/building/select-modifiers.d.ts +10 -3
- package/dist/src/planner/building/select-modifiers.d.ts.map +1 -1
- package/dist/src/planner/building/select-modifiers.js +29 -8
- package/dist/src/planner/building/select-modifiers.js.map +1 -1
- package/dist/src/planner/building/select-ordinal.d.ts +64 -19
- package/dist/src/planner/building/select-ordinal.d.ts.map +1 -1
- package/dist/src/planner/building/select-ordinal.js +79 -30
- package/dist/src/planner/building/select-ordinal.js.map +1 -1
- package/dist/src/planner/building/select-projections.d.ts +1 -1
- package/dist/src/planner/building/select-projections.d.ts.map +1 -1
- package/dist/src/planner/building/select-projections.js +18 -11
- package/dist/src/planner/building/select-projections.js.map +1 -1
- package/dist/src/planner/building/select-window.d.ts +13 -3
- package/dist/src/planner/building/select-window.d.ts.map +1 -1
- package/dist/src/planner/building/select-window.js +142 -37
- package/dist/src/planner/building/select-window.js.map +1 -1
- package/dist/src/planner/building/select.d.ts +37 -1
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +240 -109
- package/dist/src/planner/building/select.js.map +1 -1
- package/dist/src/planner/building/update.d.ts.map +1 -1
- package/dist/src/planner/building/update.js +27 -13
- package/dist/src/planner/building/update.js.map +1 -1
- package/dist/src/planner/building/view-mutation-builder.d.ts +1 -1
- package/dist/src/planner/building/view-mutation-builder.d.ts.map +1 -1
- package/dist/src/planner/building/view-mutation-builder.js +102 -8
- package/dist/src/planner/building/view-mutation-builder.js.map +1 -1
- package/dist/src/planner/building/with.d.ts.map +1 -1
- package/dist/src/planner/building/with.js +34 -4
- package/dist/src/planner/building/with.js.map +1 -1
- package/dist/src/planner/cache/correlation-detector.d.ts +15 -0
- package/dist/src/planner/cache/correlation-detector.d.ts.map +1 -1
- package/dist/src/planner/cache/correlation-detector.js +26 -0
- package/dist/src/planner/cache/correlation-detector.js.map +1 -1
- package/dist/src/planner/cache/materialization-advisory.d.ts +7 -0
- package/dist/src/planner/cache/materialization-advisory.d.ts.map +1 -1
- package/dist/src/planner/cache/materialization-advisory.js +12 -3
- package/dist/src/planner/cache/materialization-advisory.js.map +1 -1
- package/dist/src/planner/cost/conjunct-cost.d.ts +40 -0
- package/dist/src/planner/cost/conjunct-cost.d.ts.map +1 -1
- package/dist/src/planner/cost/conjunct-cost.js +45 -0
- package/dist/src/planner/cost/conjunct-cost.js.map +1 -1
- package/dist/src/planner/cost/index.d.ts +10 -0
- package/dist/src/planner/cost/index.d.ts.map +1 -1
- package/dist/src/planner/cost/index.js +15 -0
- package/dist/src/planner/cost/index.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +9 -0
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/characteristics.js.map +1 -1
- package/dist/src/planner/framework/pass.d.ts +2 -0
- package/dist/src/planner/framework/pass.d.ts.map +1 -1
- package/dist/src/planner/framework/pass.js +15 -0
- package/dist/src/planner/framework/pass.js.map +1 -1
- package/dist/src/planner/mutation/backward-body.d.ts.map +1 -1
- package/dist/src/planner/mutation/backward-body.js +4 -1
- package/dist/src/planner/mutation/backward-body.js.map +1 -1
- package/dist/src/planner/mutation/body-context.d.ts +23 -0
- package/dist/src/planner/mutation/body-context.d.ts.map +1 -0
- package/dist/src/planner/mutation/body-context.js +26 -0
- package/dist/src/planner/mutation/body-context.js.map +1 -0
- package/dist/src/planner/mutation/cte-flatten.js +15 -2
- package/dist/src/planner/mutation/cte-flatten.js.map +1 -1
- package/dist/src/planner/mutation/decomposition.d.ts +8 -0
- package/dist/src/planner/mutation/decomposition.d.ts.map +1 -1
- package/dist/src/planner/mutation/decomposition.js +8 -3
- package/dist/src/planner/mutation/decomposition.js.map +1 -1
- package/dist/src/planner/mutation/lens-enforcement.js +1 -1
- package/dist/src/planner/mutation/multi-source.d.ts +7 -0
- package/dist/src/planner/mutation/multi-source.d.ts.map +1 -1
- package/dist/src/planner/mutation/multi-source.js +5 -0
- package/dist/src/planner/mutation/multi-source.js.map +1 -1
- package/dist/src/planner/mutation/mutation-diagnostic.d.ts +1 -1
- package/dist/src/planner/mutation/mutation-diagnostic.d.ts.map +1 -1
- package/dist/src/planner/mutation/mutation-diagnostic.js.map +1 -1
- package/dist/src/planner/mutation/scope-transform.d.ts +32 -0
- package/dist/src/planner/mutation/scope-transform.d.ts.map +1 -1
- package/dist/src/planner/mutation/scope-transform.js +181 -33
- package/dist/src/planner/mutation/scope-transform.js.map +1 -1
- package/dist/src/planner/mutation/set-op.d.ts.map +1 -1
- package/dist/src/planner/mutation/set-op.js +66 -16
- package/dist/src/planner/mutation/set-op.js.map +1 -1
- package/dist/src/planner/mutation/single-source.d.ts.map +1 -1
- package/dist/src/planner/mutation/single-source.js +100 -24
- package/dist/src/planner/mutation/single-source.js.map +1 -1
- package/dist/src/planner/nodes/add-constraint-node.d.ts +15 -1
- package/dist/src/planner/nodes/add-constraint-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/add-constraint-node.js +10 -1
- package/dist/src/planner/nodes/add-constraint-node.js.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.d.ts +15 -0
- package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.js +32 -17
- package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
- package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/alias-node.js +2 -1
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/alter-table-node.d.ts +51 -10
- package/dist/src/planner/nodes/alter-table-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/alter-table-node.js +49 -2
- package/dist/src/planner/nodes/alter-table-node.js.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.js +4 -1
- package/dist/src/planner/nodes/asof-scan-node.js.map +1 -1
- package/dist/src/planner/nodes/asserted-keys-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/asserted-keys-node.js +2 -1
- package/dist/src/planner/nodes/asserted-keys-node.js.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.js +8 -3
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
- package/dist/src/planner/nodes/cache-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cache-node.js +2 -1
- package/dist/src/planner/nodes/cache-node.js.map +1 -1
- package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/constraint-check-node.js +17 -19
- package/dist/src/planner/nodes/constraint-check-node.js.map +1 -1
- package/dist/src/planner/nodes/create-assertion-node.d.ts +2 -1
- package/dist/src/planner/nodes/create-assertion-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/create-assertion-node.js +5 -2
- package/dist/src/planner/nodes/create-assertion-node.js.map +1 -1
- package/dist/src/planner/nodes/cte-node.d.ts +19 -9
- package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cte-node.js +25 -9
- package/dist/src/planner/nodes/cte-node.js.map +1 -1
- package/dist/src/planner/nodes/delete-node.d.ts +20 -2
- package/dist/src/planner/nodes/delete-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/delete-node.js +11 -2
- package/dist/src/planner/nodes/delete-node.js.map +1 -1
- package/dist/src/planner/nodes/distinct-node.d.ts +6 -0
- package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/distinct-node.js +10 -2
- package/dist/src/planner/nodes/distinct-node.js.map +1 -1
- package/dist/src/planner/nodes/dml-executor-node.d.ts +58 -1
- package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/dml-executor-node.js +107 -15
- package/dist/src/planner/nodes/dml-executor-node.js.map +1 -1
- package/dist/src/planner/nodes/drop-assertion-node.d.ts +2 -1
- package/dist/src/planner/nodes/drop-assertion-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/drop-assertion-node.js +5 -2
- package/dist/src/planner/nodes/drop-assertion-node.js.map +1 -1
- package/dist/src/planner/nodes/eager-prefetch-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/eager-prefetch-node.js +2 -1
- package/dist/src/planner/nodes/eager-prefetch-node.js.map +1 -1
- package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts +5 -0
- package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/fanout-lookup-join-node.js +13 -6
- package/dist/src/planner/nodes/fanout-lookup-join-node.js.map +1 -1
- package/dist/src/planner/nodes/filter.d.ts.map +1 -1
- package/dist/src/planner/nodes/filter.js +18 -5
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts +1 -0
- package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.js +21 -16
- package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/insert-node.d.ts +19 -2
- package/dist/src/planner/nodes/insert-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/insert-node.js +10 -2
- package/dist/src/planner/nodes/insert-node.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts +20 -1
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +30 -9
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +21 -0
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +26 -0
- package/dist/src/planner/nodes/join-utils.js.map +1 -1
- package/dist/src/planner/nodes/key-set-semi-join-node.d.ts +42 -10
- package/dist/src/planner/nodes/key-set-semi-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/key-set-semi-join-node.js +90 -17
- package/dist/src/planner/nodes/key-set-semi-join-node.js.map +1 -1
- package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts +5 -0
- package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/lens-auxiliary-access-node.js +2 -1
- package/dist/src/planner/nodes/lens-auxiliary-access-node.js.map +1 -1
- package/dist/src/planner/nodes/limit-offset.d.ts +6 -0
- package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
- package/dist/src/planner/nodes/limit-offset.js +10 -2
- package/dist/src/planner/nodes/limit-offset.js.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +8 -3
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts +5 -0
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.js +9 -2
- package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +29 -0
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js +12 -0
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +18 -36
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +3 -2
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.d.ts +16 -2
- package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.js +10 -2
- package/dist/src/planner/nodes/retrieve-node.js.map +1 -1
- package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/returning-node.js +13 -32
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +5 -18
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/sort.d.ts.map +1 -1
- package/dist/src/planner/nodes/sort.js +3 -1
- package/dist/src/planner/nodes/sort.js.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -0
- package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.js +22 -20
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +89 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +69 -2
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/nodes/update-node.d.ts +19 -2
- package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/update-node.js +10 -2
- package/dist/src/planner/nodes/update-node.js.map +1 -1
- package/dist/src/planner/nodes/window-function.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-function.js +8 -0
- package/dist/src/planner/nodes/window-function.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts +1 -1
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +3 -1
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts +27 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +130 -10
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/planning-context.d.ts +24 -0
- package/dist/src/planner/planning-context.d.ts.map +1 -1
- package/dist/src/planner/planning-context.js.map +1 -1
- package/dist/src/planner/rules/access/rule-key-set-seek.d.ts +78 -20
- package/dist/src/planner/rules/access/rule-key-set-seek.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-key-set-seek.js +296 -135
- package/dist/src/planner/rules/access/rule-key-set-seek.js.map +1 -1
- package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js +2 -2
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts +30 -1
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +70 -5
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +7 -4
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +39 -5
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-cte-optimization.js +15 -2
- package/dist/src/planner/rules/cache/rule-cte-optimization.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js +10 -3
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js +6 -4
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts +5 -31
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.js +4 -44
- package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -1
- package/dist/src/planner/rules/join/index-nested-loop.d.ts +49 -0
- package/dist/src/planner/rules/join/index-nested-loop.d.ts.map +1 -0
- package/dist/src/planner/rules/join/index-nested-loop.js +291 -0
- package/dist/src/planner/rules/join/index-nested-loop.js.map +1 -0
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +8 -8
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts +4 -0
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +50 -15
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts +6 -0
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-elimination.js +25 -9
- package/dist/src/planner/rules/join/rule-join-elimination.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-key-inference.d.ts +7 -0
- package/dist/src/planner/rules/join/rule-join-key-inference.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-key-inference.js +23 -11
- package/dist/src/planner/rules/join/rule-join-key-inference.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts +10 -4
- package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.js +115 -29
- package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts +2 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +18 -4
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts +2 -2
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +19 -22
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.d.ts +21 -8
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.js +70 -14
- package/dist/src/planner/rules/predicate/rule-filter-conjunct-ordering.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.d.ts +56 -17
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.js +103 -154
- package/dist/src/planner/rules/predicate/rule-filter-selectivity.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-join-predicate-pushdown.d.ts +76 -0
- package/dist/src/planner/rules/predicate/rule-join-predicate-pushdown.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-join-predicate-pushdown.js +208 -0
- package/dist/src/planner/rules/predicate/rule-join-predicate-pushdown.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts +14 -11
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js +21 -85
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts +7 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js +18 -22
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +1 -1
- package/dist/src/planner/rules/shared/access-leaf.d.ts +52 -0
- package/dist/src/planner/rules/shared/access-leaf.d.ts.map +1 -0
- package/dist/src/planner/rules/shared/access-leaf.js +95 -0
- package/dist/src/planner/rules/shared/access-leaf.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +17 -7
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js.map +1 -1
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts +3 -1
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +26 -9
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +69 -11
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/planner/rules/window/rule-monotonic-window.d.ts +17 -7
- package/dist/src/planner/rules/window/rule-monotonic-window.d.ts.map +1 -1
- package/dist/src/planner/rules/window/rule-monotonic-window.js +124 -87
- package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -1
- package/dist/src/planner/scopes/aliased.d.ts.map +1 -1
- package/dist/src/planner/scopes/aliased.js +6 -0
- package/dist/src/planner/scopes/aliased.js.map +1 -1
- package/dist/src/planner/stats/catalog-stats.d.ts +44 -13
- package/dist/src/planner/stats/catalog-stats.d.ts.map +1 -1
- package/dist/src/planner/stats/catalog-stats.js +137 -61
- package/dist/src/planner/stats/catalog-stats.js.map +1 -1
- package/dist/src/planner/stats/conjunct-selectivity.d.ts +48 -0
- package/dist/src/planner/stats/conjunct-selectivity.d.ts.map +1 -0
- package/dist/src/planner/stats/conjunct-selectivity.js +168 -0
- package/dist/src/planner/stats/conjunct-selectivity.js.map +1 -0
- package/dist/src/planner/stats/index.d.ts +22 -3
- package/dist/src/planner/stats/index.d.ts.map +1 -1
- package/dist/src/planner/stats/index.js.map +1 -1
- package/dist/src/planner/stats/table-cardinality.d.ts +28 -0
- package/dist/src/planner/stats/table-cardinality.d.ts.map +1 -0
- package/dist/src/planner/stats/table-cardinality.js +29 -0
- package/dist/src/planner/stats/table-cardinality.js.map +1 -0
- package/dist/src/planner/stored-body-context.d.ts +57 -0
- package/dist/src/planner/stored-body-context.d.ts.map +1 -0
- package/dist/src/planner/stored-body-context.js +64 -0
- package/dist/src/planner/stored-body-context.js.map +1 -0
- package/dist/src/planner/util/column-origins.d.ts +29 -8
- package/dist/src/planner/util/column-origins.d.ts.map +1 -1
- package/dist/src/planner/util/column-origins.js +74 -14
- package/dist/src/planner/util/column-origins.js.map +1 -1
- package/dist/src/planner/util/fd-utils.d.ts +32 -8
- package/dist/src/planner/util/fd-utils.d.ts.map +1 -1
- package/dist/src/planner/util/fd-utils.js +46 -9
- package/dist/src/planner/util/fd-utils.js.map +1 -1
- package/dist/src/planner/util/ind-utils.d.ts +66 -19
- package/dist/src/planner/util/ind-utils.d.ts.map +1 -1
- package/dist/src/planner/util/ind-utils.js +91 -21
- package/dist/src/planner/util/ind-utils.js.map +1 -1
- package/dist/src/planner/util/key-utils.d.ts +36 -3
- package/dist/src/planner/util/key-utils.d.ts.map +1 -1
- package/dist/src/planner/util/key-utils.js +57 -7
- package/dist/src/planner/util/key-utils.js.map +1 -1
- package/dist/src/planner/util/output-names.d.ts +12 -0
- package/dist/src/planner/util/output-names.d.ts.map +1 -0
- package/dist/src/planner/util/output-names.js +20 -0
- package/dist/src/planner/util/output-names.js.map +1 -0
- package/dist/src/planner/util/row-estimates.d.ts +39 -0
- package/dist/src/planner/util/row-estimates.d.ts.map +1 -0
- package/dist/src/planner/util/row-estimates.js +68 -0
- package/dist/src/planner/util/row-estimates.js.map +1 -0
- package/dist/src/planner/util/row-population.d.ts +42 -0
- package/dist/src/planner/util/row-population.d.ts.map +1 -0
- package/dist/src/planner/util/row-population.js +71 -0
- package/dist/src/planner/util/row-population.js.map +1 -0
- package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
- package/dist/src/runtime/deferred-constraint-queue.js +3 -2
- package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
- package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -1
- package/dist/src/runtime/emit/add-constraint.js +60 -6
- package/dist/src/runtime/emit/add-constraint.js.map +1 -1
- package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
- package/dist/src/runtime/emit/aggregate.js +4 -4
- package/dist/src/runtime/emit/aggregate.js.map +1 -1
- package/dist/src/runtime/emit/alter-schema-event.d.ts +97 -0
- package/dist/src/runtime/emit/alter-schema-event.d.ts.map +1 -0
- package/dist/src/runtime/emit/alter-schema-event.js +87 -0
- package/dist/src/runtime/emit/alter-schema-event.js.map +1 -0
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +582 -236
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/analyze.d.ts.map +1 -1
- package/dist/src/runtime/emit/analyze.js +50 -7
- package/dist/src/runtime/emit/analyze.js.map +1 -1
- package/dist/src/runtime/emit/assertion-drop-guard.d.ts +37 -0
- package/dist/src/runtime/emit/assertion-drop-guard.d.ts.map +1 -0
- package/dist/src/runtime/emit/assertion-drop-guard.js +59 -0
- package/dist/src/runtime/emit/assertion-drop-guard.js.map +1 -0
- package/dist/src/runtime/emit/assertion-rename-helpers.d.ts +33 -0
- package/dist/src/runtime/emit/assertion-rename-helpers.d.ts.map +1 -0
- package/dist/src/runtime/emit/assertion-rename-helpers.js +124 -0
- package/dist/src/runtime/emit/assertion-rename-helpers.js.map +1 -0
- package/dist/src/runtime/emit/cast.d.ts.map +1 -1
- package/dist/src/runtime/emit/cast.js +4 -19
- package/dist/src/runtime/emit/cast.js.map +1 -1
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +10 -227
- package/dist/src/runtime/emit/constraint-check.js.map +1 -1
- package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-assertion.js +31 -14
- package/dist/src/runtime/emit/create-assertion.js.map +1 -1
- package/dist/src/runtime/emit/cte.d.ts.map +1 -1
- package/dist/src/runtime/emit/cte.js +11 -6
- package/dist/src/runtime/emit/cte.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +233 -28
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/drop-assertion.js +8 -8
- package/dist/src/runtime/emit/drop-assertion.js.map +1 -1
- package/dist/src/runtime/emit/drop-column-guards.d.ts +151 -0
- package/dist/src/runtime/emit/drop-column-guards.d.ts.map +1 -0
- package/dist/src/runtime/emit/drop-column-guards.js +230 -0
- package/dist/src/runtime/emit/drop-column-guards.js.map +1 -0
- package/dist/src/runtime/emit/drop-index.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-index.js +4 -3
- package/dist/src/runtime/emit/drop-index.js.map +1 -1
- package/dist/src/runtime/emit/drop-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-table.js +6 -0
- package/dist/src/runtime/emit/drop-table.js.map +1 -1
- package/dist/src/runtime/emit/drop-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-view.js +4 -0
- package/dist/src/runtime/emit/drop-view.js.map +1 -1
- package/dist/src/runtime/emit/hash-aggregate.d.ts.map +1 -1
- package/dist/src/runtime/emit/hash-aggregate.js +2 -2
- package/dist/src/runtime/emit/hash-aggregate.js.map +1 -1
- package/dist/src/runtime/emit/join.d.ts.map +1 -1
- package/dist/src/runtime/emit/join.js +8 -67
- package/dist/src/runtime/emit/join.js.map +1 -1
- package/dist/src/runtime/emit/key-set-semi-join.d.ts.map +1 -1
- package/dist/src/runtime/emit/key-set-semi-join.js +11 -3
- package/dist/src/runtime/emit/key-set-semi-join.js.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts +4 -4
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.js +34 -22
- package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -1
- package/dist/src/runtime/emit/materialized-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view.js +7 -2
- package/dist/src/runtime/emit/materialized-view.js.map +1 -1
- package/dist/src/runtime/emit/operand-comparator.d.ts +30 -0
- package/dist/src/runtime/emit/operand-comparator.d.ts.map +1 -1
- package/dist/src/runtime/emit/operand-comparator.js +34 -0
- package/dist/src/runtime/emit/operand-comparator.js.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.js +4 -5
- package/dist/src/runtime/emit/recursive-cte.js.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.js +30 -0
- package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
- package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
- package/dist/src/runtime/emit/subquery.js +153 -52
- package/dist/src/runtime/emit/subquery.js.map +1 -1
- package/dist/src/runtime/emit/update.d.ts.map +1 -1
- package/dist/src/runtime/emit/update.js +18 -6
- package/dist/src/runtime/emit/update.js.map +1 -1
- package/dist/src/runtime/emit/window.js +36 -23
- package/dist/src/runtime/emit/window.js.map +1 -1
- package/dist/src/runtime/row-constraints.d.ts +85 -0
- package/dist/src/runtime/row-constraints.d.ts.map +1 -0
- package/dist/src/runtime/row-constraints.js +239 -0
- package/dist/src/runtime/row-constraints.js.map +1 -0
- package/dist/src/runtime/types.d.ts +8 -11
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/schema/assertion.d.ts +14 -1
- package/dist/src/schema/assertion.d.ts.map +1 -1
- package/dist/src/schema/assertion.js +14 -1
- package/dist/src/schema/assertion.js.map +1 -1
- package/dist/src/schema/catalog-persistability.d.ts +19 -16
- package/dist/src/schema/catalog-persistability.d.ts.map +1 -1
- package/dist/src/schema/catalog-persistability.js +92 -20
- package/dist/src/schema/catalog-persistability.js.map +1 -1
- package/dist/src/schema/catalog.d.ts +73 -2
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +220 -39
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/column-source-resolver.d.ts +18 -0
- package/dist/src/schema/column-source-resolver.d.ts.map +1 -0
- package/dist/src/schema/column-source-resolver.js +22 -0
- package/dist/src/schema/column-source-resolver.js.map +1 -0
- package/dist/src/schema/column.d.ts +26 -3
- package/dist/src/schema/column.d.ts.map +1 -1
- package/dist/src/schema/column.js.map +1 -1
- package/dist/src/schema/constraint-builder.d.ts.map +1 -1
- package/dist/src/schema/constraint-builder.js +7 -1
- package/dist/src/schema/constraint-builder.js.map +1 -1
- package/dist/src/schema/ddl-generator.d.ts.map +1 -1
- package/dist/src/schema/ddl-generator.js +27 -6
- package/dist/src/schema/ddl-generator.js.map +1 -1
- package/dist/src/schema/function.d.ts +32 -1
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js +10 -2
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/lens-compiler.d.ts.map +1 -1
- package/dist/src/schema/lens-compiler.js +203 -51
- package/dist/src/schema/lens-compiler.js.map +1 -1
- package/dist/src/schema/lens-prover.d.ts +2 -3
- package/dist/src/schema/lens-prover.d.ts.map +1 -1
- package/dist/src/schema/lens-prover.js +19 -11
- package/dist/src/schema/lens-prover.js.map +1 -1
- package/dist/src/schema/manager.d.ts +115 -20
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +202 -70
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/rename-rewriter.d.ts +142 -0
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
- package/dist/src/schema/rename-rewriter.js +254 -9
- package/dist/src/schema/rename-rewriter.js.map +1 -1
- package/dist/src/schema/reserved-tags.d.ts +1 -1
- package/dist/src/schema/reserved-tags.d.ts.map +1 -1
- package/dist/src/schema/reserved-tags.js +4 -3
- package/dist/src/schema/reserved-tags.js.map +1 -1
- package/dist/src/schema/schema-differ.d.ts +16 -0
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +225 -38
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/schema/table.d.ts +149 -1
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +248 -1
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/schema/unique-enforcement.d.ts +5 -3
- package/dist/src/schema/unique-enforcement.d.ts.map +1 -1
- package/dist/src/schema/unique-enforcement.js +5 -3
- package/dist/src/schema/unique-enforcement.js.map +1 -1
- package/dist/src/schema/view.d.ts +11 -0
- package/dist/src/schema/view.d.ts.map +1 -1
- package/dist/src/schema/view.js +12 -0
- package/dist/src/schema/view.js.map +1 -1
- package/dist/src/types/builtin-types.d.ts +54 -0
- package/dist/src/types/builtin-types.d.ts.map +1 -1
- package/dist/src/types/builtin-types.js +123 -34
- package/dist/src/types/builtin-types.js.map +1 -1
- package/dist/src/types/cast-semantics.d.ts +42 -0
- package/dist/src/types/cast-semantics.d.ts.map +1 -1
- package/dist/src/types/cast-semantics.js +64 -0
- package/dist/src/types/cast-semantics.js.map +1 -1
- package/dist/src/types/comparison-coercion.d.ts +101 -0
- package/dist/src/types/comparison-coercion.d.ts.map +1 -0
- package/dist/src/types/comparison-coercion.js +162 -0
- package/dist/src/types/comparison-coercion.js.map +1 -0
- package/dist/src/types/index.d.ts +2 -2
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +2 -2
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/logical-type.d.ts +7 -0
- package/dist/src/types/logical-type.d.ts.map +1 -1
- package/dist/src/types/logical-type.js.map +1 -1
- package/dist/src/types/validation.d.ts +56 -0
- package/dist/src/types/validation.d.ts.map +1 -1
- package/dist/src/types/validation.js +68 -0
- package/dist/src/types/validation.js.map +1 -1
- package/dist/src/util/{working-table-iterable.d.ts → array-row-iterable.d.ts} +6 -6
- package/dist/src/util/array-row-iterable.d.ts.map +1 -0
- package/dist/src/util/{working-table-iterable.js → array-row-iterable.js} +6 -6
- package/dist/src/util/array-row-iterable.js.map +1 -0
- package/dist/src/util/coercion.d.ts +8 -0
- package/dist/src/util/coercion.d.ts.map +1 -1
- package/dist/src/util/coercion.js +8 -0
- package/dist/src/util/coercion.js.map +1 -1
- package/dist/src/util/comparison.d.ts +16 -3
- package/dist/src/util/comparison.d.ts.map +1 -1
- package/dist/src/util/comparison.js +21 -5
- package/dist/src/util/comparison.js.map +1 -1
- package/dist/src/util/key-serializer.d.ts +46 -0
- package/dist/src/util/key-serializer.d.ts.map +1 -1
- package/dist/src/util/key-serializer.js +47 -0
- package/dist/src/util/key-serializer.js.map +1 -1
- package/dist/src/util/value-set.d.ts +21 -0
- package/dist/src/util/value-set.d.ts.map +1 -0
- package/dist/src/util/value-set.js +22 -0
- package/dist/src/util/value-set.js.map +1 -0
- package/dist/src/vtab/capabilities.d.ts +1 -1
- package/dist/src/vtab/events.d.ts +8 -1
- package/dist/src/vtab/events.d.ts.map +1 -1
- package/dist/src/vtab/events.js.map +1 -1
- package/dist/src/vtab/manifest.d.ts +15 -0
- package/dist/src/vtab/manifest.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/alter-column.d.ts +147 -0
- package/dist/src/vtab/memory/layer/alter-column.d.ts.map +1 -0
- package/dist/src/vtab/memory/layer/alter-column.js +214 -0
- package/dist/src/vtab/memory/layer/alter-column.js.map +1 -0
- package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/base.js +4 -3
- package/dist/src/vtab/memory/layer/base.js.map +1 -1
- package/dist/src/vtab/memory/layer/interface.d.ts +2 -2
- package/dist/src/vtab/memory/layer/interface.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +176 -25
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +569 -558
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/scan-layer.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/scan-layer.js +32 -5
- package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts +101 -15
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +133 -45
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +16 -1
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +64 -3
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/dist/src/vtab/memory/table.d.ts.map +1 -1
- package/dist/src/vtab/memory/table.js +11 -6
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/module.d.ts +77 -23
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/dist/src/vtab/table.d.ts +9 -2
- package/dist/src/vtab/table.d.ts.map +1 -1
- package/dist/src/vtab/table.js +1 -1
- package/dist/src/vtab/table.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/util/working-table-iterable.d.ts.map +0 -1
- package/dist/src/util/working-table-iterable.js.map +0 -1
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { asRun } from '../types.js';
|
|
2
2
|
import { emitCallFromPlan } from '../emitters.js';
|
|
3
3
|
import { createRowSlot } from '../context-helpers.js';
|
|
4
|
-
import { QuereusError } from '../../common/errors.js';
|
|
4
|
+
import { QuereusError, RelationNotFoundError } from '../../common/errors.js';
|
|
5
5
|
import { StatusCode } from '../../common/types.js';
|
|
6
6
|
import { createLogger } from '../../common/logger.js';
|
|
7
|
-
import { buildColumnIndexMap, withGeneratedColumnGraph, requireVtabModule, resolveNamedConstraintClass, validateCollationForType } from '../../schema/table.js';
|
|
7
|
+
import { buildColumnIndexMap, withGeneratedColumnGraph, requireVtabModule, resolveNamedConstraintClass, namedConstraintExists, assertConstraintNameFree, validateCollationForType, columnDefToSchema } from '../../schema/table.js';
|
|
8
8
|
import { validateForeignKeyCollations, buildForeignKeyConstraintSchema, extractColumnLevelCheckConstraints, extractColumnLevelForeignKeys, extractColumnLevelUniqueConstraints } from '../../schema/constraint-builder.js';
|
|
9
|
-
import { MemoryTableModule } from '../../vtab/memory/module.js';
|
|
10
9
|
import { quoteIdentifier, expressionToString, astToString } from '../../emit/ast-stringify.js';
|
|
11
|
-
import { renameTableInAst, renameColumnInAst, renameColumnInCheckExpression } from '../../schema/rename-rewriter.js';
|
|
10
|
+
import { renameTableInAst, renameColumnInAst, renameColumnInCheckExpression, renameColumnInColumnExpressions, renameTableInColumnExpressions } from '../../schema/rename-rewriter.js';
|
|
12
11
|
import { assertCatalogObjectPersistable, assertRenameDependentsPersistable } from '../../schema/catalog-persistability.js';
|
|
13
|
-
import {
|
|
12
|
+
import { assertUniqueConstraintIndexNameFree, assertUniqueConstraintNotDuplicated, uniqueConstraintColumnSetKey } from '../../schema/catalog.js';
|
|
14
13
|
import { isTruthy } from '../../util/comparison.js';
|
|
15
|
-
import { assertDdlTransactionPolicy } from './ddl-transaction-policy.js';
|
|
16
|
-
import {
|
|
14
|
+
import { assertDdlTransactionPolicy, isExplicitTransactionOpen } from './ddl-transaction-policy.js';
|
|
15
|
+
import { buildColumnSourceResolver } from '../../schema/column-source-resolver.js';
|
|
16
|
+
import { assertNoColumnDefaultNamesColumn, assertNoCheckConstraintNamesColumn, assertNoAssertionNamesColumn, assertNoForeignKeyReferencesColumn } from './drop-column-guards.js';
|
|
17
|
+
import { emitAlterSchemaEvent, withStatementScopedSchemaEvents } from './alter-schema-event.js';
|
|
18
|
+
import { foldDefaultToType, validateAndParse } from '../../types/validation.js';
|
|
17
19
|
import { snapshotStaleMaterializedViews, propagateTableRenameToMaterializedViews, propagateColumnRenameToMaterializedViews, restoreUnaffectedMaterializedViews, attachMaintainedDerivation, detachMaintainedDerivation, } from './materialized-view-helpers.js';
|
|
20
|
+
import { propagateTableRenameToAssertions, propagateColumnRenameToAssertions, } from './assertion-rename-helpers.js';
|
|
18
21
|
import { isMaintainedTable } from '../../schema/derivation.js';
|
|
19
22
|
import { inferType } from '../../types/registry.js';
|
|
20
23
|
const log = createLogger('runtime:emit:alter-table');
|
|
24
|
+
const warnLog = log.extend('warn');
|
|
21
25
|
/** A scheduled sub-program resolved to a callback the emitter invokes per row. */
|
|
22
26
|
function qualifyTableName(schemaName, tableName) {
|
|
23
27
|
const prefix = (schemaName && schemaName.toLowerCase() !== 'main')
|
|
@@ -28,12 +32,15 @@ function qualifyTableName(schemaName, tableName) {
|
|
|
28
32
|
export function emitAlterTable(plan, ctx) {
|
|
29
33
|
const tableSchema = plan.table.tableSchema;
|
|
30
34
|
const action = plan.action;
|
|
31
|
-
// An ADD COLUMN with a
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
35
|
+
// An ADD COLUMN with a per-row value source — a non-foldable DEFAULT, or a GENERATED
|
|
36
|
+
// ALWAYS AS expression — carries a backfill scalar; emit it as a scheduled sub-program
|
|
37
|
+
// so the scheduler resolves it into a callback the run() body evaluates per existing row
|
|
38
|
+
// (via a row slot over the backfill's row descriptor). When the new column also carries a
|
|
39
|
+
// CHECK, its predicates ride alongside as further callbacks, evaluated per backfilled row
|
|
40
|
+
// against `[...existingRow, backfilledValue]`. Slot order is fixed: backfill first
|
|
41
|
+
// (present whenever checks are), then the checks in order — this MUST match
|
|
42
|
+
// `AlterTableNode.addColumnExpressions()` (planner/nodes/alter-table-node.ts), which is
|
|
43
|
+
// the order the optimizer rewrites these children in via getChildren/withChildren.
|
|
37
44
|
const backfill = action.type === 'addColumn' ? action.backfill : undefined;
|
|
38
45
|
const checks = action.type === 'addColumn' ? action.checks : undefined;
|
|
39
46
|
const params = [
|
|
@@ -66,58 +73,66 @@ export function emitAlterTable(plan, ctx) {
|
|
|
66
73
|
? `cannot ALTER TABLE '${tableSchema.name}': it is a materialized view — use ALTER MATERIALIZED VIEW for tags`
|
|
67
74
|
: `cannot ALTER '${tableSchema.name}': it is a materialized view — its shape is defined by the view body (drop and recreate to change it)`, StatusCode.ERROR);
|
|
68
75
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
// Every arm runs under the statement-scoped schema-event scope: an arm that fails
|
|
77
|
+
// after the module call has already let an emitter-backed module announce the
|
|
78
|
+
// statement (it emits from inside `module.alterTable`, not at the statement's end),
|
|
79
|
+
// so the failure path must retract that announcement. See
|
|
80
|
+
// {@link withStatementScopedSchemaEvents} for why this sits at the statement
|
|
81
|
+
// boundary rather than inside any one arm's revert.
|
|
82
|
+
return withStatementScopedSchemaEvents(rctx, async () => {
|
|
83
|
+
switch (action.type) {
|
|
84
|
+
case 'renameTable':
|
|
85
|
+
return runRenameTable(rctx, tableSchema, schema, action.newName, plan.sql);
|
|
86
|
+
case 'renameColumn':
|
|
87
|
+
return runRenameColumn(rctx, tableSchema, schema, action.oldName, action.newName, plan.sql);
|
|
88
|
+
case 'addColumn': {
|
|
89
|
+
// Slot order set in `params`: backfill callback first (if any), then check callbacks.
|
|
90
|
+
const backfillCb = backfill ? args[0] : undefined;
|
|
91
|
+
const checkCbs = args.slice(backfill ? 1 : 0);
|
|
92
|
+
return runAddColumn(rctx, tableSchema, schema, action.column, plan.sql, backfill, backfillCb, checks, checkCbs);
|
|
93
|
+
}
|
|
94
|
+
case 'dropColumn':
|
|
95
|
+
return runDropColumn(rctx, tableSchema, schema, action.name, plan.sql);
|
|
96
|
+
case 'dropConstraint':
|
|
97
|
+
return runDropConstraint(rctx, tableSchema, schema, action.name, plan.sql);
|
|
98
|
+
case 'renameConstraint':
|
|
99
|
+
return runRenameConstraint(rctx, tableSchema, schema, action.oldName, action.newName, plan.sql);
|
|
100
|
+
case 'alterPrimaryKey':
|
|
101
|
+
return runAlterPrimaryKey(rctx, tableSchema, schema, action.columns, plan.sql);
|
|
102
|
+
case 'alterColumn':
|
|
103
|
+
return runAlterColumn(rctx, tableSchema, schema, action, plan.sql);
|
|
104
|
+
case 'setTags': {
|
|
105
|
+
const target = action.target;
|
|
106
|
+
if (action.mode === 'merge') {
|
|
107
|
+
// ADD TAGS — per-key merge onto the live tag set.
|
|
108
|
+
if (target.kind === 'column')
|
|
109
|
+
return runMergeColumnTags(rctx, tableSchema, target.columnName, action.tags);
|
|
110
|
+
if (target.kind === 'constraint')
|
|
111
|
+
return runMergeConstraintTags(rctx, tableSchema, target.constraintName, action.tags);
|
|
112
|
+
return runMergeTableTags(rctx, tableSchema, action.tags);
|
|
113
|
+
}
|
|
114
|
+
// SET TAGS — whole-set replace.
|
|
94
115
|
if (target.kind === 'column')
|
|
95
|
-
return
|
|
116
|
+
return runSetColumnTags(rctx, tableSchema, target.columnName, action.tags);
|
|
96
117
|
if (target.kind === 'constraint')
|
|
97
|
-
return
|
|
98
|
-
return
|
|
118
|
+
return runSetConstraintTags(rctx, tableSchema, target.constraintName, action.tags);
|
|
119
|
+
return runSetTableTags(rctx, tableSchema, action.tags);
|
|
99
120
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return runDropConstraintTags(rctx, tableSchema, target.constraintName, action.keys);
|
|
114
|
-
return runDropTableTags(rctx, tableSchema, action.keys);
|
|
121
|
+
case 'dropTags': {
|
|
122
|
+
// DROP TAGS — per-key delete (atomic NOTFOUND if any key absent).
|
|
123
|
+
const target = action.target;
|
|
124
|
+
if (target.kind === 'column')
|
|
125
|
+
return runDropColumnTags(rctx, tableSchema, target.columnName, action.keys);
|
|
126
|
+
if (target.kind === 'constraint')
|
|
127
|
+
return runDropConstraintTags(rctx, tableSchema, target.constraintName, action.keys);
|
|
128
|
+
return runDropTableTags(rctx, tableSchema, action.keys);
|
|
129
|
+
}
|
|
130
|
+
case 'setMaintained':
|
|
131
|
+
return runSetMaintained(rctx, tableSchema, schema, action.columns, action.select);
|
|
132
|
+
case 'dropMaintained':
|
|
133
|
+
return runDropMaintained(rctx, tableSchema, schema);
|
|
115
134
|
}
|
|
116
|
-
|
|
117
|
-
return runSetMaintained(rctx, tableSchema, schema, action.columns, action.select);
|
|
118
|
-
case 'dropMaintained':
|
|
119
|
-
return runDropMaintained(rctx, tableSchema, schema);
|
|
120
|
-
}
|
|
135
|
+
});
|
|
121
136
|
}
|
|
122
137
|
const note = (() => {
|
|
123
138
|
switch (action.type) {
|
|
@@ -153,7 +168,7 @@ export function emitAlterTable(plan, ctx) {
|
|
|
153
168
|
note,
|
|
154
169
|
};
|
|
155
170
|
}
|
|
156
|
-
async function runRenameTable(rctx, tableSchema, schema, newName) {
|
|
171
|
+
async function runRenameTable(rctx, tableSchema, schema, newName, sql) {
|
|
157
172
|
const oldName = tableSchema.name;
|
|
158
173
|
// Check for name conflict
|
|
159
174
|
if (schema.getTable(newName)) {
|
|
@@ -172,7 +187,7 @@ async function runRenameTable(rctx, tableSchema, schema, newName) {
|
|
|
172
187
|
// substitutes `newName`, which is already under test as the record's own name.
|
|
173
188
|
assertCatalogObjectPersistable(rctx.db, 'materializedView', { ...tableSchema, name: newName });
|
|
174
189
|
}
|
|
175
|
-
assertRenameDependentsPersistable(rctx.db, schema, ast => renameTableInAst(ast, oldName, newName, tableSchema.schemaName));
|
|
190
|
+
assertRenameDependentsPersistable(rctx.db, schema, ast => renameTableInAst(ast, oldName, newName, tableSchema.schemaName), t => rewriteTableForTableRename(t, tableSchema.schemaName.toLowerCase(), oldName, newName));
|
|
176
191
|
// Clone schema with new name
|
|
177
192
|
const updatedTableSchema = {
|
|
178
193
|
...tableSchema,
|
|
@@ -184,7 +199,9 @@ async function runRenameTable(rctx, tableSchema, schema, newName) {
|
|
|
184
199
|
// omit the hook.
|
|
185
200
|
const module = requireVtabModule(tableSchema);
|
|
186
201
|
if (module.renameTable) {
|
|
187
|
-
|
|
202
|
+
// `sql` marks this call as the statement's own action: an emitter-backed module
|
|
203
|
+
// emits its schema-change event iff it is present (see VirtualTableModule.renameTable).
|
|
204
|
+
await module.renameTable(rctx.db, tableSchema.schemaName, oldName, newName, sql);
|
|
188
205
|
}
|
|
189
206
|
// Events this transaction already recorded still carry the OLD name; relabel them so
|
|
190
207
|
// the commit delivers every event under the name the table has at delivery. AFTER the
|
|
@@ -194,9 +211,11 @@ async function runRenameTable(rctx, tableSchema, schema, newName) {
|
|
|
194
211
|
// matching where the other ALTER arms call `remapBatchedDataEvents`.
|
|
195
212
|
//
|
|
196
213
|
// NOTE: batched SCHEMA events are deliberately out of scope here. A schema event
|
|
197
|
-
// records a DDL operation, not current state —
|
|
198
|
-
//
|
|
199
|
-
//
|
|
214
|
+
// records a DDL operation, not current state — each now carries the statement's own
|
|
215
|
+
// canonical `ddl` text (and, for a rename, `oldObjectName`), so relabelling
|
|
216
|
+
// `objectName` without rewriting that text would produce an incoherent instruction.
|
|
217
|
+
// A consumer replays the schema events in order; the rename is one of them, carrying
|
|
218
|
+
// this very statement's SQL, so earlier events legitimately name the old table.
|
|
200
219
|
rctx.db._getEventEmitter().renameBatchedEvents(tableSchema.schemaName, oldName, newName);
|
|
201
220
|
// Deferred constraint checks this transaction already parked carry evaluators compiled
|
|
202
221
|
// against the OLD name — their scan leaves would connect to a table that no longer
|
|
@@ -261,10 +280,20 @@ async function runRenameTable(rctx, tableSchema, schema, newName) {
|
|
|
261
280
|
// names a vanished table. A module whose `renameTable` already did all its work (or
|
|
262
281
|
// that keeps no per-name catalog) simply omits the hook.
|
|
263
282
|
await module.finalizeRename?.(rctx.db, tableSchema.schemaName, oldName, newName);
|
|
283
|
+
// The public schema-change event, for a module with no emitter of its own — see
|
|
284
|
+
// {@link emitAlterSchemaEvent} for why every arm emits at its tail rather than
|
|
285
|
+
// alongside the module call. `objectName` is the NEW table; `oldObjectName` says
|
|
286
|
+
// what it renamed FROM, so a receiver can tell which of its tables the event is about.
|
|
287
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
288
|
+
type: 'alter', objectType: 'table',
|
|
289
|
+
objectName: newName,
|
|
290
|
+
oldObjectName: oldName,
|
|
291
|
+
ddl: sql,
|
|
292
|
+
});
|
|
264
293
|
log('Renamed table %s.%s to %s', tableSchema.schemaName, oldName, newName);
|
|
265
294
|
return null;
|
|
266
295
|
}
|
|
267
|
-
async function runRenameColumn(rctx, tableSchema, schema, oldName, newName) {
|
|
296
|
+
async function runRenameColumn(rctx, tableSchema, schema, oldName, newName, sql) {
|
|
268
297
|
const colIndex = tableSchema.columnIndexMap.get(oldName.toLowerCase());
|
|
269
298
|
if (colIndex === undefined) {
|
|
270
299
|
throw new QuereusError(`Column '${oldName}' not found in table '${tableSchema.name}'`, StatusCode.ERROR);
|
|
@@ -274,15 +303,18 @@ async function runRenameColumn(rctx, tableSchema, schema, oldName, newName) {
|
|
|
274
303
|
throw new QuereusError(`Column '${newName}' already exists in table '${tableSchema.name}'`, StatusCode.ERROR);
|
|
275
304
|
}
|
|
276
305
|
// Pre-flight, BEFORE the first side effect (`module.alterTable`): the rewritten
|
|
277
|
-
// body of every dependent view / materialized view
|
|
306
|
+
// body of every dependent view / materialized view — and the rewritten record of
|
|
307
|
+
// every dependent table (its CHECK expressions, the referenced-column list of an FK
|
|
308
|
+
// pointing here, its partial-index predicates) — must still be persistable, on the
|
|
278
309
|
// same unfailable-propagation reasoning as the table-rename arm above. Shares one
|
|
279
310
|
// resolver with `propagateColumnRename` so the two passes cannot drift apart in
|
|
280
311
|
// code; what makes them agree at RUNTIME (the resolver reads the LIVE catalog, and
|
|
281
312
|
// this probe runs pre-mutation while the propagation runs post-) is that
|
|
282
313
|
// `isTableInUnaliasedScope` skips the renamed table itself and probes only OTHER
|
|
283
314
|
// sources, whose column sets this rename does not touch.
|
|
284
|
-
const resolveColumnInSource = buildColumnSourceResolver(rctx.db);
|
|
285
|
-
assertRenameDependentsPersistable(rctx.db, schema, ast => renameColumnInAst(ast, tableSchema.name, oldName, newName, tableSchema.schemaName, resolveColumnInSource));
|
|
315
|
+
const resolveColumnInSource = buildColumnSourceResolver(rctx.db.schemaManager);
|
|
316
|
+
assertRenameDependentsPersistable(rctx.db, schema, ast => renameColumnInAst(ast, tableSchema.name, oldName, newName, tableSchema.schemaName, resolveColumnInSource), t => rewriteTableForColumnRename(t, tableSchema.schemaName.toLowerCase(), tableSchema.name, oldName, newName, resolveColumnInSource));
|
|
317
|
+
assertRenamedColumnBackingNamesFree(tableSchema, colIndex, oldName, newName);
|
|
286
318
|
const existingCol = tableSchema.columns[colIndex];
|
|
287
319
|
// Build a ColumnDef AST for the renamed column (preserving type info)
|
|
288
320
|
const newColumnDef = {
|
|
@@ -299,6 +331,7 @@ async function runRenameColumn(rctx, tableSchema, schema, oldName, newName) {
|
|
|
299
331
|
oldName,
|
|
300
332
|
newName,
|
|
301
333
|
newColumnDefAst: newColumnDef,
|
|
334
|
+
ddl: sql,
|
|
302
335
|
});
|
|
303
336
|
}
|
|
304
337
|
else {
|
|
@@ -333,10 +366,88 @@ async function runRenameColumn(rctx, tableSchema, schema, oldName, newName) {
|
|
|
333
366
|
// Propagate the rename into dependent objects (CHECK / FK / partial-index
|
|
334
367
|
// predicates in this and other tables, view and materialized-view bodies).
|
|
335
368
|
await propagateColumnRename(rctx, tableSchema.schemaName, tableSchema.name, oldName, newName, preStaleMvs, resolveColumnInSource);
|
|
369
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
370
|
+
type: 'alter', objectType: 'column',
|
|
371
|
+
objectName: tableSchema.name,
|
|
372
|
+
columnName: newName,
|
|
373
|
+
oldColumnName: oldName,
|
|
374
|
+
ddl: sql,
|
|
375
|
+
});
|
|
336
376
|
log('Renamed column %s.%s.%s to %s', tableSchema.schemaName, tableSchema.name, oldName, newName);
|
|
337
377
|
return null;
|
|
338
378
|
}
|
|
339
|
-
|
|
379
|
+
/**
|
|
380
|
+
* Refuses a RENAME COLUMN that would move an unnamed UNIQUE constraint's backing
|
|
381
|
+
* structure onto a name an index on the same table already holds.
|
|
382
|
+
*
|
|
383
|
+
* An unnamed UNIQUE is enforced by a structure named `_uc_<covered column names>`,
|
|
384
|
+
* derived from the LIVE column names and never recorded — so renaming a covered
|
|
385
|
+
* column moves that name. This is the same collision the four declaration paths
|
|
386
|
+
* already refuse (ADD CONSTRAINT, ADD COLUMN … unique, RENAME CONSTRAINT, and
|
|
387
|
+
* `SchemaManager.createIndex` from the index side), reached through a rename instead
|
|
388
|
+
* of a declaration. Left unguarded the user's index is silently reclassified as a
|
|
389
|
+
* hidden backing structure: it vanishes from `schema()` / `index_info()`, `DROP INDEX`
|
|
390
|
+
* answers `no such index`, and store-backed its `CREATE INDEX` line is dropped from
|
|
391
|
+
* the persisted catalog entry — after which the constraint's entries are built into
|
|
392
|
+
* that index's store and, on reopen, it stops rejecting duplicates.
|
|
393
|
+
*
|
|
394
|
+
* Placed before `module.alterTable` for the same reason those paths are: the store's
|
|
395
|
+
* `alterTable` persists, so a later throw would leave the damage on disk.
|
|
396
|
+
*
|
|
397
|
+
* Skips a case-only rename entirely: the derived name folds to the constraint's OWN
|
|
398
|
+
* pre-rename structure, which the memory backend materializes as a real index entry
|
|
399
|
+
* and the name-only guard would otherwise read as a collision (the same reason
|
|
400
|
+
* `runRenameConstraint` gates its check on `oldLower !== newLower`).
|
|
401
|
+
*
|
|
402
|
+
* Named and `derivedFromIndex` constraints are unaffected — neither takes a derived
|
|
403
|
+
* name. Two DIFFERENT unnamed constraints deriving one post-rename name is only
|
|
404
|
+
* reachable through duplicate unnamed UNIQUEs and is not this guard's problem.
|
|
405
|
+
*
|
|
406
|
+
* NOTE: name-only, like the declaration guards, so it also refuses the rename when the
|
|
407
|
+
* constraint is realized by a REUSED same-column-set index and therefore has no
|
|
408
|
+
* `_uc_*` structure to move — a legal rename turned away over a name nothing would
|
|
409
|
+
* have claimed. Deliberate: both backends decide reuse internally and at different
|
|
410
|
+
* times, so a reuse-aware check would make them disagree on which renames are legal.
|
|
411
|
+
* The refusal names both objects and is escapable by renaming the index first. If the
|
|
412
|
+
* false refusal ever bites, gate the check on the constraint actually holding a
|
|
413
|
+
* `_uc_*` structure — which means asking the module, not just `tableSchema.indexes`.
|
|
414
|
+
*/
|
|
415
|
+
function assertRenamedColumnBackingNamesFree(tableSchema, colIndex, oldName, newName) {
|
|
416
|
+
if (oldName.toLowerCase() === newName.toLowerCase())
|
|
417
|
+
return;
|
|
418
|
+
for (const uc of tableSchema.uniqueConstraints ?? []) {
|
|
419
|
+
if (uc.name !== undefined || uc.derivedFromIndex !== undefined)
|
|
420
|
+
continue;
|
|
421
|
+
if (!uc.columns.includes(colIndex))
|
|
422
|
+
continue;
|
|
423
|
+
const postRenameColumns = uc.columns.map(i => i === colIndex ? newName : (tableSchema.columns[i]?.name ?? String(i)));
|
|
424
|
+
assertUniqueConstraintIndexNameFree(tableSchema, undefined, postRenameColumns, `rename column '${oldName}' to '${newName}' on table '${tableSchema.name}'`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Refuses an inline constraint on a new column whose *user-written* name is already taken —
|
|
429
|
+
* by a constraint on the table, or by an earlier inline constraint in the same ADD COLUMN
|
|
430
|
+
* (neither is on `tableSchema` yet). Same within-table rule ADD CONSTRAINT and RENAME
|
|
431
|
+
* CONSTRAINT enforce; see {@link assertConstraintNameFree} for the ordering constraints.
|
|
432
|
+
*
|
|
433
|
+
* Reads the RAW declaration rather than the extracted table constraints: the extractors
|
|
434
|
+
* auto-name an unnamed CHECK `_check_<column>`, and that synthesized name is not user
|
|
435
|
+
* identity — comparing it would refuse two unnamed CHECKs on one new column, which is
|
|
436
|
+
* legal. Only the three classes that occupy a named-constraint array are compared (a name
|
|
437
|
+
* on an inline NOT NULL / DEFAULT / PRIMARY KEY is not stored, so it cannot collide).
|
|
438
|
+
*/
|
|
439
|
+
function assertInlineConstraintNamesFree(tableSchema, columnDef) {
|
|
440
|
+
const seen = new Set();
|
|
441
|
+
for (const declared of columnDef.constraints) {
|
|
442
|
+
if (!declared.name)
|
|
443
|
+
continue;
|
|
444
|
+
if (declared.type !== 'check' && declared.type !== 'unique' && declared.type !== 'foreignKey')
|
|
445
|
+
continue;
|
|
446
|
+
assertConstraintNameFree(tableSchema, declared.name, seen);
|
|
447
|
+
seen.add(declared.name.toLowerCase());
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async function runAddColumn(rctx, tableSchema, schema, columnDef, sql, backfill, backfillCb, checks, checkCbs) {
|
|
340
451
|
// Validate column doesn't already exist
|
|
341
452
|
if (tableSchema.columnIndexMap.has(columnDef.name.toLowerCase())) {
|
|
342
453
|
throw new QuereusError(`Column '${columnDef.name}' already exists in table '${tableSchema.name}'`, StatusCode.ERROR);
|
|
@@ -349,21 +460,37 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
349
460
|
// (bind params / bare columns / non-determinism rejected; `new.<column>` accepted)
|
|
350
461
|
// and, when it does not fold to a literal, compiled into `backfill` — the default
|
|
351
462
|
// evaluated against the existing row, so `new.<column>` reads that row's sibling.
|
|
463
|
+
// A GENERATED ALWAYS AS expression takes the same `backfill` route (always, since a
|
|
464
|
+
// generated column has no `defaultValue` any module could bulk-write), validated at
|
|
465
|
+
// plan-build with the generated-flavoured determinism check.
|
|
352
466
|
const defaultConstraint = columnDef.constraints?.find(c => c.type === 'default');
|
|
353
|
-
// Folded literal default
|
|
354
|
-
//
|
|
355
|
-
//
|
|
356
|
-
|
|
467
|
+
// Folded literal default, converted to the new column's declared type — the value a
|
|
468
|
+
// fresh INSERT under the same DEFAULT would store, and the same value each module
|
|
469
|
+
// folds for its own rows. Undefined when there is no default (a generated column
|
|
470
|
+
// included) or it does not fold — those carry `backfill` instead. Used by the NOT NULL
|
|
471
|
+
// gate below and by the batched-event remap's backfill value. An unconvertible literal
|
|
472
|
+
// (`integer default 'abc'`) throws MISMATCH here, before anything is mutated.
|
|
473
|
+
const foldedDefault = foldDefaultToType(defaultConstraint?.expr, inferType(columnDef.dataType), columnDef.name);
|
|
357
474
|
// Call module.alterTable for data + schema update
|
|
358
475
|
const module = requireVtabModule(tableSchema);
|
|
359
476
|
if (!module.alterTable) {
|
|
360
477
|
throw new QuereusError(`Module for table '${tableSchema.name}' does not support ALTER TABLE ADD COLUMN`, StatusCode.UNSUPPORTED);
|
|
361
478
|
}
|
|
362
|
-
// NOT NULL without a usable
|
|
363
|
-
// folded value is NULL is equivalent to "no DEFAULT" for this purpose. A
|
|
364
|
-
//
|
|
365
|
-
//
|
|
366
|
-
//
|
|
479
|
+
// NOT NULL without a usable value source cannot backfill existing rows. A DEFAULT whose
|
|
480
|
+
// folded value is NULL is equivalent to "no DEFAULT" for this purpose. A per-row source
|
|
481
|
+
// (carried in `backfill` — a non-foldable expression default or a GENERATED ALWAYS AS
|
|
482
|
+
// expression) IS usable: its NOT NULL enforcement is deferred to the module's per-row
|
|
483
|
+
// backfill, which rejects the ALTER if any row evaluates to NULL. If the table is
|
|
484
|
+
// non-empty and there is no usable source, reject before mutating any schema or data.
|
|
485
|
+
//
|
|
486
|
+
// Mandatoriness is RESOLVED, not read off the statement text: a column is NOT NULL
|
|
487
|
+
// either by an explicit `not null` or by the session `default_column_nullability`
|
|
488
|
+
// (which ships as `not_null`), so `add column x text default null` is a mandatory
|
|
489
|
+
// column with no value for the existing rows and must be refused. `columnDefToSchema`
|
|
490
|
+
// is the same resolver the memory module, the store module and the isolation layer's
|
|
491
|
+
// `deriveAddColumnBackfill` use, so a fourth spelling of the rule cannot drift. It
|
|
492
|
+
// also validates an explicit COLLATE and rejects DEFAULT + GENERATED ALWAYS AS on one
|
|
493
|
+
// column — both previously raised by the module mid-work, now pre-mutation.
|
|
367
494
|
//
|
|
368
495
|
// A module may opt out of this engine-generic rejection via the
|
|
369
496
|
// `delegatesNotNullBackfill` capability (structurally-total modules that
|
|
@@ -371,8 +498,9 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
371
498
|
// it declares the capability, the decision is left entirely to its
|
|
372
499
|
// `alterTable`. Native modules leave it off, so this still fires for them.
|
|
373
500
|
const delegatesBackfill = module.getCapabilities?.().delegatesNotNullBackfill === true;
|
|
374
|
-
const
|
|
375
|
-
|
|
501
|
+
const defaultNotNull = rctx.db.options.getStringOption('default_column_nullability') === 'not_null';
|
|
502
|
+
const resolvedNotNull = columnDefToSchema(columnDef, defaultNotNull, rctx.db.options.getStringOption('default_collation'), (n) => rctx.db.isCollationRegistered(n)).notNull;
|
|
503
|
+
if (resolvedNotNull && !delegatesBackfill && !backfill) {
|
|
376
504
|
const defaultIsNullish = !defaultConstraint?.expr || foldedDefault === null;
|
|
377
505
|
if (defaultIsNullish) {
|
|
378
506
|
await validateNotNullBackfill(rctx, tableSchema, columnDef.name);
|
|
@@ -395,9 +523,37 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
395
523
|
...inlineChecks,
|
|
396
524
|
...extractColumnLevelForeignKeys(columnDef),
|
|
397
525
|
];
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
|
|
526
|
+
// Refused before the column is materialized, so a duplicate name leaves the table
|
|
527
|
+
// completely untouched rather than relying on the revert path.
|
|
528
|
+
assertInlineConstraintNamesFree(tableSchema, columnDef);
|
|
529
|
+
// An inline `unique` builds an implicit backing structure named after the constraint
|
|
530
|
+
// — or `_uc_<column>` when unnamed — so reject before the column is materialized when
|
|
531
|
+
// that name is already an index on this table, or when the declaration merely repeats
|
|
532
|
+
// a UNIQUE the table already carries. The column does not exist yet, so both tests run
|
|
533
|
+
// off the column definition's own name (which is exactly what
|
|
534
|
+
// `extractColumnLevelUniqueConstraints` put in `columns`). Placed here, ahead of
|
|
535
|
+
// `module.alterTable`, so a refused statement leaves the table completely untouched
|
|
536
|
+
// rather than relying on the revert path.
|
|
537
|
+
//
|
|
538
|
+
// Duplicate-first, index-name-second — see the ordering rationale in
|
|
539
|
+
// `runAddConstraintViaModule`. `declaredColumnSets` carries the unnamed sets claimed by
|
|
540
|
+
// earlier inline constraints in THIS statement (`add column c … unique unique`); none
|
|
541
|
+
// of them is on `tableSchema` yet, so the guard cannot see them any other way.
|
|
542
|
+
const declaredColumnSets = new Set();
|
|
543
|
+
for (const constraint of inlineConstraints) {
|
|
544
|
+
if (constraint.type !== 'unique')
|
|
545
|
+
continue;
|
|
546
|
+
const columnNames = (constraint.columns ?? []).map(c => c.name);
|
|
547
|
+
const operation = `add ${constraint.name ? `constraint '${constraint.name}'` : 'UNIQUE'} column '${columnDef.name}' to table '${tableSchema.name}'`;
|
|
548
|
+
assertUniqueConstraintNotDuplicated(tableSchema, constraint.name, columnNames, operation, declaredColumnSets);
|
|
549
|
+
assertUniqueConstraintIndexNameFree(tableSchema, constraint.name, columnNames, operation);
|
|
550
|
+
if (constraint.name === undefined)
|
|
551
|
+
declaredColumnSets.add(uniqueConstraintColumnSetKey(columnNames));
|
|
552
|
+
}
|
|
553
|
+
// A per-row backfill derives each existing row's value from that row. Install a row slot
|
|
554
|
+
// over the backfill's row descriptor; the evaluator the module calls per existing row
|
|
555
|
+
// sets the slot to that row, so the expression's `new.<col>` refs (and the bare `<col>`
|
|
556
|
+
// refs a GENERATED ALWAYS AS expression uses) resolve to it.
|
|
401
557
|
const rowSlot = backfill ? createRowSlot(rctx, backfill.rowDescriptor) : undefined;
|
|
402
558
|
// When the new column carries a CHECK, install a second slot over the existing columns
|
|
403
559
|
// plus the new column; we evaluate each predicate against `[...existingRow, value]` after
|
|
@@ -411,7 +567,15 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
411
567
|
? async (row) => {
|
|
412
568
|
rowSlot.set(row);
|
|
413
569
|
const valueRaw = backfillCb(rctx);
|
|
414
|
-
const
|
|
570
|
+
const evaluated = (valueRaw instanceof Promise ? await valueRaw : valueRaw);
|
|
571
|
+
// Convert to the new column's declared type BEFORE the CHECK predicates see it,
|
|
572
|
+
// matching the write path (`emitInsert` coerces at the top of the DML pipeline, so
|
|
573
|
+
// constraint checking and storage both see the declared form). `coerceTo` is unset
|
|
574
|
+
// when the expression's static type already IS the column's type — see
|
|
575
|
+
// `AddColumnBackfill.coerceTo` for why re-converting there would be destructive.
|
|
576
|
+
const value = backfill.coerceTo
|
|
577
|
+
? validateAndParse(evaluated, backfill.coerceTo, columnDef.name)
|
|
578
|
+
: evaluated;
|
|
415
579
|
if (checkSlot && checkPredicates.length > 0 && checkCbs) {
|
|
416
580
|
checkSlot.set([...row, value]);
|
|
417
581
|
for (let i = 0; i < checkPredicates.length; i++) {
|
|
@@ -438,10 +602,19 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
438
602
|
// the inverse event remap.
|
|
439
603
|
let addedColIndex;
|
|
440
604
|
try {
|
|
605
|
+
// `ddl` marks this call — and only this one — as the statement's own action: the
|
|
606
|
+
// inline-constraint installs below and any revert calls pass none, so an
|
|
607
|
+
// emitter-backed module announces exactly ONE event for the whole statement.
|
|
608
|
+
//
|
|
609
|
+
// That marker settles HOW MANY events a successful statement announces, not whether a
|
|
610
|
+
// failed one announces any: this call is not the end of the statement, so a failure in
|
|
611
|
+
// the inline-constraint installs below leaves this announcement already batched. The
|
|
612
|
+
// statement-scoped retraction wrapped around the whole arm dispatch is what removes it.
|
|
441
613
|
updatedTableSchema = await module.alterTable(rctx.db, tableSchema.schemaName, tableSchema.name, {
|
|
442
614
|
type: 'addColumn',
|
|
443
615
|
columnDef,
|
|
444
616
|
backfillEvaluator,
|
|
617
|
+
ddl: sql,
|
|
445
618
|
});
|
|
446
619
|
// Events this transaction already batched for the table still describe the
|
|
447
620
|
// pre-ADD column set; insert the backfilled value at the new slot so a listener
|
|
@@ -513,9 +686,10 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
513
686
|
// folding against them is sound and preserves the optimizer's reach.
|
|
514
687
|
schema.addTable(columnOnlySchema);
|
|
515
688
|
// Validate the backfilled values against each inline CHECK, for the literal-default
|
|
516
|
-
// path only. A per-row (evaluator)
|
|
517
|
-
//
|
|
518
|
-
// stale pre-backfill snapshot
|
|
689
|
+
// path only. A per-row (evaluator) backfill — non-foldable DEFAULT or GENERATED
|
|
690
|
+
// ALWAYS AS — already enforced its CHECKs inside the backfill hook above, against the
|
|
691
|
+
// freshly-computed value rather than this scan's stale pre-backfill snapshot, and the
|
|
692
|
+
// module enforces NOT NULL there too. Runs
|
|
519
693
|
// before the whole install loop below, so on a column declaring several kinds a
|
|
520
694
|
// CHECK violation is reported ahead of a UNIQUE or FK one.
|
|
521
695
|
if (!backfill && inlineChecks.length > 0) {
|
|
@@ -554,6 +728,9 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
554
728
|
// orphans) and — store-backed — persists. Thread the returned schema forward so
|
|
555
729
|
// each constraint layers on the last. The module's answer carries no
|
|
556
730
|
// generated-column bookkeeping of its own, so re-derive it each round.
|
|
731
|
+
// Deliberately NO `ddl`: this is an engine-internal sub-step of the ADD COLUMN
|
|
732
|
+
// statement, so an emitter-backed module must announce nothing for it — the
|
|
733
|
+
// statement's one event rode the `addColumn` call above.
|
|
557
734
|
const withConstraint = await module.alterTable(rctx.db, tableSchema.schemaName, tableSchema.name, {
|
|
558
735
|
type: 'addConstraint',
|
|
559
736
|
constraint,
|
|
@@ -577,6 +754,17 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
577
754
|
oldObject: tableSchema,
|
|
578
755
|
newObject: finalTableSchema,
|
|
579
756
|
});
|
|
757
|
+
// ONE event for the whole statement, even when the column declared inline constraints.
|
|
758
|
+
// The install loop above makes a second `module.alterTable(addConstraint)` round-trip per
|
|
759
|
+
// inline constraint; an emitter-backed module now agrees on one event too, because only
|
|
760
|
+
// the `addColumn` call carried `ddl` and a module emits iff it is set. Do not "fix"
|
|
761
|
+
// this into per-constraint events on either path.
|
|
762
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
763
|
+
type: 'alter', objectType: 'column',
|
|
764
|
+
objectName: tableSchema.name,
|
|
765
|
+
columnName: columnDef.name,
|
|
766
|
+
ddl: sql,
|
|
767
|
+
});
|
|
580
768
|
log('Added column %s to table %s.%s', columnDef.name, tableSchema.schemaName, tableSchema.name);
|
|
581
769
|
return null;
|
|
582
770
|
}
|
|
@@ -594,6 +782,14 @@ async function runAddColumn(rctx, tableSchema, schema, columnDef, backfill, back
|
|
|
594
782
|
* mask the original violation. Restoring the catalog entry is a no-op when the ALTER failed
|
|
595
783
|
* before registering anything (the original schema is still the live one).
|
|
596
784
|
*
|
|
785
|
+
* Every module call here passes no `ddl`, deliberately: an emitter-backed module emits only
|
|
786
|
+
* for a call carrying `ddl`, so the unwinding itself announces nothing. That is the SECOND
|
|
787
|
+
* line of defence, not the only one — the failed statement's own `addColumn` call DID carry
|
|
788
|
+
* `ddl`, and an emitter-backed module already batched an event for it before we got here.
|
|
789
|
+
* What actually keeps a failed ADD COLUMN silent is the statement-scoped retraction the whole
|
|
790
|
+
* arm dispatch runs under (`withStatementScopedSchemaEvents` in `emitAlterTable`'s `run()`),
|
|
791
|
+
* which drops that event as the error propagates.
|
|
792
|
+
*
|
|
597
793
|
* NOTE: the hand-back is by NAME, so it assumes a name resolves to the constraint this
|
|
598
794
|
* ALTER installed. A pre-existing constraint can legitimately share an auto-name (nothing
|
|
599
795
|
* rejects `constraint _check_w check (…)` on a table that later gets `add column w …
|
|
@@ -656,6 +852,12 @@ async function validateBackfillAgainstChecks(rctx, columnOnlySchema, newCheckCon
|
|
|
656
852
|
const checkSql = expressionToString(cc.expr);
|
|
657
853
|
const sql = `select 1 from ${qualifiedTable} where not (${checkSql}) limit 1`;
|
|
658
854
|
const stmt = rctx.db.prepare(sql);
|
|
855
|
+
// The CHECK is SCHEMA-AUTHORED: it belongs to the altered table's own DDL, so a
|
|
856
|
+
// bare relation name inside it means the ALTERED table's schema — not the session
|
|
857
|
+
// path this freshly-prepared validation statement would otherwise inherit. Owning
|
|
858
|
+
// schema ONLY, matching `schemaAuthoredContext` (planner/building/schema-authored-context.ts),
|
|
859
|
+
// which decides the same thing for every CHECK the DML builders compile.
|
|
860
|
+
stmt._schemaPathOverride = [columnOnlySchema.schemaName];
|
|
659
861
|
try {
|
|
660
862
|
let violated = false;
|
|
661
863
|
for await (const _row of stmt._iterateRowsRaw()) {
|
|
@@ -672,9 +874,10 @@ async function validateBackfillAgainstChecks(rctx, columnOnlySchema, newCheckCon
|
|
|
672
874
|
}
|
|
673
875
|
}
|
|
674
876
|
/**
|
|
675
|
-
* Rejects ADD COLUMN ... NOT NULL when no usable
|
|
676
|
-
*
|
|
677
|
-
* the schema and module state are
|
|
877
|
+
* Rejects ADD COLUMN ... NOT NULL when no usable value source is supplied (no DEFAULT,
|
|
878
|
+
* a DEFAULT folding to NULL, and no per-row backfill) and the table already has rows.
|
|
879
|
+
* The pre-mutation form means no rollback is needed — the schema and module state are
|
|
880
|
+
* still untouched at this point.
|
|
678
881
|
*/
|
|
679
882
|
async function validateNotNullBackfill(rctx, tableSchema, newColumnName) {
|
|
680
883
|
const qualifiedTable = qualifyTableName(tableSchema.schemaName, tableSchema.name);
|
|
@@ -731,7 +934,7 @@ function predicateReferencesColumn(expr, columnName) {
|
|
|
731
934
|
visit(expr);
|
|
732
935
|
return found;
|
|
733
936
|
}
|
|
734
|
-
async function runDropColumn(rctx, tableSchema, schema, columnName) {
|
|
937
|
+
async function runDropColumn(rctx, tableSchema, schema, columnName, sql) {
|
|
735
938
|
const colIndex = tableSchema.columnIndexMap.get(columnName.toLowerCase());
|
|
736
939
|
if (colIndex === undefined) {
|
|
737
940
|
throw new QuereusError(`Column '${columnName}' not found in table '${tableSchema.name}'`, StatusCode.ERROR);
|
|
@@ -764,6 +967,16 @@ async function runDropColumn(rctx, tableSchema, schema, columnName) {
|
|
|
764
967
|
throw new QuereusError(`Cannot drop column '${columnName}' from '${tableSchema.name}': it is referenced by the WHERE clause of partial index '${idx.name}'`, StatusCode.CONSTRAINT);
|
|
765
968
|
}
|
|
766
969
|
}
|
|
970
|
+
// Validate: the remaining dependents `module.alterTable` cannot narrow — a sibling
|
|
971
|
+
// column's DEFAULT, a CHECK on this table, a foreign key in another table pointing AT
|
|
972
|
+
// the column, and an assertion body. All four run before `requireVtabModule` /
|
|
973
|
+
// `module.alterTable`, so a refused drop persists nothing. Ordered by widening blast
|
|
974
|
+
// radius (a column of this table → this table → another table → the whole database), so
|
|
975
|
+
// the most locally-explainable violation is the one reported.
|
|
976
|
+
assertNoColumnDefaultNamesColumn(rctx.db, tableSchema, columnName);
|
|
977
|
+
assertNoCheckConstraintNamesColumn(rctx.db, tableSchema, columnName);
|
|
978
|
+
assertNoForeignKeyReferencesColumn(rctx.db, tableSchema, columnName);
|
|
979
|
+
assertNoAssertionNamesColumn(rctx.db, tableSchema, columnName);
|
|
767
980
|
// Call module.alterTable for data + schema update
|
|
768
981
|
const module = requireVtabModule(tableSchema);
|
|
769
982
|
if (!module.alterTable) {
|
|
@@ -772,6 +985,7 @@ async function runDropColumn(rctx, tableSchema, schema, columnName) {
|
|
|
772
985
|
const updatedTableSchema = await module.alterTable(rctx.db, tableSchema.schemaName, tableSchema.name, {
|
|
773
986
|
type: 'dropColumn',
|
|
774
987
|
columnName,
|
|
988
|
+
ddl: sql,
|
|
775
989
|
});
|
|
776
990
|
// Events this transaction already batched for the table still carry the pre-drop
|
|
777
991
|
// arity; drop the slot so a listener at commit pairs value i with column i of the
|
|
@@ -792,6 +1006,14 @@ async function runDropColumn(rctx, tableSchema, schema, columnName) {
|
|
|
792
1006
|
oldObject: tableSchema,
|
|
793
1007
|
newObject: finalSchema,
|
|
794
1008
|
});
|
|
1009
|
+
// `drop`, not `alter` — the arm removes an object. Matches what an emitter-backed module
|
|
1010
|
+
// reports for the same statement.
|
|
1011
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
1012
|
+
type: 'drop', objectType: 'column',
|
|
1013
|
+
objectName: tableSchema.name,
|
|
1014
|
+
columnName,
|
|
1015
|
+
ddl: sql,
|
|
1016
|
+
});
|
|
795
1017
|
log('Dropped column %s from table %s.%s', columnName, tableSchema.schemaName, tableSchema.name);
|
|
796
1018
|
return null;
|
|
797
1019
|
}
|
|
@@ -805,7 +1027,7 @@ async function runDropColumn(rctx, tableSchema, schema, columnName) {
|
|
|
805
1027
|
* module owns the actual array rewrite and, for a UNIQUE, tearing down the
|
|
806
1028
|
* implicit covering index that backs it.
|
|
807
1029
|
*/
|
|
808
|
-
async function runDropConstraint(rctx, tableSchema, schema, constraintName) {
|
|
1030
|
+
async function runDropConstraint(rctx, tableSchema, schema, constraintName, sql) {
|
|
809
1031
|
const constraintClass = resolveNamedConstraintClass(tableSchema, constraintName);
|
|
810
1032
|
if (constraintClass === 'unique') {
|
|
811
1033
|
rejectDerivedFromIndex(tableSchema, constraintName, 'DROP');
|
|
@@ -817,6 +1039,7 @@ async function runDropConstraint(rctx, tableSchema, schema, constraintName) {
|
|
|
817
1039
|
const updatedTableSchema = await module.alterTable(rctx.db, tableSchema.schemaName, tableSchema.name, {
|
|
818
1040
|
type: 'dropConstraint',
|
|
819
1041
|
constraintName,
|
|
1042
|
+
ddl: sql,
|
|
820
1043
|
});
|
|
821
1044
|
schema.addTable(updatedTableSchema);
|
|
822
1045
|
rctx.db.schemaManager.getChangeNotifier().notifyChange({
|
|
@@ -826,6 +1049,11 @@ async function runDropConstraint(rctx, tableSchema, schema, constraintName) {
|
|
|
826
1049
|
oldObject: tableSchema,
|
|
827
1050
|
newObject: updatedTableSchema,
|
|
828
1051
|
});
|
|
1052
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
1053
|
+
type: 'alter', objectType: 'table',
|
|
1054
|
+
objectName: tableSchema.name,
|
|
1055
|
+
ddl: sql,
|
|
1056
|
+
});
|
|
829
1057
|
log('Dropped constraint %s from table %s.%s', constraintName, tableSchema.schemaName, tableSchema.name);
|
|
830
1058
|
return null;
|
|
831
1059
|
}
|
|
@@ -835,7 +1063,7 @@ async function runDropConstraint(rctx, tableSchema, schema, constraintName) {
|
|
|
835
1063
|
* name must not already address a constraint), and rejects renaming a UNIQUE
|
|
836
1064
|
* derived from an explicit index. Routed through `module.alterTable`.
|
|
837
1065
|
*/
|
|
838
|
-
async function runRenameConstraint(rctx, tableSchema, schema, oldName, newName) {
|
|
1066
|
+
async function runRenameConstraint(rctx, tableSchema, schema, oldName, newName, sql) {
|
|
839
1067
|
const constraintClass = resolveNamedConstraintClass(tableSchema, oldName);
|
|
840
1068
|
if (constraintClass === 'unique') {
|
|
841
1069
|
rejectDerivedFromIndex(tableSchema, oldName, 'RENAME');
|
|
@@ -847,6 +1075,17 @@ async function runRenameConstraint(rctx, tableSchema, schema, oldName, newName)
|
|
|
847
1075
|
if (oldLower !== newLower && namedConstraintExists(tableSchema, newName)) {
|
|
848
1076
|
throw new QuereusError(`Cannot rename constraint to '${newName}': a constraint with that name already exists in table '${tableSchema.name}'`, StatusCode.CONSTRAINT);
|
|
849
1077
|
}
|
|
1078
|
+
// A UNIQUE constraint's implicit backing structure is named after the constraint, so
|
|
1079
|
+
// the rename renames that structure too — reject when the new name is already an
|
|
1080
|
+
// index on this table (the mirror of `SchemaManager.createIndex`'s refusal). Gated on
|
|
1081
|
+
// `oldLower !== newLower` for the same reason the collision check above is: on the
|
|
1082
|
+
// memory backend the constraint's OWN backing structure is a materialized index under
|
|
1083
|
+
// the old name, which a case-only rename would otherwise match.
|
|
1084
|
+
if (constraintClass === 'unique' && oldLower !== newLower) {
|
|
1085
|
+
// No columns to pass: the renamed-to name is always a name, so the `_uc_<cols>`
|
|
1086
|
+
// auto-name branch is unreachable from here.
|
|
1087
|
+
assertUniqueConstraintIndexNameFree(tableSchema, newName, [], `rename constraint '${oldName}' to '${newName}' on table '${tableSchema.name}'`);
|
|
1088
|
+
}
|
|
850
1089
|
const module = requireVtabModule(tableSchema);
|
|
851
1090
|
if (!module.alterTable) {
|
|
852
1091
|
throw new QuereusError(`Module for table '${tableSchema.name}' does not support ALTER TABLE RENAME CONSTRAINT`, StatusCode.UNSUPPORTED);
|
|
@@ -855,6 +1094,7 @@ async function runRenameConstraint(rctx, tableSchema, schema, oldName, newName)
|
|
|
855
1094
|
type: 'renameConstraint',
|
|
856
1095
|
oldName,
|
|
857
1096
|
newName,
|
|
1097
|
+
ddl: sql,
|
|
858
1098
|
});
|
|
859
1099
|
schema.addTable(updatedTableSchema);
|
|
860
1100
|
rctx.db.schemaManager.getChangeNotifier().notifyChange({
|
|
@@ -864,16 +1104,16 @@ async function runRenameConstraint(rctx, tableSchema, schema, oldName, newName)
|
|
|
864
1104
|
oldObject: tableSchema,
|
|
865
1105
|
newObject: updatedTableSchema,
|
|
866
1106
|
});
|
|
1107
|
+
// A named constraint is not an `objectType` of its own, so the arm reports the TABLE it
|
|
1108
|
+
// reshaped — same as an emitter-backed module does.
|
|
1109
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
1110
|
+
type: 'alter', objectType: 'table',
|
|
1111
|
+
objectName: tableSchema.name,
|
|
1112
|
+
ddl: sql,
|
|
1113
|
+
});
|
|
867
1114
|
log('Renamed constraint %s.%s.%s to %s', tableSchema.schemaName, tableSchema.name, oldName, newName);
|
|
868
1115
|
return null;
|
|
869
1116
|
}
|
|
870
|
-
/** True when `name` addresses any named CHECK / UNIQUE / FOREIGN KEY constraint. */
|
|
871
|
-
function namedConstraintExists(tableSchema, name) {
|
|
872
|
-
const lower = name.toLowerCase();
|
|
873
|
-
return (tableSchema.checkConstraints ?? []).some(c => c.name?.toLowerCase() === lower)
|
|
874
|
-
|| (tableSchema.uniqueConstraints ?? []).some(c => c.name?.toLowerCase() === lower)
|
|
875
|
-
|| (tableSchema.foreignKeys ?? []).some(c => c.name?.toLowerCase() === lower);
|
|
876
|
-
}
|
|
877
1117
|
/**
|
|
878
1118
|
* Rejects DROP/RENAME of a UNIQUE constraint that was synthesized from an explicit
|
|
879
1119
|
* `CREATE UNIQUE INDEX` (`derivedFromIndex` set). That constraint is the index's
|
|
@@ -887,7 +1127,7 @@ function rejectDerivedFromIndex(tableSchema, constraintName, op) {
|
|
|
887
1127
|
throw new QuereusError(`Cannot ${op} CONSTRAINT '${constraintName}' on '${tableSchema.name}': it is backed by index '${uc.derivedFromIndex}' (created via CREATE UNIQUE INDEX). Use DROP INDEX '${uc.derivedFromIndex}' instead.`, StatusCode.CONSTRAINT);
|
|
888
1128
|
}
|
|
889
1129
|
}
|
|
890
|
-
async function runAlterColumn(rctx, tableSchema, schema, action) {
|
|
1130
|
+
async function runAlterColumn(rctx, tableSchema, schema, action, sql) {
|
|
891
1131
|
const colIndex = tableSchema.columnIndexMap.get(action.columnName.toLowerCase());
|
|
892
1132
|
if (colIndex === undefined) {
|
|
893
1133
|
throw new QuereusError(`Column '${action.columnName}' not found in table '${tableSchema.name}'`, StatusCode.ERROR);
|
|
@@ -944,6 +1184,7 @@ async function runAlterColumn(rctx, tableSchema, schema, action) {
|
|
|
944
1184
|
setDataType: action.setDataType,
|
|
945
1185
|
setDefault: action.setDefault,
|
|
946
1186
|
setCollation: action.setCollation,
|
|
1187
|
+
ddl: sql,
|
|
947
1188
|
});
|
|
948
1189
|
// Events this transaction already batched still carry the PRE-conversion value at
|
|
949
1190
|
// the altered column (`SET DATA TYPE`'s normalization, `SET NOT NULL`'s null →
|
|
@@ -965,6 +1206,15 @@ async function runAlterColumn(rctx, tableSchema, schema, action) {
|
|
|
965
1206
|
oldObject: tableSchema,
|
|
966
1207
|
newObject: updatedTableSchema,
|
|
967
1208
|
});
|
|
1209
|
+
// All four attribute forms (SET/DROP NOT NULL, SET DATA TYPE, SET/DROP DEFAULT,
|
|
1210
|
+
// SET COLLATE) report the same `alter`/`column` shape — the event says which column
|
|
1211
|
+
// changed, not which attribute; `ddl` says which attribute, exactly.
|
|
1212
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
1213
|
+
type: 'alter', objectType: 'column',
|
|
1214
|
+
objectName: tableSchema.name,
|
|
1215
|
+
columnName: action.columnName,
|
|
1216
|
+
ddl: sql,
|
|
1217
|
+
});
|
|
968
1218
|
log('Altered column %s.%s.%s', tableSchema.schemaName, tableSchema.name, action.columnName);
|
|
969
1219
|
return null;
|
|
970
1220
|
}
|
|
@@ -1002,11 +1252,17 @@ function alterColumnEventValueRemap(tableSchema, colIndex, action) {
|
|
|
1002
1252
|
};
|
|
1003
1253
|
}
|
|
1004
1254
|
if (action.setNotNull === true) {
|
|
1005
|
-
// SET NOT NULL backfill: null → the folded literal DEFAULT, the same
|
|
1006
|
-
// module applies. No usable literal default means the module
|
|
1007
|
-
// NULLs (nothing to remap) or rejected the ALTER before reaching here.
|
|
1008
|
-
|
|
1009
|
-
|
|
1255
|
+
// SET NOT NULL backfill: null → the folded-and-CONVERTED literal DEFAULT, the same
|
|
1256
|
+
// map the module applies to its rows. No usable literal default means the module
|
|
1257
|
+
// either found no NULLs (nothing to remap) or rejected the ALTER before reaching here.
|
|
1258
|
+
//
|
|
1259
|
+
// NOTE: `foldDefaultToType` throws MISMATCH on an unconvertible literal, and this
|
|
1260
|
+
// runs AFTER the module mutated. Unreachable today — every module folds the same
|
|
1261
|
+
// DEFAULT through the same helper up front and rejects the ALTER there, so a literal
|
|
1262
|
+
// that fails here would already have failed. If a module ever stops folding eagerly,
|
|
1263
|
+
// catch here and return undefined rather than aborting a completed ALTER.
|
|
1264
|
+
const col = tableSchema.columns[colIndex];
|
|
1265
|
+
const folded = foldDefaultToType(col.defaultValue, col.logicalType, col.name);
|
|
1010
1266
|
if (folded === undefined || folded === null)
|
|
1011
1267
|
return undefined;
|
|
1012
1268
|
return (v) => (v === null ? folded : v);
|
|
@@ -1080,7 +1336,7 @@ function runDropConstraintTags(rctx, tableSchema, constraintName, keys) {
|
|
|
1080
1336
|
log('Dropped tags on constraint %s.%s.%s', tableSchema.schemaName, tableSchema.name, constraintName);
|
|
1081
1337
|
return null;
|
|
1082
1338
|
}
|
|
1083
|
-
async function runAlterPrimaryKey(rctx, tableSchema, schema, columns) {
|
|
1339
|
+
async function runAlterPrimaryKey(rctx, tableSchema, schema, columns, sql) {
|
|
1084
1340
|
const newPkDef = columns.map(col => {
|
|
1085
1341
|
const idx = tableSchema.columnIndexMap.get(col.name.toLowerCase());
|
|
1086
1342
|
if (idx === undefined) {
|
|
@@ -1100,12 +1356,33 @@ async function runAlterPrimaryKey(rctx, tableSchema, schema, columns) {
|
|
|
1100
1356
|
}
|
|
1101
1357
|
seen.add(pk.index);
|
|
1102
1358
|
}
|
|
1359
|
+
// Column indices of the key being retired and the one replacing it. Both index the
|
|
1360
|
+
// CURRENT column layout — ALTER PRIMARY KEY adds and drops no column — so they are
|
|
1361
|
+
// also indices into the batched events' row images, which any earlier ALTER in this
|
|
1362
|
+
// transaction has already remapped to that layout.
|
|
1363
|
+
const oldPkIndices = tableSchema.primaryKeyDefinition.map(pk => pk.index);
|
|
1364
|
+
const newPkIndices = newPkDef.map(pk => pk.index);
|
|
1103
1365
|
// Try native module re-key first
|
|
1104
1366
|
const module = requireVtabModule(tableSchema);
|
|
1105
1367
|
if (module.alterTable) {
|
|
1106
1368
|
try {
|
|
1107
1369
|
const schemaChangePk = newPkDef.map(pk => ({ index: pk.index, desc: pk.desc ?? false }));
|
|
1108
|
-
const updatedTableSchema = await module.alterTable(rctx.db, tableSchema.schemaName, tableSchema.name, { type: 'alterPrimaryKey', newPkColumns: schemaChangePk });
|
|
1370
|
+
const updatedTableSchema = await module.alterTable(rctx.db, tableSchema.schemaName, tableSchema.name, { type: 'alterPrimaryKey', newPkColumns: schemaChangePk, ddl: sql });
|
|
1371
|
+
// Events this transaction already recorded identify their rows by the RETIRED
|
|
1372
|
+
// key; re-derive each from its own row image so the commit delivers every event
|
|
1373
|
+
// under the key the table has at delivery. AFTER the module call (a module
|
|
1374
|
+
// failure must leave the batch as untouched as the catalog, and the store's
|
|
1375
|
+
// `ddlCommitPendingOps` flushes its queued events into our batch DURING that
|
|
1376
|
+
// call — those must be in the batch before we walk it), BEFORE the catalog swap,
|
|
1377
|
+
// matching where the other ALTER arms call `remapBatchedDataEvents`.
|
|
1378
|
+
//
|
|
1379
|
+
// NOTE: this sits inside the try whose catch falls through to the rebuild, so an
|
|
1380
|
+
// UNSUPPORTED raised BELOW it (only reachable via a `table_modified` listener, as
|
|
1381
|
+
// `schema.addTable` raises no UNSUPPORTED) would re-key twice. The second pass is
|
|
1382
|
+
// idempotent for every event except a PK-moving update, whose image tie-break no
|
|
1383
|
+
// longer recognizes the already-rewritten key. If anything below this line gains
|
|
1384
|
+
// a real UNSUPPORTED path, narrow the try to the `module.alterTable` call.
|
|
1385
|
+
rctx.db._getEventEmitter().rekeyBatchedDataEvents(tableSchema.schemaName, tableSchema.name, oldPkIndices, newPkIndices);
|
|
1109
1386
|
schema.addTable(updatedTableSchema);
|
|
1110
1387
|
rctx.db.schemaManager.getChangeNotifier().notifyChange({
|
|
1111
1388
|
type: 'table_modified',
|
|
@@ -1114,39 +1391,98 @@ async function runAlterPrimaryKey(rctx, tableSchema, schema, columns) {
|
|
|
1114
1391
|
oldObject: tableSchema,
|
|
1115
1392
|
newObject: updatedTableSchema,
|
|
1116
1393
|
});
|
|
1394
|
+
// NOTE: inside the try whose catch falls through to the rebuild — same caveat as
|
|
1395
|
+
// the re-key above. The emit raises no UNSUPPORTED (the gate either emits or
|
|
1396
|
+
// does not), so it cannot itself trigger the fallback.
|
|
1397
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
1398
|
+
type: 'alter', objectType: 'table',
|
|
1399
|
+
objectName: tableSchema.name,
|
|
1400
|
+
ddl: sql,
|
|
1401
|
+
});
|
|
1117
1402
|
log('Altered primary key of %s.%s (native)', tableSchema.schemaName, tableSchema.name);
|
|
1118
1403
|
return null;
|
|
1119
1404
|
}
|
|
1120
1405
|
catch (e) {
|
|
1121
1406
|
if (e instanceof QuereusError && e.code === StatusCode.UNSUPPORTED) {
|
|
1122
|
-
// Fall through to rebuild
|
|
1407
|
+
// Fall through to rebuild. The swallow is the documented protocol
|
|
1408
|
+
// (docs/module-authoring.md § `alterPrimaryKey`), but a swallowed error must
|
|
1409
|
+
// still leave a trace — this is the only record that the native re-key was
|
|
1410
|
+
// attempted and declined.
|
|
1411
|
+
warnLog('Module %s declined an in-place re-key of %s.%s (UNSUPPORTED: %s); falling back to a shadow-table rebuild', tableSchema.vtabModuleName ?? '<unknown>', tableSchema.schemaName, tableSchema.name, e.message);
|
|
1123
1412
|
}
|
|
1124
1413
|
else {
|
|
1125
1414
|
throw e;
|
|
1126
1415
|
}
|
|
1127
1416
|
}
|
|
1128
1417
|
}
|
|
1129
|
-
// Rebuild fallback
|
|
1418
|
+
// Rebuild fallback. Two preconditions, both refusals rather than repairs — see
|
|
1419
|
+
// `rebuildViaShadowTable` for why neither has a correct outcome. Checked here, after the
|
|
1420
|
+
// native attempt, so both entry paths into the rebuild (no `alterTable` hook at all; the
|
|
1421
|
+
// hook raised UNSUPPORTED) are covered by one check each; a module that raised
|
|
1422
|
+
// UNSUPPORTED has by contract mutated nothing, so a refusal here leaves the catalog, the
|
|
1423
|
+
// table and the enclosing transaction untouched. Capability first: it is unconditional,
|
|
1424
|
+
// so it is the more informative answer when both apply.
|
|
1425
|
+
if (!module.renameTable) {
|
|
1426
|
+
throw new QuereusError(`Module '${tableSchema.vtabModuleName ?? '<unknown>'}' does not support ALTER PRIMARY KEY on table `
|
|
1427
|
+
+ `'${tableSchema.name}': it cannot re-key in place (it implements no 'alterTable' hook, or the `
|
|
1428
|
+
+ `hook declined), and the engine's fallback rebuild finishes by renaming a shadow table over `
|
|
1429
|
+
+ `this one — without 'renameTable' the module would keep the rows under the shadow name and `
|
|
1430
|
+
+ `the rebuilt table could not be opened.`, StatusCode.UNSUPPORTED);
|
|
1431
|
+
}
|
|
1432
|
+
// NOTE: refused on every `DdlTransactionality` tier, including a module declaring
|
|
1433
|
+
// 'transactional'. None does today; if one appears its DROP + RENAME would roll back
|
|
1434
|
+
// together with the row copy, making this refusal over-broad — exempt that tier then, the
|
|
1435
|
+
// way `assertDdlTransactionPolicy` already does.
|
|
1436
|
+
if (isExplicitTransactionOpen(rctx.db)) {
|
|
1437
|
+
throw new QuereusError(`ALTER PRIMARY KEY on table '${tableSchema.name}' is not allowed inside an explicit transaction: `
|
|
1438
|
+
+ `module '${tableSchema.vtabModuleName ?? '<unknown>'}' cannot re-key in place, so the statement `
|
|
1439
|
+
+ `would fall back to a shadow-table rebuild whose DROP + RENAME survives ROLLBACK while its row `
|
|
1440
|
+
+ `copy does not — a rollback would leave an empty table and destroy rows committed before this `
|
|
1441
|
+
+ `transaction began. COMMIT or ROLLBACK first, then re-issue in autocommit mode.`, StatusCode.ERROR);
|
|
1442
|
+
}
|
|
1130
1443
|
await rebuildTableWithNewShape(rctx, tableSchema, schema, tableSchema.columns.map(c => c.name), newPkDef);
|
|
1444
|
+
// A DEFENSIVE NO-OP on this path today, not the working re-key the native arm above does.
|
|
1445
|
+
// Nothing can be in the batch for this table by now: the rebuild's own events are
|
|
1446
|
+
// suppressed (see `rebuildViaShadowTable`), the ALTER statement writes no rows of its own,
|
|
1447
|
+
// and the explicit-transaction refusal above rules out earlier same-transaction writes.
|
|
1448
|
+
// Kept anyway — it costs one walk of an empty batch, and it is the correct call the moment
|
|
1449
|
+
// that transaction guard is loosened; deleting it would quietly make this arm's
|
|
1450
|
+
// as-of-delivery `key` guarantee depend on the guard staying exactly as it is. Every column
|
|
1451
|
+
// survives the rebuild in order (`survivingColumns` above is the full list), so the indices
|
|
1452
|
+
// would still line up with the event images.
|
|
1453
|
+
rctx.db._getEventEmitter().rekeyBatchedDataEvents(tableSchema.schemaName, tableSchema.name, oldPkIndices, newPkIndices);
|
|
1454
|
+
// The rebuild's own four statements are silent (`rebuildViaShadowTable` runs them inside
|
|
1455
|
+
// `withPublicEventsSuppressed`, which also swallows the inner RENAME TO arm's event). This
|
|
1456
|
+
// emit is OUTSIDE that scope, so the re-key itself reports exactly one `alter`/`table` —
|
|
1457
|
+
// the same shape the native branch above reports.
|
|
1458
|
+
//
|
|
1459
|
+
// NOTE: this arm is the one place where a module WITH its own emitter can end up reporting
|
|
1460
|
+
// nothing — it raised UNSUPPORTED instead of emitting, and the gate below then suppresses
|
|
1461
|
+
// the engine's fallback because the module registration advertises native support. No such
|
|
1462
|
+
// module exists today (memory re-keys in place, the store handles `alterPrimaryKey`
|
|
1463
|
+
// natively), so the path is unreachable. If an emitter-backed module ever declines the
|
|
1464
|
+
// re-key, teach the gate that a rebuild fallback owns the event regardless of the module's
|
|
1465
|
+
// emitter.
|
|
1466
|
+
emitAlterSchemaEvent(rctx, tableSchema, {
|
|
1467
|
+
type: 'alter', objectType: 'table',
|
|
1468
|
+
objectName: tableSchema.name,
|
|
1469
|
+
ddl: sql,
|
|
1470
|
+
});
|
|
1131
1471
|
log('Altered primary key of %s.%s (rebuild)', tableSchema.schemaName, tableSchema.name);
|
|
1132
1472
|
return null;
|
|
1133
1473
|
}
|
|
1134
1474
|
/**
|
|
1135
|
-
* Rebuilds a table with a new column projection and/or primary key
|
|
1136
|
-
*
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1475
|
+
* Rebuilds a table with a new column projection and/or primary key, via the
|
|
1476
|
+
* shadow-table SQL approach with DROP+RENAME. This is the fallback for a module
|
|
1477
|
+
* whose `alterTable` throws `UNSUPPORTED` for `alterPrimaryKey` (or omits the
|
|
1478
|
+
* hook); the built-in memory and store modules both re-key in place and never
|
|
1479
|
+
* reach it. See `rebuildViaShadowTable` for the two preconditions
|
|
1480
|
+
* `runAlterPrimaryKey` checks before calling this.
|
|
1139
1481
|
*/
|
|
1140
1482
|
async function rebuildTableWithNewShape(rctx, tableSchema, schema, survivingColumns, newPkDef) {
|
|
1141
1483
|
const tableName = tableSchema.name;
|
|
1142
1484
|
const schemaName = tableSchema.schemaName;
|
|
1143
|
-
|
|
1144
|
-
if (module instanceof MemoryTableModule) {
|
|
1145
|
-
await rebuildMemoryTable(rctx, tableSchema, schema, module, survivingColumns, newPkDef);
|
|
1146
|
-
}
|
|
1147
|
-
else {
|
|
1148
|
-
await rebuildViaShadowTable(rctx, tableSchema, schema, survivingColumns, newPkDef);
|
|
1149
|
-
}
|
|
1485
|
+
await rebuildViaShadowTable(rctx, tableSchema, schema, survivingColumns, newPkDef);
|
|
1150
1486
|
const finalSchema = schema.getTable(tableName);
|
|
1151
1487
|
if (finalSchema) {
|
|
1152
1488
|
rctx.db.schemaManager.getChangeNotifier().notifyChange({
|
|
@@ -1158,87 +1494,6 @@ async function rebuildTableWithNewShape(rctx, tableSchema, schema, survivingColu
|
|
|
1158
1494
|
});
|
|
1159
1495
|
}
|
|
1160
1496
|
}
|
|
1161
|
-
/**
|
|
1162
|
-
* MemoryTable rebuild: builds a new table via module.create() and copies rows
|
|
1163
|
-
* directly from the old manager, then swaps in the module and catalog.
|
|
1164
|
-
*/
|
|
1165
|
-
async function rebuildMemoryTable(rctx, tableSchema, schema, module, survivingColumns, newPkDef) {
|
|
1166
|
-
const tableName = tableSchema.name;
|
|
1167
|
-
const schemaName = tableSchema.schemaName;
|
|
1168
|
-
const oldKey = `${schemaName}.${tableName}`.toLowerCase();
|
|
1169
|
-
const oldMgr = module.tables.get(oldKey);
|
|
1170
|
-
if (!oldMgr) {
|
|
1171
|
-
throw new QuereusError(`Table '${tableName}' not found in module`, StatusCode.INTERNAL);
|
|
1172
|
-
}
|
|
1173
|
-
// Build column index mapping: old column index → new column index
|
|
1174
|
-
const survivingIndices = [];
|
|
1175
|
-
const newColumns = [];
|
|
1176
|
-
for (const colName of survivingColumns) {
|
|
1177
|
-
const oldIdx = tableSchema.columnIndexMap.get(colName.toLowerCase());
|
|
1178
|
-
if (oldIdx === undefined)
|
|
1179
|
-
continue;
|
|
1180
|
-
survivingIndices.push(oldIdx);
|
|
1181
|
-
newColumns.push(tableSchema.columns[oldIdx]);
|
|
1182
|
-
}
|
|
1183
|
-
// Remap PK indices from old schema to new column order
|
|
1184
|
-
const remappedPk = newPkDef.map(pk => {
|
|
1185
|
-
const newIdx = survivingIndices.indexOf(pk.index);
|
|
1186
|
-
if (newIdx === -1) {
|
|
1187
|
-
throw new QuereusError(`PK column index ${pk.index} not in surviving columns`, StatusCode.INTERNAL);
|
|
1188
|
-
}
|
|
1189
|
-
return { ...pk, index: newIdx };
|
|
1190
|
-
});
|
|
1191
|
-
// Build new schema
|
|
1192
|
-
const newSchema = Object.freeze({
|
|
1193
|
-
...tableSchema,
|
|
1194
|
-
columns: Object.freeze(newColumns),
|
|
1195
|
-
columnIndexMap: buildColumnIndexMap(newColumns),
|
|
1196
|
-
primaryKeyDefinition: Object.freeze(remappedPk),
|
|
1197
|
-
indexes: Object.freeze([]),
|
|
1198
|
-
});
|
|
1199
|
-
// Create the new table via the module API (goes directly to base layer)
|
|
1200
|
-
const shadowName = `${tableName}__rekey_${Date.now()}`;
|
|
1201
|
-
const shadowSchema = Object.freeze({ ...newSchema, name: shadowName });
|
|
1202
|
-
await module.create(rctx.db, shadowSchema);
|
|
1203
|
-
const shadowMgr = module.tables.get(`${schemaName}.${shadowName}`.toLowerCase());
|
|
1204
|
-
if (!shadowMgr) {
|
|
1205
|
-
throw new QuereusError(`Shadow table manager not found after create`, StatusCode.INTERNAL);
|
|
1206
|
-
}
|
|
1207
|
-
try {
|
|
1208
|
-
// Copy rows from old table to new, projecting surviving columns
|
|
1209
|
-
const rows = oldMgr.scanAllRows();
|
|
1210
|
-
for (const oldRow of rows) {
|
|
1211
|
-
const newRow = survivingIndices.map(i => oldRow[i]);
|
|
1212
|
-
shadowMgr.insertRow(newRow);
|
|
1213
|
-
}
|
|
1214
|
-
// Swap: remove old, remove shadow, re-register shadow under old name
|
|
1215
|
-
module.tables.delete(oldKey);
|
|
1216
|
-
module.tables.delete(`${schemaName}.${shadowName}`.toLowerCase());
|
|
1217
|
-
shadowMgr.renameTable(tableName);
|
|
1218
|
-
module.tables.set(oldKey, shadowMgr);
|
|
1219
|
-
// Update catalog
|
|
1220
|
-
schema.removeTable(tableName);
|
|
1221
|
-
schema.addTable(shadowMgr.tableSchema);
|
|
1222
|
-
// The old manager is now orphaned. Any active VirtualTableConnection bound
|
|
1223
|
-
// to it (e.g. from a prior insert in this session) is stale and must not be
|
|
1224
|
-
// reused against the rebuilt table — a reused-stale + fresh connection pair
|
|
1225
|
-
// leaves two candidates registered for the same table name, which trips
|
|
1226
|
-
// DeferredConstraintQueue.findConnection at the next commit. Mirror the
|
|
1227
|
-
// drop-table path's cleanup (schema/manager.ts dropTable). The orphaned
|
|
1228
|
-
// manager and its pending layer are discarded with the old manager, so no
|
|
1229
|
-
// rollback is needed; this intentionally bypasses implicit-transaction
|
|
1230
|
-
// deferral, exactly as drop table relies on.
|
|
1231
|
-
rctx.db.removeConnectionsForTable(schemaName, tableName);
|
|
1232
|
-
}
|
|
1233
|
-
catch (e) {
|
|
1234
|
-
// Clean up shadow on failure
|
|
1235
|
-
try {
|
|
1236
|
-
module.tables.delete(`${schemaName}.${shadowName}`.toLowerCase());
|
|
1237
|
-
}
|
|
1238
|
-
catch { /* ignore */ }
|
|
1239
|
-
throw e;
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
1497
|
/**
|
|
1243
1498
|
* Build the shadow-table CREATE TABLE DDL used by the non-memory rebuild path.
|
|
1244
1499
|
*
|
|
@@ -1310,7 +1565,7 @@ export function buildShadowTableDdl(tableSchema, shadowName, survivingColumns, n
|
|
|
1310
1565
|
async function runSetMaintained(rctx, tableSchema, schema, columns, select) {
|
|
1311
1566
|
const live = schema.getTable(tableSchema.name);
|
|
1312
1567
|
if (!live) {
|
|
1313
|
-
throw new
|
|
1568
|
+
throw new RelationNotFoundError(`no such table: ${tableSchema.name}`);
|
|
1314
1569
|
}
|
|
1315
1570
|
const explicit = columns !== undefined && columns.length > 0;
|
|
1316
1571
|
// Any omitted-insert defaults ride inside `select` (→ derivation.selectAst).
|
|
@@ -1345,9 +1600,29 @@ async function runDropMaintained(rctx, tableSchema, schema) {
|
|
|
1345
1600
|
return null;
|
|
1346
1601
|
}
|
|
1347
1602
|
/**
|
|
1348
|
-
* Generic rebuild via shadow table SQL for
|
|
1603
|
+
* Generic rebuild via shadow table SQL, for a module without a native
|
|
1604
|
+
* `alterPrimaryKey`.
|
|
1605
|
+
*
|
|
1606
|
+
* Two preconditions the caller (`runAlterPrimaryKey`) enforces, because this rebuild has no
|
|
1607
|
+
* correct outcome without them:
|
|
1608
|
+
*
|
|
1609
|
+
* - **The module must implement `renameTable`.** The last step renames the shadow table over
|
|
1610
|
+
* the original; a module that files its rows under the table's name and never hears about
|
|
1611
|
+
* the rename keeps them under the shadow name while the catalog says otherwise, and the
|
|
1612
|
+
* rebuilt table cannot be connected at all.
|
|
1613
|
+
* - **No explicit transaction may be open.** The two halves have different transactional
|
|
1614
|
+
* lifetimes: the schema half (DROP + RENAME) escapes ROLLBACK on every
|
|
1615
|
+
* `DdlTransactionality` tier a built-in module reaches, while the row copy is staged in the
|
|
1616
|
+
* transaction and IS undone. A ROLLBACK would therefore keep the new empty table and
|
|
1617
|
+
* discard the copy of the rows it replaced — destroying data committed before the
|
|
1618
|
+
* transaction began. Making the schema half roll back needs transactional DDL no module
|
|
1619
|
+
* offers; making the data half survive would commit part of the user's transaction behind
|
|
1620
|
+
* their back.
|
|
1621
|
+
*
|
|
1622
|
+
* The four statements are engine scaffolding, not statements the application issued, so the
|
|
1623
|
+
* whole rebuild runs with the PUBLIC event channels suppressed — see the scope inside.
|
|
1349
1624
|
*/
|
|
1350
|
-
async function rebuildViaShadowTable(rctx, tableSchema,
|
|
1625
|
+
async function rebuildViaShadowTable(rctx, tableSchema, _schema, survivingColumns, newPkDef) {
|
|
1351
1626
|
const tableName = tableSchema.name;
|
|
1352
1627
|
const schemaName = tableSchema.schemaName;
|
|
1353
1628
|
const shadowName = `${tableName}__rekey_${Date.now()}`;
|
|
@@ -1355,19 +1630,40 @@ async function rebuildViaShadowTable(rctx, tableSchema, schema, survivingColumns
|
|
|
1355
1630
|
const qualifiedTable = qualifyTableName(schemaName, tableName);
|
|
1356
1631
|
const createDdl = buildShadowTableDdl(tableSchema, shadowName, survivingColumns, newPkDef);
|
|
1357
1632
|
const projection = survivingColumns.map(c => quoteIdentifier(c)).join(', ');
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1633
|
+
// The rebuild's statements are ordinary SQL, so without this scope they would raise
|
|
1634
|
+
// ordinary notifications describing the scaffolding rather than what the user asked for:
|
|
1635
|
+
// the copy announces every existing row as a fresh `insert` (relabelled onto the real
|
|
1636
|
+
// table by the trailing rename), and the create/drop pair announces a timestamped table
|
|
1637
|
+
// created and the real one dropped. A re-key changes no row and replaces no table, so all
|
|
1638
|
+
// of that is wrong. Covers the failure cleanup below too — a shadow table nobody was told
|
|
1639
|
+
// about must not announce its own drop.
|
|
1640
|
+
//
|
|
1641
|
+
// Only the PUBLIC channels are suppressed. The internal catalog change notifier keeps
|
|
1642
|
+
// firing throughout (it is what invalidates the optimizer's and the write path's cached
|
|
1643
|
+
// schemas), which is why the rebuilt table is immediately plannable under its new key.
|
|
1644
|
+
//
|
|
1645
|
+
// NOTE: a module whose own emitter defers delivery to its own commit — rather than
|
|
1646
|
+
// emitting during the write — can still leak the copy's inserts, because its events
|
|
1647
|
+
// arrive after this scope has closed. Conditional, not a live defect: no module that
|
|
1648
|
+
// reaches this rebuild behaves that way (memory and the store both re-key in place and
|
|
1649
|
+
// never enter it). If one ever does, suppression has to become name-keyed (covering the
|
|
1650
|
+
// shadow name as well as the real one) or the events have to be dropped out of the batch
|
|
1651
|
+
// after the fact.
|
|
1652
|
+
await rctx.db._getEventEmitter().withPublicEventsSuppressed(async () => {
|
|
1365
1653
|
try {
|
|
1366
|
-
await rctx.db._execWithinTransaction(
|
|
1654
|
+
await rctx.db._execWithinTransaction(createDdl);
|
|
1655
|
+
await rctx.db._execWithinTransaction(`insert into ${qualifiedShadow} (${projection}) select ${projection} from ${qualifiedTable}`);
|
|
1656
|
+
await rctx.db._execWithinTransaction(`drop table ${qualifiedTable}`);
|
|
1657
|
+
await rctx.db._execWithinTransaction(`alter table ${qualifiedShadow} rename to ${quoteIdentifier(tableName)}`);
|
|
1367
1658
|
}
|
|
1368
|
-
catch {
|
|
1369
|
-
|
|
1370
|
-
|
|
1659
|
+
catch (e) {
|
|
1660
|
+
try {
|
|
1661
|
+
await rctx.db._execWithinTransaction(`drop table if exists ${qualifiedShadow}`);
|
|
1662
|
+
}
|
|
1663
|
+
catch { /* ignore */ }
|
|
1664
|
+
throw e;
|
|
1665
|
+
}
|
|
1666
|
+
});
|
|
1371
1667
|
}
|
|
1372
1668
|
/**
|
|
1373
1669
|
* Propagates a table rename into every dependent schema object the catalog
|
|
@@ -1428,6 +1724,11 @@ async function propagateTableRenameInSchema(db, schema, renamedSchemaName, oldNa
|
|
|
1428
1724
|
});
|
|
1429
1725
|
}
|
|
1430
1726
|
}
|
|
1727
|
+
// Assertions: same in-place body rewrite as plain views, plus a regenerated
|
|
1728
|
+
// `violationSql` (the text the commit-time evaluator re-parses). Assertions
|
|
1729
|
+
// feed no materialized view, so order against the MV pass is free; sitting
|
|
1730
|
+
// next to the view loop keeps the plain schema-level objects together.
|
|
1731
|
+
propagateTableRenameToAssertions(db, schema, renamedSchemaName, oldName, newName);
|
|
1431
1732
|
// Materialized views: same in-place body rewrite as plain views ("MV ≡
|
|
1432
1733
|
// faster view"), plus the derived-field re-key, row-time re-registration,
|
|
1433
1734
|
// and staleness discipline the MV record needs. Runs AFTER the view loop
|
|
@@ -1465,6 +1766,20 @@ function rewriteTableForTableRename(table, renamedSchemaLower, oldName, newName)
|
|
|
1465
1766
|
changed = true;
|
|
1466
1767
|
return { ...idx };
|
|
1467
1768
|
});
|
|
1769
|
+
// Column-level expressions — a DEFAULT (`w integer default ((select min(v) from u))`)
|
|
1770
|
+
// and a generated column's body. Unlike the column verb's arm, no seeded/unseeded
|
|
1771
|
+
// split: `renameTableInAst` resolves nothing against an implicit owning table, so one
|
|
1772
|
+
// entry point covers the renamed table's own self-referencing default and every other
|
|
1773
|
+
// table's alike.
|
|
1774
|
+
//
|
|
1775
|
+
// Also unlike the collections above, no per-item shallow copy: the rewrite is in place
|
|
1776
|
+
// and a `ColumnSchema`'s own fields are untouched, so a fresh column object would only
|
|
1777
|
+
// make the catalog's array stop being identical to the one the module's rename hook
|
|
1778
|
+
// just handed back. Flipping `changed` is what re-registers the table and fires
|
|
1779
|
+
// `table_modified`, which is all the copies above achieve either.
|
|
1780
|
+
const columnsRewritten = renameTableInColumnExpressions(table.columns, oldName, newName, renamedSchemaLower);
|
|
1781
|
+
if (columnsRewritten)
|
|
1782
|
+
changed = true;
|
|
1468
1783
|
if (!changed)
|
|
1469
1784
|
return table;
|
|
1470
1785
|
return Object.freeze({
|
|
@@ -1474,21 +1789,6 @@ function rewriteTableForTableRename(table, renamedSchemaLower, oldName, newName)
|
|
|
1474
1789
|
indexes: table.indexes ? Object.freeze(newIndexes) : table.indexes,
|
|
1475
1790
|
});
|
|
1476
1791
|
}
|
|
1477
|
-
/**
|
|
1478
|
-
* The catalog-backed {@link ResolveColumnInSource} the column-rename rewriters consult
|
|
1479
|
-
* to keep their unqualified-reference walk scope-aware. Built once per statement and
|
|
1480
|
-
* shared by the pre-flight probe in {@link runRenameColumn} and the real propagation
|
|
1481
|
-
* below, so the two cannot drift apart. Note it resolves against the LIVE catalog on
|
|
1482
|
-
* every call, so sharing it does not by itself freeze the answer between the two passes
|
|
1483
|
-
* — see the pre-flight's comment for why they agree anyway.
|
|
1484
|
-
*/
|
|
1485
|
-
function buildColumnSourceResolver(db) {
|
|
1486
|
-
return (s, t, col) => {
|
|
1487
|
-
const targetSchema = db.schemaManager.getSchema(s);
|
|
1488
|
-
const targetTable = targetSchema?.getTable(t);
|
|
1489
|
-
return targetTable?.columnIndexMap.has(col.toLowerCase()) ?? false;
|
|
1490
|
-
};
|
|
1491
|
-
}
|
|
1492
1792
|
async function propagateColumnRename(rctx, renamedSchemaName, tableName, oldCol, newCol, preStaleMvs, resolveColumnInSource) {
|
|
1493
1793
|
const schemaManager = rctx.db.schemaManager;
|
|
1494
1794
|
for (const schema of schemaManager._getAllSchemas()) {
|
|
@@ -1543,6 +1843,10 @@ async function propagateColumnRenameInSchema(db, schema, renamedSchemaName, tabl
|
|
|
1543
1843
|
});
|
|
1544
1844
|
}
|
|
1545
1845
|
}
|
|
1846
|
+
// Assertions: same in-place body rewrite as plain views (unseeded walker —
|
|
1847
|
+
// an assertion body owns its own FROM scopes), plus a regenerated
|
|
1848
|
+
// `violationSql`.
|
|
1849
|
+
propagateColumnRenameToAssertions(db, schema, renamedSchemaName, tableName, oldCol, newCol, resolveColumnInSource);
|
|
1546
1850
|
// Materialized views: same in-place body rewrite as plain views, then the
|
|
1547
1851
|
// MV-specific tail — backing-column rename for a shifted output name,
|
|
1548
1852
|
// row-time re-registration, staleness discipline (the listener marked every
|
|
@@ -1560,7 +1864,7 @@ function rewriteTableForColumnRename(table, renamedSchemaLower, tableName, oldCo
|
|
|
1560
1864
|
const newChecks = table.checkConstraints.map(cc => {
|
|
1561
1865
|
const rewrote = isRenamedTable
|
|
1562
1866
|
? renameColumnInCheckExpression(cc.expr, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource)
|
|
1563
|
-
: renameColumnInAst(cc.expr, tableName, oldCol, newCol, renamedSchemaLower);
|
|
1867
|
+
: renameColumnInAst(cc.expr, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource);
|
|
1564
1868
|
if (!rewrote)
|
|
1565
1869
|
return cc;
|
|
1566
1870
|
changed = true;
|
|
@@ -1606,12 +1910,29 @@ function rewriteTableForColumnRename(table, renamedSchemaLower, tableName, oldCo
|
|
|
1606
1910
|
const newIndexes = (table.indexes ?? []).map(idx => {
|
|
1607
1911
|
const rewrote = isRenamedTable
|
|
1608
1912
|
? renameColumnInCheckExpression(idx.predicate, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource)
|
|
1609
|
-
: renameColumnInAst(idx.predicate, tableName, oldCol, newCol, renamedSchemaLower);
|
|
1913
|
+
: renameColumnInAst(idx.predicate, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource);
|
|
1610
1914
|
if (!rewrote)
|
|
1611
1915
|
return idx;
|
|
1612
1916
|
changed = true;
|
|
1613
1917
|
return { ...idx };
|
|
1614
1918
|
});
|
|
1919
|
+
// Column-level expressions — a DEFAULT (`b integer default (new.a + 1)`) and a
|
|
1920
|
+
// generated column's body (`g integer generated always as (a + 1)`). Same branch split
|
|
1921
|
+
// the checks and predicates use above: the renamed table's own columns take the seeded
|
|
1922
|
+
// walk (a generated body's bare `a` binds to the owning table; a default's `new.a`
|
|
1923
|
+
// names its row image), any other table's take the unseeded one (it can reach here only
|
|
1924
|
+
// through a subquery, whose FROM must bind the ref).
|
|
1925
|
+
//
|
|
1926
|
+
// Unlike the collections above, no per-item shallow copy: the rewrite is in place and a
|
|
1927
|
+
// `ColumnSchema`'s own fields are untouched, so a fresh column object would only make
|
|
1928
|
+
// the catalog's array stop being identical to the one the module's rename hook just
|
|
1929
|
+
// built and handed back. Flipping `changed` is what re-registers the table and fires
|
|
1930
|
+
// `table_modified`, which is all the copies above achieve either.
|
|
1931
|
+
const columnsRewritten = isRenamedTable
|
|
1932
|
+
? renameColumnInColumnExpressions(table.columns, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource)
|
|
1933
|
+
: rewriteOtherTableColumnExpressions(table.columns, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource);
|
|
1934
|
+
if (columnsRewritten)
|
|
1935
|
+
changed = true;
|
|
1615
1936
|
if (!changed)
|
|
1616
1937
|
return table;
|
|
1617
1938
|
return Object.freeze({
|
|
@@ -1621,6 +1942,31 @@ function rewriteTableForColumnRename(table, renamedSchemaLower, tableName, oldCo
|
|
|
1621
1942
|
indexes: table.indexes ? Object.freeze(newIndexes) : table.indexes,
|
|
1622
1943
|
});
|
|
1623
1944
|
}
|
|
1945
|
+
/**
|
|
1946
|
+
* The unseeded arm of the column-expression rewrite above, for a table that is NOT the
|
|
1947
|
+
* renamed one. `renameColumnInColumnExpressions` is deliberately seeded-only (that is the
|
|
1948
|
+
* whole reason it exists), so the other branch walks the two fields directly with
|
|
1949
|
+
* {@link renameColumnInAst} — the same entry point the checks and predicates arms use for
|
|
1950
|
+
* a foreign table, and for the same reason: an unqualified ref in someone else's default
|
|
1951
|
+
* must bind inside its own subquery's FROM, never to this table.
|
|
1952
|
+
*
|
|
1953
|
+
* `resolveColumnInSource` is as load-bearing here as on the seeded arm, and for the mirror
|
|
1954
|
+
* reason: without it the walk cannot tell that an inner FROM source exposes the old name,
|
|
1955
|
+
* so a nested `(select (select max(a) from other) from t)` rewrites the INNER `a` — which
|
|
1956
|
+
* binds to `other` — and the default silently starts reading a different column. It also
|
|
1957
|
+
* keeps this pass in step with the pre-flight persistability probe, which runs the same
|
|
1958
|
+
* rewriter with the resolver supplied.
|
|
1959
|
+
*/
|
|
1960
|
+
function rewriteOtherTableColumnExpressions(columns, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource) {
|
|
1961
|
+
let changed = false;
|
|
1962
|
+
for (const col of columns) {
|
|
1963
|
+
for (const expr of [col.defaultValue, col.generatedExpr]) {
|
|
1964
|
+
if (expr && renameColumnInAst(expr, tableName, oldCol, newCol, renamedSchemaLower, resolveColumnInSource))
|
|
1965
|
+
changed = true;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
return changed;
|
|
1969
|
+
}
|
|
1624
1970
|
/**
|
|
1625
1971
|
* Build a minimal constraints array from an existing ColumnSchema
|
|
1626
1972
|
* so that the ColumnDef AST accurately represents the column.
|