@quereus/quereus 2.8.0 → 3.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 +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/emit/ast-stringify.d.ts.map +1 -1
- package/dist/src/emit/ast-stringify.js +0 -3
- package/dist/src/emit/ast-stringify.js.map +1 -1
- 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/ast.d.ts +3 -2
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +25 -8
- 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 +169 -92
- 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/foreign-key-builder.d.ts.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.js +3 -2
- package/dist/src/planner/building/foreign-key-builder.js.map +1 -1
- package/dist/src/planner/building/select.js +14 -2
- package/dist/src/planner/building/select.js.map +1 -1
- 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/building/update.d.ts.map +1 -1
- package/dist/src/planner/building/update.js +10 -6
- package/dist/src/planner/building/update.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +13 -2
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/characteristics.js +31 -5
- 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 +46 -16
- package/dist/src/planner/framework/pass.js.map +1 -1
- package/dist/src/planner/framework/physical-utils.d.ts +21 -9
- package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
- package/dist/src/planner/framework/physical-utils.js +47 -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 +8 -1
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.d.ts +137 -0
- package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/asof-scan-node.js +237 -0
- package/dist/src/planner/nodes/asof-scan-node.js.map +1 -0
- 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/constraint-check-node.d.ts +3 -0
- package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/constraint-check-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 +17 -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 +67 -5
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/function.d.ts +11 -1
- package/dist/src/planner/nodes/function.d.ts.map +1 -1
- package/dist/src/planner/nodes/function.js +94 -1
- package/dist/src/planner/nodes/function.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 +10 -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 +21 -10
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +42 -1
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +132 -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 +8 -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 +22 -9
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts +50 -0
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/ordinal-slice-node.js +130 -0
- package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts +3 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +3 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +316 -5
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js +49 -0
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +78 -28
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts +27 -2
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +117 -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 +8 -1
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +112 -1
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts +2 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.js +24 -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 +28 -1
- 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 +10 -8
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +40 -5
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +113 -18
- 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/update-node.d.ts +1 -3
- package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/update-node.js +3 -9
- package/dist/src/planner/nodes/update-node.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts +61 -2
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +71 -3
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer-tuning.d.ts +38 -1
- package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
- package/dist/src/planner/optimizer-tuning.js +6 -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 +278 -0
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/rules/access/rule-asof-strategy-select.d.ts +30 -0
- package/dist/src/planner/rules/access/rule-asof-strategy-select.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-asof-strategy-select.js +112 -0
- package/dist/src/planner/rules/access/rule-asof-strategy-select.js.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.d.ts +33 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.js +162 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.js.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts +29 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js +175 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-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 +53 -17
- 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/equi-pair-extractor.d.ts +61 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.js +155 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -0
- 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/join/rule-join-physical-selection.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.js +2 -122
- 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 +21 -0
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.js +405 -0
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.js.map +1 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts +31 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +113 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -0
- 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/rules/window/rule-monotonic-window.d.ts +47 -0
- package/dist/src/planner/rules/window/rule-monotonic-window.d.ts.map +1 -0
- package/dist/src/planner/rules/window/rule-monotonic-window.js +341 -0
- package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -0
- 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/context-helpers.d.ts +9 -0
- package/dist/src/runtime/context-helpers.d.ts.map +1 -1
- package/dist/src/runtime/context-helpers.js +5 -0
- package/dist/src/runtime/context-helpers.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 +52 -16
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/asof-scan.d.ts +10 -0
- package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -0
- package/dist/src/runtime/emit/asof-scan.js +467 -0
- package/dist/src/runtime/emit/asof-scan.js.map +1 -0
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +20 -0
- package/dist/src/runtime/emit/constraint-check.js.map +1 -1
- package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-assertion.js +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 +40 -13
- 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/emit/ordinal-slice.d.ts +13 -0
- package/dist/src/runtime/emit/ordinal-slice.d.ts.map +1 -0
- package/dist/src/runtime/emit/ordinal-slice.js +89 -0
- package/dist/src/runtime/emit/ordinal-slice.js.map +1 -0
- package/dist/src/runtime/emit/returning.d.ts.map +1 -1
- package/dist/src/runtime/emit/returning.js +9 -4
- package/dist/src/runtime/emit/returning.js.map +1 -1
- package/dist/src/runtime/emit/scan.d.ts +19 -3
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +12 -8
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.js +91 -14
- package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
- package/dist/src/runtime/emit/window.d.ts.map +1 -1
- package/dist/src/runtime/emit/window.js +732 -37
- package/dist/src/runtime/emit/window.js.map +1 -1
- package/dist/src/runtime/foreign-key-actions.d.ts +16 -0
- package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -1
- package/dist/src/runtime/foreign-key-actions.js +86 -5
- 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 +6 -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/catalog.d.ts +10 -0
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +29 -6
- package/dist/src/schema/catalog.js.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 +89 -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 +43 -0
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +105 -4
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
- package/dist/src/schema/rename-rewriter.js +303 -102
- package/dist/src/schema/rename-rewriter.js.map +1 -1
- package/dist/src/schema/schema-differ.d.ts +18 -1
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +307 -42
- package/dist/src/schema/schema-differ.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/logical-type.d.ts +11 -0
- package/dist/src/types/logical-type.d.ts.map +1 -1
- package/dist/src/types/logical-type.js.map +1 -1
- package/dist/src/types/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/util/ast-literal.d.ts +11 -0
- package/dist/src/util/ast-literal.d.ts.map +1 -0
- package/dist/src/util/ast-literal.js +26 -0
- package/dist/src/util/ast-literal.js.map +1 -0
- package/dist/src/vtab/best-access-plan.d.ts +41 -0
- package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
- package/dist/src/vtab/best-access-plan.js +29 -0
- package/dist/src/vtab/best-access-plan.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/filter-info.d.ts +14 -0
- package/dist/src/vtab/filter-info.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +24 -5
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +39 -1
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +206 -44
- package/dist/src/vtab/memory/module.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/dist/src/vtab/module.d.ts +24 -0
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-monotonic-merge-join.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-monotonic-merge-join.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAA6B,MAAM,0BAA0B,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAU7D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAwF5F"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Monotonic Merge Join
|
|
3
|
+
*
|
|
4
|
+
* Required Characteristics:
|
|
5
|
+
* - Node must be a logical JoinNode (not already physical)
|
|
6
|
+
* - Both inputs advertise `MonotonicOn` on (at least) one of the equi-pair
|
|
7
|
+
* attributes, with matching direction (ASC for v1, since the merge-join
|
|
8
|
+
* emitter assumes ASC ordering).
|
|
9
|
+
*
|
|
10
|
+
* Why this rule exists alongside `rule-join-physical-selection`:
|
|
11
|
+
* The existing rule chooses merge-join when both sources' `physical.ordering`
|
|
12
|
+
* matches the equi-pair attribute order positionally. That misses the canonical
|
|
13
|
+
* case where a merge-join's *output* declares `monotonicOn = [l.X, r.X]` but
|
|
14
|
+
* `ordering` reflects only the left side — a parent join on `r.X` then sees
|
|
15
|
+
* the right ordering implicitly through `monotonicOn` but not through
|
|
16
|
+
* `ordering[0]`. This rule looks the equi-pair attrs up directly in
|
|
17
|
+
* `monotonicOn`, recognising those (and other future MonotonicOn-propagating
|
|
18
|
+
* paths) without sorting.
|
|
19
|
+
*
|
|
20
|
+
* Out of scope (TODO):
|
|
21
|
+
* - Composite monotonic-on prefixes (multi-key streaming merge keyed on
|
|
22
|
+
* `(X, Y)` when both sides are jointly monotonic on the prefix).
|
|
23
|
+
* - Right and full outer joins — emitter doesn't support them today.
|
|
24
|
+
* - Recognising `monotonicOn(asc)` vs `monotonicOn(desc)` by reversing one
|
|
25
|
+
* side via Sort. That defeats this rule's premise (the rule's whole point is
|
|
26
|
+
* that no sort is needed because both sides are already monotonic).
|
|
27
|
+
*/
|
|
28
|
+
import { createLogger } from '../../../common/logger.js';
|
|
29
|
+
import { JoinNode } from '../../nodes/join-node.js';
|
|
30
|
+
import { MergeJoinNode } from '../../nodes/merge-join-node.js';
|
|
31
|
+
import { nestedLoopJoinCost, hashJoinCost, mergeJoinCost } from '../../cost/index.js';
|
|
32
|
+
import { PlanNodeCharacteristics } from '../../framework/characteristics.js';
|
|
33
|
+
import { extractEquiPairs, extractEquiPairsFromUsing, combineResidual, isMergeReadyOnAllPairs } from './equi-pair-extractor.js';
|
|
34
|
+
const log = createLogger('optimizer:rule:monotonic-merge-join');
|
|
35
|
+
export function ruleMonotonicMergeJoin(node, _context) {
|
|
36
|
+
if (!(node instanceof JoinNode))
|
|
37
|
+
return null;
|
|
38
|
+
const joinType = node.joinType;
|
|
39
|
+
if (joinType !== 'inner' && joinType !== 'left' && joinType !== 'semi' && joinType !== 'anti')
|
|
40
|
+
return null;
|
|
41
|
+
const leftAttrs = node.left.getAttributes();
|
|
42
|
+
const rightAttrs = node.right.getAttributes();
|
|
43
|
+
const leftAttrIds = new Set(leftAttrs.map(a => a.id));
|
|
44
|
+
const rightAttrIds = new Set(rightAttrs.map(a => a.id));
|
|
45
|
+
const extracted = node.condition
|
|
46
|
+
? extractEquiPairs(node.condition, leftAttrIds, rightAttrIds)
|
|
47
|
+
: extractEquiPairsFromUsing(node.usingColumns, leftAttrs, rightAttrs);
|
|
48
|
+
if (!extracted || extracted.equiPairs.length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
// Defer to `rule-join-physical-selection` whenever both sides' physical
|
|
51
|
+
// ordering already covers ALL equi-pairs in merge-ready order. The
|
|
52
|
+
// ordering-based path produces a multi-key merge join with full
|
|
53
|
+
// unique-key propagation; demoting pairs to residual here would lose that
|
|
54
|
+
// propagation. Our rule is meant to *extend* recognition, not regress it.
|
|
55
|
+
if (isMergeReadyOnAllPairs(node.left, node.right, extracted.equiPairs))
|
|
56
|
+
return null;
|
|
57
|
+
const leftMon = PlanNodeCharacteristics.getMonotonicOn(node.left);
|
|
58
|
+
const rightMon = PlanNodeCharacteristics.getMonotonicOn(node.right);
|
|
59
|
+
if (leftMon.length === 0 || rightMon.length === 0)
|
|
60
|
+
return null;
|
|
61
|
+
// Find equi-pairs where BOTH sides are MonotonicOn on their respective
|
|
62
|
+
// attrId with matching direction. v1 requires ASC because the merge-join
|
|
63
|
+
// emitter assumes ASC; DESC-DESC streaming would need a reversed compareKeys.
|
|
64
|
+
const matchedIndices = [];
|
|
65
|
+
for (let i = 0; i < extracted.equiPairs.length; i++) {
|
|
66
|
+
const pair = extracted.equiPairs[i];
|
|
67
|
+
const l = leftMon.find(m => m.attrId === pair.leftAttrId && m.direction === 'asc');
|
|
68
|
+
if (!l)
|
|
69
|
+
continue;
|
|
70
|
+
const r = rightMon.find(m => m.attrId === pair.rightAttrId && m.direction === 'asc');
|
|
71
|
+
if (!r)
|
|
72
|
+
continue;
|
|
73
|
+
matchedIndices.push(i);
|
|
74
|
+
}
|
|
75
|
+
if (matchedIndices.length === 0)
|
|
76
|
+
return null;
|
|
77
|
+
// v1: pick a single driving equi-pair. Other equi-pairs (matched or not)
|
|
78
|
+
// must be evaluated as residual conjuncts — the merge-join emitter assumes
|
|
79
|
+
// the right side is sorted lexicographically across ALL listed equi-pair
|
|
80
|
+
// columns, which we cannot guarantee for non-driving keys.
|
|
81
|
+
// TODO: composite monotonic-on prefixes — recognise when both sides are
|
|
82
|
+
// jointly MonotonicOn on a multi-key prefix and use multiple driving keys.
|
|
83
|
+
const drivingIndex = matchedIndices[0];
|
|
84
|
+
const driving = [extracted.equiPairs[drivingIndex]];
|
|
85
|
+
// Residualize the rest. For pairs that originated from a real `=` BinaryOpNode
|
|
86
|
+
// (ON-condition path), reuse the original node. For USING-derived pairs,
|
|
87
|
+
// `equiPairNodes[i]` is undefined — bail out and let the existing
|
|
88
|
+
// ordering-based rule handle USING-with-multiple-pairs.
|
|
89
|
+
const extras = [];
|
|
90
|
+
for (let i = 0; i < extracted.equiPairs.length; i++) {
|
|
91
|
+
if (i === drivingIndex)
|
|
92
|
+
continue;
|
|
93
|
+
const orig = extracted.equiPairNodes[i];
|
|
94
|
+
if (!orig)
|
|
95
|
+
return null;
|
|
96
|
+
extras.push(orig);
|
|
97
|
+
}
|
|
98
|
+
const residual = combineResidual(extracted.residual, extras);
|
|
99
|
+
// Cost gate: even with the precondition met, hash or nested-loop may win
|
|
100
|
+
// on tiny inputs. Don't regress those.
|
|
101
|
+
const leftRows = node.left.estimatedRows ?? 100;
|
|
102
|
+
const rightRows = node.right.estimatedRows ?? 100;
|
|
103
|
+
const mergeC = mergeJoinCost(leftRows, rightRows, false, false);
|
|
104
|
+
const hashC = hashJoinCost(Math.min(leftRows, rightRows), Math.max(leftRows, rightRows));
|
|
105
|
+
const nlC = nestedLoopJoinCost(leftRows, rightRows);
|
|
106
|
+
if (Math.min(hashC, nlC) < mergeC) {
|
|
107
|
+
log('Skipping monotonic-merge: cheaper alternative exists (merge=%.2f, hash=%.2f, nl=%.2f)', mergeC, hashC, nlC);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
log('Selecting monotonic merge-join on equi-pair %d=%d (merge=%.2f, hash=%.2f, nl=%.2f)', driving[0].leftAttrId, driving[0].rightAttrId, mergeC, hashC, nlC);
|
|
111
|
+
return new MergeJoinNode(node.scope, node.left, node.right, joinType, driving, residual, node.getAttributes().slice());
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=rule-monotonic-merge-join.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-monotonic-merge-join.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-monotonic-merge-join.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Aggregate Predicate Pushdown
|
|
3
|
+
*
|
|
4
|
+
* Subsumes WHERE-on-group-by-column and HAVING-on-group-by-column. For a
|
|
5
|
+
* FilterNode(predicate, AggregateNode|StreamAggregateNode|HashAggregateNode)
|
|
6
|
+
* each conjunct of `predicate` that references only GROUP-BY columns (or
|
|
7
|
+
* columns FD-determined by them in the aggregate's output FDs) is rewritten
|
|
8
|
+
* onto the aggregate's source attribute IDs and moved below the aggregate.
|
|
9
|
+
* Conjuncts referencing aggregate outputs (sum/count/etc.) or non-column
|
|
10
|
+
* GROUP-BY expressions stay above.
|
|
11
|
+
*
|
|
12
|
+
* Aggregate output indices in `physical.fds` come exclusively from
|
|
13
|
+
* bare-`ColumnReferenceNode` GROUP BYs (per `propagateAggregateFds`), so every
|
|
14
|
+
* output column in the FD closure has a known source attribute and can be
|
|
15
|
+
* rewritten.
|
|
16
|
+
*/
|
|
17
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
18
|
+
import type { OptContext } from '../../framework/context.js';
|
|
19
|
+
export declare function ruleAggregatePredicatePushdown(node: PlanNode, _context: OptContext): PlanNode | null;
|
|
20
|
+
//# sourceMappingURL=rule-aggregate-predicate-pushdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-aggregate-predicate-pushdown.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-aggregate-predicate-pushdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAiD,MAAM,0BAA0B,CAAC;AAExG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAqB7D,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CA8EpG"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Aggregate Predicate Pushdown
|
|
3
|
+
*
|
|
4
|
+
* Subsumes WHERE-on-group-by-column and HAVING-on-group-by-column. For a
|
|
5
|
+
* FilterNode(predicate, AggregateNode|StreamAggregateNode|HashAggregateNode)
|
|
6
|
+
* each conjunct of `predicate` that references only GROUP-BY columns (or
|
|
7
|
+
* columns FD-determined by them in the aggregate's output FDs) is rewritten
|
|
8
|
+
* onto the aggregate's source attribute IDs and moved below the aggregate.
|
|
9
|
+
* Conjuncts referencing aggregate outputs (sum/count/etc.) or non-column
|
|
10
|
+
* GROUP-BY expressions stay above.
|
|
11
|
+
*
|
|
12
|
+
* Aggregate output indices in `physical.fds` come exclusively from
|
|
13
|
+
* bare-`ColumnReferenceNode` GROUP BYs (per `propagateAggregateFds`), so every
|
|
14
|
+
* output column in the FD closure has a known source attribute and can be
|
|
15
|
+
* rewritten.
|
|
16
|
+
*/
|
|
17
|
+
import { createLogger } from '../../../common/logger.js';
|
|
18
|
+
import { isRelationalNode } from '../../nodes/plan-node.js';
|
|
19
|
+
import { PlanNodeType } from '../../nodes/plan-node-type.js';
|
|
20
|
+
import { FilterNode } from '../../nodes/filter.js';
|
|
21
|
+
import { AggregateNode } from '../../nodes/aggregate-node.js';
|
|
22
|
+
import { StreamAggregateNode } from '../../nodes/stream-aggregate.js';
|
|
23
|
+
import { HashAggregateNode } from '../../nodes/hash-aggregate.js';
|
|
24
|
+
import { ColumnReferenceNode } from '../../nodes/reference.js';
|
|
25
|
+
import { normalizePredicate } from '../../analysis/predicate-normalizer.js';
|
|
26
|
+
import { splitConjuncts, combineConjuncts } from '../../analysis/predicate-conjuncts.js';
|
|
27
|
+
import { computeClosure } from '../../util/fd-utils.js';
|
|
28
|
+
const log = createLogger('optimizer:rule:aggregate-predicate-pushdown');
|
|
29
|
+
function isAggregateNode(node) {
|
|
30
|
+
return node instanceof AggregateNode
|
|
31
|
+
|| node instanceof StreamAggregateNode
|
|
32
|
+
|| node instanceof HashAggregateNode;
|
|
33
|
+
}
|
|
34
|
+
export function ruleAggregatePredicatePushdown(node, _context) {
|
|
35
|
+
if (node.nodeType !== PlanNodeType.Filter)
|
|
36
|
+
return null;
|
|
37
|
+
const filter = node;
|
|
38
|
+
if (!isAggregateNode(filter.source))
|
|
39
|
+
return null;
|
|
40
|
+
const agg = filter.source;
|
|
41
|
+
// Scalar aggregate (no GROUP BY): the predicate selects on the single output
|
|
42
|
+
// row, so nothing is pushable.
|
|
43
|
+
if (agg.groupBy.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
const aggAttrs = agg.getAttributes();
|
|
46
|
+
const sourceAttrs = agg.source.getAttributes();
|
|
47
|
+
// Build the output → source mapping for bare-column GROUP BYs. Aggregate
|
|
48
|
+
// output columns (indices ≥ groupCount) have no source mapping. Non-column
|
|
49
|
+
// GROUP BY expressions (`group_${i}`) also have no source mapping.
|
|
50
|
+
const outputToSource = new Map();
|
|
51
|
+
const groupByOutputIndices = new Set();
|
|
52
|
+
for (let i = 0; i < agg.groupBy.length; i++) {
|
|
53
|
+
const gbExpr = agg.groupBy[i];
|
|
54
|
+
if (!(gbExpr instanceof ColumnReferenceNode))
|
|
55
|
+
continue;
|
|
56
|
+
const outAttrId = aggAttrs[i].id;
|
|
57
|
+
const srcAttrId = gbExpr.attributeId;
|
|
58
|
+
const srcIdx = sourceAttrs.findIndex(a => a.id === srcAttrId);
|
|
59
|
+
if (srcIdx < 0)
|
|
60
|
+
continue;
|
|
61
|
+
outputToSource.set(outAttrId, { sourceAttrId: srcAttrId, sourceColIdx: srcIdx });
|
|
62
|
+
groupByOutputIndices.add(i);
|
|
63
|
+
}
|
|
64
|
+
if (outputToSource.size === 0)
|
|
65
|
+
return null;
|
|
66
|
+
// Map output attribute id → output column index, used to test FD closure
|
|
67
|
+
// membership.
|
|
68
|
+
const outAttrIdToIndex = new Map();
|
|
69
|
+
aggAttrs.forEach((a, i) => outAttrIdToIndex.set(a.id, i));
|
|
70
|
+
// FD closure on the aggregate's output indices, seeded by the bare-column
|
|
71
|
+
// GROUP BY output indices. With composite GROUP BYs and inherited source
|
|
72
|
+
// FDs, this can widen `outputToSource` membership to FD-dependent columns
|
|
73
|
+
// (which by `propagateAggregateFds`'s projection are themselves bare-column
|
|
74
|
+
// GROUP BY outputs and therefore already in `outputToSource`).
|
|
75
|
+
const aggFds = agg.physical.fds ?? [];
|
|
76
|
+
const pushableOutputIndices = computeClosure(groupByOutputIndices, aggFds);
|
|
77
|
+
// Normalize → split → partition conjuncts.
|
|
78
|
+
const normalized = normalizePredicate(filter.predicate);
|
|
79
|
+
const conjuncts = splitConjuncts(normalized);
|
|
80
|
+
const pushable = [];
|
|
81
|
+
const remaining = [];
|
|
82
|
+
for (const conj of conjuncts) {
|
|
83
|
+
if (isConjunctPushable(conj, outAttrIdToIndex, outputToSource, pushableOutputIndices)) {
|
|
84
|
+
pushable.push(conj);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
remaining.push(conj);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (pushable.length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
// Rewrite pushable conjuncts: rebind output column refs to source ones.
|
|
93
|
+
const rewrittenPushable = pushable.map(c => rewriteOutputToSource(c, outputToSource, sourceAttrs));
|
|
94
|
+
const pushedPredicate = combineConjuncts(rewrittenPushable);
|
|
95
|
+
const newSource = new FilterNode(agg.source.scope, agg.source, pushedPredicate);
|
|
96
|
+
// Rebuild the aggregate over the filtered source, preserving attribute IDs.
|
|
97
|
+
const newAgg = rebuildAggregate(agg, newSource);
|
|
98
|
+
log('Pushed %d/%d conjunct(s) below %s', pushable.length, conjuncts.length, agg.nodeType);
|
|
99
|
+
if (remaining.length === 0) {
|
|
100
|
+
return newAgg;
|
|
101
|
+
}
|
|
102
|
+
const residualPredicate = combineConjuncts(remaining);
|
|
103
|
+
return new FilterNode(filter.scope, newAgg, residualPredicate);
|
|
104
|
+
}
|
|
105
|
+
function isConjunctPushable(conj, outAttrIdToIndex, outputToSource, pushableOutputIndices) {
|
|
106
|
+
const referenced = collectReferencedAttributeIds(conj);
|
|
107
|
+
if (referenced.size === 0) {
|
|
108
|
+
// Constant conjunct: safe to push (and safe to keep above too — pushing
|
|
109
|
+
// reduces work below). Keep above to avoid spurious rule firings; the
|
|
110
|
+
// rule only "fires" when there's a real column-driven push.
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
for (const attrId of referenced) {
|
|
114
|
+
const idx = outAttrIdToIndex.get(attrId);
|
|
115
|
+
if (idx === undefined)
|
|
116
|
+
return false;
|
|
117
|
+
if (!pushableOutputIndices.has(idx))
|
|
118
|
+
return false;
|
|
119
|
+
// Every pushable index must have a source mapping for rewrite.
|
|
120
|
+
if (!outputToSource.has(attrId))
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
function collectReferencedAttributeIds(expr) {
|
|
126
|
+
const ids = new Set();
|
|
127
|
+
walkScalar(expr, n => {
|
|
128
|
+
if (n instanceof ColumnReferenceNode) {
|
|
129
|
+
ids.add(n.attributeId);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return ids;
|
|
133
|
+
}
|
|
134
|
+
function walkScalar(expr, fn) {
|
|
135
|
+
fn(expr);
|
|
136
|
+
for (const c of expr.getChildren()) {
|
|
137
|
+
if (!isRelationalNode(c)) {
|
|
138
|
+
walkScalar(c, fn);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function rewriteOutputToSource(expr, outputToSource, sourceAttrs) {
|
|
143
|
+
if (expr instanceof ColumnReferenceNode) {
|
|
144
|
+
const mapping = outputToSource.get(expr.attributeId);
|
|
145
|
+
if (mapping === undefined)
|
|
146
|
+
return expr;
|
|
147
|
+
const srcAttr = sourceAttrs.find(a => a.id === mapping.sourceAttrId);
|
|
148
|
+
// `sourceAttrs` was indexed against to build `outputToSource`; the lookup must hit.
|
|
149
|
+
if (!srcAttr)
|
|
150
|
+
return expr;
|
|
151
|
+
return new ColumnReferenceNode(expr.scope, expr.expression, srcAttr.type, mapping.sourceAttrId, mapping.sourceColIdx);
|
|
152
|
+
}
|
|
153
|
+
const children = expr.getChildren();
|
|
154
|
+
if (children.length === 0)
|
|
155
|
+
return expr;
|
|
156
|
+
const newChildren = [];
|
|
157
|
+
let changed = false;
|
|
158
|
+
for (const c of children) {
|
|
159
|
+
if (isRelationalNode(c)) {
|
|
160
|
+
newChildren.push(c);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const replaced = rewriteOutputToSource(c, outputToSource, sourceAttrs);
|
|
164
|
+
newChildren.push(replaced);
|
|
165
|
+
if (replaced !== c)
|
|
166
|
+
changed = true;
|
|
167
|
+
}
|
|
168
|
+
if (!changed)
|
|
169
|
+
return expr;
|
|
170
|
+
return expr.withChildren(newChildren);
|
|
171
|
+
}
|
|
172
|
+
function rebuildAggregate(agg, newSource) {
|
|
173
|
+
if (agg instanceof AggregateNode) {
|
|
174
|
+
return new AggregateNode(agg.scope, newSource, agg.groupBy, agg.aggregates, undefined, agg.getAttributes());
|
|
175
|
+
}
|
|
176
|
+
if (agg instanceof StreamAggregateNode) {
|
|
177
|
+
return new StreamAggregateNode(agg.scope, newSource, agg.groupBy, agg.aggregates, undefined, agg.getAttributes());
|
|
178
|
+
}
|
|
179
|
+
return new HashAggregateNode(agg.scope, newSource, agg.groupBy, agg.aggregates, undefined, agg.getAttributes());
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=rule-aggregate-predicate-pushdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-aggregate-predicate-pushdown.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-aggregate-predicate-pushdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Empty-Relation Folding
|
|
3
|
+
*
|
|
4
|
+
* Const-fold pass that recognizes provably-empty subtrees and replaces them
|
|
5
|
+
* with `EmptyRelationNode`, preserving attribute IDs and `RelationType` shape
|
|
6
|
+
* so consumers above the rewrite keep working.
|
|
7
|
+
*
|
|
8
|
+
* Recognized shapes (E = EmptyRelationNode):
|
|
9
|
+
* - Filter(x, lit-false / lit-null / lit-0) → E with x's schema
|
|
10
|
+
* - Filter(E, _) → E (pass-through)
|
|
11
|
+
* - Project(E, projections) → E with project's schema
|
|
12
|
+
* - Sort(E, _) / LimitOffset(E, _) / Distinct(E) → E (schema unchanged)
|
|
13
|
+
* - Join(E, R, inner|cross|semi) → E with join's schema
|
|
14
|
+
* - Join(L, E, inner|cross|semi) → E with join's schema
|
|
15
|
+
* - Join(E, R, left) → E (empty driving side)
|
|
16
|
+
* - Join(L, E, right) → E (symmetric)
|
|
17
|
+
* - Join(E, _, anti) → E (anti drives from left)
|
|
18
|
+
* - Join(E, E, full) → E (both sides empty)
|
|
19
|
+
*
|
|
20
|
+
* Deliberately NOT folded (sound reasons):
|
|
21
|
+
* - Join(L, E, left) — returns L null-padded on right
|
|
22
|
+
* - Join(E, R, right) — symmetric
|
|
23
|
+
* - Join(L, E, anti) — anti with empty right returns all of L
|
|
24
|
+
* - Single-side-empty FULL — still emits null-padded rows for non-empty side
|
|
25
|
+
*
|
|
26
|
+
* Runs in the Structural pass (TopDown) after the IND rules. Cascade is
|
|
27
|
+
* bounded: rules chain within a single node visit via the per-node fixed-
|
|
28
|
+
* point loop in `applyPassRules`, but the Structural pass itself is one
|
|
29
|
+
* top-down traversal — a parent already visited won't re-fire when an inner
|
|
30
|
+
* Filter folds. See "Cascade limits" in `docs/optimizer.md`.
|
|
31
|
+
*/
|
|
32
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
33
|
+
import type { OptContext } from '../../framework/context.js';
|
|
34
|
+
/**
|
|
35
|
+
* WHERE-clause truthiness: `false`, `null`, `0`, `0n` all reject every row.
|
|
36
|
+
* Conservatively cover only the canonical "no rows" literals. Other coercions
|
|
37
|
+
* (e.g. empty string, 0.0) are left out; if needed, expand here.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isLiteralFalsy(node: PlanNode): boolean;
|
|
40
|
+
export declare function ruleFilterFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
41
|
+
export declare function ruleProjectFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
42
|
+
export declare function ruleSortFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
43
|
+
export declare function ruleLimitOffsetFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
44
|
+
export declare function ruleDistinctFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
45
|
+
export declare function ruleJoinFoldEmpty(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
46
|
+
//# sourceMappingURL=rule-empty-relation-folding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-empty-relation-folding.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-empty-relation-folding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AA2B7D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAItD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAWrF;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAKtF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAKnF;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAK1F;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAKvF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAwCnF"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Empty-Relation Folding
|
|
3
|
+
*
|
|
4
|
+
* Const-fold pass that recognizes provably-empty subtrees and replaces them
|
|
5
|
+
* with `EmptyRelationNode`, preserving attribute IDs and `RelationType` shape
|
|
6
|
+
* so consumers above the rewrite keep working.
|
|
7
|
+
*
|
|
8
|
+
* Recognized shapes (E = EmptyRelationNode):
|
|
9
|
+
* - Filter(x, lit-false / lit-null / lit-0) → E with x's schema
|
|
10
|
+
* - Filter(E, _) → E (pass-through)
|
|
11
|
+
* - Project(E, projections) → E with project's schema
|
|
12
|
+
* - Sort(E, _) / LimitOffset(E, _) / Distinct(E) → E (schema unchanged)
|
|
13
|
+
* - Join(E, R, inner|cross|semi) → E with join's schema
|
|
14
|
+
* - Join(L, E, inner|cross|semi) → E with join's schema
|
|
15
|
+
* - Join(E, R, left) → E (empty driving side)
|
|
16
|
+
* - Join(L, E, right) → E (symmetric)
|
|
17
|
+
* - Join(E, _, anti) → E (anti drives from left)
|
|
18
|
+
* - Join(E, E, full) → E (both sides empty)
|
|
19
|
+
*
|
|
20
|
+
* Deliberately NOT folded (sound reasons):
|
|
21
|
+
* - Join(L, E, left) — returns L null-padded on right
|
|
22
|
+
* - Join(E, R, right) — symmetric
|
|
23
|
+
* - Join(L, E, anti) — anti with empty right returns all of L
|
|
24
|
+
* - Single-side-empty FULL — still emits null-padded rows for non-empty side
|
|
25
|
+
*
|
|
26
|
+
* Runs in the Structural pass (TopDown) after the IND rules. Cascade is
|
|
27
|
+
* bounded: rules chain within a single node visit via the per-node fixed-
|
|
28
|
+
* point loop in `applyPassRules`, but the Structural pass itself is one
|
|
29
|
+
* top-down traversal — a parent already visited won't re-fire when an inner
|
|
30
|
+
* Filter folds. See "Cascade limits" in `docs/optimizer.md`.
|
|
31
|
+
*/
|
|
32
|
+
import { createLogger } from '../../../common/logger.js';
|
|
33
|
+
import { FilterNode } from '../../nodes/filter.js';
|
|
34
|
+
import { ProjectNode } from '../../nodes/project-node.js';
|
|
35
|
+
import { SortNode } from '../../nodes/sort.js';
|
|
36
|
+
import { LimitOffsetNode } from '../../nodes/limit-offset.js';
|
|
37
|
+
import { DistinctNode } from '../../nodes/distinct-node.js';
|
|
38
|
+
import { JoinNode } from '../../nodes/join-node.js';
|
|
39
|
+
import { AliasNode } from '../../nodes/alias-node.js';
|
|
40
|
+
import { LiteralNode } from '../../nodes/scalar.js';
|
|
41
|
+
import { EmptyRelationNode } from '../../nodes/empty-relation-node.js';
|
|
42
|
+
const log = createLogger('optimizer:rule:empty-relation-folding');
|
|
43
|
+
/**
|
|
44
|
+
* Detects EmptyRelation, including the common case where it sits beneath one
|
|
45
|
+
* or more attribute-renaming wrappers (Alias) introduced by FROM-clause
|
|
46
|
+
* subquery aliases. Looking through Alias is sound here because the *host*
|
|
47
|
+
* fold (Join, Project, etc.) produces an EmptyRelation carrying the host's
|
|
48
|
+
* own attributes — the wrapped Alias's rename is discarded along with the
|
|
49
|
+
* Alias itself.
|
|
50
|
+
*/
|
|
51
|
+
function isEmpty(node) {
|
|
52
|
+
if (node instanceof EmptyRelationNode)
|
|
53
|
+
return true;
|
|
54
|
+
if (node instanceof AliasNode)
|
|
55
|
+
return isEmpty(node.source);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* WHERE-clause truthiness: `false`, `null`, `0`, `0n` all reject every row.
|
|
60
|
+
* Conservatively cover only the canonical "no rows" literals. Other coercions
|
|
61
|
+
* (e.g. empty string, 0.0) are left out; if needed, expand here.
|
|
62
|
+
*/
|
|
63
|
+
export function isLiteralFalsy(node) {
|
|
64
|
+
if (!(node instanceof LiteralNode))
|
|
65
|
+
return false;
|
|
66
|
+
const v = node.expression.value;
|
|
67
|
+
return v === false || v === null || v === 0 || v === 0n;
|
|
68
|
+
}
|
|
69
|
+
export function ruleFilterFoldEmpty(node, _ctx) {
|
|
70
|
+
if (!(node instanceof FilterNode))
|
|
71
|
+
return null;
|
|
72
|
+
if (isEmpty(node.source)) {
|
|
73
|
+
log('Filter(Empty, _) → Empty');
|
|
74
|
+
return node.source;
|
|
75
|
+
}
|
|
76
|
+
if (isLiteralFalsy(node.predicate)) {
|
|
77
|
+
log('Filter(x, lit-false) → Empty');
|
|
78
|
+
return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
export function ruleProjectFoldEmpty(node, _ctx) {
|
|
83
|
+
if (!(node instanceof ProjectNode))
|
|
84
|
+
return null;
|
|
85
|
+
if (!isEmpty(node.source))
|
|
86
|
+
return null;
|
|
87
|
+
log('Project(Empty, _) → Empty');
|
|
88
|
+
return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
|
|
89
|
+
}
|
|
90
|
+
export function ruleSortFoldEmpty(node, _ctx) {
|
|
91
|
+
if (!(node instanceof SortNode))
|
|
92
|
+
return null;
|
|
93
|
+
if (!isEmpty(node.source))
|
|
94
|
+
return null;
|
|
95
|
+
log('Sort(Empty, _) → Empty');
|
|
96
|
+
return node.source;
|
|
97
|
+
}
|
|
98
|
+
export function ruleLimitOffsetFoldEmpty(node, _ctx) {
|
|
99
|
+
if (!(node instanceof LimitOffsetNode))
|
|
100
|
+
return null;
|
|
101
|
+
if (!isEmpty(node.source))
|
|
102
|
+
return null;
|
|
103
|
+
log('LimitOffset(Empty, _) → Empty');
|
|
104
|
+
return node.source;
|
|
105
|
+
}
|
|
106
|
+
export function ruleDistinctFoldEmpty(node, _ctx) {
|
|
107
|
+
if (!(node instanceof DistinctNode))
|
|
108
|
+
return null;
|
|
109
|
+
if (!isEmpty(node.source))
|
|
110
|
+
return null;
|
|
111
|
+
log('Distinct(Empty) → Empty');
|
|
112
|
+
return node.source;
|
|
113
|
+
}
|
|
114
|
+
export function ruleJoinFoldEmpty(node, _ctx) {
|
|
115
|
+
if (!(node instanceof JoinNode))
|
|
116
|
+
return null;
|
|
117
|
+
const leftEmpty = isEmpty(node.left);
|
|
118
|
+
const rightEmpty = isEmpty(node.right);
|
|
119
|
+
if (!leftEmpty && !rightEmpty)
|
|
120
|
+
return null;
|
|
121
|
+
let fold = false;
|
|
122
|
+
switch (node.joinType) {
|
|
123
|
+
case 'inner':
|
|
124
|
+
case 'cross':
|
|
125
|
+
fold = leftEmpty || rightEmpty;
|
|
126
|
+
break;
|
|
127
|
+
case 'left':
|
|
128
|
+
// LEFT JOIN: empty left → empty output. Empty right → keep (null-pad L).
|
|
129
|
+
fold = leftEmpty;
|
|
130
|
+
break;
|
|
131
|
+
case 'right':
|
|
132
|
+
// RIGHT JOIN: empty right → empty output. Empty left → keep (null-pad R).
|
|
133
|
+
fold = rightEmpty;
|
|
134
|
+
break;
|
|
135
|
+
case 'full':
|
|
136
|
+
// FULL JOIN: only fold when BOTH sides empty; one empty side still
|
|
137
|
+
// emits null-padded rows from the non-empty side.
|
|
138
|
+
fold = leftEmpty && rightEmpty;
|
|
139
|
+
break;
|
|
140
|
+
case 'semi':
|
|
141
|
+
// SEMI JOIN: empty L → empty. Empty R → empty (no matches possible).
|
|
142
|
+
fold = leftEmpty || rightEmpty;
|
|
143
|
+
break;
|
|
144
|
+
case 'anti':
|
|
145
|
+
// ANTI JOIN: empty L → empty. Empty R → all of L (do NOT fold).
|
|
146
|
+
fold = leftEmpty;
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
if (!fold)
|
|
152
|
+
return null;
|
|
153
|
+
log('Join(%s) with empty side(s) → Empty', node.joinType);
|
|
154
|
+
return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=rule-empty-relation-folding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-empty-relation-folding.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-empty-relation-folding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Filter Predicate Contradiction
|
|
3
|
+
*
|
|
4
|
+
* Folds Filter nodes whose conjuncts together with the source's
|
|
5
|
+
* `domainConstraints` and literal `constantBindings` are provably
|
|
6
|
+
* unsatisfiable. The empty result is materialized as `EmptyRelationNode`
|
|
7
|
+
* carrying the Filter's own attribute IDs / RelationType, so the const-fold
|
|
8
|
+
* cascade (Project / Sort / LimitOffset / Distinct / inner-or-cross-or-semi
|
|
9
|
+
* Join) can drop the parent subtree.
|
|
10
|
+
*
|
|
11
|
+
* Scope (see `analysis/sat-checker.ts`):
|
|
12
|
+
* - Single-column comparisons against literals (= / != / < / <= / > / >=).
|
|
13
|
+
* - Single-column BETWEEN literal AND literal.
|
|
14
|
+
* - Single-column IN (lit, lit, ...) and intersection across IN-lists.
|
|
15
|
+
* - Domain-vs-predicate intersection.
|
|
16
|
+
*
|
|
17
|
+
* Out of scope (treated as `unknown`, never folded):
|
|
18
|
+
* - OR / CASE branch analysis, cross-column arithmetic, LIKE, IS NULL,
|
|
19
|
+
* user-function reasoning. The sat-checker tracks an `unknown` flag
|
|
20
|
+
* per column so an in-scope contradiction on column `a` still fires
|
|
21
|
+
* even if an unrelated LIKE on column `b` is present.
|
|
22
|
+
*
|
|
23
|
+
* Registered at Structural pass priority 27 — runs alongside the empty-
|
|
24
|
+
* relation-folding rules so any `Filter(_, false)` produced by other rules
|
|
25
|
+
* has already been collapsed.
|
|
26
|
+
*/
|
|
27
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
28
|
+
import type { OptContext } from '../../framework/context.js';
|
|
29
|
+
export declare function ruleFilterContradiction(node: PlanNode, _ctx: OptContext): PlanNode | null;
|
|
30
|
+
//# sourceMappingURL=rule-filter-contradiction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-filter-contradiction.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-filter-contradiction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAS7D,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAoCzF"}
|