@quereus/quereus 3.2.1 → 4.0.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 +7 -0
- package/dist/src/common/datatype.d.ts +12 -0
- package/dist/src/common/datatype.d.ts.map +1 -1
- package/dist/src/common/datatype.js.map +1 -1
- package/dist/src/common/types.d.ts +24 -0
- package/dist/src/common/types.d.ts.map +1 -1
- package/dist/src/common/types.js.map +1 -1
- package/dist/src/core/database-assertions.d.ts +37 -9
- package/dist/src/core/database-assertions.d.ts.map +1 -1
- package/dist/src/core/database-assertions.js +62 -106
- package/dist/src/core/database-assertions.js.map +1 -1
- package/dist/src/core/database-events.d.ts +163 -0
- package/dist/src/core/database-events.d.ts.map +1 -1
- package/dist/src/core/database-events.js +235 -21
- package/dist/src/core/database-events.js.map +1 -1
- package/dist/src/core/database-external-changes.d.ts +28 -0
- package/dist/src/core/database-external-changes.d.ts.map +1 -0
- package/dist/src/core/database-external-changes.js +242 -0
- package/dist/src/core/database-external-changes.js.map +1 -0
- package/dist/src/core/database-internal.d.ts +50 -1
- package/dist/src/core/database-internal.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views.d.ts +1253 -0
- package/dist/src/core/database-materialized-views.d.ts.map +1 -0
- package/dist/src/core/database-materialized-views.js +3064 -0
- package/dist/src/core/database-materialized-views.js.map +1 -0
- package/dist/src/core/database-options.d.ts +4 -0
- package/dist/src/core/database-options.d.ts.map +1 -1
- package/dist/src/core/database-options.js +10 -0
- package/dist/src/core/database-options.js.map +1 -1
- package/dist/src/core/database-transaction.d.ts +19 -3
- package/dist/src/core/database-transaction.d.ts.map +1 -1
- package/dist/src/core/database-transaction.js +30 -3
- package/dist/src/core/database-transaction.js.map +1 -1
- package/dist/src/core/database-watchers.d.ts +19 -0
- package/dist/src/core/database-watchers.d.ts.map +1 -1
- package/dist/src/core/database-watchers.js +63 -3
- package/dist/src/core/database-watchers.js.map +1 -1
- package/dist/src/core/database.d.ts +203 -11
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +493 -29
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/derived-row-validator.d.ts +137 -0
- package/dist/src/core/derived-row-validator.d.ts.map +1 -0
- package/dist/src/core/derived-row-validator.js +314 -0
- package/dist/src/core/derived-row-validator.js.map +1 -0
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +30 -9
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/emit/ast-stringify.d.ts +135 -1
- package/dist/src/emit/ast-stringify.d.ts.map +1 -1
- package/dist/src/emit/ast-stringify.js +795 -120
- package/dist/src/emit/ast-stringify.js.map +1 -1
- package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
- package/dist/src/func/builtins/aggregate.js +11 -10
- 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 +32 -0
- package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts +3 -0
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +229 -0
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +10 -2
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/json.d.ts.map +1 -1
- package/dist/src/func/builtins/json.js +3 -2
- package/dist/src/func/builtins/json.js.map +1 -1
- package/dist/src/func/builtins/mutation.d.ts +2 -0
- package/dist/src/func/builtins/mutation.d.ts.map +1 -0
- package/dist/src/func/builtins/mutation.js +53 -0
- package/dist/src/func/builtins/mutation.js.map +1 -0
- package/dist/src/func/builtins/schema.d.ts +2 -0
- package/dist/src/func/builtins/schema.d.ts.map +1 -1
- package/dist/src/func/builtins/schema.js +713 -26
- package/dist/src/func/builtins/schema.js.map +1 -1
- package/dist/src/func/builtins/string.js +1 -1
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/func/registration.d.ts +9 -0
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +4 -0
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/index.d.ts +25 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +27 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/ast.d.ts +353 -21
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/index.d.ts +14 -1
- package/dist/src/parser/index.d.ts.map +1 -1
- package/dist/src/parser/index.js +19 -0
- package/dist/src/parser/index.js.map +1 -1
- package/dist/src/parser/lexer.d.ts +9 -0
- package/dist/src/parser/lexer.d.ts.map +1 -1
- package/dist/src/parser/lexer.js +9 -0
- package/dist/src/parser/lexer.js.map +1 -1
- package/dist/src/parser/parser.d.ts +277 -8
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +1393 -471
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/visitor.d.ts.map +1 -1
- package/dist/src/parser/visitor.js +12 -8
- package/dist/src/parser/visitor.js.map +1 -1
- package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -1
- package/dist/src/planner/analysis/assertion-classifier.js +4 -0
- 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 +8 -4
- package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -1
- package/dist/src/planner/analysis/authored-inverse.d.ts +22 -0
- package/dist/src/planner/analysis/authored-inverse.d.ts.map +1 -0
- package/dist/src/planner/analysis/authored-inverse.js +267 -0
- package/dist/src/planner/analysis/authored-inverse.js.map +1 -0
- package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/binding-extractor.js +9 -6
- package/dist/src/planner/analysis/binding-extractor.js.map +1 -1
- package/dist/src/planner/analysis/change-scope.d.ts +34 -4
- package/dist/src/planner/analysis/change-scope.d.ts.map +1 -1
- package/dist/src/planner/analysis/change-scope.js +115 -7
- package/dist/src/planner/analysis/change-scope.js.map +1 -1
- package/dist/src/planner/analysis/check-extraction.d.ts +36 -2
- package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -1
- package/dist/src/planner/analysis/check-extraction.js +174 -46
- package/dist/src/planner/analysis/check-extraction.js.map +1 -1
- package/dist/src/planner/analysis/coarsened-key.d.ts +109 -0
- package/dist/src/planner/analysis/coarsened-key.d.ts.map +1 -0
- package/dist/src/planner/analysis/coarsened-key.js +228 -0
- package/dist/src/planner/analysis/coarsened-key.js.map +1 -0
- package/dist/src/planner/analysis/comparison-collation.d.ts +216 -0
- package/dist/src/planner/analysis/comparison-collation.d.ts.map +1 -0
- package/dist/src/planner/analysis/comparison-collation.js +341 -0
- package/dist/src/planner/analysis/comparison-collation.js.map +1 -0
- package/dist/src/planner/analysis/constraint-extractor.d.ts +13 -1
- package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.js +220 -21
- package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
- package/dist/src/planner/analysis/coverage-prover.d.ts +321 -0
- package/dist/src/planner/analysis/coverage-prover.d.ts.map +1 -0
- package/dist/src/planner/analysis/coverage-prover.js +1038 -0
- package/dist/src/planner/analysis/coverage-prover.js.map +1 -0
- package/dist/src/planner/analysis/key-filter.d.ts +22 -0
- package/dist/src/planner/analysis/key-filter.d.ts.map +1 -0
- package/dist/src/planner/analysis/key-filter.js +105 -0
- package/dist/src/planner/analysis/key-filter.js.map +1 -0
- package/dist/src/planner/analysis/partial-unique-extraction.d.ts +36 -1
- package/dist/src/planner/analysis/partial-unique-extraction.d.ts.map +1 -1
- package/dist/src/planner/analysis/partial-unique-extraction.js +148 -22
- package/dist/src/planner/analysis/partial-unique-extraction.js.map +1 -1
- package/dist/src/planner/analysis/predicate-normalizer.d.ts.map +1 -1
- package/dist/src/planner/analysis/predicate-normalizer.js +30 -1
- package/dist/src/planner/analysis/predicate-normalizer.js.map +1 -1
- package/dist/src/planner/analysis/predicate-shape.d.ts +36 -1
- package/dist/src/planner/analysis/predicate-shape.d.ts.map +1 -1
- package/dist/src/planner/analysis/predicate-shape.js +51 -13
- package/dist/src/planner/analysis/predicate-shape.js.map +1 -1
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts +314 -0
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts.map +1 -0
- package/dist/src/planner/analysis/query-rewrite-matcher.js +1081 -0
- package/dist/src/planner/analysis/query-rewrite-matcher.js.map +1 -0
- package/dist/src/planner/analysis/scalar-invertibility.d.ts +92 -0
- package/dist/src/planner/analysis/scalar-invertibility.d.ts.map +1 -0
- package/dist/src/planner/analysis/scalar-invertibility.js +129 -0
- package/dist/src/planner/analysis/scalar-invertibility.js.map +1 -0
- package/dist/src/planner/analysis/update-lineage.d.ts +196 -0
- package/dist/src/planner/analysis/update-lineage.d.ts.map +1 -0
- package/dist/src/planner/analysis/update-lineage.js +322 -0
- package/dist/src/planner/analysis/update-lineage.js.map +1 -0
- package/dist/src/planner/analysis/view-complement.d.ts +42 -0
- package/dist/src/planner/analysis/view-complement.d.ts.map +1 -0
- package/dist/src/planner/analysis/view-complement.js +54 -0
- package/dist/src/planner/analysis/view-complement.js.map +1 -0
- package/dist/src/planner/building/alter-table.d.ts +1 -1
- package/dist/src/planner/building/alter-table.d.ts.map +1 -1
- package/dist/src/planner/building/alter-table.js +211 -2
- package/dist/src/planner/building/alter-table.js.map +1 -1
- package/dist/src/planner/building/block.d.ts.map +1 -1
- package/dist/src/planner/building/block.js +18 -1
- package/dist/src/planner/building/block.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.d.ts +33 -5
- package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +63 -28
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/building/create-view.d.ts +9 -0
- package/dist/src/planner/building/create-view.d.ts.map +1 -1
- package/dist/src/planner/building/create-view.js +41 -12
- 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 +94 -0
- package/dist/src/planner/building/ddl.js.map +1 -1
- package/dist/src/planner/building/declare-schema.d.ts +1 -0
- package/dist/src/planner/building/declare-schema.d.ts.map +1 -1
- package/dist/src/planner/building/declare-schema.js +4 -1
- package/dist/src/planner/building/declare-schema.js.map +1 -1
- package/dist/src/planner/building/default-scope.d.ts +26 -0
- package/dist/src/planner/building/default-scope.d.ts.map +1 -0
- package/dist/src/planner/building/default-scope.js +41 -0
- package/dist/src/planner/building/default-scope.js.map +1 -0
- package/dist/src/planner/building/delete.d.ts +19 -1
- package/dist/src/planner/building/delete.d.ts.map +1 -1
- package/dist/src/planner/building/delete.js +116 -34
- package/dist/src/planner/building/delete.js.map +1 -1
- package/dist/src/planner/building/dml-target.d.ts +118 -0
- package/dist/src/planner/building/dml-target.d.ts.map +1 -0
- package/dist/src/planner/building/dml-target.js +282 -0
- package/dist/src/planner/building/dml-target.js.map +1 -0
- package/dist/src/planner/building/drop-index.d.ts.map +1 -1
- package/dist/src/planner/building/drop-index.js +4 -1
- package/dist/src/planner/building/drop-index.js.map +1 -1
- package/dist/src/planner/building/drop-view.d.ts.map +1 -1
- package/dist/src/planner/building/drop-view.js +4 -2
- package/dist/src/planner/building/drop-view.js.map +1 -1
- package/dist/src/planner/building/expression.d.ts.map +1 -1
- package/dist/src/planner/building/expression.js +60 -21
- package/dist/src/planner/building/expression.js.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.d.ts +30 -0
- package/dist/src/planner/building/foreign-key-builder.d.ts.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.js +160 -129
- package/dist/src/planner/building/foreign-key-builder.js.map +1 -1
- package/dist/src/planner/building/insert.d.ts +45 -2
- package/dist/src/planner/building/insert.d.ts.map +1 -1
- package/dist/src/planner/building/insert.js +257 -88
- package/dist/src/planner/building/insert.js.map +1 -1
- package/dist/src/planner/building/lens-auxiliary-access.d.ts +22 -0
- package/dist/src/planner/building/lens-auxiliary-access.d.ts.map +1 -0
- package/dist/src/planner/building/lens-auxiliary-access.js +132 -0
- package/dist/src/planner/building/lens-auxiliary-access.js.map +1 -0
- package/dist/src/planner/building/materialized-view.d.ts +16 -0
- package/dist/src/planner/building/materialized-view.d.ts.map +1 -0
- package/dist/src/planner/building/materialized-view.js +57 -0
- package/dist/src/planner/building/materialized-view.js.map +1 -0
- package/dist/src/planner/building/returning-star.d.ts +32 -0
- package/dist/src/planner/building/returning-star.d.ts.map +1 -0
- package/dist/src/planner/building/returning-star.js +45 -0
- package/dist/src/planner/building/returning-star.js.map +1 -0
- package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
- package/dist/src/planner/building/select-aggregates.js +51 -13
- package/dist/src/planner/building/select-aggregates.js.map +1 -1
- package/dist/src/planner/building/select-compound.d.ts.map +1 -1
- package/dist/src/planner/building/select-compound.js +84 -11
- package/dist/src/planner/building/select-compound.js.map +1 -1
- package/dist/src/planner/building/select-context.d.ts +10 -2
- package/dist/src/planner/building/select-context.d.ts.map +1 -1
- package/dist/src/planner/building/select-context.js +7 -1
- package/dist/src/planner/building/select-context.js.map +1 -1
- package/dist/src/planner/building/select-modifiers.js +6 -0
- package/dist/src/planner/building/select-modifiers.js.map +1 -1
- package/dist/src/planner/building/select-ordinal.d.ts +18 -0
- package/dist/src/planner/building/select-ordinal.d.ts.map +1 -1
- package/dist/src/planner/building/select-ordinal.js +30 -0
- package/dist/src/planner/building/select-ordinal.js.map +1 -1
- package/dist/src/planner/building/select-projections.d.ts +8 -2
- package/dist/src/planner/building/select-projections.d.ts.map +1 -1
- package/dist/src/planner/building/select-projections.js +26 -4
- package/dist/src/planner/building/select-projections.js.map +1 -1
- package/dist/src/planner/building/select-window.d.ts.map +1 -1
- package/dist/src/planner/building/select-window.js +8 -5
- package/dist/src/planner/building/select-window.js.map +1 -1
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +164 -59
- package/dist/src/planner/building/select.js.map +1 -1
- package/dist/src/planner/building/set-object-tags.d.ts +7 -0
- package/dist/src/planner/building/set-object-tags.d.ts.map +1 -0
- package/dist/src/planner/building/set-object-tags.js +38 -0
- package/dist/src/planner/building/set-object-tags.js.map +1 -0
- package/dist/src/planner/building/tag-diagnostics.d.ts +27 -0
- package/dist/src/planner/building/tag-diagnostics.d.ts.map +1 -0
- package/dist/src/planner/building/tag-diagnostics.js +37 -0
- package/dist/src/planner/building/tag-diagnostics.js.map +1 -0
- package/dist/src/planner/building/update.d.ts +18 -1
- package/dist/src/planner/building/update.d.ts.map +1 -1
- package/dist/src/planner/building/update.js +134 -58
- package/dist/src/planner/building/update.js.map +1 -1
- package/dist/src/planner/building/view-mutation-builder.d.ts +15 -0
- package/dist/src/planner/building/view-mutation-builder.d.ts.map +1 -0
- package/dist/src/planner/building/view-mutation-builder.js +1158 -0
- package/dist/src/planner/building/view-mutation-builder.js.map +1 -0
- package/dist/src/planner/building/with.d.ts +11 -0
- package/dist/src/planner/building/with.d.ts.map +1 -1
- package/dist/src/planner/building/with.js +48 -10
- package/dist/src/planner/building/with.js.map +1 -1
- package/dist/src/planner/cost/index.d.ts +83 -0
- package/dist/src/planner/cost/index.d.ts.map +1 -1
- package/dist/src/planner/cost/index.js +114 -0
- package/dist/src/planner/cost/index.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +38 -4
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/characteristics.js +50 -6
- package/dist/src/planner/framework/characteristics.js.map +1 -1
- package/dist/src/planner/framework/pass.d.ts.map +1 -1
- package/dist/src/planner/framework/pass.js +2 -1
- package/dist/src/planner/framework/pass.js.map +1 -1
- package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
- package/dist/src/planner/framework/physical-utils.js +7 -1
- package/dist/src/planner/framework/physical-utils.js.map +1 -1
- package/dist/src/planner/framework/registry.d.ts +39 -1
- package/dist/src/planner/framework/registry.d.ts.map +1 -1
- package/dist/src/planner/framework/registry.js +18 -2
- package/dist/src/planner/framework/registry.js.map +1 -1
- package/dist/src/planner/mutation/backward-body.d.ts +131 -0
- package/dist/src/planner/mutation/backward-body.d.ts.map +1 -0
- package/dist/src/planner/mutation/backward-body.js +135 -0
- package/dist/src/planner/mutation/backward-body.js.map +1 -0
- package/dist/src/planner/mutation/cte-flatten.d.ts +17 -0
- package/dist/src/planner/mutation/cte-flatten.d.ts.map +1 -0
- package/dist/src/planner/mutation/cte-flatten.js +364 -0
- package/dist/src/planner/mutation/cte-flatten.js.map +1 -0
- package/dist/src/planner/mutation/decomposition.d.ts +273 -0
- package/dist/src/planner/mutation/decomposition.d.ts.map +1 -0
- package/dist/src/planner/mutation/decomposition.js +1719 -0
- package/dist/src/planner/mutation/decomposition.js.map +1 -0
- package/dist/src/planner/mutation/lens-enforcement.d.ts +165 -0
- package/dist/src/planner/mutation/lens-enforcement.d.ts.map +1 -0
- package/dist/src/planner/mutation/lens-enforcement.js +745 -0
- package/dist/src/planner/mutation/lens-enforcement.js.map +1 -0
- package/dist/src/planner/mutation/multi-source.d.ts +568 -0
- package/dist/src/planner/mutation/multi-source.d.ts.map +1 -0
- package/dist/src/planner/mutation/multi-source.js +2915 -0
- package/dist/src/planner/mutation/multi-source.js.map +1 -0
- package/dist/src/planner/mutation/mutation-diagnostic.d.ts +37 -0
- package/dist/src/planner/mutation/mutation-diagnostic.d.ts.map +1 -0
- package/dist/src/planner/mutation/mutation-diagnostic.js +24 -0
- package/dist/src/planner/mutation/mutation-diagnostic.js.map +1 -0
- package/dist/src/planner/mutation/mutation-tags.d.ts +33 -0
- package/dist/src/planner/mutation/mutation-tags.d.ts.map +1 -0
- package/dist/src/planner/mutation/mutation-tags.js +31 -0
- package/dist/src/planner/mutation/mutation-tags.js.map +1 -0
- package/dist/src/planner/mutation/propagate.d.ts +97 -0
- package/dist/src/planner/mutation/propagate.d.ts.map +1 -0
- package/dist/src/planner/mutation/propagate.js +220 -0
- package/dist/src/planner/mutation/propagate.js.map +1 -0
- package/dist/src/planner/mutation/scope-transform.d.ts +181 -0
- package/dist/src/planner/mutation/scope-transform.d.ts.map +1 -0
- package/dist/src/planner/mutation/scope-transform.js +574 -0
- package/dist/src/planner/mutation/scope-transform.js.map +1 -0
- package/dist/src/planner/mutation/set-op.d.ts +242 -0
- package/dist/src/planner/mutation/set-op.d.ts.map +1 -0
- package/dist/src/planner/mutation/set-op.js +1687 -0
- package/dist/src/planner/mutation/set-op.js.map +1 -0
- package/dist/src/planner/mutation/single-source.d.ts +261 -0
- package/dist/src/planner/mutation/single-source.d.ts.map +1 -0
- package/dist/src/planner/mutation/single-source.js +1096 -0
- package/dist/src/planner/mutation/single-source.js.map +1 -0
- package/dist/src/planner/nodes/aggregate-node.d.ts +6 -4
- package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.js +11 -9
- 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 +5 -1
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/alter-table-node.d.ts +124 -1
- package/dist/src/planner/nodes/alter-table-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/alter-table-node.js +27 -0
- package/dist/src/planner/nodes/alter-table-node.js.map +1 -1
- package/dist/src/planner/nodes/analyze-node.d.ts +2 -1
- package/dist/src/planner/nodes/analyze-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/analyze-node.js +21 -1
- package/dist/src/planner/nodes/analyze-node.js.map +1 -1
- package/dist/src/planner/nodes/asserted-keys-node.d.ts +43 -0
- package/dist/src/planner/nodes/asserted-keys-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/asserted-keys-node.js +99 -0
- package/dist/src/planner/nodes/asserted-keys-node.js.map +1 -0
- package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/async-gather-node.js +33 -8
- package/dist/src/planner/nodes/async-gather-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 +2 -1
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
- package/dist/src/planner/nodes/create-view-node.d.ts +7 -2
- package/dist/src/planner/nodes/create-view-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/create-view-node.js +4 -1
- package/dist/src/planner/nodes/create-view-node.js.map +1 -1
- package/dist/src/planner/nodes/declarative-schema.d.ts +13 -1
- package/dist/src/planner/nodes/declarative-schema.d.ts.map +1 -1
- package/dist/src/planner/nodes/declarative-schema.js +32 -0
- package/dist/src/planner/nodes/declarative-schema.js.map +1 -1
- package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/distinct-node.js +2 -0
- package/dist/src/planner/nodes/distinct-node.js.map +1 -1
- package/dist/src/planner/nodes/dml-executor-node.d.ts +29 -1
- package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/dml-executor-node.js +27 -3
- package/dist/src/planner/nodes/dml-executor-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 -0
- package/dist/src/planner/nodes/eager-prefetch-node.js.map +1 -1
- package/dist/src/planner/nodes/envelope-scan-node.d.ts +42 -0
- package/dist/src/planner/nodes/envelope-scan-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/envelope-scan-node.js +62 -0
- package/dist/src/planner/nodes/envelope-scan-node.js.map +1 -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 +11 -1
- 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 +63 -13
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.js +6 -16
- package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts +41 -1
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +78 -8
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +33 -6
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +131 -10
- package/dist/src/planner/nodes/join-utils.js.map +1 -1
- package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts +104 -0
- package/dist/src/planner/nodes/lens-auxiliary-access-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/lens-auxiliary-access-node.js +91 -0
- package/dist/src/planner/nodes/lens-auxiliary-access-node.js.map +1 -0
- package/dist/src/planner/nodes/limit-offset.d.ts +12 -0
- package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
- package/dist/src/planner/nodes/limit-offset.js +52 -3
- package/dist/src/planner/nodes/limit-offset.js.map +1 -1
- package/dist/src/planner/nodes/materialized-view-nodes.d.ts +69 -0
- package/dist/src/planner/nodes/materialized-view-nodes.d.ts.map +1 -0
- package/dist/src/planner/nodes/materialized-view-nodes.js +111 -0
- package/dist/src/planner/nodes/materialized-view-nodes.js.map +1 -0
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +2 -1
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.js +2 -0
- package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts +9 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +9 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +265 -5
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/pragma.d.ts +2 -1
- package/dist/src/planner/nodes/pragma.d.ts.map +1 -1
- package/dist/src/planner/nodes/pragma.js +12 -0
- package/dist/src/planner/nodes/pragma.js.map +1 -1
- package/dist/src/planner/nodes/project-node.d.ts +14 -1
- package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +103 -16
- 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 +63 -30
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.js +7 -0
- 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 +10 -3
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts +20 -0
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +71 -14
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/set-object-tags-node.d.ts +39 -0
- package/dist/src/planner/nodes/set-object-tags-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/set-object-tags-node.js +41 -0
- package/dist/src/planner/nodes/set-object-tags-node.js.map +1 -0
- package/dist/src/planner/nodes/set-operation-node.d.ts +123 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.js +302 -18
- package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
- package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
- package/dist/src/planner/nodes/single-row.js +3 -0
- package/dist/src/planner/nodes/single-row.js.map +1 -1
- package/dist/src/planner/nodes/sort.d.ts.map +1 -1
- package/dist/src/planner/nodes/sort.js +8 -7
- package/dist/src/planner/nodes/sort.js.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.js +8 -23
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/subquery.d.ts +2 -0
- package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
- package/dist/src/planner/nodes/subquery.js +18 -2
- package/dist/src/planner/nodes/subquery.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +23 -3
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/nodes/table-function-call.js +6 -0
- package/dist/src/planner/nodes/table-function-call.js.map +1 -1
- package/dist/src/planner/nodes/values-node.d.ts +3 -1
- package/dist/src/planner/nodes/values-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/values-node.js +26 -0
- package/dist/src/planner/nodes/values-node.js.map +1 -1
- package/dist/src/planner/nodes/view-mutation-node.d.ts +259 -0
- package/dist/src/planner/nodes/view-mutation-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/view-mutation-node.js +273 -0
- package/dist/src/planner/nodes/view-mutation-node.js.map +1 -0
- package/dist/src/planner/nodes/window-function.d.ts +17 -1
- package/dist/src/planner/nodes/window-function.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-function.js +15 -1
- package/dist/src/planner/nodes/window-function.js.map +1 -1
- package/dist/src/planner/nodes/window-node.js +3 -3
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +372 -39
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/planning-context.d.ts +1 -1
- package/dist/src/planner/planning-context.d.ts.map +1 -1
- package/dist/src/planner/rules/access/lens-access-form-matcher.d.ts +70 -0
- package/dist/src/planner/rules/access/lens-access-form-matcher.d.ts.map +1 -0
- package/dist/src/planner/rules/access/lens-access-form-matcher.js +156 -0
- package/dist/src/planner/rules/access/lens-access-form-matcher.js.map +1 -0
- package/dist/src/planner/rules/access/rule-lens-auxiliary-access.d.ts +31 -0
- package/dist/src/planner/rules/access/rule-lens-auxiliary-access.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-lens-auxiliary-access.js +176 -0
- package/dist/src/planner/rules/access/rule-lens-auxiliary-access.js.map +1 -0
- 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 +435 -37
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +8 -27
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +9 -3
- 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 +56 -5
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts +39 -0
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts.map +1 -0
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js +616 -0
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js.map +1 -0
- package/dist/src/planner/rules/cache/rule-scalar-cse.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-scalar-cse.js +8 -1
- package/dist/src/planner/rules/cache/rule-scalar-cse.js.map +1 -1
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +8 -7
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -1
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +14 -21
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts +36 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.js +42 -5
- package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -1
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +10 -0
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.js.map +1 -1
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +25 -9
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -1
- package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.d.ts +130 -0
- package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.js +206 -0
- package/dist/src/planner/rules/join/rule-inner-join-existence-recovery.js.map +1 -0
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts +67 -14
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-elimination.js +81 -25
- package/dist/src/planner/rules/join/rule-join-elimination.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-existence-pruning.d.ts +84 -0
- package/dist/src/planner/rules/join/rule-join-existence-pruning.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-join-existence-pruning.js +138 -0
- package/dist/src/planner/rules/join/rule-join-existence-pruning.js.map +1 -0
- package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-greedy-commute.js +19 -1
- package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
- 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 +14 -2
- package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.js +5 -2
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.js.map +1 -1
- 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 +4 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -1
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.js +10 -0
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.js.map +1 -1
- package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.d.ts +286 -0
- package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.js +548 -0
- package/dist/src/planner/rules/join/rule-semijoin-existence-recovery.js.map +1 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts.map +1 -1
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js +9 -1
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js.map +1 -1
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts.map +1 -1
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js +7 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js.map +1 -1
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts.map +1 -1
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js +10 -1
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js.map +1 -1
- 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 +10 -1
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +18 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +7 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -1
- 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 +9 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js +13 -3
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +2 -2
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-projection-pruning.d.ts.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-projection-pruning.js +14 -0
- package/dist/src/planner/rules/retrieve/rule-projection-pruning.js.map +1 -1
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +16 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -1
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +47 -4
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -1
- 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 +8 -0
- 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.map +1 -1
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +7 -0
- 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 +12 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/planner/rules/window/rule-monotonic-window.js +1 -1
- package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -1
- package/dist/src/planner/type-utils.d.ts +14 -0
- package/dist/src/planner/type-utils.d.ts.map +1 -1
- package/dist/src/planner/type-utils.js +66 -21
- package/dist/src/planner/type-utils.js.map +1 -1
- package/dist/src/planner/util/fd-utils.d.ts +228 -36
- package/dist/src/planner/util/fd-utils.d.ts.map +1 -1
- package/dist/src/planner/util/fd-utils.js +501 -84
- package/dist/src/planner/util/fd-utils.js.map +1 -1
- package/dist/src/planner/util/ind-utils.d.ts +27 -1
- package/dist/src/planner/util/ind-utils.d.ts.map +1 -1
- package/dist/src/planner/util/ind-utils.js +80 -6
- package/dist/src/planner/util/ind-utils.js.map +1 -1
- package/dist/src/planner/util/key-utils.d.ts +26 -3
- package/dist/src/planner/util/key-utils.d.ts.map +1 -1
- package/dist/src/planner/util/key-utils.js +182 -33
- package/dist/src/planner/util/key-utils.js.map +1 -1
- package/dist/src/planner/util/set-op-wrapper.d.ts +37 -0
- package/dist/src/planner/util/set-op-wrapper.d.ts.map +1 -0
- package/dist/src/planner/util/set-op-wrapper.js +82 -0
- package/dist/src/planner/util/set-op-wrapper.js.map +1 -0
- package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
- package/dist/src/planner/validation/plan-validator.js +1 -0
- package/dist/src/planner/validation/plan-validator.js.map +1 -1
- package/dist/src/runtime/context-helpers.d.ts +13 -1
- package/dist/src/runtime/context-helpers.d.ts.map +1 -1
- package/dist/src/runtime/context-helpers.js +7 -1
- package/dist/src/runtime/context-helpers.js.map +1 -1
- package/dist/src/runtime/delta-executor.d.ts +30 -1
- package/dist/src/runtime/delta-executor.d.ts.map +1 -1
- package/dist/src/runtime/delta-executor.js +38 -4
- package/dist/src/runtime/delta-executor.js.map +1 -1
- package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -1
- package/dist/src/runtime/emit/add-constraint.js +38 -5
- 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 +10 -8
- package/dist/src/runtime/emit/aggregate.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +664 -108
- 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 +2 -1
- package/dist/src/runtime/emit/analyze.js.map +1 -1
- package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/asof-scan.js +24 -9
- package/dist/src/runtime/emit/asof-scan.js.map +1 -1
- package/dist/src/runtime/emit/asserted-keys.d.ts +13 -0
- package/dist/src/runtime/emit/asserted-keys.d.ts.map +1 -0
- package/dist/src/runtime/emit/asserted-keys.js +13 -0
- package/dist/src/runtime/emit/asserted-keys.js.map +1 -0
- package/dist/src/runtime/emit/between.d.ts.map +1 -1
- package/dist/src/runtime/emit/between.js +24 -19
- package/dist/src/runtime/emit/between.js.map +1 -1
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +24 -36
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/block.d.ts.map +1 -1
- package/dist/src/runtime/emit/block.js +11 -2
- package/dist/src/runtime/emit/block.js.map +1 -1
- package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
- package/dist/src/runtime/emit/bloom-join.js +12 -4
- package/dist/src/runtime/emit/bloom-join.js.map +1 -1
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +50 -1
- package/dist/src/runtime/emit/constraint-check.js.map +1 -1
- package/dist/src/runtime/emit/create-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-table.js +8 -0
- package/dist/src/runtime/emit/create-table.js.map +1 -1
- package/dist/src/runtime/emit/create-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-view.js +16 -1
- package/dist/src/runtime/emit/create-view.js.map +1 -1
- package/dist/src/runtime/emit/delete.d.ts.map +1 -1
- package/dist/src/runtime/emit/delete.js +15 -5
- package/dist/src/runtime/emit/delete.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts +27 -0
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +413 -193
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/drop-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-table.js +10 -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 +17 -0
- package/dist/src/runtime/emit/drop-view.js.map +1 -1
- package/dist/src/runtime/emit/envelope-scan.d.ts +13 -0
- package/dist/src/runtime/emit/envelope-scan.d.ts.map +1 -0
- package/dist/src/runtime/emit/envelope-scan.js +22 -0
- package/dist/src/runtime/emit/envelope-scan.js.map +1 -0
- package/dist/src/runtime/emit/join.d.ts +10 -2
- package/dist/src/runtime/emit/join.d.ts.map +1 -1
- package/dist/src/runtime/emit/join.js +128 -38
- package/dist/src/runtime/emit/join.js.map +1 -1
- package/dist/src/runtime/emit/lens-auxiliary-access.d.ts +16 -0
- package/dist/src/runtime/emit/lens-auxiliary-access.d.ts.map +1 -0
- package/dist/src/runtime/emit/lens-auxiliary-access.js +16 -0
- package/dist/src/runtime/emit/lens-auxiliary-access.js.map +1 -0
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts +640 -0
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -0
- package/dist/src/runtime/emit/materialized-view-helpers.js +2576 -0
- package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -0
- package/dist/src/runtime/emit/materialized-view.d.ts +31 -0
- package/dist/src/runtime/emit/materialized-view.d.ts.map +1 -0
- package/dist/src/runtime/emit/materialized-view.js +187 -0
- package/dist/src/runtime/emit/materialized-view.js.map +1 -0
- package/dist/src/runtime/emit/merge-join.d.ts.map +1 -1
- package/dist/src/runtime/emit/merge-join.js +19 -5
- package/dist/src/runtime/emit/merge-join.js.map +1 -1
- package/dist/src/runtime/emit/project.d.ts.map +1 -1
- package/dist/src/runtime/emit/project.js +10 -5
- package/dist/src/runtime/emit/project.js.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.d.ts +1 -0
- package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.js +101 -5
- package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
- package/dist/src/runtime/emit/set-object-tags.d.ts +16 -0
- package/dist/src/runtime/emit/set-object-tags.d.ts.map +1 -0
- package/dist/src/runtime/emit/set-object-tags.js +57 -0
- package/dist/src/runtime/emit/set-object-tags.js.map +1 -0
- package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
- package/dist/src/runtime/emit/set-operation.js +140 -24
- package/dist/src/runtime/emit/set-operation.js.map +1 -1
- package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
- package/dist/src/runtime/emit/subquery.js +110 -5
- package/dist/src/runtime/emit/subquery.js.map +1 -1
- package/dist/src/runtime/emit/unary.d.ts.map +1 -1
- package/dist/src/runtime/emit/unary.js +34 -6
- package/dist/src/runtime/emit/unary.js.map +1 -1
- package/dist/src/runtime/emit/view-mutation.d.ts +70 -0
- package/dist/src/runtime/emit/view-mutation.d.ts.map +1 -0
- package/dist/src/runtime/emit/view-mutation.js +299 -0
- package/dist/src/runtime/emit/view-mutation.js.map +1 -0
- package/dist/src/runtime/emit/window.js +29 -5
- package/dist/src/runtime/emit/window.js.map +1 -1
- package/dist/src/runtime/foreign-key-actions.d.ts +66 -3
- package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
- package/dist/src/runtime/foreign-key-actions.js +580 -172
- package/dist/src/runtime/foreign-key-actions.js.map +1 -1
- package/dist/src/runtime/parallel-driver.d.ts +4 -1
- package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
- package/dist/src/runtime/parallel-driver.js +5 -1
- package/dist/src/runtime/parallel-driver.js.map +1 -1
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +17 -1
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/runtime/types.d.ts +10 -0
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/schema/basis-backfill.d.ts +63 -0
- package/dist/src/schema/basis-backfill.d.ts.map +1 -0
- package/dist/src/schema/basis-backfill.js +161 -0
- package/dist/src/schema/basis-backfill.js.map +1 -0
- package/dist/src/schema/catalog.d.ts +115 -1
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +249 -22
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/change-events.d.ts +42 -1
- package/dist/src/schema/change-events.d.ts.map +1 -1
- package/dist/src/schema/change-events.js.map +1 -1
- package/dist/src/schema/column.d.ts +16 -0
- 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 +182 -0
- package/dist/src/schema/constraint-builder.d.ts.map +1 -0
- package/dist/src/schema/constraint-builder.js +424 -0
- package/dist/src/schema/constraint-builder.js.map +1 -0
- package/dist/src/schema/ddl-generator.d.ts +86 -1
- package/dist/src/schema/ddl-generator.d.ts.map +1 -1
- package/dist/src/schema/ddl-generator.js +316 -20
- package/dist/src/schema/ddl-generator.js.map +1 -1
- package/dist/src/schema/declared-schema-manager.d.ts +51 -0
- package/dist/src/schema/declared-schema-manager.d.ts.map +1 -1
- package/dist/src/schema/declared-schema-manager.js +61 -0
- package/dist/src/schema/declared-schema-manager.js.map +1 -1
- package/dist/src/schema/derivation.d.ts +106 -0
- package/dist/src/schema/derivation.d.ts.map +1 -0
- package/dist/src/schema/derivation.js +25 -0
- package/dist/src/schema/derivation.js.map +1 -0
- package/dist/src/schema/function.d.ts +13 -0
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/lens-ack.d.ts +90 -0
- package/dist/src/schema/lens-ack.d.ts.map +1 -0
- package/dist/src/schema/lens-ack.js +361 -0
- package/dist/src/schema/lens-ack.js.map +1 -0
- package/dist/src/schema/lens-compiler.d.ts +62 -0
- package/dist/src/schema/lens-compiler.d.ts.map +1 -0
- package/dist/src/schema/lens-compiler.js +1594 -0
- package/dist/src/schema/lens-compiler.js.map +1 -0
- package/dist/src/schema/lens-fk-discovery.d.ts +175 -0
- package/dist/src/schema/lens-fk-discovery.d.ts.map +1 -0
- package/dist/src/schema/lens-fk-discovery.js +336 -0
- package/dist/src/schema/lens-fk-discovery.js.map +1 -0
- package/dist/src/schema/lens-prover.d.ts +336 -0
- package/dist/src/schema/lens-prover.d.ts.map +1 -0
- package/dist/src/schema/lens-prover.js +1988 -0
- package/dist/src/schema/lens-prover.js.map +1 -0
- package/dist/src/schema/lens.d.ts +254 -0
- package/dist/src/schema/lens.d.ts.map +1 -0
- package/dist/src/schema/lens.js +21 -0
- package/dist/src/schema/lens.js.map +1 -0
- package/dist/src/schema/manager.d.ts +676 -18
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +1573 -238
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/mapping-advertisement-tags.d.ts +39 -0
- package/dist/src/schema/mapping-advertisement-tags.d.ts.map +1 -0
- package/dist/src/schema/mapping-advertisement-tags.js +216 -0
- package/dist/src/schema/mapping-advertisement-tags.js.map +1 -0
- package/dist/src/schema/rename-rewriter.d.ts +45 -4
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
- package/dist/src/schema/rename-rewriter.js +412 -19
- package/dist/src/schema/rename-rewriter.js.map +1 -1
- package/dist/src/schema/reserved-tags-policy.d.ts +32 -0
- package/dist/src/schema/reserved-tags-policy.d.ts.map +1 -0
- package/dist/src/schema/reserved-tags-policy.js +34 -0
- package/dist/src/schema/reserved-tags-policy.js.map +1 -0
- package/dist/src/schema/reserved-tags.d.ts +170 -0
- package/dist/src/schema/reserved-tags.d.ts.map +1 -0
- package/dist/src/schema/reserved-tags.js +507 -0
- package/dist/src/schema/reserved-tags.js.map +1 -0
- package/dist/src/schema/schema-differ.d.ts +158 -2
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +1460 -78
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/schema/schema-hasher.d.ts +8 -3
- package/dist/src/schema/schema-hasher.d.ts.map +1 -1
- package/dist/src/schema/schema-hasher.js +22 -2
- package/dist/src/schema/schema-hasher.js.map +1 -1
- package/dist/src/schema/schema.d.ts +25 -1
- package/dist/src/schema/schema.d.ts.map +1 -1
- package/dist/src/schema/schema.js +36 -2
- package/dist/src/schema/schema.js.map +1 -1
- package/dist/src/schema/table.d.ts +259 -10
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +309 -26
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/schema/unique-enforcement.d.ts +78 -0
- package/dist/src/schema/unique-enforcement.d.ts.map +1 -0
- package/dist/src/schema/unique-enforcement.js +93 -0
- package/dist/src/schema/unique-enforcement.js.map +1 -0
- package/dist/src/schema/view.d.ts +83 -2
- package/dist/src/schema/view.d.ts.map +1 -1
- package/dist/src/schema/view.js +67 -1
- package/dist/src/schema/view.js.map +1 -1
- package/dist/src/schema/window-function.d.ts +9 -1
- package/dist/src/schema/window-function.d.ts.map +1 -1
- package/dist/src/schema/window-function.js.map +1 -1
- package/dist/src/types/temporal-types.d.ts.map +1 -1
- package/dist/src/types/temporal-types.js +71 -36
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/util/comparison.d.ts +24 -0
- package/dist/src/util/comparison.d.ts.map +1 -1
- package/dist/src/util/comparison.js +34 -0
- package/dist/src/util/comparison.js.map +1 -1
- package/dist/src/util/mutation-statement.d.ts.map +1 -1
- package/dist/src/util/mutation-statement.js +4 -1
- package/dist/src/util/mutation-statement.js.map +1 -1
- package/dist/src/util/serialization.d.ts +9 -0
- package/dist/src/util/serialization.d.ts.map +1 -1
- package/dist/src/util/serialization.js +26 -0
- package/dist/src/util/serialization.js.map +1 -1
- package/dist/src/vtab/backing-host.d.ts +286 -0
- package/dist/src/vtab/backing-host.d.ts.map +1 -0
- package/dist/src/vtab/backing-host.js +118 -0
- package/dist/src/vtab/backing-host.js.map +1 -0
- package/dist/src/vtab/best-access-plan.d.ts +21 -0
- package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
- package/dist/src/vtab/best-access-plan.js.map +1 -1
- package/dist/src/vtab/capabilities.d.ts +5 -5
- package/dist/src/vtab/capabilities.d.ts.map +1 -1
- package/dist/src/vtab/mapping-advertisement.d.ts +163 -0
- package/dist/src/vtab/mapping-advertisement.d.ts.map +1 -0
- package/dist/src/vtab/mapping-advertisement.js +2 -0
- package/dist/src/vtab/mapping-advertisement.js.map +1 -0
- package/dist/src/vtab/memory/index.d.ts +64 -4
- package/dist/src/vtab/memory/index.d.ts.map +1 -1
- package/dist/src/vtab/memory/index.js +119 -12
- package/dist/src/vtab/memory/index.js.map +1 -1
- package/dist/src/vtab/memory/layer/base.d.ts +38 -1
- package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/base.js +112 -24
- package/dist/src/vtab/memory/layer/base.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +291 -4
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +1050 -91
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/plan-filter.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/plan-filter.js +35 -6
- package/dist/src/vtab/memory/layer/plan-filter.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 +66 -14
- package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
- package/dist/src/vtab/memory/layer/scan-plan.d.ts +14 -0
- package/dist/src/vtab/memory/layer/scan-plan.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/scan-plan.js +27 -4
- package/dist/src/vtab/memory/layer/scan-plan.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +5 -1
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +17 -0
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +82 -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 +15 -5
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/memory/types.d.ts +20 -2
- package/dist/src/vtab/memory/types.d.ts.map +1 -1
- package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
- package/dist/src/vtab/memory/utils/predicate.js +46 -24
- package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
- package/dist/src/vtab/memory/utils/primary-key-encode.d.ts +31 -0
- package/dist/src/vtab/memory/utils/primary-key-encode.d.ts.map +1 -0
- package/dist/src/vtab/memory/utils/primary-key-encode.js +101 -0
- package/dist/src/vtab/memory/utils/primary-key-encode.js.map +1 -0
- package/dist/src/vtab/memory/utils/primary-key.d.ts +8 -0
- package/dist/src/vtab/memory/utils/primary-key.d.ts.map +1 -1
- package/dist/src/vtab/memory/utils/primary-key.js +12 -5
- package/dist/src/vtab/memory/utils/primary-key.js.map +1 -1
- package/dist/src/vtab/module.d.ts +203 -4
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/dist/src/vtab/table.d.ts +9 -0
- package/dist/src/vtab/table.d.ts.map +1 -1
- package/dist/src/vtab/table.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
import { RowOpFlag } from '../../schema/table.js';
|
|
2
|
+
import { resolveSlotBasisSource, collectColumnRefNames, authoredForwardMap } from '../../schema/lens-prover.js';
|
|
3
|
+
import { logicalToBasisColumnMap, resolveLogicalReferencedColumns, mappedFkBasisPairs, matchingBasisFks, findLogicalParentFkRefs, } from '../../schema/lens-fk-discovery.js';
|
|
4
|
+
import { transformScopedExpr, transformExpr } from './scope-transform.js';
|
|
5
|
+
import { raiseMutationDiagnostic } from './mutation-diagnostic.js';
|
|
6
|
+
import { synthesizeFKExistsExpr, synthesizeFKNotExistsExpr } from '../building/foreign-key-builder.js';
|
|
7
|
+
import { createLogger } from '../../common/logger.js';
|
|
8
|
+
const log = createLogger('planner:lens-enforcement');
|
|
9
|
+
/**
|
|
10
|
+
* Lens row-local constraint enforcement (the write side of the lens prover's
|
|
11
|
+
* `enforced-row-local` obligation class — `docs/lens.md` § Constraint Attachment).
|
|
12
|
+
*
|
|
13
|
+
* The prover (`schema/lens-prover.ts`) classifies every logical constraint into a
|
|
14
|
+
* {@link import('../../schema/lens-prover.js').ConstraintObligation} on
|
|
15
|
+
* `LensSlot.obligations`. A scalar `check` over non-computed (reconstructible)
|
|
16
|
+
* columns is `enforced-row-local`: it is evaluable on the projected row being
|
|
17
|
+
* written, so a non-materialized lens enforces it for free at the write boundary.
|
|
18
|
+
*
|
|
19
|
+
* The view-mutation substrate re-plans a lens write against the **basis table by
|
|
20
|
+
* name** (`mutation/single-source.ts`), which drops the logical context. This
|
|
21
|
+
* module re-attaches it: it rewrites each row-local logical CHECK from
|
|
22
|
+
* logical-column terms into basis-column terms (using the slot's reconstructible
|
|
23
|
+
* projection — the same logical→basis mapping the prover proves over) and hands
|
|
24
|
+
* the result to the base-table builder, which merges them into the per-row
|
|
25
|
+
* `ConstraintCheckNode` exactly as if the basis table had declared them. The
|
|
26
|
+
* effect: a logical CHECK fires at the lens write even when the basis carries no
|
|
27
|
+
* such check.
|
|
28
|
+
*
|
|
29
|
+
* The `enforced-fk` obligation is also handled here (see
|
|
30
|
+
* {@link collectLensForeignKeyConstraints}): each logical FK becomes a deferred,
|
|
31
|
+
* basis-term `EXISTS` existence check against the schema-qualified logical parent,
|
|
32
|
+
* routed through the same constraint pipeline. Because the synthesized check
|
|
33
|
+
* contains an `EXISTS`, the pipeline auto-defers it to commit — matching physical
|
|
34
|
+
* child-side FK timing.
|
|
35
|
+
*
|
|
36
|
+
* The `enforced-set-level` obligation with `mode: 'commit-time'` (a logical
|
|
37
|
+
* `unique` / primary key with no basis covering structure) is the third class
|
|
38
|
+
* handled here (see {@link collectLensSetLevelConstraints}): each becomes a
|
|
39
|
+
* deferred `(select count(*) from <logicalView> as _u where _u.lk = NEW.bk …) <= 1`
|
|
40
|
+
* CHECK over the logical key columns (logical names inside the subquery, basis
|
|
41
|
+
* names on the `NEW.*` side). Because it contains a scalar subquery the pipeline
|
|
42
|
+
* auto-defers it to commit, where the logical view reflects the post-mutation
|
|
43
|
+
* basis: a unique key sees count `1` (itself) and a duplicate count `≥ 2` ⇒ ABORT.
|
|
44
|
+
* Detection-only (no covering structure ⇒ O(n) per changed row). The row-time
|
|
45
|
+
* variant (`enforced-set-level` `mode: 'row-time'`, which unlocks conflict
|
|
46
|
+
* resolution) is **delivered without any code here**: by the prover's own
|
|
47
|
+
* precondition a row-time obligation is backed by a matching **basis `UNIQUE` +
|
|
48
|
+
* non-stale row-time covering MV**, and the single-source spine re-plans the lens
|
|
49
|
+
* write to that basis table (in basis terms), so the basis UC's physical
|
|
50
|
+
* enforcement-through-covering-MV path (`vtab/memory/layer/manager.ts`
|
|
51
|
+
* `checkUniqueViaMaterializedView`) fires for free — an O(log n) existence lookup
|
|
52
|
+
* that honors `ABORT` / `IGNORE` / `REPLACE`. That is why this collector emits
|
|
53
|
+
* nothing for row-time. `proved` / `vacuous` need no enforcement.
|
|
54
|
+
*/
|
|
55
|
+
/** Marker tag stamped on a routed basis-term constraint so its lens origin is visible. */
|
|
56
|
+
export const LENS_BOUNDARY_ATTACHED_TAG = 'quereus.lens.boundary.attached';
|
|
57
|
+
/**
|
|
58
|
+
* The {@link ScopeContext} for the logical→basis row-local CHECK rewrite — the
|
|
59
|
+
* scope-aware dual of the single-source view-column descent ({@link import('./single-source.js').makeViewScope}).
|
|
60
|
+
* It rewrites a **correlated write-row** logical column to its bare basis spelling
|
|
61
|
+
* while leaving a **subquery-local** ref (one a nested FROM introduces) untouched, so
|
|
62
|
+
* a CHECK whose subquery correlates a write-row column with a logical≠basis name spells
|
|
63
|
+
* that ref in basis terms at the constraint-build boundary instead of crashing on a
|
|
64
|
+
* column the basis write row does not carry (`docs/lens.md` § Constraint Attachment).
|
|
65
|
+
* The descent itself owns shadow accumulation / taint propagation; this object decides
|
|
66
|
+
* per column:
|
|
67
|
+
*
|
|
68
|
+
* - **Qualified by the logical table name** and mapped ⇒ a qualified write-row ref ⇒
|
|
69
|
+
* replace with the basis column qualified `NEW.<basis>` (the write-row correlation name).
|
|
70
|
+
* Any other qualifier (`Allowed.name`, a subquery FROM source) ⇒ left untouched — it
|
|
71
|
+
* resolves against the subquery FROM. This is the negative-case guard against
|
|
72
|
+
* over-rewriting a foreign ref whose name happens to equal a logical column.
|
|
73
|
+
* - **Bare**, shadowed by a (this-or-enclosing) subquery FROM ⇒ left untouched
|
|
74
|
+
* (subquery-local); else, name maps ⇒ replace with `NEW.<basis>` (a correlated
|
|
75
|
+
* write-row ref); else ⇒ left untouched.
|
|
76
|
+
*
|
|
77
|
+
* The replacement is qualified `NEW.<basis>` rather than left bare so a ref emitted
|
|
78
|
+
* inside a correlated subquery cannot be captured by a same-named column the subquery's
|
|
79
|
+
* own FROM introduces (the lens analogue of the single-source descent's
|
|
80
|
+
* {@link import('./single-source.js').makeBaseQualifier}); see {@link makeLensRewriteScope}'s
|
|
81
|
+
* `resolve`. At the top level it resolves to the write row identically to a bare ref.
|
|
82
|
+
*
|
|
83
|
+
* The old top-level behavior — strip the qualifier of an *unmapped* qualified column — is
|
|
84
|
+
* intentionally dropped: the prover errors at deploy on a CHECK over a non-reconstructible
|
|
85
|
+
* column, so every referenced logical column maps cleanly, and a top-level CHECK qualifier
|
|
86
|
+
* can only name the logical table (a CHECK reaches other tables only via a subquery).
|
|
87
|
+
*
|
|
88
|
+
* `unresolvableScope: 'taint'` (mirroring the view-column descent): when a subquery's FROM
|
|
89
|
+
* columns are not statically resolvable (`select *` / TVF / CTE), a bare logical-column-named
|
|
90
|
+
* ref inside it cannot be proven correlated — reject it from the tainted scope with a clear
|
|
91
|
+
* diagnostic rather than mis-rewrite or fall through to a cryptic build crash. A foreign /
|
|
92
|
+
* qualified ref in a tainted scope is still left untouched (its name is not a logical column).
|
|
93
|
+
*/
|
|
94
|
+
function makeLensRewriteScope(map, forwards, logicalTableName) {
|
|
95
|
+
const lcTable = logicalTableName.toLowerCase();
|
|
96
|
+
// A rewritten write-row ref is qualified `NEW.<basis>` — the write-row correlation
|
|
97
|
+
// name the constraint scope registers (`building/constraint-builder.ts` registers
|
|
98
|
+
// `new.<col>` for every basis column on an INSERT/UPDATE check; row-local lens
|
|
99
|
+
// checks are INSERT|UPDATE only). The qualifier is load-bearing for a ref emitted
|
|
100
|
+
// INSIDE a correlated subquery: a *bare* basis column there would re-bind to a
|
|
101
|
+
// same-named column the subquery's own FROM introduces (innermost SQL scoping)
|
|
102
|
+
// instead of the write row — silently changing the CHECK's meaning when a renamed
|
|
103
|
+
// logical column's basis spelling collides with a subquery-source column. This is
|
|
104
|
+
// the lens analogue of the single-source descent's `makeBaseQualifier` (which
|
|
105
|
+
// qualifies with the lowered target's alias for the same reason). At the top level
|
|
106
|
+
// `NEW.<basis>` resolves to the write row identically to the prior bare form, so the
|
|
107
|
+
// behavior is unchanged except in the collision corner. Mirrors the FK / set-level
|
|
108
|
+
// synthesizers, which likewise qualify their write-row side `NEW.*`.
|
|
109
|
+
//
|
|
110
|
+
// An **authored-inverse** column has no single basis spelling — substitute its
|
|
111
|
+
// forward `get` expression instead, every base ref `NEW.`-qualified for the same
|
|
112
|
+
// capture-safety reason, so the CHECK evaluates over the written basis row's
|
|
113
|
+
// logical image. `authoredForwardMap` admits only subquery-free forwards (whose
|
|
114
|
+
// refs are all basis columns of the single-source FROM), so the blanket
|
|
115
|
+
// re-qualification is total; the prover's CHECK realizability classifier accepts
|
|
116
|
+
// exactly that same set, keeping deploy and write-time in lockstep.
|
|
117
|
+
const resolve = (name) => {
|
|
118
|
+
const basisColumn = map.get(name);
|
|
119
|
+
if (basisColumn !== undefined)
|
|
120
|
+
return { type: 'column', name: basisColumn, table: 'NEW' };
|
|
121
|
+
const forward = forwards.get(name);
|
|
122
|
+
if (forward !== undefined) {
|
|
123
|
+
return transformExpr(forward, col => ({ type: 'column', name: col.name, table: 'NEW' }));
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
makeSubstitute: (shadowed, tainted) => (col) => {
|
|
129
|
+
const name = col.name.toLowerCase();
|
|
130
|
+
if (col.table) {
|
|
131
|
+
// Only a ref qualified by the logical table is a (qualified) write-row ref;
|
|
132
|
+
// any other qualifier resolves against the subquery FROM.
|
|
133
|
+
return col.table.toLowerCase() === lcTable ? resolve(name) : undefined;
|
|
134
|
+
}
|
|
135
|
+
if (shadowed.has(name))
|
|
136
|
+
return undefined;
|
|
137
|
+
if (!map.has(name) && !forwards.has(name))
|
|
138
|
+
return undefined;
|
|
139
|
+
if (tainted) {
|
|
140
|
+
raiseMutationDiagnostic({
|
|
141
|
+
reason: 'unsupported-subquery-correlation',
|
|
142
|
+
table: logicalTableName,
|
|
143
|
+
column: col.name,
|
|
144
|
+
message: `cannot enforce the logical CHECK on '${logicalTableName}': the reference '${col.name}' inside a subquery cannot be proven correlated to the write row because the subquery's source columns are not statically resolvable (a 'select *' / table-valued function / unresolved source); qualify the reference with the logical table, or restructure the CHECK`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return resolve(name);
|
|
148
|
+
},
|
|
149
|
+
unresolvableScope: 'taint',
|
|
150
|
+
rejectDmlSubquery: () => raiseMutationDiagnostic({
|
|
151
|
+
reason: 'unsupported-subquery-correlation',
|
|
152
|
+
table: logicalTableName,
|
|
153
|
+
message: `cannot enforce the logical CHECK on '${logicalTableName}': a data-modifying subquery (INSERT/UPDATE/DELETE) within it cannot be analysed for write-row correlation`,
|
|
154
|
+
}),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Rewrites a logical-column CHECK expression into basis-column terms, scope-aware:
|
|
159
|
+
* a top-level (or correlated) write-row logical column maps to its `NEW.<basis>` column,
|
|
160
|
+
* while a subquery-local column the nested FROM introduces is left untouched. Rides the
|
|
161
|
+
* shared {@link transformScopedExpr} descent over {@link makeLensRewriteScope}, entered at
|
|
162
|
+
* the outermost scope — so a top-level logical column still maps to the write row exactly as
|
|
163
|
+
* the prior top-level-only rewrite did, and a correlated write-row ref inside a subquery
|
|
164
|
+
* (e.g. `exists (select 1 from Allowed where Allowed.name = docKey)`, `docKey`→`doc_key`) is
|
|
165
|
+
* now also rewritten (to `NEW.doc_key`) rather than passing through verbatim and crashing at
|
|
166
|
+
* constraint build.
|
|
167
|
+
*/
|
|
168
|
+
function rewriteToBasisTerms(ctx, expr, map, forwards, logicalTableName) {
|
|
169
|
+
return transformScopedExpr(ctx, makeLensRewriteScope(map, forwards, logicalTableName), expr);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The lowercased **basis**-column names a row-local logical CHECK depends on — the
|
|
173
|
+
* prover-supplied metadata the per-op decomposition gate (`constraintsForOp` in
|
|
174
|
+
* `view-mutation-builder`) prefers over its own AST walk. Mirrors the prover's
|
|
175
|
+
* {@link import('../../schema/lens-prover.js').classifyCheckConstraint}: enumerate every
|
|
176
|
+
* `column` ref in the source CHECK (qualifier-stripped, via {@link collectColumnRefNames})
|
|
177
|
+
* and keep only those that map to a basis column — i.e. that are logical columns of *this*
|
|
178
|
+
* table. Two consequences make this exactly the right set:
|
|
179
|
+
*
|
|
180
|
+
* - a **correlated bare write-row ref** (`somecol`) that appears only *inside* a subquery
|
|
181
|
+
* IS a logical column ⇒ mapped ⇒ included. This is the ref the AST walker under-collects
|
|
182
|
+
* (it assumes a bare subquery-internal ref resolves against the subquery's own FROM), and
|
|
183
|
+
* the hardening this metadata exists to deliver;
|
|
184
|
+
* - a **foreign ref** (`peer.k`, whose name is not a logical column of this table) maps to
|
|
185
|
+
* nothing ⇒ excluded — correct, it resolves against the subquery FROM, not the write row.
|
|
186
|
+
*
|
|
187
|
+
* Over-collection is the safe direction: a subquery ref qualified to another table whose
|
|
188
|
+
* name happens to equal a logical column (`peer.title`) is qualifier-stripped here and
|
|
189
|
+
* falsely mapped, adding an extra basis name. That only ever makes the gate *defer* a
|
|
190
|
+
* constraint it might have threaded — conservative, the same bias the gate already carries.
|
|
191
|
+
* Deduped because a CHECK may reference a column more than once.
|
|
192
|
+
*
|
|
193
|
+
* An authored-inverse column contributes its forward `get` expression's basis
|
|
194
|
+
* refs (the columns the substituted CHECK actually reads on the write row).
|
|
195
|
+
*/
|
|
196
|
+
function rowLocalReferencedBasisColumns(expr, map, forwards) {
|
|
197
|
+
const cols = new Set();
|
|
198
|
+
for (const name of collectColumnRefNames(expr)) {
|
|
199
|
+
const basis = map.get(name.toLowerCase());
|
|
200
|
+
if (basis !== undefined) {
|
|
201
|
+
cols.add(basis.toLowerCase());
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const forward = forwards.get(name.toLowerCase());
|
|
205
|
+
if (forward !== undefined) {
|
|
206
|
+
for (const f of collectColumnRefNames(forward))
|
|
207
|
+
cols.add(f.toLowerCase());
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return [...cols];
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Builds the basis-term row-local CHECK constraints a lens write must enforce.
|
|
214
|
+
* Reads the slot's `enforced-row-local` obligations, rewrites each to basis terms,
|
|
215
|
+
* and tags it with {@link LENS_BOUNDARY_ATTACHED_TAG}. The result is merged into
|
|
216
|
+
* the basis INSERT/UPDATE's constraint-check pipeline by the base-table builder.
|
|
217
|
+
*
|
|
218
|
+
* Each constraint also carries {@link rowLocalReferencedBasisColumns} as
|
|
219
|
+
* `referencedWriteRowColumns` — prover-supplied metadata the per-op decomposition gate
|
|
220
|
+
* uses instead of an AST walk, so a subquery-bearing row-local CHECK (which the prover
|
|
221
|
+
* still classifies `enforced-row-local`) gates onto the member op that owns its correlated
|
|
222
|
+
* write-row column rather than crashing on a member that cannot resolve it.
|
|
223
|
+
*
|
|
224
|
+
* Returns `[]` when the slot is un-proved (`obligations` undefined) or carries no
|
|
225
|
+
* row-local checks — the common case, so a non-lens / check-free write pays nothing.
|
|
226
|
+
*/
|
|
227
|
+
export function collectLensRowLocalConstraints(ctx, slot) {
|
|
228
|
+
if (!slot.obligations || slot.obligations.length === 0)
|
|
229
|
+
return [];
|
|
230
|
+
const map = logicalToBasisColumnMap(slot);
|
|
231
|
+
const forwards = authoredForwardMap(slot);
|
|
232
|
+
const logicalTableName = slot.logicalTable.name;
|
|
233
|
+
const constraints = [];
|
|
234
|
+
for (const obligation of slot.obligations) {
|
|
235
|
+
if (obligation.kind !== 'enforced-row-local')
|
|
236
|
+
continue;
|
|
237
|
+
if (obligation.constraint.kind !== 'check')
|
|
238
|
+
continue;
|
|
239
|
+
const source = obligation.constraint.constraint;
|
|
240
|
+
constraints.push({
|
|
241
|
+
name: source.name ? `lens:${source.name}` : 'lens:check',
|
|
242
|
+
expr: rewriteToBasisTerms(ctx, source.expr, map, forwards, logicalTableName),
|
|
243
|
+
// A logical CHECK guards the row being written: insert and update only.
|
|
244
|
+
operations: RowOpFlag.INSERT | RowOpFlag.UPDATE,
|
|
245
|
+
// Prover-supplied write-row dependency set for the per-op decomposition gate.
|
|
246
|
+
referencedWriteRowColumns: rowLocalReferencedBasisColumns(source.expr, map, forwards),
|
|
247
|
+
tags: { [LENS_BOUNDARY_ATTACHED_TAG]: true },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return constraints;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Whether the lens body is a faithful, **non-row-reducing** projection of its
|
|
254
|
+
* single basis source — every basis row maps 1:1 to a logical row, so the logical
|
|
255
|
+
* relation's row set equals the basis relation's on any projected column. True iff
|
|
256
|
+
* none of the row-reducing clauses are present. `orderBy` is row-preserving (it
|
|
257
|
+
* reorders, never drops) and is ignored; `from` single-sourcedness is established
|
|
258
|
+
* separately by {@link resolveSlotBasisSource} returning the basis table.
|
|
259
|
+
*/
|
|
260
|
+
function isNonRowReducingProjection(body) {
|
|
261
|
+
return body.where === undefined
|
|
262
|
+
&& (body.groupBy === undefined || body.groupBy.length === 0)
|
|
263
|
+
&& body.having === undefined
|
|
264
|
+
&& !body.distinct
|
|
265
|
+
&& body.limit === undefined
|
|
266
|
+
&& body.offset === undefined
|
|
267
|
+
&& body.union === undefined
|
|
268
|
+
&& body.compound === undefined
|
|
269
|
+
&& body.withClause === undefined;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* The structural core shared by both FK redundancy directions (child-side
|
|
273
|
+
* {@link lensForeignKeyRedundant} and parent-side {@link lensParentSideForeignKeyRedundant})
|
|
274
|
+
* — **structural match only, no action reasoning**. Returns every basis FK that
|
|
275
|
+
* subsumes the lens-level check (`[]` ⇒ none, default to enforce). Three structural
|
|
276
|
+
* conditions, read from the parent→child direction:
|
|
277
|
+
*
|
|
278
|
+
* 1. **Single-source, value-preserving child mapping** + parent half of (2) — every
|
|
279
|
+
* logical FK child column maps with no transform to a plain `basisChild` column and
|
|
280
|
+
* every logical referenced column to a plain `basisParent` column ({@link mappedFkBasisPairs}).
|
|
281
|
+
* 2. **Equivalent basis FK** — `basisChild` carries an FK whose unordered index
|
|
282
|
+
* pair-set equals the mapped one, referencing `basisParent` ({@link matchingBasisFks}).
|
|
283
|
+
* 3. **Faithful non-row-reducing projection** of the slot the subsuming check scans —
|
|
284
|
+
* `projectionToCheck` selects which: `'parent'` for the child-side check (it scans
|
|
285
|
+
* the parent), `'child'` for the parent-side check (it scans the child).
|
|
286
|
+
*
|
|
287
|
+
* Any gap returns `[]` ⇒ enforce — a false match silently drops enforcement (a
|
|
288
|
+
* soundness hole), so the bias is hard-coded toward double-enforce.
|
|
289
|
+
*/
|
|
290
|
+
function basisFksSubsuming(childSlot, fk, parentSlot, logicalParentColumns, basisChild, basisParent, projectionToCheck) {
|
|
291
|
+
const mappedPairs = mappedFkBasisPairs(childSlot, fk, parentSlot, logicalParentColumns, basisChild, basisParent);
|
|
292
|
+
if (!mappedPairs)
|
|
293
|
+
return [];
|
|
294
|
+
const projSlot = projectionToCheck === 'parent' ? parentSlot : childSlot;
|
|
295
|
+
if (!isNonRowReducingProjection(projSlot.compiledBody))
|
|
296
|
+
return [];
|
|
297
|
+
return matchingBasisFks(basisChild, basisParent, mappedPairs);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Whether the lens-level child-side FK check for `fk` is **provably** redundant
|
|
301
|
+
* with an equivalent FK the basis child write already enforces via
|
|
302
|
+
* `buildChildSideFKChecks` — so the lens-level `EXISTS` is pure double-enforcement
|
|
303
|
+
* cost (`docs/lens.md` § Constraint Attachment). All three conditions must hold;
|
|
304
|
+
* **any** gap (multi-source child, non-plain mapping, missing/permuted basis FK, no
|
|
305
|
+
* parent lens slot, a parent body that might filter rows) returns `false`, defaulting
|
|
306
|
+
* to enforce — a false `true` would silently drop enforcement (a soundness hole).
|
|
307
|
+
*
|
|
308
|
+
* 1. **Single-source, value-preserving child mapping** — the child slot resolves to
|
|
309
|
+
* one basis child table and every logical FK child column maps with no transform
|
|
310
|
+
* to a plain basis child column.
|
|
311
|
+
* 2. **Equivalent basis FK** — `basisChild` carries an FK whose unordered
|
|
312
|
+
* `(basisChildCol → basisParentCol)` pair-set equals the mapped one, referencing
|
|
313
|
+
* the basis parent (this also requires every referenced column to map plainly).
|
|
314
|
+
* 3. **Row-set equivalence of the referenced relation** — the logical parent's lens
|
|
315
|
+
* slot resolves and its compiled body is a faithful, non-row-reducing projection
|
|
316
|
+
* of the basis parent, so the logical parent's row set ⊇ the basis parent's on the
|
|
317
|
+
* referenced columns (the basis check therefore implies the lens check).
|
|
318
|
+
*
|
|
319
|
+
* Returns the subsuming basis FK (for the elision log) or `undefined` to enforce.
|
|
320
|
+
*/
|
|
321
|
+
function lensForeignKeyRedundant(slot, fk, referencedSchema, logicalParentColumns, schemaManager) {
|
|
322
|
+
// (1) single-source child basis table.
|
|
323
|
+
const basisChild = resolveSlotBasisSource(slot, schemaManager);
|
|
324
|
+
if (!basisChild)
|
|
325
|
+
return undefined;
|
|
326
|
+
// (3) parent lens slot + its single basis source must resolve.
|
|
327
|
+
const parentSlot = schemaManager.getSchema(referencedSchema)?.getLensSlot(fk.referencedTable);
|
|
328
|
+
if (!parentSlot)
|
|
329
|
+
return undefined;
|
|
330
|
+
const basisParent = resolveSlotBasisSource(parentSlot, schemaManager);
|
|
331
|
+
if (!basisParent)
|
|
332
|
+
return undefined;
|
|
333
|
+
// Conditions (1)+(2)+(3) via the shared core: the child-side check scans the
|
|
334
|
+
// *parent*, so the parent projection must be non-row-reducing (`'parent'`).
|
|
335
|
+
// Child-side FK enforcement is action-agnostic, so the first match suffices.
|
|
336
|
+
return basisFksSubsuming(slot, fk, parentSlot, logicalParentColumns, basisChild, basisParent, 'parent')[0];
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Whether the lens-level **parent-side** FK check for `fk` (the synthesized `NOT
|
|
340
|
+
* EXISTS` over the logical child) is **provably** redundant with the equivalent
|
|
341
|
+
* parent-side check the re-planned basis parent write already enforces via
|
|
342
|
+
* `buildParentSideFKChecks` — the parent-side dual of {@link lensForeignKeyRedundant},
|
|
343
|
+
* reusing the same structural core ({@link basisFksSubsuming}). Two things differ from
|
|
344
|
+
* the child side:
|
|
345
|
+
*
|
|
346
|
+
* - **Projection slot.** The parent-side subquery scans the *child*, so condition (3)
|
|
347
|
+
* (non-row-reducing) applies to the **child** projection (`'child'`). This is a
|
|
348
|
+
* conservative parity gate: by condition (1) a single-source child already gives
|
|
349
|
+
* `L ⊆ B` on the FK columns, so the basis check (scanning the superset `B`) would
|
|
350
|
+
* reject a superset of cases even with a filtered child — but keeping the gate
|
|
351
|
+
* mirrors the child-side detector exactly and can only *reduce* elision, and
|
|
352
|
+
* default-to-double-enforce is always sound.
|
|
353
|
+
* - **Action match (parent-side only).** `buildParentSideFKChecks` emits a check
|
|
354
|
+
* **only** for a `restrict` basis FK — cascade / set-null / set-default mutate the
|
|
355
|
+
* children instead of rejecting, so they synthesize no parent-side check. The basis
|
|
356
|
+
* write therefore subsumes the lens RESTRICT only when the matched basis FK's
|
|
357
|
+
* op-appropriate action is `restrict`. Because {@link basisFksSubsuming} may return
|
|
358
|
+
* *several* matching basis FKs, the gate scans **all** of them: if **any** is
|
|
359
|
+
* non-`restrict` for the op, the basis write would cascade / null rather than reject
|
|
360
|
+
* ⇒ NOT redundant. (A divergent-action second FK on identical columns referencing
|
|
361
|
+
* the same parent is pathological, but "any uncertainty defaults to enforce" demands
|
|
362
|
+
* the defensive scan.) `ForeignKeyAction` has no distinct `'no action'` — NO ACTION
|
|
363
|
+
* normalizes to the `restrict` default at schema-build time — so "at least as strict
|
|
364
|
+
* as the lens RESTRICT" reduces to the exact `=== 'restrict'` test, matching the
|
|
365
|
+
* physical gate verbatim.
|
|
366
|
+
*
|
|
367
|
+
* Every gap returns `undefined` ⇒ enforce; a false "redundant" verdict silently drops
|
|
368
|
+
* a RESTRICT rejection (a soundness hole), so the bias is hard-coded toward
|
|
369
|
+
* double-enforce. Returns the subsuming basis FK (for the elision log) or `undefined`.
|
|
370
|
+
*/
|
|
371
|
+
function lensParentSideForeignKeyRedundant(childSlot, fk, parentSlot, basisParent, logicalParentColumns, operation, schemaManager) {
|
|
372
|
+
const basisChild = resolveSlotBasisSource(childSlot, schemaManager);
|
|
373
|
+
if (!basisChild)
|
|
374
|
+
return undefined;
|
|
375
|
+
const matches = basisFksSubsuming(childSlot, fk, parentSlot, logicalParentColumns, basisChild, basisParent, 'child');
|
|
376
|
+
if (matches.length === 0)
|
|
377
|
+
return undefined;
|
|
378
|
+
// Action match: the basis parent-side check fires only for a `restrict` basis FK.
|
|
379
|
+
// If ANY matching basis FK would cascade / null instead of reject, the basis write
|
|
380
|
+
// does not subsume the lens RESTRICT — keep enforcing.
|
|
381
|
+
const actionOf = (m) => operation === RowOpFlag.DELETE ? m.onDelete : m.onUpdate;
|
|
382
|
+
if (!matches.every(m => actionOf(m) === 'restrict'))
|
|
383
|
+
return undefined;
|
|
384
|
+
return matches[0];
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Builds the basis-term child-side FK existence constraints a lens write must
|
|
388
|
+
* enforce (the write side of the prover's `enforced-fk` obligation). For each FK
|
|
389
|
+
* obligation it synthesizes a MATCH SIMPLE-guarded `EXISTS` against the
|
|
390
|
+
* schema-qualified logical parent relation, with the child (NEW) columns rewritten
|
|
391
|
+
* from logical to basis terms via the slot's reconstructible projection; the parent
|
|
392
|
+
* side stays in logical terms (it resolves against the logical view). The result is
|
|
393
|
+
* tagged with {@link LENS_BOUNDARY_ATTACHED_TAG} and routed through the basis
|
|
394
|
+
* write's constraint pipeline, where the contained `EXISTS` auto-defers it to commit
|
|
395
|
+
* — matching physical child-side FK gating + timing.
|
|
396
|
+
*
|
|
397
|
+
* v1 **double-enforces by design**: the lens check is emitted even when the basis
|
|
398
|
+
* carries the equivalent FK (always sound). The bounded optimization here elides the
|
|
399
|
+
* lens-level check **only when it is provably redundant** with a basis FK the
|
|
400
|
+
* re-planned basis write already enforces (see {@link lensForeignKeyRedundant}) —
|
|
401
|
+
* every uncertain case still double-enforces. Redundancy is decided against the
|
|
402
|
+
* *current* basis FK set (read here, not stored on the obligation) so the elision is
|
|
403
|
+
* exactly as sound as the physical `buildChildSideFKChecks`, which also reads the
|
|
404
|
+
* basis FKs at plan time.
|
|
405
|
+
*
|
|
406
|
+
* Gated by the caller on the `foreign_keys` pragma. Returns `[]` when the slot is
|
|
407
|
+
* un-proved (`obligations` undefined) or carries no FK obligation — the common case.
|
|
408
|
+
*/
|
|
409
|
+
export function collectLensForeignKeyConstraints(slot, schemaManager) {
|
|
410
|
+
if (!slot.obligations || slot.obligations.length === 0)
|
|
411
|
+
return [];
|
|
412
|
+
const map = logicalToBasisColumnMap(slot);
|
|
413
|
+
const logicalSchemaName = slot.logicalTable.schemaName;
|
|
414
|
+
const constraints = [];
|
|
415
|
+
for (const obligation of slot.obligations) {
|
|
416
|
+
if (obligation.kind !== 'enforced-fk')
|
|
417
|
+
continue;
|
|
418
|
+
if (obligation.constraint.kind !== 'foreignKey')
|
|
419
|
+
continue;
|
|
420
|
+
const fk = obligation.constraint.constraint;
|
|
421
|
+
const referencedSchema = fk.referencedSchema ?? logicalSchemaName;
|
|
422
|
+
const parentColumns = resolveLogicalReferencedColumns(fk, referencedSchema, schemaManager);
|
|
423
|
+
// Parity with the physical child-side builder's count-mismatch guard: if the
|
|
424
|
+
// parent columns cannot be resolved to the same arity as the child columns
|
|
425
|
+
// (an unresolvable parent ⇒ `[]`, or a malformed FK the prover did not catch),
|
|
426
|
+
// skip rather than synthesize an `EXISTS` with `undefined` parent column names.
|
|
427
|
+
if (parentColumns.length !== fk.columns.length) {
|
|
428
|
+
log('lens FK %s: parent column count (%d) != child column count (%d); skipping', fk.name ?? '<anon>', parentColumns.length, fk.columns.length);
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
// Elide the lens-level check when the basis child write provably already
|
|
432
|
+
// enforces an equivalent FK (every uncertain case still double-enforces).
|
|
433
|
+
const subsuming = lensForeignKeyRedundant(slot, fk, referencedSchema, parentColumns, schemaManager);
|
|
434
|
+
if (subsuming) {
|
|
435
|
+
log('lens FK %s on %s: elided — provably subsumed by basis FK %s referencing %s (the re-planned basis write enforces it)', fk.name ?? '<anon>', slot.logicalTable.name, subsuming.name ?? '<anon>', subsuming.referencedTable);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
// Rewrite each FK child column index → logical name → basis column. A column
|
|
439
|
+
// the prover proved reconstructible maps; otherwise it falls back to the logical
|
|
440
|
+
// name (the prover would have errored on a non-reconstructible FK child column).
|
|
441
|
+
const childColumns = fk.columns.map(childIdx => {
|
|
442
|
+
const logicalName = slot.logicalTable.columns[childIdx]?.name ?? `#${childIdx}`;
|
|
443
|
+
return map.get(logicalName.toLowerCase()) ?? logicalName;
|
|
444
|
+
});
|
|
445
|
+
const expr = synthesizeFKExistsExpr(fk.referencedTable, parentColumns, childColumns, 'NEW', referencedSchema);
|
|
446
|
+
constraints.push({
|
|
447
|
+
name: fk.name ? `lens:fk:${fk.name}` : 'lens:fk',
|
|
448
|
+
expr,
|
|
449
|
+
// Child-side FK guards the row being written: insert and update only.
|
|
450
|
+
operations: RowOpFlag.INSERT | RowOpFlag.UPDATE,
|
|
451
|
+
tags: { [LENS_BOUNDARY_ATTACHED_TAG]: true },
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return constraints;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* The null-safe per-column "referenced key unchanged" predicate — equivalent to
|
|
458
|
+
* `OLD.p is not distinct from NEW.p`:
|
|
459
|
+
*
|
|
460
|
+
* ( OLD.p is null and NEW.p is null )
|
|
461
|
+
* or ( OLD.p is not null and NEW.p is not null and OLD.p = NEW.p )
|
|
462
|
+
*
|
|
463
|
+
* Built from only existing AST node kinds (`=`, `is null`, `is not null`, `and`,
|
|
464
|
+
* `or`) — Quereus has no general `is not distinct from` operator surface to
|
|
465
|
+
* synthesize into a constraint AST. Crucially this evaluates to a definite **false**
|
|
466
|
+
* (never NULL) when exactly one side is NULL: the naive `(OLD = NEW) or (OLD is null
|
|
467
|
+
* and NEW is null)` instead yields `NULL or false = NULL` there, which the
|
|
468
|
+
* deferred-constraint check (`value === false || value === 0`) does not treat as a
|
|
469
|
+
* failure — so it would wrongly admit an orphaning value→NULL update.
|
|
470
|
+
*
|
|
471
|
+
* Null-safety matters for a **nullable** referenced parent key: a value→NULL update
|
|
472
|
+
* *changes* the key (orphaning a child), so the guard must be false ⇒ fall through to
|
|
473
|
+
* the `NOT EXISTS` ⇒ reject, matching physical RESTRICT. Only a genuine NULL→NULL
|
|
474
|
+
* no-op (first arm) short-circuits true. For a NOT-NULL referenced key the first arm
|
|
475
|
+
* and the `is not null` conjuncts are dead and the predicate collapses to the plain
|
|
476
|
+
* `OLD.p = NEW.p` — exact parity with the physical path.
|
|
477
|
+
*/
|
|
478
|
+
function buildNullSafeEquality(col) {
|
|
479
|
+
const old = { type: 'column', name: col, table: 'OLD' };
|
|
480
|
+
const neo = { type: 'column', name: col, table: 'NEW' };
|
|
481
|
+
const isNull = (e) => ({ type: 'unary', operator: 'IS NULL', expr: e });
|
|
482
|
+
const isNotNull = (e) => ({ type: 'unary', operator: 'IS NOT NULL', expr: e });
|
|
483
|
+
const and = (l, r) => ({ type: 'binary', operator: 'AND', left: l, right: r });
|
|
484
|
+
const bothNull = and(isNull(old), isNull(neo));
|
|
485
|
+
const eq = { type: 'binary', operator: '=', left: old, right: neo };
|
|
486
|
+
const bothPresentEqual = and(and(isNotNull(old), isNotNull(neo)), eq);
|
|
487
|
+
return { type: 'binary', operator: 'OR', left: bothNull, right: bothPresentEqual };
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* The parent-side UPDATE short-circuit guard:
|
|
491
|
+
*
|
|
492
|
+
* ( (OLD.p1 ≡ NEW.p1 and … and OLD.pn ≡ NEW.pn) or <NOT EXISTS over OLD> )
|
|
493
|
+
*
|
|
494
|
+
* where `≡` is the null-safe {@link buildNullSafeEquality}. Reproduces the physical
|
|
495
|
+
* parent-side UPDATE short-circuit (`emit/constraint-check.ts` skips the `NOT EXISTS`
|
|
496
|
+
* when no referenced parent column changed) — a **correctness** requirement, not just
|
|
497
|
+
* perf: a plain `NOT EXISTS` over OLD values would reject a benign update that does not
|
|
498
|
+
* touch the referenced columns but whose key a child still references. The per-column
|
|
499
|
+
* comparison is null-safe so a value→NULL update on a **nullable** referenced key (which
|
|
500
|
+
* *does* change the key, orphaning the child) falls through to the `NOT EXISTS` and is
|
|
501
|
+
* rejected, while a NULL→NULL no-op still short-circuits true. DELETE never gets this
|
|
502
|
+
* guard — there NEW is all-NULL, so on a NULL OLD key `OLD ≡ NEW` would now be true and
|
|
503
|
+
* wrongly short-circuit; op-specific synthesis keeps DELETE on the plain `NOT EXISTS`.
|
|
504
|
+
*/
|
|
505
|
+
function buildParentSideUpdateGuard(parentBasisColumns, notExists) {
|
|
506
|
+
const equalities = parentBasisColumns.map(buildNullSafeEquality);
|
|
507
|
+
const guard = equalities.reduce((acc, eq) => ({
|
|
508
|
+
type: 'binary',
|
|
509
|
+
operator: 'AND',
|
|
510
|
+
left: acc,
|
|
511
|
+
right: eq,
|
|
512
|
+
}));
|
|
513
|
+
return { type: 'binary', operator: 'OR', left: guard, right: notExists };
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Builds the parent-side FK non-existence constraints a lens write through a logical
|
|
517
|
+
* **parent** must enforce — the cross-slot dual of {@link collectLensForeignKeyConstraints}
|
|
518
|
+
* and the lens analogue of `buildParentSideFKChecks`. The physical parent-side builder
|
|
519
|
+
* discovers FKs by scanning declared `TableSchema.foreignKeys` on basis tables; a logical
|
|
520
|
+
* FK lives only on the **child** slot's `enforced-fk` obligation (on no basis table), so
|
|
521
|
+
* this collector walks every schema's lens slots and, for each child slot whose FK
|
|
522
|
+
* references `parentSlot`'s logical table (name + resolved schema, case-insensitive),
|
|
523
|
+
* synthesizes one `NOT EXISTS(SELECT 1 FROM <childLogical> WHERE <child>.<childCol> =
|
|
524
|
+
* OLD.<parentBasisCol> …)` against the schema-qualified logical child relation.
|
|
525
|
+
*
|
|
526
|
+
* The child columns stay **logical** (they resolve against the registered logical child
|
|
527
|
+
* view named in the FROM). The parent's referenced columns are rewritten **logical→basis**
|
|
528
|
+
* via the parent slot's reconstructible projection, because the `OLD.*` / `NEW.*` side is
|
|
529
|
+
* the parent's basis write row. For DELETE the expression is the plain `NOT EXISTS`; for
|
|
530
|
+
* UPDATE it is wrapped in the {@link buildParentSideUpdateGuard} short-circuit. The result
|
|
531
|
+
* is tagged {@link LENS_BOUNDARY_ATTACHED_TAG}, masked to the requested op, and routed
|
|
532
|
+
* through the basis write's constraint pipeline, where the contained `EXISTS` auto-defers
|
|
533
|
+
* it to commit (the accepted v1 timing — identical ABORT outcome, symmetric with the
|
|
534
|
+
* already-shipped child-side).
|
|
535
|
+
*
|
|
536
|
+
* Action gate: only `restrict` (on the op-appropriate `onDelete` / `onUpdate`) emits —
|
|
537
|
+
* **matching `buildParentSideFKChecks` exactly**. CASCADE / SET NULL / SET DEFAULT are
|
|
538
|
+
* **propagated** (not detected here) by the runtime cascade walker
|
|
539
|
+
* `executeLensForeignKeyActions` (`runtime/foreign-key-actions.ts`), the logical dual of
|
|
540
|
+
* `executeForeignKeyActions`. The lens-level RESTRICT check **double-enforces** by default
|
|
541
|
+
* (sound: both the lens-level check and any equivalent basis parent-side check reject the
|
|
542
|
+
* same condition), but is now **elided when provably redundant** with the basis parent
|
|
543
|
+
* write's own `buildParentSideFKChecks` (see {@link lensParentSideForeignKeyRedundant}):
|
|
544
|
+
* a single-source value-preserving child mapping, an equivalent basis FK referencing the
|
|
545
|
+
* basis parent, a faithful non-row-reducing logical-child projection, **and** — the
|
|
546
|
+
* parent-side-only addition the child side does not need — every matching basis FK being
|
|
547
|
+
* `restrict` for the op (a cascade / null basis FK would not reject, so it never subsumes
|
|
548
|
+
* a lens RESTRICT). Any uncertainty defaults to double-enforce.
|
|
549
|
+
*
|
|
550
|
+
* Gated by the caller on the `foreign_keys` pragma (mirroring the child-side). Returns
|
|
551
|
+
* `[]` for a multi-source / decomposition parent (its `OLD.*` is not one basis row — a
|
|
552
|
+
* documented single-source-spine boundary, decided here via {@link resolveSlotBasisSource}),
|
|
553
|
+
* for a non-referenced parent, and for an un-proved slot.
|
|
554
|
+
*/
|
|
555
|
+
export function collectLensParentSideForeignKeyConstraints(parentSlot, schemaManager, operation) {
|
|
556
|
+
// Single-source spine: the parent-side constraint rides the parent's basis base op,
|
|
557
|
+
// so OLD.* / NEW.* must be exactly one basis row. A multi-source / decomposition
|
|
558
|
+
// parent (an opaque or multi-table FROM) routes nothing extra (documented boundary).
|
|
559
|
+
// `basisParent` is also the table the redundancy detector matches basis FKs against.
|
|
560
|
+
const basisParent = resolveSlotBasisSource(parentSlot, schemaManager);
|
|
561
|
+
if (!basisParent)
|
|
562
|
+
return [];
|
|
563
|
+
const parentMap = logicalToBasisColumnMap(parentSlot);
|
|
564
|
+
const constraints = [];
|
|
565
|
+
// Cross-slot discovery (the shared `findLogicalParentFkRefs`): every logical FK on
|
|
566
|
+
// any slot that references this parent's logical table, with the child / parent
|
|
567
|
+
// column names + the count-mismatch guard already resolved.
|
|
568
|
+
for (const { childSlot, fk, childLogicalColumns, parentLogicalColumns } of findLogicalParentFkRefs(parentSlot, schemaManager)) {
|
|
569
|
+
// Action gate — mirror buildParentSideFKChecks exactly: only RESTRICT
|
|
570
|
+
// synthesizes a parent-side check (cascades are propagated by the runtime
|
|
571
|
+
// cascade walker — `executeLensForeignKeyActions` — not here).
|
|
572
|
+
const action = operation === RowOpFlag.DELETE ? fk.onDelete : fk.onUpdate;
|
|
573
|
+
if (action !== 'restrict')
|
|
574
|
+
continue;
|
|
575
|
+
// Elide the lens-level parent-side check when the re-planned basis parent
|
|
576
|
+
// write provably already enforces an equivalent (RESTRICT) parent-side FK
|
|
577
|
+
// (every uncertain case — including any non-restrict matching basis FK —
|
|
578
|
+
// still double-enforces).
|
|
579
|
+
const subsuming = lensParentSideForeignKeyRedundant(childSlot, fk, parentSlot, basisParent, parentLogicalColumns, operation, schemaManager);
|
|
580
|
+
if (subsuming) {
|
|
581
|
+
log('lens parent-side FK %s on %s: elided — provably subsumed by basis FK %s referencing %s (action restrict; the re-planned basis parent write enforces it)', fk.name ?? '<anon>', parentSlot.logicalTable.name, subsuming.name ?? '<anon>', subsuming.referencedTable);
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
// Parent referenced columns rewritten logical→basis through the parent slot's
|
|
585
|
+
// projection for the OLD/NEW correlation side.
|
|
586
|
+
const parentBasisColumns = parentLogicalColumns.map(name => parentMap.get(name.toLowerCase()) ?? name);
|
|
587
|
+
// Child FK columns stay logical — they resolve against the schema-qualified
|
|
588
|
+
// logical child view named in the NOT EXISTS FROM.
|
|
589
|
+
const notExists = synthesizeFKNotExistsExpr(childSlot.logicalTable.name, childLogicalColumns, parentBasisColumns, 'OLD', childSlot.logicalTable.schemaName);
|
|
590
|
+
const expr = operation === RowOpFlag.DELETE
|
|
591
|
+
? notExists
|
|
592
|
+
: buildParentSideUpdateGuard(parentBasisColumns, notExists);
|
|
593
|
+
constraints.push({
|
|
594
|
+
name: fk.name ? `lens:fk:parent:${fk.name}` : 'lens:fk:parent',
|
|
595
|
+
expr,
|
|
596
|
+
operations: operation,
|
|
597
|
+
tags: { [LENS_BOUNDARY_ATTACHED_TAG]: true },
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
return constraints;
|
|
601
|
+
}
|
|
602
|
+
/** The logical key column indices forming a primary-key / unique constraint. */
|
|
603
|
+
function setLevelKeyColumns(c) {
|
|
604
|
+
return c.kind === 'primaryKey' ? c.columns.map(col => col.index) : c.constraint.columns;
|
|
605
|
+
}
|
|
606
|
+
/** The routed-constraint name for a set-level key (mirrors the FK `lens:fk:<name>` convention). */
|
|
607
|
+
function setLevelConstraintName(c) {
|
|
608
|
+
if (c.kind === 'primaryKey')
|
|
609
|
+
return 'lens:pk';
|
|
610
|
+
return c.constraint.name ? `lens:unique:${c.constraint.name}` : 'lens:unique';
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Builds the deferred count-subquery uniqueness predicate for one logical key:
|
|
614
|
+
*
|
|
615
|
+
* (select count(*) from <logicalSchema>.<logicalTable> as _u
|
|
616
|
+
* where _u.lk1 = NEW.bk1 and … and _u.lkn = NEW.bkn) <= 1
|
|
617
|
+
*
|
|
618
|
+
* The subquery FROM is the **logical view** (schema-qualified + aliased `_u`), so
|
|
619
|
+
* `_u.<logicalCol>` resolves against the registered logical relation while each key
|
|
620
|
+
* column's `newSide` expression (a correlated reference resolved from the
|
|
621
|
+
* surrounding constraint scope, exactly as the FK `EXISTS` resolves `NEW.*`)
|
|
622
|
+
* reconstructs that column's **logical key value** from the basis write row: a bare
|
|
623
|
+
* `NEW.<basisCol>` for a reconstructible (rename / passthrough) column, and the
|
|
624
|
+
* authored column's NEW-qualified **forward `get`** image (e.g. `NEW.code + 10`) for
|
|
625
|
+
* a proven-bijective `with inverse` column — so a logical-domain value is compared
|
|
626
|
+
* to a logical-domain value, not a basis-domain one. The `count(*)` is a `count`
|
|
627
|
+
* with empty args — `astToString` renders it `count(*)` and the planner treats it as
|
|
628
|
+
* the row-count aggregate. The contained scalar subquery makes the constraint
|
|
629
|
+
* pipeline auto-defer the check to commit. NULL key columns fall out for free:
|
|
630
|
+
* `_u.lk = <newSide>` is `NULL` (never true) when either side is NULL, so a NULL-key
|
|
631
|
+
* row is never counted — SQL UNIQUE's NULL-distinct rule.
|
|
632
|
+
*/
|
|
633
|
+
function synthesizeUniqueCountExpr(logicalSchema, logicalTable, keyColumns) {
|
|
634
|
+
const alias = '_u';
|
|
635
|
+
const conditions = keyColumns.map(({ logicalColumn, newSide }) => ({
|
|
636
|
+
type: 'binary',
|
|
637
|
+
operator: '=',
|
|
638
|
+
left: { type: 'column', name: logicalColumn, table: alias },
|
|
639
|
+
right: newSide,
|
|
640
|
+
}));
|
|
641
|
+
const whereExpr = conditions.reduce((acc, cond) => ({
|
|
642
|
+
type: 'binary',
|
|
643
|
+
operator: 'AND',
|
|
644
|
+
left: acc,
|
|
645
|
+
right: cond,
|
|
646
|
+
}));
|
|
647
|
+
const subquery = {
|
|
648
|
+
type: 'select',
|
|
649
|
+
columns: [{ type: 'column', expr: { type: 'function', name: 'count', args: [] } }],
|
|
650
|
+
from: [{
|
|
651
|
+
type: 'table',
|
|
652
|
+
table: { type: 'identifier', name: logicalTable, schema: logicalSchema },
|
|
653
|
+
alias,
|
|
654
|
+
}],
|
|
655
|
+
where: whereExpr,
|
|
656
|
+
};
|
|
657
|
+
return {
|
|
658
|
+
type: 'binary',
|
|
659
|
+
operator: '<=',
|
|
660
|
+
left: { type: 'subquery', query: subquery },
|
|
661
|
+
right: { type: 'literal', value: 1 },
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Builds the deferred set-level uniqueness CHECK constraints a lens write must
|
|
666
|
+
* enforce (the write side of the prover's `enforced-set-level` `commit-time`
|
|
667
|
+
* obligation). For each commit-time set-level key (no basis covering structure) it
|
|
668
|
+
* synthesizes the count-subquery `<= 1` predicate via {@link synthesizeUniqueCountExpr},
|
|
669
|
+
* with the logical key columns mapped to their basis columns on the `NEW.*` side
|
|
670
|
+
* (via the slot's reconstructible projection) and kept logical inside the subquery
|
|
671
|
+
* (they resolve against the registered logical view). The result is tagged with
|
|
672
|
+
* {@link LENS_BOUNDARY_ATTACHED_TAG} and routed through the basis write's constraint
|
|
673
|
+
* pipeline, where the contained scalar subquery auto-defers it to commit.
|
|
674
|
+
*
|
|
675
|
+
* Only the `commit-time` mode is emitted: a `row-time` key is already enforced by
|
|
676
|
+
* the basis `UNIQUE` it is (by the classifier's precondition) backed by — the
|
|
677
|
+
* single-source re-plan reaches that basis UC, whose covering-MV enforcement path
|
|
678
|
+
* does the O(log n) lookup and honors the conflict action, so no constraint is
|
|
679
|
+
* synthesized here. `proved` / `vacuous` keys need no enforcement. Returns `[]`
|
|
680
|
+
* when the slot is un-proved (`obligations` undefined) or
|
|
681
|
+
* carries no commit-time set-level key — the common case, so a non-lens / plain
|
|
682
|
+
* view / proved-key write pays nothing. DELETE never introduces a duplicate, so the
|
|
683
|
+
* caller restricts this to insert/update.
|
|
684
|
+
*/
|
|
685
|
+
export function collectLensSetLevelConstraints(slot) {
|
|
686
|
+
if (!slot.obligations || slot.obligations.length === 0)
|
|
687
|
+
return [];
|
|
688
|
+
const map = logicalToBasisColumnMap(slot);
|
|
689
|
+
const forwards = authoredForwardMap(slot);
|
|
690
|
+
const logicalSchemaName = slot.logicalTable.schemaName;
|
|
691
|
+
const logicalTableName = slot.logicalTable.name;
|
|
692
|
+
const constraints = [];
|
|
693
|
+
for (const obligation of slot.obligations) {
|
|
694
|
+
if (obligation.kind !== 'enforced-set-level' || obligation.mode !== 'commit-time')
|
|
695
|
+
continue;
|
|
696
|
+
const c = obligation.constraint;
|
|
697
|
+
if (c.kind !== 'primaryKey' && c.kind !== 'unique')
|
|
698
|
+
continue;
|
|
699
|
+
const logicalColumns = setLevelKeyColumns(c);
|
|
700
|
+
// The empty (singleton) key classifies `vacuous`, never commit-time set-level;
|
|
701
|
+
// guard defensively so an empty WHERE is never synthesized.
|
|
702
|
+
if (logicalColumns.length === 0)
|
|
703
|
+
continue;
|
|
704
|
+
// Each logical key column → the NEW.* expression reconstructing its logical key
|
|
705
|
+
// value from the basis write row: a bare `NEW.<basis>` for a reconstructible
|
|
706
|
+
// (rename / passthrough) column, or the authored column's NEW-qualified forward
|
|
707
|
+
// `get` image for a proven-bijective `with inverse` column (so the count compares
|
|
708
|
+
// logical value to logical value). A non-reconstructible, non-authored key would
|
|
709
|
+
// have made the table read-only — no write reaches here — but the bare-name
|
|
710
|
+
// fallback keeps the synthesis total.
|
|
711
|
+
const keyColumns = logicalColumns.map(li => {
|
|
712
|
+
const logicalColumn = slot.logicalTable.columns[li]?.name ?? `#${li}`;
|
|
713
|
+
const lc = logicalColumn.toLowerCase();
|
|
714
|
+
const basisColumn = map.get(lc);
|
|
715
|
+
if (basisColumn !== undefined) {
|
|
716
|
+
return { logicalColumn, newSide: { type: 'column', name: basisColumn, table: 'NEW' } };
|
|
717
|
+
}
|
|
718
|
+
const forward = forwards.get(lc);
|
|
719
|
+
if (forward !== undefined) {
|
|
720
|
+
return { logicalColumn, newSide: transformExpr(forward, col => ({ type: 'column', name: col.name, table: 'NEW' })) };
|
|
721
|
+
}
|
|
722
|
+
return { logicalColumn, newSide: { type: 'column', name: logicalColumn, table: 'NEW' } };
|
|
723
|
+
});
|
|
724
|
+
constraints.push({
|
|
725
|
+
name: setLevelConstraintName(c),
|
|
726
|
+
expr: synthesizeUniqueCountExpr(logicalSchemaName, logicalTableName, keyColumns),
|
|
727
|
+
// A duplicate is only introduced by an insert or a key-changing update;
|
|
728
|
+
// a delete cannot create one (and is excluded by the caller anyway).
|
|
729
|
+
operations: RowOpFlag.INSERT | RowOpFlag.UPDATE,
|
|
730
|
+
tags: { [LENS_BOUNDARY_ATTACHED_TAG]: true },
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
return constraints;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Whether the slot carries any `enforced-set-level` `commit-time` obligation — the
|
|
737
|
+
* detection-only set-level class. The view-mutation builder consults this to reject
|
|
738
|
+
* `or replace` / `or ignore` (and matching upserts), which the commit-time scan
|
|
739
|
+
* cannot honor (row-time conflict resolution needs a covering structure). Returns
|
|
740
|
+
* `false` for a non-lens / plain view / proved- or row-time-keyed slot.
|
|
741
|
+
*/
|
|
742
|
+
export function hasCommitTimeSetLevelObligation(slot) {
|
|
743
|
+
return (slot.obligations ?? []).some(o => o.kind === 'enforced-set-level' && o.mode === 'commit-time');
|
|
744
|
+
}
|
|
745
|
+
//# sourceMappingURL=lens-enforcement.js.map
|