@quereus/quereus 0.7.2 → 0.7.4
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/package.json +3 -3
- package/dist/src/common/constants.js.map +0 -1
- package/dist/src/common/datatype.js.map +0 -1
- package/dist/src/common/errors.js.map +0 -1
- package/dist/src/common/json-types.js.map +0 -1
- package/dist/src/common/logger.js.map +0 -1
- package/dist/src/common/type-inference.js.map +0 -1
- package/dist/src/common/types.js.map +0 -1
- package/dist/src/core/database-options.js.map +0 -1
- package/dist/src/core/database.js.map +0 -1
- package/dist/src/core/param.js.map +0 -1
- package/dist/src/core/statement.js.map +0 -1
- package/dist/src/func/builtins/aggregate.js.map +0 -1
- package/dist/src/func/builtins/builtin-window-functions.js.map +0 -1
- package/dist/src/func/builtins/conversion.js.map +0 -1
- package/dist/src/func/builtins/datetime.js.map +0 -1
- package/dist/src/func/builtins/explain.js.map +0 -1
- package/dist/src/func/builtins/generation.js.map +0 -1
- package/dist/src/func/builtins/index.js.map +0 -1
- package/dist/src/func/builtins/json-helpers.js.map +0 -1
- package/dist/src/func/builtins/json-tvf.js.map +0 -1
- package/dist/src/func/builtins/json.js.map +0 -1
- package/dist/src/func/builtins/scalar.js.map +0 -1
- package/dist/src/func/builtins/schema.js.map +0 -1
- package/dist/src/func/builtins/string.js.map +0 -1
- package/dist/src/func/builtins/timespan.js.map +0 -1
- package/dist/src/func/context.js.map +0 -1
- package/dist/src/func/registration.js.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/parser/ast.js.map +0 -1
- package/dist/src/parser/index.js.map +0 -1
- package/dist/src/parser/lexer.js.map +0 -1
- package/dist/src/parser/parser.js.map +0 -1
- package/dist/src/parser/utils.js.map +0 -1
- package/dist/src/parser/visitor.js.map +0 -1
- package/dist/src/planner/analysis/binding-collector.js.map +0 -1
- package/dist/src/planner/analysis/const-evaluator.js.map +0 -1
- package/dist/src/planner/analysis/const-pass.js.map +0 -1
- package/dist/src/planner/analysis/constraint-extractor.js.map +0 -1
- package/dist/src/planner/analysis/predicate-normalizer.js.map +0 -1
- package/dist/src/planner/building/alter-table.js.map +0 -1
- package/dist/src/planner/building/block.js.map +0 -1
- package/dist/src/planner/building/constraint-builder.js.map +0 -1
- package/dist/src/planner/building/create-assertion.js.map +0 -1
- package/dist/src/planner/building/create-view.js.map +0 -1
- package/dist/src/planner/building/ddl.js.map +0 -1
- package/dist/src/planner/building/declare-schema.js.map +0 -1
- package/dist/src/planner/building/delete.js.map +0 -1
- package/dist/src/planner/building/drop-assertion.js.map +0 -1
- package/dist/src/planner/building/drop-table.js.map +0 -1
- package/dist/src/planner/building/drop-view.js.map +0 -1
- package/dist/src/planner/building/expression.js.map +0 -1
- package/dist/src/planner/building/function-call.js.map +0 -1
- package/dist/src/planner/building/insert.js.map +0 -1
- package/dist/src/planner/building/pragma.js.map +0 -1
- package/dist/src/planner/building/schema-resolution.js.map +0 -1
- package/dist/src/planner/building/select-aggregates.js.map +0 -1
- package/dist/src/planner/building/select-compound.js.map +0 -1
- package/dist/src/planner/building/select-context.js.map +0 -1
- package/dist/src/planner/building/select-modifiers.js.map +0 -1
- package/dist/src/planner/building/select-projections.js.map +0 -1
- package/dist/src/planner/building/select-window.js.map +0 -1
- package/dist/src/planner/building/select.js.map +0 -1
- package/dist/src/planner/building/table-function.js.map +0 -1
- package/dist/src/planner/building/table.js.map +0 -1
- package/dist/src/planner/building/transaction.js.map +0 -1
- package/dist/src/planner/building/update.js.map +0 -1
- package/dist/src/planner/building/with.js.map +0 -1
- package/dist/src/planner/cache/correlation-detector.js.map +0 -1
- package/dist/src/planner/cache/materialization-advisory.js.map +0 -1
- package/dist/src/planner/cache/reference-graph.js.map +0 -1
- package/dist/src/planner/cost/index.js.map +0 -1
- package/dist/src/planner/debug/logger-utils.js.map +0 -1
- package/dist/src/planner/debug.js.map +0 -1
- package/dist/src/planner/framework/characteristics.js.map +0 -1
- package/dist/src/planner/framework/context.js.map +0 -1
- package/dist/src/planner/framework/pass.js.map +0 -1
- package/dist/src/planner/framework/physical-utils.js.map +0 -1
- package/dist/src/planner/framework/registry.js.map +0 -1
- package/dist/src/planner/framework/trace.js.map +0 -1
- package/dist/src/planner/nodes/add-constraint-node.js.map +0 -1
- package/dist/src/planner/nodes/aggregate-function.js.map +0 -1
- package/dist/src/planner/nodes/aggregate-node.js.map +0 -1
- package/dist/src/planner/nodes/array-index-node.js.map +0 -1
- package/dist/src/planner/nodes/block.js.map +0 -1
- package/dist/src/planner/nodes/cache-node.js.map +0 -1
- package/dist/src/planner/nodes/constraint-check-node.js.map +0 -1
- package/dist/src/planner/nodes/create-assertion-node.js.map +0 -1
- package/dist/src/planner/nodes/create-index-node.js.map +0 -1
- package/dist/src/planner/nodes/create-table-node.js.map +0 -1
- package/dist/src/planner/nodes/create-view-node.js.map +0 -1
- package/dist/src/planner/nodes/cte-node.js.map +0 -1
- package/dist/src/planner/nodes/cte-reference-node.js.map +0 -1
- package/dist/src/planner/nodes/declarative-schema.js.map +0 -1
- package/dist/src/planner/nodes/delete-node.js.map +0 -1
- package/dist/src/planner/nodes/distinct-node.js.map +0 -1
- package/dist/src/planner/nodes/dml-executor-node.js.map +0 -1
- package/dist/src/planner/nodes/drop-assertion-node.js.map +0 -1
- package/dist/src/planner/nodes/drop-table-node.js.map +0 -1
- package/dist/src/planner/nodes/drop-view-node.js.map +0 -1
- package/dist/src/planner/nodes/filter.js.map +0 -1
- package/dist/src/planner/nodes/function.js.map +0 -1
- package/dist/src/planner/nodes/insert-node.js.map +0 -1
- package/dist/src/planner/nodes/internal-recursive-cte-ref-node.js.map +0 -1
- package/dist/src/planner/nodes/join-node.js.map +0 -1
- package/dist/src/planner/nodes/limit-offset.js.map +0 -1
- package/dist/src/planner/nodes/plan-node-type.js.map +0 -1
- package/dist/src/planner/nodes/plan-node.js.map +0 -1
- package/dist/src/planner/nodes/pragma.js.map +0 -1
- package/dist/src/planner/nodes/project-node.js.map +0 -1
- package/dist/src/planner/nodes/recursive-cte-node.js.map +0 -1
- package/dist/src/planner/nodes/reference.js.map +0 -1
- package/dist/src/planner/nodes/remote-query-node.js.map +0 -1
- package/dist/src/planner/nodes/retrieve-node.js.map +0 -1
- package/dist/src/planner/nodes/returning-node.js.map +0 -1
- package/dist/src/planner/nodes/scalar.js.map +0 -1
- package/dist/src/planner/nodes/sequencing-node.js.map +0 -1
- package/dist/src/planner/nodes/set-operation-node.js.map +0 -1
- package/dist/src/planner/nodes/single-row.js.map +0 -1
- package/dist/src/planner/nodes/sink-node.js.map +0 -1
- package/dist/src/planner/nodes/sort.js.map +0 -1
- package/dist/src/planner/nodes/stream-aggregate.js.map +0 -1
- package/dist/src/planner/nodes/subquery.js.map +0 -1
- package/dist/src/planner/nodes/table-access-nodes.js.map +0 -1
- package/dist/src/planner/nodes/table-function-call.js.map +0 -1
- package/dist/src/planner/nodes/transaction-node.js.map +0 -1
- package/dist/src/planner/nodes/update-node.js.map +0 -1
- package/dist/src/planner/nodes/values-node.js.map +0 -1
- package/dist/src/planner/nodes/view-reference-node.js.map +0 -1
- package/dist/src/planner/nodes/window-function.js.map +0 -1
- package/dist/src/planner/nodes/window-node.js.map +0 -1
- package/dist/src/planner/optimizer-tuning.js.map +0 -1
- package/dist/src/planner/optimizer.js.map +0 -1
- package/dist/src/planner/planning-context.js.map +0 -1
- package/dist/src/planner/resolve.js.map +0 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +0 -1
- package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +0 -1
- package/dist/src/planner/rules/cache/rule-cte-optimization.js.map +0 -1
- package/dist/src/planner/rules/cache/rule-materialization-advisory.js.map +0 -1
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js.map +0 -1
- package/dist/src/planner/rules/join/rule-join-greedy-commute.js.map +0 -1
- package/dist/src/planner/rules/join/rule-join-key-inference.js.map +0 -1
- package/dist/src/planner/rules/join/rule-quickpick-enumeration.js.map +0 -1
- package/dist/src/planner/rules/predicate/rule-predicate-pushdown.js.map +0 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +0 -1
- package/dist/src/planner/scopes/aliased.js.map +0 -1
- package/dist/src/planner/scopes/base.js.map +0 -1
- package/dist/src/planner/scopes/empty.js.map +0 -1
- package/dist/src/planner/scopes/global.js.map +0 -1
- package/dist/src/planner/scopes/multi.js.map +0 -1
- package/dist/src/planner/scopes/param.js.map +0 -1
- package/dist/src/planner/scopes/registered.js.map +0 -1
- package/dist/src/planner/scopes/scope.js.map +0 -1
- package/dist/src/planner/stats/basic-estimates.js.map +0 -1
- package/dist/src/planner/stats/index.js.map +0 -1
- package/dist/src/planner/type-utils.js.map +0 -1
- package/dist/src/planner/util/key-utils.js.map +0 -1
- package/dist/src/planner/validation/determinism-validator.js.map +0 -1
- package/dist/src/planner/validation/plan-validator.js.map +0 -1
- package/dist/src/runtime/async-util.js.map +0 -1
- package/dist/src/runtime/cache/shared-cache.js.map +0 -1
- package/dist/src/runtime/context-helpers.js.map +0 -1
- package/dist/src/runtime/deferred-constraint-queue.js.map +0 -1
- package/dist/src/runtime/emission-context.js.map +0 -1
- package/dist/src/runtime/emit/add-constraint.js.map +0 -1
- package/dist/src/runtime/emit/aggregate.js.map +0 -1
- package/dist/src/runtime/emit/array-index.js.map +0 -1
- package/dist/src/runtime/emit/between.js.map +0 -1
- package/dist/src/runtime/emit/binary.js.map +0 -1
- package/dist/src/runtime/emit/block.js.map +0 -1
- package/dist/src/runtime/emit/cache.js.map +0 -1
- package/dist/src/runtime/emit/case.js.map +0 -1
- package/dist/src/runtime/emit/cast.js.map +0 -1
- package/dist/src/runtime/emit/collate.js.map +0 -1
- package/dist/src/runtime/emit/column-reference.js.map +0 -1
- package/dist/src/runtime/emit/constraint-check.js.map +0 -1
- package/dist/src/runtime/emit/create-assertion.js.map +0 -1
- package/dist/src/runtime/emit/create-index.js.map +0 -1
- package/dist/src/runtime/emit/create-table.js.map +0 -1
- package/dist/src/runtime/emit/create-view.js.map +0 -1
- package/dist/src/runtime/emit/cte-reference.js.map +0 -1
- package/dist/src/runtime/emit/cte.js.map +0 -1
- package/dist/src/runtime/emit/delete.js.map +0 -1
- package/dist/src/runtime/emit/distinct.js.map +0 -1
- package/dist/src/runtime/emit/dml-executor.js.map +0 -1
- package/dist/src/runtime/emit/drop-assertion.js.map +0 -1
- package/dist/src/runtime/emit/drop-table.js.map +0 -1
- package/dist/src/runtime/emit/drop-view.js.map +0 -1
- package/dist/src/runtime/emit/filter.js.map +0 -1
- package/dist/src/runtime/emit/insert.js.map +0 -1
- package/dist/src/runtime/emit/internal-recursive-cte-ref.js.map +0 -1
- package/dist/src/runtime/emit/join.js.map +0 -1
- package/dist/src/runtime/emit/limit-offset.js.map +0 -1
- package/dist/src/runtime/emit/literal.js.map +0 -1
- package/dist/src/runtime/emit/parameter.js.map +0 -1
- package/dist/src/runtime/emit/pragma.js.map +0 -1
- package/dist/src/runtime/emit/project.js.map +0 -1
- package/dist/src/runtime/emit/recursive-cte.js.map +0 -1
- package/dist/src/runtime/emit/remote-query.js.map +0 -1
- package/dist/src/runtime/emit/retrieve.js.map +0 -1
- package/dist/src/runtime/emit/returning.js.map +0 -1
- package/dist/src/runtime/emit/scalar-function.js.map +0 -1
- package/dist/src/runtime/emit/scan.js.map +0 -1
- package/dist/src/runtime/emit/schema-declarative.js.map +0 -1
- package/dist/src/runtime/emit/sequencing.js.map +0 -1
- package/dist/src/runtime/emit/set-operation.js.map +0 -1
- package/dist/src/runtime/emit/sink.js.map +0 -1
- package/dist/src/runtime/emit/sort.js.map +0 -1
- package/dist/src/runtime/emit/subquery.js.map +0 -1
- package/dist/src/runtime/emit/table-valued-function.js.map +0 -1
- package/dist/src/runtime/emit/temporal-arithmetic.js.map +0 -1
- package/dist/src/runtime/emit/transaction.js.map +0 -1
- package/dist/src/runtime/emit/unary.js.map +0 -1
- package/dist/src/runtime/emit/update.js.map +0 -1
- package/dist/src/runtime/emit/values.js.map +0 -1
- package/dist/src/runtime/emit/window-function.js.map +0 -1
- package/dist/src/runtime/emit/window.js.map +0 -1
- package/dist/src/runtime/emitters.js.map +0 -1
- package/dist/src/runtime/register.js.map +0 -1
- package/dist/src/runtime/scheduler.js.map +0 -1
- package/dist/src/runtime/types.js.map +0 -1
- package/dist/src/runtime/utils.js.map +0 -1
- package/dist/src/schema/assertion.js.map +0 -1
- package/dist/src/schema/catalog.js.map +0 -1
- package/dist/src/schema/change-events.js.map +0 -1
- package/dist/src/schema/column.js.map +0 -1
- package/dist/src/schema/declared-schema-manager.js.map +0 -1
- package/dist/src/schema/function.js.map +0 -1
- package/dist/src/schema/manager.js.map +0 -1
- package/dist/src/schema/schema-differ.js.map +0 -1
- package/dist/src/schema/schema-hasher.js.map +0 -1
- package/dist/src/schema/schema.js.map +0 -1
- package/dist/src/schema/table.js.map +0 -1
- package/dist/src/schema/view.js.map +0 -1
- package/dist/src/schema/window-function.js.map +0 -1
- package/dist/src/types/builtin-types.js.map +0 -1
- package/dist/src/types/index.js.map +0 -1
- package/dist/src/types/json-type.js.map +0 -1
- package/dist/src/types/logical-type.js.map +0 -1
- package/dist/src/types/plugin-interface.js.map +0 -1
- package/dist/src/types/registry.js.map +0 -1
- package/dist/src/types/temporal-types.js.map +0 -1
- package/dist/src/types/validation.js.map +0 -1
- package/dist/src/util/affinity.js.map +0 -1
- package/dist/src/util/ast-stringify.js.map +0 -1
- package/dist/src/util/cached.js.map +0 -1
- package/dist/src/util/coercion.js.map +0 -1
- package/dist/src/util/comparison.js.map +0 -1
- package/dist/src/util/environment.js.map +0 -1
- package/dist/src/util/hash.js.map +0 -1
- package/dist/src/util/latches.js.map +0 -1
- package/dist/src/util/mutation-statement.js.map +0 -1
- package/dist/src/util/patterns.js.map +0 -1
- package/dist/src/util/plan-formatter.js.map +0 -1
- package/dist/src/util/plugin-helper.js.map +0 -1
- package/dist/src/util/row-descriptor.js.map +0 -1
- package/dist/src/util/serialization.js.map +0 -1
- package/dist/src/util/sql-literal.js.map +0 -1
- package/dist/src/util/working-table-iterable.js.map +0 -1
- package/dist/src/vtab/best-access-plan.js.map +0 -1
- package/dist/src/vtab/connection.js.map +0 -1
- package/dist/src/vtab/filter-info.js.map +0 -1
- package/dist/src/vtab/index-info.js.map +0 -1
- package/dist/src/vtab/manifest.js.map +0 -1
- package/dist/src/vtab/memory/connection.js.map +0 -1
- package/dist/src/vtab/memory/index.js.map +0 -1
- package/dist/src/vtab/memory/layer/base-cursor.js.map +0 -1
- package/dist/src/vtab/memory/layer/base.js.map +0 -1
- package/dist/src/vtab/memory/layer/connection.js.map +0 -1
- package/dist/src/vtab/memory/layer/interface.js.map +0 -1
- package/dist/src/vtab/memory/layer/manager.js.map +0 -1
- package/dist/src/vtab/memory/layer/safe-iterate.js.map +0 -1
- package/dist/src/vtab/memory/layer/scan-plan.js.map +0 -1
- package/dist/src/vtab/memory/layer/transaction-cursor.js.map +0 -1
- package/dist/src/vtab/memory/layer/transaction.js.map +0 -1
- package/dist/src/vtab/memory/module.js.map +0 -1
- package/dist/src/vtab/memory/table.js.map +0 -1
- package/dist/src/vtab/memory/types.js.map +0 -1
- package/dist/src/vtab/memory/utils/logging.js.map +0 -1
- package/dist/src/vtab/memory/utils/primary-key.js.map +0 -1
- package/dist/src/vtab/module.js.map +0 -1
- package/dist/src/vtab/table.js.map +0 -1
- package/src/common/constants.ts +0 -60
- package/src/common/datatype.ts +0 -85
- package/src/common/errors.ts +0 -189
- package/src/common/json-types.ts +0 -16
- package/src/common/logger.ts +0 -97
- package/src/common/type-inference.ts +0 -39
- package/src/common/types.ts +0 -151
- package/src/core/database-options.ts +0 -258
- package/src/core/database.ts +0 -1461
- package/src/core/param.ts +0 -56
- package/src/core/statement.ts +0 -528
- package/src/func/builtins/aggregate.ts +0 -269
- package/src/func/builtins/builtin-window-functions.ts +0 -166
- package/src/func/builtins/conversion.ts +0 -226
- package/src/func/builtins/datetime.ts +0 -500
- package/src/func/builtins/explain.ts +0 -779
- package/src/func/builtins/generation.ts +0 -43
- package/src/func/builtins/index.ts +0 -167
- package/src/func/builtins/json-helpers.ts +0 -237
- package/src/func/builtins/json-tvf.ts +0 -224
- package/src/func/builtins/json.ts +0 -588
- package/src/func/builtins/scalar.ts +0 -423
- package/src/func/builtins/schema.ts +0 -213
- package/src/func/builtins/string.ts +0 -306
- package/src/func/builtins/timespan.ts +0 -179
- package/src/func/context.ts +0 -258
- package/src/func/registration.ts +0 -201
- package/src/index.ts +0 -172
- package/src/parser/ast.ts +0 -581
- package/src/parser/index.ts +0 -65
- package/src/parser/lexer.ts +0 -806
- package/src/parser/parser.ts +0 -3352
- package/src/parser/utils.ts +0 -10
- package/src/parser/visitor.ts +0 -188
- package/src/planner/analysis/README.md +0 -93
- package/src/planner/analysis/binding-collector.ts +0 -83
- package/src/planner/analysis/const-evaluator.ts +0 -63
- package/src/planner/analysis/const-pass.ts +0 -282
- package/src/planner/analysis/constraint-extractor.ts +0 -764
- package/src/planner/analysis/predicate-normalizer.ts +0 -237
- package/src/planner/building/alter-table.ts +0 -49
- package/src/planner/building/block.ts +0 -93
- package/src/planner/building/constraint-builder.ts +0 -178
- package/src/planner/building/create-assertion.ts +0 -7
- package/src/planner/building/create-view.ts +0 -29
- package/src/planner/building/ddl.ts +0 -24
- package/src/planner/building/declare-schema.ts +0 -22
- package/src/planner/building/delete.ts +0 -218
- package/src/planner/building/drop-assertion.ts +0 -11
- package/src/planner/building/drop-table.ts +0 -13
- package/src/planner/building/drop-view.ts +0 -19
- package/src/planner/building/expression.ts +0 -205
- package/src/planner/building/function-call.ts +0 -129
- package/src/planner/building/insert.ts +0 -435
- package/src/planner/building/pragma.ts +0 -34
- package/src/planner/building/schema-resolution.ts +0 -176
- package/src/planner/building/select-aggregates.ts +0 -318
- package/src/planner/building/select-compound.ts +0 -119
- package/src/planner/building/select-context.ts +0 -85
- package/src/planner/building/select-modifiers.ts +0 -236
- package/src/planner/building/select-projections.ts +0 -177
- package/src/planner/building/select-window.ts +0 -259
- package/src/planner/building/select.ts +0 -567
- package/src/planner/building/table-function.ts +0 -49
- package/src/planner/building/table.ts +0 -40
- package/src/planner/building/transaction.ts +0 -23
- package/src/planner/building/update.ts +0 -331
- package/src/planner/building/with.ts +0 -180
- package/src/planner/cache/correlation-detector.ts +0 -83
- package/src/planner/cache/materialization-advisory.ts +0 -265
- package/src/planner/cache/reference-graph.ts +0 -196
- package/src/planner/cost/index.ts +0 -169
- package/src/planner/debug/logger-utils.ts +0 -68
- package/src/planner/debug.ts +0 -480
- package/src/planner/framework/README.md +0 -132
- package/src/planner/framework/characteristics.ts +0 -503
- package/src/planner/framework/context.ts +0 -239
- package/src/planner/framework/pass.ts +0 -354
- package/src/planner/framework/physical-utils.ts +0 -210
- package/src/planner/framework/registry.ts +0 -261
- package/src/planner/framework/trace.ts +0 -259
- package/src/planner/nodes/add-constraint-node.ts +0 -62
- package/src/planner/nodes/aggregate-function.ts +0 -155
- package/src/planner/nodes/aggregate-node.ts +0 -267
- package/src/planner/nodes/array-index-node.ts +0 -50
- package/src/planner/nodes/block.ts +0 -80
- package/src/planner/nodes/cache-node.ts +0 -103
- package/src/planner/nodes/constraint-check-node.ts +0 -138
- package/src/planner/nodes/create-assertion-node.ts +0 -51
- package/src/planner/nodes/create-index-node.ts +0 -41
- package/src/planner/nodes/create-table-node.ts +0 -35
- package/src/planner/nodes/create-view-node.ts +0 -44
- package/src/planner/nodes/cte-node.ts +0 -168
- package/src/planner/nodes/cte-reference-node.ts +0 -125
- package/src/planner/nodes/declarative-schema.ts +0 -221
- package/src/planner/nodes/delete-node.ts +0 -102
- package/src/planner/nodes/distinct-node.ts +0 -107
- package/src/planner/nodes/dml-executor-node.ts +0 -104
- package/src/planner/nodes/drop-assertion-node.ts +0 -50
- package/src/planner/nodes/drop-table-node.ts +0 -36
- package/src/planner/nodes/drop-view-node.ts +0 -37
- package/src/planner/nodes/filter.ts +0 -144
- package/src/planner/nodes/function.ts +0 -98
- package/src/planner/nodes/insert-node.ts +0 -126
- package/src/planner/nodes/internal-recursive-cte-ref-node.ts +0 -61
- package/src/planner/nodes/join-node.ts +0 -336
- package/src/planner/nodes/limit-offset.ts +0 -144
- package/src/planner/nodes/plan-node-type.ts +0 -95
- package/src/planner/nodes/plan-node.ts +0 -503
- package/src/planner/nodes/pragma.ts +0 -98
- package/src/planner/nodes/project-node.ts +0 -337
- package/src/planner/nodes/recursive-cte-node.ts +0 -158
- package/src/planner/nodes/reference.ts +0 -334
- package/src/planner/nodes/remote-query-node.ts +0 -73
- package/src/planner/nodes/retrieve-node.ts +0 -86
- package/src/planner/nodes/returning-node.ts +0 -269
- package/src/planner/nodes/scalar.ts +0 -772
- package/src/planner/nodes/sequencing-node.ts +0 -113
- package/src/planner/nodes/set-operation-node.ts +0 -87
- package/src/planner/nodes/single-row.ts +0 -85
- package/src/planner/nodes/sink-node.ts +0 -61
- package/src/planner/nodes/sort.ts +0 -166
- package/src/planner/nodes/stream-aggregate.ts +0 -293
- package/src/planner/nodes/subquery.ts +0 -268
- package/src/planner/nodes/table-access-nodes.ts +0 -323
- package/src/planner/nodes/table-function-call.ts +0 -134
- package/src/planner/nodes/transaction-node.ts +0 -55
- package/src/planner/nodes/update-node.ts +0 -138
- package/src/planner/nodes/values-node.ts +0 -244
- package/src/planner/nodes/view-reference-node.ts +0 -97
- package/src/planner/nodes/window-function.ts +0 -73
- package/src/planner/nodes/window-node.ts +0 -199
- package/src/planner/optimizer-tuning.ts +0 -105
- package/src/planner/optimizer.ts +0 -332
- package/src/planner/planning-context.ts +0 -190
- package/src/planner/resolve.ts +0 -101
- package/src/planner/rules/README.md +0 -96
- package/src/planner/rules/access/rule-select-access-path.ts +0 -399
- package/src/planner/rules/aggregate/rule-aggregate-streaming.ts +0 -162
- package/src/planner/rules/cache/rule-cte-optimization.ts +0 -79
- package/src/planner/rules/cache/rule-materialization-advisory.ts +0 -77
- package/src/planner/rules/cache/rule-mutating-subquery-cache.ts +0 -104
- package/src/planner/rules/join/rule-join-greedy-commute.ts +0 -48
- package/src/planner/rules/join/rule-join-key-inference.ts +0 -35
- package/src/planner/rules/join/rule-quickpick-enumeration.ts +0 -267
- package/src/planner/rules/predicate/rule-predicate-pushdown.ts +0 -144
- package/src/planner/rules/retrieve/rule-grow-retrieve.ts +0 -337
- package/src/planner/scopes/aliased.ts +0 -50
- package/src/planner/scopes/base.ts +0 -10
- package/src/planner/scopes/empty.ts +0 -12
- package/src/planner/scopes/global.ts +0 -73
- package/src/planner/scopes/multi.ts +0 -40
- package/src/planner/scopes/param.ts +0 -95
- package/src/planner/scopes/registered.ts +0 -67
- package/src/planner/scopes/scope.ts +0 -16
- package/src/planner/stats/basic-estimates.ts +0 -107
- package/src/planner/stats/index.ts +0 -158
- package/src/planner/type-utils.ts +0 -87
- package/src/planner/util/key-utils.ts +0 -46
- package/src/planner/validation/determinism-validator.ts +0 -104
- package/src/planner/validation/plan-validator.ts +0 -335
- package/src/runtime/async-util.ts +0 -283
- package/src/runtime/cache/shared-cache.ts +0 -169
- package/src/runtime/context-helpers.ts +0 -191
- package/src/runtime/deferred-constraint-queue.ts +0 -196
- package/src/runtime/emission-context.ts +0 -319
- package/src/runtime/emit/add-constraint.ts +0 -78
- package/src/runtime/emit/aggregate.ts +0 -581
- package/src/runtime/emit/array-index.ts +0 -25
- package/src/runtime/emit/between.ts +0 -51
- package/src/runtime/emit/binary.ts +0 -357
- package/src/runtime/emit/block.ts +0 -23
- package/src/runtime/emit/cache.ts +0 -64
- package/src/runtime/emit/case.ts +0 -87
- package/src/runtime/emit/cast.ts +0 -151
- package/src/runtime/emit/collate.ts +0 -9
- package/src/runtime/emit/column-reference.ts +0 -17
- package/src/runtime/emit/constraint-check.ts +0 -290
- package/src/runtime/emit/create-assertion.ts +0 -82
- package/src/runtime/emit/create-index.ts +0 -15
- package/src/runtime/emit/create-table.ts +0 -15
- package/src/runtime/emit/create-view.ts +0 -52
- package/src/runtime/emit/cte-reference.ts +0 -38
- package/src/runtime/emit/cte.ts +0 -39
- package/src/runtime/emit/delete.ts +0 -24
- package/src/runtime/emit/distinct.ts +0 -40
- package/src/runtime/emit/dml-executor.ts +0 -198
- package/src/runtime/emit/drop-assertion.ts +0 -45
- package/src/runtime/emit/drop-table.ts +0 -27
- package/src/runtime/emit/drop-view.ts +0 -49
- package/src/runtime/emit/filter.ts +0 -30
- package/src/runtime/emit/insert.ts +0 -42
- package/src/runtime/emit/internal-recursive-cte-ref.ts +0 -37
- package/src/runtime/emit/join.ts +0 -148
- package/src/runtime/emit/limit-offset.ts +0 -73
- package/src/runtime/emit/literal.ts +0 -17
- package/src/runtime/emit/parameter.ts +0 -59
- package/src/runtime/emit/pragma.ts +0 -56
- package/src/runtime/emit/project.ts +0 -46
- package/src/runtime/emit/recursive-cte.ts +0 -111
- package/src/runtime/emit/remote-query.ts +0 -47
- package/src/runtime/emit/retrieve.ts +0 -15
- package/src/runtime/emit/returning.ts +0 -41
- package/src/runtime/emit/scalar-function.ts +0 -69
- package/src/runtime/emit/scan.ts +0 -106
- package/src/runtime/emit/schema-declarative.ts +0 -215
- package/src/runtime/emit/sequencing.ts +0 -24
- package/src/runtime/emit/set-operation.ts +0 -141
- package/src/runtime/emit/sink.ts +0 -27
- package/src/runtime/emit/sort.ts +0 -75
- package/src/runtime/emit/subquery.ts +0 -203
- package/src/runtime/emit/table-valued-function.ts +0 -106
- package/src/runtime/emit/temporal-arithmetic.ts +0 -302
- package/src/runtime/emit/transaction.ts +0 -205
- package/src/runtime/emit/unary.ts +0 -101
- package/src/runtime/emit/update.ts +0 -66
- package/src/runtime/emit/values.ts +0 -66
- package/src/runtime/emit/window-function.ts +0 -42
- package/src/runtime/emit/window.ts +0 -458
- package/src/runtime/emitters.ts +0 -183
- package/src/runtime/register.ts +0 -150
- package/src/runtime/scheduler.ts +0 -488
- package/src/runtime/types.ts +0 -242
- package/src/runtime/utils.ts +0 -177
- package/src/schema/assertion.ts +0 -21
- package/src/schema/catalog.ts +0 -269
- package/src/schema/change-events.ts +0 -80
- package/src/schema/column.ts +0 -51
- package/src/schema/declared-schema-manager.ts +0 -82
- package/src/schema/function.ts +0 -188
- package/src/schema/manager.ts +0 -1034
- package/src/schema/schema-differ.ts +0 -214
- package/src/schema/schema-hasher.ts +0 -26
- package/src/schema/schema.ts +0 -222
- package/src/schema/table.ts +0 -409
- package/src/schema/view.ts +0 -19
- package/src/schema/window-function.ts +0 -56
- package/src/types/builtin-types.ts +0 -350
- package/src/types/index.ts +0 -17
- package/src/types/json-type.ts +0 -152
- package/src/types/logical-type.ts +0 -91
- package/src/types/plugin-interface.ts +0 -10
- package/src/types/registry.ts +0 -204
- package/src/types/temporal-types.ts +0 -290
- package/src/types/validation.ts +0 -120
- package/src/util/affinity.ts +0 -151
- package/src/util/ast-stringify.ts +0 -887
- package/src/util/cached.ts +0 -25
- package/src/util/coercion.ts +0 -113
- package/src/util/comparison.ts +0 -510
- package/src/util/environment.ts +0 -52
- package/src/util/hash.ts +0 -90
- package/src/util/latches.ts +0 -47
- package/src/util/mutation-statement.ts +0 -135
- package/src/util/patterns.ts +0 -56
- package/src/util/plan-formatter.ts +0 -48
- package/src/util/plugin-helper.ts +0 -110
- package/src/util/row-descriptor.ts +0 -105
- package/src/util/serialization.ts +0 -47
- package/src/util/sql-literal.ts +0 -22
- package/src/util/working-table-iterable.ts +0 -38
- package/src/vtab/best-access-plan.ts +0 -244
- package/src/vtab/connection.ts +0 -36
- package/src/vtab/filter-info.ts +0 -23
- package/src/vtab/index-info.ts +0 -84
- package/src/vtab/manifest.ts +0 -86
- package/src/vtab/memory/connection.ts +0 -73
- package/src/vtab/memory/index.ts +0 -191
- package/src/vtab/memory/layer/base-cursor.ts +0 -124
- package/src/vtab/memory/layer/base.ts +0 -275
- package/src/vtab/memory/layer/connection.ts +0 -203
- package/src/vtab/memory/layer/interface.ts +0 -47
- package/src/vtab/memory/layer/manager.ts +0 -909
- package/src/vtab/memory/layer/safe-iterate.ts +0 -49
- package/src/vtab/memory/layer/scan-plan.ts +0 -84
- package/src/vtab/memory/layer/transaction-cursor.ts +0 -162
- package/src/vtab/memory/layer/transaction.ts +0 -229
- package/src/vtab/memory/module.ts +0 -667
- package/src/vtab/memory/table.ts +0 -251
- package/src/vtab/memory/types.ts +0 -23
- package/src/vtab/memory/utils/logging.ts +0 -36
- package/src/vtab/memory/utils/primary-key.ts +0 -163
- package/src/vtab/module.ts +0 -162
- package/src/vtab/table.ts +0 -177
|
@@ -1,764 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constraint extraction utilities for predicate analysis and pushdown optimization
|
|
3
|
-
* Converts scalar expressions into constraints that can be pushed down to virtual tables
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { ScalarPlanNode, RelationalPlanNode, PlanNode } from '../nodes/plan-node.js';
|
|
7
|
-
import { PlanNodeType } from '../nodes/plan-node-type.js';
|
|
8
|
-
import type { ColumnReferenceNode } from '../nodes/reference.js';
|
|
9
|
-
import { BinaryOpNode, BetweenNode } from '../nodes/scalar.js';
|
|
10
|
-
import type { LiteralNode } from '../nodes/scalar.js';
|
|
11
|
-
import { InNode } from '../nodes/subquery.js';
|
|
12
|
-
import type { Row, SqlValue } from '../../common/types.js';
|
|
13
|
-
import { createLogger } from '../../common/logger.js';
|
|
14
|
-
import type * as AST from '../../parser/ast.js';
|
|
15
|
-
import { getSyncLiteral } from '../../parser/utils.js';
|
|
16
|
-
import type { ConstraintOp, PredicateConstraint as VtabPredicateConstraint } from '../../vtab/best-access-plan.js';
|
|
17
|
-
import { TableReferenceNode, ColumnReferenceNode as _ColumnRef } from '../nodes/reference.js';
|
|
18
|
-
import { CapabilityDetectors } from '../framework/characteristics.js';
|
|
19
|
-
|
|
20
|
-
const log = createLogger('planner:analysis:constraint-extractor');
|
|
21
|
-
|
|
22
|
-
// ConstraintOp is imported from vtab/best-access-plan.ts
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* A constraint extracted from a predicate expression
|
|
26
|
-
* Extends the vtab PredicateConstraint with additional metadata for the planner
|
|
27
|
-
*/
|
|
28
|
-
export interface PredicateConstraint extends VtabPredicateConstraint {
|
|
29
|
-
/** Attribute ID of the column reference */
|
|
30
|
-
attributeId: number;
|
|
31
|
-
/** Original expression node for debugging */
|
|
32
|
-
sourceExpression: ScalarPlanNode;
|
|
33
|
-
/** Target table relation (for multi-table predicates) */
|
|
34
|
-
targetRelation?: string;
|
|
35
|
-
/** Dynamic value expression for parameterized/correlated constraints (or IN lists) */
|
|
36
|
-
valueExpr?: ScalarPlanNode | ScalarPlanNode[];
|
|
37
|
-
/** Binding kind describing how value is supplied */
|
|
38
|
-
bindingKind?: 'literal' | 'parameter' | 'correlated' | 'expression' | 'mixed';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Result of constraint extraction
|
|
43
|
-
*/
|
|
44
|
-
export interface ConstraintExtractionResult {
|
|
45
|
-
/** Extracted constraints grouped by target table relation */
|
|
46
|
-
constraintsByTable: Map<string, PredicateConstraint[]>;
|
|
47
|
-
/** Residual predicate that couldn't be converted to constraints */
|
|
48
|
-
residualPredicate?: ScalarPlanNode;
|
|
49
|
-
/** All constraints in a flat list */
|
|
50
|
-
allConstraints: PredicateConstraint[];
|
|
51
|
-
/** Predicate comprised only of supported fragments for a specific table (optional) */
|
|
52
|
-
supportedPredicateByTable?: Map<string, ScalarPlanNode>;
|
|
53
|
-
/** For each table, which unique key(s) are fully covered by equality constraints (by column indexes). Empty if none. */
|
|
54
|
-
coveredKeysByTable?: Map<string, number[][]>;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Table information for constraint mapping
|
|
59
|
-
*/
|
|
60
|
-
export interface TableInfo {
|
|
61
|
-
relationName: string; // human-readable (e.g., schema.table)
|
|
62
|
-
relationKey: string; // instance-unique (e.g., schema.table#<nodeId>)
|
|
63
|
-
attributes: Array<{ id: number; name: string }>;
|
|
64
|
-
columnIndexMap: Map<number, number>; // attributeId -> columnIndex
|
|
65
|
-
/** Logical unique keys for the relation, expressed as output column indexes */
|
|
66
|
-
uniqueKeys?: number[][];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Extract constraints from a scalar predicate expression
|
|
71
|
-
* Handles binary comparisons, boolean logic (AND/OR), and complex expressions
|
|
72
|
-
*/
|
|
73
|
-
export function extractConstraints(
|
|
74
|
-
predicate: ScalarPlanNode,
|
|
75
|
-
tableInfos: TableInfo[] = []
|
|
76
|
-
): ConstraintExtractionResult {
|
|
77
|
-
const constraintsByTable = new Map<string, PredicateConstraint[]>();
|
|
78
|
-
const allConstraints: PredicateConstraint[] = [];
|
|
79
|
-
const residualExpressions: ScalarPlanNode[] = [];
|
|
80
|
-
|
|
81
|
-
log('Extracting constraints from predicate: %s', predicate.toString());
|
|
82
|
-
|
|
83
|
-
// Build attribute-to-table mapping for quick lookups
|
|
84
|
-
const tableByAttribute = new Map<number, TableInfo>();
|
|
85
|
-
for (const tableInfo of tableInfos) {
|
|
86
|
-
for (const attr of tableInfo.attributes) {
|
|
87
|
-
tableByAttribute.set(attr.id, tableInfo);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Start extraction process & build supported fragments per table
|
|
92
|
-
const perTableParts = new Map<string, ScalarPlanNode[]>();
|
|
93
|
-
extractFromExpression(predicate, allConstraints, residualExpressions, tableByAttribute, perTableParts);
|
|
94
|
-
|
|
95
|
-
// Group constraints by table instance key
|
|
96
|
-
for (const constraint of allConstraints) {
|
|
97
|
-
if (constraint.targetRelation) {
|
|
98
|
-
if (!constraintsByTable.has(constraint.targetRelation)) {
|
|
99
|
-
constraintsByTable.set(constraint.targetRelation, []);
|
|
100
|
-
}
|
|
101
|
-
constraintsByTable.get(constraint.targetRelation)!.push(constraint);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Build residual predicate from unmatched expressions (combine with AND)
|
|
106
|
-
let residualPredicate: ScalarPlanNode | undefined;
|
|
107
|
-
if (residualExpressions.length === 1) {
|
|
108
|
-
residualPredicate = residualExpressions[0];
|
|
109
|
-
} else if (residualExpressions.length > 1) {
|
|
110
|
-
let acc = residualExpressions[0];
|
|
111
|
-
for (let i = 1; i < residualExpressions.length; i++) {
|
|
112
|
-
const right = residualExpressions[i];
|
|
113
|
-
const ast: AST.BinaryExpr = { type: 'binary', operator: 'AND', left: (acc as any).expression, right: (right as any).expression };
|
|
114
|
-
acc = new BinaryOpNode((acc as any).scope, ast, acc, right);
|
|
115
|
-
}
|
|
116
|
-
residualPredicate = acc;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
log('Extracted %d constraints across %d tables, %d residual expressions',
|
|
120
|
-
allConstraints.length, constraintsByTable.size, residualExpressions.length);
|
|
121
|
-
|
|
122
|
-
const supportedPredicateByTable = new Map<string, ScalarPlanNode>();
|
|
123
|
-
for (const [rel, parts] of perTableParts) {
|
|
124
|
-
const combined = combineParts(parts);
|
|
125
|
-
if (combined) supportedPredicateByTable.set(rel, combined);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Compute covered keys per table: collect equality constraints and check against table unique keys
|
|
129
|
-
const coveredKeysByTable = new Map<string, number[][]>();
|
|
130
|
-
for (const [rel, constraints] of constraintsByTable) {
|
|
131
|
-
const tInfo = tableInfos.find(t => t.relationKey === rel || t.relationName === rel);
|
|
132
|
-
if (!tInfo || !tInfo.uniqueKeys || tInfo.uniqueKeys.length === 0) {
|
|
133
|
-
coveredKeysByTable.set(rel, []);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
const eqCols = new Set<number>();
|
|
137
|
-
for (const c of constraints) {
|
|
138
|
-
if (c.op === '=') {
|
|
139
|
-
eqCols.add(c.columnIndex);
|
|
140
|
-
}
|
|
141
|
-
// Single-value IN could be treated as equality
|
|
142
|
-
if (c.op === 'IN' && Array.isArray(c.value) && (c.value as unknown[]).length === 1) {
|
|
143
|
-
eqCols.add(c.columnIndex);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
const covered: number[][] = [];
|
|
147
|
-
for (const key of tInfo.uniqueKeys) {
|
|
148
|
-
if (key.length === 0) {
|
|
149
|
-
// Zero-length key means at most one row; trivially covered
|
|
150
|
-
covered.push([]);
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
const allCovered = key.every(idx => eqCols.has(idx));
|
|
154
|
-
if (allCovered) covered.push([...key]);
|
|
155
|
-
}
|
|
156
|
-
coveredKeysByTable.set(rel, covered);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
constraintsByTable,
|
|
161
|
-
residualPredicate,
|
|
162
|
-
allConstraints,
|
|
163
|
-
supportedPredicateByTable,
|
|
164
|
-
coveredKeysByTable
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Recursively extract constraints from an expression
|
|
170
|
-
*/
|
|
171
|
-
function extractFromExpression(
|
|
172
|
-
expr: ScalarPlanNode,
|
|
173
|
-
constraints: PredicateConstraint[],
|
|
174
|
-
residual: ScalarPlanNode[],
|
|
175
|
-
attributeToTableMap: Map<number, TableInfo>,
|
|
176
|
-
perTableParts: Map<string, ScalarPlanNode[]>
|
|
177
|
-
): void {
|
|
178
|
-
// Handle AND expressions - recurse on both sides
|
|
179
|
-
if (isAndExpression(expr)) {
|
|
180
|
-
const binaryOp = expr as BinaryOpNode;
|
|
181
|
-
extractFromExpression(binaryOp.left, constraints, residual, attributeToTableMap, perTableParts);
|
|
182
|
-
extractFromExpression(binaryOp.right, constraints, residual, attributeToTableMap, perTableParts);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Handle OR expressions - for now, treat as residual (could be enhanced later)
|
|
187
|
-
if (isOrExpression(expr)) {
|
|
188
|
-
log('OR expression found, treating as residual: %s', expr.toString());
|
|
189
|
-
residual.push(expr);
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// BETWEEN → range constraints
|
|
194
|
-
if (expr.nodeType === PlanNodeType.Between) {
|
|
195
|
-
const c = extractBetweenConstraints(expr as BetweenNode, attributeToTableMap);
|
|
196
|
-
if (c) {
|
|
197
|
-
constraints.push(...c);
|
|
198
|
-
addSupportedPart(expr, attributeToTableMap, perTableParts);
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// IN list → IN constraint (literals only)
|
|
204
|
-
if (expr.nodeType === PlanNodeType.In) {
|
|
205
|
-
const c = extractInConstraint(expr as InNode, attributeToTableMap);
|
|
206
|
-
if (c) {
|
|
207
|
-
constraints.push(c);
|
|
208
|
-
addSupportedPart(expr, attributeToTableMap, perTableParts);
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Try to extract constraint from binary comparison
|
|
214
|
-
const constraint = extractBinaryConstraint(expr, attributeToTableMap);
|
|
215
|
-
if (constraint) {
|
|
216
|
-
constraints.push(constraint);
|
|
217
|
-
addSupportedPart(expr, attributeToTableMap, perTableParts);
|
|
218
|
-
log('Extracted constraint: %s %s %s (table: %s)',
|
|
219
|
-
constraint.attributeId, constraint.op, constraint.value, constraint.targetRelation);
|
|
220
|
-
} else {
|
|
221
|
-
// Cannot convert to constraint - add to residual
|
|
222
|
-
log('Cannot extract constraint from expression, adding to residual: %s', expr.toString());
|
|
223
|
-
residual.push(expr);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function addSupportedPart(expr: ScalarPlanNode, attributeToTableMap: Map<number, TableInfo>, perTableParts: Map<string, ScalarPlanNode[]>): void {
|
|
228
|
-
// Determine target table by first column reference in expr; if absent, skip
|
|
229
|
-
const relKey = findTargetRelationKey(expr, attributeToTableMap);
|
|
230
|
-
if (!relKey) return;
|
|
231
|
-
if (!perTableParts.has(relKey)) perTableParts.set(relKey, []);
|
|
232
|
-
perTableParts.get(relKey)!.push(expr);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function findTargetRelationKey(expr: ScalarPlanNode, attributeToTableMap: Map<number, TableInfo>): string | undefined {
|
|
236
|
-
let found: string | undefined;
|
|
237
|
-
const stack: ScalarPlanNode[] = [expr];
|
|
238
|
-
while (stack.length) {
|
|
239
|
-
const n = stack.pop()!;
|
|
240
|
-
if (n.nodeType === PlanNodeType.ColumnReference) {
|
|
241
|
-
const attrId = (n as unknown as _ColumnRef).attributeId;
|
|
242
|
-
const info = attributeToTableMap.get(attrId);
|
|
243
|
-
if (info) return info.relationKey ?? info.relationName;
|
|
244
|
-
}
|
|
245
|
-
for (const c of n.getChildren()) {
|
|
246
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
247
|
-
stack.push(c as any);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return found;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function combineParts(parts: ScalarPlanNode[]): ScalarPlanNode | undefined {
|
|
254
|
-
if (parts.length === 0) return undefined;
|
|
255
|
-
if (parts.length === 1) return parts[0];
|
|
256
|
-
// Combine with AND
|
|
257
|
-
let acc = parts[0];
|
|
258
|
-
for (let i = 1; i < parts.length; i++) {
|
|
259
|
-
const right = parts[i];
|
|
260
|
-
const ast: AST.BinaryExpr = { type: 'binary', operator: 'AND', left: (acc as any).expression, right: (right as any).expression };
|
|
261
|
-
acc = new BinaryOpNode((acc as any).scope, ast, acc, right);
|
|
262
|
-
}
|
|
263
|
-
return acc;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Extract constraint from binary comparison expression
|
|
268
|
-
*/
|
|
269
|
-
function extractBinaryConstraint(
|
|
270
|
-
expr: ScalarPlanNode,
|
|
271
|
-
attributeToTableMap: Map<number, TableInfo>
|
|
272
|
-
): PredicateConstraint | null {
|
|
273
|
-
// Must be a binary operation
|
|
274
|
-
if (expr.nodeType !== PlanNodeType.BinaryOp) {
|
|
275
|
-
return null;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const binaryOp = expr as BinaryOpNode;
|
|
279
|
-
const { left, right } = binaryOp;
|
|
280
|
-
const operator = binaryOp.expression.operator;
|
|
281
|
-
|
|
282
|
-
// Try column-constant pattern (column op constant)
|
|
283
|
-
let columnRef: ColumnReferenceNode | null = null;
|
|
284
|
-
let constant: SqlValue | undefined;
|
|
285
|
-
let finalOp: ConstraintOp | null = null;
|
|
286
|
-
|
|
287
|
-
if (isColumnReference(left) && (isLiteralConstant(right) || isDynamicValue(right))) {
|
|
288
|
-
columnRef = left;
|
|
289
|
-
if (isLiteralConstant(right)) {
|
|
290
|
-
constant = getLiteralValue(right);
|
|
291
|
-
}
|
|
292
|
-
finalOp = mapOperatorToConstraint(operator, constant);
|
|
293
|
-
} else if ((isLiteralConstant(left) || isDynamicValue(left)) && isColumnReference(right)) {
|
|
294
|
-
// Reverse pattern (constant op column) - flip operator
|
|
295
|
-
columnRef = right;
|
|
296
|
-
if (isLiteralConstant(left)) {
|
|
297
|
-
constant = getLiteralValue(left);
|
|
298
|
-
}
|
|
299
|
-
const baseOp = mapOperatorToConstraint(operator, constant);
|
|
300
|
-
finalOp = baseOp ? flipOperator(baseOp) : null;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (!columnRef || !finalOp) {
|
|
304
|
-
log('No column-constant pattern found in binary expression');
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Map attribute ID to table and column index
|
|
309
|
-
const tableInfo = attributeToTableMap.get(columnRef.attributeId);
|
|
310
|
-
if (!tableInfo) {
|
|
311
|
-
log('No table mapping found for attribute ID %d', columnRef.attributeId);
|
|
312
|
-
return null;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const columnIndex = tableInfo.columnIndexMap.get(columnRef.attributeId);
|
|
316
|
-
if (columnIndex === undefined) {
|
|
317
|
-
log('No column index found for attribute ID %d', columnRef.attributeId);
|
|
318
|
-
return null;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const result: PredicateConstraint = {
|
|
322
|
-
columnIndex,
|
|
323
|
-
attributeId: columnRef.attributeId,
|
|
324
|
-
op: finalOp,
|
|
325
|
-
value: constant,
|
|
326
|
-
usable: true, // Usable since we found table mapping
|
|
327
|
-
sourceExpression: expr,
|
|
328
|
-
targetRelation: tableInfo.relationKey
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
// Attach dynamic binding metadata when RHS/LHS is not a literal
|
|
332
|
-
const rhs = (expr as BinaryOpNode).right;
|
|
333
|
-
const lhs = (expr as BinaryOpNode).left;
|
|
334
|
-
const nonLiteral = !isLiteralConstant(lhs) || !isLiteralConstant(rhs);
|
|
335
|
-
if (nonLiteral) {
|
|
336
|
-
// Determine which side is the value side
|
|
337
|
-
const valueSide = (columnRef === lhs ? rhs : lhs) as ScalarPlanNode;
|
|
338
|
-
if (!isLiteralConstant(valueSide)) {
|
|
339
|
-
result.valueExpr = valueSide;
|
|
340
|
-
if (valueSide.nodeType === PlanNodeType.ParameterReference) {
|
|
341
|
-
result.bindingKind = 'parameter';
|
|
342
|
-
} else if (valueSide.nodeType === PlanNodeType.ColumnReference) {
|
|
343
|
-
const rhsAttrId = (valueSide as unknown as ColumnReferenceNode).attributeId;
|
|
344
|
-
const sameTable = tableInfo.columnIndexMap.has(rhsAttrId);
|
|
345
|
-
result.bindingKind = sameTable ? 'expression' : 'correlated';
|
|
346
|
-
} else {
|
|
347
|
-
result.bindingKind = 'expression';
|
|
348
|
-
}
|
|
349
|
-
} else {
|
|
350
|
-
result.bindingKind = 'literal';
|
|
351
|
-
}
|
|
352
|
-
} else {
|
|
353
|
-
result.bindingKind = 'literal';
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
return result;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
function extractBetweenConstraints(
|
|
360
|
-
expr: BetweenNode,
|
|
361
|
-
attributeToTableMap: Map<number, TableInfo>
|
|
362
|
-
): PredicateConstraint[] | null {
|
|
363
|
-
// Only support column BETWEEN literal AND literal
|
|
364
|
-
const col = expr.expr;
|
|
365
|
-
const low = expr.lower;
|
|
366
|
-
const up = expr.upper;
|
|
367
|
-
const not = !!expr.expression.not;
|
|
368
|
-
|
|
369
|
-
if (col.nodeType !== PlanNodeType.ColumnReference) return null;
|
|
370
|
-
if (!isLiteralConstant(low) || !isLiteralConstant(up)) return null;
|
|
371
|
-
|
|
372
|
-
const columnRef = col as unknown as ColumnReferenceNode;
|
|
373
|
-
const tableInfo = attributeToTableMap.get(columnRef.attributeId);
|
|
374
|
-
if (!tableInfo) return null;
|
|
375
|
-
const columnIndex = tableInfo.columnIndexMap.get(columnRef.attributeId);
|
|
376
|
-
if (columnIndex === undefined) return null;
|
|
377
|
-
|
|
378
|
-
if (not) {
|
|
379
|
-
// NOT BETWEEN not expressible as single contiguous range; leave as residual
|
|
380
|
-
return null;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const lowVal = getLiteralValue(low);
|
|
384
|
-
const upVal = getLiteralValue(up);
|
|
385
|
-
return [
|
|
386
|
-
{
|
|
387
|
-
columnIndex,
|
|
388
|
-
attributeId: columnRef.attributeId,
|
|
389
|
-
op: '>=',
|
|
390
|
-
value: lowVal,
|
|
391
|
-
usable: true,
|
|
392
|
-
sourceExpression: expr,
|
|
393
|
-
targetRelation: tableInfo.relationKey
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
columnIndex,
|
|
397
|
-
attributeId: columnRef.attributeId,
|
|
398
|
-
op: '<=',
|
|
399
|
-
value: upVal,
|
|
400
|
-
usable: true,
|
|
401
|
-
sourceExpression: expr,
|
|
402
|
-
targetRelation: tableInfo.relationKey
|
|
403
|
-
}
|
|
404
|
-
];
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function extractInConstraint(
|
|
408
|
-
expr: InNode,
|
|
409
|
-
attributeToTableMap: Map<number, TableInfo>
|
|
410
|
-
): PredicateConstraint | null {
|
|
411
|
-
// Only support column IN (literal, ...)
|
|
412
|
-
if (expr.source) return null;
|
|
413
|
-
if (!expr.values || expr.values.length === 0) return null;
|
|
414
|
-
const col = expr.condition;
|
|
415
|
-
if (col.nodeType !== PlanNodeType.ColumnReference) return null;
|
|
416
|
-
|
|
417
|
-
// Ensure all are literals
|
|
418
|
-
if (!expr.values.every(v => isLiteralConstant(v))) return null;
|
|
419
|
-
|
|
420
|
-
const columnRef = col as unknown as ColumnReferenceNode;
|
|
421
|
-
const tableInfo = attributeToTableMap.get(columnRef.attributeId);
|
|
422
|
-
if (!tableInfo) return null;
|
|
423
|
-
const columnIndex = tableInfo.columnIndexMap.get(columnRef.attributeId);
|
|
424
|
-
if (columnIndex === undefined) return null;
|
|
425
|
-
|
|
426
|
-
// Virtual table IN constraint can carry a single array value or multiple equality constraints.
|
|
427
|
-
// Our API supports op 'IN' with value array.
|
|
428
|
-
const values = expr.values.map(v => getLiteralValue(v));
|
|
429
|
-
return {
|
|
430
|
-
columnIndex,
|
|
431
|
-
attributeId: columnRef.attributeId,
|
|
432
|
-
op: 'IN',
|
|
433
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
434
|
-
value: values as any,
|
|
435
|
-
usable: true,
|
|
436
|
-
sourceExpression: expr,
|
|
437
|
-
targetRelation: tableInfo.relationKey
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* Map AST operators to constraint operators
|
|
443
|
-
*/
|
|
444
|
-
function mapOperatorToConstraint(operator: string, rightValue?: SqlValue): ConstraintOp | null {
|
|
445
|
-
switch (operator) {
|
|
446
|
-
case '=': return '=';
|
|
447
|
-
case '>': return '>';
|
|
448
|
-
case '>=': return '>=';
|
|
449
|
-
case '<': return '<';
|
|
450
|
-
case '<=': return '<=';
|
|
451
|
-
case 'LIKE': return 'LIKE';
|
|
452
|
-
case 'GLOB': return 'GLOB';
|
|
453
|
-
case 'MATCH': return 'MATCH';
|
|
454
|
-
case 'IN': return 'IN';
|
|
455
|
-
case 'NOT IN': return 'NOT IN';
|
|
456
|
-
case 'IS':
|
|
457
|
-
return rightValue === null ? 'IS NULL' : null;
|
|
458
|
-
case 'IS NOT':
|
|
459
|
-
return rightValue === null ? 'IS NOT NULL' : null;
|
|
460
|
-
default: return null;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Check if expression is an AND operation
|
|
466
|
-
*/
|
|
467
|
-
function isAndExpression(expr: ScalarPlanNode): boolean {
|
|
468
|
-
return expr.nodeType === PlanNodeType.BinaryOp &&
|
|
469
|
-
(expr as BinaryOpNode).expression.operator === 'AND';
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* Check if expression is an OR operation
|
|
474
|
-
*/
|
|
475
|
-
function isOrExpression(expr: ScalarPlanNode): boolean {
|
|
476
|
-
return expr.nodeType === PlanNodeType.BinaryOp &&
|
|
477
|
-
(expr as BinaryOpNode).expression.operator === 'OR';
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Check if node is a column reference
|
|
482
|
-
*/
|
|
483
|
-
function isColumnReference(node: ScalarPlanNode): node is ColumnReferenceNode {
|
|
484
|
-
return CapabilityDetectors.isColumnReference(node);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Check if node is a literal constant
|
|
489
|
-
*/
|
|
490
|
-
function isLiteralConstant(node: ScalarPlanNode): node is LiteralNode {
|
|
491
|
-
return node.nodeType === PlanNodeType.Literal;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
function isDynamicValue(node: ScalarPlanNode): boolean {
|
|
495
|
-
// Parameter or column reference from any table (correlation handled later)
|
|
496
|
-
return node.nodeType === PlanNodeType.ParameterReference || node.nodeType === PlanNodeType.ColumnReference;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Get literal value from literal node
|
|
501
|
-
*/
|
|
502
|
-
function getLiteralValue(node: ScalarPlanNode): SqlValue {
|
|
503
|
-
const literalNode = node as LiteralNode;
|
|
504
|
-
return getSyncLiteral(literalNode.expression);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Flip comparison operator for reversed operand order
|
|
509
|
-
*/
|
|
510
|
-
function flipOperator(op: ConstraintOp): ConstraintOp {
|
|
511
|
-
switch (op) {
|
|
512
|
-
case '<': return '>';
|
|
513
|
-
case '<=': return '>=';
|
|
514
|
-
case '>': return '<';
|
|
515
|
-
case '>=': return '<=';
|
|
516
|
-
case '=': return '=';
|
|
517
|
-
case 'LIKE': return 'LIKE'; // Not flippable
|
|
518
|
-
case 'GLOB': return 'GLOB'; // Not flippable
|
|
519
|
-
case 'MATCH': return 'MATCH'; // Not flippable
|
|
520
|
-
case 'IN': return 'IN'; // Not flippable in this context
|
|
521
|
-
case 'NOT IN': return 'NOT IN'; // Not flippable in this context
|
|
522
|
-
default: return op;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
* Extract constraints for a specific table from a relational plan
|
|
528
|
-
* Analyzes all Filter nodes and join conditions that reference the table
|
|
529
|
-
*/
|
|
530
|
-
export function extractConstraintsForTable(
|
|
531
|
-
plan: RelationalPlanNode,
|
|
532
|
-
targetTableRelationKey: string
|
|
533
|
-
): PredicateConstraint[] {
|
|
534
|
-
const constraints: PredicateConstraint[] = [];
|
|
535
|
-
|
|
536
|
-
// Walk the plan tree looking for filter predicates
|
|
537
|
-
walkPlanForPredicates(plan, (predicate, sourceNode) => {
|
|
538
|
-
// Create table info for the target table only
|
|
539
|
-
const tableInfos = createTableInfosFromPlan(plan).filter(
|
|
540
|
-
info => info.relationKey === targetTableRelationKey
|
|
541
|
-
);
|
|
542
|
-
|
|
543
|
-
if (tableInfos.length > 0) {
|
|
544
|
-
const result = extractConstraints(predicate, tableInfos);
|
|
545
|
-
const tableConstraints = result.constraintsByTable.get(targetTableRelationKey);
|
|
546
|
-
if (tableConstraints) {
|
|
547
|
-
constraints.push(...tableConstraints);
|
|
548
|
-
log('Found %d constraints for table %s from %s',
|
|
549
|
-
tableConstraints.length, targetTableRelationKey, sourceNode);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
return constraints;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Extract constraints and combined residual predicate for a specific table
|
|
559
|
-
*/
|
|
560
|
-
export function extractConstraintsAndResidualForTable(
|
|
561
|
-
plan: RelationalPlanNode,
|
|
562
|
-
targetTableRelationKey: string
|
|
563
|
-
): { constraints: PredicateConstraint[]; residualPredicate?: ScalarPlanNode } {
|
|
564
|
-
const constraints: PredicateConstraint[] = [];
|
|
565
|
-
const residuals: ScalarPlanNode[] = [];
|
|
566
|
-
|
|
567
|
-
walkPlanForPredicates(plan, (predicate) => {
|
|
568
|
-
const tableInfos = createTableInfosFromPlan(plan).filter(
|
|
569
|
-
info => info.relationKey === targetTableRelationKey
|
|
570
|
-
);
|
|
571
|
-
if (tableInfos.length === 0) return;
|
|
572
|
-
const result = extractConstraints(predicate, tableInfos);
|
|
573
|
-
const tableConstraints = result.constraintsByTable.get(targetTableRelationKey);
|
|
574
|
-
if (tableConstraints && tableConstraints.length) {
|
|
575
|
-
constraints.push(...tableConstraints);
|
|
576
|
-
}
|
|
577
|
-
if (result.residualPredicate) {
|
|
578
|
-
residuals.push(result.residualPredicate);
|
|
579
|
-
}
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
return { constraints, residualPredicate: combineResiduals(residuals) };
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/**
|
|
586
|
-
* Compute which unique keys are fully covered by equality constraints for a table within a plan.
|
|
587
|
-
* Returns a list of covered keys (each key is a list of column indexes in the table output order).
|
|
588
|
-
*/
|
|
589
|
-
export function extractCoveredKeysForTable(
|
|
590
|
-
plan: RelationalPlanNode,
|
|
591
|
-
targetTableRelationKey: string
|
|
592
|
-
): number[][] {
|
|
593
|
-
const constraints: PredicateConstraint[] = extractConstraintsForTable(plan, targetTableRelationKey);
|
|
594
|
-
const tInfos = createTableInfosFromPlan(plan).filter(info => info.relationKey === targetTableRelationKey);
|
|
595
|
-
if (tInfos.length === 0) return [];
|
|
596
|
-
const uniqueKeys = tInfos[0].uniqueKeys ?? [];
|
|
597
|
-
return computeCoveredKeysForConstraints(constraints, uniqueKeys);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
* Given a set of constraints and a table's unique keys, compute which keys are fully covered by equality.
|
|
602
|
-
*/
|
|
603
|
-
export function computeCoveredKeysForConstraints(
|
|
604
|
-
constraints: readonly PredicateConstraint[],
|
|
605
|
-
tableUniqueKeys: readonly number[][]
|
|
606
|
-
): number[][] {
|
|
607
|
-
const eqCols = new Set<number>();
|
|
608
|
-
for (const c of constraints) {
|
|
609
|
-
if (c.op === '=') {
|
|
610
|
-
eqCols.add(c.columnIndex);
|
|
611
|
-
}
|
|
612
|
-
if (c.op === 'IN' && Array.isArray(c.value) && (c.value as unknown[]).length === 1) {
|
|
613
|
-
eqCols.add(c.columnIndex);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
const covered: number[][] = [];
|
|
617
|
-
for (const key of tableUniqueKeys) {
|
|
618
|
-
if (key.length === 0) {
|
|
619
|
-
covered.push([]);
|
|
620
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
const allCovered = key.every(idx => eqCols.has(idx));
|
|
623
|
-
if (allCovered) covered.push([...key]);
|
|
624
|
-
}
|
|
625
|
-
return covered;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
/**
|
|
629
|
-
* Analyze plan to classify each TableReference instance as 'row' (row-specific) or 'global'.
|
|
630
|
-
* Row-specific means equality constraints fully cover at least one unique key at that reference.
|
|
631
|
-
*/
|
|
632
|
-
export function analyzeRowSpecific(
|
|
633
|
-
plan: RelationalPlanNode | PlanNode
|
|
634
|
-
): Map<string, 'row' | 'global'> {
|
|
635
|
-
const result = new Map<string, 'row' | 'global'>();
|
|
636
|
-
const infos = createTableInfosFromPlan(plan as RelationalPlanNode);
|
|
637
|
-
for (const info of infos) {
|
|
638
|
-
const covered = extractCoveredKeysForTable(plan as RelationalPlanNode, info.relationKey);
|
|
639
|
-
result.set(info.relationKey, covered.length > 0 ? 'row' : 'global');
|
|
640
|
-
}
|
|
641
|
-
return result;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
function combineResiduals(predicates: ScalarPlanNode[]): ScalarPlanNode | undefined {
|
|
645
|
-
if (predicates.length === 0) return undefined;
|
|
646
|
-
if (predicates.length === 1) return predicates[0];
|
|
647
|
-
let acc = predicates[0];
|
|
648
|
-
for (let i = 1; i < predicates.length; i++) {
|
|
649
|
-
const right = predicates[i];
|
|
650
|
-
const ast: AST.BinaryExpr = { type: 'binary', operator: 'AND', left: (acc as any).expression, right: (right as any).expression };
|
|
651
|
-
acc = new BinaryOpNode((acc as any).scope, ast, acc, right);
|
|
652
|
-
}
|
|
653
|
-
return acc;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
/**
|
|
657
|
-
* Walk a plan tree and call callback for each predicate found
|
|
658
|
-
*/
|
|
659
|
-
function walkPlanForPredicates(
|
|
660
|
-
plan: PlanNode,
|
|
661
|
-
callback: (predicate: ScalarPlanNode, sourceNode: string) => void
|
|
662
|
-
): void {
|
|
663
|
-
if (!plan) return;
|
|
664
|
-
// If node exposes predicates via characteristic, collect them
|
|
665
|
-
if (CapabilityDetectors.isPredicateSource(plan as any)) {
|
|
666
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
667
|
-
const preds = (plan as any).getPredicates() as ReadonlyArray<ScalarPlanNode>;
|
|
668
|
-
for (const p of preds) {
|
|
669
|
-
callback(p, 'PredicateSource');
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
// Recurse into all children (scalar and relational)
|
|
674
|
-
for (const child of plan.getChildren()) {
|
|
675
|
-
walkPlanForPredicates(child as unknown as PlanNode, callback);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
/**
|
|
680
|
-
* Create table information from a relational plan
|
|
681
|
-
*/
|
|
682
|
-
function createTableInfosFromPlan(plan: RelationalPlanNode | PlanNode): TableInfo[] {
|
|
683
|
-
const tableInfos: TableInfo[] = [];
|
|
684
|
-
|
|
685
|
-
const seen = new Set<string>();
|
|
686
|
-
|
|
687
|
-
function visitAny(node: PlanNode): void {
|
|
688
|
-
const id = (node as any).id ?? null;
|
|
689
|
-
if (id !== null) {
|
|
690
|
-
const k = String(id);
|
|
691
|
-
if (seen.has(k)) return;
|
|
692
|
-
seen.add(k);
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
if (node instanceof TableReferenceNode) {
|
|
696
|
-
const tr = node as unknown as { tableSchema: { schemaName: string; name: string } };
|
|
697
|
-
tableInfos.push(createTableInfoFromNode(node as unknown as RelationalPlanNode, `${tr.tableSchema.schemaName}.${tr.tableSchema.name}`));
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
for (const rel of node.getRelations()) {
|
|
701
|
-
visitAny(rel as unknown as PlanNode);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
for (const child of node.getChildren()) {
|
|
705
|
-
visitAny(child as unknown as PlanNode);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
visitAny(plan as unknown as PlanNode);
|
|
710
|
-
return tableInfos;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* Utility to create table info from a table reference node
|
|
715
|
-
*/
|
|
716
|
-
export function createTableInfoFromNode(node: RelationalPlanNode, relationName?: string): TableInfo {
|
|
717
|
-
const attributes = node.getAttributes();
|
|
718
|
-
const columnIndexMap = new Map<number, number>();
|
|
719
|
-
|
|
720
|
-
// Map attribute IDs to column indices
|
|
721
|
-
attributes.forEach((attr, index) => {
|
|
722
|
-
columnIndexMap.set(attr.id, index);
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
// Extract logical unique keys from relation type, map ColRef[] to plain column indexes
|
|
726
|
-
const relType = (node as unknown as { getType: () => { keys: { index: number }[][] } }).getType();
|
|
727
|
-
const uniqueKeys: number[][] | undefined = Array.isArray(relType?.keys)
|
|
728
|
-
? relType.keys.map(key => key.map(ref => ref.index))
|
|
729
|
-
: undefined;
|
|
730
|
-
|
|
731
|
-
const relName = relationName || node.toString();
|
|
732
|
-
const relationKey = `${relName}#${(node as any).id ?? 'unknown'}`;
|
|
733
|
-
|
|
734
|
-
return {
|
|
735
|
-
relationName: relName,
|
|
736
|
-
relationKey,
|
|
737
|
-
attributes: attributes.map(attr => ({ id: attr.id, name: attr.name })),
|
|
738
|
-
columnIndexMap,
|
|
739
|
-
uniqueKeys
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
/**
|
|
744
|
-
* Create a residual filter predicate from constraints that weren't handled
|
|
745
|
-
* This allows creating a filter function that can be applied at runtime
|
|
746
|
-
*/
|
|
747
|
-
export function createResidualFilter(
|
|
748
|
-
originalPredicate: ScalarPlanNode,
|
|
749
|
-
handledConstraints: PredicateConstraint[]
|
|
750
|
-
): ((row: Row) => boolean) | undefined {
|
|
751
|
-
// If no constraints were handled, return undefined (original predicate still needed)
|
|
752
|
-
if (handledConstraints.length === 0) {
|
|
753
|
-
return undefined;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
// TODO: Implement sophisticated residual filter construction
|
|
757
|
-
// This would need to:
|
|
758
|
-
// 1. Identify which parts of the original predicate were handled
|
|
759
|
-
// 2. Construct a new predicate with only the unhandled parts
|
|
760
|
-
// 3. Compile that predicate to a runtime function
|
|
761
|
-
|
|
762
|
-
log('Residual filter construction not yet implemented - using original predicate');
|
|
763
|
-
return undefined;
|
|
764
|
-
}
|