@quereus/quereus 2.7.0 → 2.9.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/dist/src/common/errors.d.ts +21 -0
- package/dist/src/common/errors.d.ts.map +1 -1
- package/dist/src/common/errors.js +29 -0
- package/dist/src/common/errors.js.map +1 -1
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +20 -7
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +15 -5
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/emit/ast-stringify.d.ts.map +1 -1
- package/dist/src/emit/ast-stringify.js +0 -4
- package/dist/src/emit/ast-stringify.js.map +1 -1
- package/dist/src/func/builtins/explain.d.ts.map +1 -1
- package/dist/src/func/builtins/explain.js +39 -36
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/json-helpers.d.ts +1 -1
- package/dist/src/func/builtins/json-helpers.d.ts.map +1 -1
- package/dist/src/func/builtins/json-helpers.js.map +1 -1
- package/dist/src/func/builtins/json.d.ts.map +1 -1
- package/dist/src/func/builtins/json.js +5 -7
- package/dist/src/func/builtins/json.js.map +1 -1
- package/dist/src/func/builtins/scalar.d.ts.map +1 -1
- package/dist/src/func/builtins/scalar.js +17 -2
- package/dist/src/func/builtins/scalar.js.map +1 -1
- package/dist/src/func/builtins/string.d.ts.map +1 -1
- package/dist/src/func/builtins/string.js +4 -2
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/parser/ast.d.ts +4 -3
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/lexer.d.ts.map +1 -1
- package/dist/src/parser/lexer.js +8 -48
- package/dist/src/parser/lexer.js.map +1 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +43 -11
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/utils.d.ts +10 -1
- package/dist/src/parser/utils.d.ts.map +1 -1
- package/dist/src/parser/utils.js +23 -0
- package/dist/src/parser/utils.js.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.d.ts.map +1 -1
- package/dist/src/planner/analysis/constraint-extractor.js +0 -1
- package/dist/src/planner/analysis/constraint-extractor.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.d.ts +12 -1
- package/dist/src/planner/building/constraint-builder.d.ts.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +60 -1
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/building/create-view.d.ts.map +1 -1
- package/dist/src/planner/building/create-view.js +16 -0
- package/dist/src/planner/building/create-view.js.map +1 -1
- package/dist/src/planner/building/delete.d.ts.map +1 -1
- package/dist/src/planner/building/delete.js +13 -7
- package/dist/src/planner/building/delete.js.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.d.ts.map +1 -1
- package/dist/src/planner/building/foreign-key-builder.js +27 -17
- package/dist/src/planner/building/foreign-key-builder.js.map +1 -1
- package/dist/src/planner/building/insert.d.ts.map +1 -1
- package/dist/src/planner/building/insert.js +51 -43
- package/dist/src/planner/building/insert.js.map +1 -1
- package/dist/src/planner/building/select-aggregates.d.ts +4 -1
- package/dist/src/planner/building/select-aggregates.d.ts.map +1 -1
- package/dist/src/planner/building/select-aggregates.js +122 -21
- package/dist/src/planner/building/select-aggregates.js.map +1 -1
- package/dist/src/planner/building/select-modifiers.d.ts +6 -2
- package/dist/src/planner/building/select-modifiers.d.ts.map +1 -1
- package/dist/src/planner/building/select-modifiers.js +20 -5
- package/dist/src/planner/building/select-modifiers.js.map +1 -1
- package/dist/src/planner/building/select-ordinal.d.ts +20 -0
- package/dist/src/planner/building/select-ordinal.d.ts.map +1 -0
- package/dist/src/planner/building/select-ordinal.js +62 -0
- package/dist/src/planner/building/select-ordinal.js.map +1 -0
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +78 -19
- package/dist/src/planner/building/select.js.map +1 -1
- package/dist/src/planner/building/update.d.ts.map +1 -1
- package/dist/src/planner/building/update.js +38 -27
- 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 +25 -2
- package/dist/src/planner/building/with.js.map +1 -1
- package/dist/src/planner/framework/characteristics.d.ts +3 -1
- package/dist/src/planner/framework/characteristics.d.ts.map +1 -1
- package/dist/src/planner/framework/characteristics.js +7 -0
- package/dist/src/planner/framework/characteristics.js.map +1 -1
- package/dist/src/planner/framework/physical-utils.d.ts +22 -1
- package/dist/src/planner/framework/physical-utils.d.ts.map +1 -1
- package/dist/src/planner/framework/physical-utils.js +47 -0
- package/dist/src/planner/framework/physical-utils.js.map +1 -1
- package/dist/src/planner/nodes/alias-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/alias-node.js +2 -0
- package/dist/src/planner/nodes/alias-node.js.map +1 -1
- package/dist/src/planner/nodes/asof-scan-node.d.ts +137 -0
- package/dist/src/planner/nodes/asof-scan-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/asof-scan-node.js +223 -0
- package/dist/src/planner/nodes/asof-scan-node.js.map +1 -0
- package/dist/src/planner/nodes/constraint-check-node.d.ts +25 -1
- package/dist/src/planner/nodes/constraint-check-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/constraint-check-node.js +36 -6
- package/dist/src/planner/nodes/constraint-check-node.js.map +1 -1
- package/dist/src/planner/nodes/distinct-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/distinct-node.js +7 -0
- package/dist/src/planner/nodes/distinct-node.js.map +1 -1
- package/dist/src/planner/nodes/filter.d.ts.map +1 -1
- package/dist/src/planner/nodes/filter.js +8 -2
- package/dist/src/planner/nodes/filter.js.map +1 -1
- package/dist/src/planner/nodes/function.d.ts +11 -1
- package/dist/src/planner/nodes/function.d.ts.map +1 -1
- package/dist/src/planner/nodes/function.js +94 -1
- package/dist/src/planner/nodes/function.js.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/hash-aggregate.js +2 -0
- package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-node.js +10 -2
- package/dist/src/planner/nodes/join-node.js.map +1 -1
- package/dist/src/planner/nodes/join-utils.d.ts +19 -1
- package/dist/src/planner/nodes/join-utils.d.ts.map +1 -1
- package/dist/src/planner/nodes/join-utils.js +46 -0
- package/dist/src/planner/nodes/join-utils.js.map +1 -1
- package/dist/src/planner/nodes/limit-offset.d.ts.map +1 -1
- package/dist/src/planner/nodes/limit-offset.js +2 -0
- package/dist/src/planner/nodes/limit-offset.js.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +4 -1
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts +50 -0
- package/dist/src/planner/nodes/ordinal-slice-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/ordinal-slice-node.js +127 -0
- package/dist/src/planner/nodes/ordinal-slice-node.js.map +1 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts +2 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +2 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +130 -1
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js +49 -0
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/project-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/project-node.js +6 -1
- package/dist/src/planner/nodes/project-node.js.map +1 -1
- package/dist/src/planner/nodes/recursive-cte-node.d.ts +5 -3
- package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/recursive-cte-node.js +24 -8
- package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts +4 -1
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +16 -0
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/returning-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/returning-node.js +5 -12
- package/dist/src/planner/nodes/returning-node.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts +7 -1
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +100 -1
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts +2 -1
- package/dist/src/planner/nodes/set-operation-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/set-operation-node.js +9 -0
- package/dist/src/planner/nodes/set-operation-node.js.map +1 -1
- package/dist/src/planner/nodes/sort.d.ts.map +1 -1
- package/dist/src/planner/nodes/sort.js +20 -0
- package/dist/src/planner/nodes/sort.js.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
- package/dist/src/planner/nodes/stream-aggregate.js +2 -0
- package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.d.ts +37 -2
- package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
- package/dist/src/planner/nodes/table-access-nodes.js +87 -10
- package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
- package/dist/src/planner/nodes/update-node.d.ts +1 -3
- package/dist/src/planner/nodes/update-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/update-node.js +3 -9
- package/dist/src/planner/nodes/update-node.js.map +1 -1
- package/dist/src/planner/nodes/window-node.d.ts +61 -2
- package/dist/src/planner/nodes/window-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/window-node.js +64 -3
- package/dist/src/planner/nodes/window-node.js.map +1 -1
- package/dist/src/planner/optimizer-tuning.d.ts +9 -0
- package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
- package/dist/src/planner/optimizer-tuning.js +3 -0
- package/dist/src/planner/optimizer-tuning.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +91 -0
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/rules/access/rule-asof-strategy-select.d.ts +30 -0
- package/dist/src/planner/rules/access/rule-asof-strategy-select.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-asof-strategy-select.js +112 -0
- package/dist/src/planner/rules/access/rule-asof-strategy-select.js.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.d.ts +33 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.js +162 -0
- package/dist/src/planner/rules/access/rule-monotonic-limit-pushdown.js.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts +29 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.d.ts.map +1 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js +175 -0
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -0
- package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +53 -36
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts +61 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.d.ts.map +1 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.js +155 -0
- package/dist/src/planner/rules/join/equi-pair-extractor.js.map +1 -0
- package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-join-physical-selection.js +3 -123
- package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts +21 -0
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.js +405 -0
- package/dist/src/planner/rules/join/rule-lateral-top1-asof.js.map +1 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts +31 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +113 -0
- package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -0
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.js +7 -3
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-filter-merge.js.map +1 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +161 -9
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +2 -2
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/planner/rules/window/rule-monotonic-window.d.ts +47 -0
- package/dist/src/planner/rules/window/rule-monotonic-window.d.ts.map +1 -0
- package/dist/src/planner/rules/window/rule-monotonic-window.js +341 -0
- package/dist/src/planner/rules/window/rule-monotonic-window.js.map +1 -0
- package/dist/src/runtime/context-helpers.d.ts +9 -0
- package/dist/src/runtime/context-helpers.d.ts.map +1 -1
- package/dist/src/runtime/context-helpers.js +5 -0
- package/dist/src/runtime/context-helpers.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +286 -7
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/asof-scan.d.ts +10 -0
- package/dist/src/runtime/emit/asof-scan.d.ts.map +1 -0
- package/dist/src/runtime/emit/asof-scan.js +467 -0
- package/dist/src/runtime/emit/asof-scan.js.map +1 -0
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +12 -7
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/constraint-check.d.ts.map +1 -1
- package/dist/src/runtime/emit/constraint-check.js +145 -62
- package/dist/src/runtime/emit/constraint-check.js.map +1 -1
- package/dist/src/runtime/emit/create-assertion.d.ts.map +1 -1
- package/dist/src/runtime/emit/create-assertion.js +6 -6
- package/dist/src/runtime/emit/create-assertion.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +133 -76
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/ordinal-slice.d.ts +13 -0
- package/dist/src/runtime/emit/ordinal-slice.d.ts.map +1 -0
- package/dist/src/runtime/emit/ordinal-slice.js +89 -0
- package/dist/src/runtime/emit/ordinal-slice.js.map +1 -0
- package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.js +61 -10
- 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 +9 -4
- package/dist/src/runtime/emit/returning.js.map +1 -1
- package/dist/src/runtime/emit/scalar-function.d.ts.map +1 -1
- package/dist/src/runtime/emit/scalar-function.js +2 -1
- package/dist/src/runtime/emit/scalar-function.js.map +1 -1
- package/dist/src/runtime/emit/scan.d.ts +19 -3
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +12 -8
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.js +91 -14
- package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
- package/dist/src/runtime/emit/table-valued-function.d.ts.map +1 -1
- package/dist/src/runtime/emit/table-valued-function.js +4 -2
- 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 +8 -5
- 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 +732 -37
- package/dist/src/runtime/emit/window.js.map +1 -1
- package/dist/src/runtime/foreign-key-actions.js +7 -6
- package/dist/src/runtime/foreign-key-actions.js.map +1 -1
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +4 -0
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/schema/catalog.d.ts +12 -0
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +47 -6
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/column.d.ts +7 -0
- package/dist/src/schema/column.d.ts.map +1 -1
- package/dist/src/schema/column.js.map +1 -1
- package/dist/src/schema/function.d.ts +28 -3
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/manager.d.ts +42 -6
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +175 -23
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/schema/rename-rewriter.d.ts +4 -0
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -0
- package/dist/src/schema/rename-rewriter.js +506 -0
- package/dist/src/schema/rename-rewriter.js.map +1 -0
- package/dist/src/schema/schema-differ.d.ts +18 -1
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +344 -42
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/schema/table.d.ts +65 -2
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +144 -0
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/types/logical-type.d.ts +11 -0
- package/dist/src/types/logical-type.d.ts.map +1 -1
- package/dist/src/types/logical-type.js.map +1 -1
- package/dist/src/util/ast-literal.d.ts +11 -0
- package/dist/src/util/ast-literal.d.ts.map +1 -0
- package/dist/src/util/ast-literal.js +26 -0
- package/dist/src/util/ast-literal.js.map +1 -0
- package/dist/src/util/async-iterator.d.ts +2 -1
- package/dist/src/util/async-iterator.d.ts.map +1 -1
- package/dist/src/util/async-iterator.js +4 -4
- package/dist/src/util/async-iterator.js.map +1 -1
- package/dist/src/util/patterns.d.ts.map +1 -1
- package/dist/src/util/patterns.js +58 -10
- package/dist/src/util/patterns.js.map +1 -1
- package/dist/src/vtab/best-access-plan.d.ts +48 -0
- package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
- package/dist/src/vtab/best-access-plan.js +29 -0
- package/dist/src/vtab/best-access-plan.js.map +1 -1
- package/dist/src/vtab/filter-info.d.ts +14 -0
- package/dist/src/vtab/filter-info.d.ts.map +1 -1
- package/dist/src/vtab/memory/index.d.ts +8 -0
- package/dist/src/vtab/memory/index.d.ts.map +1 -1
- package/dist/src/vtab/memory/index.js +11 -0
- package/dist/src/vtab/memory/index.js.map +1 -1
- package/dist/src/vtab/memory/layer/base.d.ts +8 -1
- package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/base.js +36 -2
- package/dist/src/vtab/memory/layer/base.js.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +5 -1
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +63 -13
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +21 -2
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +45 -2
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +268 -27
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/dist/src/vtab/memory/utils/predicate.d.ts +27 -0
- package/dist/src/vtab/memory/utils/predicate.d.ts.map +1 -0
- package/dist/src/vtab/memory/utils/predicate.js +182 -0
- package/dist/src/vtab/memory/utils/predicate.js.map +1 -0
- package/dist/src/vtab/module.d.ts +24 -0
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -7,6 +7,7 @@ import { resolveKeyNormalizer, serializeKeyNullGrouping } from '../../util/key-s
|
|
|
7
7
|
import { createLogger } from '../../common/logger.js';
|
|
8
8
|
import { buildRowDescriptor } from '../../util/row-descriptor.js';
|
|
9
9
|
import { createRowSlot } from '../context-helpers.js';
|
|
10
|
+
import { tryExtractNumericLiteral } from '../../util/ast-literal.js';
|
|
10
11
|
const log = createLogger('runtime:emit:window');
|
|
11
12
|
export function emitWindow(plan, ctx) {
|
|
12
13
|
// Get schemas for all window functions in this node
|
|
@@ -55,14 +56,21 @@ export function emitWindow(plan, ctx) {
|
|
|
55
56
|
funcArgCallbackGroups.push(callbacks.slice(argOffset, argOffset + count));
|
|
56
57
|
argOffset += count;
|
|
57
58
|
}
|
|
58
|
-
// Collect all rows (window functions require materialization for frame evaluation)
|
|
59
|
-
const allRows = [];
|
|
60
|
-
for await (const row of source) {
|
|
61
|
-
allRows.push(row);
|
|
62
|
-
}
|
|
63
59
|
// Single source slot shared across all partition/sort/ranking/aggregate operations
|
|
64
60
|
const sourceSlot = createRowSlot(rctx, sourceRowDescriptor);
|
|
65
61
|
try {
|
|
62
|
+
if (plan.streaming) {
|
|
63
|
+
// Streaming fast path: source already arrives in
|
|
64
|
+
// [PARTITION BY..., ORDER BY] order, so we walk it once and emit
|
|
65
|
+
// in source order without materializing.
|
|
66
|
+
yield* runStreaming(plan, functionSchemas, rctx, source, sourceRowDescriptor, partitionCallbackList, orderByCallbackList, funcArgCallbackGroups, partitionKeyNormalizers, orderByEqualityComparators);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Buffered path: materialize then partition/sort.
|
|
70
|
+
const allRows = [];
|
|
71
|
+
for await (const row of source) {
|
|
72
|
+
allRows.push(row);
|
|
73
|
+
}
|
|
66
74
|
if (plan.windowSpec.partitionBy.length === 0) {
|
|
67
75
|
// No partitioning - process as single partition
|
|
68
76
|
yield* processPartition(allRows, plan, functionSchemas, rctx, sourceRowDescriptor, partitionCallbackList, orderByCallbackList, funcArgCallbackGroups, sourceSlot, orderByComparators, orderByEqualityComparators);
|
|
@@ -96,7 +104,13 @@ async function groupByPartitions(rows, partitionCallbacks, rctx, sourceSlot, key
|
|
|
96
104
|
const partitions = new Map();
|
|
97
105
|
for (const row of rows) {
|
|
98
106
|
sourceSlot.set(row);
|
|
99
|
-
|
|
107
|
+
// Sequential evaluation: parallel callbacks that share a plan subtree
|
|
108
|
+
// (e.g. PARTITION BY (SELECT ... FROM cte), (SELECT ... FROM cte))
|
|
109
|
+
// would race on the shared inner-scan RowSlot.
|
|
110
|
+
const partitionValues = [];
|
|
111
|
+
for (const callback of partitionCallbacks) {
|
|
112
|
+
partitionValues.push(await callback(rctx));
|
|
113
|
+
}
|
|
100
114
|
const partitionKey = serializeKeyNullGrouping(partitionValues, keyNormalizers);
|
|
101
115
|
if (!partitions.has(partitionKey)) {
|
|
102
116
|
partitions.set(partitionKey, []);
|
|
@@ -154,29 +168,27 @@ async function sortRows(rows, orderBy, orderByCallbacks, rctx, sourceSlot, preRe
|
|
|
154
168
|
if (orderBy.length === 0) {
|
|
155
169
|
return { rows, orderByValues: rows.map(() => []) };
|
|
156
170
|
}
|
|
157
|
-
// Pre-evaluate ORDER BY values for all rows to avoid async in sort
|
|
158
|
-
|
|
171
|
+
// Pre-evaluate ORDER BY values for all rows to avoid async in sort.
|
|
172
|
+
// Sequential outer loop: parallel iterations would race on the shared
|
|
173
|
+
// sourceSlot. Sequential inner loop: parallel callbacks that share a
|
|
174
|
+
// plan subtree would race on the shared inner-scan RowSlot.
|
|
175
|
+
const rowsWithValues = [];
|
|
176
|
+
for (const row of rows) {
|
|
159
177
|
sourceSlot.set(row);
|
|
160
|
-
const values =
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
}
|
|
178
|
+
const values = [];
|
|
179
|
+
for (const callback of orderByCallbacks) {
|
|
180
|
+
values.push(await callback(rctx));
|
|
181
|
+
}
|
|
182
|
+
rowsWithValues.push({ row, values });
|
|
183
|
+
}
|
|
166
184
|
// Now sort using the pre-evaluated values
|
|
167
185
|
rowsWithValues.sort((a, b) => {
|
|
168
186
|
// Compare each ORDER BY expression in sequence
|
|
169
187
|
for (let i = 0; i < orderBy.length; i++) {
|
|
170
|
-
const
|
|
171
|
-
const valueA = a.values[i];
|
|
172
|
-
const valueB = b.values[i];
|
|
173
|
-
// Use pre-created optimized comparator
|
|
174
|
-
const comparison = comparator(valueA, valueB);
|
|
175
|
-
// If not equal, return comparison result
|
|
188
|
+
const comparison = preResolvedComparators[i](a.values[i], b.values[i]);
|
|
176
189
|
if (comparison !== 0) {
|
|
177
190
|
return comparison;
|
|
178
191
|
}
|
|
179
|
-
// Equal, continue to next ORDER BY expression
|
|
180
192
|
}
|
|
181
193
|
return 0; // All ORDER BY expressions are equal
|
|
182
194
|
});
|
|
@@ -490,21 +502,704 @@ function getFrameOffset(expr) {
|
|
|
490
502
|
}
|
|
491
503
|
return value;
|
|
492
504
|
}
|
|
493
|
-
function
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
505
|
+
function makeFuncState(mode) {
|
|
506
|
+
const s = { mode };
|
|
507
|
+
switch (mode.kind) {
|
|
508
|
+
case 'lag':
|
|
509
|
+
s.lagBuffer = [];
|
|
510
|
+
break;
|
|
511
|
+
case 'lead':
|
|
512
|
+
s.leadQueue = [];
|
|
513
|
+
break;
|
|
514
|
+
case 'firstValue':
|
|
515
|
+
s.firstValueCached = { value: null, cached: false };
|
|
516
|
+
break;
|
|
517
|
+
case 'runningAgg':
|
|
518
|
+
s.aggAccumulator = null;
|
|
519
|
+
s.aggRowCount = 0;
|
|
520
|
+
s.pendingPeerEntries = [];
|
|
521
|
+
break;
|
|
522
|
+
case 'slidingAgg':
|
|
523
|
+
s.slidingBuffer = [];
|
|
524
|
+
s.slidingHead = 0;
|
|
525
|
+
s.slidingAcc = { sum: 0, count: 0 };
|
|
526
|
+
s.slidingNextFinalizeIdx = 0;
|
|
527
|
+
if (mode.frameMode === 'rows') {
|
|
528
|
+
s.slidingPending = [];
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
s.slidingRangePending = [];
|
|
532
|
+
}
|
|
533
|
+
break;
|
|
534
|
+
default:
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
return s;
|
|
538
|
+
}
|
|
539
|
+
function freshPartitionState(streamingModes) {
|
|
540
|
+
return {
|
|
541
|
+
rowCount: 0,
|
|
542
|
+
denseRankCounter: 0,
|
|
543
|
+
currentRank: 0,
|
|
544
|
+
lastOrderByValues: null,
|
|
545
|
+
queue: [],
|
|
546
|
+
funcStates: streamingModes.map(makeFuncState),
|
|
547
|
+
pendingPeers: [],
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function arePeers(a, b, cmps) {
|
|
551
|
+
for (let i = 0; i < cmps.length; i++) {
|
|
552
|
+
if (cmps[i](a[i], b[i]) !== 0)
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Streaming runner. Processes one row at a time, yielding output rows once
|
|
559
|
+
* their slot values are all finalised.
|
|
560
|
+
*/
|
|
561
|
+
async function* runStreaming(plan, functionSchemas, rctx, source, sourceRowDescriptor, partitionCallbacks, orderByCallbacks, funcArgCallbackGroups, partitionKeyNormalizers, orderByEqualityComparators) {
|
|
562
|
+
const streaming = plan.streaming;
|
|
563
|
+
const funcContexts = plan.functions.map((_func, fi) => ({
|
|
564
|
+
fi,
|
|
565
|
+
schema: functionSchemas[fi],
|
|
566
|
+
args: funcArgCallbackGroups[fi],
|
|
567
|
+
}));
|
|
568
|
+
const funcCount = plan.functions.length;
|
|
569
|
+
// Frame mode for RANGE-vs-ROWS peer handling on running aggregates.
|
|
570
|
+
// Default frame (with ORDER BY) is RANGE; explicit ROWS UNBOUNDED PRECEDING
|
|
571
|
+
// suppresses peer-buffering.
|
|
572
|
+
const frame = plan.windowSpec.frame;
|
|
573
|
+
const isRangeMode = frame === undefined || frame.type === 'range';
|
|
574
|
+
let curPartitionKey = null;
|
|
575
|
+
let state = null;
|
|
576
|
+
// We register our own source-attribute getter directly in the rctx context.
|
|
577
|
+
// This bypasses the slot abstraction so we can fully control insertion
|
|
578
|
+
// order: each iteration we delete-then-re-set the entry, pushing it to
|
|
579
|
+
// the *end* of the map's insertion order. This matters when streaming
|
|
580
|
+
// Windows are stacked — without re-promotion, an outer Window's slot
|
|
581
|
+
// (registered later) would shadow ours during our iterations, and our
|
|
582
|
+
// attribute resolutions would read the outer Window's stale row.
|
|
583
|
+
//
|
|
584
|
+
// Use a fresh descriptor reference (NOT `sourceRowDescriptor`) so we
|
|
585
|
+
// occupy our own map slot rather than co-tenanting Window's outer
|
|
586
|
+
// `sourceSlot` entry.
|
|
587
|
+
const myDesc = [];
|
|
588
|
+
for (const k in sourceRowDescriptor) {
|
|
589
|
+
const idx = sourceRowDescriptor[+k];
|
|
590
|
+
if (idx !== undefined)
|
|
591
|
+
myDesc[+k] = idx;
|
|
592
|
+
}
|
|
593
|
+
const myRef = { current: undefined };
|
|
594
|
+
const myGetter = () => myRef.current;
|
|
595
|
+
let myRegistered = false;
|
|
596
|
+
const promote = (row) => {
|
|
597
|
+
myRef.current = row;
|
|
598
|
+
// Move our entry to the end of the context map by deleting and re-adding.
|
|
599
|
+
// `Map.set` on an existing key only updates the value; it does not move
|
|
600
|
+
// the key. We need re-insertion to win attribute-index rebuilds
|
|
601
|
+
// triggered by upstream `withAsyncRowContext` cycles.
|
|
602
|
+
if (myRegistered) {
|
|
603
|
+
rctx.context.delete(myDesc);
|
|
604
|
+
}
|
|
605
|
+
rctx.context.set(myDesc, myGetter);
|
|
606
|
+
myRegistered = true;
|
|
607
|
+
};
|
|
608
|
+
try {
|
|
609
|
+
for await (const row of source) {
|
|
610
|
+
promote(row);
|
|
611
|
+
// Resolve partition key. Sequential evaluation: parallel callbacks
|
|
612
|
+
// that share a plan subtree would race on the shared inner-scan
|
|
613
|
+
// RowSlot.
|
|
614
|
+
const partitionValues = [];
|
|
615
|
+
for (const cb of partitionCallbacks) {
|
|
616
|
+
partitionValues.push(await cb(rctx));
|
|
617
|
+
}
|
|
618
|
+
const partitionKey = serializeKeyNullGrouping(partitionValues, partitionKeyNormalizers);
|
|
619
|
+
// Resolve ORDER BY values (same shared-subtree concern as above).
|
|
620
|
+
const orderByValues = [];
|
|
621
|
+
for (const cb of orderByCallbacks) {
|
|
622
|
+
orderByValues.push(await cb(rctx));
|
|
623
|
+
}
|
|
624
|
+
// Partition boundary: close out the previous partition.
|
|
625
|
+
if (state !== null && partitionKey !== curPartitionKey) {
|
|
626
|
+
yield* finalizePartition(state, funcContexts, isRangeMode, rctx, promote);
|
|
627
|
+
promote(row);
|
|
628
|
+
state = null;
|
|
629
|
+
}
|
|
630
|
+
if (state === null) {
|
|
631
|
+
state = freshPartitionState(streaming.modes);
|
|
632
|
+
curPartitionKey = partitionKey;
|
|
633
|
+
}
|
|
634
|
+
// Peer-group boundary detection (within the current partition).
|
|
635
|
+
const isPeerOfPrev = state.lastOrderByValues !== null &&
|
|
636
|
+
arePeers(orderByValues, state.lastOrderByValues, orderByEqualityComparators);
|
|
637
|
+
// Closing the prior peer group fills RANGE-mode running-agg slots.
|
|
638
|
+
if (state.lastOrderByValues !== null && !isPeerOfPrev) {
|
|
639
|
+
closePeerGroup(state, funcContexts, isRangeMode);
|
|
640
|
+
}
|
|
641
|
+
// Update ranking-related counters BEFORE creating the new entry: row_number
|
|
642
|
+
// and dense_rank are determined at row arrival.
|
|
643
|
+
const rowIndex0Based = state.rowCount; // 0-based position in partition
|
|
644
|
+
state.rowCount++;
|
|
645
|
+
if (!isPeerOfPrev) {
|
|
646
|
+
state.denseRankCounter++;
|
|
647
|
+
state.currentRank = rowIndex0Based + 1;
|
|
648
|
+
}
|
|
649
|
+
// Pre-evaluate args[0] (the value expression) for each function. Done
|
|
650
|
+
// inline because the source slot is set to the current row right now.
|
|
651
|
+
const expr0Values = new Array(funcCount).fill(null);
|
|
652
|
+
for (let fi = 0; fi < funcCount; fi++) {
|
|
653
|
+
const fc = funcContexts[fi];
|
|
654
|
+
if (fc.args.length >= 1) {
|
|
655
|
+
expr0Values[fi] = await Promise.resolve(fc.args[0](rctx));
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
// Numeric form of the leading ORDER BY value, used by RANGE-sliding.
|
|
659
|
+
// SQL NULL must coerce to NaN (not `Number(null) === 0`) so the
|
|
660
|
+
// non-finite-peer-span branch handles it correctly.
|
|
661
|
+
const orderByLead = orderByValues.length > 0 ? orderByValues[0] : null;
|
|
662
|
+
const orderByVal0Num = orderByLead === null ? NaN : Number(orderByLead);
|
|
663
|
+
// Allocate a new queue entry for this row.
|
|
664
|
+
const sourceColCount = row.length;
|
|
665
|
+
const outRow = new Array(sourceColCount + funcCount);
|
|
666
|
+
for (let i = 0; i < sourceColCount; i++)
|
|
667
|
+
outRow[i] = row[i];
|
|
668
|
+
for (let i = 0; i < funcCount; i++)
|
|
669
|
+
outRow[sourceColCount + i] = null;
|
|
670
|
+
const entry = {
|
|
671
|
+
row: outRow,
|
|
672
|
+
filled: new Array(funcCount).fill(false),
|
|
673
|
+
pending: funcCount,
|
|
674
|
+
funcSlotsStart: sourceColCount,
|
|
675
|
+
};
|
|
676
|
+
state.queue.push(entry);
|
|
677
|
+
// Per-function update: fill what we can, defer the rest.
|
|
678
|
+
for (let fi = 0; fi < funcCount; fi++) {
|
|
679
|
+
const fs = state.funcStates[fi];
|
|
680
|
+
const fc = funcContexts[fi];
|
|
681
|
+
const argVal = expr0Values[fi];
|
|
682
|
+
switch (fs.mode.kind) {
|
|
683
|
+
case 'rowNumber':
|
|
684
|
+
fillSlot(entry, fi, rowIndex0Based + 1);
|
|
685
|
+
break;
|
|
686
|
+
case 'rank':
|
|
687
|
+
fillSlot(entry, fi, state.currentRank);
|
|
688
|
+
break;
|
|
689
|
+
case 'denseRank':
|
|
690
|
+
fillSlot(entry, fi, state.denseRankCounter);
|
|
691
|
+
break;
|
|
692
|
+
case 'lag':
|
|
693
|
+
await fillLag(entry, fi, fs, fc, argVal, rctx);
|
|
694
|
+
break;
|
|
695
|
+
case 'lead':
|
|
696
|
+
handleLead(entry, fi, fs, argVal);
|
|
697
|
+
break;
|
|
698
|
+
case 'firstValue':
|
|
699
|
+
if (!fs.firstValueCached.cached) {
|
|
700
|
+
fs.firstValueCached.value = argVal;
|
|
701
|
+
fs.firstValueCached.cached = true;
|
|
702
|
+
}
|
|
703
|
+
fillSlot(entry, fi, fs.firstValueCached.value);
|
|
704
|
+
break;
|
|
705
|
+
case 'lastValue':
|
|
706
|
+
fillSlot(entry, fi, argVal);
|
|
707
|
+
break;
|
|
708
|
+
case 'runningAgg':
|
|
709
|
+
stepRunningAgg(entry, fi, fs, fc, argVal, isRangeMode);
|
|
710
|
+
break;
|
|
711
|
+
case 'slidingAgg':
|
|
712
|
+
handleSlidingArrival(entry, fi, fs, argVal, orderByVal0Num);
|
|
713
|
+
break;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
state.lastOrderByValues = orderByValues;
|
|
717
|
+
// Yield any front-queue entries that are now fully filled.
|
|
718
|
+
// Promote our slot at the yielded row before yielding so downstream
|
|
719
|
+
// attribute resolution sees the yielded row, not the row we're
|
|
720
|
+
// currently processing.
|
|
721
|
+
while (state.queue.length > 0 && state.queue[0].pending === 0) {
|
|
722
|
+
const entry = state.queue.shift();
|
|
723
|
+
const yieldedRow = entry.row;
|
|
724
|
+
promote(yieldedRow);
|
|
725
|
+
yield yieldedRow;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
// Source exhausted: flush trailing partition (if any).
|
|
729
|
+
if (state !== null) {
|
|
730
|
+
yield* finalizePartition(state, funcContexts, isRangeMode, rctx, promote);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
finally {
|
|
734
|
+
if (myRegistered)
|
|
735
|
+
rctx.context.delete(myDesc);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
/** Mark slot `fi` of `entry` filled with `value`. Idempotent on already-filled slots. */
|
|
739
|
+
function fillSlot(entry, fi, value) {
|
|
740
|
+
if (entry.filled[fi])
|
|
741
|
+
return;
|
|
742
|
+
entry.filled[fi] = true;
|
|
743
|
+
entry.row[entry.funcSlotsStart + fi] = value;
|
|
744
|
+
entry.pending--;
|
|
745
|
+
}
|
|
746
|
+
async function fillLag(entry, fi, fs, fc, currentArgVal, rctx) {
|
|
747
|
+
const offset = fs.mode.offset;
|
|
748
|
+
const buf = fs.lagBuffer;
|
|
749
|
+
let lagged;
|
|
750
|
+
// LAG with offset 0 returns current row's expr value.
|
|
751
|
+
if (offset === 0) {
|
|
752
|
+
lagged = currentArgVal;
|
|
753
|
+
}
|
|
754
|
+
else if (buf.length >= offset) {
|
|
755
|
+
// buf holds the last `offset` evaluated arg values prior to this row.
|
|
756
|
+
lagged = buf[buf.length - offset];
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
// Not enough history: use default if provided, else NULL.
|
|
760
|
+
lagged = await evalLagLeadDefault(fc, rctx);
|
|
761
|
+
}
|
|
762
|
+
fillSlot(entry, fi, lagged);
|
|
763
|
+
// Push current arg value into ring buffer; trim when oversized.
|
|
764
|
+
buf.push(currentArgVal);
|
|
765
|
+
if (buf.length > offset)
|
|
766
|
+
buf.shift();
|
|
767
|
+
}
|
|
768
|
+
/** Evaluate a LAG/LEAD's optional default-value argument (args[2]) in the
|
|
769
|
+
* current source-slot context. Mirrors the buffered emitter, which also
|
|
770
|
+
* evaluates the default per-row in the current source context. */
|
|
771
|
+
async function evalLagLeadDefault(fc, rctx) {
|
|
772
|
+
if (fc.args.length < 3)
|
|
773
|
+
return null;
|
|
774
|
+
return await Promise.resolve(fc.args[2](rctx));
|
|
775
|
+
}
|
|
776
|
+
function handleLead(entry, fi, fs, currentArgVal) {
|
|
777
|
+
const offset = fs.mode.offset;
|
|
778
|
+
if (offset === 0) {
|
|
779
|
+
fillSlot(entry, fi, currentArgVal);
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
// When this is the offset+1-th entry in the queue, fill the head's lead
|
|
783
|
+
// slot with the current row's expr value.
|
|
784
|
+
const leadQ = fs.leadQueue;
|
|
785
|
+
if (leadQ.length >= offset) {
|
|
786
|
+
const target = leadQ[leadQ.length - offset];
|
|
787
|
+
fillSlot(target, fi, currentArgVal);
|
|
788
|
+
}
|
|
789
|
+
leadQ.push(entry);
|
|
790
|
+
// Bound to offset+1: once we've filled an entry's slot, we no longer need to
|
|
791
|
+
// keep it referenced.
|
|
792
|
+
if (leadQ.length > offset)
|
|
793
|
+
leadQ.shift();
|
|
794
|
+
}
|
|
795
|
+
function stepRunningAgg(entry, fi, fs, fc, argVal, isRangeMode) {
|
|
796
|
+
const schema = fc.schema;
|
|
797
|
+
if (schema.step) {
|
|
798
|
+
fs.aggAccumulator = schema.step(fs.aggAccumulator, argVal);
|
|
799
|
+
fs.aggRowCount = (fs.aggRowCount ?? 0) + 1;
|
|
800
|
+
}
|
|
801
|
+
if (!isRangeMode) {
|
|
802
|
+
// ROWS UNBOUNDED PRECEDING TO CURRENT ROW: each row gets its post-step
|
|
803
|
+
// final value immediately.
|
|
804
|
+
const finalValue = schema.final
|
|
805
|
+
? schema.final(fs.aggAccumulator, fs.aggRowCount ?? 0)
|
|
806
|
+
: fs.aggAccumulator;
|
|
807
|
+
fillSlot(entry, fi, finalValue);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
// RANGE mode: defer until peer group closes. Track this entry as part of
|
|
811
|
+
// the open peer group; we'll backfill at close.
|
|
812
|
+
fs.pendingPeerEntries.push(entry);
|
|
813
|
+
}
|
|
814
|
+
function closePeerGroup(state, funcContexts, isRangeMode) {
|
|
815
|
+
if (!isRangeMode)
|
|
816
|
+
return;
|
|
817
|
+
for (let fi = 0; fi < funcContexts.length; fi++) {
|
|
818
|
+
const fs = state.funcStates[fi];
|
|
819
|
+
if (fs.mode.kind !== 'runningAgg')
|
|
820
|
+
continue;
|
|
821
|
+
const schema = funcContexts[fi].schema;
|
|
822
|
+
const value = schema.final
|
|
823
|
+
? schema.final(fs.aggAccumulator, fs.aggRowCount ?? 0)
|
|
824
|
+
: fs.aggAccumulator;
|
|
825
|
+
const pending = fs.pendingPeerEntries;
|
|
826
|
+
for (const entry of pending) {
|
|
827
|
+
fillSlot(entry, fi, value);
|
|
828
|
+
}
|
|
829
|
+
pending.length = 0;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
async function* finalizePartition(state, funcContexts, isRangeMode, rctx, promote) {
|
|
833
|
+
// Close trailing peer group (RANGE running aggs).
|
|
834
|
+
closePeerGroup(state, funcContexts, isRangeMode);
|
|
835
|
+
// Drain LEAD queues with default values for unfilled trailing entries.
|
|
836
|
+
for (let fi = 0; fi < funcContexts.length; fi++) {
|
|
837
|
+
const fs = state.funcStates[fi];
|
|
838
|
+
if (fs.mode.kind !== 'lead')
|
|
839
|
+
continue;
|
|
840
|
+
const fc = funcContexts[fi];
|
|
841
|
+
const offset = fs.mode.offset;
|
|
842
|
+
if (offset === 0)
|
|
843
|
+
continue;
|
|
844
|
+
const leadQ = fs.leadQueue;
|
|
845
|
+
const def = await evalLagLeadDefault(fc, rctx);
|
|
846
|
+
for (const entry of leadQ) {
|
|
847
|
+
if (!entry.filled[fi]) {
|
|
848
|
+
fillSlot(entry, fi, def);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
// Finalize trailing pending entries for sliding-frame functions. Their
|
|
853
|
+
// frames clamp at the partition end; values are computed from the
|
|
854
|
+
// current sliding state.
|
|
855
|
+
for (let fi = 0; fi < funcContexts.length; fi++) {
|
|
856
|
+
const fs = state.funcStates[fi];
|
|
857
|
+
if (fs.mode.kind !== 'slidingAgg')
|
|
858
|
+
continue;
|
|
859
|
+
finalizeSlidingTrailing(fi, fs);
|
|
860
|
+
}
|
|
861
|
+
// Yield queued entries in order. Promote our slot to each entry's row so
|
|
862
|
+
// downstream attribute resolution sees the correct row.
|
|
863
|
+
for (const entry of state.queue) {
|
|
864
|
+
promote(entry.row);
|
|
865
|
+
yield entry.row;
|
|
866
|
+
}
|
|
867
|
+
state.queue.length = 0;
|
|
868
|
+
}
|
|
869
|
+
// ============================================================================
|
|
870
|
+
// Sliding-frame helpers (slidingAgg mode)
|
|
871
|
+
// ============================================================================
|
|
872
|
+
//
|
|
873
|
+
// Activated when `rule-monotonic-window` recognizes
|
|
874
|
+
// `ROWS BETWEEN n PRECEDING AND m FOLLOWING` or
|
|
875
|
+
// `RANGE BETWEEN <num> PRECEDING AND <num> FOLLOWING` (with literal
|
|
876
|
+
// non-negative offsets) over the supported aggregates / value functions.
|
|
877
|
+
//
|
|
878
|
+
// ROWS strategy (per function):
|
|
879
|
+
// - `slidingBuffer` holds {argVal, orderByVal0} for rows with index in
|
|
880
|
+
// [slidingHead, currentRow]; entries fall off the front as they age out
|
|
881
|
+
// of the leftmost-pending entry's frame.
|
|
882
|
+
// - SUM/COUNT/AVG: maintain a `{ sum, count }` accumulator with step+unstep;
|
|
883
|
+
// skip null argVals (matches the schema's null-skipping semantics).
|
|
884
|
+
// - MIN/MAX/FIRST_VALUE/LAST_VALUE: recompute from the buffer slice on each
|
|
885
|
+
// finalize (acceptable for v1 — windows are typically small).
|
|
886
|
+
// - Each pending entry is finalized when row `j + following` arrives
|
|
887
|
+
// (mid-partition) or at partition close (right edge clamps to last row).
|
|
888
|
+
//
|
|
889
|
+
// RANGE strategy (per function):
|
|
890
|
+
// - Bounds advance by ORDER BY value, not by row offset.
|
|
891
|
+
// - Each pending entry tracks its `v_j` and a `rightClosed` flag flipped on
|
|
892
|
+
// by a later arrival whose value strictly exceeds `v_j + following`.
|
|
893
|
+
// - On finalize: scan the buffer for rows in [v_j - preceding, v_j +
|
|
894
|
+
// following] (finite v_j) or for the contiguous non-finite peer span
|
|
895
|
+
// (non-finite v_j); compute the aggregate by direct scan in v1 (no
|
|
896
|
+
// incremental acc — keeps the code simple and handles non-finite v
|
|
897
|
+
// entries cleanly).
|
|
898
|
+
function slidingStepNum(acc, argVal) {
|
|
899
|
+
if (argVal === null)
|
|
900
|
+
return;
|
|
901
|
+
acc.sum += Number(argVal);
|
|
902
|
+
acc.count += 1;
|
|
903
|
+
}
|
|
904
|
+
function slidingUnstepNum(acc, argVal) {
|
|
905
|
+
if (argVal === null)
|
|
906
|
+
return;
|
|
907
|
+
acc.sum -= Number(argVal);
|
|
908
|
+
acc.count -= 1;
|
|
909
|
+
}
|
|
910
|
+
function slidingFinalAcc(name, acc) {
|
|
911
|
+
switch (name) {
|
|
912
|
+
case 'sum': return acc.count === 0 ? null : acc.sum;
|
|
913
|
+
case 'count': return acc.count;
|
|
914
|
+
case 'avg': return acc.count === 0 ? null : acc.sum / acc.count;
|
|
915
|
+
default: return null;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
function slidingScanMin(buf, lo, hi) {
|
|
919
|
+
let best = null;
|
|
920
|
+
for (let k = lo; k <= hi; k++) {
|
|
921
|
+
const v = buf[k].argVal;
|
|
922
|
+
if (v === null)
|
|
923
|
+
continue;
|
|
924
|
+
if (best === null || v < best)
|
|
925
|
+
best = v;
|
|
926
|
+
}
|
|
927
|
+
return best;
|
|
928
|
+
}
|
|
929
|
+
function slidingScanMax(buf, lo, hi) {
|
|
930
|
+
let best = null;
|
|
931
|
+
for (let k = lo; k <= hi; k++) {
|
|
932
|
+
const v = buf[k].argVal;
|
|
933
|
+
if (v === null)
|
|
934
|
+
continue;
|
|
935
|
+
if (best === null || v > best)
|
|
936
|
+
best = v;
|
|
937
|
+
}
|
|
938
|
+
return best;
|
|
939
|
+
}
|
|
940
|
+
function slidingScanCountNonNull(buf, lo, hi) {
|
|
941
|
+
let n = 0;
|
|
942
|
+
for (let k = lo; k <= hi; k++) {
|
|
943
|
+
if (buf[k].argVal !== null)
|
|
944
|
+
n++;
|
|
945
|
+
}
|
|
946
|
+
return n;
|
|
947
|
+
}
|
|
948
|
+
function slidingScanSum(buf, lo, hi) {
|
|
949
|
+
let sum = 0, count = 0;
|
|
950
|
+
for (let k = lo; k <= hi; k++) {
|
|
951
|
+
const v = buf[k].argVal;
|
|
952
|
+
if (v === null)
|
|
953
|
+
continue;
|
|
954
|
+
sum += Number(v);
|
|
955
|
+
count += 1;
|
|
956
|
+
}
|
|
957
|
+
return { sum, count };
|
|
958
|
+
}
|
|
959
|
+
/** Per-row dispatch for slidingAgg functions. */
|
|
960
|
+
function handleSlidingArrival(entry, fi, fs, argVal, orderByVal0Num) {
|
|
961
|
+
const m = fs.mode;
|
|
962
|
+
fs.slidingBuffer.push({ argVal, orderByVal0: orderByVal0Num });
|
|
963
|
+
if (m.frameMode === 'rows') {
|
|
964
|
+
handleSlidingRowsArrival(entry, fi, fs, m, argVal);
|
|
965
|
+
}
|
|
966
|
+
else {
|
|
967
|
+
handleSlidingRangeArrival(entry, fi, fs, m, orderByVal0Num);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
// ----- ROWS sliding -----
|
|
971
|
+
function handleSlidingRowsArrival(entry, fi, fs, m, argVal) {
|
|
972
|
+
if (m.name === 'sum' || m.name === 'count' || m.name === 'avg') {
|
|
973
|
+
slidingStepNum(fs.slidingAcc, argVal);
|
|
974
|
+
}
|
|
975
|
+
fs.slidingPending.push(entry);
|
|
976
|
+
while (fs.slidingPending.length > m.following) {
|
|
977
|
+
finalizeSlidingRowsEntry(fi, fs, m);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
function finalizeSlidingRowsEntry(fi, fs, m) {
|
|
981
|
+
const j = fs.slidingNextFinalizeIdx;
|
|
982
|
+
const targetLeft = Math.max(0, j - m.preceding);
|
|
983
|
+
// Trim left: rows that have aged out of the next-pending entry's frame.
|
|
984
|
+
while (fs.slidingHead < targetLeft) {
|
|
985
|
+
if (m.name === 'sum' || m.name === 'count' || m.name === 'avg') {
|
|
986
|
+
slidingUnstepNum(fs.slidingAcc, fs.slidingBuffer[0].argVal);
|
|
987
|
+
}
|
|
988
|
+
fs.slidingBuffer.shift();
|
|
989
|
+
fs.slidingHead++;
|
|
990
|
+
}
|
|
991
|
+
const buf = fs.slidingBuffer;
|
|
992
|
+
const lo = 0;
|
|
993
|
+
const hi = buf.length - 1;
|
|
994
|
+
let value;
|
|
995
|
+
switch (m.name) {
|
|
996
|
+
case 'sum':
|
|
997
|
+
case 'count':
|
|
998
|
+
case 'avg':
|
|
999
|
+
value = slidingFinalAcc(m.name, fs.slidingAcc);
|
|
1000
|
+
break;
|
|
1001
|
+
case 'min':
|
|
1002
|
+
value = slidingScanMin(buf, lo, hi);
|
|
1003
|
+
break;
|
|
1004
|
+
case 'max':
|
|
1005
|
+
value = slidingScanMax(buf, lo, hi);
|
|
1006
|
+
break;
|
|
1007
|
+
case 'first_value':
|
|
1008
|
+
value = lo > hi ? null : buf[lo].argVal;
|
|
1009
|
+
break;
|
|
1010
|
+
case 'last_value':
|
|
1011
|
+
value = lo > hi ? null : buf[hi].argVal;
|
|
1012
|
+
break;
|
|
1013
|
+
default:
|
|
1014
|
+
value = null;
|
|
1015
|
+
}
|
|
1016
|
+
const targetEntry = fs.slidingPending.shift();
|
|
1017
|
+
fillSlot(targetEntry, fi, value);
|
|
1018
|
+
fs.slidingNextFinalizeIdx++;
|
|
1019
|
+
}
|
|
1020
|
+
// ----- RANGE sliding -----
|
|
1021
|
+
function handleSlidingRangeArrival(entry, fi, fs, m, orderByVal0Num) {
|
|
1022
|
+
const isFinite = Number.isFinite(orderByVal0Num);
|
|
1023
|
+
const pending = fs.slidingRangePending;
|
|
1024
|
+
pending.push({ entry, v_j: orderByVal0Num, isFinite, rightClosed: false });
|
|
1025
|
+
// Mark right-closed for any pending entry whose right edge has now been
|
|
1026
|
+
// strictly exceeded by this arrival. Walking front-to-back: once an
|
|
1027
|
+
// existing entry is right-closed, we can stop (since pending is in
|
|
1028
|
+
// arrival order and v's are sorted).
|
|
1029
|
+
for (const p of pending) {
|
|
1030
|
+
if (p.rightClosed)
|
|
1031
|
+
continue;
|
|
1032
|
+
if (!p.isFinite) {
|
|
1033
|
+
// Non-finite entry: closes once a finite-v row arrives (the
|
|
1034
|
+
// non-finite peer span ends).
|
|
1035
|
+
if (isFinite)
|
|
1036
|
+
p.rightClosed = true;
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
if (isFinite && orderByVal0Num > p.v_j + m.following)
|
|
1040
|
+
p.rightClosed = true;
|
|
1041
|
+
// Finite entry followed by a non-finite arrival doesn't close it
|
|
1042
|
+
// (might still see more finite rows in the same partition — but
|
|
1043
|
+
// since the source is monotonic, finite never follows non-finite
|
|
1044
|
+
// in practice).
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
while (pending.length > 0 && pending[0].rightClosed) {
|
|
1048
|
+
finalizeSlidingRangeEntry(fi, fs, m);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Find the buffer index range that constitutes the finite-v window
|
|
1053
|
+
* [v_j - preceding, v_j + following]. Returns lo > hi for an empty range
|
|
1054
|
+
* (shouldn't happen for finite v_j because v_j itself is in scope).
|
|
1055
|
+
*/
|
|
1056
|
+
function findRangeWindow(buf, v_j, preceding, following) {
|
|
1057
|
+
const left = v_j - preceding;
|
|
1058
|
+
const right = v_j + following;
|
|
1059
|
+
let lo = -1, hi = -1;
|
|
1060
|
+
for (let k = 0; k < buf.length; k++) {
|
|
1061
|
+
const v = buf[k].orderByVal0;
|
|
1062
|
+
if (!Number.isFinite(v))
|
|
1063
|
+
continue;
|
|
1064
|
+
if (v < left)
|
|
1065
|
+
continue;
|
|
1066
|
+
if (v > right)
|
|
1067
|
+
break; // buffer is in v-sorted order for finite v
|
|
1068
|
+
if (lo < 0)
|
|
1069
|
+
lo = k;
|
|
1070
|
+
hi = k;
|
|
1071
|
+
}
|
|
1072
|
+
return { lo, hi };
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Find the contiguous non-finite peer span around the given pending entry's
|
|
1076
|
+
* row in the buffer. The span is the maximal run of consecutive non-finite-v
|
|
1077
|
+
* rows in `buf` that includes `entryIdx` (or the latest non-finite row, if
|
|
1078
|
+
* the entry has already been shifted out).
|
|
1079
|
+
*/
|
|
1080
|
+
function findNonFinitePeerSpan(buf) {
|
|
1081
|
+
// Find the run that contains the entry. For monotonic input, non-finite
|
|
1082
|
+
// rows cluster at edges. We look for any non-finite run.
|
|
1083
|
+
let lo = -1, hi = -1;
|
|
1084
|
+
for (let k = 0; k < buf.length; k++) {
|
|
1085
|
+
if (!Number.isFinite(buf[k].orderByVal0)) {
|
|
1086
|
+
if (lo < 0)
|
|
1087
|
+
lo = k;
|
|
1088
|
+
hi = k;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
return { lo, hi };
|
|
1092
|
+
}
|
|
1093
|
+
function finalizeSlidingRangeEntry(fi, fs, m) {
|
|
1094
|
+
const pending = fs.slidingRangePending;
|
|
1095
|
+
const head = pending[0];
|
|
1096
|
+
const buf = fs.slidingBuffer;
|
|
1097
|
+
let lo, hi;
|
|
1098
|
+
if (head.isFinite) {
|
|
1099
|
+
({ lo, hi } = findRangeWindow(buf, head.v_j, m.preceding, m.following));
|
|
1100
|
+
}
|
|
1101
|
+
else {
|
|
1102
|
+
({ lo, hi } = findNonFinitePeerSpan(buf));
|
|
1103
|
+
}
|
|
1104
|
+
let value;
|
|
1105
|
+
if (lo < 0 || hi < 0 || lo > hi) {
|
|
1106
|
+
// Empty frame: SUM/MIN/MAX/FIRST/LAST return NULL, COUNT returns 0.
|
|
1107
|
+
value = m.name === 'count' ? 0 : null;
|
|
1108
|
+
}
|
|
1109
|
+
else {
|
|
1110
|
+
switch (m.name) {
|
|
1111
|
+
case 'sum': {
|
|
1112
|
+
const r = slidingScanSum(buf, lo, hi);
|
|
1113
|
+
value = r.count === 0 ? null : r.sum;
|
|
1114
|
+
break;
|
|
1115
|
+
}
|
|
1116
|
+
case 'count':
|
|
1117
|
+
value = slidingScanCountNonNull(buf, lo, hi);
|
|
1118
|
+
break;
|
|
1119
|
+
case 'avg': {
|
|
1120
|
+
const r = slidingScanSum(buf, lo, hi);
|
|
1121
|
+
value = r.count === 0 ? null : r.sum / r.count;
|
|
1122
|
+
break;
|
|
1123
|
+
}
|
|
1124
|
+
case 'min':
|
|
1125
|
+
value = slidingScanMin(buf, lo, hi);
|
|
1126
|
+
break;
|
|
1127
|
+
case 'max':
|
|
1128
|
+
value = slidingScanMax(buf, lo, hi);
|
|
1129
|
+
break;
|
|
1130
|
+
case 'first_value':
|
|
1131
|
+
value = buf[lo].argVal;
|
|
1132
|
+
break;
|
|
1133
|
+
case 'last_value':
|
|
1134
|
+
value = buf[hi].argVal;
|
|
1135
|
+
break;
|
|
1136
|
+
default:
|
|
1137
|
+
value = null;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
fillSlot(head.entry, fi, value);
|
|
1141
|
+
pending.shift();
|
|
1142
|
+
// Trim buffer rows that no remaining pending entry needs.
|
|
1143
|
+
trimSlidingRangeBuffer(fs, m);
|
|
1144
|
+
}
|
|
1145
|
+
function trimSlidingRangeBuffer(fs, m) {
|
|
1146
|
+
const pending = fs.slidingRangePending;
|
|
1147
|
+
const buf = fs.slidingBuffer;
|
|
1148
|
+
if (pending.length === 0) {
|
|
1149
|
+
buf.length = 0;
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
// Find the smallest left edge across remaining pending entries. For
|
|
1153
|
+
// finite pending entries, left = v_p - preceding. Pending is in arrival
|
|
1154
|
+
// (v-sorted) order, so the front entry has the smallest left.
|
|
1155
|
+
let minFiniteLeft = null;
|
|
1156
|
+
let anyNonFinitePending = false;
|
|
1157
|
+
for (const p of pending) {
|
|
1158
|
+
if (p.isFinite) {
|
|
1159
|
+
const left = p.v_j - m.preceding;
|
|
1160
|
+
if (minFiniteLeft === null || left < minFiniteLeft)
|
|
1161
|
+
minFiniteLeft = left;
|
|
1162
|
+
}
|
|
1163
|
+
else {
|
|
1164
|
+
anyNonFinitePending = true;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
// Trim front rows that are outside any pending entry's frame.
|
|
1168
|
+
while (buf.length > 0) {
|
|
1169
|
+
const v0 = buf[0].orderByVal0;
|
|
1170
|
+
if (!Number.isFinite(v0)) {
|
|
1171
|
+
// Drop leading non-finite rows only if no non-finite pending entry
|
|
1172
|
+
// would still need them.
|
|
1173
|
+
if (anyNonFinitePending)
|
|
1174
|
+
break;
|
|
1175
|
+
buf.shift();
|
|
1176
|
+
continue;
|
|
1177
|
+
}
|
|
1178
|
+
// Finite row: drop if smaller than every pending finite entry's left.
|
|
1179
|
+
if (minFiniteLeft === null) {
|
|
1180
|
+
// Only non-finite pending entries remain; finite rows aren't in
|
|
1181
|
+
// any of their frames.
|
|
1182
|
+
buf.shift();
|
|
1183
|
+
continue;
|
|
1184
|
+
}
|
|
1185
|
+
if (v0 < minFiniteLeft) {
|
|
1186
|
+
buf.shift();
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
break;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
function finalizeSlidingTrailing(fi, fs) {
|
|
1193
|
+
const m = fs.mode;
|
|
1194
|
+
if (m.frameMode === 'rows') {
|
|
1195
|
+
while (fs.slidingPending.length > 0) {
|
|
1196
|
+
finalizeSlidingRowsEntry(fi, fs, m);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
else {
|
|
1200
|
+
while (fs.slidingRangePending.length > 0) {
|
|
1201
|
+
finalizeSlidingRangeEntry(fi, fs, m);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
509
1204
|
}
|
|
510
1205
|
//# sourceMappingURL=window.js.map
|