@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,60 @@
|
|
|
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 { createLogger } from '../../../common/logger.js';
|
|
28
|
+
import { FilterNode } from '../../nodes/filter.js';
|
|
29
|
+
import { EmptyRelationNode } from '../../nodes/empty-relation-node.js';
|
|
30
|
+
import { splitConjuncts } from '../../analysis/predicate-conjuncts.js';
|
|
31
|
+
import { checkSatisfiability } from '../../analysis/sat-checker.js';
|
|
32
|
+
import { isLiteralFalsy } from './rule-empty-relation-folding.js';
|
|
33
|
+
const log = createLogger('optimizer:rule:filter-contradiction');
|
|
34
|
+
export function ruleFilterContradiction(node, _ctx) {
|
|
35
|
+
if (!(node instanceof FilterNode))
|
|
36
|
+
return null;
|
|
37
|
+
// `Filter(_, lit-false|null|0|0n)` is the empty-folding rule's job; bail out
|
|
38
|
+
// so this rule doesn't dispatch to the sat-checker for predicates the
|
|
39
|
+
// sibling rule will collapse anyway.
|
|
40
|
+
if (isLiteralFalsy(node.predicate)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const sourcePhysical = node.source.physical;
|
|
44
|
+
const domains = sourcePhysical.domainConstraints ?? [];
|
|
45
|
+
const bindings = sourcePhysical.constantBindings ?? [];
|
|
46
|
+
const conjuncts = splitConjuncts(node.predicate);
|
|
47
|
+
const sourceAttrs = node.source.getAttributes();
|
|
48
|
+
const attrIdToIndex = new Map();
|
|
49
|
+
sourceAttrs.forEach((a, i) => attrIdToIndex.set(a.id, i));
|
|
50
|
+
const collationOf = (col) => {
|
|
51
|
+
const attr = sourceAttrs[col];
|
|
52
|
+
return attr?.type.collationName;
|
|
53
|
+
};
|
|
54
|
+
const result = checkSatisfiability(conjuncts, domains, bindings, (attrId) => attrIdToIndex.get(attrId), collationOf);
|
|
55
|
+
if (result !== 'unsat')
|
|
56
|
+
return null;
|
|
57
|
+
log('Filter predicate provably unsatisfiable → Empty');
|
|
58
|
+
return new EmptyRelationNode(node.scope, node.getAttributes(), node.getType());
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=rule-filter-contradiction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-filter-contradiction.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-filter-contradiction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,MAAM,GAAG,GAAG,YAAY,CAAC,qCAAqC,CAAC,CAAC;AAEhE,MAAM,UAAU,uBAAuB,CAAC,IAAc,EAAE,IAAgB;IACvE,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/C,6EAA6E;IAC7E,sEAAsE;IACtE,qCAAqC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,cAAc,CAAC,gBAAgB,IAAI,EAAE,CAAC;IACvD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IAChD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAE1D,MAAM,WAAW,GAAG,CAAC,GAAW,EAAsB,EAAE;QACvD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,mBAAmB,CACjC,SAAS,EACT,OAAO,EACP,QAAQ,EACR,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EACrC,WAAW,CACX,CAAC;IAEF,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAEpC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IACvD,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Predicate Inference (Equivalence-Class driven)
|
|
3
|
+
*
|
|
4
|
+
* Materializes inferred equality predicates derived from combining
|
|
5
|
+
* (predicate-derived) constant bindings with (source-derived) equivalence
|
|
6
|
+
* classes. When `t.k = u.k` is known via a join's equi-pair and `t.k = V`
|
|
7
|
+
* is asserted in the filter, the rule emits `u.k = V` so the predicate is
|
|
8
|
+
* visible to vtab access plans on the `u` side independently.
|
|
9
|
+
*
|
|
10
|
+
* Simple form (always run):
|
|
11
|
+
* Filter(predicate, source)
|
|
12
|
+
* - Extract `predBindings` from the predicate (col-index → constant value).
|
|
13
|
+
* - Cross with `source.physical.equivClasses`: for every EC member of a
|
|
14
|
+
* bound column that is not itself bound by the predicate, emit a new
|
|
15
|
+
* `col = value` conjunct.
|
|
16
|
+
* - AND the new conjuncts into the filter predicate.
|
|
17
|
+
*
|
|
18
|
+
* Powerful form (additional when source is an inner/cross JoinNode):
|
|
19
|
+
* - Split the newly-inferred conjuncts by which side of the join their
|
|
20
|
+
* columns reference. For each single-side conjunct, inject a FilterNode
|
|
21
|
+
* wrapping that side of the join, re-keyed onto the branch's local
|
|
22
|
+
* column indices.
|
|
23
|
+
* - The outer FilterNode still carries the augmented predicate; the
|
|
24
|
+
* branch filter is what subsequent predicate-pushdown can carry into
|
|
25
|
+
* the leaf's Retrieve pipeline.
|
|
26
|
+
*
|
|
27
|
+
* Fixpoint guard: the rule's emission set is `{otherIdx ∈ EC | otherIdx
|
|
28
|
+
* is not already in predBoundIdx}`. On a second invocation the
|
|
29
|
+
* inferred conjuncts have themselves contributed bindings, so every EC
|
|
30
|
+
* member is in `predBoundIdx` and the rule yields nothing. The registry's
|
|
31
|
+
* per-node `markRuleApplied` is a belt-and-suspenders second guard.
|
|
32
|
+
*
|
|
33
|
+
* Safety:
|
|
34
|
+
* - LEFT/RIGHT/FULL joins: per `propagateJoinFds`, NULL-padded sides drop
|
|
35
|
+
* their bindings/ECs, so the EC visible at the filter's source is
|
|
36
|
+
* restricted to the preserved side. The rule additionally refuses
|
|
37
|
+
* branch injection on these join types (outer filter only).
|
|
38
|
+
* - SEMI/ANTI: only the left side is in the output; no right inference
|
|
39
|
+
* can arise here. Treat as LEFT for branch injection.
|
|
40
|
+
*
|
|
41
|
+
* See ticket `3-rule-predicate-inference-equivalence` for the full design.
|
|
42
|
+
*/
|
|
43
|
+
import type { OptContext as _OptContext } from '../../framework/context.js';
|
|
44
|
+
export declare function rulePredicateInferenceEquivalence(node: import('../../nodes/plan-node.js').PlanNode, _context: _OptContext): import('../../nodes/plan-node.js').PlanNode | null;
|
|
45
|
+
//# sourceMappingURL=rule-predicate-inference-equivalence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-predicate-inference-equivalence.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-inference-equivalence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,OAAO,KAAK,EAAE,UAAU,IAAI,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAoB5E,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,OAAO,0BAA0B,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,0BAA0B,EAAE,QAAQ,GAAG,IAAI,CA2D9K"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Predicate Inference (Equivalence-Class driven)
|
|
3
|
+
*
|
|
4
|
+
* Materializes inferred equality predicates derived from combining
|
|
5
|
+
* (predicate-derived) constant bindings with (source-derived) equivalence
|
|
6
|
+
* classes. When `t.k = u.k` is known via a join's equi-pair and `t.k = V`
|
|
7
|
+
* is asserted in the filter, the rule emits `u.k = V` so the predicate is
|
|
8
|
+
* visible to vtab access plans on the `u` side independently.
|
|
9
|
+
*
|
|
10
|
+
* Simple form (always run):
|
|
11
|
+
* Filter(predicate, source)
|
|
12
|
+
* - Extract `predBindings` from the predicate (col-index → constant value).
|
|
13
|
+
* - Cross with `source.physical.equivClasses`: for every EC member of a
|
|
14
|
+
* bound column that is not itself bound by the predicate, emit a new
|
|
15
|
+
* `col = value` conjunct.
|
|
16
|
+
* - AND the new conjuncts into the filter predicate.
|
|
17
|
+
*
|
|
18
|
+
* Powerful form (additional when source is an inner/cross JoinNode):
|
|
19
|
+
* - Split the newly-inferred conjuncts by which side of the join their
|
|
20
|
+
* columns reference. For each single-side conjunct, inject a FilterNode
|
|
21
|
+
* wrapping that side of the join, re-keyed onto the branch's local
|
|
22
|
+
* column indices.
|
|
23
|
+
* - The outer FilterNode still carries the augmented predicate; the
|
|
24
|
+
* branch filter is what subsequent predicate-pushdown can carry into
|
|
25
|
+
* the leaf's Retrieve pipeline.
|
|
26
|
+
*
|
|
27
|
+
* Fixpoint guard: the rule's emission set is `{otherIdx ∈ EC | otherIdx
|
|
28
|
+
* is not already in predBoundIdx}`. On a second invocation the
|
|
29
|
+
* inferred conjuncts have themselves contributed bindings, so every EC
|
|
30
|
+
* member is in `predBoundIdx` and the rule yields nothing. The registry's
|
|
31
|
+
* per-node `markRuleApplied` is a belt-and-suspenders second guard.
|
|
32
|
+
*
|
|
33
|
+
* Safety:
|
|
34
|
+
* - LEFT/RIGHT/FULL joins: per `propagateJoinFds`, NULL-padded sides drop
|
|
35
|
+
* their bindings/ECs, so the EC visible at the filter's source is
|
|
36
|
+
* restricted to the preserved side. The rule additionally refuses
|
|
37
|
+
* branch injection on these join types (outer filter only).
|
|
38
|
+
* - SEMI/ANTI: only the left side is in the output; no right inference
|
|
39
|
+
* can arise here. Treat as LEFT for branch injection.
|
|
40
|
+
*
|
|
41
|
+
* See ticket `3-rule-predicate-inference-equivalence` for the full design.
|
|
42
|
+
*/
|
|
43
|
+
import { createLogger } from '../../../common/logger.js';
|
|
44
|
+
import { FilterNode } from '../../nodes/filter.js';
|
|
45
|
+
import { JoinNode } from '../../nodes/join-node.js';
|
|
46
|
+
import { BinaryOpNode, LiteralNode } from '../../nodes/scalar.js';
|
|
47
|
+
import { ColumnReferenceNode, ParameterReferenceNode } from '../../nodes/reference.js';
|
|
48
|
+
import { extractEqualityFds } from '../../util/fd-utils.js';
|
|
49
|
+
const log = createLogger('optimizer:rule:predicate-inference-equivalence');
|
|
50
|
+
export function rulePredicateInferenceEquivalence(node, _context) {
|
|
51
|
+
if (!(node instanceof FilterNode))
|
|
52
|
+
return null;
|
|
53
|
+
const filter = node;
|
|
54
|
+
const source = filter.source;
|
|
55
|
+
const sourcePhys = source.physical;
|
|
56
|
+
const ecs = sourcePhys?.equivClasses;
|
|
57
|
+
if (!ecs || ecs.length === 0)
|
|
58
|
+
return null;
|
|
59
|
+
const sourceAttrs = source.getAttributes();
|
|
60
|
+
const attrIdToIndex = new Map();
|
|
61
|
+
sourceAttrs.forEach((a, i) => attrIdToIndex.set(a.id, i));
|
|
62
|
+
const { constantBindings: predBindings } = extractEqualityFds(filter.predicate, attrIdToIndex);
|
|
63
|
+
if (predBindings.length === 0)
|
|
64
|
+
return null;
|
|
65
|
+
// Columns the predicate itself directly pins. Used both to find which
|
|
66
|
+
// EC members already have a binding and as the fixpoint guard: once
|
|
67
|
+
// every EC member is in this set, the rule contributes nothing further.
|
|
68
|
+
const predBoundIdx = new Set();
|
|
69
|
+
for (const b of predBindings)
|
|
70
|
+
for (const c of b.attrs)
|
|
71
|
+
predBoundIdx.add(c);
|
|
72
|
+
const inferred = [];
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
for (const binding of predBindings) {
|
|
75
|
+
for (const predIdx of binding.attrs) {
|
|
76
|
+
for (const cls of ecs) {
|
|
77
|
+
if (!cls.includes(predIdx))
|
|
78
|
+
continue;
|
|
79
|
+
for (const otherIdx of cls) {
|
|
80
|
+
if (otherIdx === predIdx)
|
|
81
|
+
continue;
|
|
82
|
+
if (predBoundIdx.has(otherIdx))
|
|
83
|
+
continue;
|
|
84
|
+
const key = `${otherIdx}|${valueSignature(binding.value)}`;
|
|
85
|
+
if (seen.has(key))
|
|
86
|
+
continue;
|
|
87
|
+
seen.add(key);
|
|
88
|
+
const attr = sourceAttrs[otherIdx];
|
|
89
|
+
if (!attr)
|
|
90
|
+
continue;
|
|
91
|
+
const conjunct = synthesizeEquality(filter.scope, attr, otherIdx, binding.value);
|
|
92
|
+
inferred.push({ sourceColIdx: otherIdx, value: binding.value, conjunct });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (inferred.length === 0)
|
|
98
|
+
return null;
|
|
99
|
+
log('Inferring %d new equality conjunct(s) on Filter from EC × bindings', inferred.length);
|
|
100
|
+
// AND every inferred conjunct into the predicate.
|
|
101
|
+
let combinedPredicate = filter.predicate;
|
|
102
|
+
for (const inf of inferred) {
|
|
103
|
+
combinedPredicate = andTogether(filter.scope, combinedPredicate, inf.conjunct);
|
|
104
|
+
}
|
|
105
|
+
// Powerful form: branch injection below inner/cross joins.
|
|
106
|
+
let newSource = source;
|
|
107
|
+
if (source instanceof JoinNode) {
|
|
108
|
+
newSource = tryBranchInjection(source, inferred) ?? source;
|
|
109
|
+
}
|
|
110
|
+
return new FilterNode(filter.scope, newSource, combinedPredicate);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* For an inner or cross JoinNode whose output bears `inferred` conjuncts,
|
|
114
|
+
* inject single-side conjuncts as FilterNode wrappers on the corresponding
|
|
115
|
+
* branch. Returns the rebuilt join, or null if no inferred conjunct lands
|
|
116
|
+
* on either branch.
|
|
117
|
+
*/
|
|
118
|
+
function tryBranchInjection(join, inferred) {
|
|
119
|
+
// Only inner / cross are safe — see file-level "Safety" notes.
|
|
120
|
+
if (join.joinType !== 'inner' && join.joinType !== 'cross')
|
|
121
|
+
return null;
|
|
122
|
+
const leftAttrs = join.left.getAttributes();
|
|
123
|
+
const rightAttrs = join.right.getAttributes();
|
|
124
|
+
const leftCount = leftAttrs.length;
|
|
125
|
+
const leftBranchConjuncts = [];
|
|
126
|
+
const rightBranchConjuncts = [];
|
|
127
|
+
for (const inf of inferred) {
|
|
128
|
+
if (inf.sourceColIdx < leftCount) {
|
|
129
|
+
// Left-branch: attribute id is stable, so re-synthesize against the
|
|
130
|
+
// branch's local column index (which is `sourceColIdx` itself).
|
|
131
|
+
const attr = leftAttrs[inf.sourceColIdx];
|
|
132
|
+
if (!attr)
|
|
133
|
+
continue;
|
|
134
|
+
leftBranchConjuncts.push(synthesizeEquality(join.scope, attr, inf.sourceColIdx, inf.value));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const rightIdx = inf.sourceColIdx - leftCount;
|
|
138
|
+
const attr = rightAttrs[rightIdx];
|
|
139
|
+
if (!attr)
|
|
140
|
+
continue;
|
|
141
|
+
rightBranchConjuncts.push(synthesizeEquality(join.scope, attr, rightIdx, inf.value));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (leftBranchConjuncts.length === 0 && rightBranchConjuncts.length === 0)
|
|
145
|
+
return null;
|
|
146
|
+
let newLeft = join.left;
|
|
147
|
+
let newRight = join.right;
|
|
148
|
+
if (leftBranchConjuncts.length > 0) {
|
|
149
|
+
const leftPred = combineAnds(join.scope, leftBranchConjuncts);
|
|
150
|
+
newLeft = new FilterNode(join.left.scope, join.left, leftPred);
|
|
151
|
+
}
|
|
152
|
+
if (rightBranchConjuncts.length > 0) {
|
|
153
|
+
const rightPred = combineAnds(join.scope, rightBranchConjuncts);
|
|
154
|
+
newRight = new FilterNode(join.right.scope, join.right, rightPred);
|
|
155
|
+
}
|
|
156
|
+
log('Injecting %d left + %d right branch filter(s) below %s join', leftBranchConjuncts.length, rightBranchConjuncts.length, join.joinType);
|
|
157
|
+
return new JoinNode(join.scope, newLeft, newRight, join.joinType, join.condition, join.usingColumns);
|
|
158
|
+
}
|
|
159
|
+
function synthesizeEquality(scope, attr, columnIndex, value) {
|
|
160
|
+
const colExpr = attr.relationName
|
|
161
|
+
? { type: 'column', name: attr.name, table: attr.relationName }
|
|
162
|
+
: { type: 'column', name: attr.name };
|
|
163
|
+
const colRef = new ColumnReferenceNode(scope, colExpr, attr.type, attr.id, columnIndex);
|
|
164
|
+
let valueNode;
|
|
165
|
+
if (value.kind === 'literal') {
|
|
166
|
+
const litExpr = { type: 'literal', value: value.value };
|
|
167
|
+
valueNode = new LiteralNode(scope, litExpr);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
const paramExpr = typeof value.paramRef === 'string'
|
|
171
|
+
? { type: 'parameter', name: value.paramRef }
|
|
172
|
+
: { type: 'parameter', index: value.paramRef };
|
|
173
|
+
valueNode = new ParameterReferenceNode(scope, paramExpr, value.paramRef, attr.type);
|
|
174
|
+
}
|
|
175
|
+
const eqAst = {
|
|
176
|
+
type: 'binary',
|
|
177
|
+
operator: '=',
|
|
178
|
+
left: colRef.expression,
|
|
179
|
+
right: valueNode.expression,
|
|
180
|
+
};
|
|
181
|
+
return new BinaryOpNode(scope, eqAst, colRef, valueNode);
|
|
182
|
+
}
|
|
183
|
+
function andTogether(scope, left, right) {
|
|
184
|
+
const ast = {
|
|
185
|
+
type: 'binary',
|
|
186
|
+
operator: 'AND',
|
|
187
|
+
left: left.expression,
|
|
188
|
+
right: right.expression,
|
|
189
|
+
};
|
|
190
|
+
return new BinaryOpNode(scope, ast, left, right);
|
|
191
|
+
}
|
|
192
|
+
function combineAnds(scope, conjuncts) {
|
|
193
|
+
let acc = conjuncts[0];
|
|
194
|
+
for (let i = 1; i < conjuncts.length; i++) {
|
|
195
|
+
acc = andTogether(scope, acc, conjuncts[i]);
|
|
196
|
+
}
|
|
197
|
+
return acc;
|
|
198
|
+
}
|
|
199
|
+
function valueSignature(value) {
|
|
200
|
+
if (value.kind === 'literal') {
|
|
201
|
+
const v = value.value;
|
|
202
|
+
if (v === null)
|
|
203
|
+
return 'lit:null';
|
|
204
|
+
if (v instanceof Uint8Array)
|
|
205
|
+
return `lit:blob:${Array.from(v).join(',')}`;
|
|
206
|
+
return `lit:${typeof v}:${String(v)}`;
|
|
207
|
+
}
|
|
208
|
+
return `param:${value.paramRef}`;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=rule-predicate-inference-equivalence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-predicate-inference-equivalence.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-predicate-inference-equivalence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Sargable Range Rewrite
|
|
3
|
+
*
|
|
4
|
+
* For predicates of the form `f(col) = c` where `f` is a monotone-but-lossy
|
|
5
|
+
* bucket conversion (e.g. `date(datetime_col) = '2024-01-15'`), rewrite the
|
|
6
|
+
* conjunct to a half-open range on the underlying column:
|
|
7
|
+
*
|
|
8
|
+
* f(col) = c → col >= lower(c) AND col < upper(c)
|
|
9
|
+
*
|
|
10
|
+
* The half-open bounds come from `ScalarPlanNode.rangeRewriteIn(attrId, c)`,
|
|
11
|
+
* which delegates to `LogicalType.bucketBounds` on the column's logical type.
|
|
12
|
+
* The rewritten `col op literal` shape is what `analysis/constraint-extractor`
|
|
13
|
+
* already recognizes, so the resulting range can be pushed through
|
|
14
|
+
* `rule-predicate-pushdown` into the Retrieve pipeline and consumed by
|
|
15
|
+
* `rule-select-access-path` (IndexSeek, range scans, etc.).
|
|
16
|
+
*
|
|
17
|
+
* NULL semantics: a null constant is left alone (`f(col) = null` is already
|
|
18
|
+
* null, which WHERE / ON treat as false). A null column value satisfies neither
|
|
19
|
+
* `col >= L` nor `col < U` (both yield null), so row-rejection behavior
|
|
20
|
+
* matches the original predicate.
|
|
21
|
+
*
|
|
22
|
+
* Only the `=` shape is handled in this pass; `<`/`<=`/`>`/`>=` need direction
|
|
23
|
+
* analysis on `monotonicityIn` and asymmetric bound mapping — tracked
|
|
24
|
+
* separately in the optimization backlog.
|
|
25
|
+
*/
|
|
26
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
27
|
+
import type { OptContext } from '../../framework/context.js';
|
|
28
|
+
export declare function ruleSargableRangeRewrite(node: PlanNode, _context: OptContext): PlanNode | null;
|
|
29
|
+
//# sourceMappingURL=rule-sargable-range-rewrite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-sargable-range-rewrite.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-sargable-range-rewrite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAa7D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAuB9F"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Sargable Range Rewrite
|
|
3
|
+
*
|
|
4
|
+
* For predicates of the form `f(col) = c` where `f` is a monotone-but-lossy
|
|
5
|
+
* bucket conversion (e.g. `date(datetime_col) = '2024-01-15'`), rewrite the
|
|
6
|
+
* conjunct to a half-open range on the underlying column:
|
|
7
|
+
*
|
|
8
|
+
* f(col) = c → col >= lower(c) AND col < upper(c)
|
|
9
|
+
*
|
|
10
|
+
* The half-open bounds come from `ScalarPlanNode.rangeRewriteIn(attrId, c)`,
|
|
11
|
+
* which delegates to `LogicalType.bucketBounds` on the column's logical type.
|
|
12
|
+
* The rewritten `col op literal` shape is what `analysis/constraint-extractor`
|
|
13
|
+
* already recognizes, so the resulting range can be pushed through
|
|
14
|
+
* `rule-predicate-pushdown` into the Retrieve pipeline and consumed by
|
|
15
|
+
* `rule-select-access-path` (IndexSeek, range scans, etc.).
|
|
16
|
+
*
|
|
17
|
+
* NULL semantics: a null constant is left alone (`f(col) = null` is already
|
|
18
|
+
* null, which WHERE / ON treat as false). A null column value satisfies neither
|
|
19
|
+
* `col >= L` nor `col < U` (both yield null), so row-rejection behavior
|
|
20
|
+
* matches the original predicate.
|
|
21
|
+
*
|
|
22
|
+
* Only the `=` shape is handled in this pass; `<`/`<=`/`>`/`>=` need direction
|
|
23
|
+
* analysis on `monotonicityIn` and asymmetric bound mapping — tracked
|
|
24
|
+
* separately in the optimization backlog.
|
|
25
|
+
*/
|
|
26
|
+
import { createLogger } from '../../../common/logger.js';
|
|
27
|
+
import { PlanNodeType } from '../../nodes/plan-node-type.js';
|
|
28
|
+
import { FilterNode } from '../../nodes/filter.js';
|
|
29
|
+
import { BinaryOpNode, LiteralNode } from '../../nodes/scalar.js';
|
|
30
|
+
import { ColumnReferenceNode, ParameterReferenceNode } from '../../nodes/reference.js';
|
|
31
|
+
import { splitConjuncts, combineConjuncts } from '../../analysis/predicate-conjuncts.js';
|
|
32
|
+
import { getSyncLiteral } from '../../../parser/utils.js';
|
|
33
|
+
const log = createLogger('optimizer:rule:sargable-range-rewrite');
|
|
34
|
+
export function ruleSargableRangeRewrite(node, _context) {
|
|
35
|
+
if (node.nodeType !== PlanNodeType.Filter)
|
|
36
|
+
return null;
|
|
37
|
+
const filter = node;
|
|
38
|
+
const conjuncts = splitConjuncts(filter.predicate);
|
|
39
|
+
let rewrittenCount = 0;
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const c of conjuncts) {
|
|
42
|
+
const rewritten = tryRewriteEqualityToRange(c);
|
|
43
|
+
if (rewritten) {
|
|
44
|
+
out.push(rewritten);
|
|
45
|
+
rewrittenCount++;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
out.push(c);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (rewrittenCount === 0)
|
|
52
|
+
return null;
|
|
53
|
+
const combined = combineConjuncts(out);
|
|
54
|
+
if (!combined)
|
|
55
|
+
return null;
|
|
56
|
+
log('Rewrote %d sargable bucket-equality conjunct(s)', rewrittenCount);
|
|
57
|
+
return new FilterNode(filter.scope, filter.source, combined);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Recognize a `f(col) = const` conjunct and lift it to a half-open range on
|
|
61
|
+
* `col`. Returns the rewritten AND-tree on success, or `undefined` when the
|
|
62
|
+
* conjunct is not in the recognized shape / the function declines the rewrite.
|
|
63
|
+
*/
|
|
64
|
+
function tryRewriteEqualityToRange(expr) {
|
|
65
|
+
if (expr.nodeType !== PlanNodeType.BinaryOp)
|
|
66
|
+
return undefined;
|
|
67
|
+
const bin = expr;
|
|
68
|
+
if (bin.expression.operator !== '=')
|
|
69
|
+
return undefined;
|
|
70
|
+
// Exactly one side must be a literal constant; the other is the candidate
|
|
71
|
+
// function-shaped expression.
|
|
72
|
+
const leftLit = isLiteralConstant(bin.left);
|
|
73
|
+
const rightLit = isLiteralConstant(bin.right);
|
|
74
|
+
if (leftLit === rightLit)
|
|
75
|
+
return undefined; // both or neither
|
|
76
|
+
const literalSide = leftLit ? bin.left : bin.right;
|
|
77
|
+
const candidateSide = leftLit ? bin.right : bin.left;
|
|
78
|
+
const literalValue = getLiteralValue(literalSide);
|
|
79
|
+
if (literalValue === null)
|
|
80
|
+
return undefined;
|
|
81
|
+
// The candidate must depend on exactly one column attribute. Other leaves
|
|
82
|
+
// (literals / parameters) are fine — `rangeRewriteIn` itself enforces that
|
|
83
|
+
// the operand at the trait index is a bare ColumnReferenceNode.
|
|
84
|
+
const colRef = findUniqueColumnReference(candidateSide);
|
|
85
|
+
if (!colRef)
|
|
86
|
+
return undefined;
|
|
87
|
+
const bounds = candidateSide.rangeRewriteIn(colRef.attributeId, literalValue);
|
|
88
|
+
if (!bounds)
|
|
89
|
+
return undefined;
|
|
90
|
+
// Build `col >= L AND col < U` reusing the original ColumnReferenceNode (so
|
|
91
|
+
// the attribute id survives verbatim for downstream constraint extraction).
|
|
92
|
+
const scope = expr.scope;
|
|
93
|
+
const colType = colRef.getType();
|
|
94
|
+
const lower = makeComparison(scope, colRef, '>=', bounds.lowerInclusive, colType);
|
|
95
|
+
const upper = makeComparison(scope, colRef, '<', bounds.upperExclusive, colType);
|
|
96
|
+
const andAst = {
|
|
97
|
+
type: 'binary',
|
|
98
|
+
operator: 'AND',
|
|
99
|
+
left: lower.expression,
|
|
100
|
+
right: upper.expression,
|
|
101
|
+
};
|
|
102
|
+
return new BinaryOpNode(scope, andAst, lower, upper);
|
|
103
|
+
}
|
|
104
|
+
function makeComparison(scope, colRef, op, value, colType) {
|
|
105
|
+
const litExpr = { type: 'literal', value };
|
|
106
|
+
const literal = new LiteralNode(scope, litExpr, colType);
|
|
107
|
+
const ast = {
|
|
108
|
+
type: 'binary',
|
|
109
|
+
operator: op,
|
|
110
|
+
left: colRef.expression,
|
|
111
|
+
right: litExpr,
|
|
112
|
+
};
|
|
113
|
+
return new BinaryOpNode(scope, ast, colRef, literal);
|
|
114
|
+
}
|
|
115
|
+
/** Strip a planner-inserted CastNode wrapper. */
|
|
116
|
+
function unwrapCast(node) {
|
|
117
|
+
return node.nodeType === PlanNodeType.Cast ? node.operand : node;
|
|
118
|
+
}
|
|
119
|
+
function isLiteralConstant(node) {
|
|
120
|
+
return unwrapCast(node).nodeType === PlanNodeType.Literal;
|
|
121
|
+
}
|
|
122
|
+
function getLiteralValue(node) {
|
|
123
|
+
const lit = unwrapCast(node);
|
|
124
|
+
return getSyncLiteral(lit.expression);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Walk the subtree's leaves and return the single `ColumnReferenceNode` if
|
|
128
|
+
* exactly one is found and every other leaf is a literal or parameter; return
|
|
129
|
+
* undefined for zero, two, or any unrecognized leaf shape (subqueries,
|
|
130
|
+
* function-of-other-column, etc.).
|
|
131
|
+
*/
|
|
132
|
+
function findUniqueColumnReference(node) {
|
|
133
|
+
let found;
|
|
134
|
+
let ok = true;
|
|
135
|
+
const visit = (n) => {
|
|
136
|
+
if (!ok)
|
|
137
|
+
return;
|
|
138
|
+
const children = n.getChildren();
|
|
139
|
+
if (children.length === 0) {
|
|
140
|
+
if (n instanceof ColumnReferenceNode) {
|
|
141
|
+
if (found && found !== n) {
|
|
142
|
+
ok = false;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
found = n;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (n instanceof LiteralNode || n instanceof ParameterReferenceNode) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
ok = false;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
for (const c of children) {
|
|
155
|
+
visit(c);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
visit(node);
|
|
159
|
+
return ok ? found : undefined;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=rule-sargable-range-rewrite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-sargable-range-rewrite.js","sourceRoot":"","sources":["../../../../../src/planner/rules/predicate/rule-sargable-range-rewrite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: ORDER BY FD pruning
|
|
3
|
+
*
|
|
4
|
+
* Drops trailing ORDER BY keys that are functionally determined by the
|
|
5
|
+
* preceding bare-column keys under the source's FDs and equivalence classes.
|
|
6
|
+
*
|
|
7
|
+
* For a SortNode with ≥ 2 keys, walk the keys front-to-back maintaining
|
|
8
|
+
* `determined = closure({leading bare-column source-indices}, fds, ECs)`.
|
|
9
|
+
* Drop any trailing key whose expression is a bare `ColumnReferenceNode` and
|
|
10
|
+
* whose source-attribute index is already in `determined`. Direction and
|
|
11
|
+
* NULL placement on the dropped trailing key are irrelevant — once the
|
|
12
|
+
* preceding keys pin every value of that column to a single value per group,
|
|
13
|
+
* the trailing key cannot reorder anything.
|
|
14
|
+
*
|
|
15
|
+
* Sort-key matcher semantics: only bare `ColumnReferenceNode` keys
|
|
16
|
+
* participate in either direction of the reasoning. A non-bare-column key
|
|
17
|
+
* contributes nothing to `determined` (we can't prove what expression values
|
|
18
|
+
* "determine"), and a non-bare-column key cannot be dropped. The rule walks
|
|
19
|
+
* past non-bare keys treating them as opaque.
|
|
20
|
+
*
|
|
21
|
+
* Reasoning space: `fds`/`equivClasses` from `node.source.physical` are in
|
|
22
|
+
* source-attribute-INDEX space (positions in `source.getAttributes()`), NOT
|
|
23
|
+
* attribute IDs. The rule converts each sort-key's `ColumnReferenceNode.
|
|
24
|
+
* attributeId` to its source-attribute index before feeding `computeClosure`
|
|
25
|
+
* — mirroring how `SortNode.computePhysical` does its `leadIdx` lookup.
|
|
26
|
+
*
|
|
27
|
+
* Soundness: equality-class FDs from a `WHERE a = b` filter or a join key
|
|
28
|
+
* are sound here because every surviving row has equal values on the EC
|
|
29
|
+
* members, so the trailing key is a no-op tiebreaker.
|
|
30
|
+
*
|
|
31
|
+
* Ordering with other rules: this is a Structural-pass rule. It must run
|
|
32
|
+
* before `monotonic-limit-pushdown` (PostOptimization priority 8) so single-
|
|
33
|
+
* key reductions can enable the pushdown. That ordering is automatic since
|
|
34
|
+
* Structural runs before PostOptimization.
|
|
35
|
+
*/
|
|
36
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
37
|
+
import type { OptContext as _OptContext } from '../../framework/context.js';
|
|
38
|
+
export declare function ruleOrderByFdPruning(node: PlanNode, _context: _OptContext): PlanNode | null;
|
|
39
|
+
//# sourceMappingURL=rule-orderby-fd-pruning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-orderby-fd-pruning.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/sort/rule-orderby-fd-pruning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,IAAI,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAO5E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAmD3F"}
|