@quereus/quereus 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -23
- package/dist/src/common/types.d.ts +1 -0
- package/dist/src/common/types.d.ts.map +1 -1
- package/dist/src/core/database.d.ts +22 -4
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +44 -6
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.d.ts +0 -7
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +1 -51
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +0 -11
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/index.d.ts +13 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/ast.d.ts +10 -4
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +40 -44
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/planner/analysis/const-pass.d.ts.map +1 -1
- package/dist/src/planner/analysis/const-pass.js +12 -6
- package/dist/src/planner/analysis/const-pass.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.d.ts +11 -0
- package/dist/src/planner/building/constraint-builder.d.ts.map +1 -0
- package/dist/src/planner/building/constraint-builder.js +79 -0
- package/dist/src/planner/building/constraint-builder.js.map +1 -0
- package/dist/src/planner/building/delete.d.ts.map +1 -1
- package/dist/src/planner/building/delete.js +7 -4
- package/dist/src/planner/building/delete.js.map +1 -1
- package/dist/src/planner/building/expression.d.ts +3 -0
- package/dist/src/planner/building/expression.d.ts.map +1 -1
- package/dist/src/planner/building/expression.js +33 -7
- package/dist/src/planner/building/expression.js.map +1 -1
- package/dist/src/planner/building/insert.d.ts.map +1 -1
- package/dist/src/planner/building/insert.js +5 -2
- package/dist/src/planner/building/insert.js.map +1 -1
- package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
- package/dist/src/planner/building/select-aggregates.js +46 -9
- package/dist/src/planner/building/select-aggregates.js.map +1 -1
- package/dist/src/planner/building/select-context.js +20 -11
- package/dist/src/planner/building/select-context.js.map +1 -1
- package/dist/src/planner/building/select-modifiers.d.ts +5 -3
- package/dist/src/planner/building/select-modifiers.d.ts.map +1 -1
- package/dist/src/planner/building/select-modifiers.js +29 -20
- package/dist/src/planner/building/select-modifiers.js.map +1 -1
- package/dist/src/planner/building/select-projections.d.ts +3 -1
- package/dist/src/planner/building/select-projections.d.ts.map +1 -1
- package/dist/src/planner/building/select-projections.js +15 -20
- package/dist/src/planner/building/select-projections.js.map +1 -1
- package/dist/src/planner/building/select-window.d.ts.map +1 -1
- package/dist/src/planner/building/select-window.js +6 -3
- package/dist/src/planner/building/select-window.js.map +1 -1
- package/dist/src/planner/building/select.d.ts +25 -2
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +147 -24
- package/dist/src/planner/building/select.js.map +1 -1
- package/dist/src/planner/building/table.d.ts +0 -10
- package/dist/src/planner/building/table.d.ts.map +1 -1
- package/dist/src/planner/building/table.js +1 -35
- 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 +8 -5
- package/dist/src/planner/building/update.js.map +1 -1
- package/dist/src/planner/building/with.d.ts.map +1 -1
- package/dist/src/planner/building/with.js +7 -8
- package/dist/src/planner/building/with.js.map +1 -1
- package/dist/src/planner/cache/correlation-detector.d.ts +11 -0
- package/dist/src/planner/cache/correlation-detector.d.ts.map +1 -0
- package/dist/src/planner/cache/correlation-detector.js +73 -0
- package/dist/src/planner/cache/correlation-detector.js.map +1 -0
- package/dist/src/planner/cache/materialization-advisory.d.ts +12 -18
- package/dist/src/planner/cache/materialization-advisory.d.ts.map +1 -1
- package/dist/src/planner/cache/materialization-advisory.js +65 -46
- package/dist/src/planner/cache/materialization-advisory.js.map +1 -1
- package/dist/src/planner/cache/reference-graph.d.ts +14 -9
- package/dist/src/planner/cache/reference-graph.d.ts.map +1 -1
- package/dist/src/planner/cache/reference-graph.js +93 -84
- package/dist/src/planner/cache/reference-graph.js.map +1 -1
- package/dist/src/planner/debug.d.ts +25 -0
- package/dist/src/planner/debug.d.ts.map +1 -1
- package/dist/src/planner/debug.js +127 -0
- package/dist/src/planner/debug.js.map +1 -1
- package/dist/src/planner/framework/context.d.ts +11 -0
- package/dist/src/planner/framework/context.d.ts.map +1 -1
- package/dist/src/planner/framework/context.js +25 -2
- package/dist/src/planner/framework/context.js.map +1 -1
- package/dist/src/planner/framework/registry.d.ts +3 -7
- package/dist/src/planner/framework/registry.d.ts.map +1 -1
- package/dist/src/planner/framework/registry.js +20 -31
- package/dist/src/planner/framework/registry.js.map +1 -1
- package/dist/src/planner/nodes/add-constraint-node.d.ts +2 -1
- package/dist/src/planner/nodes/add-constraint-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/add-constraint-node.js +3 -0
- package/dist/src/planner/nodes/add-constraint-node.js.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/aggregate-node.js +6 -4
- package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
- package/dist/src/planner/nodes/cache-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cache-node.js +2 -2
- package/dist/src/planner/nodes/cache-node.js.map +1 -1
- package/dist/src/planner/nodes/constraint-check-node.d.ts +13 -6
- package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/constraint-check-node.js +38 -12
- package/dist/src/planner/nodes/constraint-check-node.js.map +1 -1
- package/dist/src/planner/nodes/create-index-node.d.ts +2 -1
- package/dist/src/planner/nodes/create-index-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/create-index-node.js +3 -0
- package/dist/src/planner/nodes/create-index-node.js.map +1 -1
- package/dist/src/planner/nodes/create-table-node.d.ts +2 -1
- package/dist/src/planner/nodes/create-table-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/create-table-node.js +3 -0
- package/dist/src/planner/nodes/create-table-node.js.map +1 -1
- package/dist/src/planner/nodes/create-view-node.d.ts +2 -1
- package/dist/src/planner/nodes/create-view-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/create-view-node.js +3 -0
- package/dist/src/planner/nodes/create-view-node.js.map +1 -1
- package/dist/src/planner/nodes/cte-node.d.ts +1 -1
- package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cte-node.js +33 -12
- package/dist/src/planner/nodes/cte-node.js.map +1 -1
- package/dist/src/planner/nodes/cte-reference-node.d.ts +18 -4
- package/dist/src/planner/nodes/cte-reference-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cte-reference-node.js +40 -10
- package/dist/src/planner/nodes/cte-reference-node.js.map +1 -1
- package/dist/src/planner/nodes/delete-node.d.ts +4 -3
- package/dist/src/planner/nodes/delete-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/delete-node.js +20 -6
- package/dist/src/planner/nodes/delete-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 +2 -2
- package/dist/src/planner/nodes/distinct-node.js.map +1 -1
- package/dist/src/planner/nodes/dml-executor-node.d.ts +1 -1
- package/dist/src/planner/nodes/dml-executor-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/dml-executor-node.js +2 -2
- package/dist/src/planner/nodes/dml-executor-node.js.map +1 -1
- package/dist/src/planner/nodes/drop-table-node.d.ts +2 -1
- package/dist/src/planner/nodes/drop-table-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/drop-table-node.js +3 -0
- package/dist/src/planner/nodes/drop-table-node.js.map +1 -1
- package/dist/src/planner/nodes/drop-view-node.d.ts +2 -1
- package/dist/src/planner/nodes/drop-view-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/drop-view-node.js +3 -0
- package/dist/src/planner/nodes/drop-view-node.js.map +1 -1
- package/dist/src/planner/nodes/filter.d.ts.map +1 -1
- package/dist/src/planner/nodes/filter.js +3 -3
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/insert-node.d.ts +2 -1
- package/dist/src/planner/nodes/insert-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/insert-node.js +18 -5
- package/dist/src/planner/nodes/insert-node.js.map +1 -1
- package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts +28 -0
- package/dist/src/planner/nodes/internal-recursive-cte-ref-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js +69 -0
- package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js.map +1 -0
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +3 -3
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
- package/dist/src/planner/nodes/limit-offset.js +2 -2
- package/dist/src/planner/nodes/limit-offset.js.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +1 -1
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +23 -0
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js +25 -2
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/project-node.d.ts +5 -1
- package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +39 -20
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/recursive-cte-node.d.ts +2 -2
- package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/recursive-cte-node.js +20 -8
- package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +4 -2
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/returning-node.d.ts +1 -1
- package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/returning-node.js +21 -13
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts +26 -2
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +82 -10
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/sequencing-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/sequencing-node.js +2 -2
- package/dist/src/planner/nodes/sequencing-node.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 +3 -3
- package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
- package/dist/src/planner/nodes/single-row.d.ts +4 -2
- package/dist/src/planner/nodes/single-row.d.ts.map +1 -1
- package/dist/src/planner/nodes/single-row.js +3 -0
- package/dist/src/planner/nodes/single-row.js.map +1 -1
- package/dist/src/planner/nodes/sink-node.d.ts +1 -1
- package/dist/src/planner/nodes/sink-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/sink-node.js +4 -4
- package/dist/src/planner/nodes/sink-node.js.map +1 -1
- package/dist/src/planner/nodes/sort.d.ts.map +1 -1
- package/dist/src/planner/nodes/sort.js +2 -2
- package/dist/src/planner/nodes/sort.js.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts +1 -0
- package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.js +64 -11
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/subquery.d.ts +4 -4
- package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
- package/dist/src/planner/nodes/subquery.js +68 -23
- package/dist/src/planner/nodes/subquery.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +83 -0
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -0
- package/dist/src/planner/nodes/table-access-nodes.js +226 -0
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -0
- package/dist/src/planner/nodes/update-node.d.ts +4 -2
- package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/update-node.js +26 -13
- package/dist/src/planner/nodes/update-node.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +25 -23
- 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 +46 -50
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/planning-context.d.ts +13 -0
- package/dist/src/planner/planning-context.d.ts.map +1 -1
- package/dist/src/planner/planning-context.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts +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 +59 -53
- 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 +62 -2
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-materialization-advisory.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-materialization-advisory.js +31 -24
- package/dist/src/planner/rules/cache/rule-materialization-advisory.js.map +1 -1
- package/dist/src/planner/scopes/base.d.ts +0 -10
- package/dist/src/planner/scopes/base.d.ts.map +1 -1
- package/dist/src/planner/scopes/base.js +0 -14
- package/dist/src/planner/scopes/base.js.map +1 -1
- package/dist/src/planner/scopes/empty.d.ts +0 -2
- package/dist/src/planner/scopes/empty.d.ts.map +1 -1
- package/dist/src/planner/scopes/empty.js +0 -8
- package/dist/src/planner/scopes/empty.js.map +1 -1
- package/dist/src/planner/scopes/multi.d.ts.map +1 -1
- package/dist/src/planner/scopes/multi.js +0 -1
- package/dist/src/planner/scopes/multi.js.map +1 -1
- package/dist/src/planner/scopes/param.d.ts.map +1 -1
- package/dist/src/planner/scopes/param.js +0 -1
- package/dist/src/planner/scopes/param.js.map +1 -1
- package/dist/src/planner/scopes/registered.d.ts +0 -10
- package/dist/src/planner/scopes/registered.d.ts.map +1 -1
- package/dist/src/planner/scopes/registered.js +1 -17
- package/dist/src/planner/scopes/registered.js.map +1 -1
- package/dist/src/planner/scopes/scope.d.ts +0 -8
- package/dist/src/planner/scopes/scope.d.ts.map +1 -1
- package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
- package/dist/src/planner/validation/plan-validator.js +1 -7
- package/dist/src/planner/validation/plan-validator.js.map +1 -1
- package/dist/src/runtime/context-helpers.d.ts +45 -0
- package/dist/src/runtime/context-helpers.d.ts.map +1 -0
- package/dist/src/runtime/context-helpers.js +139 -0
- package/dist/src/runtime/context-helpers.js.map +1 -0
- package/dist/src/runtime/emission-context.d.ts +1 -0
- package/dist/src/runtime/emission-context.d.ts.map +1 -1
- package/dist/src/runtime/emission-context.js +2 -1
- 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 +119 -86
- package/dist/src/runtime/emit/aggregate.js.map +1 -1
- package/dist/src/runtime/emit/between.d.ts +5 -0
- package/dist/src/runtime/emit/between.d.ts.map +1 -0
- package/dist/src/runtime/emit/between.js +38 -0
- package/dist/src/runtime/emit/between.js.map +1 -0
- package/dist/src/runtime/emit/binary.d.ts +0 -1
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +0 -36
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/column-reference.d.ts.map +1 -1
- package/dist/src/runtime/emit/column-reference.js +2 -26
- package/dist/src/runtime/emit/column-reference.js.map +1 -1
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +16 -123
- 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 +16 -48
- 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 +2 -8
- package/dist/src/runtime/emit/distinct.js.map +1 -1
- package/dist/src/runtime/emit/filter.d.ts.map +1 -1
- package/dist/src/runtime/emit/filter.js +6 -13
- package/dist/src/runtime/emit/filter.js.map +1 -1
- package/dist/src/runtime/emit/internal-recursive-cte-ref.d.ts +5 -0
- package/dist/src/runtime/emit/internal-recursive-cte-ref.d.ts.map +1 -0
- package/dist/src/runtime/emit/internal-recursive-cte-ref.js +23 -0
- package/dist/src/runtime/emit/internal-recursive-cte-ref.js.map +1 -0
- package/dist/src/runtime/emit/join.d.ts.map +1 -1
- package/dist/src/runtime/emit/join.js +40 -40
- package/dist/src/runtime/emit/join.js.map +1 -1
- package/dist/src/runtime/emit/project.d.ts.map +1 -1
- package/dist/src/runtime/emit/project.js +13 -13
- 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 +3 -14
- 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 +7 -14
- package/dist/src/runtime/emit/returning.js.map +1 -1
- package/dist/src/runtime/emit/scan.d.ts +5 -2
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +21 -17
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/emit/sort.d.ts.map +1 -1
- package/dist/src/runtime/emit/sort.js +8 -11
- package/dist/src/runtime/emit/sort.js.map +1 -1
- package/dist/src/runtime/emit/subquery.d.ts.map +1 -1
- package/dist/src/runtime/emit/subquery.js +95 -40
- 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 +7 -22
- package/dist/src/runtime/emit/table-valued-function.js.map +1 -1
- package/dist/src/runtime/emit/update.d.ts.map +1 -1
- package/dist/src/runtime/emit/update.js +20 -27
- 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 +55 -83
- package/dist/src/runtime/emit/window.js.map +1 -1
- package/dist/src/runtime/emitters.d.ts.map +1 -1
- package/dist/src/runtime/emitters.js +49 -1
- package/dist/src/runtime/emitters.js.map +1 -1
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +5 -4
- 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 +47 -42
- package/dist/src/runtime/scheduler.js.map +1 -1
- package/dist/src/runtime/types.d.ts +34 -0
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js +21 -0
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +29 -16
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/table.d.ts +4 -4
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +10 -10
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/util/plugin-loader.d.ts +10 -1
- package/dist/src/util/plugin-loader.d.ts.map +1 -1
- package/dist/src/util/plugin-loader.js +56 -1
- package/dist/src/util/plugin-loader.js.map +1 -1
- package/dist/src/util/working-table-iterable.d.ts.map +1 -1
- package/dist/src/util/working-table-iterable.js +8 -8
- package/dist/src/util/working-table-iterable.js.map +1 -1
- package/dist/src/vtab/manifest.d.ts +36 -0
- package/dist/src/vtab/manifest.d.ts.map +1 -1
- package/dist/src/vtab/table.d.ts +1 -1
- package/dist/src/vtab/table.d.ts.map +1 -1
- package/package.json +8 -3
- package/src/common/types.ts +1 -0
- package/src/core/database.ts +48 -6
- package/src/core/statement.ts +1 -49
- package/src/func/builtins/explain.ts +0 -11
- package/src/index.ts +39 -5
- package/src/parser/ast.ts +12 -6
- package/src/parser/parser.ts +45 -52
- package/src/planner/analysis/const-pass.ts +281 -270
- package/src/planner/building/constraint-builder.ts +114 -0
- package/src/planner/building/delete.ts +18 -5
- package/src/planner/building/expression.ts +35 -7
- package/src/planner/building/insert.ts +16 -3
- package/src/planner/building/select-aggregates.ts +57 -11
- package/src/planner/building/select-context.ts +22 -12
- package/src/planner/building/select-modifiers.ts +35 -21
- package/src/planner/building/select-projections.ts +25 -26
- package/src/planner/building/select-window.ts +14 -9
- package/src/planner/building/select.ts +163 -31
- package/src/planner/building/table.ts +1 -40
- package/src/planner/building/update.ts +22 -7
- package/src/planner/building/with.ts +12 -13
- package/src/planner/cache/correlation-detector.ts +83 -0
- package/src/planner/cache/materialization-advisory.ts +71 -50
- package/src/planner/cache/reference-graph.ts +115 -91
- package/src/planner/debug.ts +163 -0
- package/src/planner/framework/context.ts +36 -2
- package/src/planner/framework/registry.ts +261 -274
- package/src/planner/nodes/add-constraint-node.ts +5 -1
- package/src/planner/nodes/aggregate-node.ts +6 -4
- package/src/planner/nodes/cache-node.ts +2 -2
- package/src/planner/nodes/constraint-check-node.ts +49 -15
- package/src/planner/nodes/create-index-node.ts +5 -1
- package/src/planner/nodes/create-table-node.ts +5 -1
- package/src/planner/nodes/create-view-node.ts +5 -1
- package/src/planner/nodes/cte-node.ts +45 -14
- package/src/planner/nodes/cte-reference-node.ts +49 -13
- package/src/planner/nodes/delete-node.ts +31 -7
- package/src/planner/nodes/distinct-node.ts +2 -2
- package/src/planner/nodes/dml-executor-node.ts +3 -3
- package/src/planner/nodes/drop-table-node.ts +5 -1
- package/src/planner/nodes/drop-view-node.ts +5 -1
- package/src/planner/nodes/filter.ts +3 -3
- package/src/planner/nodes/function.ts +93 -93
- package/src/planner/nodes/insert-node.ts +28 -5
- package/src/planner/nodes/internal-recursive-cte-ref-node.ts +76 -0
- package/src/planner/nodes/join-node.ts +3 -3
- package/src/planner/nodes/limit-offset.ts +2 -2
- package/src/planner/nodes/plan-node-type.ts +1 -1
- package/src/planner/nodes/plan-node.ts +39 -2
- package/src/planner/nodes/project-node.ts +39 -19
- package/src/planner/nodes/recursive-cte-node.ts +37 -9
- package/src/planner/nodes/reference.ts +4 -2
- package/src/planner/nodes/returning-node.ts +25 -13
- package/src/planner/nodes/scalar.ts +95 -11
- package/src/planner/nodes/sequencing-node.ts +2 -2
- package/src/planner/nodes/set-operation-node.ts +3 -3
- package/src/planner/nodes/single-row.ts +7 -2
- package/src/planner/nodes/sink-node.ts +5 -5
- package/src/planner/nodes/sort.ts +2 -2
- package/src/planner/nodes/stream-aggregate.ts +76 -12
- package/src/planner/nodes/subquery.ts +90 -27
- package/src/planner/nodes/{physical-access-nodes.ts → table-access-nodes.ts} +6 -6
- package/src/planner/nodes/update-node.ts +31 -13
- package/src/planner/nodes/window-node.ts +28 -22
- package/src/planner/optimizer.ts +257 -263
- package/src/planner/planning-context.ts +15 -0
- package/src/planner/rules/access/rule-select-access-path.ts +68 -64
- package/src/planner/rules/aggregate/rule-aggregate-streaming.ts +74 -2
- package/src/planner/rules/cache/rule-materialization-advisory.ts +31 -27
- package/src/planner/scopes/base.ts +0 -17
- package/src/planner/scopes/empty.ts +0 -10
- package/src/planner/scopes/multi.ts +0 -1
- package/src/planner/scopes/param.ts +0 -1
- package/src/planner/scopes/registered.ts +1 -20
- package/src/planner/scopes/scope.ts +0 -12
- package/src/planner/validation/plan-validator.ts +1 -8
- package/src/runtime/context-helpers.ts +191 -0
- package/src/runtime/emission-context.ts +5 -2
- package/src/runtime/emit/aggregate.ts +131 -85
- package/src/runtime/emit/between.ts +51 -0
- package/src/runtime/emit/binary.ts +0 -46
- package/src/runtime/emit/column-reference.ts +3 -36
- package/src/runtime/emit/constraint-check.ts +19 -144
- package/src/runtime/emit/cte-reference.ts +23 -60
- package/src/runtime/emit/distinct.ts +2 -7
- package/src/runtime/emit/filter.ts +6 -13
- package/src/runtime/emit/internal-recursive-cte-ref.ts +37 -0
- package/src/runtime/emit/join.ts +45 -43
- package/src/runtime/emit/project.ts +18 -12
- package/src/runtime/emit/recursive-cte.ts +3 -12
- package/src/runtime/emit/returning.ts +7 -14
- package/src/runtime/emit/scan.ts +25 -23
- package/src/runtime/emit/sort.ts +8 -11
- package/src/runtime/emit/subquery.ts +108 -48
- package/src/runtime/emit/table-valued-function.ts +7 -20
- package/src/runtime/emit/update.ts +22 -29
- package/src/runtime/emit/window.ts +74 -88
- package/src/runtime/emitters.ts +52 -1
- package/src/runtime/register.ts +5 -4
- package/src/runtime/scheduler.ts +54 -54
- package/src/runtime/types.ts +45 -0
- package/src/schema/manager.ts +34 -19
- package/src/schema/table.ts +8 -8
- package/src/util/plugin-loader.ts +78 -4
- package/src/util/working-table-iterable.ts +15 -7
- package/src/vtab/manifest.ts +42 -0
- package/src/vtab/table.ts +1 -1
- package/src/planner/nodes/scan.ts +0 -103
- package/src/planner/rules/physical/rule-mark-physical.ts +0 -37
- package/src/runtime/emit/table-reference.ts +0 -92
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { RuntimeContext } from './types.js';
|
|
2
|
+
import type { RowDescriptor, RowGetter } from '../planner/nodes/plan-node.js';
|
|
3
|
+
import type { SqlValue, Row } from '../common/types.js';
|
|
4
|
+
import { QuereusError } from '../common/errors.js';
|
|
5
|
+
import { StatusCode } from '../common/types.js';
|
|
6
|
+
import { createLogger } from '../common/logger.js';
|
|
7
|
+
|
|
8
|
+
const ctxLog = createLogger('runtime:context');
|
|
9
|
+
const ctxLookupLog = createLogger('runtime:context:lookup');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A mutable slot for efficient row context management in streaming operations.
|
|
13
|
+
* Avoids per-row Map mutations while maintaining context safety.
|
|
14
|
+
*/
|
|
15
|
+
export interface RowSlot {
|
|
16
|
+
/** Replace the current row (cheap field write) */
|
|
17
|
+
set(row: Row): void;
|
|
18
|
+
/** Tear down (removes descriptor from context) */
|
|
19
|
+
close(): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Create a row slot for efficient streaming context management.
|
|
24
|
+
* The slot installs a context entry once and updates it by reference.
|
|
25
|
+
* Perfect for scan/join/window operations that process many rows.
|
|
26
|
+
*/
|
|
27
|
+
export function createRowSlot(
|
|
28
|
+
rctx: RuntimeContext,
|
|
29
|
+
descriptor: RowDescriptor
|
|
30
|
+
): RowSlot {
|
|
31
|
+
// Internal boxed reference - one allocation per slot
|
|
32
|
+
const ref = { current: undefined as Row | undefined };
|
|
33
|
+
|
|
34
|
+
// Install only once
|
|
35
|
+
rctx.context.set(descriptor, () => ref.current!);
|
|
36
|
+
|
|
37
|
+
const attrs = Object.keys(descriptor).filter(k => descriptor[parseInt(k)] !== undefined);
|
|
38
|
+
ctxLog('CREATE slot with attrs=[%s]', attrs.join(','));
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
set(row: Row) {
|
|
42
|
+
ref.current = row;
|
|
43
|
+
},
|
|
44
|
+
close() {
|
|
45
|
+
rctx.context.delete(descriptor);
|
|
46
|
+
ctxLog('CLOSE slot with attrs=[%s]', attrs.join(','));
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolve an attribute ID to its column value in the current context.
|
|
53
|
+
* Searches from newest (innermost) to oldest (outermost) scope.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveAttribute(rctx: RuntimeContext, attributeId: number, columnName?: string): SqlValue {
|
|
56
|
+
// Iterate newest → oldest so the most recently pushed scope wins
|
|
57
|
+
const contextsReversed = Array.from(rctx.context.entries()).reverse();
|
|
58
|
+
|
|
59
|
+
ctxLookupLog('LOOKUP column %s (attr#%d) in %d contexts', columnName || '?', attributeId, contextsReversed.length);
|
|
60
|
+
|
|
61
|
+
for (const [descriptor, rowGetter] of contextsReversed) {
|
|
62
|
+
const columnIndex = descriptor[attributeId];
|
|
63
|
+
if (columnIndex !== undefined) {
|
|
64
|
+
const row = rowGetter();
|
|
65
|
+
if (Array.isArray(row) && columnIndex < row.length) {
|
|
66
|
+
ctxLookupLog('FOUND column %s at index %d in row', columnName || '?', columnIndex);
|
|
67
|
+
return row[columnIndex];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Log available attributes for debugging
|
|
73
|
+
if (ctxLookupLog.enabled) {
|
|
74
|
+
ctxLookupLog('Available contexts:');
|
|
75
|
+
for (const [descriptor, _] of contextsReversed) {
|
|
76
|
+
const attrs = Object.keys(descriptor).filter(k => descriptor[parseInt(k)] !== undefined);
|
|
77
|
+
ctxLookupLog(' - Descriptor with attrs=[%s]', attrs.join(','));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Log current plan execution stack if available
|
|
81
|
+
if (rctx.planStack && rctx.planStack.length > 0) {
|
|
82
|
+
const currentNode = rctx.planStack[rctx.planStack.length - 1];
|
|
83
|
+
ctxLookupLog('LOOKUP FAILED in node %s id=%d', currentNode.nodeType, currentNode.id);
|
|
84
|
+
ctxLookupLog('Execution stack: %s',
|
|
85
|
+
rctx.planStack.map(n => `${n.nodeType}#${n.id}`).join(' → '));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
throw new QuereusError(
|
|
90
|
+
`No row context found for column ${columnName || `attr#${attributeId}`}. The column reference must be evaluated within the context of its source relation.`,
|
|
91
|
+
StatusCode.ERROR
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Look up a specific column by descriptor and index.
|
|
97
|
+
* Useful when you already know which descriptor contains the column.
|
|
98
|
+
*/
|
|
99
|
+
export function lookupColumn(rctx: RuntimeContext, descriptor: RowDescriptor, columnIndex: number): SqlValue | undefined {
|
|
100
|
+
const rowGetter = rctx.context.get(descriptor);
|
|
101
|
+
if (!rowGetter) {
|
|
102
|
+
ctxLookupLog('LOOKUP by index %d - no context found', columnIndex);
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const row = rowGetter();
|
|
107
|
+
if (Array.isArray(row) && columnIndex < row.length) {
|
|
108
|
+
ctxLookupLog('LOOKUP by index %d - found value', columnIndex);
|
|
109
|
+
return row[columnIndex];
|
|
110
|
+
}
|
|
111
|
+
ctxLookupLog('LOOKUP by index %d - index out of bounds', columnIndex);
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Execute a function with a row context, ensuring proper cleanup.
|
|
117
|
+
* This is the recommended pattern for all row-processing emitters.
|
|
118
|
+
*/
|
|
119
|
+
export async function withAsyncRowContext<T>(
|
|
120
|
+
rctx: RuntimeContext,
|
|
121
|
+
descriptor: RowDescriptor,
|
|
122
|
+
rowGetter: RowGetter,
|
|
123
|
+
fn: () => T | Promise<T>
|
|
124
|
+
): Promise<T> {
|
|
125
|
+
const attrs = Object.keys(descriptor).filter(k => descriptor[parseInt(k)] !== undefined);
|
|
126
|
+
ctxLog('PUSH async context with attrs=[%s]', attrs.join(','));
|
|
127
|
+
|
|
128
|
+
rctx.context.set(descriptor, rowGetter);
|
|
129
|
+
try {
|
|
130
|
+
return await fn();
|
|
131
|
+
} finally {
|
|
132
|
+
rctx.context.delete(descriptor);
|
|
133
|
+
ctxLog('POP async context with attrs=[%s]', attrs.join(','));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Execute a function with a row context, ensuring proper cleanup.
|
|
139
|
+
* This is the recommended pattern for all row-processing emitters.
|
|
140
|
+
*/
|
|
141
|
+
export function withRowContext<T>(
|
|
142
|
+
rctx: RuntimeContext,
|
|
143
|
+
descriptor: RowDescriptor,
|
|
144
|
+
rowGetter: RowGetter,
|
|
145
|
+
fn: () => T
|
|
146
|
+
): T {
|
|
147
|
+
const attrs = Object.keys(descriptor).filter(k => descriptor[parseInt(k)] !== undefined);
|
|
148
|
+
ctxLog('PUSH context with attrs=[%s]', attrs.join(','));
|
|
149
|
+
|
|
150
|
+
rctx.context.set(descriptor, rowGetter);
|
|
151
|
+
try {
|
|
152
|
+
return fn();
|
|
153
|
+
} finally {
|
|
154
|
+
rctx.context.delete(descriptor);
|
|
155
|
+
ctxLog('POP context with attrs=[%s]', attrs.join(','));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Execute a generator function with row context management.
|
|
161
|
+
* Useful for streaming operations that process multiple rows.
|
|
162
|
+
*/
|
|
163
|
+
export async function* withRowContextGenerator<T>(
|
|
164
|
+
rctx: RuntimeContext,
|
|
165
|
+
descriptor: RowDescriptor,
|
|
166
|
+
rows: AsyncIterable<Row>,
|
|
167
|
+
fn: (row: Row) => AsyncIterable<T>
|
|
168
|
+
): AsyncIterable<T> {
|
|
169
|
+
const attrs = Object.keys(descriptor).filter(k => descriptor[parseInt(k)] !== undefined);
|
|
170
|
+
let rowCount = 0;
|
|
171
|
+
|
|
172
|
+
for await (const row of rows) {
|
|
173
|
+
if (rowCount === 0) {
|
|
174
|
+
ctxLog('PUSH generator context with attrs=[%s]', attrs.join(','));
|
|
175
|
+
}
|
|
176
|
+
rctx.context.set(descriptor, () => row);
|
|
177
|
+
try {
|
|
178
|
+
yield* fn(row);
|
|
179
|
+
rowCount++;
|
|
180
|
+
} finally {
|
|
181
|
+
rctx.context.delete(descriptor);
|
|
182
|
+
if (ctxLog.enabled && rowCount % 1000 === 0) {
|
|
183
|
+
ctxLog('Generator context processed %d rows', rowCount);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (rowCount > 0) {
|
|
189
|
+
ctxLog('POP generator context after %d rows', rowCount);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -98,9 +98,12 @@ export class EmissionContext {
|
|
|
98
98
|
private readonly schemaManager: SchemaManager;
|
|
99
99
|
private readonly dependencyTracker = new DependencyTracker();
|
|
100
100
|
private readonly schemaSnapshot = new Map<string, any>();
|
|
101
|
+
public readonly tracePlanStack: boolean;
|
|
101
102
|
|
|
102
|
-
constructor(
|
|
103
|
-
|
|
103
|
+
constructor(
|
|
104
|
+
public readonly db: Database,
|
|
105
|
+
) {
|
|
106
|
+
this.tracePlanStack = !!db.getOption('trace_plan_stack').value;
|
|
104
107
|
this.schemaManager = db.schemaManager;
|
|
105
108
|
}
|
|
106
109
|
|
|
@@ -56,10 +56,10 @@ function compareDistinctValues(a: SqlValue | SqlValue[], b: SqlValue | SqlValue[
|
|
|
56
56
|
* This traverses up the tree to find the original table scan or similar node.
|
|
57
57
|
*/
|
|
58
58
|
function findSourceRelation(node: PlanNode): PlanNode {
|
|
59
|
-
// Keep going up until we find a
|
|
59
|
+
// Keep going up until we find a values node
|
|
60
60
|
let current = node;
|
|
61
61
|
while (current) {
|
|
62
|
-
if (current.nodeType === '
|
|
62
|
+
if (current.nodeType === 'Values' || current.nodeType === 'SingleRow') {
|
|
63
63
|
return current;
|
|
64
64
|
}
|
|
65
65
|
// Get the first relational source
|
|
@@ -79,11 +79,12 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
79
79
|
|
|
80
80
|
// Create row descriptors for context
|
|
81
81
|
const sourceAttributes = plan.source.getAttributes();
|
|
82
|
-
const sourceRowDescriptor = buildRowDescriptor(sourceAttributes);
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
// Create separate descriptors for group yielding to avoid conflicts with source row processing
|
|
84
|
+
const groupSourceRowDescriptor = buildRowDescriptor(sourceAttributes);
|
|
85
|
+
const groupSourceRelationRowDescriptor = sourceRelation !== plan.source
|
|
85
86
|
? buildRowDescriptor((sourceRelation as any).getAttributes?.() || sourceAttributes)
|
|
86
|
-
:
|
|
87
|
+
: groupSourceRowDescriptor;
|
|
87
88
|
|
|
88
89
|
ctxLog('StreamAggregate setup: source=%s, sourceRelation=%s', plan.source.nodeType, sourceRelation.nodeType);
|
|
89
90
|
ctxLog('Source attributes: %O', sourceAttributes.map(attr => `${attr.name}(#${attr.id})`));
|
|
@@ -95,13 +96,16 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
95
96
|
// Create output row descriptor for the StreamAggregate's output
|
|
96
97
|
const outputRowDescriptor = buildRowDescriptor(plan.getAttributes());
|
|
97
98
|
|
|
99
|
+
// Create scan row descriptor for source relation attributes (for Filter evaluation)
|
|
100
|
+
const scanRowDescriptor = buildRowDescriptor(sourceAttributes);
|
|
101
|
+
|
|
98
102
|
// CRITICAL FIX: Create a combined descriptor that includes BOTH output and source attributes
|
|
99
103
|
// This allows correlated subqueries to access original table attributes
|
|
100
|
-
const combinedRowDescriptor: RowDescriptor =
|
|
104
|
+
const combinedRowDescriptor: RowDescriptor = {...outputRowDescriptor};
|
|
101
105
|
sourceAttributes.forEach((attr, index) => {
|
|
102
106
|
// Only add if not already present in output (avoid conflicts)
|
|
103
107
|
if (combinedRowDescriptor[attr.id] === undefined) {
|
|
104
|
-
combinedRowDescriptor[attr.id] = index;
|
|
108
|
+
combinedRowDescriptor[attr.id] = Object.keys(outputRowDescriptor).length + index;
|
|
105
109
|
}
|
|
106
110
|
});
|
|
107
111
|
|
|
@@ -182,15 +186,16 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
182
186
|
) : new BTree<SqlValue | SqlValue[], SqlValue | SqlValue[]>((val: SqlValue | SqlValue[]) => val, compareDistinctValues) // Empty tree for non-distinct
|
|
183
187
|
);
|
|
184
188
|
|
|
189
|
+
// Track the last source row for representative row in combined descriptor
|
|
190
|
+
let lastSourceRow: Row | null = null;
|
|
191
|
+
|
|
185
192
|
// Process all rows
|
|
186
193
|
for await (const row of sourceRows) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
logContextPush(sourceRelationRowDescriptor, 'source-relation-row');
|
|
193
|
-
}
|
|
194
|
+
lastSourceRow = row;
|
|
195
|
+
|
|
196
|
+
// Set the current row in the runtime context for Filter and aggregate evaluation
|
|
197
|
+
ctx.context.set(scanRowDescriptor, () => row);
|
|
198
|
+
logContextPush(scanRowDescriptor, 'scan-row', sourceAttributes);
|
|
194
199
|
|
|
195
200
|
try {
|
|
196
201
|
// For each aggregate, call its step function
|
|
@@ -234,18 +239,14 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
241
|
} finally {
|
|
237
|
-
// Clean up context for this row
|
|
238
|
-
logContextPop(
|
|
239
|
-
ctx.context.delete(
|
|
240
|
-
if (sourceRelation !== plan.source) {
|
|
241
|
-
logContextPop(sourceRelationRowDescriptor, 'source-relation-row');
|
|
242
|
-
ctx.context.delete(sourceRelationRowDescriptor);
|
|
243
|
-
}
|
|
242
|
+
// Clean up scan context for this row
|
|
243
|
+
logContextPop(scanRowDescriptor, 'scan-row');
|
|
244
|
+
ctx.context.delete(scanRowDescriptor);
|
|
244
245
|
}
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
// Finalize and yield the result
|
|
248
|
-
const
|
|
249
|
+
const aggregateRow: SqlValue[] = [];
|
|
249
250
|
for (let i = 0; i < plan.aggregates.length; i++) {
|
|
250
251
|
const schema = aggregateSchemas[i];
|
|
251
252
|
|
|
@@ -256,18 +257,28 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
256
257
|
finalValue = accumulators[i];
|
|
257
258
|
}
|
|
258
259
|
|
|
259
|
-
|
|
260
|
+
aggregateRow.push(finalValue);
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
// Build combined row with aggregate results + representative source row
|
|
264
|
+
const fullRow = lastSourceRow ? [...aggregateRow, ...lastSourceRow] : aggregateRow;
|
|
265
|
+
|
|
262
266
|
// Set up combined context for the result row (includes both output and source attributes)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
if (lastSourceRow) {
|
|
268
|
+
ctx.context.set(scanRowDescriptor, () => lastSourceRow);
|
|
269
|
+
logContextPush(scanRowDescriptor, 'aggregate-rep-row');
|
|
270
|
+
}
|
|
271
|
+
ctx.context.set(combinedRowDescriptor, () => fullRow);
|
|
272
|
+
logContextPush(combinedRowDescriptor, 'aggregate-full-row');
|
|
266
273
|
try {
|
|
267
|
-
yield
|
|
274
|
+
yield aggregateRow;
|
|
268
275
|
} finally {
|
|
269
|
-
logContextPop(
|
|
270
|
-
ctx.context.delete(
|
|
276
|
+
logContextPop(combinedRowDescriptor, 'aggregate-full-row');
|
|
277
|
+
ctx.context.delete(combinedRowDescriptor);
|
|
278
|
+
if (lastSourceRow) {
|
|
279
|
+
logContextPop(scanRowDescriptor, 'aggregate-rep-row');
|
|
280
|
+
ctx.context.delete(scanRowDescriptor);
|
|
281
|
+
}
|
|
271
282
|
}
|
|
272
283
|
} else {
|
|
273
284
|
// Handle GROUP BY case with streaming aggregation
|
|
@@ -278,17 +289,19 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
278
289
|
let currentSourceRow: Row | null = null; // Track the current group's representative row
|
|
279
290
|
let currentAccumulators: any[] = [];
|
|
280
291
|
let currentDistinctTrees: BTree<SqlValue | SqlValue[], SqlValue | SqlValue[]>[] = [];
|
|
292
|
+
let cleanupPreviousGroupContext: (() => void) | null = null;
|
|
281
293
|
|
|
282
294
|
// Process all rows
|
|
283
295
|
for await (const row of sourceRows) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (sourceRelation !== plan.source) {
|
|
288
|
-
ctx.context.set(sourceRelationRowDescriptor, () => row);
|
|
289
|
-
logContextPush(sourceRelationRowDescriptor, 'source-relation-row');
|
|
296
|
+
if (cleanupPreviousGroupContext) {
|
|
297
|
+
cleanupPreviousGroupContext();
|
|
298
|
+
cleanupPreviousGroupContext = null;
|
|
290
299
|
}
|
|
291
300
|
|
|
301
|
+
// Set the current row in the runtime context for Filter and GROUP BY evaluation
|
|
302
|
+
ctx.context.set(scanRowDescriptor, () => row);
|
|
303
|
+
logContextPush(scanRowDescriptor, 'scan-row', sourceAttributes);
|
|
304
|
+
|
|
292
305
|
try {
|
|
293
306
|
// Evaluate GROUP BY expressions to determine the group
|
|
294
307
|
const groupValues: SqlValue[] = [];
|
|
@@ -323,11 +336,14 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
323
336
|
|
|
324
337
|
// Check if we've moved to a new group using proper SQL value comparison
|
|
325
338
|
if (currentGroupKey !== null && compareGroupKeys(currentGroupKey, groupValues) !== 0) {
|
|
339
|
+
// CRITICAL: Save the previous group's representative row before yielding
|
|
340
|
+
const previousGroupSourceRow = currentSourceRow;
|
|
341
|
+
|
|
326
342
|
// Yield the previous group's results
|
|
327
|
-
const
|
|
343
|
+
const aggregateRow: SqlValue[] = [];
|
|
328
344
|
|
|
329
345
|
// First, add the GROUP BY values
|
|
330
|
-
|
|
346
|
+
aggregateRow.push(...currentGroupValues);
|
|
331
347
|
|
|
332
348
|
// Then, add the finalized aggregate values
|
|
333
349
|
for (let i = 0; i < plan.aggregates.length; i++) {
|
|
@@ -340,37 +356,49 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
340
356
|
finalValue = currentAccumulators[i];
|
|
341
357
|
}
|
|
342
358
|
|
|
343
|
-
|
|
359
|
+
aggregateRow.push(finalValue);
|
|
344
360
|
}
|
|
345
361
|
|
|
346
|
-
//
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if (
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
362
|
+
// Build combined row with aggregate results + representative source row
|
|
363
|
+
const fullRow = previousGroupSourceRow ? [...aggregateRow, ...previousGroupSourceRow] : aggregateRow;
|
|
364
|
+
|
|
365
|
+
// Set up context with the PREVIOUS group's representative row (not the current row)
|
|
366
|
+
if (previousGroupSourceRow) {
|
|
367
|
+
ctx.context.set(scanRowDescriptor, () => previousGroupSourceRow);
|
|
368
|
+
logContextPush(scanRowDescriptor, 'group-rep-row');
|
|
369
|
+
}
|
|
370
|
+
ctx.context.set(combinedRowDescriptor, () => fullRow);
|
|
371
|
+
logContextPush(combinedRowDescriptor, 'output-row-groupby');
|
|
372
|
+
if (previousGroupSourceRow) {
|
|
373
|
+
// Use the previous group's representative row for HAVING evaluation
|
|
374
|
+
// Use separate descriptors to avoid conflicts with source row processing
|
|
375
|
+
ctx.context.set(groupSourceRowDescriptor, () => previousGroupSourceRow!);
|
|
376
|
+
logContextPush(groupSourceRowDescriptor, 'source-row-groupby', sourceAttributes);
|
|
355
377
|
if (sourceRelation !== plan.source) {
|
|
356
|
-
ctx.context.set(
|
|
357
|
-
logContextPush(
|
|
378
|
+
ctx.context.set(groupSourceRelationRowDescriptor, () => previousGroupSourceRow!);
|
|
379
|
+
logContextPush(groupSourceRelationRowDescriptor, 'source-relation-row-groupby');
|
|
358
380
|
}
|
|
359
381
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
logContextPop(
|
|
364
|
-
ctx.context.delete(
|
|
365
|
-
if (
|
|
366
|
-
logContextPop(
|
|
367
|
-
ctx.context.delete(
|
|
382
|
+
|
|
383
|
+
// Defer context cleanup
|
|
384
|
+
cleanupPreviousGroupContext = () => {
|
|
385
|
+
logContextPop(combinedRowDescriptor, 'output-row-groupby');
|
|
386
|
+
ctx.context.delete(combinedRowDescriptor);
|
|
387
|
+
if (previousGroupSourceRow) {
|
|
388
|
+
logContextPop(scanRowDescriptor, 'group-rep-row');
|
|
389
|
+
ctx.context.delete(scanRowDescriptor);
|
|
390
|
+
}
|
|
391
|
+
if (previousGroupSourceRow) {
|
|
392
|
+
logContextPop(groupSourceRowDescriptor, 'source-row-groupby');
|
|
393
|
+
ctx.context.delete(groupSourceRowDescriptor);
|
|
368
394
|
if (sourceRelation !== plan.source) {
|
|
369
|
-
logContextPop(
|
|
370
|
-
ctx.context.delete(
|
|
395
|
+
logContextPop(groupSourceRelationRowDescriptor, 'source-relation-row-groupby');
|
|
396
|
+
ctx.context.delete(groupSourceRelationRowDescriptor);
|
|
371
397
|
}
|
|
372
398
|
}
|
|
373
|
-
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
yield aggregateRow;
|
|
374
402
|
|
|
375
403
|
// Reset for new group
|
|
376
404
|
currentAccumulators = aggregateSchemas.map(schema => {
|
|
@@ -392,6 +420,8 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
392
420
|
compareDistinctValues
|
|
393
421
|
) : new BTree<SqlValue | SqlValue[], SqlValue | SqlValue[]>((val: SqlValue | SqlValue[]) => val, compareDistinctValues)
|
|
394
422
|
);
|
|
423
|
+
// Set representative row for the new group (which is the current row)
|
|
424
|
+
currentSourceRow = row;
|
|
395
425
|
}
|
|
396
426
|
|
|
397
427
|
// Initialize if first group
|
|
@@ -415,12 +445,13 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
415
445
|
compareDistinctValues
|
|
416
446
|
) : new BTree<SqlValue | SqlValue[], SqlValue | SqlValue[]>((val: SqlValue | SqlValue[]) => val, compareDistinctValues)
|
|
417
447
|
);
|
|
448
|
+
// Set representative row for the first group
|
|
449
|
+
currentSourceRow = row;
|
|
418
450
|
}
|
|
419
451
|
|
|
420
452
|
// Update current group
|
|
421
453
|
currentGroupKey = groupValues;
|
|
422
454
|
currentGroupValues = groupValues;
|
|
423
|
-
currentSourceRow = row; // Keep a representative row for this group
|
|
424
455
|
|
|
425
456
|
// For each aggregate, call its step function using the pre-evaluated arguments
|
|
426
457
|
for (let i = 0; i < plan.aggregates.length; i++) {
|
|
@@ -444,22 +475,23 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
444
475
|
}
|
|
445
476
|
}
|
|
446
477
|
} finally {
|
|
447
|
-
// Clean up context for this row
|
|
448
|
-
logContextPop(
|
|
449
|
-
ctx.context.delete(
|
|
450
|
-
if (sourceRelation !== plan.source) {
|
|
451
|
-
logContextPop(sourceRelationRowDescriptor, 'source-relation-row');
|
|
452
|
-
ctx.context.delete(sourceRelationRowDescriptor);
|
|
453
|
-
}
|
|
478
|
+
// Clean up scan context for this row
|
|
479
|
+
logContextPop(scanRowDescriptor, 'scan-row');
|
|
480
|
+
ctx.context.delete(scanRowDescriptor);
|
|
454
481
|
}
|
|
455
482
|
}
|
|
456
483
|
|
|
484
|
+
if (cleanupPreviousGroupContext) {
|
|
485
|
+
cleanupPreviousGroupContext();
|
|
486
|
+
cleanupPreviousGroupContext = null;
|
|
487
|
+
}
|
|
488
|
+
|
|
457
489
|
// Yield the final group if any rows were processed
|
|
458
490
|
if (currentGroupKey !== null) {
|
|
459
|
-
const
|
|
491
|
+
const aggregateRow: SqlValue[] = [];
|
|
460
492
|
|
|
461
493
|
// First, add the GROUP BY values
|
|
462
|
-
|
|
494
|
+
aggregateRow.push(...currentGroupValues);
|
|
463
495
|
|
|
464
496
|
// Then, add the finalized aggregate values
|
|
465
497
|
for (let i = 0; i < plan.aggregates.length; i++) {
|
|
@@ -472,31 +504,45 @@ export function emitStreamAggregate(plan: StreamAggregateNode, ctx: EmissionCont
|
|
|
472
504
|
finalValue = currentAccumulators[i];
|
|
473
505
|
}
|
|
474
506
|
|
|
475
|
-
|
|
507
|
+
aggregateRow.push(finalValue);
|
|
476
508
|
}
|
|
477
509
|
|
|
478
|
-
//
|
|
479
|
-
|
|
480
|
-
|
|
510
|
+
// Build combined row with aggregate results + representative source row
|
|
511
|
+
const fullRow = currentSourceRow ? [...aggregateRow, ...currentSourceRow] : aggregateRow;
|
|
512
|
+
|
|
513
|
+
// Set up context for final group with correct source row
|
|
514
|
+
if (currentSourceRow) {
|
|
515
|
+
ctx.context.set(scanRowDescriptor, () => currentSourceRow);
|
|
516
|
+
logContextPush(scanRowDescriptor, 'final-group-rep-row');
|
|
517
|
+
}
|
|
518
|
+
ctx.context.set(combinedRowDescriptor, () => fullRow);
|
|
519
|
+
logContextPush(combinedRowDescriptor, 'final-output-row');
|
|
481
520
|
if (currentSourceRow) {
|
|
482
|
-
|
|
483
|
-
|
|
521
|
+
// Use the final group's representative row for HAVING evaluation
|
|
522
|
+
// Use separate descriptors to avoid conflicts with source row processing
|
|
523
|
+
ctx.context.set(groupSourceRowDescriptor, () => currentSourceRow!);
|
|
524
|
+
logContextPush(groupSourceRowDescriptor, 'final-source-row', sourceAttributes);
|
|
484
525
|
if (sourceRelation !== plan.source) {
|
|
485
|
-
ctx.context.set(
|
|
486
|
-
logContextPush(
|
|
526
|
+
ctx.context.set(groupSourceRelationRowDescriptor, () => currentSourceRow!);
|
|
527
|
+
logContextPush(groupSourceRelationRowDescriptor, 'final-source-relation-row');
|
|
487
528
|
}
|
|
488
529
|
}
|
|
530
|
+
|
|
489
531
|
try {
|
|
490
|
-
yield
|
|
532
|
+
yield aggregateRow;
|
|
491
533
|
} finally {
|
|
492
|
-
logContextPop(
|
|
493
|
-
ctx.context.delete(
|
|
534
|
+
logContextPop(combinedRowDescriptor, 'final-output-row');
|
|
535
|
+
ctx.context.delete(combinedRowDescriptor);
|
|
536
|
+
if (currentSourceRow) {
|
|
537
|
+
logContextPop(scanRowDescriptor, 'final-group-rep-row');
|
|
538
|
+
ctx.context.delete(scanRowDescriptor);
|
|
539
|
+
}
|
|
494
540
|
if (currentSourceRow) {
|
|
495
|
-
logContextPop(
|
|
496
|
-
ctx.context.delete(
|
|
541
|
+
logContextPop(groupSourceRowDescriptor, 'final-source-row');
|
|
542
|
+
ctx.context.delete(groupSourceRowDescriptor);
|
|
497
543
|
if (sourceRelation !== plan.source) {
|
|
498
|
-
logContextPop(
|
|
499
|
-
ctx.context.delete(
|
|
544
|
+
logContextPop(groupSourceRelationRowDescriptor, 'final-source-relation-row');
|
|
545
|
+
ctx.context.delete(groupSourceRelationRowDescriptor);
|
|
500
546
|
}
|
|
501
547
|
}
|
|
502
548
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SqlValue } from "../../common/types.js";
|
|
2
|
+
import type { Instruction, InstructionRun, RuntimeContext } from "../types.js";
|
|
3
|
+
import type { BetweenNode } from "../../planner/nodes/scalar.js";
|
|
4
|
+
import { emitPlanNode } from "../emitters.js";
|
|
5
|
+
import { compareSqlValuesFast, resolveCollation } from "../../util/comparison.js";
|
|
6
|
+
import { coerceForComparison } from "../../util/coercion.js";
|
|
7
|
+
import type { EmissionContext } from "../emission-context.js";
|
|
8
|
+
|
|
9
|
+
export function emitBetween(plan: BetweenNode, ctx: EmissionContext): Instruction {
|
|
10
|
+
// Pre-resolve collation function for optimal performance (using BINARY as default for BETWEEN)
|
|
11
|
+
const collationFunc = resolveCollation('BINARY');
|
|
12
|
+
|
|
13
|
+
function run(ctx: RuntimeContext, value: SqlValue, lowerBound: SqlValue, upperBound: SqlValue): SqlValue {
|
|
14
|
+
// SQL BETWEEN logic: value BETWEEN lower AND upper
|
|
15
|
+
// Equivalent to: value >= lower AND value <= upper
|
|
16
|
+
// NULL handling: if any operand is NULL, result is NULL
|
|
17
|
+
if (value === null || lowerBound === null || upperBound === null) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Apply type coercion before comparison
|
|
22
|
+
const [coercedValue1, coercedLower] = coerceForComparison(value, lowerBound);
|
|
23
|
+
const [coercedValue2, coercedUpper] = coerceForComparison(value, upperBound);
|
|
24
|
+
|
|
25
|
+
// Use pre-resolved collation function for optimal performance
|
|
26
|
+
const lowerResult = compareSqlValuesFast(coercedValue1, coercedLower, collationFunc);
|
|
27
|
+
const upperResult = compareSqlValuesFast(coercedValue2, coercedUpper, collationFunc);
|
|
28
|
+
|
|
29
|
+
// value >= lowerBound AND value <= upperBound
|
|
30
|
+
const betweenResult = (lowerResult >= 0 && upperResult <= 0) ? 1 : 0;
|
|
31
|
+
|
|
32
|
+
// Handle NOT BETWEEN
|
|
33
|
+
if (plan.expression.not) {
|
|
34
|
+
return betweenResult ? 0 : 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return betweenResult;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const valueExpr = emitPlanNode(plan.expr, ctx);
|
|
41
|
+
const lowerExpr = emitPlanNode(plan.lower, ctx);
|
|
42
|
+
const upperExpr = emitPlanNode(plan.upper, ctx);
|
|
43
|
+
|
|
44
|
+
const notPrefix = plan.expression.not ? 'NOT ' : '';
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
params: [valueExpr, lowerExpr, upperExpr],
|
|
48
|
+
run: run as InstructionRun,
|
|
49
|
+
note: `${notPrefix}BETWEEN`
|
|
50
|
+
};
|
|
51
|
+
}
|