@quereus/quereus 3.1.1 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/database-assertions.js +3 -3
- package/dist/src/core/database-assertions.js.map +1 -1
- package/dist/src/core/database.d.ts +17 -3
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +79 -6
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.js +3 -3
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/emit/ast-stringify.d.ts +0 -1
- package/dist/src/emit/ast-stringify.d.ts.map +1 -1
- package/dist/src/emit/ast-stringify.js +187 -78
- package/dist/src/emit/ast-stringify.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/ast.d.ts +0 -4
- package/dist/src/parser/ast.d.ts.map +1 -1
- package/dist/src/parser/parser.d.ts +9 -1
- package/dist/src/parser/parser.d.ts.map +1 -1
- package/dist/src/parser/parser.js +33 -20
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/visitor.js +1 -1
- package/dist/src/parser/visitor.js.map +1 -1
- package/dist/src/planner/analysis/attribute-provenance.d.ts +45 -0
- package/dist/src/planner/analysis/attribute-provenance.d.ts.map +1 -0
- package/dist/src/planner/analysis/attribute-provenance.js +81 -0
- package/dist/src/planner/analysis/attribute-provenance.js.map +1 -0
- package/dist/src/planner/analysis/const-evaluator.js +5 -5
- package/dist/src/planner/analysis/const-evaluator.js.map +1 -1
- package/dist/src/planner/building/select-window.d.ts.map +1 -1
- package/dist/src/planner/building/select-window.js +54 -21
- package/dist/src/planner/building/select-window.js.map +1 -1
- package/dist/src/planner/cache/correlation-detector.d.ts +7 -0
- package/dist/src/planner/cache/correlation-detector.d.ts.map +1 -1
- package/dist/src/planner/cache/correlation-detector.js +34 -2
- package/dist/src/planner/cache/correlation-detector.js.map +1 -1
- package/dist/src/planner/nodes/async-gather-node.d.ts +169 -0
- package/dist/src/planner/nodes/async-gather-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/async-gather-node.js +488 -0
- package/dist/src/planner/nodes/async-gather-node.js.map +1 -0
- package/dist/src/planner/nodes/bloom-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/bloom-join-node.js +8 -7
- package/dist/src/planner/nodes/bloom-join-node.js.map +1 -1
- package/dist/src/planner/nodes/eager-prefetch-node.d.ts +47 -0
- package/dist/src/planner/nodes/eager-prefetch-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/eager-prefetch-node.js +96 -0
- package/dist/src/planner/nodes/eager-prefetch-node.js.map +1 -0
- package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts +150 -0
- package/dist/src/planner/nodes/fanout-lookup-join-node.d.ts.map +1 -0
- package/dist/src/planner/nodes/fanout-lookup-join-node.js +265 -0
- package/dist/src/planner/nodes/fanout-lookup-join-node.js.map +1 -0
- package/dist/src/planner/nodes/merge-join-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/merge-join-node.js +8 -7
- package/dist/src/planner/nodes/merge-join-node.js.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.d.ts +3 -0
- package/dist/src/planner/nodes/plan-node-type.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node-type.js +3 -0
- package/dist/src/planner/nodes/plan-node-type.js.map +1 -1
- package/dist/src/planner/nodes/plan-node.d.ts +36 -0
- package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/plan-node.js +26 -0
- package/dist/src/planner/nodes/plan-node.js.map +1 -1
- package/dist/src/planner/nodes/reference.d.ts.map +1 -1
- package/dist/src/planner/nodes/reference.js +36 -1
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/optimizer-tuning.d.ts +107 -0
- package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
- package/dist/src/planner/optimizer-tuning.js +43 -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-monotonic-range-access.d.ts.map +1 -1
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js +1 -6
- package/dist/src/planner/rules/access/rule-monotonic-range-access.js.map +1 -1
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts +74 -0
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +139 -0
- package/dist/src/planner/rules/join/rule-fanout-batched-outer.js.map +1 -0
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts +58 -0
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts.map +1 -0
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +592 -0
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts +43 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.d.ts.map +1 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js +115 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-union-all.js.map +1 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts +102 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.d.ts.map +1 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js +545 -0
- package/dist/src/planner/rules/parallel/rule-async-gather-zip-by-key.js.map +1 -0
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts +45 -0
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.d.ts.map +1 -0
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js +78 -0
- package/dist/src/planner/rules/parallel/rule-eager-prefetch-probe.js.map +1 -0
- package/dist/src/planner/scopes/param.d.ts.map +1 -1
- package/dist/src/planner/scopes/param.js +13 -11
- package/dist/src/planner/scopes/param.js.map +1 -1
- package/dist/src/planner/type-utils.js +1 -1
- package/dist/src/planner/type-utils.js.map +1 -1
- package/dist/src/planner/validation/plan-validator.d.ts.map +1 -1
- package/dist/src/planner/validation/plan-validator.js +17 -19
- package/dist/src/planner/validation/plan-validator.js.map +1 -1
- package/dist/src/runtime/async-semaphore.d.ts +36 -0
- package/dist/src/runtime/async-semaphore.d.ts.map +1 -0
- package/dist/src/runtime/async-semaphore.js +72 -0
- package/dist/src/runtime/async-semaphore.js.map +1 -0
- package/dist/src/runtime/deferred-constraint-queue.d.ts.map +1 -1
- package/dist/src/runtime/deferred-constraint-queue.js +4 -3
- package/dist/src/runtime/deferred-constraint-queue.js.map +1 -1
- package/dist/src/runtime/emit/add-constraint.d.ts.map +1 -1
- package/dist/src/runtime/emit/add-constraint.js +51 -37
- package/dist/src/runtime/emit/add-constraint.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +0 -2
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/async-gather.d.ts +77 -0
- package/dist/src/runtime/emit/async-gather.d.ts.map +1 -0
- package/dist/src/runtime/emit/async-gather.js +234 -0
- package/dist/src/runtime/emit/async-gather.js.map +1 -0
- package/dist/src/runtime/emit/bloom-join.d.ts.map +1 -1
- package/dist/src/runtime/emit/bloom-join.js +38 -17
- package/dist/src/runtime/emit/bloom-join.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +12 -52
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/eager-prefetch.d.ts +77 -0
- package/dist/src/runtime/emit/eager-prefetch.d.ts.map +1 -0
- package/dist/src/runtime/emit/eager-prefetch.js +223 -0
- package/dist/src/runtime/emit/eager-prefetch.js.map +1 -0
- package/dist/src/runtime/emit/fanout-lookup-join.d.ts +130 -0
- package/dist/src/runtime/emit/fanout-lookup-join.d.ts.map +1 -0
- package/dist/src/runtime/emit/fanout-lookup-join.js +521 -0
- package/dist/src/runtime/emit/fanout-lookup-join.js.map +1 -0
- package/dist/src/runtime/emit/schema-declarative.d.ts.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.js +28 -2
- package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
- package/dist/src/runtime/emit/transaction.d.ts.map +1 -1
- package/dist/src/runtime/emit/transaction.js +4 -22
- package/dist/src/runtime/emit/transaction.js.map +1 -1
- package/dist/src/runtime/parallel-driver.d.ts +68 -0
- package/dist/src/runtime/parallel-driver.d.ts.map +1 -0
- package/dist/src/runtime/parallel-driver.js +233 -0
- package/dist/src/runtime/parallel-driver.js.map +1 -0
- package/dist/src/runtime/register.d.ts.map +1 -1
- package/dist/src/runtime/register.js +9 -0
- package/dist/src/runtime/register.js.map +1 -1
- package/dist/src/runtime/strict-fork.d.ts +36 -0
- package/dist/src/runtime/strict-fork.d.ts.map +1 -0
- package/dist/src/runtime/strict-fork.js +125 -0
- package/dist/src/runtime/strict-fork.js.map +1 -0
- package/dist/src/schema/manager.d.ts.map +1 -1
- package/dist/src/schema/manager.js +0 -4
- package/dist/src/schema/manager.js.map +1 -1
- package/dist/src/util/comparison.d.ts.map +1 -1
- package/dist/src/util/comparison.js +11 -1
- package/dist/src/util/comparison.js.map +1 -1
- package/dist/src/vtab/capabilities.d.ts +26 -0
- package/dist/src/vtab/capabilities.d.ts.map +1 -1
- package/dist/src/vtab/concurrency.d.ts +29 -0
- package/dist/src/vtab/concurrency.d.ts.map +1 -0
- package/dist/src/vtab/concurrency.js +47 -0
- package/dist/src/vtab/concurrency.js.map +1 -0
- package/dist/src/vtab/memory/layer/scan-layer.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/scan-layer.js +67 -29
- package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +21 -0
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +23 -0
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/dist/src/vtab/memory/table.d.ts.map +1 -1
- package/dist/src/vtab/memory/table.js +2 -0
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/module.d.ts +51 -1
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PlanNodeType } from './plan-node-type.js';
|
|
2
|
+
import { PlanNode, type RelationalPlanNode, type UnaryRelationalNode, type Attribute, type PhysicalProperties } from './plan-node.js';
|
|
3
|
+
import type { RelationType } from '../../common/datatype.js';
|
|
4
|
+
import type { Scope } from '../scopes/scope.js';
|
|
5
|
+
/**
|
|
6
|
+
* Physical pass-through that forks the runtime context and pumps its child
|
|
7
|
+
* sub-tree into a bounded ring buffer **eagerly on `run()`** (emit / scheduler
|
|
8
|
+
* arg-assembly), not on the consumer's first demand. Inside a hash join this
|
|
9
|
+
* lets the probe's first fetch overlap the build phase's materialization.
|
|
10
|
+
*
|
|
11
|
+
* Rows, order, attribute IDs, keys, FDs, equivClasses, orderings, monotonicity
|
|
12
|
+
* all pass through verbatim. The only effect is timing: the source starts
|
|
13
|
+
* executing the moment the scheduler invokes this node's `run()`, ahead of the
|
|
14
|
+
* consumer's first demand.
|
|
15
|
+
*
|
|
16
|
+
* Iterate-or-close contract: because the fork (and its strict-fork counter) is
|
|
17
|
+
* live from `run()`, any consumer of an EagerPrefetch MUST either iterate the
|
|
18
|
+
* returned stream to completion or call its iterator's `return()` — otherwise
|
|
19
|
+
* the pump leaks (fills the buffer, then blocks on back-pressure forever) and
|
|
20
|
+
* the fork counter stays bumped. `emitBloomJoin` honors this by closing the
|
|
21
|
+
* left iterator in a `finally` that wraps both the build and probe phases.
|
|
22
|
+
*
|
|
23
|
+
* The relational pass-through claims (ordering/fds/equivClasses/
|
|
24
|
+
* constantBindings/domainConstraints/monotonicOn) are propagated explicitly by
|
|
25
|
+
* `computePhysical` — the default child-merge only carries
|
|
26
|
+
* deterministic/idempotent/readonly/expectedLatencyMs/concurrencySafe and would
|
|
27
|
+
* otherwise silently drop them. Access-path-local claims
|
|
28
|
+
* (accessCapabilities/rangeBoundedOn) are NOT propagated: this is a
|
|
29
|
+
* single-input pass-through node, and those live only on the physical leaf
|
|
30
|
+
* where the access plan resolved.
|
|
31
|
+
*/
|
|
32
|
+
export declare class EagerPrefetchNode extends PlanNode implements UnaryRelationalNode {
|
|
33
|
+
readonly source: RelationalPlanNode;
|
|
34
|
+
readonly bufferSize: number;
|
|
35
|
+
readonly nodeType = PlanNodeType.EagerPrefetch;
|
|
36
|
+
constructor(scope: Scope, source: RelationalPlanNode, bufferSize?: number, estimatedCostOverride?: number);
|
|
37
|
+
getAttributes(): readonly Attribute[];
|
|
38
|
+
getType(): RelationType;
|
|
39
|
+
getChildren(): readonly [RelationalPlanNode];
|
|
40
|
+
getRelations(): readonly [RelationalPlanNode];
|
|
41
|
+
withChildren(newChildren: readonly PlanNode[]): PlanNode;
|
|
42
|
+
get estimatedRows(): number | undefined;
|
|
43
|
+
computePhysical(childrenPhysical: PhysicalProperties[]): Partial<PhysicalProperties>;
|
|
44
|
+
toString(): string;
|
|
45
|
+
getLogicalAttributes(): Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=eager-prefetch-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eager-prefetch-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/eager-prefetch-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAoB,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACxJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIhD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,iBAAkB,SAAQ,QAAS,YAAW,mBAAmB;aAK5D,MAAM,EAAE,kBAAkB;aAC1B,UAAU,EAAE,MAAM;IALnC,SAAkB,QAAQ,8BAA8B;gBAGvD,KAAK,EAAE,KAAK,EACI,MAAM,EAAE,kBAAkB,EAC1B,UAAU,GAAE,MAAW,EACvC,qBAAqB,CAAC,EAAE,MAAM;IAK/B,aAAa,IAAI,SAAS,SAAS,EAAE;IAIrC,OAAO,IAAI,YAAY;IAIvB,WAAW,IAAI,SAAS,CAAC,kBAAkB,CAAC;IAI5C,YAAY,IAAI,SAAS,CAAC,kBAAkB,CAAC;IAI7C,YAAY,CAAC,WAAW,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ;IAsBxD,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;IAED,eAAe,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkB3E,QAAQ,IAAI,MAAM;IAIlB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAMxD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { PlanNodeType } from './plan-node-type.js';
|
|
2
|
+
import { PlanNode, isRelationalNode } from './plan-node.js';
|
|
3
|
+
import { StatusCode } from '../../common/types.js';
|
|
4
|
+
import { quereusError } from '../../common/errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* Physical pass-through that forks the runtime context and pumps its child
|
|
7
|
+
* sub-tree into a bounded ring buffer **eagerly on `run()`** (emit / scheduler
|
|
8
|
+
* arg-assembly), not on the consumer's first demand. Inside a hash join this
|
|
9
|
+
* lets the probe's first fetch overlap the build phase's materialization.
|
|
10
|
+
*
|
|
11
|
+
* Rows, order, attribute IDs, keys, FDs, equivClasses, orderings, monotonicity
|
|
12
|
+
* all pass through verbatim. The only effect is timing: the source starts
|
|
13
|
+
* executing the moment the scheduler invokes this node's `run()`, ahead of the
|
|
14
|
+
* consumer's first demand.
|
|
15
|
+
*
|
|
16
|
+
* Iterate-or-close contract: because the fork (and its strict-fork counter) is
|
|
17
|
+
* live from `run()`, any consumer of an EagerPrefetch MUST either iterate the
|
|
18
|
+
* returned stream to completion or call its iterator's `return()` — otherwise
|
|
19
|
+
* the pump leaks (fills the buffer, then blocks on back-pressure forever) and
|
|
20
|
+
* the fork counter stays bumped. `emitBloomJoin` honors this by closing the
|
|
21
|
+
* left iterator in a `finally` that wraps both the build and probe phases.
|
|
22
|
+
*
|
|
23
|
+
* The relational pass-through claims (ordering/fds/equivClasses/
|
|
24
|
+
* constantBindings/domainConstraints/monotonicOn) are propagated explicitly by
|
|
25
|
+
* `computePhysical` — the default child-merge only carries
|
|
26
|
+
* deterministic/idempotent/readonly/expectedLatencyMs/concurrencySafe and would
|
|
27
|
+
* otherwise silently drop them. Access-path-local claims
|
|
28
|
+
* (accessCapabilities/rangeBoundedOn) are NOT propagated: this is a
|
|
29
|
+
* single-input pass-through node, and those live only on the physical leaf
|
|
30
|
+
* where the access plan resolved.
|
|
31
|
+
*/
|
|
32
|
+
export class EagerPrefetchNode extends PlanNode {
|
|
33
|
+
source;
|
|
34
|
+
bufferSize;
|
|
35
|
+
nodeType = PlanNodeType.EagerPrefetch;
|
|
36
|
+
constructor(scope, source, bufferSize = 64, estimatedCostOverride) {
|
|
37
|
+
super(scope, estimatedCostOverride);
|
|
38
|
+
this.source = source;
|
|
39
|
+
this.bufferSize = bufferSize;
|
|
40
|
+
}
|
|
41
|
+
getAttributes() {
|
|
42
|
+
return this.source.getAttributes();
|
|
43
|
+
}
|
|
44
|
+
getType() {
|
|
45
|
+
return this.source.getType();
|
|
46
|
+
}
|
|
47
|
+
getChildren() {
|
|
48
|
+
return [this.source];
|
|
49
|
+
}
|
|
50
|
+
getRelations() {
|
|
51
|
+
return [this.source];
|
|
52
|
+
}
|
|
53
|
+
withChildren(newChildren) {
|
|
54
|
+
if (newChildren.length !== 1) {
|
|
55
|
+
quereusError(`EagerPrefetchNode expects 1 child, got ${newChildren.length}`, StatusCode.INTERNAL);
|
|
56
|
+
}
|
|
57
|
+
const [newSource] = newChildren;
|
|
58
|
+
if (!isRelationalNode(newSource)) {
|
|
59
|
+
quereusError('EagerPrefetchNode: child must be a RelationalPlanNode', StatusCode.INTERNAL);
|
|
60
|
+
}
|
|
61
|
+
if (newSource === this.source) {
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
return new EagerPrefetchNode(this.scope, newSource, this.bufferSize);
|
|
65
|
+
}
|
|
66
|
+
get estimatedRows() {
|
|
67
|
+
return this.source.estimatedRows;
|
|
68
|
+
}
|
|
69
|
+
computePhysical(childrenPhysical) {
|
|
70
|
+
const sourcePhysical = childrenPhysical[0];
|
|
71
|
+
return {
|
|
72
|
+
estimatedRows: this.estimatedRows,
|
|
73
|
+
// FIFO ring buffer: rows, order, and attribute IDs are identical at
|
|
74
|
+
// runtime, so every relational claim passes through verbatim.
|
|
75
|
+
ordering: sourcePhysical?.ordering,
|
|
76
|
+
fds: sourcePhysical?.fds,
|
|
77
|
+
equivClasses: sourcePhysical?.equivClasses,
|
|
78
|
+
constantBindings: sourcePhysical?.constantBindings,
|
|
79
|
+
domainConstraints: sourcePhysical?.domainConstraints,
|
|
80
|
+
monotonicOn: sourcePhysical?.monotonicOn,
|
|
81
|
+
// accessCapabilities/rangeBoundedOn are access-path-local — a
|
|
82
|
+
// pass-through node sits between the leaf iterator and the consumer,
|
|
83
|
+
// so they must NOT be propagated.
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
toString() {
|
|
87
|
+
return `EAGER PREFETCH (buffer=${this.bufferSize})`;
|
|
88
|
+
}
|
|
89
|
+
getLogicalAttributes() {
|
|
90
|
+
return {
|
|
91
|
+
bufferSize: this.bufferSize,
|
|
92
|
+
sourceNodeType: this.source.nodeType,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=eager-prefetch-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eager-prefetch-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/eager-prefetch-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAqE,gBAAgB,EAA2B,MAAM,gBAAgB,CAAC;AAGxJ,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;IAK7B;IACA;IALC,QAAQ,GAAG,YAAY,CAAC,aAAa,CAAC;IAExD,YACC,KAAY,EACI,MAA0B,EAC1B,aAAqB,EAAE,EACvC,qBAA8B;QAE9B,KAAK,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAJpB,WAAM,GAAN,MAAM,CAAoB;QAC1B,eAAU,GAAV,UAAU,CAAa;IAIxC,CAAC;IAED,aAAa;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IACpC,CAAC;IAED,OAAO;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED,WAAW;QACV,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,YAAY;QACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,YAAY,CAAC,WAAgC;QAC5C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,YAAY,CAAC,0CAA0C,WAAW,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;QACnG,CAAC;QAED,MAAM,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC;QAEhC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,YAAY,CAAC,uDAAuD,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5F,CAAC;QAED,IAAI,SAAS,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO,IAAI,iBAAiB,CAC3B,IAAI,CAAC,KAAK,EACV,SAA+B,EAC/B,IAAI,CAAC,UAAU,CACf,CAAC;IACH,CAAC;IAED,IAAI,aAAa;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;IAClC,CAAC;IAED,eAAe,CAAC,gBAAsC;QACrD,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO;YACN,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,oEAAoE;YACpE,8DAA8D;YAC9D,QAAQ,EAAE,cAAc,EAAE,QAAQ;YAClC,GAAG,EAAE,cAAc,EAAE,GAAG;YACxB,YAAY,EAAE,cAAc,EAAE,YAAY;YAC1C,gBAAgB,EAAE,cAAc,EAAE,gBAAgB;YAClD,iBAAiB,EAAE,cAAc,EAAE,iBAAiB;YACpD,WAAW,EAAE,cAAc,EAAE,WAAW;YACxC,8DAA8D;YAC9D,qEAAqE;YACrE,kCAAkC;SAClC,CAAC;IACH,CAAC;IAEQ,QAAQ;QAChB,OAAO,0BAA0B,IAAI,CAAC,UAAU,GAAG,CAAC;IACrD,CAAC;IAEQ,oBAAoB;QAC5B,OAAO;YACN,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;SACpC,CAAC;IACH,CAAC;CACD"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { PlanNodeType } from './plan-node-type.js';
|
|
2
|
+
import { PlanNode, type RelationalPlanNode, type Attribute, type PhysicalProperties } from './plan-node.js';
|
|
3
|
+
import type { RelationType } from '../../common/datatype.js';
|
|
4
|
+
import type { Scope } from '../scopes/scope.js';
|
|
5
|
+
/**
|
|
6
|
+
* The mode a FanOutLookupJoin branch contributes for one outer row:
|
|
7
|
+
*
|
|
8
|
+
* - `atMostOne-left` — like LEFT JOIN: branch yields zero or one row; a zero-row
|
|
9
|
+
* match emits NULLs for the branch's output columns and keeps the outer row.
|
|
10
|
+
* - `atMostOne-inner` — like INNER JOIN: branch yields zero or one row; a
|
|
11
|
+
* zero-row match drops the outer row entirely.
|
|
12
|
+
* - `cross` — like an inner nested-loop join: the branch yields *n* rows per
|
|
13
|
+
* outer row (data-driven cardinality) and the node emits one wide row per
|
|
14
|
+
* `(outer, branch-row)` combination — the Cartesian product. A zero-row
|
|
15
|
+
* branch drops the outer row entirely (inner-drop semantics), matching the
|
|
16
|
+
* chain of inner nested-loop joins it replaces.
|
|
17
|
+
* - `cross-left` — like a LEFT nested-loop join with a data-driven 1:n match:
|
|
18
|
+
* a non-empty branch contributes every row (Cartesian product, like `cross`),
|
|
19
|
+
* but a zero-row branch emits one NULL-padded factor row so the outer row is
|
|
20
|
+
* preserved (LEFT semantics). Its output attributes are nullable-widened, like
|
|
21
|
+
* `atMostOne-left`.
|
|
22
|
+
*
|
|
23
|
+
* The `array` mode is deferred to a follow-up backlog ticket.
|
|
24
|
+
*/
|
|
25
|
+
export type FanOutBranchMode = 'atMostOne-left' | 'atMostOne-inner' | 'cross' | 'cross-left';
|
|
26
|
+
/**
|
|
27
|
+
* True when the branch preserves the outer row on an empty match (LEFT
|
|
28
|
+
* semantics) and therefore nullable-widens its output attributes. Shared by the
|
|
29
|
+
* node's attribute/type widening, the recognition rule's `preserveAttrs`
|
|
30
|
+
* widening, and the emit composer's empty-buffer NULL-pad path.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isLeftBranchMode(mode: FanOutBranchMode): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* True when the branch contributes a data-driven 1:n Cartesian factor (`cross`
|
|
35
|
+
* or `cross-left`). Used by the memory guard and the cardinality estimate.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isCrossBranchMode(mode: FanOutBranchMode): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* How the node drives the outer side:
|
|
40
|
+
*
|
|
41
|
+
* - `serial` — drive one outer row at a time: fork its branches, run them
|
|
42
|
+
* concurrently (bounded by `concurrencyCap`), compose, yield, then read the
|
|
43
|
+
* next outer row. The N branches of one row overlap; the next row's lookups
|
|
44
|
+
* do not begin until the current row is fully resolved. **Default.**
|
|
45
|
+
* - `batched` — pipeline lookups *across* outer rows: admit multiple outer
|
|
46
|
+
* rows ahead of the emit frontier (bounded read-ahead with backpressure),
|
|
47
|
+
* share a single global in-flight budget across all of them, and re-order
|
|
48
|
+
* completed rows back into outer order before emitting. Saturates block I/O
|
|
49
|
+
* when there are many outer rows but few branches per row.
|
|
50
|
+
*
|
|
51
|
+
* Output order is identical for both modes (outer order); only the internal
|
|
52
|
+
* scheduling differs. The recognition rule that *chooses* `batched` is a
|
|
53
|
+
* separate concern — nothing in the optimizer constructs a batched node yet,
|
|
54
|
+
* so `serial` keeps existing plans byte-for-byte unchanged.
|
|
55
|
+
*/
|
|
56
|
+
export type FanOutOuterMode = 'serial' | 'batched';
|
|
57
|
+
/**
|
|
58
|
+
* Per-branch specification for {@link FanOutLookupJoinNode}.
|
|
59
|
+
*
|
|
60
|
+
* `child` is a parameterized sub-plan that, for one outer row, produces the
|
|
61
|
+
* lookup-row stream for this branch. The sub-plan reads its outer-binding
|
|
62
|
+
* dependencies via the surrounding `RuntimeContext.context` map; the emitter
|
|
63
|
+
* sets the outer row's slot on the parent context *before* forking so the
|
|
64
|
+
* fork's snapshot already carries the binding.
|
|
65
|
+
*
|
|
66
|
+
* `outputAttrs` carries the output-side attribute identities the branch
|
|
67
|
+
* contributes to the FanOutLookupJoin's wide output row, in `child` output
|
|
68
|
+
* order. They are tracked separately from `child.getAttributes()` so a
|
|
69
|
+
* recognition rule can preserve a surrounding Project's attribute IDs across
|
|
70
|
+
* the rewrite (mirroring `BloomJoinNode.preserveAttributeIds`).
|
|
71
|
+
*
|
|
72
|
+
* `concurrencySafe` is computed by the constructor (rule layer, or test) from
|
|
73
|
+
* `getModuleConcurrencyMode` on the child's underlying table reference plus a
|
|
74
|
+
* read-only-subtree check. The emitter consults it to decide whether to drive
|
|
75
|
+
* the branch raw or wrap it in `acquireConnectionLock` against the active
|
|
76
|
+
* connection.
|
|
77
|
+
*
|
|
78
|
+
* `connectionKey` is an optional identity hint used to choose the lock target:
|
|
79
|
+
* when two branches reference distinct connections, both can run unsynchronized
|
|
80
|
+
* even if both modules declare `'serial'`. When unset, the emitter falls back
|
|
81
|
+
* to `rctx.activeConnection` as the lock target.
|
|
82
|
+
*/
|
|
83
|
+
export interface FanOutBranchSpec {
|
|
84
|
+
readonly child: RelationalPlanNode;
|
|
85
|
+
readonly mode: FanOutBranchMode;
|
|
86
|
+
readonly outputAttrs: readonly Attribute[];
|
|
87
|
+
readonly concurrencySafe: boolean;
|
|
88
|
+
readonly connectionKey?: object;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Physical relational node that, for one outer row, forks N parameterized
|
|
92
|
+
* child sub-plans concurrently, collects `atMostOne` row per branch, and
|
|
93
|
+
* assembles a wide result row.
|
|
94
|
+
*
|
|
95
|
+
* Replaces a chain of N nested-loop LEFT/INNER joins where each branch is a
|
|
96
|
+
* key-aligned (FK→PK) lookup against an independent table, or — for `cross`
|
|
97
|
+
* branches — an unconstrained 1:n inner nested-loop join. The runtime drives
|
|
98
|
+
* the N branch factories through {@link ParallelDriver.drive}, bounded by
|
|
99
|
+
* `concurrencyCap`.
|
|
100
|
+
*
|
|
101
|
+
* Attribute layout: outer's attributes first, then each branch's
|
|
102
|
+
* `outputAttrs` in declared order. `preserveAttributeIds`, when supplied,
|
|
103
|
+
* fixes the entire layout verbatim so rewrites can preserve a surrounding
|
|
104
|
+
* Project's attribute IDs.
|
|
105
|
+
*
|
|
106
|
+
* **Key/FD propagation is conservative.** v1 folds the branches in left-to-
|
|
107
|
+
* right per-branch `propagateJoinFds` calls with **empty equi-pair lists** —
|
|
108
|
+
* the node does not carry per-branch FK→PK alignment, so the propagation
|
|
109
|
+
* cannot derive the cross-branch FDs the optimizer rule (4.5) would otherwise
|
|
110
|
+
* see. The result is correct, just less precise than what the rule layer
|
|
111
|
+
* could produce after recognizing FK alignment. Once the rule lands and a
|
|
112
|
+
* per-branch equi-pair surface is added to {@link FanOutBranchSpec}, this can
|
|
113
|
+
* tighten without changing the emitter.
|
|
114
|
+
*
|
|
115
|
+
* Outer ordering passes through; v1 emits rows in outer order (for `cross`
|
|
116
|
+
* branches, all product rows of one outer row are emitted contiguously before
|
|
117
|
+
* the next outer row). The `array` branch mode is deferred to a follow-up.
|
|
118
|
+
*/
|
|
119
|
+
export declare class FanOutLookupJoinNode extends PlanNode implements RelationalPlanNode {
|
|
120
|
+
readonly outer: RelationalPlanNode;
|
|
121
|
+
readonly branches: readonly FanOutBranchSpec[];
|
|
122
|
+
readonly concurrencyCap: number;
|
|
123
|
+
readonly preserveAttributeIds?: readonly Attribute[] | undefined;
|
|
124
|
+
readonly outerMode: FanOutOuterMode;
|
|
125
|
+
readonly nodeType = PlanNodeType.FanOutLookupJoin;
|
|
126
|
+
private readonly attributesCache;
|
|
127
|
+
constructor(scope: Scope, outer: RelationalPlanNode, branches: readonly FanOutBranchSpec[], concurrencyCap: number, preserveAttributeIds?: readonly Attribute[] | undefined, outerMode?: FanOutOuterMode);
|
|
128
|
+
private static validateConstruction;
|
|
129
|
+
private buildAttributes;
|
|
130
|
+
getAttributes(): readonly Attribute[];
|
|
131
|
+
getType(): RelationType;
|
|
132
|
+
computePhysical(childrenPhysical: readonly PhysicalProperties[]): Partial<PhysicalProperties>;
|
|
133
|
+
/**
|
|
134
|
+
* Outer cardinality multiplied by each cross branch's per-outer-row fan-out
|
|
135
|
+
* (`cross` and `cross-left`; at-most-one branches contribute a ×1 factor). A
|
|
136
|
+
* cross branch whose child has no estimate falls back to ×1 for that branch
|
|
137
|
+
* rather than poisoning the whole estimate to `undefined`. (A `cross-left`
|
|
138
|
+
* branch preserves the outer row when empty, so its true factor is at least 1;
|
|
139
|
+
* the child-estimate product is an upper-leaning approximation either way.)
|
|
140
|
+
* Returns `undefined` only when the outer side itself has no estimate.
|
|
141
|
+
*/
|
|
142
|
+
private computeEstimatedRows;
|
|
143
|
+
get estimatedRows(): number | undefined;
|
|
144
|
+
getChildren(): readonly PlanNode[];
|
|
145
|
+
getRelations(): readonly RelationalPlanNode[];
|
|
146
|
+
withChildren(newChildren: readonly PlanNode[]): PlanNode;
|
|
147
|
+
toString(): string;
|
|
148
|
+
getLogicalAttributes(): Record<string, unknown>;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=fanout-lookup-join-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout-lookup-join-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/fanout-lookup-join-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACN,QAAQ,EAER,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,kBAAkB,EAIvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAMhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,OAAO,GAAG,YAAY,CAAC;AAE7F;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAEhE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAEjE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS,SAAS,EAAE,CAAC;IAC3C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,oBAAqB,SAAQ,QAAS,YAAW,kBAAkB;aAM9D,KAAK,EAAE,kBAAkB;aACzB,QAAQ,EAAE,SAAS,gBAAgB,EAAE;aACrC,cAAc,EAAE,MAAM;aACtB,oBAAoB,CAAC,EAAE,SAAS,SAAS,EAAE;aAC3C,SAAS,EAAE,eAAe;IAT3C,SAAkB,QAAQ,iCAAiC;IAC3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;gBAG9D,KAAK,EAAE,KAAK,EACI,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,SAAS,gBAAgB,EAAE,EACrC,cAAc,EAAE,MAAM,EACtB,oBAAoB,CAAC,EAAE,SAAS,SAAS,EAAE,YAAA,EAC3C,SAAS,GAAE,eAA0B;IAQtD,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA+CnC,OAAO,CAAC,eAAe;IAmBvB,aAAa,IAAI,SAAS,SAAS,EAAE;IAIrC,OAAO,IAAI,YAAY;IA+BvB,eAAe,CAAC,gBAAgB,EAAE,SAAS,kBAAkB,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAiD7F;;;;;;;;OAQG;IACH,OAAO,CAAC,oBAAoB;IAa5B,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;IAED,WAAW,IAAI,SAAS,QAAQ,EAAE;IAIlC,YAAY,IAAI,SAAS,kBAAkB,EAAE;IAI7C,YAAY,CAAC,WAAW,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ;IA2C/C,QAAQ,IAAI,MAAM;IAQlB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYxD"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { PlanNodeType } from './plan-node-type.js';
|
|
2
|
+
import { PlanNode, isRelationalNode, } from './plan-node.js';
|
|
3
|
+
import { Cached } from '../../util/cached.js';
|
|
4
|
+
import { StatusCode } from '../../common/types.js';
|
|
5
|
+
import { quereusError } from '../../common/errors.js';
|
|
6
|
+
import { propagateJoinFds } from './join-utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* True when the branch preserves the outer row on an empty match (LEFT
|
|
9
|
+
* semantics) and therefore nullable-widens its output attributes. Shared by the
|
|
10
|
+
* node's attribute/type widening, the recognition rule's `preserveAttrs`
|
|
11
|
+
* widening, and the emit composer's empty-buffer NULL-pad path.
|
|
12
|
+
*/
|
|
13
|
+
export function isLeftBranchMode(mode) {
|
|
14
|
+
return mode === 'atMostOne-left' || mode === 'cross-left';
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* True when the branch contributes a data-driven 1:n Cartesian factor (`cross`
|
|
18
|
+
* or `cross-left`). Used by the memory guard and the cardinality estimate.
|
|
19
|
+
*/
|
|
20
|
+
export function isCrossBranchMode(mode) {
|
|
21
|
+
return mode === 'cross' || mode === 'cross-left';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Physical relational node that, for one outer row, forks N parameterized
|
|
25
|
+
* child sub-plans concurrently, collects `atMostOne` row per branch, and
|
|
26
|
+
* assembles a wide result row.
|
|
27
|
+
*
|
|
28
|
+
* Replaces a chain of N nested-loop LEFT/INNER joins where each branch is a
|
|
29
|
+
* key-aligned (FK→PK) lookup against an independent table, or — for `cross`
|
|
30
|
+
* branches — an unconstrained 1:n inner nested-loop join. The runtime drives
|
|
31
|
+
* the N branch factories through {@link ParallelDriver.drive}, bounded by
|
|
32
|
+
* `concurrencyCap`.
|
|
33
|
+
*
|
|
34
|
+
* Attribute layout: outer's attributes first, then each branch's
|
|
35
|
+
* `outputAttrs` in declared order. `preserveAttributeIds`, when supplied,
|
|
36
|
+
* fixes the entire layout verbatim so rewrites can preserve a surrounding
|
|
37
|
+
* Project's attribute IDs.
|
|
38
|
+
*
|
|
39
|
+
* **Key/FD propagation is conservative.** v1 folds the branches in left-to-
|
|
40
|
+
* right per-branch `propagateJoinFds` calls with **empty equi-pair lists** —
|
|
41
|
+
* the node does not carry per-branch FK→PK alignment, so the propagation
|
|
42
|
+
* cannot derive the cross-branch FDs the optimizer rule (4.5) would otherwise
|
|
43
|
+
* see. The result is correct, just less precise than what the rule layer
|
|
44
|
+
* could produce after recognizing FK alignment. Once the rule lands and a
|
|
45
|
+
* per-branch equi-pair surface is added to {@link FanOutBranchSpec}, this can
|
|
46
|
+
* tighten without changing the emitter.
|
|
47
|
+
*
|
|
48
|
+
* Outer ordering passes through; v1 emits rows in outer order (for `cross`
|
|
49
|
+
* branches, all product rows of one outer row are emitted contiguously before
|
|
50
|
+
* the next outer row). The `array` branch mode is deferred to a follow-up.
|
|
51
|
+
*/
|
|
52
|
+
export class FanOutLookupJoinNode extends PlanNode {
|
|
53
|
+
outer;
|
|
54
|
+
branches;
|
|
55
|
+
concurrencyCap;
|
|
56
|
+
preserveAttributeIds;
|
|
57
|
+
outerMode;
|
|
58
|
+
nodeType = PlanNodeType.FanOutLookupJoin;
|
|
59
|
+
attributesCache;
|
|
60
|
+
constructor(scope, outer, branches, concurrencyCap, preserveAttributeIds, outerMode = 'serial') {
|
|
61
|
+
FanOutLookupJoinNode.validateConstruction(outer, branches, concurrencyCap, preserveAttributeIds, outerMode);
|
|
62
|
+
const branchCost = branches.reduce((acc, b) => acc + b.child.getTotalCost(), 0);
|
|
63
|
+
super(scope, outer.getTotalCost() + branchCost);
|
|
64
|
+
this.outer = outer;
|
|
65
|
+
this.branches = branches;
|
|
66
|
+
this.concurrencyCap = concurrencyCap;
|
|
67
|
+
this.preserveAttributeIds = preserveAttributeIds;
|
|
68
|
+
this.outerMode = outerMode;
|
|
69
|
+
this.attributesCache = new Cached(() => this.buildAttributes());
|
|
70
|
+
}
|
|
71
|
+
static validateConstruction(outer, branches, concurrencyCap, preserveAttributeIds, outerMode) {
|
|
72
|
+
if (outerMode !== 'serial' && outerMode !== 'batched') {
|
|
73
|
+
quereusError(`FanOutLookupJoinNode: unknown outerMode '${String(outerMode)}'`, StatusCode.INTERNAL);
|
|
74
|
+
}
|
|
75
|
+
if (branches.length < 1) {
|
|
76
|
+
quereusError(`FanOutLookupJoinNode requires >= 1 branch, got ${branches.length}`, StatusCode.INTERNAL);
|
|
77
|
+
}
|
|
78
|
+
if (!Number.isInteger(concurrencyCap) || concurrencyCap < 1) {
|
|
79
|
+
quereusError(`FanOutLookupJoinNode concurrencyCap must be a positive integer, got ${concurrencyCap}`, StatusCode.INTERNAL);
|
|
80
|
+
}
|
|
81
|
+
for (let i = 0; i < branches.length; i++) {
|
|
82
|
+
const b = branches[i];
|
|
83
|
+
const childAttrCount = b.child.getAttributes().length;
|
|
84
|
+
if (b.outputAttrs.length !== childAttrCount) {
|
|
85
|
+
quereusError(`FanOutLookupJoinNode: branch ${i} outputAttrs length (${b.outputAttrs.length}) does not match child attributes (${childAttrCount})`, StatusCode.INTERNAL);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (preserveAttributeIds !== undefined) {
|
|
89
|
+
let expected = outer.getAttributes().length;
|
|
90
|
+
for (const b of branches)
|
|
91
|
+
expected += b.outputAttrs.length;
|
|
92
|
+
if (preserveAttributeIds.length !== expected) {
|
|
93
|
+
quereusError(`FanOutLookupJoinNode: preserveAttributeIds length (${preserveAttributeIds.length}) does not match outer+branches attribute count (${expected})`, StatusCode.INTERNAL);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
buildAttributes() {
|
|
98
|
+
if (this.preserveAttributeIds) {
|
|
99
|
+
return this.preserveAttributeIds.slice();
|
|
100
|
+
}
|
|
101
|
+
const out = [];
|
|
102
|
+
for (const a of this.outer.getAttributes())
|
|
103
|
+
out.push(a);
|
|
104
|
+
for (const b of this.branches) {
|
|
105
|
+
const nullable = isLeftBranchMode(b.mode);
|
|
106
|
+
for (const a of b.outputAttrs) {
|
|
107
|
+
if (nullable && !a.type.nullable) {
|
|
108
|
+
out.push({ ...a, type: { ...a.type, nullable: true } });
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
out.push(a);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
getAttributes() {
|
|
118
|
+
return this.attributesCache.value;
|
|
119
|
+
}
|
|
120
|
+
getType() {
|
|
121
|
+
const outerType = this.outer.getType();
|
|
122
|
+
let isReadOnly = outerType.isReadOnly;
|
|
123
|
+
const columns = [
|
|
124
|
+
...outerType.columns.map(col => col),
|
|
125
|
+
...this.branches.flatMap(b => {
|
|
126
|
+
const nullable = isLeftBranchMode(b.mode);
|
|
127
|
+
return b.child.getType().columns.map(col => nullable && !col.type.nullable
|
|
128
|
+
? { ...col, type: { ...col.type, nullable: true } }
|
|
129
|
+
: col);
|
|
130
|
+
}),
|
|
131
|
+
];
|
|
132
|
+
const rowConstraints = [
|
|
133
|
+
...outerType.rowConstraints.map(rc => rc),
|
|
134
|
+
...this.branches.flatMap(b => b.child.getType().rowConstraints.map(rc => rc)),
|
|
135
|
+
];
|
|
136
|
+
for (const b of this.branches) {
|
|
137
|
+
isReadOnly = isReadOnly && b.child.getType().isReadOnly;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
typeClass: 'relation',
|
|
141
|
+
columns,
|
|
142
|
+
isSet: false,
|
|
143
|
+
isReadOnly,
|
|
144
|
+
keys: [],
|
|
145
|
+
rowConstraints,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
computePhysical(childrenPhysical) {
|
|
149
|
+
const outerPhys = childrenPhysical[0];
|
|
150
|
+
let fds = outerPhys.fds ?? [];
|
|
151
|
+
let equiv = outerPhys.equivClasses ?? [];
|
|
152
|
+
let bindings = outerPhys.constantBindings ?? [];
|
|
153
|
+
let domains = outerPhys.domainConstraints ?? [];
|
|
154
|
+
let leftColCount = this.outer.getAttributes().length;
|
|
155
|
+
for (let i = 0; i < this.branches.length; i++) {
|
|
156
|
+
const b = this.branches[i];
|
|
157
|
+
const rightPhys = childrenPhysical[i + 1];
|
|
158
|
+
const branchCols = b.outputAttrs.length;
|
|
159
|
+
const totalCols = leftColCount + branchCols;
|
|
160
|
+
const joinType = isLeftBranchMode(b.mode) ? 'left' : 'inner';
|
|
161
|
+
const leftPhys = {
|
|
162
|
+
fds,
|
|
163
|
+
equivClasses: equiv,
|
|
164
|
+
constantBindings: bindings,
|
|
165
|
+
domainConstraints: domains,
|
|
166
|
+
};
|
|
167
|
+
const merged = propagateJoinFds(joinType, leftPhys, rightPhys, [], leftColCount, totalCols, []);
|
|
168
|
+
fds = merged.fds ?? [];
|
|
169
|
+
equiv = merged.equivClasses ?? [];
|
|
170
|
+
bindings = merged.constantBindings ?? [];
|
|
171
|
+
domains = merged.domainConstraints ?? [];
|
|
172
|
+
leftColCount = totalCols;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
ordering: outerPhys.ordering,
|
|
176
|
+
monotonicOn: outerPhys.monotonicOn,
|
|
177
|
+
fds: fds.length > 0 ? fds : undefined,
|
|
178
|
+
equivClasses: equiv.length > 0 ? equiv : undefined,
|
|
179
|
+
constantBindings: bindings.length > 0 ? bindings : undefined,
|
|
180
|
+
domainConstraints: domains.length > 0 ? domains : undefined,
|
|
181
|
+
estimatedRows: this.computeEstimatedRows(),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Outer cardinality multiplied by each cross branch's per-outer-row fan-out
|
|
186
|
+
* (`cross` and `cross-left`; at-most-one branches contribute a ×1 factor). A
|
|
187
|
+
* cross branch whose child has no estimate falls back to ×1 for that branch
|
|
188
|
+
* rather than poisoning the whole estimate to `undefined`. (A `cross-left`
|
|
189
|
+
* branch preserves the outer row when empty, so its true factor is at least 1;
|
|
190
|
+
* the child-estimate product is an upper-leaning approximation either way.)
|
|
191
|
+
* Returns `undefined` only when the outer side itself has no estimate.
|
|
192
|
+
*/
|
|
193
|
+
computeEstimatedRows() {
|
|
194
|
+
const outerEst = this.outer.estimatedRows;
|
|
195
|
+
if (outerEst === undefined)
|
|
196
|
+
return undefined;
|
|
197
|
+
let est = outerEst;
|
|
198
|
+
for (const b of this.branches) {
|
|
199
|
+
if (isCrossBranchMode(b.mode)) {
|
|
200
|
+
const childEst = b.child.estimatedRows;
|
|
201
|
+
if (childEst !== undefined)
|
|
202
|
+
est *= childEst;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return est;
|
|
206
|
+
}
|
|
207
|
+
get estimatedRows() {
|
|
208
|
+
return this.computeEstimatedRows();
|
|
209
|
+
}
|
|
210
|
+
getChildren() {
|
|
211
|
+
return [this.outer, ...this.branches.map(b => b.child)];
|
|
212
|
+
}
|
|
213
|
+
getRelations() {
|
|
214
|
+
return [this.outer, ...this.branches.map(b => b.child)];
|
|
215
|
+
}
|
|
216
|
+
withChildren(newChildren) {
|
|
217
|
+
const expected = 1 + this.branches.length;
|
|
218
|
+
if (newChildren.length !== expected) {
|
|
219
|
+
quereusError(`FanOutLookupJoinNode expects ${expected} children, got ${newChildren.length}`, StatusCode.INTERNAL);
|
|
220
|
+
}
|
|
221
|
+
const [newOuter, ...newBranchChildren] = newChildren;
|
|
222
|
+
if (!isRelationalNode(newOuter)) {
|
|
223
|
+
quereusError('FanOutLookupJoinNode: outer child must be a RelationalPlanNode', StatusCode.INTERNAL);
|
|
224
|
+
}
|
|
225
|
+
let changed = newOuter !== this.outer;
|
|
226
|
+
for (let i = 0; i < newBranchChildren.length; i++) {
|
|
227
|
+
const child = newBranchChildren[i];
|
|
228
|
+
if (!isRelationalNode(child)) {
|
|
229
|
+
quereusError(`FanOutLookupJoinNode: branch ${i} child must be a RelationalPlanNode`, StatusCode.INTERNAL);
|
|
230
|
+
}
|
|
231
|
+
if (child !== this.branches[i].child)
|
|
232
|
+
changed = true;
|
|
233
|
+
}
|
|
234
|
+
if (!changed)
|
|
235
|
+
return this;
|
|
236
|
+
const newBranches = this.branches.map((b, i) => ({
|
|
237
|
+
child: newBranchChildren[i],
|
|
238
|
+
mode: b.mode,
|
|
239
|
+
outputAttrs: b.outputAttrs,
|
|
240
|
+
concurrencySafe: b.concurrencySafe,
|
|
241
|
+
connectionKey: b.connectionKey,
|
|
242
|
+
}));
|
|
243
|
+
return new FanOutLookupJoinNode(this.scope, newOuter, newBranches, this.concurrencyCap, this.preserveAttributeIds, this.outerMode);
|
|
244
|
+
}
|
|
245
|
+
toString() {
|
|
246
|
+
const branchSummary = this.branches
|
|
247
|
+
.map((b, i) => `b${i}:${b.mode}${b.concurrencySafe ? '' : '/locked'}`)
|
|
248
|
+
.join(', ');
|
|
249
|
+
const modeSuffix = this.outerMode === 'batched' ? ', batched' : '';
|
|
250
|
+
return `FANOUT_LOOKUP_JOIN(N=${this.branches.length}, cap=${this.concurrencyCap}${modeSuffix}) [${branchSummary}]`;
|
|
251
|
+
}
|
|
252
|
+
getLogicalAttributes() {
|
|
253
|
+
return {
|
|
254
|
+
branchCount: this.branches.length,
|
|
255
|
+
concurrencyCap: this.concurrencyCap,
|
|
256
|
+
outerMode: this.outerMode,
|
|
257
|
+
branches: this.branches.map(b => ({
|
|
258
|
+
mode: b.mode,
|
|
259
|
+
concurrencySafe: b.concurrencySafe,
|
|
260
|
+
outputColCount: b.outputAttrs.length,
|
|
261
|
+
})),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=fanout-lookup-join-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout-lookup-join-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/fanout-lookup-join-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACN,QAAQ,EACR,gBAAgB,GAOhB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAwBnD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAsB;IACtD,OAAO,IAAI,KAAK,gBAAgB,IAAI,IAAI,KAAK,YAAY,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAsB;IACvD,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,YAAY,CAAC;AAClD,CAAC;AAwDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IAMhC;IACA;IACA;IACA;IACA;IATC,QAAQ,GAAG,YAAY,CAAC,gBAAgB,CAAC;IAC1C,eAAe,CAA+B;IAE/D,YACC,KAAY,EACI,KAAyB,EACzB,QAAqC,EACrC,cAAsB,EACtB,oBAA2C,EAC3C,YAA6B,QAAQ;QAErD,oBAAoB,CAAC,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EAAE,SAAS,CAAC,CAAC;QAC5G,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;QAChF,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,GAAG,UAAU,CAAC,CAAC;QARhC,UAAK,GAAL,KAAK,CAAoB;QACzB,aAAQ,GAAR,QAAQ,CAA6B;QACrC,mBAAc,GAAd,cAAc,CAAQ;QACtB,yBAAoB,GAApB,oBAAoB,CAAuB;QAC3C,cAAS,GAAT,SAAS,CAA4B;QAKrD,IAAI,CAAC,eAAe,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IACjE,CAAC;IAEO,MAAM,CAAC,oBAAoB,CAClC,KAAyB,EACzB,QAAqC,EACrC,cAAsB,EACtB,oBAAsD,EACtD,SAA0B;QAE1B,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACvD,YAAY,CACX,4CAA4C,MAAM,CAAC,SAAS,CAAC,GAAG,EAChE,UAAU,CAAC,QAAQ,CACnB,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,YAAY,CACX,kDAAkD,QAAQ,CAAC,MAAM,EAAE,EACnE,UAAU,CAAC,QAAQ,CACnB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YAC7D,YAAY,CACX,uEAAuE,cAAc,EAAE,EACvF,UAAU,CAAC,QAAQ,CACnB,CAAC;QACH,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC;YACtD,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;gBAC7C,YAAY,CACX,gCAAgC,CAAC,wBAAwB,CAAC,CAAC,WAAW,CAAC,MAAM,sCAAsC,cAAc,GAAG,EACpI,UAAU,CAAC,QAAQ,CACnB,CAAC;YACH,CAAC;QACF,CAAC;QACD,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;YACxC,IAAI,QAAQ,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC;YAC5C,KAAK,MAAM,CAAC,IAAI,QAAQ;gBAAE,QAAQ,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;YAC3D,IAAI,oBAAoB,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC9C,YAAY,CACX,sDAAsD,oBAAoB,CAAC,MAAM,oDAAoD,QAAQ,GAAG,EAChJ,UAAU,CAAC,QAAQ,CACnB,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC;IAEO,eAAe;QACtB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAC1C,CAAC;QACD,MAAM,GAAG,GAAgB,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC1C,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC/B,IAAI,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAClC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBACzD,CAAC;qBAAM,CAAC;oBACP,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACb,CAAC;YACF,CAAC;QACF,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,aAAa;QACZ,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;IACnC,CAAC;IAED,OAAO;QACN,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACvC,IAAI,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC;QACtC,MAAM,OAAO,GAAG;YACf,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC;YACpC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBAC5B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC1C,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAC1C,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ;oBAC7B,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;oBACnD,CAAC,CAAC,GAAG,CACN,CAAC;YACH,CAAC,CAAC;SACF,CAAC;QACF,MAAM,cAAc,GAAG;YACtB,GAAG,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YACzC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SAC7E,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,UAAU,GAAG,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;QACzD,CAAC;QACD,OAAO;YACN,SAAS,EAAE,UAAU;YACrB,OAAO;YACP,KAAK,EAAE,KAAK;YACZ,UAAU;YACV,IAAI,EAAE,EAAE;YACR,cAAc;SACE,CAAC;IACnB,CAAC;IAED,eAAe,CAAC,gBAA+C;QAC9D,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,GAAG,GAAwC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC;QACnE,IAAI,KAAK,GAAyC,SAAS,CAAC,YAAY,IAAI,EAAE,CAAC;QAC/E,IAAI,QAAQ,GAAmC,SAAS,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAChF,IAAI,OAAO,GAAoC,SAAS,CAAC,iBAAiB,IAAI,EAAE,CAAC;QACjF,IAAI,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC;QAErD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;YACxC,MAAM,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC;YAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAE7D,MAAM,QAAQ,GAAuB;gBACpC,GAAG;gBACH,YAAY,EAAE,KAAK;gBACnB,gBAAgB,EAAE,QAAQ;gBAC1B,iBAAiB,EAAE,OAAO;aAC1B,CAAC;YACF,MAAM,MAAM,GAAG,gBAAgB,CAC9B,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,EAAE,EACF,YAAY,EACZ,SAAS,EACT,EAAE,CACF,CAAC;YAEF,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;YACvB,KAAK,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;YAClC,QAAQ,GAAG,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC;YACzC,OAAO,GAAG,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC;YACzC,YAAY,GAAG,SAAS,CAAC;QAC1B,CAAC;QAED,OAAO;YACN,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;YACrC,YAAY,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;YAClD,gBAAgB,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YAC5D,iBAAiB,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YAC3D,aAAa,EAAE,IAAI,CAAC,oBAAoB,EAAE;SAC1C,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACK,oBAAoB;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;QAC1C,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC7C,IAAI,GAAG,GAAG,QAAQ,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,IAAI,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;gBACvC,IAAI,QAAQ,KAAK,SAAS;oBAAE,GAAG,IAAI,QAAQ,CAAC;YAC7C,CAAC;QACF,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,aAAa;QAChB,OAAO,IAAI,CAAC,oBAAoB,EAAE,CAAC;IACpC,CAAC;IAED,WAAW;QACV,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,YAAY;QACX,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,YAAY,CAAC,WAAgC;QAC5C,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC1C,IAAI,WAAW,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACrC,YAAY,CACX,gCAAgC,QAAQ,kBAAkB,WAAW,CAAC,MAAM,EAAE,EAC9E,UAAU,CAAC,QAAQ,CACnB,CAAC;QACH,CAAC;QACD,MAAM,CAAC,QAAQ,EAAE,GAAG,iBAAiB,CAAC,GAAG,WAAW,CAAC;QACrD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,YAAY,CAAC,gEAAgE,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,OAAO,GAAG,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC;QACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;YACnC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,YAAY,CACX,gCAAgC,CAAC,qCAAqC,EACtE,UAAU,CAAC,QAAQ,CACnB,CAAC;YACH,CAAC;YACD,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK;gBAAE,OAAO,GAAG,IAAI,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE1B,MAAM,WAAW,GAAuB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACpE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAuB;YACjD,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,eAAe,EAAE,CAAC,CAAC,eAAe;YAClC,aAAa,EAAE,CAAC,CAAC,aAAa;SAC9B,CAAC,CAAC,CAAC;QAEJ,OAAO,IAAI,oBAAoB,CAC9B,IAAI,CAAC,KAAK,EACV,QAA8B,EAC9B,WAAW,EACX,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,oBAAoB,EACzB,IAAI,CAAC,SAAS,CACd,CAAC;IACH,CAAC;IAEQ,QAAQ;QAChB,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ;aACjC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;aACrE,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,wBAAwB,IAAI,CAAC,QAAQ,CAAC,MAAM,SAAS,IAAI,CAAC,cAAc,GAAG,UAAU,MAAM,aAAa,GAAG,CAAC;IACpH,CAAC;IAEQ,oBAAoB;QAC5B,OAAO;YACN,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;YACjC,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjC,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,eAAe,EAAE,CAAC,CAAC,eAAe;gBAClC,cAAc,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM;aACpC,CAAC,CAAC;SACH,CAAC;IACH,CAAC;CACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-join-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/merge-join-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAoB,MAAM,gBAAgB,CAAC;AAC9K,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIhD,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAE3F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAA4G,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG9J;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,QAAS,YAAW,oBAAoB,EAAE,WAAW,EAAE,sBAAsB;IAM9G,sCAAsC;aACtB,IAAI,EAAE,kBAAkB;IACxC,uCAAuC;aACvB,KAAK,EAAE,kBAAkB;aACzB,QAAQ,EAAE,QAAQ;IAClC,2DAA2D;aAC3C,SAAS,EAAE,SAAS,YAAY,EAAE;IAClD,qDAAqD;aACrC,iBAAiB,CAAC,EAAE,cAAc;IAClD,wDAAwD;aACxC,oBAAoB,CAAC,EAAE,SAAS,SAAS,EAAE;IAf5D,SAAkB,QAAQ,0BAA0B;IACpD,OAAO,CAAC,eAAe,CAAsB;gBAG5C,KAAK,EAAE,KAAK;IACZ,sCAAsC;IACtB,IAAI,EAAE,kBAAkB;IACxC,uCAAuC;IACvB,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,QAAQ;IAClC,2DAA2D;IAC3C,SAAS,EAAE,SAAS,YAAY,EAAE;IAClD,qDAAqD;IACrC,iBAAiB,CAAC,EAAE,cAAc,YAAA;IAClD,wDAAwD;IACxC,oBAAoB,CAAC,EAAE,SAAS,SAAS,EAAE,YAAA;IAW5D,OAAO,CAAC,eAAe;IAOvB,aAAa,IAAI,SAAS,EAAE;IAI5B,OAAO,IAAI,YAAY;IAavB,eAAe,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"merge-join-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/merge-join-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAoB,MAAM,gBAAgB,CAAC;AAC9K,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIhD,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAE3F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAA4G,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG9J;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,QAAS,YAAW,oBAAoB,EAAE,WAAW,EAAE,sBAAsB;IAM9G,sCAAsC;aACtB,IAAI,EAAE,kBAAkB;IACxC,uCAAuC;aACvB,KAAK,EAAE,kBAAkB;aACzB,QAAQ,EAAE,QAAQ;IAClC,2DAA2D;aAC3C,SAAS,EAAE,SAAS,YAAY,EAAE;IAClD,qDAAqD;aACrC,iBAAiB,CAAC,EAAE,cAAc;IAClD,wDAAwD;aACxC,oBAAoB,CAAC,EAAE,SAAS,SAAS,EAAE;IAf5D,SAAkB,QAAQ,0BAA0B;IACpD,OAAO,CAAC,eAAe,CAAsB;gBAG5C,KAAK,EAAE,KAAK;IACZ,sCAAsC;IACtB,IAAI,EAAE,kBAAkB;IACxC,uCAAuC;IACvB,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,QAAQ;IAClC,2DAA2D;IAC3C,SAAS,EAAE,SAAS,YAAY,EAAE;IAClD,qDAAqD;IACrC,iBAAiB,CAAC,EAAE,cAAc,YAAA;IAClD,wDAAwD;IACxC,oBAAoB,CAAC,EAAE,SAAS,SAAS,EAAE,YAAA;IAW5D,OAAO,CAAC,eAAe;IAOvB,aAAa,IAAI,SAAS,EAAE;IAI5B,OAAO,IAAI,YAAY;IAavB,eAAe,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA4CpF,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;IAED,WAAW,IAAI,SAAS,QAAQ,EAAE;IAMlC,YAAY,IAAI,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAIjE,YAAY,CAAC,WAAW,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ;IAgCxD,WAAW,IAAI,QAAQ;IACvB,gBAAgB,IAAI,cAAc,GAAG,SAAS;IAC9C,aAAa,IAAI,kBAAkB;IACnC,cAAc,IAAI,kBAAkB;IACpC,eAAe,IAAI,SAAS,MAAM,EAAE,GAAG,SAAS;IAGhD,aAAa,IAAI,SAAS,cAAc,EAAE;IAIjC,QAAQ,IAAI,MAAM;IAKlB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAUxD"}
|
|
@@ -58,11 +58,11 @@ export class MergeJoinNode extends PlanNode {
|
|
|
58
58
|
getType() {
|
|
59
59
|
const leftType = this.left.getType();
|
|
60
60
|
const rightType = this.right.getType();
|
|
61
|
-
const
|
|
62
|
-
const
|
|
61
|
+
const leftIndex = this.left.getAttributeIndex();
|
|
62
|
+
const rightIndex = this.right.getAttributeIndex();
|
|
63
63
|
const indexPairs = this.equiPairs.map(p => ({
|
|
64
|
-
left:
|
|
65
|
-
right:
|
|
64
|
+
left: leftIndex.get(p.leftAttrId) ?? -1,
|
|
65
|
+
right: rightIndex.get(p.rightAttrId) ?? -1,
|
|
66
66
|
})).filter(p => p.left >= 0 && p.right >= 0);
|
|
67
67
|
const keys = combineJoinKeys(leftType.keys, rightType.keys, this.joinType, leftType.columns.length, indexPairs);
|
|
68
68
|
return buildJoinRelationType(leftType, rightType, this.joinType, keys);
|
|
@@ -71,11 +71,12 @@ export class MergeJoinNode extends PlanNode {
|
|
|
71
71
|
const leftPhys = childrenPhysical[0];
|
|
72
72
|
const rightPhys = childrenPhysical[1];
|
|
73
73
|
const leftAttrs = this.left.getAttributes();
|
|
74
|
-
const
|
|
74
|
+
const leftIndex = this.left.getAttributeIndex();
|
|
75
|
+
const rightIndex = this.right.getAttributeIndex();
|
|
75
76
|
// Map attribute-ID-based equi-pairs to column-index-based pairs
|
|
76
77
|
const indexPairs = this.equiPairs.map(p => ({
|
|
77
|
-
left:
|
|
78
|
-
right:
|
|
78
|
+
left: leftIndex.get(p.leftAttrId) ?? -1,
|
|
79
|
+
right: rightIndex.get(p.rightAttrId) ?? -1,
|
|
79
80
|
}));
|
|
80
81
|
const result = analyzeJoinKeyCoverage(this.joinType, leftPhys, rightPhys, this.left.getType(), this.right.getType(), indexPairs, this.left.estimatedRows, this.right.estimatedRows, leftAttrs.length);
|
|
81
82
|
// Merge join preserves left-side ordering
|