@harperfast/harper 5.2.0-alpha.6 → 5.2.0-beta.2
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/bin/cliOperations.ts +76 -12
- package/bin/run.ts +10 -0
- package/bin/status.ts +1 -1
- package/components/Application.ts +146 -83
- package/components/Scope.ts +4 -0
- package/components/componentLoader.ts +7 -0
- package/components/operations.js +21 -1
- package/config/configUtils.ts +139 -5
- package/config-app.schema.json +70 -0
- package/dataLayer/harperBridge/ResourceBridge.ts +7 -0
- package/dist/bin/cliOperations.js +76 -12
- package/dist/bin/cliOperations.js.map +1 -1
- package/dist/bin/run.js +9 -0
- package/dist/bin/run.js.map +1 -1
- package/dist/bin/status.js +1 -1
- package/dist/bin/status.js.map +1 -1
- package/dist/components/Application.d.ts +12 -5
- package/dist/components/Application.js +121 -60
- package/dist/components/Application.js.map +1 -1
- package/dist/components/Scope.d.ts +1 -0
- package/dist/components/Scope.js +4 -0
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/componentLoader.js +7 -0
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/operations.js +20 -1
- package/dist/components/operations.js.map +1 -1
- package/dist/config/configUtils.d.ts +31 -0
- package/dist/config/configUtils.js +127 -5
- package/dist/config/configUtils.js.map +1 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.js +8 -0
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/resources/DatabaseTransaction.d.ts +12 -0
- package/dist/resources/DatabaseTransaction.js +97 -0
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/RequestTarget.js +13 -3
- package/dist/resources/RequestTarget.js.map +1 -1
- package/dist/resources/Resource.js +21 -2
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/Table.d.ts +3 -1
- package/dist/resources/Table.js +48 -5
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/metadata.d.ts +3 -0
- package/dist/resources/analytics/metadata.js +3 -0
- package/dist/resources/analytics/metadata.js.map +1 -1
- package/dist/resources/analytics/write.js +22 -0
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/databases.js +21 -0
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/defineResource.js +20 -7
- package/dist/resources/defineResource.js.map +1 -1
- package/dist/resources/jsResource.d.ts +24 -0
- package/dist/resources/jsResource.js +58 -2
- package/dist/resources/jsResource.js.map +1 -1
- package/dist/resources/openApi.js +45 -20
- package/dist/resources/openApi.js.map +1 -1
- package/dist/resources/scheduler/CronExpression.d.ts +71 -0
- package/dist/resources/scheduler/CronExpression.js +367 -0
- package/dist/resources/scheduler/CronExpression.js.map +1 -0
- package/dist/resources/scheduler/engine.d.ts +91 -0
- package/dist/resources/scheduler/engine.js +767 -0
- package/dist/resources/scheduler/engine.js.map +1 -0
- package/dist/resources/scheduler/scheduler.d.ts +33 -0
- package/dist/resources/scheduler/scheduler.js +200 -0
- package/dist/resources/scheduler/scheduler.js.map +1 -0
- package/dist/security/auth.js +1 -0
- package/dist/security/auth.js.map +1 -1
- package/dist/security/jsLoader.js +8 -0
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/security/keys.d.ts +32 -0
- package/dist/security/keys.js +147 -0
- package/dist/security/keys.js.map +1 -1
- package/dist/server/REST.js +67 -1
- package/dist/server/REST.js.map +1 -1
- package/dist/server/Server.d.ts +6 -0
- package/dist/server/Server.js.map +1 -1
- package/dist/server/http.d.ts +2 -0
- package/dist/server/http.js +139 -14
- package/dist/server/http.js.map +1 -1
- package/dist/server/operationsServer.js +3 -3
- package/dist/server/operationsServer.js.map +1 -1
- package/dist/server/serverHelpers/progressEmitter.js +5 -1
- package/dist/server/serverHelpers/progressEmitter.js.map +1 -1
- package/dist/server/threads/threadServer.js +9 -5
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/sqlEngine/binder/bind.d.ts +72 -0
- package/dist/sqlEngine/binder/bind.js +289 -0
- package/dist/sqlEngine/binder/bind.js.map +1 -0
- package/dist/sqlEngine/config.d.ts +35 -0
- package/dist/sqlEngine/config.js +62 -0
- package/dist/sqlEngine/config.js.map +1 -0
- package/dist/sqlEngine/diff/differential.d.ts +23 -0
- package/dist/sqlEngine/diff/differential.js +90 -0
- package/dist/sqlEngine/diff/differential.js.map +1 -0
- package/dist/sqlEngine/errors.d.ts +22 -0
- package/dist/sqlEngine/errors.js +36 -0
- package/dist/sqlEngine/errors.js.map +1 -0
- package/dist/sqlEngine/executor/runMutation.d.ts +35 -0
- package/dist/sqlEngine/executor/runMutation.js +352 -0
- package/dist/sqlEngine/executor/runMutation.js.map +1 -0
- package/dist/sqlEngine/executor/runSelect.d.ts +7 -0
- package/dist/sqlEngine/executor/runSelect.js +14 -0
- package/dist/sqlEngine/executor/runSelect.js.map +1 -0
- package/dist/sqlEngine/expressions/compile.d.ts +24 -0
- package/dist/sqlEngine/expressions/compile.js +326 -0
- package/dist/sqlEngine/expressions/compile.js.map +1 -0
- package/dist/sqlEngine/functions/aggregates.d.ts +12 -0
- package/dist/sqlEngine/functions/aggregates.js +299 -0
- package/dist/sqlEngine/functions/aggregates.js.map +1 -0
- package/dist/sqlEngine/functions/registry.d.ts +36 -0
- package/dist/sqlEngine/functions/registry.js +33 -0
- package/dist/sqlEngine/functions/registry.js.map +1 -0
- package/dist/sqlEngine/functions/standard.d.ts +9 -0
- package/dist/sqlEngine/functions/standard.js +86 -0
- package/dist/sqlEngine/functions/standard.js.map +1 -0
- package/dist/sqlEngine/index.d.ts +29 -0
- package/dist/sqlEngine/index.js +62 -0
- package/dist/sqlEngine/index.js.map +1 -0
- package/dist/sqlEngine/logical/build.d.ts +20 -0
- package/dist/sqlEngine/logical/build.js +326 -0
- package/dist/sqlEngine/logical/build.js.map +1 -0
- package/dist/sqlEngine/logical/op.d.ts +105 -0
- package/dist/sqlEngine/logical/op.js +10 -0
- package/dist/sqlEngine/logical/op.js.map +1 -0
- package/dist/sqlEngine/optimizer/joinAnalysis.d.ts +37 -0
- package/dist/sqlEngine/optimizer/joinAnalysis.js +144 -0
- package/dist/sqlEngine/optimizer/joinAnalysis.js.map +1 -0
- package/dist/sqlEngine/optimizer/optimize.d.ts +13 -0
- package/dist/sqlEngine/optimizer/optimize.js +53 -0
- package/dist/sqlEngine/optimizer/optimize.js.map +1 -0
- package/dist/sqlEngine/optimizer/ruleEngine.d.ts +7 -0
- package/dist/sqlEngine/optimizer/ruleEngine.js +26 -0
- package/dist/sqlEngine/optimizer/ruleEngine.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/limitPushdown.d.ts +19 -0
- package/dist/sqlEngine/optimizer/rules/limitPushdown.js +55 -0
- package/dist/sqlEngine/optimizer/rules/limitPushdown.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/planJoins.d.ts +19 -0
- package/dist/sqlEngine/optimizer/rules/planJoins.js +62 -0
- package/dist/sqlEngine/optimizer/rules/planJoins.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/predicateNormalize.d.ts +18 -0
- package/dist/sqlEngine/optimizer/rules/predicateNormalize.js +80 -0
- package/dist/sqlEngine/optimizer/rules/predicateNormalize.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/predicatePushdown.d.ts +11 -0
- package/dist/sqlEngine/optimizer/rules/predicatePushdown.js +48 -0
- package/dist/sqlEngine/optimizer/rules/predicatePushdown.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/projectionPushdown.d.ts +23 -0
- package/dist/sqlEngine/optimizer/rules/projectionPushdown.js +160 -0
- package/dist/sqlEngine/optimizer/rules/projectionPushdown.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/sortFromIndex.d.ts +14 -0
- package/dist/sqlEngine/optimizer/rules/sortFromIndex.js +49 -0
- package/dist/sqlEngine/optimizer/rules/sortFromIndex.js.map +1 -0
- package/dist/sqlEngine/optimizer/rules/validateScannable.d.ts +15 -0
- package/dist/sqlEngine/optimizer/rules/validateScannable.js +60 -0
- package/dist/sqlEngine/optimizer/rules/validateScannable.js.map +1 -0
- package/dist/sqlEngine/optimizer/whereToConditions.d.ts +85 -0
- package/dist/sqlEngine/optimizer/whereToConditions.js +484 -0
- package/dist/sqlEngine/optimizer/whereToConditions.js.map +1 -0
- package/dist/sqlEngine/parser/ast.d.ts +139 -0
- package/dist/sqlEngine/parser/ast.js +10 -0
- package/dist/sqlEngine/parser/ast.js.map +1 -0
- package/dist/sqlEngine/parser/normalizer.d.ts +28 -0
- package/dist/sqlEngine/parser/normalizer.js +413 -0
- package/dist/sqlEngine/parser/normalizer.js.map +1 -0
- package/dist/sqlEngine/parser/parse.d.ts +14 -0
- package/dist/sqlEngine/parser/parse.js +20 -0
- package/dist/sqlEngine/parser/parse.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalDistinct.d.ts +9 -0
- package/dist/sqlEngine/physical/PhysicalDistinct.js +29 -0
- package/dist/sqlEngine/physical/PhysicalDistinct.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalFilter.d.ts +10 -0
- package/dist/sqlEngine/physical/PhysicalFilter.js +25 -0
- package/dist/sqlEngine/physical/PhysicalFilter.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalHashAggregate.d.ts +27 -0
- package/dist/sqlEngine/physical/PhysicalHashAggregate.js +100 -0
- package/dist/sqlEngine/physical/PhysicalHashAggregate.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalHashJoin.d.ts +29 -0
- package/dist/sqlEngine/physical/PhysicalHashJoin.js +93 -0
- package/dist/sqlEngine/physical/PhysicalHashJoin.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.d.ts +36 -0
- package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.js +78 -0
- package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalIndexScan.d.ts +22 -0
- package/dist/sqlEngine/physical/PhysicalIndexScan.js +77 -0
- package/dist/sqlEngine/physical/PhysicalIndexScan.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalLimit.d.ts +5 -0
- package/dist/sqlEngine/physical/PhysicalLimit.js +28 -0
- package/dist/sqlEngine/physical/PhysicalLimit.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.d.ts +20 -0
- package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.js +51 -0
- package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalProject.d.ts +18 -0
- package/dist/sqlEngine/physical/PhysicalProject.js +117 -0
- package/dist/sqlEngine/physical/PhysicalProject.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalQualify.d.ts +13 -0
- package/dist/sqlEngine/physical/PhysicalQualify.js +29 -0
- package/dist/sqlEngine/physical/PhysicalQualify.js.map +1 -0
- package/dist/sqlEngine/physical/PhysicalSort.d.ts +12 -0
- package/dist/sqlEngine/physical/PhysicalSort.js +59 -0
- package/dist/sqlEngine/physical/PhysicalSort.js.map +1 -0
- package/dist/sqlEngine/physical/op.d.ts +11 -0
- package/dist/sqlEngine/physical/op.js +9 -0
- package/dist/sqlEngine/physical/op.js.map +1 -0
- package/dist/sqlEngine/physical/plan.d.ts +23 -0
- package/dist/sqlEngine/physical/plan.js +162 -0
- package/dist/sqlEngine/physical/plan.js.map +1 -0
- package/dist/sqlEngine/router.d.ts +26 -0
- package/dist/sqlEngine/router.js +48 -0
- package/dist/sqlEngine/router.js.map +1 -0
- package/dist/sqlEngine/types.d.ts +37 -0
- package/dist/sqlEngine/types.js +13 -0
- package/dist/sqlEngine/types.js.map +1 -0
- package/dist/sqlTranslator/index.js +7 -1
- package/dist/sqlTranslator/index.js.map +1 -1
- package/dist/utility/common_utils.js +25 -0
- package/dist/utility/common_utils.js.map +1 -1
- package/dist/utility/install/installer.d.ts +9 -1
- package/dist/utility/install/installer.js +21 -0
- package/dist/utility/install/installer.js.map +1 -1
- package/dist/validation/configValidator.js +3 -0
- package/dist/validation/configValidator.js.map +1 -1
- package/dist/validation/deleteValidator.js +10 -2
- package/dist/validation/deleteValidator.js.map +1 -1
- package/npm-shrinkwrap.json +272 -230
- package/package.json +3 -3
- package/resources/DESIGN.md +17 -16
- package/resources/DatabaseTransaction.ts +95 -0
- package/resources/RequestTarget.ts +12 -3
- package/resources/Resource.ts +23 -2
- package/resources/Table.ts +57 -6
- package/resources/analytics/metadata.ts +3 -0
- package/resources/analytics/write.ts +23 -0
- package/resources/databases.ts +24 -0
- package/resources/defineResource.ts +17 -4
- package/resources/jsResource.ts +61 -2
- package/resources/openApi.ts +44 -19
- package/resources/scheduler/CronExpression.ts +394 -0
- package/resources/scheduler/engine.ts +812 -0
- package/resources/scheduler/scheduler.ts +236 -0
- package/security/auth.ts +1 -0
- package/security/jsLoader.ts +8 -0
- package/security/keys.ts +152 -0
- package/server/REST.ts +70 -1
- package/server/Server.ts +6 -0
- package/server/http.ts +122 -15
- package/server/operationsServer.ts +5 -3
- package/server/serverHelpers/progressEmitter.ts +5 -1
- package/server/threads/threadServer.js +9 -5
- package/sqlTranslator/index.ts +16 -6
- package/studio/web/assets/{Chat-CTjtL8Z4.js → Chat-DHP4XpID.js} +2 -2
- package/studio/web/assets/{Chat-CTjtL8Z4.js.map → Chat-DHP4XpID.js.map} +1 -1
- package/studio/web/assets/{FloatingChat-CafHR4Ur.js → FloatingChat-CJ7PssCv.js} +4 -4
- package/studio/web/assets/{FloatingChat-CafHR4Ur.js.map → FloatingChat-CJ7PssCv.js.map} +1 -1
- package/studio/web/assets/{applications-Buh_q0Vj.js → applications-DxXiGpsR.js} +2 -2
- package/studio/web/assets/{applications-Buh_q0Vj.js.map → applications-DxXiGpsR.js.map} +1 -1
- package/studio/web/assets/{index-0hXeECkS.js → index-BdbBanDP.js} +6 -6
- package/studio/web/assets/{index-0hXeECkS.js.map → index-BdbBanDP.js.map} +1 -1
- package/studio/web/assets/{index.lazy-B00B7VBT.js → index.lazy-B2eH28zD.js} +4 -4
- package/studio/web/assets/{index.lazy-B00B7VBT.js.map → index.lazy-B2eH28zD.js.map} +1 -1
- package/studio/web/assets/{profile-Cg2wwYPn.js → profile-DK5hgucv.js} +2 -2
- package/studio/web/assets/{profile-Cg2wwYPn.js.map → profile-DK5hgucv.js.map} +1 -1
- package/studio/web/assets/{setComponentFile-DCaDIvyB.js → setComponentFile-BVDWRYxx.js} +2 -2
- package/studio/web/assets/{setComponentFile-DCaDIvyB.js.map → setComponentFile-BVDWRYxx.js.map} +1 -1
- package/studio/web/assets/{setup-CAVcAQjK.js → setup-DJ9BInoK.js} +2 -2
- package/studio/web/assets/{setup-CAVcAQjK.js.map → setup-DJ9BInoK.js.map} +1 -1
- package/studio/web/assets/{status-BRXorNdD.js → status-B_qzmgfD.js} +2 -2
- package/studio/web/assets/{status-BRXorNdD.js.map → status-B_qzmgfD.js.map} +1 -1
- package/studio/web/assets/{swagger-ui-react-Dy1D62vO.js → swagger-ui-react-DOL5jCqg.js} +2 -2
- package/studio/web/assets/{swagger-ui-react-Dy1D62vO.js.map → swagger-ui-react-DOL5jCqg.js.map} +1 -1
- package/studio/web/assets/{tsMode-A8gbL74v.js → tsMode-DpxUxfTW.js} +2 -2
- package/studio/web/assets/{tsMode-A8gbL74v.js.map → tsMode-DpxUxfTW.js.map} +1 -1
- package/studio/web/assets/{useEntityRestURL-cDodrVcQ.js → useEntityRestURL-CU_lY6XW.js} +2 -2
- package/studio/web/assets/{useEntityRestURL-cDodrVcQ.js.map → useEntityRestURL-CU_lY6XW.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/utility/common_utils.ts +26 -0
- package/utility/install/installer.ts +26 -1
- package/validation/configValidator.ts +3 -0
- package/validation/deleteValidator.ts +11 -2
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logical operators.
|
|
3
|
+
*
|
|
4
|
+
* The logical plan is a tree of these nodes produced by logical/build.ts from
|
|
5
|
+
* the bound IR and rewritten by optimizer/rules/* before being lowered to a
|
|
6
|
+
* physical plan in physical/plan.ts.
|
|
7
|
+
*/
|
|
8
|
+
import type { ExprNode, ProjectionNode, SortNode, TableRefNode } from '../parser/ast.ts';
|
|
9
|
+
import type { BoundTable } from '../binder/bind.ts';
|
|
10
|
+
export type LogicalPlan = LogicalScan | LogicalFilter | LogicalProject | LogicalJoin | LogicalAggregate | LogicalSort | LogicalLimit | LogicalDistinct | LogicalInsert | LogicalUpdate | LogicalDelete;
|
|
11
|
+
export interface LogicalScan {
|
|
12
|
+
kind: 'Scan';
|
|
13
|
+
table: TableRefNode;
|
|
14
|
+
boundTable?: BoundTable;
|
|
15
|
+
/**
|
|
16
|
+
* Set in join queries: the canonical alias this scan's rows are qualified by
|
|
17
|
+
* (`<alias>.<attr>`). Undefined for single-table queries (bare-keyed rows).
|
|
18
|
+
*/
|
|
19
|
+
alias?: string;
|
|
20
|
+
pushedFilter?: ExprNode;
|
|
21
|
+
pushedSort?: SortNode[];
|
|
22
|
+
pushedLimit?: {
|
|
23
|
+
limit?: number;
|
|
24
|
+
offset?: number;
|
|
25
|
+
};
|
|
26
|
+
projection?: string[];
|
|
27
|
+
residualFilter?: ExprNode;
|
|
28
|
+
/**
|
|
29
|
+
* Set when this scan is the inner side of an index-nested-loop join: it is
|
|
30
|
+
* re-probed per outer row via an equality on `keyAttribute` (which must be
|
|
31
|
+
* indexed), so validateScannable treats it as index-served rather than a
|
|
32
|
+
* standalone full scan.
|
|
33
|
+
*/
|
|
34
|
+
joinProbe?: {
|
|
35
|
+
keyAttribute: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export interface LogicalFilter {
|
|
39
|
+
kind: 'Filter';
|
|
40
|
+
input: LogicalPlan;
|
|
41
|
+
predicate: ExprNode;
|
|
42
|
+
}
|
|
43
|
+
export interface LogicalProject {
|
|
44
|
+
kind: 'Project';
|
|
45
|
+
input: LogicalPlan;
|
|
46
|
+
projections: ProjectionNode[];
|
|
47
|
+
}
|
|
48
|
+
export interface LogicalJoin {
|
|
49
|
+
kind: 'Join';
|
|
50
|
+
left: LogicalPlan;
|
|
51
|
+
right: LogicalPlan;
|
|
52
|
+
on?: ExprNode;
|
|
53
|
+
type: 'inner' | 'left' | 'cross';
|
|
54
|
+
strategy?: 'relationship' | 'indexNL' | 'hash' | 'nestedLoop';
|
|
55
|
+
}
|
|
56
|
+
export interface LogicalAggregate {
|
|
57
|
+
kind: 'Aggregate';
|
|
58
|
+
input: LogicalPlan;
|
|
59
|
+
groupKeys: ExprNode[];
|
|
60
|
+
aggs: {
|
|
61
|
+
name: string;
|
|
62
|
+
arg: ExprNode | {
|
|
63
|
+
kind: 'star';
|
|
64
|
+
};
|
|
65
|
+
outputName: string;
|
|
66
|
+
distinct?: boolean;
|
|
67
|
+
}[];
|
|
68
|
+
having?: ExprNode;
|
|
69
|
+
}
|
|
70
|
+
export interface LogicalSort {
|
|
71
|
+
kind: 'Sort';
|
|
72
|
+
input: LogicalPlan;
|
|
73
|
+
keys: SortNode[];
|
|
74
|
+
}
|
|
75
|
+
export interface LogicalLimit {
|
|
76
|
+
kind: 'Limit';
|
|
77
|
+
input: LogicalPlan;
|
|
78
|
+
limit?: number;
|
|
79
|
+
offset?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface LogicalDistinct {
|
|
82
|
+
kind: 'Distinct';
|
|
83
|
+
input: LogicalPlan;
|
|
84
|
+
keys?: ExprNode[];
|
|
85
|
+
}
|
|
86
|
+
export interface LogicalInsert {
|
|
87
|
+
kind: 'Insert';
|
|
88
|
+
table: TableRefNode;
|
|
89
|
+
rows: ExprNode[][] | LogicalPlan;
|
|
90
|
+
columns: string[];
|
|
91
|
+
}
|
|
92
|
+
export interface LogicalUpdate {
|
|
93
|
+
kind: 'Update';
|
|
94
|
+
table: TableRefNode;
|
|
95
|
+
assignments: {
|
|
96
|
+
column: string;
|
|
97
|
+
expr: ExprNode;
|
|
98
|
+
}[];
|
|
99
|
+
selector: LogicalPlan;
|
|
100
|
+
}
|
|
101
|
+
export interface LogicalDelete {
|
|
102
|
+
kind: 'Delete';
|
|
103
|
+
table: TableRefNode;
|
|
104
|
+
selector: LogicalPlan;
|
|
105
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Logical operators.
|
|
4
|
+
*
|
|
5
|
+
* The logical plan is a tree of these nodes produced by logical/build.ts from
|
|
6
|
+
* the bound IR and rewritten by optimizer/rules/* before being lowered to a
|
|
7
|
+
* physical plan in physical/plan.ts.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
//# sourceMappingURL=op.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"op.js","sourceRoot":"","sources":["../../../sqlEngine/logical/op.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared analysis of a LogicalJoin's ON clause, used by both the join-strategy
|
|
3
|
+
* rule (optimizer/rules/planJoins.ts) and the physical planner (physical/plan).
|
|
4
|
+
*
|
|
5
|
+
* In a left-deep tree the right child is always a single base table (a Scan,
|
|
6
|
+
* optionally wrapped in a Filter for its own single-table WHERE conjuncts). We
|
|
7
|
+
* split the ON predicate into:
|
|
8
|
+
* - equi-pairs `outer = inner`, where `inner` references only the right
|
|
9
|
+
* table's alias and `outer` references only left-side aliases;
|
|
10
|
+
* - a residual predicate (non-equi conditions, or equalities that don't cleanly
|
|
11
|
+
* separate across the join boundary) applied on the merged row.
|
|
12
|
+
*/
|
|
13
|
+
import type { ExprNode } from '../parser/ast.ts';
|
|
14
|
+
import type { LogicalJoin, LogicalScan } from '../logical/op.ts';
|
|
15
|
+
export interface EquiPair {
|
|
16
|
+
outer: ExprNode;
|
|
17
|
+
inner: ExprNode;
|
|
18
|
+
}
|
|
19
|
+
export interface JoinAnalysis {
|
|
20
|
+
rightAlias: string;
|
|
21
|
+
rightScan: LogicalScan;
|
|
22
|
+
equiPairs: EquiPair[];
|
|
23
|
+
residualOn?: ExprNode;
|
|
24
|
+
}
|
|
25
|
+
/** Unwraps the right child to its base Scan (through any stacked Filters). */
|
|
26
|
+
export declare function rightBaseScan(join: LogicalJoin): LogicalScan | null;
|
|
27
|
+
export declare function analyzeJoin(join: LogicalJoin): JoinAnalysis | null;
|
|
28
|
+
/**
|
|
29
|
+
* Picks the equi-pair to drive an index-nested-loop probe: its inner operand is
|
|
30
|
+
* a plain column on the right table that is indexed. Returns null when no
|
|
31
|
+
* equi-pair qualifies (caller falls back to hash / nested-loop).
|
|
32
|
+
*/
|
|
33
|
+
export declare function pickIndexedProbe(analysis: JoinAnalysis): {
|
|
34
|
+
pair: EquiPair;
|
|
35
|
+
attribute: string;
|
|
36
|
+
} | null;
|
|
37
|
+
export declare function referencedAliases(expr: ExprNode, out?: Set<string>): Set<string>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared analysis of a LogicalJoin's ON clause, used by both the join-strategy
|
|
4
|
+
* rule (optimizer/rules/planJoins.ts) and the physical planner (physical/plan).
|
|
5
|
+
*
|
|
6
|
+
* In a left-deep tree the right child is always a single base table (a Scan,
|
|
7
|
+
* optionally wrapped in a Filter for its own single-table WHERE conjuncts). We
|
|
8
|
+
* split the ON predicate into:
|
|
9
|
+
* - equi-pairs `outer = inner`, where `inner` references only the right
|
|
10
|
+
* table's alias and `outer` references only left-side aliases;
|
|
11
|
+
* - a residual predicate (non-equi conditions, or equalities that don't cleanly
|
|
12
|
+
* separate across the join boundary) applied on the merged row.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.rightBaseScan = rightBaseScan;
|
|
16
|
+
exports.analyzeJoin = analyzeJoin;
|
|
17
|
+
exports.pickIndexedProbe = pickIndexedProbe;
|
|
18
|
+
exports.referencedAliases = referencedAliases;
|
|
19
|
+
/** Unwraps the right child to its base Scan (through any stacked Filters). */
|
|
20
|
+
function rightBaseScan(join) {
|
|
21
|
+
let node = join.right;
|
|
22
|
+
// Rules may layer more than one Filter; unwrap them all.
|
|
23
|
+
while (node.kind === 'Filter')
|
|
24
|
+
node = node.input;
|
|
25
|
+
return node.kind === 'Scan' ? node : null;
|
|
26
|
+
}
|
|
27
|
+
function analyzeJoin(join) {
|
|
28
|
+
const rightScan = rightBaseScan(join);
|
|
29
|
+
if (!rightScan || !rightScan.alias)
|
|
30
|
+
return null;
|
|
31
|
+
const rightAlias = rightScan.alias;
|
|
32
|
+
const equiPairs = [];
|
|
33
|
+
const residuals = [];
|
|
34
|
+
for (const conjunct of flattenAnd(join.on)) {
|
|
35
|
+
const pair = asEquiPair(conjunct, rightAlias);
|
|
36
|
+
if (pair)
|
|
37
|
+
equiPairs.push(pair);
|
|
38
|
+
else
|
|
39
|
+
residuals.push(conjunct);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
rightAlias,
|
|
43
|
+
rightScan,
|
|
44
|
+
equiPairs,
|
|
45
|
+
residualOn: residuals.length > 0 ? andAll(residuals) : undefined,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Picks the equi-pair to drive an index-nested-loop probe: its inner operand is
|
|
50
|
+
* a plain column on the right table that is indexed. Returns null when no
|
|
51
|
+
* equi-pair qualifies (caller falls back to hash / nested-loop).
|
|
52
|
+
*/
|
|
53
|
+
function pickIndexedProbe(analysis) {
|
|
54
|
+
const attrs = analysis.rightScan.boundTable?.attributes ?? [];
|
|
55
|
+
for (const pair of analysis.equiPairs) {
|
|
56
|
+
if (pair.inner.kind === 'column' && pair.inner.table === analysis.rightAlias) {
|
|
57
|
+
const attr = attrs.find((a) => a.name === pair.inner.name);
|
|
58
|
+
if (attr?.indexed)
|
|
59
|
+
return { pair, attribute: pair.inner.name };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function asEquiPair(expr, rightAlias) {
|
|
65
|
+
if (expr.kind !== 'binop' || expr.op !== '=')
|
|
66
|
+
return null;
|
|
67
|
+
const leftAliases = referencedAliases(expr.left);
|
|
68
|
+
const rightAliases = referencedAliases(expr.right);
|
|
69
|
+
// One operand must reference only the right table; the other only left-side
|
|
70
|
+
// table(s) (and at least one — a literal isn't a join key).
|
|
71
|
+
if (onlyAlias(rightAliases, rightAlias) && leftAliases.size > 0 && !leftAliases.has(rightAlias)) {
|
|
72
|
+
return { outer: expr.left, inner: expr.right };
|
|
73
|
+
}
|
|
74
|
+
if (onlyAlias(leftAliases, rightAlias) && rightAliases.size > 0 && !rightAliases.has(rightAlias)) {
|
|
75
|
+
return { outer: expr.right, inner: expr.left };
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function onlyAlias(aliases, alias) {
|
|
80
|
+
return aliases.size === 1 && aliases.has(alias);
|
|
81
|
+
}
|
|
82
|
+
function flattenAnd(expr) {
|
|
83
|
+
if (!expr)
|
|
84
|
+
return [];
|
|
85
|
+
if (expr.kind === 'logical' && expr.op === 'and')
|
|
86
|
+
return expr.args.flatMap(flattenAnd);
|
|
87
|
+
return [expr];
|
|
88
|
+
}
|
|
89
|
+
function andAll(exprs) {
|
|
90
|
+
return exprs.length === 1 ? exprs[0] : { kind: 'logical', op: 'and', args: exprs };
|
|
91
|
+
}
|
|
92
|
+
function referencedAliases(expr, out = new Set()) {
|
|
93
|
+
switch (expr.kind) {
|
|
94
|
+
case 'column':
|
|
95
|
+
if (expr.table)
|
|
96
|
+
out.add(expr.table);
|
|
97
|
+
return out;
|
|
98
|
+
case 'binop':
|
|
99
|
+
referencedAliases(expr.left, out);
|
|
100
|
+
referencedAliases(expr.right, out);
|
|
101
|
+
return out;
|
|
102
|
+
case 'logical':
|
|
103
|
+
expr.args.forEach((a) => referencedAliases(a, out));
|
|
104
|
+
return out;
|
|
105
|
+
case 'in':
|
|
106
|
+
referencedAliases(expr.expr, out);
|
|
107
|
+
if (Array.isArray(expr.list))
|
|
108
|
+
expr.list.forEach((e) => referencedAliases(e, out));
|
|
109
|
+
return out;
|
|
110
|
+
case 'between':
|
|
111
|
+
referencedAliases(expr.expr, out);
|
|
112
|
+
referencedAliases(expr.low, out);
|
|
113
|
+
referencedAliases(expr.high, out);
|
|
114
|
+
return out;
|
|
115
|
+
case 'like':
|
|
116
|
+
referencedAliases(expr.expr, out);
|
|
117
|
+
referencedAliases(expr.pattern, out);
|
|
118
|
+
return out;
|
|
119
|
+
case 'isNull':
|
|
120
|
+
referencedAliases(expr.expr, out);
|
|
121
|
+
return out;
|
|
122
|
+
case 'funcCall':
|
|
123
|
+
expr.args.forEach((a) => referencedAliases(a, out));
|
|
124
|
+
return out;
|
|
125
|
+
case 'aggCall':
|
|
126
|
+
if (expr.arg.kind !== 'star')
|
|
127
|
+
referencedAliases(expr.arg, out);
|
|
128
|
+
return out;
|
|
129
|
+
case 'case':
|
|
130
|
+
for (const c of expr.cases) {
|
|
131
|
+
referencedAliases(c.when, out);
|
|
132
|
+
referencedAliases(c.then, out);
|
|
133
|
+
}
|
|
134
|
+
if (expr.else)
|
|
135
|
+
referencedAliases(expr.else, out);
|
|
136
|
+
return out;
|
|
137
|
+
case 'cast':
|
|
138
|
+
referencedAliases(expr.expr, out);
|
|
139
|
+
return out;
|
|
140
|
+
default:
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=joinAnalysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joinAnalysis.js","sourceRoot":"","sources":["../../../sqlEngine/optimizer/joinAnalysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Driver for phase-1 optimizer rules.
|
|
3
|
+
*
|
|
4
|
+
* The order here matters: predicate normalization happens first so other
|
|
5
|
+
* rules see the canonical form; predicate pushdown then lifts the predicate
|
|
6
|
+
* into the scan; sort-from-index inspects the bound table's index list to
|
|
7
|
+
* decide whether the sort can be served by Table.search; limit pushdown
|
|
8
|
+
* finally folds limit/offset into the scan; projection pushdown computes the
|
|
9
|
+
* minimal attribute set; validateScannable enforces "no full scan without
|
|
10
|
+
* opt-in".
|
|
11
|
+
*/
|
|
12
|
+
import type { LogicalPlan } from '../logical/op.ts';
|
|
13
|
+
export declare function optimize(plan: LogicalPlan): LogicalPlan;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Driver for phase-1 optimizer rules.
|
|
4
|
+
*
|
|
5
|
+
* The order here matters: predicate normalization happens first so other
|
|
6
|
+
* rules see the canonical form; predicate pushdown then lifts the predicate
|
|
7
|
+
* into the scan; sort-from-index inspects the bound table's index list to
|
|
8
|
+
* decide whether the sort can be served by Table.search; limit pushdown
|
|
9
|
+
* finally folds limit/offset into the scan; projection pushdown computes the
|
|
10
|
+
* minimal attribute set; validateScannable enforces "no full scan without
|
|
11
|
+
* opt-in".
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.optimize = optimize;
|
|
15
|
+
const ruleEngine_ts_1 = require("./ruleEngine.js");
|
|
16
|
+
const predicatePushdown_ts_1 = require("./rules/predicatePushdown.js");
|
|
17
|
+
const limitPushdown_ts_1 = require("./rules/limitPushdown.js");
|
|
18
|
+
const sortFromIndex_ts_1 = require("./rules/sortFromIndex.js");
|
|
19
|
+
const projectionPushdown_ts_1 = require("./rules/projectionPushdown.js");
|
|
20
|
+
const validateScannable_ts_1 = require("./rules/validateScannable.js");
|
|
21
|
+
const predicateNormalize_ts_1 = require("./rules/predicateNormalize.js");
|
|
22
|
+
const planJoins_ts_1 = require("./rules/planJoins.js");
|
|
23
|
+
function normalizePredicates(plan) {
|
|
24
|
+
switch (plan.kind) {
|
|
25
|
+
case 'Filter':
|
|
26
|
+
return {
|
|
27
|
+
...plan,
|
|
28
|
+
predicate: (0, predicateNormalize_ts_1.normalizePredicate)(plan.predicate),
|
|
29
|
+
input: normalizePredicates(plan.input) ?? plan.input,
|
|
30
|
+
};
|
|
31
|
+
case 'Scan':
|
|
32
|
+
return plan.pushedFilter ? { ...plan, pushedFilter: (0, predicateNormalize_ts_1.normalizePredicate)(plan.pushedFilter) } : plan;
|
|
33
|
+
case 'Join':
|
|
34
|
+
return {
|
|
35
|
+
...plan,
|
|
36
|
+
on: plan.on ? (0, predicateNormalize_ts_1.normalizePredicate)(plan.on) : plan.on,
|
|
37
|
+
left: normalizePredicates(plan.left) ?? plan.left,
|
|
38
|
+
right: normalizePredicates(plan.right) ?? plan.right,
|
|
39
|
+
};
|
|
40
|
+
default:
|
|
41
|
+
if ('input' in plan) {
|
|
42
|
+
return { ...plan, input: normalizePredicates(plan.input) ?? plan.input };
|
|
43
|
+
}
|
|
44
|
+
return plan;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function optimize(plan) {
|
|
48
|
+
const rules = [normalizePredicates, predicatePushdown_ts_1.predicatePushdown, sortFromIndex_ts_1.sortFromIndex, limitPushdown_ts_1.limitPushdown, projectionPushdown_ts_1.projectionPushdown, planJoins_ts_1.planJoins];
|
|
49
|
+
const optimized = (0, ruleEngine_ts_1.applyRules)(plan, rules);
|
|
50
|
+
(0, validateScannable_ts_1.validateScannable)(optimized);
|
|
51
|
+
return optimized;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=optimize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../sqlEngine/optimizer/optimize.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAqCH,4BAKC;AAvCD,mDAA6C;AAC7C,uEAAiE;AACjE,+DAAyD;AACzD,+DAAyD;AACzD,yEAAmE;AACnE,uEAAiE;AACjE,yEAAmE;AACnE,uDAAiD;AAEjD,SAAS,mBAAmB,CAAC,IAAiB;IAC7C,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,QAAQ;YACZ,OAAO;gBACN,GAAG,IAAI;gBACP,SAAS,EAAE,IAAA,0CAAkB,EAAC,IAAI,CAAC,SAAS,CAAC;gBAC7C,KAAK,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK;aACpD,CAAC;QACH,KAAK,MAAM;YACV,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,IAAA,0CAAkB,EAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACpG,KAAK,MAAM;YACV,OAAO;gBACN,GAAG,IAAI;gBACP,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,0CAAkB,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;gBACnD,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;gBACjD,KAAK,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK;aACpD,CAAC;QACH;YACC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACrB,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1E,CAAC;YACD,OAAO,IAAI,CAAC;IACd,CAAC;AACF,CAAC;AAED,SAAgB,QAAQ,CAAC,IAAiB;IACzC,MAAM,KAAK,GAAG,CAAC,mBAAmB,EAAE,wCAAiB,EAAE,gCAAa,EAAE,gCAAa,EAAE,0CAAkB,EAAE,wBAAS,CAAC,CAAC;IACpH,MAAM,SAAS,GAAG,IAAA,0BAAU,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAA,wCAAiB,EAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,SAAS,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed-point rule engine. Phase 0 scaffold; rules under rules/ are added in
|
|
3
|
+
* phase 1+.
|
|
4
|
+
*/
|
|
5
|
+
import type { LogicalPlan } from '../logical/op.ts';
|
|
6
|
+
export type Rule = (plan: LogicalPlan) => LogicalPlan | null;
|
|
7
|
+
export declare function applyRules(plan: LogicalPlan, rules: Rule[]): LogicalPlan;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fixed-point rule engine. Phase 0 scaffold; rules under rules/ are added in
|
|
4
|
+
* phase 1+.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.applyRules = applyRules;
|
|
8
|
+
function applyRules(plan, rules) {
|
|
9
|
+
let current = plan;
|
|
10
|
+
let changed = true;
|
|
11
|
+
let iterations = 0;
|
|
12
|
+
const MAX_ITERATIONS = 32;
|
|
13
|
+
while (changed && iterations < MAX_ITERATIONS) {
|
|
14
|
+
changed = false;
|
|
15
|
+
iterations++;
|
|
16
|
+
for (const rule of rules) {
|
|
17
|
+
const next = rule(current);
|
|
18
|
+
if (next && next !== current) {
|
|
19
|
+
current = next;
|
|
20
|
+
changed = true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return current;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ruleEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruleEngine.js","sourceRoot":"","sources":["../../../sqlEngine/optimizer/ruleEngine.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAMH,gCAiBC;AAjBD,SAAgB,UAAU,CAAC,IAAiB,EAAE,KAAa;IAC1D,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,cAAc,GAAG,EAAE,CAAC;IAC1B,OAAO,OAAO,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;QAC/C,OAAO,GAAG,KAAK,CAAC;QAChB,UAAU,EAAE,CAAC;QACb,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,IAAI,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9B,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,GAAG,IAAI,CAAC;YAChB,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule R5: limit pushdown.
|
|
3
|
+
*
|
|
4
|
+
* If a Limit sits directly on top of a Scan (with optional Project/Sort that
|
|
5
|
+
* preserve cardinality through-pushdown), push the limit/offset into the
|
|
6
|
+
* Scan so Table.search returns only what we need.
|
|
7
|
+
*
|
|
8
|
+
* For phase 1 we push through Project unconditionally (a plain projection
|
|
9
|
+
* preserves cardinality) and through Sort only when the Sort itself is
|
|
10
|
+
* pushed into the scan (sortFromIndex rule has done that work).
|
|
11
|
+
*
|
|
12
|
+
* A limit is pushed into a Scan only when the scan carries no residual: if
|
|
13
|
+
* part of the WHERE lowers to a post-scan PhysicalFilter (whereToConditions
|
|
14
|
+
* residual, or an explicit residualFilter), Table.search would cap rows
|
|
15
|
+
* *before* that filter runs and silently under-fetch. In that case the Limit
|
|
16
|
+
* node is left above the residual filter.
|
|
17
|
+
*/
|
|
18
|
+
import type { LogicalPlan } from '../../logical/op.ts';
|
|
19
|
+
export declare function limitPushdown(plan: LogicalPlan): LogicalPlan | null;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Rule R5: limit pushdown.
|
|
4
|
+
*
|
|
5
|
+
* If a Limit sits directly on top of a Scan (with optional Project/Sort that
|
|
6
|
+
* preserve cardinality through-pushdown), push the limit/offset into the
|
|
7
|
+
* Scan so Table.search returns only what we need.
|
|
8
|
+
*
|
|
9
|
+
* For phase 1 we push through Project unconditionally (a plain projection
|
|
10
|
+
* preserves cardinality) and through Sort only when the Sort itself is
|
|
11
|
+
* pushed into the scan (sortFromIndex rule has done that work).
|
|
12
|
+
*
|
|
13
|
+
* A limit is pushed into a Scan only when the scan carries no residual: if
|
|
14
|
+
* part of the WHERE lowers to a post-scan PhysicalFilter (whereToConditions
|
|
15
|
+
* residual, or an explicit residualFilter), Table.search would cap rows
|
|
16
|
+
* *before* that filter runs and silently under-fetch. In that case the Limit
|
|
17
|
+
* node is left above the residual filter.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.limitPushdown = limitPushdown;
|
|
21
|
+
const whereToConditions_ts_1 = require("../whereToConditions.js");
|
|
22
|
+
function limitPushdown(plan) {
|
|
23
|
+
return rewrite(plan);
|
|
24
|
+
}
|
|
25
|
+
function scanHasResidual(scan) {
|
|
26
|
+
if (scan.residualFilter)
|
|
27
|
+
return true;
|
|
28
|
+
return (0, whereToConditions_ts_1.whereToConditions)(scan.pushedFilter, scan.boundTable?.attributes).residual !== undefined;
|
|
29
|
+
}
|
|
30
|
+
function rewrite(plan) {
|
|
31
|
+
switch (plan.kind) {
|
|
32
|
+
case 'Limit': {
|
|
33
|
+
const child = rewrite(plan.input);
|
|
34
|
+
if (child.kind === 'Scan' && !child.pushedLimit && !scanHasResidual(child)) {
|
|
35
|
+
return { ...child, pushedLimit: { limit: plan.limit, offset: plan.offset } };
|
|
36
|
+
}
|
|
37
|
+
if (child.kind === 'Project') {
|
|
38
|
+
const sub = rewrite({ ...plan, input: child.input });
|
|
39
|
+
return { ...child, input: sub };
|
|
40
|
+
}
|
|
41
|
+
return { ...plan, input: child };
|
|
42
|
+
}
|
|
43
|
+
case 'Project':
|
|
44
|
+
return { ...plan, input: rewrite(plan.input) };
|
|
45
|
+
case 'Sort':
|
|
46
|
+
return { ...plan, input: rewrite(plan.input) };
|
|
47
|
+
case 'Filter':
|
|
48
|
+
return { ...plan, input: rewrite(plan.input) };
|
|
49
|
+
case 'Distinct':
|
|
50
|
+
return { ...plan, input: rewrite(plan.input) };
|
|
51
|
+
default:
|
|
52
|
+
return plan;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=limitPushdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limitPushdown.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/limitPushdown.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;AAKH,sCAEC;AAJD,kEAA4D;AAE5D,SAAgB,aAAa,CAAC,IAAiB;IAC9C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,eAAe,CAAC,IAAiB;IACzC,IAAI,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,IAAA,wCAAiB,EAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC;AACjG,CAAC;AAED,SAAS,OAAO,CAAC,IAAiB;IACjC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,OAAO,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5E,OAAO,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9E,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAgB,CAAC;gBACpE,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;YACjC,CAAC;YACD,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;QACD,KAAK,SAAS;YACb,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,MAAM;YACV,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,QAAQ;YACZ,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,UAAU;YACd,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD;YACC,OAAO,IAAI,CAAC;IACd,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Join-strategy rule.
|
|
3
|
+
*
|
|
4
|
+
* Sets `LogicalJoin.strategy` and, for index-nested-loop joins, marks the inner
|
|
5
|
+
* scan with `joinProbe` so validateScannable accepts it (it is served by an
|
|
6
|
+
* indexed equality probe, not a standalone full scan).
|
|
7
|
+
*
|
|
8
|
+
* Strategy choice:
|
|
9
|
+
* - `indexNL` — equi-join whose inner join key is an indexed column. The
|
|
10
|
+
* inner table is probed once per outer row; no full scan.
|
|
11
|
+
* - `hash` — equi-join without an indexed inner key. Reads the whole
|
|
12
|
+
* inner side (allowed only if the inner scan is otherwise
|
|
13
|
+
* index-served by its own WHERE, or allowFullScan is on).
|
|
14
|
+
* - `nestedLoop` — CROSS joins and non-equi ON predicates.
|
|
15
|
+
*
|
|
16
|
+
* (`relationship` — the declared-relationship fast path — is a later addition.)
|
|
17
|
+
*/
|
|
18
|
+
import type { LogicalPlan } from '../../logical/op.ts';
|
|
19
|
+
export declare function planJoins(plan: LogicalPlan): LogicalPlan | null;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Join-strategy rule.
|
|
4
|
+
*
|
|
5
|
+
* Sets `LogicalJoin.strategy` and, for index-nested-loop joins, marks the inner
|
|
6
|
+
* scan with `joinProbe` so validateScannable accepts it (it is served by an
|
|
7
|
+
* indexed equality probe, not a standalone full scan).
|
|
8
|
+
*
|
|
9
|
+
* Strategy choice:
|
|
10
|
+
* - `indexNL` — equi-join whose inner join key is an indexed column. The
|
|
11
|
+
* inner table is probed once per outer row; no full scan.
|
|
12
|
+
* - `hash` — equi-join without an indexed inner key. Reads the whole
|
|
13
|
+
* inner side (allowed only if the inner scan is otherwise
|
|
14
|
+
* index-served by its own WHERE, or allowFullScan is on).
|
|
15
|
+
* - `nestedLoop` — CROSS joins and non-equi ON predicates.
|
|
16
|
+
*
|
|
17
|
+
* (`relationship` — the declared-relationship fast path — is a later addition.)
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.planJoins = planJoins;
|
|
21
|
+
const joinAnalysis_ts_1 = require("../joinAnalysis.js");
|
|
22
|
+
function planJoins(plan) {
|
|
23
|
+
let mutated = false;
|
|
24
|
+
function walk(node) {
|
|
25
|
+
switch (node.kind) {
|
|
26
|
+
case 'Join': {
|
|
27
|
+
const left = walk(node.left);
|
|
28
|
+
const right = walk(node.right);
|
|
29
|
+
const next = { ...node, left, right };
|
|
30
|
+
if (!next.strategy) {
|
|
31
|
+
assignStrategy(next);
|
|
32
|
+
mutated = true;
|
|
33
|
+
}
|
|
34
|
+
return next;
|
|
35
|
+
}
|
|
36
|
+
default:
|
|
37
|
+
if ('input' in node) {
|
|
38
|
+
const input = walk(node.input);
|
|
39
|
+
return input === node.input ? node : { ...node, input };
|
|
40
|
+
}
|
|
41
|
+
return node;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const result = walk(plan);
|
|
45
|
+
return mutated ? result : null;
|
|
46
|
+
}
|
|
47
|
+
function assignStrategy(join) {
|
|
48
|
+
const analysis = (0, joinAnalysis_ts_1.analyzeJoin)(join);
|
|
49
|
+
if (!analysis || analysis.equiPairs.length === 0) {
|
|
50
|
+
join.strategy = 'nestedLoop';
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const probe = (0, joinAnalysis_ts_1.pickIndexedProbe)(analysis);
|
|
54
|
+
if (probe) {
|
|
55
|
+
join.strategy = 'indexNL';
|
|
56
|
+
analysis.rightScan.joinProbe = { keyAttribute: probe.attribute };
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
join.strategy = 'hash';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=planJoins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planJoins.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/planJoins.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;AAKH,8BA0BC;AA5BD,wDAAmE;AAEnE,SAAgB,SAAS,CAAC,IAAiB;IAC1C,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,SAAS,IAAI,CAAC,IAAiB;QAC9B,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,CAAC,CAAC;gBACb,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC/B,MAAM,IAAI,GAAgB,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;gBACnD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACpB,cAAc,CAAC,IAAI,CAAC,CAAC;oBACrB,OAAO,GAAG,IAAI,CAAC;gBAChB,CAAC;gBACD,OAAO,IAAI,CAAC;YACb,CAAC;YACD;gBACC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;oBACrB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC/B,OAAO,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC;gBACzD,CAAC;gBACD,OAAO,IAAI,CAAC;QACd,CAAC;IACF,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC;AAED,SAAS,cAAc,CAAC,IAAiB;IACxC,MAAM,QAAQ,GAAG,IAAA,6BAAW,EAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC;QAC7B,OAAO;IACR,CAAC;IACD,MAAM,KAAK,GAAG,IAAA,kCAAgB,EAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,KAAK,EAAE,CAAC;QACX,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,QAAQ,CAAC,SAAS,CAAC,SAAS,GAAG,EAAE,YAAY,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;IAClE,CAAC;SAAM,CAAC;QACP,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;IACxB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule R3: predicate normalization.
|
|
3
|
+
*
|
|
4
|
+
* Maps AlaSQL operator forms to a canonical shape ahead of pushdown:
|
|
5
|
+
* - LIKE 'foo%' -> starts_with(foo)
|
|
6
|
+
* - LIKE '%foo' -> ends_with(foo)
|
|
7
|
+
* - LIKE '%foo%' -> contains(foo)
|
|
8
|
+
* - BETWEEN a AND b -> binop chain (col >= a AND col <= b) with semantic
|
|
9
|
+
* hint kept via marker for the pushdown rule
|
|
10
|
+
* - NOT (a > b) -> a <= b (NULL semantics preserved by leaving NOT in
|
|
11
|
+
* place when the operand is anything other than a
|
|
12
|
+
* comparable binop on a single column ref)
|
|
13
|
+
* - IS NULL / IS NOT NULL: left as-is (rule output for downstream).
|
|
14
|
+
*
|
|
15
|
+
* No change-of-meaning rewrites at this stage; the rule is conservative.
|
|
16
|
+
*/
|
|
17
|
+
import type { ExprNode } from '../../parser/ast.ts';
|
|
18
|
+
export declare function normalizePredicate(expr: ExprNode): ExprNode;
|