@quereus/quereus 4.3.2 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/database-external-changes.d.ts +2 -2
- package/dist/src/core/database-external-changes.d.ts.map +1 -1
- package/dist/src/core/database-external-changes.js +12 -9
- package/dist/src/core/database-external-changes.js.map +1 -1
- package/dist/src/core/database-materialized-views-apply.d.ts +156 -14
- package/dist/src/core/database-materialized-views-apply.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views-apply.js +370 -65
- package/dist/src/core/database-materialized-views-apply.js.map +1 -1
- package/dist/src/core/database-materialized-views-plan-builders.d.ts +65 -1
- package/dist/src/core/database-materialized-views-plan-builders.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views-plan-builders.js +347 -8
- package/dist/src/core/database-materialized-views-plan-builders.js.map +1 -1
- package/dist/src/core/database-materialized-views-plans.d.ts +254 -30
- package/dist/src/core/database-materialized-views-plans.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views.d.ts +96 -40
- package/dist/src/core/database-materialized-views.d.ts.map +1 -1
- package/dist/src/core/database-materialized-views.js +172 -116
- package/dist/src/core/database-materialized-views.js.map +1 -1
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +20 -17
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
- package/dist/src/func/builtins/aggregate.js +127 -21
- package/dist/src/func/builtins/aggregate.js.map +1 -1
- package/dist/src/func/registration.d.ts +6 -1
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +16 -0
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/planner/analysis/equi-correlation.d.ts +26 -0
- package/dist/src/planner/analysis/equi-correlation.d.ts.map +1 -0
- package/dist/src/planner/analysis/equi-correlation.js +62 -0
- package/dist/src/planner/analysis/equi-correlation.js.map +1 -0
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts +54 -18
- package/dist/src/planner/analysis/query-rewrite-matcher.d.ts.map +1 -1
- package/dist/src/planner/analysis/query-rewrite-matcher.js +86 -42
- package/dist/src/planner/analysis/query-rewrite-matcher.js.map +1 -1
- package/dist/src/planner/analysis/scalar-subqueries.d.ts +28 -0
- package/dist/src/planner/analysis/scalar-subqueries.d.ts.map +1 -0
- package/dist/src/planner/analysis/scalar-subqueries.js +60 -0
- package/dist/src/planner/analysis/scalar-subqueries.js.map +1 -0
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +15 -1
- package/dist/src/planner/building/select.js.map +1 -1
- package/dist/src/planner/building/with.d.ts.map +1 -1
- package/dist/src/planner/building/with.js +5 -8
- package/dist/src/planner/building/with.js.map +1 -1
- package/dist/src/planner/cache/materialization-advisory.d.ts +33 -0
- package/dist/src/planner/cache/materialization-advisory.d.ts.map +1 -1
- package/dist/src/planner/cache/materialization-advisory.js +164 -28
- package/dist/src/planner/cache/materialization-advisory.js.map +1 -1
- package/dist/src/planner/cache/reference-graph.d.ts +0 -4
- package/dist/src/planner/cache/reference-graph.d.ts.map +1 -1
- package/dist/src/planner/cache/reference-graph.js +5 -13
- package/dist/src/planner/cache/reference-graph.js.map +1 -1
- package/dist/src/planner/cost/index.d.ts +28 -7
- package/dist/src/planner/cost/index.d.ts.map +1 -1
- package/dist/src/planner/cost/index.js +26 -0
- package/dist/src/planner/cost/index.js.map +1 -1
- package/dist/src/planner/nodes/cache-node.d.ts +18 -2
- package/dist/src/planner/nodes/cache-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cache-node.js +42 -3
- package/dist/src/planner/nodes/cache-node.js.map +1 -1
- package/dist/src/planner/nodes/cte-node.d.ts +15 -1
- package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cte-node.js +12 -2
- package/dist/src/planner/nodes/cte-node.js.map +1 -1
- package/dist/src/planner/nodes/recursive-cte-node.d.ts +30 -1
- package/dist/src/planner/nodes/recursive-cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/recursive-cte-node.js +30 -3
- package/dist/src/planner/nodes/recursive-cte-node.js.map +1 -1
- package/dist/src/planner/optimizer.d.ts.map +1 -1
- package/dist/src/planner/optimizer.js +129 -1
- package/dist/src/planner/optimizer.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-cte-optimization.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-cte-optimization.js +8 -1
- package/dist/src/planner/rules/cache/rule-cte-optimization.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.d.ts +7 -0
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.js +14 -1
- package/dist/src/planner/rules/cache/rule-in-subquery-cache.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js +53 -54
- package/dist/src/planner/rules/cache/rule-materialized-view-rewrite.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.d.ts.map +1 -1
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js +6 -0
- package/dist/src/planner/rules/cache/rule-mutating-subquery-cache.js.map +1 -1
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.d.ts +25 -0
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.d.ts.map +1 -0
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js +176 -0
- package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js.map +1 -0
- package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.d.ts +29 -0
- package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.d.ts.map +1 -0
- package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.js +66 -0
- package/dist/src/planner/rules/cache/rule-scalar-subquery-cache.js.map +1 -0
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.d.ts.map +1 -1
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js +1 -54
- package/dist/src/planner/rules/join/rule-fanout-lookup-join.js.map +1 -1
- package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.d.ts +191 -0
- package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.d.ts.map +1 -0
- package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.js +623 -0
- package/dist/src/planner/rules/subquery/rule-scalar-agg-decorrelation.js.map +1 -0
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts +10 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.d.ts.map +1 -1
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js +242 -51
- package/dist/src/planner/rules/subquery/rule-subquery-decorrelation.js.map +1 -1
- package/dist/src/runtime/cache/shared-cache.d.ts +7 -0
- package/dist/src/runtime/cache/shared-cache.d.ts.map +1 -1
- package/dist/src/runtime/cache/shared-cache.js +34 -1
- package/dist/src/runtime/cache/shared-cache.js.map +1 -1
- package/dist/src/runtime/emit/aggregate.d.ts +2 -3
- package/dist/src/runtime/emit/aggregate.d.ts.map +1 -1
- package/dist/src/runtime/emit/aggregate.js +6 -15
- package/dist/src/runtime/emit/aggregate.js.map +1 -1
- package/dist/src/runtime/emit/cache.d.ts +7 -3
- package/dist/src/runtime/emit/cache.d.ts.map +1 -1
- package/dist/src/runtime/emit/cache.js +23 -6
- package/dist/src/runtime/emit/cache.js.map +1 -1
- package/dist/src/runtime/emit/cte.d.ts.map +1 -1
- package/dist/src/runtime/emit/cte.js +43 -20
- package/dist/src/runtime/emit/cte.js.map +1 -1
- package/dist/src/runtime/emit/dml-executor.d.ts.map +1 -1
- package/dist/src/runtime/emit/dml-executor.js +68 -43
- package/dist/src/runtime/emit/dml-executor.js.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.js +5 -4
- package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.d.ts.map +1 -1
- package/dist/src/runtime/emit/recursive-cte.js +59 -1
- package/dist/src/runtime/emit/recursive-cte.js.map +1 -1
- package/dist/src/runtime/parallel-driver.d.ts +15 -1
- package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
- package/dist/src/runtime/parallel-driver.js +17 -1
- package/dist/src/runtime/parallel-driver.js.map +1 -1
- package/dist/src/runtime/types.d.ts +36 -0
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/schema/function.d.ts +79 -0
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/vtab/memory/layer/scan-layer.js +21 -2
- package/dist/src/vtab/memory/layer/scan-layer.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PlanNodeType } from './plan-node-type.js';
|
|
2
|
-
import { PlanNode, type RelationalPlanNode, type UnaryRelationalNode, type Attribute } from './plan-node.js';
|
|
2
|
+
import { PlanNode, type RelationalPlanNode, type UnaryRelationalNode, type Attribute, type PhysicalProperties } from './plan-node.js';
|
|
3
3
|
import type { RelationType } from '../../common/datatype.js';
|
|
4
4
|
import type { Scope } from '../scopes/scope.js';
|
|
5
5
|
import type { CacheCapable } from '../framework/characteristics.js';
|
|
@@ -15,14 +15,30 @@ export declare class CacheNode extends PlanNode implements UnaryRelationalNode,
|
|
|
15
15
|
readonly source: RelationalPlanNode;
|
|
16
16
|
readonly strategy: CacheStrategy;
|
|
17
17
|
readonly threshold: number;
|
|
18
|
+
/**
|
|
19
|
+
* Eager build mode: fully drain + commit the buffer on the first evaluation
|
|
20
|
+
* before yielding any row, so a short-circuiting consumer above the cache
|
|
21
|
+
* (e.g. IN's first-match early-exit) cannot abort the build. Defaults to the
|
|
22
|
+
* streaming-first behaviour that CTE / nested-loop-right / mutating-subquery
|
|
23
|
+
* caches rely on for first-row latency.
|
|
24
|
+
*/
|
|
25
|
+
readonly eager: boolean;
|
|
18
26
|
readonly nodeType = PlanNodeType.Cache;
|
|
19
27
|
readonly isCacheCapable: true;
|
|
20
28
|
constructor(scope: Scope, source: RelationalPlanNode, strategy?: CacheStrategy, threshold?: number, // Rows before switching to pass-through
|
|
21
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Eager build mode: fully drain + commit the buffer on the first evaluation
|
|
31
|
+
* before yielding any row, so a short-circuiting consumer above the cache
|
|
32
|
+
* (e.g. IN's first-match early-exit) cannot abort the build. Defaults to the
|
|
33
|
+
* streaming-first behaviour that CTE / nested-loop-right / mutating-subquery
|
|
34
|
+
* caches rely on for first-row latency.
|
|
35
|
+
*/
|
|
36
|
+
eager?: boolean, estimatedCostOverride?: number);
|
|
22
37
|
getAttributes(): readonly Attribute[];
|
|
23
38
|
getType(): RelationType;
|
|
24
39
|
getChildren(): readonly [RelationalPlanNode];
|
|
25
40
|
getRelations(): readonly [RelationalPlanNode];
|
|
41
|
+
computePhysical(childrenPhysical: PhysicalProperties[]): Partial<PhysicalProperties>;
|
|
26
42
|
withChildren(newChildren: readonly PlanNode[]): PlanNode;
|
|
27
43
|
get estimatedRows(): number | undefined;
|
|
28
44
|
getCacheStrategy(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/cache-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,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/cache-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,EAAE,KAAK,kBAAkB,EAAoB,MAAM,gBAAgB,CAAC;AACxJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/C;;;;;;GAMG;AACH,qBAAa,SAAU,SAAQ,QAAS,YAAW,mBAAmB,EAAE,YAAY;aAMlE,MAAM,EAAE,kBAAkB;aAC1B,QAAQ,EAAE,aAAa;aACvB,SAAS,EAAE,MAAM;IACjC;;;;;;OAMG;aACa,KAAK,EAAE,OAAO;IAf/B,QAAQ,CAAC,QAAQ,sBAAsB;IACvC,QAAQ,CAAC,cAAc,EAAG,IAAI,CAAU;gBAGvC,KAAK,EAAE,KAAK,EACI,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,GAAE,aAAwB,EAClC,SAAS,GAAE,MAAc,EAAG,wCAAwC;IACpF;;;;;;OAMG;IACa,KAAK,GAAE,OAAe,EACtC,qBAAqB,CAAC,EAAE,MAAM;IAM/B,aAAa,IAAI,SAAS,SAAS,EAAE;IAIrC,OAAO,IAAI,YAAY;IAUvB,WAAW,IAAI,SAAS,CAAC,kBAAkB,CAAC;IAI5C,YAAY,IAAI,SAAS,CAAC,kBAAkB,CAAC;IAI7C,eAAe,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA6BpF,YAAY,CAAC,WAAW,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ;IA4BxD,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;IAED,gBAAgB,IAAI,MAAM;IAI1B,QAAQ,IAAI,OAAO;IAIV,QAAQ,IAAI,MAAM;IAIlB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQxD"}
|
|
@@ -13,14 +13,23 @@ export class CacheNode extends PlanNode {
|
|
|
13
13
|
source;
|
|
14
14
|
strategy;
|
|
15
15
|
threshold;
|
|
16
|
+
eager;
|
|
16
17
|
nodeType = PlanNodeType.Cache;
|
|
17
18
|
isCacheCapable = true;
|
|
18
19
|
constructor(scope, source, strategy = 'memory', threshold = 10000, // Rows before switching to pass-through
|
|
19
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Eager build mode: fully drain + commit the buffer on the first evaluation
|
|
22
|
+
* before yielding any row, so a short-circuiting consumer above the cache
|
|
23
|
+
* (e.g. IN's first-match early-exit) cannot abort the build. Defaults to the
|
|
24
|
+
* streaming-first behaviour that CTE / nested-loop-right / mutating-subquery
|
|
25
|
+
* caches rely on for first-row latency.
|
|
26
|
+
*/
|
|
27
|
+
eager = false, estimatedCostOverride) {
|
|
20
28
|
super(scope, estimatedCostOverride);
|
|
21
29
|
this.source = source;
|
|
22
30
|
this.strategy = strategy;
|
|
23
31
|
this.threshold = threshold;
|
|
32
|
+
this.eager = eager;
|
|
24
33
|
}
|
|
25
34
|
// Cache preserves source attributes exactly
|
|
26
35
|
getAttributes() {
|
|
@@ -41,6 +50,34 @@ export class CacheNode extends PlanNode {
|
|
|
41
50
|
getRelations() {
|
|
42
51
|
return [this.source];
|
|
43
52
|
}
|
|
53
|
+
computePhysical(childrenPhysical) {
|
|
54
|
+
const sourcePhysical = childrenPhysical[0];
|
|
55
|
+
// A cache is a pure materialization pass-through: it buffers the source on
|
|
56
|
+
// first iteration and replays it in the SAME order, preserving every
|
|
57
|
+
// relational characteristic. Attribute ids are unchanged, so — exactly like
|
|
58
|
+
// AliasNode — FDs, equivalence classes, constant bindings, domain
|
|
59
|
+
// constraints, INDs, backward update-lineage, ordering, and monotonicOn all
|
|
60
|
+
// carry through. Without this, wrapping a relation in a Cache would silently
|
|
61
|
+
// drop its keys/FDs and disable downstream key-based optimizations (DISTINCT
|
|
62
|
+
// elimination, join-key coverage, ≤1-row detection).
|
|
63
|
+
//
|
|
64
|
+
// `accessCapabilities` / `rangeBoundedOn` are deliberately NOT propagated:
|
|
65
|
+
// they describe the physical *leaf iterator* (ordinal seek, asof-right), and
|
|
66
|
+
// the cache's replay iterator is not that leaf — matching the pass-through
|
|
67
|
+
// contract documented on those fields.
|
|
68
|
+
return {
|
|
69
|
+
estimatedRows: this.source.estimatedRows,
|
|
70
|
+
ordering: sourcePhysical?.ordering,
|
|
71
|
+
monotonicOn: sourcePhysical?.monotonicOn,
|
|
72
|
+
fds: sourcePhysical?.fds,
|
|
73
|
+
equivClasses: sourcePhysical?.equivClasses,
|
|
74
|
+
constantBindings: sourcePhysical?.constantBindings,
|
|
75
|
+
domainConstraints: sourcePhysical?.domainConstraints,
|
|
76
|
+
inds: sourcePhysical?.inds,
|
|
77
|
+
updateLineage: sourcePhysical?.updateLineage,
|
|
78
|
+
attributeDefaults: sourcePhysical?.attributeDefaults,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
44
81
|
withChildren(newChildren) {
|
|
45
82
|
if (newChildren.length !== 1) {
|
|
46
83
|
quereusError(`CacheNode expects 1 child, got ${newChildren.length}`, StatusCode.INTERNAL);
|
|
@@ -55,7 +92,8 @@ export class CacheNode extends PlanNode {
|
|
|
55
92
|
return this;
|
|
56
93
|
}
|
|
57
94
|
// Create new instance preserving attributes (cache preserves source attributes exactly)
|
|
58
|
-
|
|
95
|
+
// Thread `eager` through so an optimizer rebuild doesn't silently drop it to false.
|
|
96
|
+
return new CacheNode(this.scope, newSource, this.strategy, this.threshold, this.eager);
|
|
59
97
|
}
|
|
60
98
|
get estimatedRows() {
|
|
61
99
|
return this.source.estimatedRows;
|
|
@@ -67,12 +105,13 @@ export class CacheNode extends PlanNode {
|
|
|
67
105
|
return true;
|
|
68
106
|
}
|
|
69
107
|
toString() {
|
|
70
|
-
return `CACHE (${this.strategy}, threshold=${this.threshold})`;
|
|
108
|
+
return `CACHE (${this.strategy}, threshold=${this.threshold}${this.eager ? ', eager' : ''})`;
|
|
71
109
|
}
|
|
72
110
|
getLogicalAttributes() {
|
|
73
111
|
return {
|
|
74
112
|
strategy: this.strategy,
|
|
75
113
|
threshold: this.threshold,
|
|
114
|
+
eager: this.eager,
|
|
76
115
|
sourceNodeType: this.source.nodeType
|
|
77
116
|
};
|
|
78
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/cache-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"cache-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/cache-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,12 +36,26 @@ export declare class CTENode extends PlanNode implements CTEPlanNode, CTEScopeNo
|
|
|
36
36
|
readonly source: RelationalPlanNode;
|
|
37
37
|
readonly materializationHint: 'materialized' | 'not_materialized' | undefined;
|
|
38
38
|
readonly isRecursive: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Resolved materialization decision for emission, set by the
|
|
41
|
+
* materialization-advisory pass: when true, emitCTE buffers this CTE's
|
|
42
|
+
* rows once per statement execution and every reference reads that one
|
|
43
|
+
* shared buffer (multi-referenced or MATERIALIZED-hinted CTEs).
|
|
44
|
+
*/
|
|
45
|
+
readonly materialize: boolean;
|
|
39
46
|
readonly nodeType = PlanNodeType.CTE;
|
|
40
47
|
readonly isCTECapable: true;
|
|
41
48
|
readonly tableDescriptor: TableDescriptor;
|
|
42
49
|
private attributesCache;
|
|
43
50
|
private typeCache;
|
|
44
|
-
constructor(scope: Scope, cteName: string, columns: string[] | undefined, source: RelationalPlanNode, materializationHint: 'materialized' | 'not_materialized' | undefined, isRecursive?: boolean
|
|
51
|
+
constructor(scope: Scope, cteName: string, columns: string[] | undefined, source: RelationalPlanNode, materializationHint: 'materialized' | 'not_materialized' | undefined, isRecursive?: boolean,
|
|
52
|
+
/**
|
|
53
|
+
* Resolved materialization decision for emission, set by the
|
|
54
|
+
* materialization-advisory pass: when true, emitCTE buffers this CTE's
|
|
55
|
+
* rows once per statement execution and every reference reads that one
|
|
56
|
+
* shared buffer (multi-referenced or MATERIALIZED-hinted CTEs).
|
|
57
|
+
*/
|
|
58
|
+
materialize?: boolean);
|
|
45
59
|
private buildAttributes;
|
|
46
60
|
private buildType;
|
|
47
61
|
getAttributes(): readonly Attribute[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cte-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/cte-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAoB,MAAM,gBAAgB,CAAC;AACrJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE;;;;GAIG;AACH,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC1C,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,2DAA2D;IAC3D,aAAa,IAAI,SAAS,SAAS,EAAE,CAAC;IAEtC,uCAAuC;IACvC,OAAO,IAAI,YAAY,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,mBAAmB;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS,CAAC;IAC9E,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,OAAQ,SAAQ,QAAS,YAAW,WAAW,EAAE,YAAY,EAAE,UAAU;aAUpE,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;aAC7B,MAAM,EAAE,kBAAkB;aAC1B,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS;aACpE,WAAW,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"cte-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/cte-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAoB,MAAM,gBAAgB,CAAC;AACrJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE;;;;GAIG;AACH,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC1C,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,2DAA2D;IAC3D,aAAa,IAAI,SAAS,SAAS,EAAE,CAAC;IAEtC,uCAAuC;IACvC,OAAO,IAAI,YAAY,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,mBAAmB;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS,CAAC;IAC9E,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,OAAQ,SAAQ,QAAS,YAAW,WAAW,EAAE,YAAY,EAAE,UAAU;aAUpE,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;aAC7B,MAAM,EAAE,kBAAkB;aAC1B,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS;aACpE,WAAW,EAAE,OAAO;IACpC;;;;;OAKG;aACa,WAAW,EAAE,OAAO;IApBrC,QAAQ,CAAC,QAAQ,oBAAoB;IACrC,QAAQ,CAAC,YAAY,EAAG,IAAI,CAAU;IACtC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAM;IAE/C,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,SAAS,CAAuB;gBAGvC,KAAK,EAAE,KAAK,EACI,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,EAC7B,MAAM,EAAE,kBAAkB,EAC1B,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS,EACpE,WAAW,GAAE,OAAe;IAC5C;;;;;OAKG;IACa,WAAW,GAAE,OAAe;IAS7C,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,SAAS;IAejB,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;IA6BxD,YAAY,IAAI,kBAAkB;IAIzB,QAAQ,IAAI,MAAM;IAOlB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAUxD"}
|
|
@@ -11,12 +11,20 @@ export class CTENode extends PlanNode {
|
|
|
11
11
|
source;
|
|
12
12
|
materializationHint;
|
|
13
13
|
isRecursive;
|
|
14
|
+
materialize;
|
|
14
15
|
nodeType = PlanNodeType.CTE;
|
|
15
16
|
isCTECapable = true;
|
|
16
17
|
tableDescriptor = {}; // Identity object for table context lookup
|
|
17
18
|
attributesCache;
|
|
18
19
|
typeCache;
|
|
19
|
-
constructor(scope, cteName, columns, source, materializationHint, isRecursive = false
|
|
20
|
+
constructor(scope, cteName, columns, source, materializationHint, isRecursive = false,
|
|
21
|
+
/**
|
|
22
|
+
* Resolved materialization decision for emission, set by the
|
|
23
|
+
* materialization-advisory pass: when true, emitCTE buffers this CTE's
|
|
24
|
+
* rows once per statement execution and every reference reads that one
|
|
25
|
+
* shared buffer (multi-referenced or MATERIALIZED-hinted CTEs).
|
|
26
|
+
*/
|
|
27
|
+
materialize = false) {
|
|
20
28
|
// Self-cost only: the source flows in via getChildren(). Self is the CTE
|
|
21
29
|
// materialization overhead.
|
|
22
30
|
super(scope, 10);
|
|
@@ -25,6 +33,7 @@ export class CTENode extends PlanNode {
|
|
|
25
33
|
this.source = source;
|
|
26
34
|
this.materializationHint = materializationHint;
|
|
27
35
|
this.isRecursive = isRecursive;
|
|
36
|
+
this.materialize = materialize;
|
|
28
37
|
this.attributesCache = new Cached(() => this.buildAttributes());
|
|
29
38
|
this.typeCache = new Cached(() => this.buildType());
|
|
30
39
|
}
|
|
@@ -78,7 +87,7 @@ export class CTENode extends PlanNode {
|
|
|
78
87
|
return this;
|
|
79
88
|
}
|
|
80
89
|
// Create new instance with updated source
|
|
81
|
-
return new CTENode(this.scope, this.cteName, this.columns, newSource, this.materializationHint, this.isRecursive);
|
|
90
|
+
return new CTENode(this.scope, this.cteName, this.columns, newSource, this.materializationHint, this.isRecursive, this.materialize);
|
|
82
91
|
}
|
|
83
92
|
getCTESource() {
|
|
84
93
|
return this.source;
|
|
@@ -95,6 +104,7 @@ export class CTENode extends PlanNode {
|
|
|
95
104
|
columns: this.columns,
|
|
96
105
|
materializationHint: this.materializationHint,
|
|
97
106
|
isRecursive: this.isRecursive,
|
|
107
|
+
materialize: this.materialize,
|
|
98
108
|
queryType: this.getType()
|
|
99
109
|
};
|
|
100
110
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cte-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/cte-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA2F,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErJ,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AA8B9C;;;GAGG;AACH,MAAM,OAAO,OAAQ,SAAQ,QAAQ;IAUnB;IACA;IACA;IACA;IACA;
|
|
1
|
+
{"version":3,"file":"cte-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/cte-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,13 +16,35 @@ export declare class RecursiveCTENode extends PlanNode implements CTEPlanNode, C
|
|
|
16
16
|
readonly maxRecursion?: number | undefined;
|
|
17
17
|
readonly limitExpr?: ScalarPlanNode | undefined;
|
|
18
18
|
readonly offsetExpr?: ScalarPlanNode | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Resolved materialization decision for emission, set by the
|
|
21
|
+
* materialization-advisory pass: when true, emitRecursiveCTE drives the
|
|
22
|
+
* recursion once per statement execution into a shared buffer that every
|
|
23
|
+
* reference replays (multi-referenced recursive CTEs — gated purely on
|
|
24
|
+
* reference count, ignoring the materialization hint; see
|
|
25
|
+
* MaterializationAdvisory.shouldMaterializeCTE). When false, each reference
|
|
26
|
+
* streams its own drive (single-reference: keeps early-exit under an outer
|
|
27
|
+
* LIMIT working).
|
|
28
|
+
*/
|
|
29
|
+
readonly materialize: boolean;
|
|
19
30
|
readonly nodeType = PlanNodeType.RecursiveCTE;
|
|
20
31
|
readonly isRecursive = true;
|
|
21
32
|
readonly tableDescriptor: TableDescriptor;
|
|
22
33
|
private attributesCache;
|
|
23
34
|
private typeCache;
|
|
24
35
|
private _recursiveCaseQuery;
|
|
25
|
-
constructor(scope: Scope, cteName: string, columns: string[] | undefined, baseCaseQuery: RelationalPlanNode, recursiveCaseQuery: RelationalPlanNode, isUnionAll: boolean, materializationHint?: 'materialized' | 'not_materialized' | undefined, maxRecursion?: number | undefined, tableDescriptor?: TableDescriptor, limitExpr?: ScalarPlanNode | undefined, offsetExpr?: ScalarPlanNode | undefined
|
|
36
|
+
constructor(scope: Scope, cteName: string, columns: string[] | undefined, baseCaseQuery: RelationalPlanNode, recursiveCaseQuery: RelationalPlanNode, isUnionAll: boolean, materializationHint?: 'materialized' | 'not_materialized' | undefined, maxRecursion?: number | undefined, tableDescriptor?: TableDescriptor, limitExpr?: ScalarPlanNode | undefined, offsetExpr?: ScalarPlanNode | undefined,
|
|
37
|
+
/**
|
|
38
|
+
* Resolved materialization decision for emission, set by the
|
|
39
|
+
* materialization-advisory pass: when true, emitRecursiveCTE drives the
|
|
40
|
+
* recursion once per statement execution into a shared buffer that every
|
|
41
|
+
* reference replays (multi-referenced recursive CTEs — gated purely on
|
|
42
|
+
* reference count, ignoring the materialization hint; see
|
|
43
|
+
* MaterializationAdvisory.shouldMaterializeCTE). When false, each reference
|
|
44
|
+
* streams its own drive (single-reference: keeps early-exit under an outer
|
|
45
|
+
* LIMIT working).
|
|
46
|
+
*/
|
|
47
|
+
materialize?: boolean);
|
|
26
48
|
get recursiveCaseQuery(): RelationalPlanNode;
|
|
27
49
|
/**
|
|
28
50
|
* Sets the recursive case query after construction.
|
|
@@ -37,6 +59,13 @@ export declare class RecursiveCTENode extends PlanNode implements CTEPlanNode, C
|
|
|
37
59
|
get source(): RelationalPlanNode;
|
|
38
60
|
getRelations(): readonly [RelationalPlanNode];
|
|
39
61
|
withChildren(newChildren: readonly PlanNode[]): PlanNode;
|
|
62
|
+
/**
|
|
63
|
+
* Clone with a flipped `materialize` decision, preserving every other field
|
|
64
|
+
* (crucially the `tableDescriptor` identity and the recursive case). Lets the
|
|
65
|
+
* materialization-advisory pass set the flag without hand-copying the full
|
|
66
|
+
* constructor argument list (which `withChildren` already owns).
|
|
67
|
+
*/
|
|
68
|
+
withMaterialize(materialize: boolean): RecursiveCTENode;
|
|
40
69
|
toString(): string;
|
|
41
70
|
getLogicalAttributes(): Record<string, unknown>;
|
|
42
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recursive-cte-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/recursive-cte-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAoB,MAAM,gBAAgB,CAAC;AAChJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE/D;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,QAAS,YAAW,WAAW,EAAE,YAAY;aAWjE,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;aAC7B,aAAa,EAAE,kBAAkB;aAEjC,UAAU,EAAE,OAAO;aACnB,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS;aACpE,YAAY,CAAC,EAAE,MAAM;aAErB,SAAS,CAAC,EAAE,cAAc;aAC1B,UAAU,CAAC,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"recursive-cte-node.d.ts","sourceRoot":"","sources":["../../../../src/planner/nodes/recursive-cte-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAoB,MAAM,gBAAgB,CAAC;AAChJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE/D;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,QAAS,YAAW,WAAW,EAAE,YAAY;aAWjE,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;aAC7B,aAAa,EAAE,kBAAkB;aAEjC,UAAU,EAAE,OAAO;aACnB,mBAAmB,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS;aACpE,YAAY,CAAC,EAAE,MAAM;aAErB,SAAS,CAAC,EAAE,cAAc;aAC1B,UAAU,CAAC,EAAE,cAAc;IAC3C;;;;;;;;;OASG;aACa,WAAW,EAAE,OAAO;IA9BrC,QAAQ,CAAC,QAAQ,6BAA6B;IAC9C,QAAQ,CAAC,WAAW,QAAQ;IAC5B,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,mBAAmB,CAAqB;gBAG/C,KAAK,EAAE,KAAK,EACI,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,EAC7B,aAAa,EAAE,kBAAkB,EACjD,kBAAkB,EAAE,kBAAkB,EACtB,UAAU,EAAE,OAAO,EACnB,mBAAmB,GAAE,cAAc,GAAG,kBAAkB,GAAG,SAA0B,EACrF,YAAY,CAAC,EAAE,MAAM,YAAA,EACrC,eAAe,CAAC,EAAE,eAAe,EACjB,SAAS,CAAC,EAAE,cAAc,YAAA,EAC1B,UAAU,CAAC,EAAE,cAAc,YAAA;IAC3C;;;;;;;;;OASG;IACa,WAAW,GAAE,OAAe;IAY7C,IAAI,kBAAkB,IAAI,kBAAkB,CAE3C;IAED;;;OAGG;IACH,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAUtD,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,SAAS;IAcjB,aAAa,IAAI,SAAS,EAAE;IAI5B,OAAO,IAAI,YAAY;IAIvB,WAAW,IAAI,SAAS,QAAQ,EAAE;IAQlC,IAAI,MAAM,IAAI,kBAAkB,CAE/B;IAED,YAAY,IAAI,SAAS,CAAC,kBAAkB,CAAC;IAI7C,YAAY,CAAC,WAAW,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ;IA8CxD;;;;;OAKG;IACH,eAAe,CAAC,WAAW,EAAE,OAAO,GAAG,gBAAgB;IAoB9C,QAAQ,IAAI,MAAM;IASlB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAaxD"}
|
|
@@ -14,13 +14,25 @@ export class RecursiveCTENode extends PlanNode {
|
|
|
14
14
|
maxRecursion;
|
|
15
15
|
limitExpr;
|
|
16
16
|
offsetExpr;
|
|
17
|
+
materialize;
|
|
17
18
|
nodeType = PlanNodeType.RecursiveCTE;
|
|
18
19
|
isRecursive = true; // Always true for recursive CTEs
|
|
19
20
|
tableDescriptor;
|
|
20
21
|
attributesCache;
|
|
21
22
|
typeCache;
|
|
22
23
|
_recursiveCaseQuery;
|
|
23
|
-
constructor(scope, cteName, columns, baseCaseQuery, recursiveCaseQuery, isUnionAll, materializationHint = 'materialized', maxRecursion, tableDescriptor, limitExpr, offsetExpr
|
|
24
|
+
constructor(scope, cteName, columns, baseCaseQuery, recursiveCaseQuery, isUnionAll, materializationHint = 'materialized', maxRecursion, tableDescriptor, limitExpr, offsetExpr,
|
|
25
|
+
/**
|
|
26
|
+
* Resolved materialization decision for emission, set by the
|
|
27
|
+
* materialization-advisory pass: when true, emitRecursiveCTE drives the
|
|
28
|
+
* recursion once per statement execution into a shared buffer that every
|
|
29
|
+
* reference replays (multi-referenced recursive CTEs — gated purely on
|
|
30
|
+
* reference count, ignoring the materialization hint; see
|
|
31
|
+
* MaterializationAdvisory.shouldMaterializeCTE). When false, each reference
|
|
32
|
+
* streams its own drive (single-reference: keeps early-exit under an outer
|
|
33
|
+
* LIMIT working).
|
|
34
|
+
*/
|
|
35
|
+
materialize = false) {
|
|
24
36
|
// Self-cost only: the base and recursive cases are both in getChildren(),
|
|
25
37
|
// so their subtree costs flow in once via getTotalCost(). Self is the fixed
|
|
26
38
|
// recursion overhead.
|
|
@@ -33,6 +45,7 @@ export class RecursiveCTENode extends PlanNode {
|
|
|
33
45
|
this.maxRecursion = maxRecursion;
|
|
34
46
|
this.limitExpr = limitExpr;
|
|
35
47
|
this.offsetExpr = offsetExpr;
|
|
48
|
+
this.materialize = materialize;
|
|
36
49
|
this._recursiveCaseQuery = recursiveCaseQuery;
|
|
37
50
|
this.tableDescriptor = tableDescriptor || {}; // Identity object for table context lookup
|
|
38
51
|
this.attributesCache = new Cached(() => this.buildAttributes());
|
|
@@ -122,15 +135,28 @@ export class RecursiveCTENode extends PlanNode {
|
|
|
122
135
|
return this;
|
|
123
136
|
}
|
|
124
137
|
// Create new instance with updated children
|
|
125
|
-
const newNode = new RecursiveCTENode(this.scope, this.cteName, this.columns, newBaseCaseQuery, newRecursiveCaseQuery, this.isUnionAll, this.materializationHint, this.maxRecursion, this.tableDescriptor, newLimitExpr, newOffsetExpr);
|
|
138
|
+
const newNode = new RecursiveCTENode(this.scope, this.cteName, this.columns, newBaseCaseQuery, newRecursiveCaseQuery, this.isUnionAll, this.materializationHint, this.maxRecursion, this.tableDescriptor, newLimitExpr, newOffsetExpr, this.materialize);
|
|
126
139
|
return newNode;
|
|
127
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Clone with a flipped `materialize` decision, preserving every other field
|
|
143
|
+
* (crucially the `tableDescriptor` identity and the recursive case). Lets the
|
|
144
|
+
* materialization-advisory pass set the flag without hand-copying the full
|
|
145
|
+
* constructor argument list (which `withChildren` already owns).
|
|
146
|
+
*/
|
|
147
|
+
withMaterialize(materialize) {
|
|
148
|
+
if (this.materialize === materialize) {
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
return new RecursiveCTENode(this.scope, this.cteName, this.columns, this.baseCaseQuery, this.recursiveCaseQuery, this.isUnionAll, this.materializationHint, this.maxRecursion, this.tableDescriptor, this.limitExpr, this.offsetExpr, materialize);
|
|
152
|
+
}
|
|
128
153
|
toString() {
|
|
129
154
|
const recursiveText = 'RECURSIVE ';
|
|
130
155
|
const columnsText = this.columns ? `(${this.columns.join(', ')})` : '';
|
|
131
156
|
const unionText = this.isUnionAll ? 'UNION ALL' : 'UNION';
|
|
132
157
|
const materializationText = this.materializationHint ? ` ${this.materializationHint.toUpperCase()}` : '';
|
|
133
|
-
|
|
158
|
+
const bufferedText = this.materialize ? ' [buffered]' : '';
|
|
159
|
+
return `${recursiveText}CTE ${this.cteName}${columnsText} [${unionText}]${materializationText}${bufferedText}`;
|
|
134
160
|
}
|
|
135
161
|
getLogicalAttributes() {
|
|
136
162
|
return {
|
|
@@ -138,6 +164,7 @@ export class RecursiveCTENode extends PlanNode {
|
|
|
138
164
|
columns: this.columns,
|
|
139
165
|
isUnionAll: this.isUnionAll,
|
|
140
166
|
materializationHint: this.materializationHint,
|
|
167
|
+
materialize: this.materialize,
|
|
141
168
|
isRecursive: true,
|
|
142
169
|
maxRecursion: this.maxRecursion,
|
|
143
170
|
baseCaseType: this.baseCaseQuery.getType(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recursive-cte-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/recursive-cte-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsF,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEhJ,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,QAAQ;IAW5B;IACA;IACA;IAEA;IACA;IACA;IAEA;IACA;
|
|
1
|
+
{"version":3,"file":"recursive-cte-node.js","sourceRoot":"","sources":["../../../../src/planner/nodes/recursive-cte-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimizer.d.ts","sourceRoot":"","sources":["../../../src/planner/optimizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGxE,OAAO,EAAE,cAAc,EAAE,CAAC;AAG1B,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"optimizer.d.ts","sourceRoot":"","sources":["../../../src/planner/optimizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGxE,OAAO,EAAE,cAAc,EAAE,CAAC;AAG1B,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AA+DjF,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAI/C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IACjC,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,QAAQ,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IACxC,KAAK,EAAE,SAAS,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,cAAc,CAAC;CAC/B;AAq/BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,WAAW,EAAE,WAAW,GACtB,IAAI,CA0CN;AAED;;GAEG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,eAAe,CAAqC;IACrD,MAAM,EAAE,eAAe,CAAC;gBAG9B,MAAM,GAAE,eAAgC,EACxC,KAAK,CAAC,EAAE,aAAa;IAUtB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAI3C;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,GAAG,QAAQ;IAgChD;;;OAGG;IACH,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,GAAG,QAAQ;IAe3D;;OAEG;IACH,QAAQ,IAAI,aAAa;IAIzB,qDAAqD;IACrD,kBAAkB,IAAI,oBAAoB,GAAG,IAAI;CAGjD"}
|
|
@@ -48,8 +48,11 @@ import { ruleMonotonicWindow } from './rules/window/rule-monotonic-window.js';
|
|
|
48
48
|
// Constraint rules removed - now handled in builders for correctness
|
|
49
49
|
import { ruleCteOptimization } from './rules/cache/rule-cte-optimization.js';
|
|
50
50
|
import { ruleMutatingSubqueryCache } from './rules/cache/rule-mutating-subquery-cache.js';
|
|
51
|
+
import { ruleNestedLoopRightCache } from './rules/cache/rule-nested-loop-right-cache.js';
|
|
51
52
|
import { ruleInSubqueryCache } from './rules/cache/rule-in-subquery-cache.js';
|
|
52
|
-
import {
|
|
53
|
+
import { ruleScalarSubqueryCache } from './rules/cache/rule-scalar-subquery-cache.js';
|
|
54
|
+
import { ruleSubqueryDecorrelation, ruleExistsInSelectDecorrelation } from './rules/subquery/rule-subquery-decorrelation.js';
|
|
55
|
+
import { ruleScalarAggDecorrelation, ruleScalarAggDecorrelationAggregate, ruleScalarAggDecorrelationFilter, ruleScalarAggDecorrelationSort } from './rules/subquery/rule-scalar-agg-decorrelation.js';
|
|
53
56
|
import { ruleAntiJoinFkEmpty } from './rules/subquery/rule-anti-join-fk-empty.js';
|
|
54
57
|
import { ruleSemiJoinFkTrivial } from './rules/subquery/rule-semi-join-fk-trivial.js';
|
|
55
58
|
import { ruleFilterFoldEmpty, ruleProjectFoldEmpty, ruleSortFoldEmpty, ruleLimitOffsetFoldEmpty, ruleDistinctFoldEmpty, ruleJoinFoldEmpty, } from './rules/predicate/rule-empty-relation-folding.js';
|
|
@@ -469,6 +472,103 @@ const RULE_MANIFEST = [
|
|
|
469
472
|
// executed — refuses when the inner subtree carries a write.
|
|
470
473
|
sideEffectMode: 'aware',
|
|
471
474
|
},
|
|
475
|
+
// Filter match site for scalar-aggregate decorrelation: a correlated
|
|
476
|
+
// scalar-aggregate subquery used in a WHERE (or HAVING) comparison —
|
|
477
|
+
// `where o.total > (select avg(c.amount) from c where c.fk = o.k)` — is
|
|
478
|
+
// rewritten to `Filter[pred'](LeftJoin(outer, groupedAgg))`, sharing the
|
|
479
|
+
// per-subquery rewrite (`decorrelateOne`) with the Project- and Aggregate-site
|
|
480
|
+
// siblings. HAVING is the same shape (a FilterNode over an AggregateNode), so
|
|
481
|
+
// one anchor covers both. Registered AFTER `subquery-decorrelation` (both are
|
|
482
|
+
// Filter-typed; pass rules fire in registration order) so EXISTS/IN semi/anti
|
|
483
|
+
// joins materialize first and this rule then decorrelates any scalar-agg
|
|
484
|
+
// comparison over the already-rewritten source. The two Filter rules target
|
|
485
|
+
// disjoint subquery node types (ExistsNode/InNode conjuncts vs ScalarSubqueryNode
|
|
486
|
+
// anywhere in the tree), so there is no match collision.
|
|
487
|
+
{
|
|
488
|
+
pass: PassId.Structural,
|
|
489
|
+
id: 'scalar-agg-decorrelation-filter',
|
|
490
|
+
nodeType: PlanNodeType.Filter,
|
|
491
|
+
phase: 'rewrite',
|
|
492
|
+
fn: ruleScalarAggDecorrelationFilter,
|
|
493
|
+
// Changes the inner subquery subtree's execution count (per outer row →
|
|
494
|
+
// once) — refuses when the inner subtree carries a write.
|
|
495
|
+
sideEffectMode: 'aware',
|
|
496
|
+
},
|
|
497
|
+
// Scalar-aggregate subquery decorrelation: transform a correlated
|
|
498
|
+
// scalar-aggregate subquery in a SELECT projection into a grouped LEFT JOIN
|
|
499
|
+
// (inner table scanned once, hash-aggregated by correlation key). Registered
|
|
500
|
+
// AFTER `fanout-lookup-join` (which is Project-typed too and, on
|
|
501
|
+
// remote-latency plans, consumes the same subquery shape first — it is inert
|
|
502
|
+
// locally) and adjacent to `subquery-decorrelation`, its WHERE-clause
|
|
503
|
+
// sibling. Unconditional (no cost gate), matching the EXISTS/IN precedent;
|
|
504
|
+
// the tiny-outer/huge-inner tradeoff is tracked in
|
|
505
|
+
// `backlog/feat-decorrelation-cost-model`.
|
|
506
|
+
{
|
|
507
|
+
pass: PassId.Structural,
|
|
508
|
+
id: 'scalar-agg-decorrelation',
|
|
509
|
+
nodeType: PlanNodeType.Project,
|
|
510
|
+
phase: 'rewrite',
|
|
511
|
+
fn: ruleScalarAggDecorrelation,
|
|
512
|
+
// Changes the inner subquery subtree's execution count (per outer row →
|
|
513
|
+
// once) — refuses when the inner subtree carries a write.
|
|
514
|
+
sideEffectMode: 'aware',
|
|
515
|
+
},
|
|
516
|
+
// Aggregate-argument match site for the same rewrite: a scalar-aggregate
|
|
517
|
+
// subquery nested inside an aggregate argument (the shape a two-level
|
|
518
|
+
// nested subquery takes after the Project-site rewrite fires on its
|
|
519
|
+
// enclosing level) is decorrelated into a grouped LEFT JOIN placed BELOW
|
|
520
|
+
// the enclosing aggregate. The structural pass is top-down with rules
|
|
521
|
+
// firing before descent, so multi-level nesting converges level by level
|
|
522
|
+
// within a single pass.
|
|
523
|
+
{
|
|
524
|
+
pass: PassId.Structural,
|
|
525
|
+
id: 'scalar-agg-decorrelation-aggregate',
|
|
526
|
+
nodeType: PlanNodeType.Aggregate,
|
|
527
|
+
phase: 'rewrite',
|
|
528
|
+
fn: ruleScalarAggDecorrelationAggregate,
|
|
529
|
+
// Same execution-count change as the Project-site entry — refuses when
|
|
530
|
+
// the inner subtree carries a write.
|
|
531
|
+
sideEffectMode: 'aware',
|
|
532
|
+
},
|
|
533
|
+
// Sort (ORDER BY) match site for the same rewrite: a correlated
|
|
534
|
+
// scalar-aggregate subquery in a sort-key expression —
|
|
535
|
+
// `order by (select count(*) from c where c.fk = o.k)` — is rewritten to a
|
|
536
|
+
// grouped LEFT JOIN placed BELOW the Sort (so the key can read the value
|
|
537
|
+
// column), then capped with a bare pass-through Project that restores the
|
|
538
|
+
// Sort's original output shape (a SortNode publishes its source's attributes
|
|
539
|
+
// verbatim, so the join's appended columns would otherwise leak upward). Sort
|
|
540
|
+
// is not otherwise a decorrelation anchor, so there is no registration-order
|
|
541
|
+
// coupling with the Filter/Project/Aggregate sites — placed adjacent for
|
|
542
|
+
// locality.
|
|
543
|
+
{
|
|
544
|
+
pass: PassId.Structural,
|
|
545
|
+
id: 'scalar-agg-decorrelation-sort',
|
|
546
|
+
nodeType: PlanNodeType.Sort,
|
|
547
|
+
phase: 'rewrite',
|
|
548
|
+
fn: ruleScalarAggDecorrelationSort,
|
|
549
|
+
// Changes the inner subquery subtree's execution count (per outer row →
|
|
550
|
+
// once) — refuses when the inner subtree carries a write.
|
|
551
|
+
sideEffectMode: 'aware',
|
|
552
|
+
},
|
|
553
|
+
// SELECT-list match site for EXISTS/IN decorrelation: a correlated EXISTS /
|
|
554
|
+
// NOT EXISTS / IN in a ProjectNode's expressions becomes a LEFT join carrying
|
|
555
|
+
// an `exists right as` match flag, with the subquery node replaced by a flag
|
|
556
|
+
// column reference (every outer row survives — a semi/anti join cannot express
|
|
557
|
+
// this). Registered adjacent to its decorrelation siblings; ordering relative
|
|
558
|
+
// to the earlier-registered Project-typed flag rules (join-existence-pruning,
|
|
559
|
+
// the recovery rules) is not load-bearing — the per-node applyRules fixpoint
|
|
560
|
+
// re-offers every rule whenever a transform mints a new node, so they see the
|
|
561
|
+
// flag-bearing Project produced here in the same loop.
|
|
562
|
+
{
|
|
563
|
+
pass: PassId.Structural,
|
|
564
|
+
id: 'exists-in-select-decorrelation',
|
|
565
|
+
nodeType: PlanNodeType.Project,
|
|
566
|
+
phase: 'rewrite',
|
|
567
|
+
fn: ruleExistsInSelectDecorrelation,
|
|
568
|
+
// Changes the inner subquery subtree's execution count (per outer row →
|
|
569
|
+
// once) — refuses when the inner subtree carries a write.
|
|
570
|
+
sideEffectMode: 'aware',
|
|
571
|
+
},
|
|
472
572
|
// IND-driven existence folding (runs after decorrelation has materialized
|
|
473
573
|
// EXISTS / NOT EXISTS as semi/anti joins):
|
|
474
574
|
// - Anti-join over a covering non-null FK → Filter(L, false)
|
|
@@ -770,6 +870,24 @@ const RULE_MANIFEST = [
|
|
|
770
870
|
// them in a run-once CacheNode — the canonical aware rule.
|
|
771
871
|
sideEffectMode: 'aware',
|
|
772
872
|
},
|
|
873
|
+
// Cache the pure right side of a surviving nested-loop JoinNode. Runs
|
|
874
|
+
// immediately after mutating-subquery-cache so that a side-effect-bearing
|
|
875
|
+
// right side is already wrapped (and this rule's already-cached gate skips
|
|
876
|
+
// it) — the two rules partition the space: mutating handles impure right
|
|
877
|
+
// sides, this one handles pure ones. By PostOptimization every equi-join is
|
|
878
|
+
// already a hash/merge, so any logical JoinNode reaching here is a nested
|
|
879
|
+
// loop whose left-driven types re-open the right pipeline per left row.
|
|
880
|
+
{
|
|
881
|
+
pass: PassId.PostOptimization,
|
|
882
|
+
id: 'nested-loop-right-cache',
|
|
883
|
+
nodeType: PlanNodeType.Join,
|
|
884
|
+
phase: 'rewrite',
|
|
885
|
+
fn: ruleNestedLoopRightCache,
|
|
886
|
+
// Only fires on side-effect-free right sides (purity gate), but declares
|
|
887
|
+
// 'aware' to match the sibling cache rules and stay correct if the gate
|
|
888
|
+
// is ever relaxed.
|
|
889
|
+
sideEffectMode: 'aware',
|
|
890
|
+
},
|
|
773
891
|
// AsofScan strategy selection (hash → merge). Runs after the leaves' physical
|
|
774
892
|
// ordering / monotonicOn are finalized (monotonic-range-access) so the
|
|
775
893
|
// predicate-driven check can read them off.
|
|
@@ -881,6 +999,16 @@ const RULE_MANIFEST = [
|
|
|
881
999
|
// Already gates on `isFunctional(source)` (deterministic + read-only).
|
|
882
1000
|
sideEffectMode: 'aware',
|
|
883
1001
|
},
|
|
1002
|
+
// Scalar-subquery caching: wrap uncorrelated scalar subquery inners in CacheNode.
|
|
1003
|
+
{
|
|
1004
|
+
pass: PassId.PostOptimization,
|
|
1005
|
+
id: 'scalar-subquery-cache',
|
|
1006
|
+
nodeType: PlanNodeType.ScalarSubquery,
|
|
1007
|
+
phase: 'rewrite',
|
|
1008
|
+
fn: ruleScalarSubqueryCache,
|
|
1009
|
+
// Gates on isFunctional(inner) (deterministic + read-only).
|
|
1010
|
+
sideEffectMode: 'aware',
|
|
1011
|
+
},
|
|
884
1012
|
// NOTE: The materialization advisory no longer registers per-node-type rules.
|
|
885
1013
|
// It runs once over the whole plan as a dedicated custom-execute pass
|
|
886
1014
|
// (`PassId.Materialization`, order 35 — after PostOptimization so it observes
|