metal-orm 1.0.8 → 1.0.9
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/README.md +12 -1
- package/dist/decorators/index.cjs +2564 -0
- package/dist/decorators/index.cjs.map +1 -0
- package/dist/decorators/index.d.cts +53 -0
- package/dist/decorators/index.d.ts +53 -0
- package/dist/decorators/index.js +2530 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/index.cjs +4227 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +701 -0
- package/dist/index.d.ts +701 -0
- package/dist/index.js +4131 -0
- package/dist/index.js.map +1 -0
- package/dist/select-654m4qy8.d.cts +1522 -0
- package/dist/select-654m4qy8.d.ts +1522 -0
- package/package.json +27 -20
- package/src/codegen/typescript.ts +405 -393
- package/src/core/ast/aggregate-functions.ts +30 -0
- package/src/core/ast/builders.ts +43 -0
- package/src/core/ast/expression-builders.ts +310 -0
- package/src/core/ast/expression-nodes.ts +211 -0
- package/src/core/ast/expression-visitor.ts +99 -0
- package/src/core/ast/expression.ts +5 -0
- package/src/{utils → core/ast}/join-node.ts +20 -20
- package/src/{ast → core/ast}/join.ts +18 -18
- package/src/{ast → core/ast}/query.ts +113 -113
- package/src/core/ast/window-functions.ts +140 -0
- package/src/{dialect → core/dialect}/abstract.ts +94 -94
- package/src/{dialect → core/dialect}/mssql/index.ts +31 -31
- package/src/{dialect → core/dialect}/mysql/index.ts +31 -31
- package/src/{dialect → core/dialect}/postgres/index.ts +45 -45
- package/src/{dialect → core/dialect}/sqlite/index.ts +45 -45
- package/src/{constants → core/sql}/sql-operator-config.ts +39 -39
- package/src/decorators/bootstrap.ts +126 -0
- package/src/decorators/column.ts +78 -0
- package/src/decorators/entity.ts +36 -0
- package/src/decorators/index.ts +4 -0
- package/src/decorators/relations.ts +107 -0
- package/src/global.d.ts +1 -0
- package/src/index.ts +22 -22
- package/src/orm/db-executor.ts +11 -0
- package/src/orm/domain-event-bus.ts +52 -0
- package/src/{runtime → orm}/entity-meta.ts +52 -52
- package/src/orm/entity-metadata.ts +140 -0
- package/src/{runtime → orm}/entity.ts +252 -252
- package/src/{runtime → orm}/execute.ts +36 -36
- package/src/{runtime → orm}/hydration.ts +103 -103
- package/src/orm/identity-map.ts +37 -0
- package/src/{runtime → orm}/lazy-batch.ts +205 -205
- package/src/orm/orm-context.ts +154 -0
- package/src/orm/relation-change-processor.ts +140 -0
- package/src/{runtime → orm}/relations/belongs-to.ts +92 -92
- package/src/{runtime → orm}/relations/has-many.ts +111 -111
- package/src/{runtime → orm}/relations/many-to-many.ts +149 -149
- package/src/orm/runtime-types.ts +39 -0
- package/src/orm/transaction-runner.ts +17 -0
- package/src/orm/unit-of-work.ts +232 -0
- package/src/{builder/operations → query-builder}/column-selector.ts +78 -78
- package/src/{builder → query-builder}/delete-query-state.ts +38 -42
- package/src/{builder → query-builder}/delete.ts +46 -57
- package/src/{builder → query-builder}/hydration-manager.ts +87 -87
- package/src/{builder → query-builder}/hydration-planner.ts +182 -182
- package/src/{builder → query-builder}/insert-query-state.ts +51 -62
- package/src/{builder → query-builder}/insert.ts +48 -59
- package/src/{builder → query-builder}/query-ast-service.ts +208 -226
- package/src/{utils → query-builder}/raw-column-parser.ts +32 -32
- package/src/{builder → query-builder}/relation-conditions.ts +112 -112
- package/src/{builder/operations → query-builder}/relation-manager.ts +82 -82
- package/src/{builder → query-builder}/relation-projection-helper.ts +101 -101
- package/src/{builder → query-builder}/relation-service.ts +284 -284
- package/src/{builder → query-builder}/relation-types.ts +21 -21
- package/src/{builder → query-builder}/relation-utils.ts +12 -12
- package/src/{builder → query-builder}/select-query-builder-deps.ts +112 -94
- package/src/{builder → query-builder}/select-query-state.ts +179 -179
- package/src/{builder → query-builder}/select.ts +78 -69
- package/src/{builder → query-builder}/update-query-state.ts +55 -59
- package/src/{builder → query-builder}/update.ts +50 -61
- package/src/schema/column.ts +25 -25
- package/src/schema/relation.ts +116 -116
- package/src/schema/table.ts +34 -34
- package/src/schema/types.ts +76 -76
- package/.github/workflows/publish-metal-orm.yml +0 -38
- package/ROADMAP.md +0 -125
- package/docs/CHANGES.md +0 -104
- package/docs/advanced-features.md +0 -176
- package/docs/api-reference.md +0 -31
- package/docs/dml-operations.md +0 -156
- package/docs/getting-started.md +0 -171
- package/docs/hydration.md +0 -115
- package/docs/index.md +0 -36
- package/docs/multi-dialect-support.md +0 -59
- package/docs/query-builder.md +0 -135
- package/docs/runtime.md +0 -105
- package/docs/schema-definition.md +0 -112
- package/metadata.json +0 -5
- package/playground/api/playground-api.ts +0 -94
- package/playground/index.html +0 -15
- package/playground/src/App.css +0 -1
- package/playground/src/App.tsx +0 -114
- package/playground/src/components/CodeDisplay.tsx +0 -43
- package/playground/src/components/QueryExecutor.tsx +0 -189
- package/playground/src/components/ResultsTable.tsx +0 -67
- package/playground/src/components/ResultsTabs.tsx +0 -105
- package/playground/src/components/ScenarioList.tsx +0 -56
- package/playground/src/components/logo.svg +0 -45
- package/playground/src/data/scenarios.ts +0 -2
- package/playground/src/main.tsx +0 -9
- package/playground/src/services/PlaygroundApiService.ts +0 -60
- package/postcss.config.cjs +0 -5
- package/sql_sql-ansi-cheatsheet-2025.md +0 -264
- package/src/ast/expression.ts +0 -658
- package/src/builder/operations/cte-manager.ts +0 -34
- package/src/builder/operations/filter-manager.ts +0 -68
- package/src/builder/operations/join-manager.ts +0 -36
- package/src/builder/operations/pagination-manager.ts +0 -36
- package/src/playground/features/playground/api/types.ts +0 -16
- package/src/playground/features/playground/clients/MockClient.ts +0 -17
- package/src/playground/features/playground/clients/SqliteClient.ts +0 -57
- package/src/playground/features/playground/common/IDatabaseClient.ts +0 -10
- package/src/playground/features/playground/data/scenarios/aggregation.ts +0 -36
- package/src/playground/features/playground/data/scenarios/basics.ts +0 -25
- package/src/playground/features/playground/data/scenarios/edge_cases.ts +0 -57
- package/src/playground/features/playground/data/scenarios/filtering.ts +0 -94
- package/src/playground/features/playground/data/scenarios/hydration.ts +0 -27
- package/src/playground/features/playground/data/scenarios/index.ts +0 -29
- package/src/playground/features/playground/data/scenarios/ordering.ts +0 -25
- package/src/playground/features/playground/data/scenarios/pagination.ts +0 -16
- package/src/playground/features/playground/data/scenarios/relationships.ts +0 -75
- package/src/playground/features/playground/data/scenarios/types.ts +0 -70
- package/src/playground/features/playground/data/schema.ts +0 -91
- package/src/playground/features/playground/data/seed.ts +0 -104
- package/src/playground/features/playground/services/QueryExecutionService.ts +0 -121
- package/src/runtime/orm-context.ts +0 -539
- package/tests/belongs-to-many.test.ts +0 -57
- package/tests/between.test.ts +0 -43
- package/tests/case-expression.test.ts +0 -58
- package/tests/complex-exists.test.ts +0 -230
- package/tests/cte.test.ts +0 -118
- package/tests/dml.test.ts +0 -206
- package/tests/exists.test.ts +0 -127
- package/tests/like.test.ts +0 -33
- package/tests/orm-runtime.test.ts +0 -254
- package/tests/postgres.test.ts +0 -30
- package/tests/right-join.test.ts +0 -89
- package/tests/subquery-having.test.ts +0 -193
- package/tests/window-function.test.ts +0 -151
- package/tsconfig.json +0 -30
- package/tsup.config.ts +0 -10
- package/vite.config.ts +0 -22
- package/vitest.config.ts +0 -14
- /package/src/{constants → core/sql}/sql.ts +0 -0
- /package/src/{runtime → orm}/als.ts +0 -0
- /package/src/{utils → query-builder}/relation-alias.ts +0 -0
|
@@ -1,94 +1,112 @@
|
|
|
1
|
-
import { TableDef } from '../schema/table';
|
|
2
|
-
import { SelectQueryState } from './select-query-state';
|
|
3
|
-
import { HydrationManager } from './hydration-manager';
|
|
4
|
-
import { HydrationPlanner } from './hydration-planner';
|
|
5
|
-
import { QueryAstService } from './query-ast-service';
|
|
6
|
-
import { RelationService } from './relation-service';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Context for query building operations
|
|
10
|
-
*/
|
|
11
|
-
export interface SelectQueryBuilderContext {
|
|
12
|
-
/**
|
|
13
|
-
* Current query state
|
|
14
|
-
*/
|
|
15
|
-
readonly state: SelectQueryState;
|
|
16
|
-
/**
|
|
17
|
-
* Hydration manager for the query
|
|
18
|
-
*/
|
|
19
|
-
readonly hydration: HydrationManager;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Dependencies for query builder operations
|
|
24
|
-
*/
|
|
25
|
-
export interface SelectQueryBuilderDependencies {
|
|
26
|
-
/**
|
|
27
|
-
* Creates a new query state
|
|
28
|
-
* @param table - Table definition
|
|
29
|
-
* @returns New query state
|
|
30
|
-
*/
|
|
31
|
-
createState: (table: TableDef) => SelectQueryState;
|
|
32
|
-
/**
|
|
33
|
-
* Creates a new hydration manager
|
|
34
|
-
* @param table - Table definition
|
|
35
|
-
* @returns New hydration manager
|
|
36
|
-
*/
|
|
37
|
-
createHydration: (table: TableDef) => HydrationManager;
|
|
38
|
-
/**
|
|
39
|
-
* Creates a new hydration planner
|
|
40
|
-
* @param table - Table definition
|
|
41
|
-
* @returns Hydration planner
|
|
42
|
-
*/
|
|
43
|
-
createHydrationPlanner: (table: TableDef) => HydrationPlanner;
|
|
44
|
-
/**
|
|
45
|
-
* Creates a new query AST service
|
|
46
|
-
* @param table - Table definition
|
|
47
|
-
* @param state - Query state
|
|
48
|
-
* @returns New query AST service
|
|
49
|
-
*/
|
|
50
|
-
createQueryAstService: (table: TableDef, state: SelectQueryState) => QueryAstService;
|
|
51
|
-
/**
|
|
52
|
-
* Creates a new relation service
|
|
53
|
-
* @param table - Table definition
|
|
54
|
-
* @param state - Query state
|
|
55
|
-
* @param hydration - Hydration manager
|
|
56
|
-
* @returns New relation service
|
|
57
|
-
*/
|
|
58
|
-
createRelationService: (
|
|
59
|
-
table: TableDef,
|
|
60
|
-
state: SelectQueryState,
|
|
61
|
-
hydration: HydrationManager
|
|
62
|
-
) => RelationService;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Environment for query builder operations
|
|
67
|
-
*/
|
|
68
|
-
export interface SelectQueryBuilderEnvironment {
|
|
69
|
-
/**
|
|
70
|
-
* Table definition
|
|
71
|
-
*/
|
|
72
|
-
readonly table: TableDef;
|
|
73
|
-
/**
|
|
74
|
-
* Query builder dependencies
|
|
75
|
-
*/
|
|
76
|
-
readonly deps: SelectQueryBuilderDependencies;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Default
|
|
81
|
-
*/
|
|
82
|
-
const defaultCreateQueryAstService = (table: TableDef, state: SelectQueryState) => new QueryAstService(table, state);
|
|
83
|
-
const defaultCreateHydrationPlanner = (table: TableDef) => new HydrationPlanner(table);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
1
|
+
import { TableDef } from '../schema/table.js';
|
|
2
|
+
import { SelectQueryState } from './select-query-state.js';
|
|
3
|
+
import { HydrationManager } from './hydration-manager.js';
|
|
4
|
+
import { HydrationPlanner } from './hydration-planner.js';
|
|
5
|
+
import { QueryAstService } from './query-ast-service.js';
|
|
6
|
+
import { RelationService } from './relation-service.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Context for query building operations
|
|
10
|
+
*/
|
|
11
|
+
export interface SelectQueryBuilderContext {
|
|
12
|
+
/**
|
|
13
|
+
* Current query state
|
|
14
|
+
*/
|
|
15
|
+
readonly state: SelectQueryState;
|
|
16
|
+
/**
|
|
17
|
+
* Hydration manager for the query
|
|
18
|
+
*/
|
|
19
|
+
readonly hydration: HydrationManager;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Dependencies for query builder operations
|
|
24
|
+
*/
|
|
25
|
+
export interface SelectQueryBuilderDependencies {
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new query state
|
|
28
|
+
* @param table - Table definition
|
|
29
|
+
* @returns New query state
|
|
30
|
+
*/
|
|
31
|
+
createState: (table: TableDef) => SelectQueryState;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new hydration manager
|
|
34
|
+
* @param table - Table definition
|
|
35
|
+
* @returns New hydration manager
|
|
36
|
+
*/
|
|
37
|
+
createHydration: (table: TableDef) => HydrationManager;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new hydration planner
|
|
40
|
+
* @param table - Table definition
|
|
41
|
+
* @returns Hydration planner
|
|
42
|
+
*/
|
|
43
|
+
createHydrationPlanner: (table: TableDef) => HydrationPlanner;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new query AST service
|
|
46
|
+
* @param table - Table definition
|
|
47
|
+
* @param state - Query state
|
|
48
|
+
* @returns New query AST service
|
|
49
|
+
*/
|
|
50
|
+
createQueryAstService: (table: TableDef, state: SelectQueryState) => QueryAstService;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new relation service
|
|
53
|
+
* @param table - Table definition
|
|
54
|
+
* @param state - Query state
|
|
55
|
+
* @param hydration - Hydration manager
|
|
56
|
+
* @returns New relation service
|
|
57
|
+
*/
|
|
58
|
+
createRelationService: (
|
|
59
|
+
table: TableDef,
|
|
60
|
+
state: SelectQueryState,
|
|
61
|
+
hydration: HydrationManager
|
|
62
|
+
) => RelationService;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Environment for query builder operations
|
|
67
|
+
*/
|
|
68
|
+
export interface SelectQueryBuilderEnvironment {
|
|
69
|
+
/**
|
|
70
|
+
* Table definition
|
|
71
|
+
*/
|
|
72
|
+
readonly table: TableDef;
|
|
73
|
+
/**
|
|
74
|
+
* Query builder dependencies
|
|
75
|
+
*/
|
|
76
|
+
readonly deps: SelectQueryBuilderDependencies;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Default implementations for query builder dependencies
|
|
81
|
+
*/
|
|
82
|
+
const defaultCreateQueryAstService = (table: TableDef, state: SelectQueryState) => new QueryAstService(table, state);
|
|
83
|
+
const defaultCreateHydrationPlanner = (table: TableDef) => new HydrationPlanner(table);
|
|
84
|
+
|
|
85
|
+
const defaultCreateHydration = (table: TableDef, plannerFactory: (table: TableDef) => HydrationPlanner) =>
|
|
86
|
+
new HydrationManager(table, plannerFactory(table));
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Resolves query builder dependencies by merging overrides with internal defaults
|
|
90
|
+
* @param overrides - Partial overrides for dependency factories
|
|
91
|
+
*/
|
|
92
|
+
export const resolveSelectQueryBuilderDependencies = (
|
|
93
|
+
overrides: Partial<SelectQueryBuilderDependencies> = {}
|
|
94
|
+
): SelectQueryBuilderDependencies => {
|
|
95
|
+
const createQueryAstService = overrides.createQueryAstService ?? defaultCreateQueryAstService;
|
|
96
|
+
const createHydrationPlanner = overrides.createHydrationPlanner ?? defaultCreateHydrationPlanner;
|
|
97
|
+
const createHydration =
|
|
98
|
+
overrides.createHydration ?? (table => defaultCreateHydration(table, createHydrationPlanner));
|
|
99
|
+
const createRelationService =
|
|
100
|
+
overrides.createRelationService ??
|
|
101
|
+
((table, state, hydration) => new RelationService(table, state, hydration, createQueryAstService));
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
createState: overrides.createState ?? (table => new SelectQueryState(table)),
|
|
105
|
+
createHydration,
|
|
106
|
+
createHydrationPlanner,
|
|
107
|
+
createQueryAstService,
|
|
108
|
+
createRelationService
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const defaultSelectQueryBuilderDependencies = resolveSelectQueryBuilderDependencies();
|
|
@@ -1,179 +1,179 @@
|
|
|
1
|
-
import { TableDef } from '../schema/table';
|
|
2
|
-
import { SelectQueryNode, CommonTableExpressionNode, OrderByNode } from '../ast/query';
|
|
3
|
-
import {
|
|
4
|
-
ColumnNode,
|
|
5
|
-
ExpressionNode,
|
|
6
|
-
FunctionNode,
|
|
7
|
-
ScalarSubqueryNode,
|
|
8
|
-
CaseExpressionNode,
|
|
9
|
-
WindowFunctionNode
|
|
10
|
-
} from '../ast/expression';
|
|
11
|
-
import { JoinNode } from '../ast/join';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Node types that can be used in query projections
|
|
15
|
-
*/
|
|
16
|
-
export type ProjectionNode =
|
|
17
|
-
| ColumnNode
|
|
18
|
-
| FunctionNode
|
|
19
|
-
| ScalarSubqueryNode
|
|
20
|
-
| CaseExpressionNode
|
|
21
|
-
| WindowFunctionNode;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Manages the state of a SELECT query being built
|
|
25
|
-
*/
|
|
26
|
-
export class SelectQueryState {
|
|
27
|
-
/**
|
|
28
|
-
* Table definition for the query
|
|
29
|
-
*/
|
|
30
|
-
public readonly table: TableDef;
|
|
31
|
-
/**
|
|
32
|
-
* Abstract Syntax Tree (AST) representation of the query
|
|
33
|
-
*/
|
|
34
|
-
public readonly ast: SelectQueryNode;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Creates a new SelectQueryState instance
|
|
38
|
-
* @param table - Table definition
|
|
39
|
-
* @param ast - Optional existing AST
|
|
40
|
-
*/
|
|
41
|
-
constructor(table: TableDef, ast?: SelectQueryNode) {
|
|
42
|
-
this.table = table;
|
|
43
|
-
this.ast = ast ?? {
|
|
44
|
-
type: 'SelectQuery',
|
|
45
|
-
from: { type: 'Table', name: table.name },
|
|
46
|
-
columns: [],
|
|
47
|
-
joins: []
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Creates a new SelectQueryState with updated AST
|
|
53
|
-
* @param nextAst - Updated AST
|
|
54
|
-
* @returns New SelectQueryState instance
|
|
55
|
-
*/
|
|
56
|
-
private clone(nextAst: SelectQueryNode): SelectQueryState {
|
|
57
|
-
return new SelectQueryState(this.table, nextAst);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Adds columns to the query
|
|
62
|
-
* @param newCols - Columns to add
|
|
63
|
-
* @returns New SelectQueryState with added columns
|
|
64
|
-
*/
|
|
65
|
-
withColumns(newCols: ProjectionNode[]): SelectQueryState {
|
|
66
|
-
return this.clone({
|
|
67
|
-
...this.ast,
|
|
68
|
-
columns: [...(this.ast.columns ?? []), ...newCols]
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Adds a join to the query
|
|
74
|
-
* @param join - Join node to add
|
|
75
|
-
* @returns New SelectQueryState with added join
|
|
76
|
-
*/
|
|
77
|
-
withJoin(join: JoinNode): SelectQueryState {
|
|
78
|
-
return this.clone({
|
|
79
|
-
...this.ast,
|
|
80
|
-
joins: [...(this.ast.joins ?? []), join]
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Adds a WHERE clause to the query
|
|
86
|
-
* @param predicate - WHERE predicate expression
|
|
87
|
-
* @returns New SelectQueryState with WHERE clause
|
|
88
|
-
*/
|
|
89
|
-
withWhere(predicate: ExpressionNode): SelectQueryState {
|
|
90
|
-
return this.clone({
|
|
91
|
-
...this.ast,
|
|
92
|
-
where: predicate
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Adds a HAVING clause to the query
|
|
98
|
-
* @param predicate - HAVING predicate expression
|
|
99
|
-
* @returns New SelectQueryState with HAVING clause
|
|
100
|
-
*/
|
|
101
|
-
withHaving(predicate: ExpressionNode): SelectQueryState {
|
|
102
|
-
return this.clone({
|
|
103
|
-
...this.ast,
|
|
104
|
-
having: predicate
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Adds GROUP BY columns to the query
|
|
110
|
-
* @param columns - Columns to group by
|
|
111
|
-
* @returns New SelectQueryState with GROUP BY clause
|
|
112
|
-
*/
|
|
113
|
-
withGroupBy(columns: ColumnNode[]): SelectQueryState {
|
|
114
|
-
return this.clone({
|
|
115
|
-
...this.ast,
|
|
116
|
-
groupBy: [...(this.ast.groupBy ?? []), ...columns]
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Adds ORDER BY clauses to the query
|
|
122
|
-
* @param orderBy - ORDER BY nodes
|
|
123
|
-
* @returns New SelectQueryState with ORDER BY clause
|
|
124
|
-
*/
|
|
125
|
-
withOrderBy(orderBy: OrderByNode[]): SelectQueryState {
|
|
126
|
-
return this.clone({
|
|
127
|
-
...this.ast,
|
|
128
|
-
orderBy: [...(this.ast.orderBy ?? []), ...orderBy]
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Adds DISTINCT columns to the query
|
|
134
|
-
* @param columns - Columns to make distinct
|
|
135
|
-
* @returns New SelectQueryState with DISTINCT clause
|
|
136
|
-
*/
|
|
137
|
-
withDistinct(columns: ColumnNode[]): SelectQueryState {
|
|
138
|
-
return this.clone({
|
|
139
|
-
...this.ast,
|
|
140
|
-
distinct: [...(this.ast.distinct ?? []), ...columns]
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Adds a LIMIT clause to the query
|
|
146
|
-
* @param limit - Maximum number of rows to return
|
|
147
|
-
* @returns New SelectQueryState with LIMIT clause
|
|
148
|
-
*/
|
|
149
|
-
withLimit(limit: number): SelectQueryState {
|
|
150
|
-
return this.clone({
|
|
151
|
-
...this.ast,
|
|
152
|
-
limit
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Adds an OFFSET clause to the query
|
|
158
|
-
* @param offset - Number of rows to skip
|
|
159
|
-
* @returns New SelectQueryState with OFFSET clause
|
|
160
|
-
*/
|
|
161
|
-
withOffset(offset: number): SelectQueryState {
|
|
162
|
-
return this.clone({
|
|
163
|
-
...this.ast,
|
|
164
|
-
offset
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Adds a Common Table Expression (CTE) to the query
|
|
170
|
-
* @param cte - CTE node to add
|
|
171
|
-
* @returns New SelectQueryState with CTE
|
|
172
|
-
*/
|
|
173
|
-
withCte(cte: CommonTableExpressionNode): SelectQueryState {
|
|
174
|
-
return this.clone({
|
|
175
|
-
...this.ast,
|
|
176
|
-
ctes: [...(this.ast.ctes ?? []), cte]
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
1
|
+
import { TableDef } from '../schema/table.js';
|
|
2
|
+
import { SelectQueryNode, CommonTableExpressionNode, OrderByNode } from '../core/ast/query.js';
|
|
3
|
+
import {
|
|
4
|
+
ColumnNode,
|
|
5
|
+
ExpressionNode,
|
|
6
|
+
FunctionNode,
|
|
7
|
+
ScalarSubqueryNode,
|
|
8
|
+
CaseExpressionNode,
|
|
9
|
+
WindowFunctionNode
|
|
10
|
+
} from '../core/ast/expression.js';
|
|
11
|
+
import { JoinNode } from '../core/ast/join.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Node types that can be used in query projections
|
|
15
|
+
*/
|
|
16
|
+
export type ProjectionNode =
|
|
17
|
+
| ColumnNode
|
|
18
|
+
| FunctionNode
|
|
19
|
+
| ScalarSubqueryNode
|
|
20
|
+
| CaseExpressionNode
|
|
21
|
+
| WindowFunctionNode;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Manages the state of a SELECT query being built
|
|
25
|
+
*/
|
|
26
|
+
export class SelectQueryState {
|
|
27
|
+
/**
|
|
28
|
+
* Table definition for the query
|
|
29
|
+
*/
|
|
30
|
+
public readonly table: TableDef;
|
|
31
|
+
/**
|
|
32
|
+
* Abstract Syntax Tree (AST) representation of the query
|
|
33
|
+
*/
|
|
34
|
+
public readonly ast: SelectQueryNode;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new SelectQueryState instance
|
|
38
|
+
* @param table - Table definition
|
|
39
|
+
* @param ast - Optional existing AST
|
|
40
|
+
*/
|
|
41
|
+
constructor(table: TableDef, ast?: SelectQueryNode) {
|
|
42
|
+
this.table = table;
|
|
43
|
+
this.ast = ast ?? {
|
|
44
|
+
type: 'SelectQuery',
|
|
45
|
+
from: { type: 'Table', name: table.name },
|
|
46
|
+
columns: [],
|
|
47
|
+
joins: []
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new SelectQueryState with updated AST
|
|
53
|
+
* @param nextAst - Updated AST
|
|
54
|
+
* @returns New SelectQueryState instance
|
|
55
|
+
*/
|
|
56
|
+
private clone(nextAst: SelectQueryNode): SelectQueryState {
|
|
57
|
+
return new SelectQueryState(this.table, nextAst);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Adds columns to the query
|
|
62
|
+
* @param newCols - Columns to add
|
|
63
|
+
* @returns New SelectQueryState with added columns
|
|
64
|
+
*/
|
|
65
|
+
withColumns(newCols: ProjectionNode[]): SelectQueryState {
|
|
66
|
+
return this.clone({
|
|
67
|
+
...this.ast,
|
|
68
|
+
columns: [...(this.ast.columns ?? []), ...newCols]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Adds a join to the query
|
|
74
|
+
* @param join - Join node to add
|
|
75
|
+
* @returns New SelectQueryState with added join
|
|
76
|
+
*/
|
|
77
|
+
withJoin(join: JoinNode): SelectQueryState {
|
|
78
|
+
return this.clone({
|
|
79
|
+
...this.ast,
|
|
80
|
+
joins: [...(this.ast.joins ?? []), join]
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Adds a WHERE clause to the query
|
|
86
|
+
* @param predicate - WHERE predicate expression
|
|
87
|
+
* @returns New SelectQueryState with WHERE clause
|
|
88
|
+
*/
|
|
89
|
+
withWhere(predicate: ExpressionNode): SelectQueryState {
|
|
90
|
+
return this.clone({
|
|
91
|
+
...this.ast,
|
|
92
|
+
where: predicate
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Adds a HAVING clause to the query
|
|
98
|
+
* @param predicate - HAVING predicate expression
|
|
99
|
+
* @returns New SelectQueryState with HAVING clause
|
|
100
|
+
*/
|
|
101
|
+
withHaving(predicate: ExpressionNode): SelectQueryState {
|
|
102
|
+
return this.clone({
|
|
103
|
+
...this.ast,
|
|
104
|
+
having: predicate
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Adds GROUP BY columns to the query
|
|
110
|
+
* @param columns - Columns to group by
|
|
111
|
+
* @returns New SelectQueryState with GROUP BY clause
|
|
112
|
+
*/
|
|
113
|
+
withGroupBy(columns: ColumnNode[]): SelectQueryState {
|
|
114
|
+
return this.clone({
|
|
115
|
+
...this.ast,
|
|
116
|
+
groupBy: [...(this.ast.groupBy ?? []), ...columns]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Adds ORDER BY clauses to the query
|
|
122
|
+
* @param orderBy - ORDER BY nodes
|
|
123
|
+
* @returns New SelectQueryState with ORDER BY clause
|
|
124
|
+
*/
|
|
125
|
+
withOrderBy(orderBy: OrderByNode[]): SelectQueryState {
|
|
126
|
+
return this.clone({
|
|
127
|
+
...this.ast,
|
|
128
|
+
orderBy: [...(this.ast.orderBy ?? []), ...orderBy]
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Adds DISTINCT columns to the query
|
|
134
|
+
* @param columns - Columns to make distinct
|
|
135
|
+
* @returns New SelectQueryState with DISTINCT clause
|
|
136
|
+
*/
|
|
137
|
+
withDistinct(columns: ColumnNode[]): SelectQueryState {
|
|
138
|
+
return this.clone({
|
|
139
|
+
...this.ast,
|
|
140
|
+
distinct: [...(this.ast.distinct ?? []), ...columns]
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Adds a LIMIT clause to the query
|
|
146
|
+
* @param limit - Maximum number of rows to return
|
|
147
|
+
* @returns New SelectQueryState with LIMIT clause
|
|
148
|
+
*/
|
|
149
|
+
withLimit(limit: number): SelectQueryState {
|
|
150
|
+
return this.clone({
|
|
151
|
+
...this.ast,
|
|
152
|
+
limit
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Adds an OFFSET clause to the query
|
|
158
|
+
* @param offset - Number of rows to skip
|
|
159
|
+
* @returns New SelectQueryState with OFFSET clause
|
|
160
|
+
*/
|
|
161
|
+
withOffset(offset: number): SelectQueryState {
|
|
162
|
+
return this.clone({
|
|
163
|
+
...this.ast,
|
|
164
|
+
offset
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Adds a Common Table Expression (CTE) to the query
|
|
170
|
+
* @param cte - CTE node to add
|
|
171
|
+
* @returns New SelectQueryState with CTE
|
|
172
|
+
*/
|
|
173
|
+
withCte(cte: CommonTableExpressionNode): SelectQueryState {
|
|
174
|
+
return this.clone({
|
|
175
|
+
...this.ast,
|
|
176
|
+
ctes: [...(this.ast.ctes ?? []), cte]
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|