@quereus/quereus 0.1.0 → 0.2.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 +47 -23
- 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 +9 -2
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +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 +6 -3
- 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 +4 -1
- 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 +7 -4
- 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 +11 -4
- 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.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 +14 -121
- 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/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/package.json +8 -3
- 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 +11 -2
- package/src/parser/parser.ts +40 -47
- package/src/planner/analysis/const-pass.ts +281 -270
- package/src/planner/building/constraint-builder.ts +114 -0
- package/src/planner/building/delete.ts +16 -3
- package/src/planner/building/expression.ts +35 -7
- package/src/planner/building/insert.ts +14 -1
- 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 +19 -4
- 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 +47 -13
- 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 +2 -2
- 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 +17 -142
- 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/util/plugin-loader.ts +78 -4
- package/src/util/working-table-iterable.ts +15 -7
- package/src/vtab/manifest.ts +42 -0
- 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,114 @@
|
|
|
1
|
+
import type { PlanningContext } from '../planning-context.js';
|
|
2
|
+
import type { TableSchema, RowConstraintSchema } from '../../schema/table.js';
|
|
3
|
+
import type { RowOp } from '../../schema/table.js';
|
|
4
|
+
import type { Attribute, RowDescriptor } from '../nodes/plan-node.js';
|
|
5
|
+
import type { ConstraintCheck } from '../nodes/constraint-check-node.js';
|
|
6
|
+
import { RegisteredScope } from '../scopes/registered.js';
|
|
7
|
+
import { buildExpression } from './expression.js';
|
|
8
|
+
import { ColumnReferenceNode } from '../nodes/reference.js';
|
|
9
|
+
import type { ScalarPlanNode } from '../nodes/plan-node.js';
|
|
10
|
+
import * as AST from '../../parser/ast.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Determines if a constraint should be checked for the given operation
|
|
14
|
+
*/
|
|
15
|
+
function shouldCheckConstraint(constraint: RowConstraintSchema, operation: RowOp): boolean {
|
|
16
|
+
// Check if the current operation is in the constraint's operations bitmask
|
|
17
|
+
return (constraint.operations & operation) !== 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Builds constraint check expressions at plan time.
|
|
22
|
+
* This allows the optimizer to see and optimize constraint expressions.
|
|
23
|
+
*/
|
|
24
|
+
export function buildConstraintChecks(
|
|
25
|
+
ctx: PlanningContext,
|
|
26
|
+
tableSchema: TableSchema,
|
|
27
|
+
operation: RowOp,
|
|
28
|
+
oldAttributes: Attribute[],
|
|
29
|
+
newAttributes: Attribute[],
|
|
30
|
+
_flatRowDescriptor: RowDescriptor
|
|
31
|
+
): ConstraintCheck[] {
|
|
32
|
+
// Build attribute ID mappings for column registration
|
|
33
|
+
const newAttrIdByCol: Record<string, number> = {};
|
|
34
|
+
const oldAttrIdByCol: Record<string, number> = {};
|
|
35
|
+
|
|
36
|
+
newAttributes.forEach((attr, columnIndex) => {
|
|
37
|
+
if (columnIndex < tableSchema.columns.length) {
|
|
38
|
+
const column = tableSchema.columns[columnIndex];
|
|
39
|
+
newAttrIdByCol[column.name.toLowerCase()] = attr.id;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
oldAttributes.forEach((attr, columnIndex) => {
|
|
44
|
+
if (columnIndex < tableSchema.columns.length) {
|
|
45
|
+
const column = tableSchema.columns[columnIndex];
|
|
46
|
+
oldAttrIdByCol[column.name.toLowerCase()] = attr.id;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Filter constraints by operation
|
|
51
|
+
const applicableConstraints = tableSchema.checkConstraints
|
|
52
|
+
.filter(constraint => shouldCheckConstraint(constraint, operation));
|
|
53
|
+
|
|
54
|
+
// Build expression nodes for each constraint
|
|
55
|
+
return applicableConstraints.map(constraint => {
|
|
56
|
+
// Create scope with OLD/NEW column access for constraint evaluation
|
|
57
|
+
const constraintScope = new RegisteredScope(ctx.scope);
|
|
58
|
+
|
|
59
|
+
// Register column symbols (similar to current emitConstraintCheck logic)
|
|
60
|
+
tableSchema.columns.forEach((tableColumn, tableColIndex) => {
|
|
61
|
+
const colNameLower = tableColumn.name.toLowerCase();
|
|
62
|
+
|
|
63
|
+
// Register NEW.col and unqualified col (defaults to NEW for INSERT/UPDATE, OLD for DELETE)
|
|
64
|
+
const newAttrId = newAttrIdByCol[colNameLower];
|
|
65
|
+
if (newAttrId !== undefined) {
|
|
66
|
+
const newColumnType = {
|
|
67
|
+
typeClass: 'scalar' as const,
|
|
68
|
+
affinity: tableColumn.affinity,
|
|
69
|
+
nullable: !tableColumn.notNull,
|
|
70
|
+
isReadOnly: false
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// NEW.column
|
|
74
|
+
constraintScope.registerSymbol(`new.${colNameLower}`, (exp, s) =>
|
|
75
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, newColumnType, newAttrId, tableColIndex));
|
|
76
|
+
|
|
77
|
+
// For INSERT/UPDATE, unqualified column defaults to NEW
|
|
78
|
+
if (operation === 1 || operation === 2) { // INSERT or UPDATE
|
|
79
|
+
constraintScope.registerSymbol(colNameLower, (exp, s) =>
|
|
80
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, newColumnType, newAttrId, tableColIndex));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Register OLD.col
|
|
85
|
+
const oldAttrId = oldAttrIdByCol[colNameLower];
|
|
86
|
+
if (oldAttrId !== undefined) {
|
|
87
|
+
const oldColumnType = {
|
|
88
|
+
typeClass: 'scalar' as const,
|
|
89
|
+
affinity: tableColumn.affinity,
|
|
90
|
+
nullable: true, // OLD values can be NULL (especially for INSERT)
|
|
91
|
+
isReadOnly: false
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// OLD.column
|
|
95
|
+
constraintScope.registerSymbol(`old.${colNameLower}`, (exp, s) =>
|
|
96
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, oldColumnType, oldAttrId, tableColIndex));
|
|
97
|
+
|
|
98
|
+
// For DELETE, unqualified column defaults to OLD
|
|
99
|
+
if (operation === 4) { // DELETE
|
|
100
|
+
constraintScope.registerSymbol(colNameLower, (exp, s) =>
|
|
101
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, oldColumnType, oldAttrId, tableColIndex));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Build the constraint expression using the specialized scope
|
|
107
|
+
const expression = buildExpression(
|
|
108
|
+
{ ...ctx, scope: constraintScope },
|
|
109
|
+
constraint.expr
|
|
110
|
+
) as ScalarPlanNode;
|
|
111
|
+
|
|
112
|
+
return { constraint, expression };
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type * as AST from '../../parser/ast.js';
|
|
2
2
|
import type { PlanningContext } from '../planning-context.js';
|
|
3
3
|
import { DeleteNode } from '../nodes/delete-node.js';
|
|
4
|
-
import { buildTableReference
|
|
4
|
+
import { buildTableReference } from './table.js';
|
|
5
5
|
import { buildExpression } from './expression.js';
|
|
6
6
|
import { PlanNode, type RelationalPlanNode, type ScalarPlanNode } from '../nodes/plan-node.js';
|
|
7
7
|
import { FilterNode } from '../nodes/filter.js';
|
|
@@ -15,6 +15,7 @@ import { RowOp } from '../../schema/table.js';
|
|
|
15
15
|
import { ReturningNode } from '../nodes/returning-node.js';
|
|
16
16
|
import { buildOldNewRowDescriptors } from '../../util/row-descriptor.js';
|
|
17
17
|
import { DmlExecutorNode } from '../nodes/dml-executor-node.js';
|
|
18
|
+
import { buildConstraintChecks } from './constraint-builder.js';
|
|
18
19
|
|
|
19
20
|
export function buildDeleteStmt(
|
|
20
21
|
ctx: PlanningContext,
|
|
@@ -23,7 +24,7 @@ export function buildDeleteStmt(
|
|
|
23
24
|
const tableReference = buildTableReference({ type: 'table', table: stmt.table }, ctx);
|
|
24
25
|
|
|
25
26
|
// Plan the source of rows to delete. This is typically the table itself, potentially filtered.
|
|
26
|
-
let sourceNode: RelationalPlanNode =
|
|
27
|
+
let sourceNode: RelationalPlanNode = buildTableReference({ type: 'table', table: stmt.table }, ctx);
|
|
27
28
|
|
|
28
29
|
// Create a new scope with the table columns registered for column resolution
|
|
29
30
|
const tableScope = new RegisteredScope(ctx.scope);
|
|
@@ -69,6 +70,16 @@ export function buildDeleteStmt(
|
|
|
69
70
|
|
|
70
71
|
const { oldRowDescriptor, newRowDescriptor, flatRowDescriptor } = buildOldNewRowDescriptors(oldAttributes, newAttributes);
|
|
71
72
|
|
|
73
|
+
// Build constraint checks at plan time
|
|
74
|
+
const constraintChecks = buildConstraintChecks(
|
|
75
|
+
deleteCtx,
|
|
76
|
+
tableReference.tableSchema,
|
|
77
|
+
RowOp.DELETE,
|
|
78
|
+
oldAttributes,
|
|
79
|
+
newAttributes,
|
|
80
|
+
flatRowDescriptor
|
|
81
|
+
);
|
|
82
|
+
|
|
72
83
|
// Always inject ConstraintCheckNode for DELETE operations
|
|
73
84
|
const constraintCheckNode = new ConstraintCheckNode(
|
|
74
85
|
deleteCtx.scope,
|
|
@@ -76,7 +87,9 @@ export function buildDeleteStmt(
|
|
|
76
87
|
tableReference,
|
|
77
88
|
RowOp.DELETE,
|
|
78
89
|
oldRowDescriptor,
|
|
79
|
-
newRowDescriptor
|
|
90
|
+
newRowDescriptor,
|
|
91
|
+
flatRowDescriptor,
|
|
92
|
+
constraintChecks
|
|
80
93
|
);
|
|
81
94
|
|
|
82
95
|
const deleteNode = new DeleteNode(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as AST from '../../parser/ast.js';
|
|
2
2
|
import type { PlanningContext } from '../planning-context.js';
|
|
3
|
-
import { LiteralNode, BinaryOpNode, UnaryOpNode, CaseExprNode, CastNode, CollateNode } from '../nodes/scalar.js';
|
|
3
|
+
import { LiteralNode, BinaryOpNode, UnaryOpNode, CaseExprNode, CastNode, CollateNode, BetweenNode } from '../nodes/scalar.js';
|
|
4
4
|
import { ScalarSubqueryNode, InNode, ExistsNode } from '../nodes/subquery.js';
|
|
5
5
|
import { WindowFunctionCallNode } from '../nodes/window-function.js';
|
|
6
6
|
import type { ScalarPlanNode, RelationalPlanNode } from '../nodes/plan-node.js';
|
|
@@ -12,7 +12,13 @@ import { Ambiguous } from '../scopes/scope.js';
|
|
|
12
12
|
import { buildSelectStmt } from './select.js';
|
|
13
13
|
import { resolveWindowFunction } from '../../schema/window-function.js';
|
|
14
14
|
import { buildFunctionCall } from './function-call.js';
|
|
15
|
+
import { createLogger } from '../../common/logger.js';
|
|
15
16
|
|
|
17
|
+
const logger = createLogger('planner:expression');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Builds an expression plan node from an AST expression.
|
|
21
|
+
*/
|
|
16
22
|
export function buildExpression(ctx: PlanningContext, expr: AST.Expression, allowAggregates: boolean = false): ScalarPlanNode {
|
|
17
23
|
switch (expr.type) {
|
|
18
24
|
case 'literal':
|
|
@@ -92,8 +98,16 @@ export function buildExpression(ctx: PlanningContext, expr: AST.Expression, allo
|
|
|
92
98
|
case 'subquery': {
|
|
93
99
|
// For scalar subqueries, create a context that allows correlation
|
|
94
100
|
// The buildSelectStmt will create the proper scope chain with subquery tables taking precedence
|
|
95
|
-
|
|
96
|
-
|
|
101
|
+
// CRITICAL: Share the cteReferenceCache to ensure consistent attribute IDs across contexts
|
|
102
|
+
logger(`Building scalar subquery - ctx.cteReferenceCache size: ${ctx.cteReferenceCache?.size ?? 'undefined'}`);
|
|
103
|
+
const subqueryContext = {
|
|
104
|
+
...ctx,
|
|
105
|
+
cteReferenceCache: ctx.cteReferenceCache || new Map()
|
|
106
|
+
};
|
|
107
|
+
// Preserve input columns in scalar subqueries to ensure correlated predicates
|
|
108
|
+
// have access to all underlying attributes.
|
|
109
|
+
const subqueryPlan = buildSelectStmt(subqueryContext, expr.query, ctx.cteNodes, true);
|
|
110
|
+
logger(`Building scalar subquery with preserveInputColumns=true`);
|
|
97
111
|
if (subqueryPlan.getType().typeClass !== 'relation') {
|
|
98
112
|
throw new QuereusError('Subquery must produce a relation', StatusCode.ERROR, undefined, expr.loc?.start.line, expr.loc?.start.column);
|
|
99
113
|
}
|
|
@@ -138,8 +152,11 @@ export function buildExpression(ctx: PlanningContext, expr: AST.Expression, allo
|
|
|
138
152
|
|
|
139
153
|
if (expr.subquery) {
|
|
140
154
|
// IN subquery: expr IN (SELECT ...)
|
|
141
|
-
const inSubqueryContext = {
|
|
142
|
-
|
|
155
|
+
const inSubqueryContext = {
|
|
156
|
+
...ctx,
|
|
157
|
+
cteReferenceCache: ctx.cteReferenceCache || new Map()
|
|
158
|
+
};
|
|
159
|
+
const inSubqueryPlan = buildSelectStmt(inSubqueryContext, expr.subquery, ctx.cteNodes, true);
|
|
143
160
|
if (inSubqueryPlan.getType().typeClass !== 'relation') {
|
|
144
161
|
throw new QuereusError('IN subquery must produce a relation', StatusCode.ERROR, undefined, expr.loc?.start.line, expr.loc?.start.column);
|
|
145
162
|
}
|
|
@@ -162,14 +179,25 @@ export function buildExpression(ctx: PlanningContext, expr: AST.Expression, allo
|
|
|
162
179
|
|
|
163
180
|
case 'exists': {
|
|
164
181
|
// Build the EXISTS subquery
|
|
165
|
-
const existsSubqueryContext = {
|
|
166
|
-
|
|
182
|
+
const existsSubqueryContext = {
|
|
183
|
+
...ctx,
|
|
184
|
+
cteReferenceCache: ctx.cteReferenceCache || new Map()
|
|
185
|
+
};
|
|
186
|
+
const existsSubqueryPlan = buildSelectStmt(existsSubqueryContext, expr.subquery, ctx.cteNodes, true);
|
|
167
187
|
if (existsSubqueryPlan.getType().typeClass !== 'relation') {
|
|
168
188
|
throw new QuereusError('EXISTS subquery must produce a relation', StatusCode.ERROR, undefined, expr.loc?.start.line, expr.loc?.start.column);
|
|
169
189
|
}
|
|
170
190
|
return new ExistsNode(ctx.scope, expr, existsSubqueryPlan as RelationalPlanNode);
|
|
171
191
|
}
|
|
172
192
|
|
|
193
|
+
case 'between': {
|
|
194
|
+
// Build the BETWEEN expression: expr BETWEEN lower AND upper
|
|
195
|
+
const exprNode = buildExpression(ctx, expr.expr, allowAggregates);
|
|
196
|
+
const lowerNode = buildExpression(ctx, expr.lower, allowAggregates);
|
|
197
|
+
const upperNode = buildExpression(ctx, expr.upper, allowAggregates);
|
|
198
|
+
return new BetweenNode(ctx.scope, expr, exprNode, lowerNode, upperNode);
|
|
199
|
+
}
|
|
200
|
+
|
|
173
201
|
default:
|
|
174
202
|
throw new QuereusError(`Expression type '${(expr as any).type}' not yet supported in buildExpression.`, StatusCode.UNSUPPORTED, undefined, expr.loc?.start.line, expr.loc?.start.column);
|
|
175
203
|
}
|
|
@@ -21,6 +21,7 @@ import { ReturningNode } from '../nodes/returning-node.js';
|
|
|
21
21
|
import { ProjectNode, type Projection } from '../nodes/project-node.js';
|
|
22
22
|
import { buildOldNewRowDescriptors } from '../../util/row-descriptor.js';
|
|
23
23
|
import { DmlExecutorNode } from '../nodes/dml-executor-node.js';
|
|
24
|
+
import { buildConstraintChecks } from './constraint-builder.js';
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Creates a uniform row expansion projection that maps any relational source
|
|
@@ -243,6 +244,16 @@ export function buildInsertStmt(
|
|
|
243
244
|
|
|
244
245
|
const { oldRowDescriptor, newRowDescriptor, flatRowDescriptor } = buildOldNewRowDescriptors(oldAttributes, newAttributes);
|
|
245
246
|
|
|
247
|
+
// Build constraint checks at plan time
|
|
248
|
+
const constraintChecks = buildConstraintChecks(
|
|
249
|
+
ctx,
|
|
250
|
+
tableReference.tableSchema,
|
|
251
|
+
RowOp.INSERT,
|
|
252
|
+
oldAttributes,
|
|
253
|
+
newAttributes,
|
|
254
|
+
flatRowDescriptor
|
|
255
|
+
);
|
|
256
|
+
|
|
246
257
|
const insertNode = new InsertNode(
|
|
247
258
|
ctx.scope,
|
|
248
259
|
tableReference,
|
|
@@ -257,7 +268,9 @@ export function buildInsertStmt(
|
|
|
257
268
|
tableReference,
|
|
258
269
|
RowOp.INSERT,
|
|
259
270
|
oldRowDescriptor,
|
|
260
|
-
newRowDescriptor
|
|
271
|
+
newRowDescriptor,
|
|
272
|
+
flatRowDescriptor,
|
|
273
|
+
constraintChecks
|
|
261
274
|
);
|
|
262
275
|
|
|
263
276
|
// Add DML executor node to perform the actual database insert operations
|
|
@@ -27,17 +27,17 @@ export function buildAggregatePhase(
|
|
|
27
27
|
needsFinalProjection: boolean;
|
|
28
28
|
preAggregateSort: boolean;
|
|
29
29
|
} {
|
|
30
|
+
const hasGroupBy = stmt.groupBy && stmt.groupBy.length > 0;
|
|
31
|
+
|
|
30
32
|
// If there is a HAVING clause but the SELECT contains **no aggregate functions**
|
|
31
|
-
// we can safely treat the HAVING predicate as a regular filter
|
|
32
|
-
// the aggregation (i.e. between the source and the AggregateNode).
|
|
33
|
-
// the "missing column context" problem where the predicate refers to columns
|
|
33
|
+
// AND **no GROUP BY**, we can safely treat the HAVING predicate as a regular filter
|
|
34
|
+
// that runs *before* the aggregation (i.e. between the source and the AggregateNode).
|
|
35
|
+
// This avoids the "missing column context" problem where the predicate refers to columns
|
|
34
36
|
// that are not available after the AggregateNode (only grouping columns and
|
|
35
37
|
// aggregate results are exposed). This behaviour is compatible with SQLite –
|
|
36
38
|
// GROUP BY with a primary-key guarantees one row per group so the semantics
|
|
37
39
|
// are unchanged.
|
|
38
|
-
const shouldPushHavingBelowAggregate = Boolean(stmt.having && !hasAggregates);
|
|
39
|
-
|
|
40
|
-
const hasGroupBy = stmt.groupBy && stmt.groupBy.length > 0;
|
|
40
|
+
const shouldPushHavingBelowAggregate = Boolean(stmt.having && !hasAggregates && !hasGroupBy);
|
|
41
41
|
|
|
42
42
|
if (!hasAggregates && !hasGroupBy) {
|
|
43
43
|
return { output: input, needsFinalProjection: false, preAggregateSort: false };
|
|
@@ -67,7 +67,7 @@ export function buildAggregatePhase(
|
|
|
67
67
|
const groupByExpressions = stmt.groupBy ?
|
|
68
68
|
stmt.groupBy.map(expr => buildExpression(selectContext, expr, false)) : [];
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
// Create AggregateNode
|
|
71
71
|
currentInput = new AggregateNode(selectContext.scope, currentInput, groupByExpressions, aggregates);
|
|
72
72
|
|
|
73
73
|
// Create aggregate output scope
|
|
@@ -166,6 +166,21 @@ function createAggregateOutputScope(
|
|
|
166
166
|
new ColumnReferenceNode(s, exp as AST.ColumnExpr, agg.expression.getType(), attr.id, columnIndex));
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
+
// Register source columns for HAVING clause access
|
|
170
|
+
// Start after GROUP BY and aggregate columns
|
|
171
|
+
const sourceColumnStartIndex = groupByExpressions.length + aggregates.length;
|
|
172
|
+
for (let i = sourceColumnStartIndex; i < aggregateAttributes.length; i++) {
|
|
173
|
+
const attr = aggregateAttributes[i];
|
|
174
|
+
// Only register if not already registered (avoid conflicts with GROUP BY columns)
|
|
175
|
+
const symbolName = attr.name.toLowerCase();
|
|
176
|
+
const existingSymbols = aggregateOutputScope.getSymbols();
|
|
177
|
+
const alreadyRegistered = existingSymbols.some(([key]) => key === symbolName);
|
|
178
|
+
if (!alreadyRegistered) {
|
|
179
|
+
aggregateOutputScope.registerSymbol(symbolName, (exp, s) =>
|
|
180
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, attr.type, attr.id, i));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
169
184
|
return aggregateOutputScope;
|
|
170
185
|
}
|
|
171
186
|
|
|
@@ -182,10 +197,35 @@ function buildHavingFilter(
|
|
|
182
197
|
): RelationalPlanNode {
|
|
183
198
|
const aggregateAttributes = input.getAttributes();
|
|
184
199
|
|
|
185
|
-
//
|
|
200
|
+
// Create a hybrid scope that first tries the aggregate output scope,
|
|
201
|
+
// then falls back to the original source scope for column resolution
|
|
202
|
+
const hybridScope = new RegisteredScope();
|
|
203
|
+
|
|
204
|
+
// Copy all symbols from aggregate output scope
|
|
205
|
+
for (const [symbolKey, callback] of aggregateOutputScope.getSymbols()) {
|
|
206
|
+
hybridScope.registerSymbol(symbolKey, callback);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// For any source columns not already registered, register them with
|
|
210
|
+
// references to the source table
|
|
211
|
+
const sourceInput = input.getRelations()[0]; // The AggregateNode's source
|
|
212
|
+
const sourceAttributes = sourceInput.getAttributes();
|
|
213
|
+
|
|
214
|
+
sourceAttributes.forEach((sourceAttr, sourceIndex) => {
|
|
215
|
+
const symbolName = sourceAttr.name.toLowerCase();
|
|
216
|
+
const existingSymbols = hybridScope.getSymbols();
|
|
217
|
+
const alreadyRegistered = existingSymbols.some(([key]) => key === symbolName);
|
|
218
|
+
|
|
219
|
+
if (!alreadyRegistered) {
|
|
220
|
+
hybridScope.registerSymbol(symbolName, (exp, s) =>
|
|
221
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, sourceAttr.type, sourceAttr.id, sourceIndex));
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Build HAVING expression with the hybrid scope
|
|
186
226
|
const havingContext: PlanningContext = {
|
|
187
227
|
...selectContext,
|
|
188
|
-
scope:
|
|
228
|
+
scope: hybridScope,
|
|
189
229
|
aggregates: aggregates.map((agg, index) => {
|
|
190
230
|
const columnIndex = groupByExpressions.length + index;
|
|
191
231
|
const attr = aggregateAttributes[columnIndex];
|
|
@@ -200,7 +240,7 @@ function buildHavingFilter(
|
|
|
200
240
|
|
|
201
241
|
const havingExpression = buildExpression(havingContext, havingClause, true);
|
|
202
242
|
|
|
203
|
-
return new FilterNode(
|
|
243
|
+
return new FilterNode(hybridScope, input, havingExpression);
|
|
204
244
|
}
|
|
205
245
|
|
|
206
246
|
/**
|
|
@@ -234,9 +274,15 @@ export function buildFinalAggregateProjections(
|
|
|
234
274
|
const finalContext: PlanningContext = { ...selectContext, scope: aggregateOutputScope };
|
|
235
275
|
const scalarNode = buildExpression(finalContext, column.expr, true);
|
|
236
276
|
|
|
277
|
+
let attrId: number | undefined = undefined;
|
|
278
|
+
if (scalarNode instanceof ColumnReferenceNode) {
|
|
279
|
+
attrId = scalarNode.attributeId;
|
|
280
|
+
}
|
|
281
|
+
|
|
237
282
|
finalProjections.push({
|
|
238
283
|
node: scalarNode,
|
|
239
|
-
alias: column.alias || (column.expr.type === 'column' ? column.expr.name : undefined)
|
|
284
|
+
alias: column.alias || (column.expr.type === 'column' ? column.expr.name : undefined),
|
|
285
|
+
attributeId: attrId
|
|
240
286
|
});
|
|
241
287
|
}
|
|
242
288
|
}
|
|
@@ -27,8 +27,8 @@ export function buildWithContext(
|
|
|
27
27
|
contextWithCTEs: PlanningContext;
|
|
28
28
|
cteNodes: Map<string, CTEPlanNode>;
|
|
29
29
|
} {
|
|
30
|
-
// Start with parent CTEs
|
|
31
|
-
const cteNodes: Map<string, CTEPlanNode> = new Map(parentCTEs);
|
|
30
|
+
// Start with parent CTEs - either from parameter or from context
|
|
31
|
+
const cteNodes: Map<string, CTEPlanNode> = new Map(parentCTEs.size > 0 ? parentCTEs : (ctx.cteNodes ?? new Map()));
|
|
32
32
|
let contextWithCTEs = ctx;
|
|
33
33
|
|
|
34
34
|
if (stmt.withClause) {
|
|
@@ -40,11 +40,11 @@ export function buildWithContext(
|
|
|
40
40
|
|
|
41
41
|
// Create a new scope that includes the CTEs
|
|
42
42
|
const cteScope = createCTEScope(cteNodes, ctx);
|
|
43
|
-
contextWithCTEs = { ...ctx, scope: cteScope };
|
|
44
|
-
} else if (
|
|
43
|
+
contextWithCTEs = { ...ctx, scope: cteScope, cteNodes, cteReferenceCache: ctx.cteReferenceCache };
|
|
44
|
+
} else if (cteNodes.size > 0) {
|
|
45
45
|
// No WITH clause but we have parent CTEs, create scope for them
|
|
46
|
-
const cteScope = createCTEScope(
|
|
47
|
-
contextWithCTEs = { ...ctx, scope: cteScope };
|
|
46
|
+
const cteScope = createCTEScope(cteNodes, ctx);
|
|
47
|
+
contextWithCTEs = { ...ctx, scope: cteScope, cteNodes, cteReferenceCache: ctx.cteReferenceCache };
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
return { contextWithCTEs, cteNodes };
|
|
@@ -52,6 +52,8 @@ export function buildWithContext(
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Creates a scope that includes CTE references
|
|
55
|
+
* CRITICAL: Uses stable input attribute IDs only, ignoring any projection output scopes
|
|
56
|
+
* that might cause attribute ID collisions in correlated subqueries
|
|
55
57
|
*/
|
|
56
58
|
function createCTEScope(
|
|
57
59
|
cteNodes: Map<string, CTEPlanNode>,
|
|
@@ -61,13 +63,21 @@ function createCTEScope(
|
|
|
61
63
|
|
|
62
64
|
// Register each CTE in the scope
|
|
63
65
|
for (const [cteName, cteNode] of cteNodes) {
|
|
66
|
+
// CRITICAL: Use only the stable input attributes from the CTE definition
|
|
67
|
+
// Do NOT use any projection output attributes that might have fresh IDs
|
|
64
68
|
const attributes = cteNode.getAttributes();
|
|
65
|
-
cteNode.getType().columns
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
const columnTypes = cteNode.getType().columns;
|
|
70
|
+
|
|
71
|
+
// Only register columns that are stable input attributes
|
|
72
|
+
// This prevents scope pollution from projection output attributes
|
|
73
|
+
columnTypes.forEach((col: any, i: number) => {
|
|
74
|
+
if (i < attributes.length) {
|
|
75
|
+
const attr = attributes[i];
|
|
76
|
+
// Register CTE columns with qualified names to avoid collisions
|
|
77
|
+
const qualifiedColumnName = `${cteName}.${col.name.toLowerCase()}`;
|
|
78
|
+
cteScope.registerSymbol(qualifiedColumnName, (exp, s) =>
|
|
79
|
+
new ColumnReferenceNode(s, exp as AST.ColumnExpr, col.type, attr.id, i));
|
|
80
|
+
}
|
|
71
81
|
});
|
|
72
82
|
}
|
|
73
83
|
|
|
@@ -20,23 +20,25 @@ export function buildFinalProjections(
|
|
|
20
20
|
projections: Projection[],
|
|
21
21
|
selectScope: any,
|
|
22
22
|
stmt: AST.SelectStmt,
|
|
23
|
-
selectContext: PlanningContext
|
|
23
|
+
selectContext: PlanningContext,
|
|
24
|
+
preserveInputColumns: boolean = true
|
|
24
25
|
): {
|
|
25
26
|
output: RelationalPlanNode;
|
|
26
27
|
finalContext: PlanningContext;
|
|
28
|
+
projectionScope?: RegisteredScope;
|
|
27
29
|
preAggregateSort: boolean;
|
|
28
30
|
} {
|
|
29
31
|
if (projections.length === 0) {
|
|
30
32
|
return { output: input, finalContext: selectContext, preAggregateSort: false };
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
// Check if ORDER BY should be applied before projection
|
|
35
|
+
// Check if ORDER BY should be applied before projection (using input scope only)
|
|
34
36
|
const needsPreProjectionSort = shouldApplyOrderByBeforeProjection(stmt, projections);
|
|
35
37
|
let preAggregateSort = false;
|
|
36
38
|
|
|
37
39
|
let currentInput = input;
|
|
38
40
|
|
|
39
|
-
// Apply ORDER BY before projection if needed
|
|
41
|
+
// Apply ORDER BY before projection if needed (compile expressions against input scope)
|
|
40
42
|
if (needsPreProjectionSort && stmt.orderBy && stmt.orderBy.length > 0) {
|
|
41
43
|
const sortKeys: SortKey[] = stmt.orderBy.map(orderByClause => {
|
|
42
44
|
const expression = buildExpression(selectContext, orderByClause.expr);
|
|
@@ -50,21 +52,17 @@ export function buildFinalProjections(
|
|
|
50
52
|
preAggregateSort = true;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
// Create the ProjectNode only after all expressions are compiled against input scope
|
|
56
|
+
currentInput = new ProjectNode(selectScope, currentInput, projections, undefined, undefined, preserveInputColumns);
|
|
54
57
|
|
|
55
|
-
// Create
|
|
58
|
+
// Create projection output scope but DON'T merge it into finalContext yet
|
|
59
|
+
// Let the caller decide when to make these output attributes visible
|
|
56
60
|
const projectionOutputScope = createProjectionOutputScope(currentInput);
|
|
57
61
|
|
|
58
|
-
// Update selectContext to use BOTH the projection output scope AND the original scope
|
|
59
|
-
let finalContext = selectContext;
|
|
60
|
-
if (!needsPreProjectionSort) {
|
|
61
|
-
const combinedScope = new MultiScope([projectionOutputScope, selectScope]);
|
|
62
|
-
finalContext = { ...selectContext, scope: combinedScope };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
62
|
return {
|
|
66
63
|
output: currentInput,
|
|
67
|
-
finalContext,
|
|
64
|
+
finalContext: selectContext, // Keep unchanged - no premature scope pollution
|
|
65
|
+
projectionScope: projectionOutputScope,
|
|
68
66
|
preAggregateSort
|
|
69
67
|
};
|
|
70
68
|
}
|
|
@@ -90,11 +88,19 @@ export function applyOrderBy(
|
|
|
90
88
|
input: RelationalPlanNode,
|
|
91
89
|
stmt: AST.SelectStmt,
|
|
92
90
|
selectContext: PlanningContext,
|
|
93
|
-
preAggregateSort: boolean
|
|
91
|
+
preAggregateSort: boolean,
|
|
92
|
+
projectionScope?: RegisteredScope
|
|
94
93
|
): RelationalPlanNode {
|
|
95
94
|
if (stmt.orderBy && stmt.orderBy.length > 0 && !preAggregateSort) {
|
|
95
|
+
// Merge projection scope if available so ORDER BY can reference output column aliases
|
|
96
|
+
let orderByContext = selectContext;
|
|
97
|
+
if (projectionScope) {
|
|
98
|
+
const combinedScope = new MultiScope([projectionScope, selectContext.scope]);
|
|
99
|
+
orderByContext = { ...selectContext, scope: combinedScope };
|
|
100
|
+
}
|
|
101
|
+
|
|
96
102
|
const sortKeys: SortKey[] = stmt.orderBy.map(orderByClause => {
|
|
97
|
-
const expression = buildExpression(
|
|
103
|
+
const expression = buildExpression(orderByContext, orderByClause.expr);
|
|
98
104
|
return {
|
|
99
105
|
expression,
|
|
100
106
|
direction: orderByClause.direction,
|
|
@@ -102,7 +108,7 @@ export function applyOrderBy(
|
|
|
102
108
|
};
|
|
103
109
|
});
|
|
104
110
|
|
|
105
|
-
return new SortNode(
|
|
111
|
+
return new SortNode(orderByContext.scope, input, sortKeys);
|
|
106
112
|
}
|
|
107
113
|
return input;
|
|
108
114
|
}
|
|
@@ -113,13 +119,21 @@ export function applyOrderBy(
|
|
|
113
119
|
export function applyLimitOffset(
|
|
114
120
|
input: RelationalPlanNode,
|
|
115
121
|
stmt: AST.SelectStmt,
|
|
116
|
-
selectContext: PlanningContext
|
|
122
|
+
selectContext: PlanningContext,
|
|
123
|
+
projectionScope?: RegisteredScope
|
|
117
124
|
): RelationalPlanNode {
|
|
118
125
|
if (stmt.limit || stmt.offset) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
// Merge projection scope if available so LIMIT/OFFSET can reference output column aliases
|
|
127
|
+
let limitContext = selectContext;
|
|
128
|
+
if (projectionScope) {
|
|
129
|
+
const combinedScope = new MultiScope([projectionScope, selectContext.scope]);
|
|
130
|
+
limitContext = { ...selectContext, scope: combinedScope };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const literalNull = new LiteralNode(limitContext.scope, { type: 'literal', value: null });
|
|
134
|
+
const limitExpression = stmt.limit ? buildExpression(limitContext, stmt.limit) : literalNull;
|
|
135
|
+
const offsetExpression = stmt.offset ? buildExpression(limitContext, stmt.offset) : literalNull;
|
|
136
|
+
return new LimitOffsetNode(limitContext.scope, input, limitExpression, offsetExpression);
|
|
123
137
|
}
|
|
124
138
|
return input;
|
|
125
139
|
}
|
|
@@ -9,6 +9,8 @@ import { QuereusError } from '../../common/errors.js';
|
|
|
9
9
|
import { StatusCode } from '../../common/types.js';
|
|
10
10
|
import { AggregateFunctionCallNode } from '../nodes/aggregate-function.js';
|
|
11
11
|
import { WindowFunctionCallNode } from '../nodes/window-function.js';
|
|
12
|
+
import { type RelationalPlanNode } from '../nodes/plan-node.js';
|
|
13
|
+
import type { Scope } from '../scopes/scope.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Checks if an expression contains aggregate functions
|
|
@@ -53,48 +55,45 @@ export function isWindowExpression(node: ScalarPlanNode): boolean {
|
|
|
53
55
|
*/
|
|
54
56
|
export function buildStarProjections(
|
|
55
57
|
column: { type: 'all'; table?: string },
|
|
56
|
-
|
|
57
|
-
selectScope:
|
|
58
|
+
source: RelationalPlanNode,
|
|
59
|
+
selectScope: Scope
|
|
58
60
|
): Projection[] {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
const allAttributes = source.getAttributes();
|
|
62
|
+
|
|
63
|
+
// Filter by relation name if qualified (e.g., SELECT t1.*)
|
|
64
|
+
const matchingAttributes = column.table
|
|
65
|
+
? allAttributes.filter(attr =>
|
|
66
|
+
attr.relationName && attr.relationName.toLowerCase() === column.table!.toLowerCase()
|
|
67
|
+
)
|
|
68
|
+
: allAttributes;
|
|
69
|
+
|
|
70
|
+
if (column.table && matchingAttributes.length === 0) {
|
|
71
|
+
throw new QuereusError(
|
|
72
|
+
`Table '${column.table}' not found in FROM clause for qualified SELECT *`,
|
|
73
|
+
StatusCode.ERROR
|
|
74
|
+
);
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
+
// Convert to projections
|
|
78
|
+
return matchingAttributes.map((attr, index) => {
|
|
77
79
|
const columnExpr: AST.ColumnExpr = {
|
|
78
80
|
type: 'column',
|
|
79
|
-
name:
|
|
81
|
+
name: attr.name,
|
|
80
82
|
};
|
|
81
83
|
|
|
82
|
-
const attr = inputAttributes[index];
|
|
83
84
|
const columnRef = new ColumnReferenceNode(
|
|
84
85
|
selectScope,
|
|
85
86
|
columnExpr,
|
|
86
|
-
|
|
87
|
+
attr.type,
|
|
87
88
|
attr.id,
|
|
88
89
|
index
|
|
89
90
|
);
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
return {
|
|
92
93
|
node: columnRef,
|
|
93
|
-
alias:
|
|
94
|
-
}
|
|
94
|
+
alias: attr.name
|
|
95
|
+
};
|
|
95
96
|
});
|
|
96
|
-
|
|
97
|
-
return projections;
|
|
98
97
|
}
|
|
99
98
|
|
|
100
99
|
/**
|