@quereus/quereus 2.9.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/func/builtins/conversion.d.ts.map +1 -1
- package/dist/src/func/builtins/conversion.js +12 -1
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +22 -8
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/generation.d.ts.map +1 -1
- package/dist/src/func/builtins/generation.js +26 -1
- package/dist/src/func/builtins/generation.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +5 -1
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/json-tvf.d.ts.map +1 -1
- package/dist/src/func/builtins/json-tvf.js +16 -2
- package/dist/src/func/builtins/json-tvf.js.map +1 -1
- package/dist/src/func/builtins/schema.d.ts +4 -0
- package/dist/src/func/builtins/schema.d.ts.map +1 -1
- package/dist/src/func/builtins/schema.js +270 -11
- package/dist/src/func/builtins/schema.js.map +1 -1
- package/dist/src/func/registration.d.ts +19 -1
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +8 -3
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +12 -4
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/planner/analysis/assertion-classifier.d.ts +71 -0
- package/dist/src/planner/analysis/assertion-classifier.d.ts.map +1 -0
- package/dist/src/planner/analysis/assertion-classifier.js +286 -0
- package/dist/src/planner/analysis/assertion-classifier.js.map +1 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.d.ts +34 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.d.ts.map +1 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.js +119 -0
- package/dist/src/planner/analysis/assertion-hoist-cache.js.map +1 -0
- package/dist/src/planner/analysis/binding-extractor.d.ts +58 -0
- package/dist/src/planner/analysis/binding-extractor.d.ts.map +1 -0
- package/dist/src/planner/analysis/binding-extractor.js +110 -0
- package/dist/src/planner/analysis/binding-extractor.js.map +1 -0
- package/dist/src/planner/analysis/change-scope.d.ts +184 -0
- package/dist/src/planner/analysis/change-scope.d.ts.map +1 -0
- package/dist/src/planner/analysis/change-scope.js +825 -0
- package/dist/src/planner/analysis/change-scope.js.map +1 -0
- package/dist/src/planner/analysis/check-extraction.d.ts +29 -0
- package/dist/src/planner/analysis/check-extraction.d.ts.map +1 -0
- package/dist/src/planner/analysis/check-extraction.js +420 -0
- package/dist/src/planner/analysis/check-extraction.js.map +1 -0
- package/dist/src/planner/analysis/constraint-extractor.d.ts +47 -7
- package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.js +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/table.d.ts.map +1 -1
- package/dist/src/planner/building/table.js +1 -1
- package/dist/src/planner/building/table.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +10 -1
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/characteristics.js +24 -5
- package/dist/src/planner/framework/characteristics.js.map +1 -1
- package/dist/src/planner/framework/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 +0 -9
- package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
- package/dist/src/planner/framework/physical-utils.js +0 -31
- package/dist/src/planner/framework/physical-utils.js.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.d.ts +25 -0
- package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.js +75 -8
- package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
- package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/alias-node.js +6 -1
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.js +17 -3
- package/dist/src/planner/nodes/asof-scan-node.js.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.js +19 -9
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
- package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/distinct-node.js +10 -6
- package/dist/src/planner/nodes/distinct-node.js.map +1 -1
- package/dist/src/planner/nodes/empty-relation-node.d.ts +27 -0
- package/dist/src/planner/nodes/empty-relation-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/empty-relation-node.js +61 -0
- package/dist/src/planner/nodes/empty-relation-node.js.map +1 -0
- package/dist/src/planner/nodes/filter.d.ts.map +1 -1
- package/dist/src/planner/nodes/filter.js +65 -5
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.js +8 -6
- package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +12 -9
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +24 -1
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +86 -0
- package/dist/src/planner/nodes/join-utils.js.map +1 -1
- package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
- package/dist/src/planner/nodes/limit-offset.js +6 -1
- package/dist/src/planner/nodes/limit-offset.js.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +19 -9
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.js +5 -2
- package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts +1 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +1 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +186 -4
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +75 -30
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts +24 -2
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +101 -1
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.d.ts +9 -1
- package/dist/src/planner/nodes/retrieve-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/retrieve-node.js +21 -0
- package/dist/src/planner/nodes/retrieve-node.js.map +1 -1
- package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/returning-node.js +64 -28
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts +1 -0
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +12 -0
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.js +15 -0
- package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
- package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
- package/dist/src/planner/nodes/single-row.js +3 -1
- package/dist/src/planner/nodes/single-row.js.map +1 -1
- package/dist/src/planner/nodes/sort.d.ts.map +1 -1
- package/dist/src/planner/nodes/sort.js +10 -3
- package/dist/src/planner/nodes/sort.js.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.js +8 -8
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +3 -3
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +26 -8
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/nodes/table-function-call.d.ts +4 -1
- package/dist/src/planner/nodes/table-function-call.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-function-call.js +224 -14
- package/dist/src/planner/nodes/table-function-call.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +9 -2
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer-tuning.d.ts +29 -1
- package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
- package/dist/src/planner/optimizer-tuning.js +3 -0
- package/dist/src/planner/optimizer-tuning.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +187 -0
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +22 -7
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts +30 -0
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.d.ts.map +1 -0
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js +116 -0
- package/dist/src/planner/rules/aggregate/rule-groupby-fd-simplification.js.map +1 -0
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +7 -7
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -1
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +18 -16
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts +56 -0
- package/dist/src/planner/rules/join/rule-join-elimination.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-join-elimination.js +326 -0
- package/dist/src/planner/rules/join/rule-join-elimination.js.map +1 -0
- package/dist/src/planner/rules/join/rule-join-greedy-commute.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-greedy-commute.js +10 -2
- package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts +20 -0
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js +181 -0
- package/dist/src/planner/rules/predicate/rule-aggregate-predicate-pushdown.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts +46 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js +156 -0
- package/dist/src/planner/rules/predicate/rule-empty-relation-folding.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts +30 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.js +60 -0
- package/dist/src/planner/rules/predicate/rule-filter-contradiction.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts +45 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js +210 -0
- package/dist/src/planner/rules/predicate/rule-predicate-inference-equivalence.js.map +1 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts +29 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.d.ts.map +1 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js +161 -0
- package/dist/src/planner/rules/predicate/rule-sargable-range-rewrite.js.map +1 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts +39 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.d.ts.map +1 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js +91 -0
- package/dist/src/planner/rules/sort/rule-orderby-fd-pruning.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts +35 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.d.ts.map +1 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js +74 -0
- package/dist/src/planner/rules/subquery/rule-anti-join-fk-empty.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts +27 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.d.ts.map +1 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js +103 -0
- package/dist/src/planner/rules/subquery/rule-semi-join-fk-trivial.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +1 -25
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/planner/scopes/global.js +2 -2
- package/dist/src/planner/scopes/global.js.map +1 -1
- package/dist/src/planner/type-utils.d.ts.map +1 -1
- package/dist/src/planner/type-utils.js +11 -0
- package/dist/src/planner/type-utils.js.map +1 -1
- package/dist/src/planner/util/fd-utils.d.ts +245 -0
- package/dist/src/planner/util/fd-utils.d.ts.map +1 -0
- package/dist/src/planner/util/fd-utils.js +1416 -0
- package/dist/src/planner/util/fd-utils.js.map +1 -0
- package/dist/src/planner/util/ind-utils.d.ts +79 -0
- package/dist/src/planner/util/ind-utils.d.ts.map +1 -0
- package/dist/src/planner/util/ind-utils.js +146 -0
- package/dist/src/planner/util/ind-utils.js.map +1 -0
- package/dist/src/planner/util/key-utils.d.ts +75 -14
- package/dist/src/planner/util/key-utils.d.ts.map +1 -1
- package/dist/src/planner/util/key-utils.js +234 -57
- package/dist/src/planner/util/key-utils.js.map +1 -1
- package/dist/src/runtime/delta-executor.d.ts +134 -0
- package/dist/src/runtime/delta-executor.d.ts.map +1 -0
- package/dist/src/runtime/delta-executor.js +382 -0
- package/dist/src/runtime/delta-executor.js.map +1 -0
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +52 -16
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-assertion.js +3 -2
- package/dist/src/runtime/emit/create-assertion.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +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/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 +81 -1
- package/dist/src/runtime/foreign-key-actions.js.map +1 -1
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +2 -0
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/schema/assertion.d.ts +8 -0
- package/dist/src/schema/assertion.d.ts.map +1 -1
- package/dist/src/schema/change-events.d.ts +5 -1
- package/dist/src/schema/change-events.d.ts.map +1 -1
- package/dist/src/schema/change-events.js.map +1 -1
- package/dist/src/schema/function.d.ts +65 -1
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js +31 -0
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/manager.d.ts +33 -0
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +95 -4
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/rename-rewriter.d.ts.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/table.d.ts +21 -2
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +17 -8
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/types/temporal-types.d.ts.map +1 -1
- package/dist/src/types/temporal-types.js +32 -0
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/vtab/events.d.ts +9 -0
- package/dist/src/vtab/events.d.ts.map +1 -1
- package/dist/src/vtab/events.js +19 -0
- package/dist/src/vtab/events.js.map +1 -1
- package/dist/src/vtab/memory/layer/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/utils/predicate.d.ts +2 -1
- package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -1
- package/dist/src/vtab/memory/utils/predicate.js +32 -1
- package/dist/src/vtab/memory/utils/predicate.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { createLogger } from '../../../common/logger.js';
|
|
2
2
|
import { JoinNode } from '../../nodes/join-node.js';
|
|
3
|
+
import { hasSingletonFd } from '../../util/fd-utils.js';
|
|
3
4
|
const log = createLogger('optimizer:rule:join-greedy-commute');
|
|
5
|
+
/** True when the relation provably emits at most one row. */
|
|
6
|
+
function isSingleton(node) {
|
|
7
|
+
const colCount = node.getAttributes().length;
|
|
8
|
+
if (colCount === 0)
|
|
9
|
+
return node.physical?.estimatedRows === 1;
|
|
10
|
+
return hasSingletonFd(node.physical?.fds, colCount);
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* Rule: Join Greedy Commute
|
|
6
14
|
*
|
|
@@ -19,8 +27,8 @@ export function ruleJoinGreedyCommute(node, _context) {
|
|
|
19
27
|
const leftRows = node.getLeftSource().estimatedRows ?? Number.POSITIVE_INFINITY;
|
|
20
28
|
const rightRows = node.getRightSource().estimatedRows ?? Number.POSITIVE_INFINITY;
|
|
21
29
|
// Prefer known finite estimatedRows; also detect <=1 row driver on either side
|
|
22
|
-
const leftIsSingleton = node.getLeftSource()
|
|
23
|
-
const rightIsSingleton = node.getRightSource()
|
|
30
|
+
const leftIsSingleton = isSingleton(node.getLeftSource());
|
|
31
|
+
const rightIsSingleton = isSingleton(node.getRightSource());
|
|
24
32
|
// If right is strictly better driver (smaller or singleton), swap
|
|
25
33
|
const shouldSwap = (rightIsSingleton && !leftIsSingleton) || (!rightIsSingleton && !leftIsSingleton && rightRows < leftRows);
|
|
26
34
|
if (!shouldSwap)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-join-greedy-commute.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-greedy-commute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"rule-join-greedy-commute.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-greedy-commute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,GAAG,GAAG,YAAY,CAAC,oCAAoC,CAAC,CAAC;AAE/D,6DAA6D;AAC7D,SAAS,WAAW,CAAC,IAAwB;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC;IAC7C,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,QAAQ,EAAE,aAAa,KAAK,CAAC,CAAC;IAC9D,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAc,EAAE,QAAoB;IACxE,IAAI,CAAC,CAAC,IAAI,YAAY,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAExE,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,aAAa,IAAI,MAAM,CAAC,iBAAiB,CAAC;IAChF,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,aAAa,IAAI,MAAM,CAAC,iBAAiB,CAAC;IAElF,+EAA+E;IAC/E,MAAM,eAAe,GAAG,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,WAAW,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IAE5D,kEAAkE;IAClE,MAAM,UAAU,GAAG,CAAC,gBAAgB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,gBAAgB,IAAI,CAAC,eAAe,IAAI,SAAS,GAAG,QAAQ,CAAC,CAAC;IAC7H,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,GAAG,CAAC,wFAAwF,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnI,qEAAqE;IACrE,MAAM,OAAO,GAAG,IAAI,QAAQ,CAC1B,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,cAAc,EAAwB,EAC3C,IAAI,CAAC,aAAa,EAAwB,EAC1C,IAAI,CAAC,WAAW,EAAE,EAClB,IAAI,CAAC,gBAAgB,EAAE,EACvB,IAAI,CAAC,eAAe,EAAE,CACvB,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -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":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,GAAG,GAAG,YAAY,CAAC,6CAA6C,CAAC,CAAC;AAIxE,SAAS,eAAe,CAAC,IAAc;IACtC,OAAO,IAAI,YAAY,aAAa;WAChC,IAAI,YAAY,mBAAmB;WACnC,IAAI,YAAY,iBAAiB,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,IAAc,EAAE,QAAoB;IAClF,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,MAAM,GAAG,IAAkB,CAAC;IAClC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,+BAA+B;IAC/B,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IAE/C,yEAAyE;IACzE,2EAA2E;IAC3E,mEAAmE;IACnE,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0D,CAAC;IACzF,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC,MAAM,YAAY,mBAAmB,CAAC;YAAE,SAAS;QACvD,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC;QACrC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAC9D,IAAI,MAAM,GAAG,CAAC;YAAE,SAAS;QACzB,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QACjF,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,yEAAyE;IACzE,cAAc;IACd,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAE1D,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC;IACtC,MAAM,qBAAqB,GAAG,cAAc,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAE3E,2CAA2C;IAC3C,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAE7C,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,MAAM,SAAS,GAAqB,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,qBAAqB,CAAC,EAAE,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACP,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,wEAAwE;IACxE,MAAM,iBAAiB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;IACnG,MAAM,eAAe,GAAG,gBAAgB,CAAC,iBAAiB,CAAE,CAAC;IAE7D,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAEhF,4EAA4E;IAC5E,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEhD,GAAG,CAAC,mCAAmC,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE1F,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC;IACf,CAAC;IACD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,SAAS,CAAE,CAAC;IACvD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,kBAAkB,CAC1B,IAAoB,EACpB,gBAA6C,EAC7C,cAAmF,EACnF,qBAA0C;IAE1C,MAAM,UAAU,GAAG,6BAA6B,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC3B,wEAAwE;QACxE,sEAAsE;QACtE,4DAA4D;QAC5D,OAAO,KAAK,CAAC;IACd,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAClD,+DAA+D;QAC/D,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,6BAA6B,CAAC,IAAoB;IAC1D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE;QACpB,IAAI,CAAC,YAAY,mBAAmB,EAAE,CAAC;YACtC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACxB,CAAC;IACF,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,UAAU,CAAC,IAAoB,EAAE,EAA+B;IACxE,EAAE,CAAC,IAAI,CAAC,CAAC;IACT,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,UAAU,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;AACF,CAAC;AAED,SAAS,qBAAqB,CAC7B,IAAoB,EACpB,cAAmF,EACnF,WAAiC;IAEjC,IAAI,IAAI,YAAY,mBAAmB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACvC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACrE,oFAAoF;QACpF,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO,IAAI,mBAAmB,CAC7B,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,UAAU,EACf,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,YAAY,EACpB,OAAO,CAAC,YAAY,CACpB,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,WAAW,GAAe,EAAE,CAAC;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1B,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,SAAS;QACV,CAAC;QACD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,CAAmB,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;QACzF,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,GAAG,IAAI,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAmB,CAAC;AACzD,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAiB,EAAE,SAA6B;IACzE,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;QAClC,OAAO,IAAI,aAAa,CACvB,GAAG,CAAC,KAAK,EACT,SAAS,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,SAAS,EACT,GAAG,CAAC,aAAa,EAAE,CACnB,CAAC;IACH,CAAC;IACD,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;QACxC,OAAO,IAAI,mBAAmB,CAC7B,GAAG,CAAC,KAAK,EACT,SAAS,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,SAAS,EACT,GAAG,CAAC,aAAa,EAAE,CACnB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,iBAAiB,CAC3B,GAAG,CAAC,KAAK,EACT,SAAS,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,SAAS,EACT,GAAG,CAAC,aAAa,EAAE,CACnB,CAAC;AACH,CAAC"}
|
|
@@ -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"}
|
|
@@ -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"}
|