@quereus/quereus 2.9.0 → 3.0.1
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 +224 -222
- package/dist/src/core/database-assertions.d.ts +36 -16
- package/dist/src/core/database-assertions.d.ts.map +1 -1
- package/dist/src/core/database-assertions.js +222 -118
- package/dist/src/core/database-assertions.js.map +1 -1
- package/dist/src/core/database-transaction.d.ts +96 -13
- package/dist/src/core/database-transaction.d.ts.map +1 -1
- package/dist/src/core/database-transaction.js +294 -35
- package/dist/src/core/database-transaction.js.map +1 -1
- package/dist/src/core/database-watchers.d.ts +58 -0
- package/dist/src/core/database-watchers.d.ts.map +1 -0
- package/dist/src/core/database-watchers.js +206 -0
- package/dist/src/core/database-watchers.js.map +1 -0
- package/dist/src/core/database.d.ts +78 -5
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +120 -20
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.d.ts +9 -0
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +29 -0
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/core/table-handle.d.ts +45 -0
- package/dist/src/core/table-handle.d.ts.map +1 -0
- package/dist/src/core/table-handle.js +54 -0
- package/dist/src/core/table-handle.js.map +1 -0
- package/dist/src/func/builtins/conversion.d.ts.map +1 -1
- package/dist/src/func/builtins/conversion.js +12 -1
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +22 -8
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/generation.d.ts.map +1 -1
- package/dist/src/func/builtins/generation.js +26 -1
- package/dist/src/func/builtins/generation.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +5 -1
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/json-tvf.d.ts.map +1 -1
- package/dist/src/func/builtins/json-tvf.js +16 -2
- package/dist/src/func/builtins/json-tvf.js.map +1 -1
- package/dist/src/func/builtins/schema.d.ts +4 -0
- package/dist/src/func/builtins/schema.d.ts.map +1 -1
- package/dist/src/func/builtins/schema.js +270 -11
- package/dist/src/func/builtins/schema.js.map +1 -1
- package/dist/src/func/registration.d.ts +19 -1
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +8 -3
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +12 -4
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/planner/analysis/assertion-classifier.d.ts +71 -0
- package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -0
- package/dist/src/planner/analysis/assertion-classifier.js +286 -0
- package/dist/src/planner/analysis/assertion-classifier.js.map +1 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.d.ts +34 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.d.ts.map +1 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.js +119 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -0
- package/dist/src/planner/analysis/binding-extractor.d.ts +58 -0
- package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -0
- package/dist/src/planner/analysis/binding-extractor.js +110 -0
- package/dist/src/planner/analysis/binding-extractor.js.map +1 -0
- package/dist/src/planner/analysis/change-scope.d.ts +184 -0
- package/dist/src/planner/analysis/change-scope.d.ts.map +1 -0
- package/dist/src/planner/analysis/change-scope.js +825 -0
- package/dist/src/planner/analysis/change-scope.js.map +1 -0
- package/dist/src/planner/analysis/check-extraction.d.ts +29 -0
- package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -0
- package/dist/src/planner/analysis/check-extraction.js +420 -0
- package/dist/src/planner/analysis/check-extraction.js.map +1 -0
- package/dist/src/planner/analysis/constraint-extractor.d.ts +47 -7
- package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.js +186 -93
- package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
- package/dist/src/planner/analysis/partial-unique-extraction.d.ts +68 -0
- package/dist/src/planner/analysis/partial-unique-extraction.d.ts.map +1 -0
- package/dist/src/planner/analysis/partial-unique-extraction.js +347 -0
- package/dist/src/planner/analysis/partial-unique-extraction.js.map +1 -0
- package/dist/src/planner/analysis/predicate-conjuncts.d.ts +14 -0
- package/dist/src/planner/analysis/predicate-conjuncts.d.ts.map +1 -0
- package/dist/src/planner/analysis/predicate-conjuncts.js +31 -0
- package/dist/src/planner/analysis/predicate-conjuncts.js.map +1 -0
- package/dist/src/planner/analysis/predicate-shape.d.ts +52 -0
- package/dist/src/planner/analysis/predicate-shape.d.ts.map +1 -0
- package/dist/src/planner/analysis/predicate-shape.js +119 -0
- package/dist/src/planner/analysis/predicate-shape.js.map +1 -0
- package/dist/src/planner/analysis/sat-checker.d.ts +43 -0
- package/dist/src/planner/analysis/sat-checker.d.ts.map +1 -0
- package/dist/src/planner/analysis/sat-checker.js +393 -0
- package/dist/src/planner/analysis/sat-checker.js.map +1 -0
- package/dist/src/planner/building/table.d.ts.map +1 -1
- package/dist/src/planner/building/table.js +1 -1
- package/dist/src/planner/building/table.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +10 -1
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/characteristics.js +24 -5
- package/dist/src/planner/framework/characteristics.js.map +1 -1
- package/dist/src/planner/framework/context.d.ts +1 -8
- package/dist/src/planner/framework/context.d.ts.map +1 -1
- package/dist/src/planner/framework/context.js +4 -21
- package/dist/src/planner/framework/context.js.map +1 -1
- package/dist/src/planner/framework/pass.d.ts +18 -2
- package/dist/src/planner/framework/pass.d.ts.map +1 -1
- package/dist/src/planner/framework/pass.js +145 -46
- package/dist/src/planner/framework/pass.js.map +1 -1
- package/dist/src/planner/framework/physical-utils.d.ts +0 -9
- package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
- package/dist/src/planner/framework/physical-utils.js +0 -31
- package/dist/src/planner/framework/physical-utils.js.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.d.ts +25 -0
- package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.js +75 -8
- 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 +6 -1
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.js +17 -3
- package/dist/src/planner/nodes/asof-scan-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 +19 -9
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
- package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/distinct-node.js +10 -6
- package/dist/src/planner/nodes/distinct-node.js.map +1 -1
- package/dist/src/planner/nodes/empty-relation-node.d.ts +27 -0
- package/dist/src/planner/nodes/empty-relation-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/empty-relation-node.js +61 -0
- package/dist/src/planner/nodes/empty-relation-node.js.map +1 -0
- package/dist/src/planner/nodes/filter.d.ts.map +1 -1
- package/dist/src/planner/nodes/filter.js +65 -5
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.js +8 -6
- package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +12 -9
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +24 -1
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +86 -0
- package/dist/src/planner/nodes/join-utils.js.map +1 -1
- package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
- package/dist/src/planner/nodes/limit-offset.js +6 -1
- package/dist/src/planner/nodes/limit-offset.js.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +19 -9
- 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 +5 -2
- package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts +1 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +1 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +186 -4
- 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/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +75 -30
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts +24 -2
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +101 -1
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.d.ts +9 -1
- package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.js +21 -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 +64 -28
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts +1 -0
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +12 -0
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.js +15 -0
- 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 -1
- 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 +10 -3
- package/dist/src/planner/nodes/sort.js.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.js +8 -8
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +3 -3
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +26 -8
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/nodes/table-function-call.d.ts +4 -1
- package/dist/src/planner/nodes/table-function-call.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-function-call.js +224 -14
- package/dist/src/planner/nodes/table-function-call.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +9 -2
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer-tuning.d.ts +29 -1
- package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
- package/dist/src/planner/optimizer-tuning.js +3 -0
- package/dist/src/planner/optimizer-tuning.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +187 -0
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +22 -7
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +30 -0
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -0
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +116 -0
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -0
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +7 -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 +18 -16
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts +56 -0
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-join-elimination.js +326 -0
- package/dist/src/planner/rules/join/rule-join-elimination.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 +10 -2
- package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts +20 -0
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +181 -0
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts +46 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +156 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts +30 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +60 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts +45 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js +210 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts +29 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js +161 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js.map +1 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +39 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +91 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts +35 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts.map +1 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +74 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts +27 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts.map +1 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +103 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +1 -25
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/planner/scopes/global.js +2 -2
- package/dist/src/planner/scopes/global.js.map +1 -1
- package/dist/src/planner/type-utils.d.ts.map +1 -1
- package/dist/src/planner/type-utils.js +11 -0
- package/dist/src/planner/type-utils.js.map +1 -1
- package/dist/src/planner/util/fd-utils.d.ts +245 -0
- package/dist/src/planner/util/fd-utils.d.ts.map +1 -0
- package/dist/src/planner/util/fd-utils.js +1416 -0
- package/dist/src/planner/util/fd-utils.js.map +1 -0
- package/dist/src/planner/util/ind-utils.d.ts +79 -0
- package/dist/src/planner/util/ind-utils.d.ts.map +1 -0
- package/dist/src/planner/util/ind-utils.js +146 -0
- package/dist/src/planner/util/ind-utils.js.map +1 -0
- package/dist/src/planner/util/key-utils.d.ts +75 -14
- package/dist/src/planner/util/key-utils.d.ts.map +1 -1
- package/dist/src/planner/util/key-utils.js +234 -57
- package/dist/src/planner/util/key-utils.js.map +1 -1
- package/dist/src/runtime/delta-executor.d.ts +134 -0
- package/dist/src/runtime/delta-executor.d.ts.map +1 -0
- package/dist/src/runtime/delta-executor.js +382 -0
- package/dist/src/runtime/delta-executor.js.map +1 -0
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +70 -24
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-assertion.js +3 -2
- package/dist/src/runtime/emit/create-assertion.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +121 -41
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/drop-assertion.js +1 -1
- package/dist/src/runtime/emit/drop-assertion.js.map +1 -1
- package/dist/src/runtime/emit/empty-relation.d.ts +5 -0
- package/dist/src/runtime/emit/empty-relation.d.ts.map +1 -0
- package/dist/src/runtime/emit/empty-relation.js +11 -0
- package/dist/src/runtime/emit/empty-relation.js.map +1 -0
- package/dist/src/runtime/foreign-key-actions.d.ts +39 -0
- package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
- package/dist/src/runtime/foreign-key-actions.js +219 -1
- package/dist/src/runtime/foreign-key-actions.js.map +1 -1
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +2 -0
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/schema/assertion.d.ts +8 -0
- package/dist/src/schema/assertion.d.ts.map +1 -1
- package/dist/src/schema/change-events.d.ts +5 -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/function.d.ts +65 -1
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js +31 -0
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/manager.d.ts +33 -0
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +95 -4
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/rename-rewriter.d.ts +32 -0
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
- package/dist/src/schema/rename-rewriter.js +392 -105
- package/dist/src/schema/rename-rewriter.js.map +1 -1
- package/dist/src/schema/table.d.ts +21 -2
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +17 -8
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/types/temporal-types.d.ts.map +1 -1
- package/dist/src/types/temporal-types.js +32 -0
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/vtab/events.d.ts +9 -0
- package/dist/src/vtab/events.d.ts.map +1 -1
- package/dist/src/vtab/events.js +19 -0
- package/dist/src/vtab/events.js.map +1 -1
- package/dist/src/vtab/memory/layer/connection.d.ts +20 -8
- package/dist/src/vtab/memory/layer/connection.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/connection.js +95 -73
- package/dist/src/vtab/memory/layer/connection.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +91 -10
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts +0 -8
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +0 -15
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/table.d.ts.map +1 -1
- package/dist/src/vtab/memory/table.js +13 -2
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/memory/utils/predicate.d.ts +2 -1
- package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
- package/dist/src/vtab/memory/utils/predicate.js +32 -1
- package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify a `create assertion` for optimizer-hoisting eligibility.
|
|
3
|
+
*
|
|
4
|
+
* Recognized canonical form (purely syntactic on the AST):
|
|
5
|
+
*
|
|
6
|
+
* not exists (select 1 from T [where P])
|
|
7
|
+
*
|
|
8
|
+
* where `T` is a base table (not a view, CTE, or TVF) and `P` references only
|
|
9
|
+
* columns of `T`. The negated predicate `not P` is hoisted onto `T` as if it
|
|
10
|
+
* were a per-row CHECK constraint — see ticket
|
|
11
|
+
* `3-optimizer-assertion-as-rewrite-premise` for the rationale.
|
|
12
|
+
*
|
|
13
|
+
* Anything outside this shape — existential `exists(...)`, aggregate
|
|
14
|
+
* `(select count(*) ...) = 0`, multi-table joins, non-deterministic calls,
|
|
15
|
+
* nested subqueries, view-targeted assertions, etc. — is silently rejected;
|
|
16
|
+
* the assertion falls through to commit-time enforcement, which remains the
|
|
17
|
+
* source of truth.
|
|
18
|
+
*/
|
|
19
|
+
import type * as AST from '../../parser/ast.js';
|
|
20
|
+
import type { IntegrityAssertionSchema } from '../../schema/assertion.js';
|
|
21
|
+
import type { SchemaManager } from '../../schema/manager.js';
|
|
22
|
+
import { collectColumnNames } from './predicate-shape.js';
|
|
23
|
+
export interface AssertionHoistCandidate {
|
|
24
|
+
/** Lowercased `schema.table` name of the target base table. */
|
|
25
|
+
readonly baseTableQualifiedName: string;
|
|
26
|
+
/**
|
|
27
|
+
* The inner predicate `P` from `not exists (select 1 from T where P)`.
|
|
28
|
+
* `undefined` is reserved for the unconditional-empty case
|
|
29
|
+
* (`not exists (select 1 from T)`) and is currently rejected at the
|
|
30
|
+
* classifier — synthesizing `check (false)` is too aggressive for a pilot.
|
|
31
|
+
*/
|
|
32
|
+
readonly innerPredicate?: AST.Expression;
|
|
33
|
+
/** Lowercased assertion name, for provenance tagging. */
|
|
34
|
+
readonly assertionName: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Return a hoist candidate if the assertion matches the canonical
|
|
38
|
+
* `not exists (select 1 from T [where P])` shape with a base-table target
|
|
39
|
+
* and a determinist column-only predicate. Otherwise `undefined`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function classifyAssertionForHoisting(assertion: IntegrityAssertionSchema, schemaManager: SchemaManager): AssertionHoistCandidate | undefined;
|
|
42
|
+
export { collectColumnNames };
|
|
43
|
+
/**
|
|
44
|
+
* AST-level NOT pusher. Mirrors `predicate-normalizer.ts:pushNotDown` in
|
|
45
|
+
* spirit but operates on `AST.Expression` instead of `ScalarPlanNode`. The
|
|
46
|
+
* result is fed back into `extractCheckConstraints`, which understands ANDs,
|
|
47
|
+
* comparisons, BETWEEN, and IN — so push NOT down so it ends up at the
|
|
48
|
+
* leaves where those recognizers can consume it.
|
|
49
|
+
*
|
|
50
|
+
* Rewrites (mirroring partial-unique's rejection rules where applicable):
|
|
51
|
+
* NOT (a AND b) → (NOT a) OR (NOT b)
|
|
52
|
+
* NOT (a OR b) → (NOT a) AND (NOT b)
|
|
53
|
+
* NOT (NOT x) → x
|
|
54
|
+
* NOT (a = b) → a <> b (and `==` ↦ <>)
|
|
55
|
+
* NOT (a <> b) → a = b (and `!=` ↦ =)
|
|
56
|
+
* NOT (a < b) → a >= b
|
|
57
|
+
* NOT (a <= b) → a > b
|
|
58
|
+
* NOT (a > b) → a <= b
|
|
59
|
+
* NOT (a >= b) → a < b
|
|
60
|
+
* NOT (a IS NULL) → a IS NOT NULL
|
|
61
|
+
* NOT (a IS NOT NULL) → a IS NULL
|
|
62
|
+
* NOT BETWEEN → flip the BetweenExpr.not flag
|
|
63
|
+
*
|
|
64
|
+
* `InExpr` has no `not` field in this AST (the parser lowers `NOT IN` to a
|
|
65
|
+
* `UnaryExpr` wrapping an `InExpr`), so negating an `InExpr` falls through to
|
|
66
|
+
* the wrap-in-NOT fallback. For any other shape the result is
|
|
67
|
+
* `{ type: 'unary', operator: 'NOT', ... }` — `extractCheckConstraints` will
|
|
68
|
+
* then ignore it, which is the safe outcome.
|
|
69
|
+
*/
|
|
70
|
+
export declare function negateAst(expr: AST.Expression): AST.Expression;
|
|
71
|
+
//# sourceMappingURL=assertion-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertion-classifier.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/assertion-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,WAAW,uBAAuB;IACvC,+DAA+D;IAC/D,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC;IACzC,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAID;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC3C,SAAS,EAAE,wBAAwB,EACnC,aAAa,EAAE,aAAa,GAC1B,uBAAuB,GAAG,SAAS,CA0ErC;AAyFD,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CA8D9D"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify a `create assertion` for optimizer-hoisting eligibility.
|
|
3
|
+
*
|
|
4
|
+
* Recognized canonical form (purely syntactic on the AST):
|
|
5
|
+
*
|
|
6
|
+
* not exists (select 1 from T [where P])
|
|
7
|
+
*
|
|
8
|
+
* where `T` is a base table (not a view, CTE, or TVF) and `P` references only
|
|
9
|
+
* columns of `T`. The negated predicate `not P` is hoisted onto `T` as if it
|
|
10
|
+
* were a per-row CHECK constraint — see ticket
|
|
11
|
+
* `3-optimizer-assertion-as-rewrite-premise` for the rationale.
|
|
12
|
+
*
|
|
13
|
+
* Anything outside this shape — existential `exists(...)`, aggregate
|
|
14
|
+
* `(select count(*) ...) = 0`, multi-table joins, non-deterministic calls,
|
|
15
|
+
* nested subqueries, view-targeted assertions, etc. — is silently rejected;
|
|
16
|
+
* the assertion falls through to commit-time enforcement, which remains the
|
|
17
|
+
* source of truth.
|
|
18
|
+
*/
|
|
19
|
+
import { containsNonDeterministicCall } from './check-extraction.js';
|
|
20
|
+
import { collectColumnNames } from './predicate-shape.js';
|
|
21
|
+
const allDeterministic = () => true;
|
|
22
|
+
/**
|
|
23
|
+
* Return a hoist candidate if the assertion matches the canonical
|
|
24
|
+
* `not exists (select 1 from T [where P])` shape with a base-table target
|
|
25
|
+
* and a determinist column-only predicate. Otherwise `undefined`.
|
|
26
|
+
*/
|
|
27
|
+
export function classifyAssertionForHoisting(assertion, schemaManager) {
|
|
28
|
+
const expr = assertion.checkExpression;
|
|
29
|
+
if (!expr)
|
|
30
|
+
return undefined;
|
|
31
|
+
// Outer: NOT. The parser preserves lexeme case verbatim, so we
|
|
32
|
+
// compare case-insensitively to handle both `NOT EXISTS` and `not exists`.
|
|
33
|
+
if (expr.type !== 'unary')
|
|
34
|
+
return undefined;
|
|
35
|
+
const outer = expr;
|
|
36
|
+
if (outer.operator.toUpperCase() !== 'NOT')
|
|
37
|
+
return undefined;
|
|
38
|
+
// Inner: EXISTS (...)
|
|
39
|
+
if (outer.expr.type !== 'exists')
|
|
40
|
+
return undefined;
|
|
41
|
+
const existsExpr = outer.expr;
|
|
42
|
+
const sel = existsExpr.subquery;
|
|
43
|
+
// Strict shape gates on the inner SELECT.
|
|
44
|
+
if (sel.compound)
|
|
45
|
+
return undefined;
|
|
46
|
+
if (sel.union)
|
|
47
|
+
return undefined;
|
|
48
|
+
if (sel.groupBy && sel.groupBy.length > 0)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (sel.having)
|
|
51
|
+
return undefined;
|
|
52
|
+
if (sel.orderBy && sel.orderBy.length > 0)
|
|
53
|
+
return undefined;
|
|
54
|
+
if (sel.limit)
|
|
55
|
+
return undefined;
|
|
56
|
+
if (sel.offset)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (sel.withClause)
|
|
59
|
+
return undefined;
|
|
60
|
+
// Single base-table FROM clause.
|
|
61
|
+
const fromClauses = sel.from;
|
|
62
|
+
if (!fromClauses || fromClauses.length !== 1)
|
|
63
|
+
return undefined;
|
|
64
|
+
const fromItem = fromClauses[0];
|
|
65
|
+
if (fromItem.type !== 'table')
|
|
66
|
+
return undefined;
|
|
67
|
+
const tableSource = fromItem;
|
|
68
|
+
// Resolve to a base TableSchema.
|
|
69
|
+
const tableSchema = schemaManager.findTable(tableSource.table.name, tableSource.table.schema);
|
|
70
|
+
if (!tableSchema)
|
|
71
|
+
return undefined;
|
|
72
|
+
// Unconditional-empty case is out of scope for this pilot — it would
|
|
73
|
+
// synthesize `check (false)` on T, which is correct but too aggressive
|
|
74
|
+
// without further safeguards.
|
|
75
|
+
const innerPredicate = sel.where;
|
|
76
|
+
if (!innerPredicate)
|
|
77
|
+
return undefined;
|
|
78
|
+
// The inner predicate may only reference columns of T (no correlated refs).
|
|
79
|
+
// `collectColumnNames` walks for column / identifier nodes that resolve via
|
|
80
|
+
// `columnIndexMap` — any unrecognized reference (column from a different
|
|
81
|
+
// table, qualified `other.x`, etc.) is silently excluded from the set, so
|
|
82
|
+
// we need to verify the predicate doesn't reference anything else. We do
|
|
83
|
+
// that by scanning for any column / identifier node that doesn't resolve.
|
|
84
|
+
if (predicateReferencesForeignColumns(innerPredicate, tableSchema.columnIndexMap)) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
// Non-determinism / subquery / aggregate gate. `containsNonDeterministicCall`
|
|
88
|
+
// rejects any subquery or exists node, which is exactly the conservative
|
|
89
|
+
// behaviour we want for the inner predicate (the OUTER `not exists` is
|
|
90
|
+
// fine — we already structurally matched it; we only check the inner
|
|
91
|
+
// predicate body here).
|
|
92
|
+
if (containsNonDeterministicCall(innerPredicate, allDeterministic)) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
// The whole inner predicate must not contain aggregates (functions like
|
|
96
|
+
// count/sum/min/max/avg). `allDeterministic` accepts every function, so we
|
|
97
|
+
// add a separate aggregate-reject pass.
|
|
98
|
+
if (containsAggregateCall(innerPredicate))
|
|
99
|
+
return undefined;
|
|
100
|
+
return {
|
|
101
|
+
baseTableQualifiedName: `${tableSchema.schemaName.toLowerCase()}.${tableSchema.name.toLowerCase()}`,
|
|
102
|
+
innerPredicate,
|
|
103
|
+
assertionName: assertion.name.toLowerCase(),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const AGGREGATE_NAMES = new Set([
|
|
107
|
+
'count', 'sum', 'avg', 'min', 'max',
|
|
108
|
+
'total', 'group_concat',
|
|
109
|
+
'json_group_array', 'json_group_object',
|
|
110
|
+
]);
|
|
111
|
+
function containsAggregateCall(expr) {
|
|
112
|
+
const stack = [expr];
|
|
113
|
+
while (stack.length > 0) {
|
|
114
|
+
const node = stack.pop();
|
|
115
|
+
if (node.type === 'function') {
|
|
116
|
+
const fn = node;
|
|
117
|
+
if (AGGREGATE_NAMES.has(fn.name.toLowerCase()))
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
for (const key of Object.keys(node)) {
|
|
121
|
+
const v = node[key];
|
|
122
|
+
if (!v)
|
|
123
|
+
continue;
|
|
124
|
+
if (Array.isArray(v)) {
|
|
125
|
+
for (const item of v) {
|
|
126
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
127
|
+
stack.push(item);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (typeof v === 'object' && 'type' in v) {
|
|
132
|
+
stack.push(v);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* True if any `column` / `identifier` node in `expr` does NOT resolve via the
|
|
140
|
+
* target table's `columnIndexMap`. Catches correlated references (`u.foo`
|
|
141
|
+
* where `u` is some other table) and qualified `schema.table.col` references
|
|
142
|
+
* that don't belong to the target table.
|
|
143
|
+
*/
|
|
144
|
+
function predicateReferencesForeignColumns(expr, columnIndexMap) {
|
|
145
|
+
const stack = [expr];
|
|
146
|
+
while (stack.length > 0) {
|
|
147
|
+
const node = stack.pop();
|
|
148
|
+
if (node.type === 'column') {
|
|
149
|
+
const col = node;
|
|
150
|
+
// Reject schema-qualified or foreign-table-qualified references.
|
|
151
|
+
if (col.schema)
|
|
152
|
+
return true;
|
|
153
|
+
if (col.table) {
|
|
154
|
+
// Could be the target table's name; accept only if resolves.
|
|
155
|
+
if (!columnIndexMap.has(col.name.toLowerCase()))
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
if (!columnIndexMap.has(col.name.toLowerCase()))
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else if (node.type === 'identifier') {
|
|
164
|
+
const id = node;
|
|
165
|
+
if (id.schema)
|
|
166
|
+
return true;
|
|
167
|
+
// Identifiers used as column references must resolve.
|
|
168
|
+
if (!columnIndexMap.has(id.name.toLowerCase())) {
|
|
169
|
+
// Identifier could also be e.g. a function-call name nested under a
|
|
170
|
+
// `function` node — those are visited via the function node itself,
|
|
171
|
+
// not as direct identifiers in expression position. Be conservative:
|
|
172
|
+
// reject the assertion. The conservative path matches the rest of
|
|
173
|
+
// the classifier — when in doubt, fall through to commit-time
|
|
174
|
+
// enforcement.
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const key of Object.keys(node)) {
|
|
179
|
+
// Skip identifier name nodes wrapped inside function calls (already handled).
|
|
180
|
+
const v = node[key];
|
|
181
|
+
if (!v)
|
|
182
|
+
continue;
|
|
183
|
+
if (Array.isArray(v)) {
|
|
184
|
+
for (const item of v) {
|
|
185
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
186
|
+
stack.push(item);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else if (typeof v === 'object' && 'type' in v) {
|
|
191
|
+
stack.push(v);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
// Re-export for tests / callers that want to drive these directly.
|
|
198
|
+
export { collectColumnNames };
|
|
199
|
+
/**
|
|
200
|
+
* AST-level NOT pusher. Mirrors `predicate-normalizer.ts:pushNotDown` in
|
|
201
|
+
* spirit but operates on `AST.Expression` instead of `ScalarPlanNode`. The
|
|
202
|
+
* result is fed back into `extractCheckConstraints`, which understands ANDs,
|
|
203
|
+
* comparisons, BETWEEN, and IN — so push NOT down so it ends up at the
|
|
204
|
+
* leaves where those recognizers can consume it.
|
|
205
|
+
*
|
|
206
|
+
* Rewrites (mirroring partial-unique's rejection rules where applicable):
|
|
207
|
+
* NOT (a AND b) → (NOT a) OR (NOT b)
|
|
208
|
+
* NOT (a OR b) → (NOT a) AND (NOT b)
|
|
209
|
+
* NOT (NOT x) → x
|
|
210
|
+
* NOT (a = b) → a <> b (and `==` ↦ <>)
|
|
211
|
+
* NOT (a <> b) → a = b (and `!=` ↦ =)
|
|
212
|
+
* NOT (a < b) → a >= b
|
|
213
|
+
* NOT (a <= b) → a > b
|
|
214
|
+
* NOT (a > b) → a <= b
|
|
215
|
+
* NOT (a >= b) → a < b
|
|
216
|
+
* NOT (a IS NULL) → a IS NOT NULL
|
|
217
|
+
* NOT (a IS NOT NULL) → a IS NULL
|
|
218
|
+
* NOT BETWEEN → flip the BetweenExpr.not flag
|
|
219
|
+
*
|
|
220
|
+
* `InExpr` has no `not` field in this AST (the parser lowers `NOT IN` to a
|
|
221
|
+
* `UnaryExpr` wrapping an `InExpr`), so negating an `InExpr` falls through to
|
|
222
|
+
* the wrap-in-NOT fallback. For any other shape the result is
|
|
223
|
+
* `{ type: 'unary', operator: 'NOT', ... }` — `extractCheckConstraints` will
|
|
224
|
+
* then ignore it, which is the safe outcome.
|
|
225
|
+
*/
|
|
226
|
+
export function negateAst(expr) {
|
|
227
|
+
if (expr.type === 'unary') {
|
|
228
|
+
const u = expr;
|
|
229
|
+
const uOp = u.operator.toUpperCase();
|
|
230
|
+
if (uOp === 'NOT') {
|
|
231
|
+
// Double-negation eliminates.
|
|
232
|
+
return u.expr;
|
|
233
|
+
}
|
|
234
|
+
if (uOp === 'IS NULL') {
|
|
235
|
+
return { type: 'unary', operator: 'IS NOT NULL', expr: u.expr };
|
|
236
|
+
}
|
|
237
|
+
if (uOp === 'IS NOT NULL') {
|
|
238
|
+
return { type: 'unary', operator: 'IS NULL', expr: u.expr };
|
|
239
|
+
}
|
|
240
|
+
// Fall through to the wrap-in-NOT fallback.
|
|
241
|
+
}
|
|
242
|
+
if (expr.type === 'binary') {
|
|
243
|
+
const b = expr;
|
|
244
|
+
const op = b.operator.toUpperCase();
|
|
245
|
+
switch (op) {
|
|
246
|
+
case 'AND':
|
|
247
|
+
return {
|
|
248
|
+
type: 'binary',
|
|
249
|
+
operator: 'OR',
|
|
250
|
+
left: negateAst(b.left),
|
|
251
|
+
right: negateAst(b.right),
|
|
252
|
+
};
|
|
253
|
+
case 'OR':
|
|
254
|
+
return {
|
|
255
|
+
type: 'binary',
|
|
256
|
+
operator: 'AND',
|
|
257
|
+
left: negateAst(b.left),
|
|
258
|
+
right: negateAst(b.right),
|
|
259
|
+
};
|
|
260
|
+
case '=':
|
|
261
|
+
case '==':
|
|
262
|
+
return { type: 'binary', operator: '<>', left: b.left, right: b.right };
|
|
263
|
+
case '<>':
|
|
264
|
+
case '!=':
|
|
265
|
+
return { type: 'binary', operator: '=', left: b.left, right: b.right };
|
|
266
|
+
case '<':
|
|
267
|
+
return { type: 'binary', operator: '>=', left: b.left, right: b.right };
|
|
268
|
+
case '<=':
|
|
269
|
+
return { type: 'binary', operator: '>', left: b.left, right: b.right };
|
|
270
|
+
case '>':
|
|
271
|
+
return { type: 'binary', operator: '<=', left: b.left, right: b.right };
|
|
272
|
+
case '>=':
|
|
273
|
+
return { type: 'binary', operator: '<', left: b.left, right: b.right };
|
|
274
|
+
default:
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (expr.type === 'between') {
|
|
279
|
+
const bt = expr;
|
|
280
|
+
return { ...bt, not: !bt.not };
|
|
281
|
+
}
|
|
282
|
+
// Fallback: wrap in a fresh NOT. `extractCheckConstraints` ignores top-level
|
|
283
|
+
// NOT, so this contributes nothing — the safe outcome for unrecognized shapes.
|
|
284
|
+
return { type: 'unary', operator: 'NOT', expr };
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=assertion-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertion-classifier.js","sourceRoot":"","sources":["../../../../src/planner/analysis/assertion-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-table hoist of "trivially universal" `create assertion` predicates into
|
|
3
|
+
* FD / EC / constant-binding / domain-constraint contributions. Reuses ticket
|
|
4
|
+
* #1's `extractCheckConstraints` walker via a synthetic `RowConstraintSchema`
|
|
5
|
+
* whose `expr` is the negated inner predicate from the assertion's canonical
|
|
6
|
+
* `not exists (select 1 from T [where P])` shape.
|
|
7
|
+
*
|
|
8
|
+
* Cached per (SchemaManager, TableSchema). Invalidated by schema-change
|
|
9
|
+
* events: any `assertion_*` event bumps a generation counter; lookups whose
|
|
10
|
+
* cached generation is stale recompute. Table-side invalidation rides on
|
|
11
|
+
* `TableSchema` identity — ALTER TABLE swaps the schema instance, which is
|
|
12
|
+
* the cache key.
|
|
13
|
+
*
|
|
14
|
+
* Soundness: hoisted facts add to the optimizer's premises; they NEVER
|
|
15
|
+
* suppress commit-time assertion enforcement (that remains the source of
|
|
16
|
+
* truth in `AssertionEvaluator`).
|
|
17
|
+
*/
|
|
18
|
+
import type { ConstantBinding, DomainConstraint, FunctionalDependency } from '../nodes/plan-node.js';
|
|
19
|
+
import type { TableSchema } from '../../schema/table.js';
|
|
20
|
+
import type { SchemaManager } from '../../schema/manager.js';
|
|
21
|
+
export interface HoistedConstraintsForTable {
|
|
22
|
+
readonly fds: ReadonlyArray<FunctionalDependency>;
|
|
23
|
+
readonly equivPairs: ReadonlyArray<readonly [number, number]>;
|
|
24
|
+
readonly constantBindings: ReadonlyArray<ConstantBinding>;
|
|
25
|
+
readonly domainConstraints: ReadonlyArray<DomainConstraint>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build (or look up) the hoisted constraint contributions for `table` derived
|
|
29
|
+
* from every qualifying `create assertion` known to `schemaManager`. Safe to
|
|
30
|
+
* call from `TableReferenceNode.computePhysical` — results are cached per
|
|
31
|
+
* (manager, table-instance) and invalidated by assertion schema-change events.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAssertionHoistedConstraints(schemaManager: SchemaManager, table: TableSchema): HoistedConstraintsForTable;
|
|
34
|
+
//# sourceMappingURL=assertion-hoist-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertion-hoist-cache.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/assertion-hoist-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EACX,eAAe,EAEf,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAkC,MAAM,uBAAuB,CAAC;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAO7D,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,gBAAgB,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC1D,QAAQ,CAAC,iBAAiB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC5D;AAgDD;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC7C,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,WAAW,GAChB,0BAA0B,CAmE5B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-table hoist of "trivially universal" `create assertion` predicates into
|
|
3
|
+
* FD / EC / constant-binding / domain-constraint contributions. Reuses ticket
|
|
4
|
+
* #1's `extractCheckConstraints` walker via a synthetic `RowConstraintSchema`
|
|
5
|
+
* whose `expr` is the negated inner predicate from the assertion's canonical
|
|
6
|
+
* `not exists (select 1 from T [where P])` shape.
|
|
7
|
+
*
|
|
8
|
+
* Cached per (SchemaManager, TableSchema). Invalidated by schema-change
|
|
9
|
+
* events: any `assertion_*` event bumps a generation counter; lookups whose
|
|
10
|
+
* cached generation is stale recompute. Table-side invalidation rides on
|
|
11
|
+
* `TableSchema` identity — ALTER TABLE swaps the schema instance, which is
|
|
12
|
+
* the cache key.
|
|
13
|
+
*
|
|
14
|
+
* Soundness: hoisted facts add to the optimizer's premises; they NEVER
|
|
15
|
+
* suppress commit-time assertion enforcement (that remains the source of
|
|
16
|
+
* truth in `AssertionEvaluator`).
|
|
17
|
+
*/
|
|
18
|
+
import { createLogger } from '../../common/logger.js';
|
|
19
|
+
import { extractCheckConstraints } from './check-extraction.js';
|
|
20
|
+
import { classifyAssertionForHoisting, negateAst } from './assertion-classifier.js';
|
|
21
|
+
const log = createLogger('planner:analysis:assertion-hoist');
|
|
22
|
+
const EMPTY = {
|
|
23
|
+
fds: [],
|
|
24
|
+
equivPairs: [],
|
|
25
|
+
constantBindings: [],
|
|
26
|
+
domainConstraints: [],
|
|
27
|
+
};
|
|
28
|
+
const registries = new WeakMap();
|
|
29
|
+
function getRegistry(schemaManager) {
|
|
30
|
+
let reg = registries.get(schemaManager);
|
|
31
|
+
if (reg)
|
|
32
|
+
return reg;
|
|
33
|
+
const newReg = {
|
|
34
|
+
generation: 0,
|
|
35
|
+
cache: new WeakMap(),
|
|
36
|
+
unsubscribe: () => undefined,
|
|
37
|
+
};
|
|
38
|
+
const notifier = schemaManager.getChangeNotifier();
|
|
39
|
+
newReg.unsubscribe = notifier.addListener((event) => {
|
|
40
|
+
if (event.type === 'assertion_added' ||
|
|
41
|
+
event.type === 'assertion_removed' ||
|
|
42
|
+
event.type === 'assertion_modified') {
|
|
43
|
+
newReg.generation++;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
registries.set(schemaManager, newReg);
|
|
47
|
+
reg = newReg;
|
|
48
|
+
return reg;
|
|
49
|
+
}
|
|
50
|
+
const allDeterministic = () => true;
|
|
51
|
+
/**
|
|
52
|
+
* Build (or look up) the hoisted constraint contributions for `table` derived
|
|
53
|
+
* from every qualifying `create assertion` known to `schemaManager`. Safe to
|
|
54
|
+
* call from `TableReferenceNode.computePhysical` — results are cached per
|
|
55
|
+
* (manager, table-instance) and invalidated by assertion schema-change events.
|
|
56
|
+
*/
|
|
57
|
+
export function getAssertionHoistedConstraints(schemaManager, table) {
|
|
58
|
+
// Re-entrancy guard: when AssertionEvaluator is compiling an assertion's
|
|
59
|
+
// own violation query, returning the hoisted facts would let the optimizer
|
|
60
|
+
// fold the violation query to empty (the assertion's claim would prove
|
|
61
|
+
// itself), defeating commit-time enforcement. Skip the cache entirely so
|
|
62
|
+
// non-suppressed lookups continue to see fully-hoisted results.
|
|
63
|
+
if (schemaManager.isAssertionHoistSuppressed()) {
|
|
64
|
+
return EMPTY;
|
|
65
|
+
}
|
|
66
|
+
const reg = getRegistry(schemaManager);
|
|
67
|
+
const cached = reg.cache.get(table);
|
|
68
|
+
if (cached && cached.generation === reg.generation) {
|
|
69
|
+
return cached.value;
|
|
70
|
+
}
|
|
71
|
+
const targetName = `${table.schemaName.toLowerCase()}.${table.name.toLowerCase()}`;
|
|
72
|
+
const synthChecks = [];
|
|
73
|
+
const provenanceByCheckIdx = [];
|
|
74
|
+
for (const assertion of schemaManager.getAllAssertions()) {
|
|
75
|
+
const candidate = classifyAssertionForHoisting(assertion, schemaManager);
|
|
76
|
+
if (!candidate)
|
|
77
|
+
continue;
|
|
78
|
+
if (candidate.baseTableQualifiedName !== targetName)
|
|
79
|
+
continue;
|
|
80
|
+
if (!candidate.innerPredicate)
|
|
81
|
+
continue;
|
|
82
|
+
// Synthetic check on T: per-row `not P`. `operations` is unused by
|
|
83
|
+
// extractCheckConstraints; defaulting to 0 is safe.
|
|
84
|
+
synthChecks.push({
|
|
85
|
+
name: `__assertion_${candidate.assertionName}`,
|
|
86
|
+
expr: negateAst(candidate.innerPredicate),
|
|
87
|
+
operations: 0,
|
|
88
|
+
});
|
|
89
|
+
provenanceByCheckIdx.push({ kind: 'assertion', name: candidate.assertionName });
|
|
90
|
+
log('Hoisted assertion %s onto %s', candidate.assertionName, targetName);
|
|
91
|
+
}
|
|
92
|
+
let result = EMPTY;
|
|
93
|
+
if (synthChecks.length > 0) {
|
|
94
|
+
// Run each synthetic check separately so we can tag provenance per
|
|
95
|
+
// assertion. (extractCheckConstraints iterates checks but does not
|
|
96
|
+
// surface which check produced which fact.)
|
|
97
|
+
const fds = [];
|
|
98
|
+
const equivPairs = [];
|
|
99
|
+
const constantBindings = [];
|
|
100
|
+
const domainConstraints = [];
|
|
101
|
+
for (let i = 0; i < synthChecks.length; i++) {
|
|
102
|
+
const prov = provenanceByCheckIdx[i];
|
|
103
|
+
const ext = extractCheckConstraints([synthChecks[i]], table.columnIndexMap, allDeterministic);
|
|
104
|
+
for (const fd of ext.fds)
|
|
105
|
+
fds.push({ ...fd, source: prov });
|
|
106
|
+
for (const p of ext.equivPairs)
|
|
107
|
+
equivPairs.push(p);
|
|
108
|
+
for (const b of ext.constantBindings)
|
|
109
|
+
constantBindings.push({ ...b, source: prov });
|
|
110
|
+
for (const d of ext.domainConstraints) {
|
|
111
|
+
domainConstraints.push({ ...d, source: prov });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
result = { fds, equivPairs, constantBindings, domainConstraints };
|
|
115
|
+
}
|
|
116
|
+
reg.cache.set(table, { generation: reg.generation, value: result });
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=assertion-hoist-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertion-hoist-cache.js","sourceRoot":"","sources":["../../../../src/planner/analysis/assertion-hoist-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binding-key extraction for incremental delta planning.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `analyzeRowSpecific` and packages its per-relation classifications
|
|
5
|
+
* into a `BindingMode` per `TableReferenceNode` instance. The shape is
|
|
6
|
+
* consumer-neutral — assertions, materialized views, and any other change-
|
|
7
|
+
* driven consumer can register a `DeltaSubscription` against the same
|
|
8
|
+
* `PlanBindings`.
|
|
9
|
+
*
|
|
10
|
+
* - 'row' bindings carry the unique-key columns to bind on (PK preferred,
|
|
11
|
+
* else the lex-min covered key under FD closure).
|
|
12
|
+
* - 'group' bindings carry the minimal GROUP BY columns recovered from
|
|
13
|
+
* `analyzeRowSpecific.groupKeys`.
|
|
14
|
+
* - 'global' bindings carry no extra metadata — the consumer evaluates its
|
|
15
|
+
* plan once for any dependency change.
|
|
16
|
+
*/
|
|
17
|
+
import { PlanNode, type RelationalPlanNode } from '../nodes/plan-node.js';
|
|
18
|
+
/**
|
|
19
|
+
* The way one plan instance binds to its changes.
|
|
20
|
+
*
|
|
21
|
+
* - `'global'`: the plan re-runs once when any dependency table changes.
|
|
22
|
+
* - `'row'`: the plan binds on `keyColumns` (output-column indices on the
|
|
23
|
+
* table reference). Consumers parameterize per changed PK tuple.
|
|
24
|
+
* - `'group'`: the plan binds on `groupColumns` (output-column indices on
|
|
25
|
+
* the table reference). Consumers parameterize per changed group-key
|
|
26
|
+
* tuple, including OLD and NEW projections when group membership shifts.
|
|
27
|
+
*/
|
|
28
|
+
export type BindingMode = {
|
|
29
|
+
kind: 'global';
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'row';
|
|
32
|
+
keyColumns: number[];
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'group';
|
|
35
|
+
groupColumns: number[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Per-`TableReferenceNode` binding info for a plan, plus a quick lookup
|
|
39
|
+
* from `relationKey` to the qualified base table name (lowercased).
|
|
40
|
+
*/
|
|
41
|
+
export interface PlanBindings {
|
|
42
|
+
/** For each TableReference instance in the plan, how this plan is bound to its changes. */
|
|
43
|
+
perRelation: Map<string, BindingMode>;
|
|
44
|
+
/** Convenience: relationKey → base table name (lowercased `schema.table`). */
|
|
45
|
+
relationToBase: Map<string, string>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Walk a plan and emit the per-`TableReferenceNode` binding modes the runtime
|
|
49
|
+
* needs to parameterize a delta-driven consumer over the same plan.
|
|
50
|
+
*
|
|
51
|
+
* The selection rule for `'row'` matches what the assertion path already
|
|
52
|
+
* picks: prefer the primary key when it's covered, else fall back to the
|
|
53
|
+
* first covered unique key (lex-min by column index). For `'group'`,
|
|
54
|
+
* `groupKeys.get(relKey)` from `analyzeRowSpecific` is copied through
|
|
55
|
+
* verbatim — already in the table reference's output-column space.
|
|
56
|
+
*/
|
|
57
|
+
export declare function extractBindings(plan: PlanNode | RelationalPlanNode): PlanBindings;
|
|
58
|
+
//# sourceMappingURL=binding-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binding-extractor.d.ts","sourceRoot":"","sources":["../../../../src/planner/analysis/binding-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAI1E;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,2FAA2F;IAC3F,WAAW,EAAE,GAAG,CAAC,MAAM,EAAoB,WAAW,CAAC,CAAC;IACxD,8EAA8E;IAC9E,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,kBAAkB,GAAG,YAAY,CA6CjF"}
|