@quereus/quereus 0.17.0 → 0.18.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 +372 -361
- package/dist/src/common/errors.d.ts +2 -18
- package/dist/src/common/errors.d.ts.map +1 -1
- package/dist/src/common/errors.js +6 -29
- package/dist/src/common/errors.js.map +1 -1
- package/dist/src/common/types.d.ts +8 -0
- package/dist/src/common/types.d.ts.map +1 -1
- package/dist/src/common/types.js +20 -0
- package/dist/src/common/types.js.map +1 -1
- package/dist/src/core/database-assertions.d.ts +19 -2
- package/dist/src/core/database-assertions.d.ts.map +1 -1
- package/dist/src/core/database-assertions.js +113 -32
- package/dist/src/core/database-assertions.js.map +1 -1
- package/dist/src/core/database-events.d.ts +17 -0
- package/dist/src/core/database-events.d.ts.map +1 -1
- package/dist/src/core/database-events.js +36 -0
- package/dist/src/core/database-events.js.map +1 -1
- package/dist/src/core/database.d.ts +11 -0
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +178 -85
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.d.ts +6 -0
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +42 -56
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/emit/ast-stringify.d.ts +1 -0
- package/dist/src/emit/ast-stringify.d.ts.map +1 -1
- package/dist/src/emit/ast-stringify.js +12 -2
- package/dist/src/emit/ast-stringify.js.map +1 -1
- package/dist/src/func/builtins/builtin-window-functions.d.ts.map +1 -1
- package/dist/src/func/builtins/builtin-window-functions.js +75 -0
- package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
- package/dist/src/func/builtins/conversion.js +9 -12
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/datetime.js +1 -1
- package/dist/src/func/builtins/datetime.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +15 -3
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +1 -11
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/json-helpers.js +1 -1
- package/dist/src/func/builtins/json-helpers.js.map +1 -1
- package/dist/src/func/builtins/json.d.ts.map +1 -1
- package/dist/src/func/builtins/json.js +2 -5
- package/dist/src/func/builtins/json.js.map +1 -1
- package/dist/src/func/builtins/schema.d.ts.map +1 -1
- package/dist/src/func/builtins/schema.js +30 -32
- package/dist/src/func/builtins/schema.js.map +1 -1
- package/dist/src/func/builtins/string.d.ts.map +1 -1
- package/dist/src/func/builtins/string.js +40 -64
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/func/builtins/timespan.d.ts.map +1 -1
- package/dist/src/func/builtins/timespan.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/ast.d.ts +9 -2
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/lexer.d.ts +1 -0
- package/dist/src/parser/lexer.d.ts.map +1 -1
- package/dist/src/parser/lexer.js +3 -0
- package/dist/src/parser/lexer.js.map +1 -1
- package/dist/src/parser/parser.d.ts +11 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +75 -135
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/planner/analysis/const-evaluator.d.ts.map +1 -1
- package/dist/src/planner/analysis/const-evaluator.js +6 -3
- package/dist/src/planner/analysis/const-evaluator.js.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.d.ts +2 -1
- package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.js +154 -22
- package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
- package/dist/src/planner/building/alter-table.d.ts.map +1 -1
- package/dist/src/planner/building/alter-table.js +18 -1
- package/dist/src/planner/building/alter-table.js.map +1 -1
- package/dist/src/planner/building/analyze.d.ts +5 -0
- package/dist/src/planner/building/analyze.d.ts.map +1 -0
- package/dist/src/planner/building/analyze.js +5 -0
- package/dist/src/planner/building/analyze.js.map +1 -0
- package/dist/src/planner/building/block.d.ts.map +1 -1
- package/dist/src/planner/building/block.js +3 -0
- package/dist/src/planner/building/block.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +25 -3
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/building/delete.d.ts.map +1 -1
- package/dist/src/planner/building/delete.js +11 -0
- package/dist/src/planner/building/delete.js.map +1 -1
- package/dist/src/planner/building/drop-assertion.d.ts.map +1 -1
- package/dist/src/planner/building/drop-assertion.js +2 -1
- package/dist/src/planner/building/drop-assertion.js.map +1 -1
- package/dist/src/planner/building/expression.d.ts.map +1 -1
- package/dist/src/planner/building/expression.js +55 -7
- package/dist/src/planner/building/expression.js.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.d.ts +16 -0
- package/dist/src/planner/building/foreign-key-builder.d.ts.map +1 -0
- package/dist/src/planner/building/foreign-key-builder.js +269 -0
- package/dist/src/planner/building/foreign-key-builder.js.map +1 -0
- package/dist/src/planner/building/function-call.d.ts.map +1 -1
- package/dist/src/planner/building/function-call.js +3 -2
- package/dist/src/planner/building/function-call.js.map +1 -1
- package/dist/src/planner/building/insert.d.ts.map +1 -1
- package/dist/src/planner/building/insert.js +91 -10
- package/dist/src/planner/building/insert.js.map +1 -1
- package/dist/src/planner/building/schema-resolution.d.ts +4 -0
- package/dist/src/planner/building/schema-resolution.d.ts.map +1 -1
- package/dist/src/planner/building/schema-resolution.js +14 -3
- package/dist/src/planner/building/schema-resolution.js.map +1 -1
- package/dist/src/planner/building/select-aggregates.d.ts +1 -0
- package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
- package/dist/src/planner/building/select-aggregates.js +118 -3
- package/dist/src/planner/building/select-aggregates.js.map +1 -1
- package/dist/src/planner/building/select-modifiers.js +3 -3
- package/dist/src/planner/building/select-modifiers.js.map +1 -1
- package/dist/src/planner/building/select-window.js +9 -8
- package/dist/src/planner/building/select-window.js.map +1 -1
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +21 -10
- 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 +5 -3
- 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 +30 -1
- package/dist/src/planner/building/update.js.map +1 -1
- package/dist/src/planner/building/with.js +1 -1
- package/dist/src/planner/building/with.js.map +1 -1
- package/dist/src/planner/cache/reference-graph.d.ts +1 -1
- package/dist/src/planner/cache/reference-graph.js +1 -1
- package/dist/src/planner/cost/index.d.ts +10 -3
- package/dist/src/planner/cost/index.d.ts.map +1 -1
- package/dist/src/planner/cost/index.js +17 -3
- package/dist/src/planner/cost/index.js.map +1 -1
- package/dist/src/planner/debug.js +1 -1
- package/dist/src/planner/debug.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +1 -1
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/pass.d.ts +3 -1
- package/dist/src/planner/framework/pass.d.ts.map +1 -1
- package/dist/src/planner/framework/pass.js +62 -18
- package/dist/src/planner/framework/pass.js.map +1 -1
- package/dist/src/planner/framework/physical-utils.d.ts +5 -0
- package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
- package/dist/src/planner/framework/physical-utils.js +19 -0
- package/dist/src/planner/framework/physical-utils.js.map +1 -1
- package/dist/src/planner/framework/trace.d.ts.map +1 -1
- package/dist/src/planner/framework/trace.js +3 -2
- package/dist/src/planner/framework/trace.js.map +1 -1
- package/dist/src/planner/nodes/alias-node.d.ts +2 -1
- package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/alias-node.js +8 -0
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/alter-table-node.d.ts +42 -0
- package/dist/src/planner/nodes/alter-table-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/alter-table-node.js +55 -0
- package/dist/src/planner/nodes/alter-table-node.js.map +1 -0
- package/dist/src/planner/nodes/analyze-node.d.ts +25 -0
- package/dist/src/planner/nodes/analyze-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/analyze-node.js +83 -0
- package/dist/src/planner/nodes/analyze-node.js.map +1 -0
- package/dist/src/planner/nodes/bloom-join-node.d.ts +66 -0
- package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/bloom-join-node.js +200 -0
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -0
- package/dist/src/planner/nodes/constraint-check-node.d.ts +1 -1
- package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cte-reference-node.js +7 -7
- package/dist/src/planner/nodes/cte-reference-node.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts +9 -1
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +69 -79
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.d.ts +60 -0
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/merge-join-node.js +207 -0
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -0
- 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/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +3 -2
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts +2 -1
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +6 -2
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/returning-node.js +3 -2
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/subquery.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/nodes/update-node.d.ts +2 -0
- package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/update-node.js +2 -1
- package/dist/src/planner/nodes/update-node.js.map +1 -1
- package/dist/src/planner/nodes/window-function.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-function.js +7 -7
- package/dist/src/planner/nodes/window-function.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts +2 -2
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +9 -14
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +40 -2
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/planning-context.d.ts.map +1 -1
- package/dist/src/planner/planning-context.js +1 -6
- package/dist/src/planner/planning-context.js.map +1 -1
- package/dist/src/planner/resolve.d.ts.map +1 -1
- package/dist/src/planner/resolve.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +157 -28
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.d.ts.map +1 -1
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +27 -6
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.d.ts +19 -0
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.d.ts.map +1 -0
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.js +53 -0
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.js.map +1 -0
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js +5 -0
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js.map +1 -1
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts +18 -0
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.d.ts.map +1 -0
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js +37 -0
- package/dist/src/planner/rules/distinct/rule-distinct-elimination.js.map +1 -0
- package/dist/src/planner/rules/join/rule-join-key-inference.d.ts +8 -3
- package/dist/src/planner/rules/join/rule-join-key-inference.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-key-inference.js +28 -17
- package/dist/src/planner/rules/join/rule-join-key-inference.js.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts +16 -0
- package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-join-physical-selection.js +216 -0
- package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -0
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +34 -4
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts +23 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +293 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -0
- package/dist/src/planner/scopes/multi.d.ts +3 -2
- package/dist/src/planner/scopes/multi.d.ts.map +1 -1
- package/dist/src/planner/scopes/multi.js +32 -7
- package/dist/src/planner/scopes/multi.js.map +1 -1
- package/dist/src/planner/scopes/shadow.d.ts +20 -0
- package/dist/src/planner/scopes/shadow.d.ts.map +1 -0
- package/dist/src/planner/scopes/shadow.js +31 -0
- package/dist/src/planner/scopes/shadow.js.map +1 -0
- package/dist/src/planner/stats/analyze.d.ts +17 -0
- package/dist/src/planner/stats/analyze.d.ts.map +1 -0
- package/dist/src/planner/stats/analyze.js +114 -0
- package/dist/src/planner/stats/analyze.js.map +1 -0
- package/dist/src/planner/stats/catalog-stats.d.ts +80 -0
- package/dist/src/planner/stats/catalog-stats.d.ts.map +1 -0
- package/dist/src/planner/stats/catalog-stats.js +248 -0
- package/dist/src/planner/stats/catalog-stats.js.map +1 -0
- package/dist/src/planner/stats/histogram.d.ts +24 -0
- package/dist/src/planner/stats/histogram.d.ts.map +1 -0
- package/dist/src/planner/stats/histogram.js +142 -0
- package/dist/src/planner/stats/histogram.js.map +1 -0
- package/dist/src/planner/type-utils.d.ts.map +1 -1
- package/dist/src/planner/type-utils.js +8 -2
- package/dist/src/planner/type-utils.js.map +1 -1
- package/dist/src/planner/util/key-utils.d.ts +48 -2
- package/dist/src/planner/util/key-utils.d.ts.map +1 -1
- package/dist/src/planner/util/key-utils.js +123 -0
- package/dist/src/planner/util/key-utils.js.map +1 -1
- package/dist/src/planner/validation/determinism-validator.d.ts +9 -0
- package/dist/src/planner/validation/determinism-validator.d.ts.map +1 -1
- package/dist/src/planner/validation/determinism-validator.js +11 -0
- package/dist/src/planner/validation/determinism-validator.js.map +1 -1
- package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
- package/dist/src/planner/validation/plan-validator.js +1 -0
- package/dist/src/planner/validation/plan-validator.js.map +1 -1
- package/dist/src/runtime/context-helpers.d.ts +34 -10
- package/dist/src/runtime/context-helpers.d.ts.map +1 -1
- package/dist/src/runtime/context-helpers.js +115 -39
- package/dist/src/runtime/context-helpers.js.map +1 -1
- package/dist/src/runtime/deferred-constraint-queue.d.ts +0 -1
- package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
- package/dist/src/runtime/deferred-constraint-queue.js +10 -23
- package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
- package/dist/src/runtime/descriptor-helpers.d.ts +7 -0
- package/dist/src/runtime/descriptor-helpers.d.ts.map +1 -0
- package/dist/src/runtime/descriptor-helpers.js +24 -0
- package/dist/src/runtime/descriptor-helpers.js.map +1 -0
- package/dist/src/runtime/emission-context.d.ts +7 -1
- package/dist/src/runtime/emission-context.d.ts.map +1 -1
- package/dist/src/runtime/emission-context.js +16 -0
- package/dist/src/runtime/emission-context.js.map +1 -1
- package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
- package/dist/src/runtime/emit/aggregate.js +97 -93
- package/dist/src/runtime/emit/aggregate.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts +5 -0
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -0
- package/dist/src/runtime/emit/alter-table.js +209 -0
- package/dist/src/runtime/emit/alter-table.js.map +1 -0
- package/dist/src/runtime/emit/analyze.d.ts +9 -0
- package/dist/src/runtime/emit/analyze.d.ts.map +1 -0
- package/dist/src/runtime/emit/analyze.js +72 -0
- package/dist/src/runtime/emit/analyze.js.map +1 -0
- package/dist/src/runtime/emit/array-index.d.ts.map +1 -1
- package/dist/src/runtime/emit/array-index.js +4 -2
- package/dist/src/runtime/emit/array-index.js.map +1 -1
- package/dist/src/runtime/emit/between.d.ts.map +1 -1
- package/dist/src/runtime/emit/between.js +8 -20
- package/dist/src/runtime/emit/between.js.map +1 -1
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +155 -126
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/bloom-join.d.ts +12 -0
- package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -0
- package/dist/src/runtime/emit/bloom-join.js +114 -0
- package/dist/src/runtime/emit/bloom-join.js.map +1 -0
- package/dist/src/runtime/emit/cache.js +2 -2
- package/dist/src/runtime/emit/cache.js.map +1 -1
- package/dist/src/runtime/emit/cast.d.ts.map +1 -1
- package/dist/src/runtime/emit/cast.js +31 -117
- package/dist/src/runtime/emit/cast.js.map +1 -1
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +2 -24
- package/dist/src/runtime/emit/constraint-check.js.map +1 -1
- package/dist/src/runtime/emit/cte-reference.d.ts.map +1 -1
- package/dist/src/runtime/emit/cte-reference.js +11 -5
- package/dist/src/runtime/emit/cte-reference.js.map +1 -1
- package/dist/src/runtime/emit/distinct.d.ts.map +1 -1
- package/dist/src/runtime/emit/distinct.js +21 -12
- package/dist/src/runtime/emit/distinct.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +5 -1
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/drop-assertion.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-assertion.js +2 -0
- package/dist/src/runtime/emit/drop-assertion.js.map +1 -1
- package/dist/src/runtime/emit/filter.d.ts.map +1 -1
- package/dist/src/runtime/emit/filter.js +26 -7
- package/dist/src/runtime/emit/filter.js.map +1 -1
- package/dist/src/runtime/emit/internal-recursive-cte-ref.d.ts.map +1 -1
- package/dist/src/runtime/emit/internal-recursive-cte-ref.js +11 -5
- package/dist/src/runtime/emit/internal-recursive-cte-ref.js.map +1 -1
- package/dist/src/runtime/emit/join.d.ts +1 -1
- package/dist/src/runtime/emit/join.d.ts.map +1 -1
- package/dist/src/runtime/emit/join.js +44 -33
- package/dist/src/runtime/emit/join.js.map +1 -1
- package/dist/src/runtime/emit/merge-join.d.ts +14 -0
- package/dist/src/runtime/emit/merge-join.d.ts.map +1 -0
- package/dist/src/runtime/emit/merge-join.js +152 -0
- package/dist/src/runtime/emit/merge-join.js.map +1 -0
- package/dist/src/runtime/emit/parameter.d.ts.map +1 -1
- package/dist/src/runtime/emit/parameter.js +10 -32
- package/dist/src/runtime/emit/parameter.js.map +1 -1
- package/dist/src/runtime/emit/project.d.ts.map +1 -1
- package/dist/src/runtime/emit/project.js +22 -12
- package/dist/src/runtime/emit/project.js.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.js +5 -9
- package/dist/src/runtime/emit/recursive-cte.js.map +1 -1
- package/dist/src/runtime/emit/returning.d.ts.map +1 -1
- package/dist/src/runtime/emit/returning.js +14 -8
- package/dist/src/runtime/emit/returning.js.map +1 -1
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +4 -1
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
- package/dist/src/runtime/emit/set-operation.js +8 -5
- package/dist/src/runtime/emit/set-operation.js.map +1 -1
- package/dist/src/runtime/emit/sort.js +2 -2
- package/dist/src/runtime/emit/sort.js.map +1 -1
- package/dist/src/runtime/emit/subquery.js +2 -2
- package/dist/src/runtime/emit/subquery.js.map +1 -1
- package/dist/src/runtime/emit/table-valued-function.d.ts.map +1 -1
- package/dist/src/runtime/emit/table-valued-function.js +21 -7
- package/dist/src/runtime/emit/table-valued-function.js.map +1 -1
- package/dist/src/runtime/emit/unary.js +2 -2
- package/dist/src/runtime/emit/unary.js.map +1 -1
- package/dist/src/runtime/emit/update.d.ts.map +1 -1
- package/dist/src/runtime/emit/update.js +43 -21
- package/dist/src/runtime/emit/update.js.map +1 -1
- package/dist/src/runtime/emit/window.d.ts.map +1 -1
- package/dist/src/runtime/emit/window.js +368 -126
- package/dist/src/runtime/emit/window.js.map +1 -1
- package/dist/src/runtime/foreign-key-actions.d.ts +15 -0
- package/dist/src/runtime/foreign-key-actions.d.ts.map +1 -0
- package/dist/src/runtime/foreign-key-actions.js +109 -0
- package/dist/src/runtime/foreign-key-actions.js.map +1 -0
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +8 -0
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/src/runtime/scheduler.js +4 -1
- package/dist/src/runtime/scheduler.js.map +1 -1
- package/dist/src/runtime/types.d.ts +6 -5
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/schema/change-events.d.ts +36 -8
- package/dist/src/schema/change-events.d.ts.map +1 -1
- package/dist/src/schema/change-events.js.map +1 -1
- package/dist/src/schema/column.d.ts +5 -1
- package/dist/src/schema/column.d.ts.map +1 -1
- package/dist/src/schema/column.js +1 -2
- package/dist/src/schema/column.js.map +1 -1
- package/dist/src/schema/manager.d.ts +54 -4
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +353 -313
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/schema-differ.js +3 -3
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/schema/schema.d.ts +1 -1
- package/dist/src/schema/schema.js +2 -2
- package/dist/src/schema/schema.js.map +1 -1
- package/dist/src/schema/table.d.ts +49 -0
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +30 -11
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/types/builtin-types.d.ts.map +1 -1
- package/dist/src/types/builtin-types.js +26 -95
- package/dist/src/types/builtin-types.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/json-type.d.ts.map +1 -1
- package/dist/src/types/json-type.js +28 -40
- package/dist/src/types/json-type.js.map +1 -1
- package/dist/src/types/logical-type.d.ts +6 -0
- package/dist/src/types/logical-type.d.ts.map +1 -1
- package/dist/src/types/logical-type.js +12 -0
- 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 +8 -37
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/util/coercion.d.ts +4 -5
- package/dist/src/util/coercion.d.ts.map +1 -1
- package/dist/src/util/coercion.js +10 -14
- package/dist/src/util/coercion.js.map +1 -1
- package/dist/src/util/comparison.d.ts +34 -21
- package/dist/src/util/comparison.d.ts.map +1 -1
- package/dist/src/util/comparison.js +77 -43
- package/dist/src/util/comparison.js.map +1 -1
- package/dist/src/util/environment.d.ts +0 -8
- package/dist/src/util/environment.d.ts.map +1 -1
- package/dist/src/util/environment.js +0 -12
- package/dist/src/util/environment.js.map +1 -1
- package/dist/src/util/key-serializer.d.ts +33 -0
- package/dist/src/util/key-serializer.d.ts.map +1 -0
- package/dist/src/util/key-serializer.js +95 -0
- package/dist/src/util/key-serializer.js.map +1 -0
- package/dist/src/util/plugin-helper.d.ts.map +1 -1
- package/dist/src/util/plugin-helper.js +21 -45
- package/dist/src/util/plugin-helper.js.map +1 -1
- package/dist/src/util/serialization.d.ts +1 -0
- package/dist/src/util/serialization.d.ts.map +1 -1
- package/dist/src/util/serialization.js +8 -1
- package/dist/src/util/serialization.js.map +1 -1
- package/dist/src/util/working-table-iterable.d.ts +6 -5
- package/dist/src/util/working-table-iterable.d.ts.map +1 -1
- package/dist/src/util/working-table-iterable.js +8 -15
- package/dist/src/util/working-table-iterable.js.map +1 -1
- package/dist/src/vtab/best-access-plan.d.ts +12 -0
- package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
- package/dist/src/vtab/best-access-plan.js +22 -0
- package/dist/src/vtab/best-access-plan.js.map +1 -1
- package/dist/src/vtab/manifest.d.ts +3 -1
- package/dist/src/vtab/manifest.d.ts.map +1 -1
- package/dist/src/vtab/memory/index.d.ts +2 -2
- package/dist/src/vtab/memory/index.d.ts.map +1 -1
- package/dist/src/vtab/memory/index.js +4 -7
- package/dist/src/vtab/memory/index.js.map +1 -1
- package/dist/src/vtab/memory/layer/base-cursor.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/base-cursor.js +37 -9
- package/dist/src/vtab/memory/layer/base-cursor.js.map +1 -1
- package/dist/src/vtab/memory/layer/base.js +1 -1
- package/dist/src/vtab/memory/layer/base.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +15 -3
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +85 -37
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/scan-plan.d.ts +2 -0
- package/dist/src/vtab/memory/layer/scan-plan.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/scan-plan.js +153 -78
- package/dist/src/vtab/memory/layer/scan-plan.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction-cursor.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction-cursor.js +39 -9
- package/dist/src/vtab/memory/layer/transaction-cursor.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +1 -5
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +14 -24
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +88 -283
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/dist/src/vtab/memory/table.d.ts +9 -0
- package/dist/src/vtab/memory/table.d.ts.map +1 -1
- package/dist/src/vtab/memory/table.js +121 -18
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/memory/types.d.ts +1 -0
- package/dist/src/vtab/memory/types.d.ts.map +1 -1
- package/dist/src/vtab/memory/utils/primary-key.js.map +1 -1
- package/dist/src/vtab/module.d.ts +13 -0
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/dist/src/vtab/table.d.ts +9 -0
- package/dist/src/vtab/table.d.ts.map +1 -1
- package/dist/src/vtab/table.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: IN-Subquery Cache
|
|
3
|
+
*
|
|
4
|
+
* Required Characteristics:
|
|
5
|
+
* - Node must be an InNode with a subquery source (not a value list)
|
|
6
|
+
* - Source must be uncorrelated (no outer attribute references)
|
|
7
|
+
* - Source must be deterministic and read-only (functional)
|
|
8
|
+
* - Source must not already be cached
|
|
9
|
+
*
|
|
10
|
+
* Applied When:
|
|
11
|
+
* - IN subquery source would be re-executed for every outer row in a filter predicate
|
|
12
|
+
*
|
|
13
|
+
* Benefits: Materializes the subquery result once and replays from cache on subsequent
|
|
14
|
+
* evaluations, reducing O(N * K) CTE/subquery evaluations to O(K + N * K_cached)
|
|
15
|
+
*/
|
|
16
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
17
|
+
import type { OptContext } from '../../framework/context.js';
|
|
18
|
+
export declare function ruleInSubqueryCache(node: PlanNode, context: OptContext): PlanNode | null;
|
|
19
|
+
//# sourceMappingURL=rule-in-subquery-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-in-subquery-cache.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-in-subquery-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAS7D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAoDxF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: IN-Subquery Cache
|
|
3
|
+
*
|
|
4
|
+
* Required Characteristics:
|
|
5
|
+
* - Node must be an InNode with a subquery source (not a value list)
|
|
6
|
+
* - Source must be uncorrelated (no outer attribute references)
|
|
7
|
+
* - Source must be deterministic and read-only (functional)
|
|
8
|
+
* - Source must not already be cached
|
|
9
|
+
*
|
|
10
|
+
* Applied When:
|
|
11
|
+
* - IN subquery source would be re-executed for every outer row in a filter predicate
|
|
12
|
+
*
|
|
13
|
+
* Benefits: Materializes the subquery result once and replays from cache on subsequent
|
|
14
|
+
* evaluations, reducing O(N * K) CTE/subquery evaluations to O(K + N * K_cached)
|
|
15
|
+
*/
|
|
16
|
+
import { createLogger } from '../../../common/logger.js';
|
|
17
|
+
import { InNode } from '../../nodes/subquery.js';
|
|
18
|
+
import { CacheNode } from '../../nodes/cache-node.js';
|
|
19
|
+
import { CapabilityDetectors, CachingAnalysis, PlanNodeCharacteristics } from '../../framework/characteristics.js';
|
|
20
|
+
import { isCorrelatedSubquery } from '../../cache/correlation-detector.js';
|
|
21
|
+
import { PlanNodeType } from '../../nodes/plan-node-type.js';
|
|
22
|
+
const log = createLogger('optimizer:rule:in-subquery-cache');
|
|
23
|
+
export function ruleInSubqueryCache(node, context) {
|
|
24
|
+
// Guard: must be an InNode with a subquery source
|
|
25
|
+
if (node.nodeType !== PlanNodeType.In) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const inNode = node;
|
|
29
|
+
if (!inNode.source) {
|
|
30
|
+
return null; // Value-list IN, nothing to cache
|
|
31
|
+
}
|
|
32
|
+
const source = inNode.source;
|
|
33
|
+
// Gate: source must not already be cached
|
|
34
|
+
if (CapabilityDetectors.isCached(source) && source.isCached()) {
|
|
35
|
+
log('IN-subquery source already cached, skipping');
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
// Gate: source must be uncorrelated (no outer attribute references)
|
|
39
|
+
if (isCorrelatedSubquery(source)) {
|
|
40
|
+
log('IN-subquery is correlated, skipping cache wrapping');
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Gate: source must be deterministic and read-only
|
|
44
|
+
if (!PlanNodeCharacteristics.isFunctional(source)) {
|
|
45
|
+
log('IN-subquery source is not functional, skipping cache wrapping');
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
log('Wrapping uncorrelated IN-subquery source in CacheNode');
|
|
49
|
+
const cacheThreshold = Math.min(CachingAnalysis.getCacheThreshold(source), context.tuning.cte.maxCacheThreshold);
|
|
50
|
+
const cachedSource = new CacheNode(source.scope, source, 'memory', cacheThreshold);
|
|
51
|
+
return new InNode(inNode.scope, inNode.expression, inNode.condition, cachedSource, inNode.values);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=rule-in-subquery-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-in-subquery-cache.js","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-in-subquery-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AACnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,MAAM,GAAG,GAAG,YAAY,CAAC,kCAAkC,CAAC,CAAC;AAE7D,MAAM,UAAU,mBAAmB,CAAC,IAAc,EAAE,OAAmB;IACtE,kDAAkD;IAClD,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,EAAE,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG,IAAc,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,CAAC,kCAAkC;IAChD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAE7B,0CAA0C;IAC1C,IAAI,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC/D,GAAG,CAAC,6CAA6C,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,oEAAoE;IACpE,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACb,CAAC;IAED,mDAAmD;IACnD,IAAI,CAAC,uBAAuB,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,+DAA+D,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,uDAAuD,CAAC,CAAC;IAE7D,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAC9B,eAAe,CAAC,iBAAiB,CAAC,MAAM,CAAC,EACzC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CACpC,CAAC;IAEF,MAAM,YAAY,GAAG,IAAI,SAAS,CACjC,MAAM,CAAC,KAAK,EACZ,MAAM,EACN,QAAQ,EACR,cAAc,CACd,CAAC;IAEF,OAAO,IAAI,MAAM,CAChB,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,SAAS,EAChB,YAAY,EACZ,MAAM,CAAC,MAAM,CACb,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-mutating-subquery-cache.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-mutating-subquery-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAO7D,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"rule-mutating-subquery-cache.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-mutating-subquery-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAO7D,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CA2D/F"}
|
|
@@ -21,6 +21,11 @@ export function ruleMutatingSubqueryCache(node, _context) {
|
|
|
21
21
|
if (!CapabilityDetectors.isJoin(node)) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
|
+
// Skip physical join nodes — they already materialize the build side,
|
|
25
|
+
// so caching is inherent and we must not replace them with logical JoinNodes.
|
|
26
|
+
if (!(node instanceof JoinNode)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
24
29
|
log('Checking join operation for side effects on right side');
|
|
25
30
|
// Get join-specific characteristics
|
|
26
31
|
const joinNode = node;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-mutating-subquery-cache.js","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-mutating-subquery-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,eAAe,EAAoB,MAAM,oCAAoC,CAAC;AAErI,MAAM,GAAG,GAAG,YAAY,CAAC,wCAAwC,CAAC,CAAC;AAEnE,MAAM,UAAU,yBAAyB,CAAC,IAAc,EAAE,QAAoB;IAC7E,2CAA2C;IAC3C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,wDAAwD,CAAC,CAAC;IAE9D,oCAAoC;IACpC,MAAM,QAAQ,GAAG,IAAmB,CAAC;IACrC,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;IAE5C,4DAA4D;IAC5D,MAAM,cAAc,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,cAAc,EAAE,CAAC;QACrB,GAAG,CAAC,oEAAoE,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACb,CAAC;IAED,wCAAwC;IACxC,IAAI,mBAAmB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;QACrE,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,8EAA8E,CAAC,CAAC;IAEpF,8DAA8D;IAC9D,MAAM,SAAS,GAAG,eAAe,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAE/D,wCAAwC;IACxC,MAAM,eAAe,GAAG,IAAI,SAAS,CACpC,SAAS,CAAC,KAAK,EACf,SAAS,EACT,QAAQ,EACR,SAAS,CACT,CAAC;IAEF,8CAA8C;IAC9C,iGAAiG;IACjG,MAAM,MAAM,GAAG,IAAI,QAAQ,CAC1B,IAAI,CAAC,KAAK,EACV,QAAQ,CAAC,aAAa,EAAE,EACxB,eAAe,EACf,QAAQ,CAAC,WAAW,EAAE,EACtB,QAAQ,CAAC,gBAAgB,EAAE;IAC3B,+EAA+E;IAC/E,kEAAkE;IAClE,QAAQ,CAAC,eAAe,EAAE,CAC1B,CAAC;IAEF,GAAG,CAAC,8EAA8E,EAAE,SAAS,CAAC,CAAC;IAC/F,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,iCAAiC,CAAC,IAAc;IACxD,oCAAoC;IACpC,IAAI,uBAAuB,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,IAAI,iCAAiC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,uEAAuE;IACvE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QAC5C,IAAI,iCAAiC,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"rule-mutating-subquery-cache.js","sourceRoot":"","sources":["../../../../../src/planner/rules/cache/rule-mutating-subquery-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,eAAe,EAAoB,MAAM,oCAAoC,CAAC;AAErI,MAAM,GAAG,GAAG,YAAY,CAAC,wCAAwC,CAAC,CAAC;AAEnE,MAAM,UAAU,yBAAyB,CAAC,IAAc,EAAE,QAAoB;IAC7E,2CAA2C;IAC3C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,sEAAsE;IACtE,8EAA8E;IAC9E,IAAI,CAAC,CAAC,IAAI,YAAY,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,wDAAwD,CAAC,CAAC;IAE9D,oCAAoC;IACpC,MAAM,QAAQ,GAAG,IAAmB,CAAC;IACrC,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;IAE5C,4DAA4D;IAC5D,MAAM,cAAc,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,cAAc,EAAE,CAAC;QACrB,GAAG,CAAC,oEAAoE,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACb,CAAC;IAED,wCAAwC;IACxC,IAAI,mBAAmB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;QACrE,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,8EAA8E,CAAC,CAAC;IAEpF,8DAA8D;IAC9D,MAAM,SAAS,GAAG,eAAe,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAE/D,wCAAwC;IACxC,MAAM,eAAe,GAAG,IAAI,SAAS,CACpC,SAAS,CAAC,KAAK,EACf,SAAS,EACT,QAAQ,EACR,SAAS,CACT,CAAC;IAEF,8CAA8C;IAC9C,iGAAiG;IACjG,MAAM,MAAM,GAAG,IAAI,QAAQ,CAC1B,IAAI,CAAC,KAAK,EACV,QAAQ,CAAC,aAAa,EAAE,EACxB,eAAe,EACf,QAAQ,CAAC,WAAW,EAAE,EACtB,QAAQ,CAAC,gBAAgB,EAAE;IAC3B,+EAA+E;IAC/E,kEAAkE;IAClE,QAAQ,CAAC,eAAe,EAAE,CAC1B,CAAC;IAEF,GAAG,CAAC,8EAA8E,EAAE,SAAS,CAAC,CAAC;IAC/F,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,iCAAiC,CAAC,IAAc;IACxD,oCAAoC;IACpC,IAAI,uBAAuB,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,IAAI,iCAAiC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,uEAAuE;IACvE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QAC5C,IAAI,iCAAiC,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
2
|
+
import type { OptContext } from '../../framework/context.js';
|
|
3
|
+
/**
|
|
4
|
+
* Rule: DISTINCT Elimination
|
|
5
|
+
*
|
|
6
|
+
* When a DistinctNode's source already guarantees unique rows (via logical keys
|
|
7
|
+
* from RelationType or physical uniqueKeys), the DISTINCT is redundant and can
|
|
8
|
+
* be removed.
|
|
9
|
+
*
|
|
10
|
+
* Checks both:
|
|
11
|
+
* 1. Physical uniqueKeys (from computePhysical, available after physical pass)
|
|
12
|
+
* 2. Logical keys (from RelationType.keys, available at any time)
|
|
13
|
+
*
|
|
14
|
+
* A key that is present in the source proves it already produces unique rows —
|
|
15
|
+
* DISTINCT is a no-op.
|
|
16
|
+
*/
|
|
17
|
+
export declare function ruleDistinctElimination(node: PlanNode, _context: OptContext): PlanNode | null;
|
|
18
|
+
//# sourceMappingURL=rule-distinct-elimination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-distinct-elimination.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/distinct/rule-distinct-elimination.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAK7D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAoB7F"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createLogger } from '../../../common/logger.js';
|
|
2
|
+
import { DistinctNode } from '../../nodes/distinct-node.js';
|
|
3
|
+
const log = createLogger('optimizer:rule:distinct-elimination');
|
|
4
|
+
/**
|
|
5
|
+
* Rule: DISTINCT Elimination
|
|
6
|
+
*
|
|
7
|
+
* When a DistinctNode's source already guarantees unique rows (via logical keys
|
|
8
|
+
* from RelationType or physical uniqueKeys), the DISTINCT is redundant and can
|
|
9
|
+
* be removed.
|
|
10
|
+
*
|
|
11
|
+
* Checks both:
|
|
12
|
+
* 1. Physical uniqueKeys (from computePhysical, available after physical pass)
|
|
13
|
+
* 2. Logical keys (from RelationType.keys, available at any time)
|
|
14
|
+
*
|
|
15
|
+
* A key that is present in the source proves it already produces unique rows —
|
|
16
|
+
* DISTINCT is a no-op.
|
|
17
|
+
*/
|
|
18
|
+
export function ruleDistinctElimination(node, _context) {
|
|
19
|
+
if (!(node instanceof DistinctNode))
|
|
20
|
+
return null;
|
|
21
|
+
// Check physical uniqueKeys (available if physical pass has run or compute is triggered)
|
|
22
|
+
const sourcePhys = node.source.physical;
|
|
23
|
+
if (sourcePhys?.uniqueKeys && sourcePhys.uniqueKeys.length > 0) {
|
|
24
|
+
log('Eliminating redundant DISTINCT: source has physical uniqueKeys %j', sourcePhys.uniqueKeys);
|
|
25
|
+
return node.source;
|
|
26
|
+
}
|
|
27
|
+
// Check logical keys from RelationType
|
|
28
|
+
// If the source's logical type declares any key, the source already produces
|
|
29
|
+
// unique rows (since any superset of a key is also unique).
|
|
30
|
+
const sourceType = node.source.getType();
|
|
31
|
+
if (sourceType.keys && sourceType.keys.length > 0) {
|
|
32
|
+
log('Eliminating redundant DISTINCT: source has logical keys %j', sourceType.keys);
|
|
33
|
+
return node.source;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=rule-distinct-elimination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-distinct-elimination.js","sourceRoot":"","sources":["../../../../../src/planner/rules/distinct/rule-distinct-elimination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,MAAM,GAAG,GAAG,YAAY,CAAC,qCAAqC,CAAC,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAc,EAAE,QAAoB;IAC3E,IAAI,CAAC,CAAC,IAAI,YAAY,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjD,yFAAyF;IACzF,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IACxC,IAAI,UAAU,EAAE,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,mEAAmE,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;QAChG,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,uCAAuC;IACvC,6EAA6E;IAC7E,4DAA4D;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACzC,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,4DAA4D,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
|
|
@@ -3,9 +3,14 @@ import type { OptContext } from '../../framework/context.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Rule: Join Key Inference
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Detects equi-join predicates and FK→PK relationships between join sides.
|
|
7
|
+
* When an FK→PK alignment is found, the PK side's key is guaranteed to be
|
|
8
|
+
* covered (each FK row matches ≤1 PK row), so computePhysical already handles
|
|
9
|
+
* cardinality reduction. This rule logs the detection for diagnostics.
|
|
10
|
+
*
|
|
11
|
+
* The real work happens in:
|
|
12
|
+
* - analyzeJoinKeyCoverage (key-utils.ts): unique key preservation + estimatedRows
|
|
13
|
+
* - CatalogStatsProvider.joinSelectivity: FK-aware selectivity = 1/ndv_pk
|
|
9
14
|
*/
|
|
10
15
|
export declare function ruleJoinKeyInference(node: PlanNode, _context: OptContext): PlanNode | null;
|
|
11
16
|
//# sourceMappingURL=rule-join-key-inference.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-join-key-inference.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-key-inference.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"rule-join-key-inference.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-key-inference.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAM7D;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CA4B1F"}
|
|
@@ -1,32 +1,43 @@
|
|
|
1
1
|
import { createLogger } from '../../../common/logger.js';
|
|
2
|
-
import { JoinNode } from '../../nodes/join-node.js';
|
|
3
|
-
import {
|
|
4
|
-
import { ColumnReferenceNode } from '../../nodes/reference.js';
|
|
2
|
+
import { JoinNode, extractEquiPairsFromCondition } from '../../nodes/join-node.js';
|
|
3
|
+
import { extractTableSchema, checkFkPkAlignment } from '../../util/key-utils.js';
|
|
5
4
|
const log = createLogger('optimizer:rule:join-key-inference');
|
|
6
5
|
/**
|
|
7
6
|
* Rule: Join Key Inference
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* Detects equi-join predicates and FK→PK relationships between join sides.
|
|
9
|
+
* When an FK→PK alignment is found, the PK side's key is guaranteed to be
|
|
10
|
+
* covered (each FK row matches ≤1 PK row), so computePhysical already handles
|
|
11
|
+
* cardinality reduction. This rule logs the detection for diagnostics.
|
|
12
|
+
*
|
|
13
|
+
* The real work happens in:
|
|
14
|
+
* - analyzeJoinKeyCoverage (key-utils.ts): unique key preservation + estimatedRows
|
|
15
|
+
* - CatalogStatsProvider.joinSelectivity: FK-aware selectivity = 1/ndv_pk
|
|
12
16
|
*/
|
|
13
17
|
export function ruleJoinKeyInference(node, _context) {
|
|
14
18
|
if (!(node instanceof JoinNode))
|
|
15
19
|
return null;
|
|
16
20
|
if (node.joinType !== 'inner' && node.joinType !== 'cross')
|
|
17
21
|
return null;
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
return null;
|
|
23
|
-
// Simple left.col = right.col pattern check; placeholder for future FK->PK detection
|
|
24
|
-
const leftIsCol = cond.left instanceof ColumnReferenceNode;
|
|
25
|
-
const rightIsCol = cond.right instanceof ColumnReferenceNode;
|
|
26
|
-
if (!leftIsCol || !rightIsCol)
|
|
22
|
+
const leftAttrs = node.left.getAttributes();
|
|
23
|
+
const rightAttrs = node.right.getAttributes();
|
|
24
|
+
const pairs = extractEquiPairsFromCondition(node.condition, leftAttrs, rightAttrs);
|
|
25
|
+
if (pairs.length === 0)
|
|
27
26
|
return null;
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
// Check for FK→PK alignment
|
|
28
|
+
const leftSchema = extractTableSchema(node.left);
|
|
29
|
+
const rightSchema = extractTableSchema(node.right);
|
|
30
|
+
if (leftSchema && rightSchema) {
|
|
31
|
+
const leftFkIndices = pairs.map(p => p.left);
|
|
32
|
+
const rightFkIndices = pairs.map(p => p.right);
|
|
33
|
+
if (checkFkPkAlignment(leftSchema, rightSchema, leftFkIndices, rightFkIndices)) {
|
|
34
|
+
log('FK→PK detected: %s.FK → %s.PK; PK-side key covered by equi-join', leftSchema.name, rightSchema.name);
|
|
35
|
+
}
|
|
36
|
+
else if (checkFkPkAlignment(rightSchema, leftSchema, rightFkIndices, leftFkIndices)) {
|
|
37
|
+
log('FK→PK detected: %s.FK → %s.PK; PK-side key covered by equi-join', rightSchema.name, leftSchema.name);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// No structural transformation needed — computePhysical handles key preservation
|
|
30
41
|
return null;
|
|
31
42
|
}
|
|
32
43
|
//# sourceMappingURL=rule-join-key-inference.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-join-key-inference.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-key-inference.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-key-inference.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-key-inference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEjF,MAAM,GAAG,GAAG,YAAY,CAAC,mCAAmC,CAAC,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAc,EAAE,QAAoB;IACvE,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,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACnF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,4BAA4B;IAC5B,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAA0B,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAA2B,CAAC,CAAC;IAEzE,IAAI,UAAU,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAE/C,IAAI,kBAAkB,CAAC,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,iEAAiE,EACnE,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,kBAAkB,CAAC,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,CAAC;YACtF,GAAG,CAAC,iEAAiE,EACnE,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,iFAAiF;IACjF,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Join Physical Selection
|
|
3
|
+
*
|
|
4
|
+
* Required Characteristics:
|
|
5
|
+
* - Node must be a logical JoinNode (not already a physical join)
|
|
6
|
+
* - Node must have an equi-join predicate for hash/merge join consideration
|
|
7
|
+
*
|
|
8
|
+
* Applied When:
|
|
9
|
+
* - Logical JoinNode with equi-join predicates where hash or merge join is cheaper than nested loop
|
|
10
|
+
*
|
|
11
|
+
* Benefits: Replaces O(n*m) nested loop with O(n+m) hash/merge join for equi-joins
|
|
12
|
+
*/
|
|
13
|
+
import type { PlanNode } from '../../nodes/plan-node.js';
|
|
14
|
+
import type { OptContext } from '../../framework/context.js';
|
|
15
|
+
export declare function ruleJoinPhysicalSelection(node: PlanNode, _context: OptContext): PlanNode | null;
|
|
16
|
+
//# sourceMappingURL=rule-join-physical-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-join-physical-selection.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-physical-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAiD,MAAM,0BAA0B,CAAC;AACxG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAuI7D,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAuI/F"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Join Physical Selection
|
|
3
|
+
*
|
|
4
|
+
* Required Characteristics:
|
|
5
|
+
* - Node must be a logical JoinNode (not already a physical join)
|
|
6
|
+
* - Node must have an equi-join predicate for hash/merge join consideration
|
|
7
|
+
*
|
|
8
|
+
* Applied When:
|
|
9
|
+
* - Logical JoinNode with equi-join predicates where hash or merge join is cheaper than nested loop
|
|
10
|
+
*
|
|
11
|
+
* Benefits: Replaces O(n*m) nested loop with O(n+m) hash/merge join for equi-joins
|
|
12
|
+
*/
|
|
13
|
+
import { createLogger } from '../../../common/logger.js';
|
|
14
|
+
import { JoinNode } from '../../nodes/join-node.js';
|
|
15
|
+
import { BloomJoinNode } from '../../nodes/bloom-join-node.js';
|
|
16
|
+
import { MergeJoinNode } from '../../nodes/merge-join-node.js';
|
|
17
|
+
import { SortNode } from '../../nodes/sort.js';
|
|
18
|
+
import { BinaryOpNode } from '../../nodes/scalar.js';
|
|
19
|
+
import { ColumnReferenceNode } from '../../nodes/reference.js';
|
|
20
|
+
import { normalizePredicate } from '../../analysis/predicate-normalizer.js';
|
|
21
|
+
import { nestedLoopJoinCost, hashJoinCost, mergeJoinCost } from '../../cost/index.js';
|
|
22
|
+
import { PlanNodeCharacteristics } from '../../framework/characteristics.js';
|
|
23
|
+
const log = createLogger('optimizer:rule:join-physical-selection');
|
|
24
|
+
/**
|
|
25
|
+
* Extract equi-join pairs and residual predicates from an ON condition.
|
|
26
|
+
* Returns null if no equi-pairs found.
|
|
27
|
+
*/
|
|
28
|
+
function extractEquiPairs(condition, leftAttrIds, rightAttrIds) {
|
|
29
|
+
if (!condition)
|
|
30
|
+
return null;
|
|
31
|
+
const norm = normalizePredicate(condition);
|
|
32
|
+
const equiPairs = [];
|
|
33
|
+
const residuals = [];
|
|
34
|
+
// Walk AND-tree and classify each conjunct
|
|
35
|
+
const stack = [norm];
|
|
36
|
+
while (stack.length) {
|
|
37
|
+
const n = stack.pop();
|
|
38
|
+
if (n instanceof BinaryOpNode && n.expression.operator === 'AND') {
|
|
39
|
+
stack.push(n.left, n.right);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
// Check for equi-join: col_ref = col_ref across left/right
|
|
43
|
+
let isEqui = false;
|
|
44
|
+
if (n instanceof BinaryOpNode && n.expression.operator === '=') {
|
|
45
|
+
if (n.left instanceof ColumnReferenceNode && n.right instanceof ColumnReferenceNode) {
|
|
46
|
+
const lId = n.left.attributeId;
|
|
47
|
+
const rId = n.right.attributeId;
|
|
48
|
+
if (leftAttrIds.has(lId) && rightAttrIds.has(rId)) {
|
|
49
|
+
equiPairs.push({ leftAttrId: lId, rightAttrId: rId });
|
|
50
|
+
isEqui = true;
|
|
51
|
+
}
|
|
52
|
+
else if (leftAttrIds.has(rId) && rightAttrIds.has(lId)) {
|
|
53
|
+
equiPairs.push({ leftAttrId: rId, rightAttrId: lId });
|
|
54
|
+
isEqui = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!isEqui) {
|
|
59
|
+
residuals.push(n);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (equiPairs.length === 0)
|
|
63
|
+
return null;
|
|
64
|
+
// Combine residuals back into an AND-tree
|
|
65
|
+
let residual;
|
|
66
|
+
if (residuals.length > 0) {
|
|
67
|
+
residual = residuals.reduce((acc, cur) => new BinaryOpNode(cur.scope, { type: 'binary', operator: 'AND' }, acc, cur));
|
|
68
|
+
}
|
|
69
|
+
return { equiPairs, residual };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if a source's ordering covers the given equi-pair columns.
|
|
73
|
+
* Returns true if the source is already sorted ascending on the equi-pair
|
|
74
|
+
* columns in the exact order the equi-pairs specify. Positional matching
|
|
75
|
+
* is required because the merge-join emitter compares keys in equi-pair
|
|
76
|
+
* order; a mismatch (e.g. source sorted (b, a) vs equi-pairs (a, b))
|
|
77
|
+
* would break the linear-scan invariant.
|
|
78
|
+
*/
|
|
79
|
+
function isOrderedOnEquiPairs(source, equiPairs, side) {
|
|
80
|
+
const ordering = PlanNodeCharacteristics.getOrdering(source);
|
|
81
|
+
if (!ordering || ordering.length === 0)
|
|
82
|
+
return false;
|
|
83
|
+
if (equiPairs.length > ordering.length)
|
|
84
|
+
return false;
|
|
85
|
+
const attrs = source.getAttributes();
|
|
86
|
+
for (let i = 0; i < equiPairs.length; i++) {
|
|
87
|
+
const attrId = side === 'left' ? equiPairs[i].leftAttrId : equiPairs[i].rightAttrId;
|
|
88
|
+
const idx = attrs.findIndex(a => a.id === attrId);
|
|
89
|
+
if (idx === -1)
|
|
90
|
+
return false;
|
|
91
|
+
// Ordering entry at position i must match this equi-pair column and
|
|
92
|
+
// must be ascending (merge join's compareKeys assumes ASC order).
|
|
93
|
+
if (ordering[i].column !== idx || ordering[i].desc)
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a SortNode that sorts a source on the equi-pair columns for this side.
|
|
100
|
+
*/
|
|
101
|
+
function createSortForEquiPairs(source, equiPairs, side, scope) {
|
|
102
|
+
const attrs = source.getAttributes();
|
|
103
|
+
const sortKeys = equiPairs.map(pair => {
|
|
104
|
+
const attrId = side === 'left' ? pair.leftAttrId : pair.rightAttrId;
|
|
105
|
+
const idx = attrs.findIndex(a => a.id === attrId);
|
|
106
|
+
const attr = attrs[idx];
|
|
107
|
+
// Create a ColumnReferenceNode for this attribute
|
|
108
|
+
const colRef = new ColumnReferenceNode(scope, { type: 'column', table: '', column: attr.name, schema: '' }, attr.type, attr.id, idx);
|
|
109
|
+
return {
|
|
110
|
+
expression: colRef,
|
|
111
|
+
direction: 'asc',
|
|
112
|
+
nulls: undefined
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
return new SortNode(scope, source, sortKeys);
|
|
116
|
+
}
|
|
117
|
+
export function ruleJoinPhysicalSelection(node, _context) {
|
|
118
|
+
// Guard: only apply to logical JoinNode, not already-physical nodes
|
|
119
|
+
if (!(node instanceof JoinNode))
|
|
120
|
+
return null;
|
|
121
|
+
const joinType = node.joinType;
|
|
122
|
+
// Support INNER, LEFT, SEMI, and ANTI joins
|
|
123
|
+
if (joinType !== 'inner' && joinType !== 'left' && joinType !== 'semi' && joinType !== 'anti')
|
|
124
|
+
return null;
|
|
125
|
+
// Build attribute ID sets for left and right
|
|
126
|
+
const leftAttrs = node.left.getAttributes();
|
|
127
|
+
const rightAttrs = node.right.getAttributes();
|
|
128
|
+
const leftAttrIds = new Set(leftAttrs.map(a => a.id));
|
|
129
|
+
const rightAttrIds = new Set(rightAttrs.map(a => a.id));
|
|
130
|
+
// Try to extract equi-join pairs from condition (or USING)
|
|
131
|
+
let extracted = null;
|
|
132
|
+
if (node.condition) {
|
|
133
|
+
extracted = extractEquiPairs(node.condition, leftAttrIds, rightAttrIds);
|
|
134
|
+
}
|
|
135
|
+
else if (node.usingColumns) {
|
|
136
|
+
// Convert USING columns to equi-pairs
|
|
137
|
+
const equiPairs = [];
|
|
138
|
+
for (const colName of node.usingColumns) {
|
|
139
|
+
const lowerName = colName.toLowerCase();
|
|
140
|
+
const leftAttr = leftAttrs.find(a => a.name.toLowerCase() === lowerName);
|
|
141
|
+
const rightAttr = rightAttrs.find(a => a.name.toLowerCase() === lowerName);
|
|
142
|
+
if (leftAttr && rightAttr) {
|
|
143
|
+
equiPairs.push({ leftAttrId: leftAttr.id, rightAttrId: rightAttr.id });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (equiPairs.length > 0) {
|
|
147
|
+
extracted = { equiPairs, residual: undefined };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (!extracted || extracted.equiPairs.length === 0)
|
|
151
|
+
return null;
|
|
152
|
+
// Cost comparison: nested loop vs hash join vs merge join
|
|
153
|
+
const leftRows = node.left.estimatedRows ?? 100;
|
|
154
|
+
const rightRows = node.right.estimatedRows ?? 100;
|
|
155
|
+
const nlCost = nestedLoopJoinCost(leftRows, rightRows);
|
|
156
|
+
// Hash join cost: build side is the smaller input
|
|
157
|
+
const buildRows = Math.min(leftRows, rightRows);
|
|
158
|
+
const probeRows = Math.max(leftRows, rightRows);
|
|
159
|
+
const hashCostValue = hashJoinCost(buildRows, probeRows);
|
|
160
|
+
// Merge join cost: depends on whether inputs are already sorted
|
|
161
|
+
const leftOrdered = isOrderedOnEquiPairs(node.left, extracted.equiPairs, 'left');
|
|
162
|
+
const rightOrdered = isOrderedOnEquiPairs(node.right, extracted.equiPairs, 'right');
|
|
163
|
+
const mergeCostValue = mergeJoinCost(leftRows, rightRows, !leftOrdered, !rightOrdered);
|
|
164
|
+
let bestAlgo = 'nested-loop';
|
|
165
|
+
let bestCost = nlCost;
|
|
166
|
+
if (hashCostValue < bestCost) {
|
|
167
|
+
bestAlgo = 'hash';
|
|
168
|
+
bestCost = hashCostValue;
|
|
169
|
+
}
|
|
170
|
+
if (mergeCostValue < bestCost) {
|
|
171
|
+
bestAlgo = 'merge';
|
|
172
|
+
bestCost = mergeCostValue;
|
|
173
|
+
}
|
|
174
|
+
if (bestAlgo === 'nested-loop') {
|
|
175
|
+
log('Nested loop cheapest (nl=%.2f, hash=%.2f, merge=%.2f) for %d x %d rows', nlCost, hashCostValue, mergeCostValue, leftRows, rightRows);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
log('Selecting %s join (nl=%.2f, hash=%.2f, merge=%.2f) for %d x %d rows', bestAlgo, nlCost, hashCostValue, mergeCostValue, leftRows, rightRows);
|
|
179
|
+
// Preserve attribute IDs from the logical JoinNode
|
|
180
|
+
const preserveAttrs = node.getAttributes().slice();
|
|
181
|
+
if (bestAlgo === 'merge') {
|
|
182
|
+
// Build merge join, inserting SortNodes if needed
|
|
183
|
+
let leftSource = node.left;
|
|
184
|
+
let rightSource = node.right;
|
|
185
|
+
if (!leftOrdered) {
|
|
186
|
+
leftSource = createSortForEquiPairs(node.left, extracted.equiPairs, 'left', node.scope);
|
|
187
|
+
log('Inserted left sort for merge join');
|
|
188
|
+
}
|
|
189
|
+
if (!rightOrdered) {
|
|
190
|
+
rightSource = createSortForEquiPairs(node.right, extracted.equiPairs, 'right', node.scope);
|
|
191
|
+
log('Inserted right sort for merge join');
|
|
192
|
+
}
|
|
193
|
+
return new MergeJoinNode(node.scope, leftSource, rightSource, joinType, extracted.equiPairs, extracted.residual, preserveAttrs);
|
|
194
|
+
}
|
|
195
|
+
// Hash join path
|
|
196
|
+
// Determine build and probe sides: build=smaller, probe=larger
|
|
197
|
+
// For LEFT JOIN, the left side MUST remain the probe side to preserve
|
|
198
|
+
// null-padding semantics (all left rows must appear in output).
|
|
199
|
+
let probeSource = node.left;
|
|
200
|
+
let buildSource = node.right;
|
|
201
|
+
let equiPairs = extracted.equiPairs;
|
|
202
|
+
// For INNER join, swap sides if left is smaller (becomes build side).
|
|
203
|
+
// For LEFT/SEMI/ANTI, left must remain probe to preserve semantics.
|
|
204
|
+
if (joinType === 'inner' && leftRows < rightRows) {
|
|
205
|
+
// Swap: left becomes build, right becomes probe
|
|
206
|
+
probeSource = node.right;
|
|
207
|
+
buildSource = node.left;
|
|
208
|
+
// Flip equi-pair directions
|
|
209
|
+
equiPairs = extracted.equiPairs.map(p => ({
|
|
210
|
+
leftAttrId: p.rightAttrId,
|
|
211
|
+
rightAttrId: p.leftAttrId
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
return new BloomJoinNode(node.scope, probeSource, buildSource, joinType, equiPairs, extracted.residual, preserveAttrs);
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=rule-join-physical-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-join-physical-selection.js","sourceRoot":"","sources":["../../../../../src/planner/rules/join/rule-join-physical-selection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-grow-retrieve.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/retrieve/rule-grow-retrieve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAoB,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"rule-grow-retrieve.d.ts","sourceRoot":"","sources":["../../../../../src/planner/rules/retrieve/rule-grow-retrieve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAoB,KAAK,QAAQ,EAAgD,MAAM,0BAA0B,CAAC;AACzH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAmC7D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAgHrF"}
|
|
@@ -25,6 +25,7 @@ import { normalizePredicate } from '../../analysis/predicate-normalizer.js';
|
|
|
25
25
|
import { seqScanCost } from '../../cost/index.js';
|
|
26
26
|
import { extractOrderingFromSortKeys } from '../../framework/physical-utils.js';
|
|
27
27
|
import { PlanNodeType as _PlanNodeType } from '../../nodes/plan-node-type.js';
|
|
28
|
+
import { BinaryOpNode } from '../../nodes/scalar.js';
|
|
28
29
|
import { collectBindingsInPlan } from '../../analysis/binding-collector.js';
|
|
29
30
|
const log = createLogger('optimizer:rule:grow-retrieve');
|
|
30
31
|
function isIndexStyleContext(ctx) {
|
|
@@ -177,10 +178,11 @@ function fallbackIndexSupports(node, candidatePipeline, context, tableRef) {
|
|
|
177
178
|
filters: [],
|
|
178
179
|
requiredOrdering: undefined,
|
|
179
180
|
limit: undefined,
|
|
180
|
-
estimatedRows: tableRef.estimatedRows
|
|
181
|
+
estimatedRows: tableRef.estimatedRows || context.stats.tableRows(tableSchema) || 1000
|
|
181
182
|
};
|
|
182
183
|
// Extract information based on node type
|
|
183
184
|
let residualPredicate;
|
|
185
|
+
let plannerConstraints;
|
|
184
186
|
if (node instanceof FilterNode) {
|
|
185
187
|
// Extract constraints from filter predicate
|
|
186
188
|
const tableInfo = createTableInfoFromNode(tableRef, tableSchema.name);
|
|
@@ -190,9 +192,10 @@ function fallbackIndexSupports(node, candidatePipeline, context, tableRef) {
|
|
|
190
192
|
log('No extractable constraints from filter predicate');
|
|
191
193
|
return undefined;
|
|
192
194
|
}
|
|
193
|
-
|
|
195
|
+
plannerConstraints = extraction.allConstraints;
|
|
196
|
+
request.filters = plannerConstraints;
|
|
194
197
|
residualPredicate = extraction.residualPredicate;
|
|
195
|
-
log('Extracted %d constraints from Filter',
|
|
198
|
+
log('Extracted %d constraints from Filter', plannerConstraints.length);
|
|
196
199
|
}
|
|
197
200
|
else if (node.nodeType === PlanNodeType.Sort) {
|
|
198
201
|
// Extract ordering requirements from Sort node
|
|
@@ -246,12 +249,39 @@ function fallbackIndexSupports(node, candidatePipeline, context, tableRef) {
|
|
|
246
249
|
return undefined;
|
|
247
250
|
}
|
|
248
251
|
log('Index-style fallback beneficial: cost %d vs %d seq scan', accessPlan.cost, seqCost);
|
|
252
|
+
// Compute full residual: extraction residual + source expressions of unhandled constraints.
|
|
253
|
+
// The extractor marks constraints it can decompose (e.g., LIKE), but the module may not
|
|
254
|
+
// handle them. Those unhandled constraints must be preserved as a residual filter.
|
|
255
|
+
if (plannerConstraints && plannerConstraints.length > 0) {
|
|
256
|
+
const unhandledExprs = [];
|
|
257
|
+
for (let i = 0; i < plannerConstraints.length; i++) {
|
|
258
|
+
if (!accessPlan.handledFilters[i] && plannerConstraints[i].sourceExpression) {
|
|
259
|
+
unhandledExprs.push(plannerConstraints[i].sourceExpression);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (unhandledExprs.length > 0) {
|
|
263
|
+
const parts = residualPredicate ? [residualPredicate, ...unhandledExprs] : unhandledExprs;
|
|
264
|
+
if (parts.length === 1) {
|
|
265
|
+
residualPredicate = parts[0];
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
let acc = parts[0];
|
|
269
|
+
for (let i = 1; i < parts.length; i++) {
|
|
270
|
+
const right = parts[i];
|
|
271
|
+
const ast = { type: 'binary', operator: 'AND', left: acc.expression, right: right.expression };
|
|
272
|
+
acc = new BinaryOpNode(acc.scope, ast, acc, right);
|
|
273
|
+
}
|
|
274
|
+
residualPredicate = acc;
|
|
275
|
+
}
|
|
276
|
+
log('Added %d unhandled constraint expressions to residual', unhandledExprs.length);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
249
279
|
// Store context for later use in ruleSelectAccessPath
|
|
250
280
|
const indexCtx = {
|
|
251
281
|
kind: 'index-style',
|
|
252
282
|
accessPlan,
|
|
253
283
|
residualPredicate,
|
|
254
|
-
originalConstraints: [...
|
|
284
|
+
originalConstraints: plannerConstraints ? [...plannerConstraints] : []
|
|
255
285
|
};
|
|
256
286
|
return {
|
|
257
287
|
cost: accessPlan.cost,
|