metal-orm 1.0.39 → 1.0.41
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/index.cjs +1466 -189
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +723 -51
- package/dist/index.d.ts +723 -51
- package/dist/index.js +1457 -189
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen/typescript.ts +66 -5
- package/src/core/ast/aggregate-functions.ts +15 -15
- package/src/core/ast/expression-builders.ts +378 -316
- package/src/core/ast/expression-nodes.ts +210 -186
- package/src/core/ast/expression-visitor.ts +40 -30
- package/src/core/ast/query.ts +164 -132
- package/src/core/ast/window-functions.ts +86 -86
- package/src/core/dialect/abstract.ts +509 -479
- package/src/core/dialect/base/groupby-compiler.ts +6 -6
- package/src/core/dialect/base/join-compiler.ts +9 -12
- package/src/core/dialect/base/orderby-compiler.ts +20 -6
- package/src/core/dialect/base/sql-dialect.ts +237 -138
- package/src/core/dialect/mssql/index.ts +164 -185
- package/src/core/dialect/sqlite/index.ts +39 -34
- package/src/core/execution/db-executor.ts +46 -6
- package/src/core/execution/executors/mssql-executor.ts +39 -22
- package/src/core/execution/executors/mysql-executor.ts +23 -6
- package/src/core/execution/executors/sqlite-executor.ts +29 -3
- package/src/core/execution/pooling/pool-types.ts +30 -0
- package/src/core/execution/pooling/pool.ts +268 -0
- package/src/core/functions/standard-strategy.ts +46 -37
- package/src/decorators/bootstrap.ts +7 -7
- package/src/index.ts +6 -0
- package/src/orm/domain-event-bus.ts +49 -0
- package/src/orm/entity-metadata.ts +9 -9
- package/src/orm/entity.ts +58 -0
- package/src/orm/orm-session.ts +465 -270
- package/src/orm/orm.ts +61 -11
- package/src/orm/pooled-executor-factory.ts +131 -0
- package/src/orm/query-logger.ts +6 -12
- package/src/orm/relation-change-processor.ts +75 -0
- package/src/orm/relations/many-to-many.ts +4 -2
- package/src/orm/save-graph.ts +303 -0
- package/src/orm/transaction-runner.ts +3 -3
- package/src/orm/unit-of-work.ts +128 -0
- package/src/query-builder/delete-query-state.ts +67 -38
- package/src/query-builder/delete.ts +37 -1
- package/src/query-builder/hydration-manager.ts +93 -79
- package/src/query-builder/insert-query-state.ts +131 -61
- package/src/query-builder/insert.ts +27 -1
- package/src/query-builder/query-ast-service.ts +207 -170
- package/src/query-builder/select-query-state.ts +169 -162
- package/src/query-builder/select.ts +15 -23
- package/src/query-builder/update-query-state.ts +114 -77
- package/src/query-builder/update.ts +38 -1
|
@@ -1,52 +1,61 @@
|
|
|
1
|
-
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import { ColumnDef } from '../schema/column.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
|
|
1
|
+
import { TableDef } from '../schema/table.js';
|
|
2
|
+
import { ColumnDef } from '../schema/column.js';
|
|
3
|
+
import {
|
|
4
|
+
SelectQueryNode,
|
|
5
|
+
CommonTableExpressionNode,
|
|
6
|
+
SetOperationKind,
|
|
7
|
+
SetOperationNode,
|
|
8
|
+
TableSourceNode,
|
|
9
|
+
OrderingTerm
|
|
10
|
+
} from '../core/ast/query.js';
|
|
11
|
+
import { buildColumnNode } from '../core/ast/builders.js';
|
|
12
|
+
import {
|
|
13
|
+
AliasRefNode,
|
|
14
|
+
ColumnNode,
|
|
15
|
+
ExpressionNode,
|
|
16
|
+
FunctionNode,
|
|
17
|
+
CaseExpressionNode,
|
|
18
|
+
WindowFunctionNode,
|
|
19
|
+
ScalarSubqueryNode,
|
|
20
|
+
and,
|
|
21
|
+
isExpressionSelectionNode,
|
|
22
|
+
isOperandNode
|
|
23
|
+
} from '../core/ast/expression.js';
|
|
24
|
+
import { JoinNode } from '../core/ast/join.js';
|
|
25
|
+
import { SelectQueryState, ProjectionNode } from './select-query-state.js';
|
|
26
|
+
import { OrderDirection } from '../core/sql/sql.js';
|
|
27
|
+
import { parseRawColumn } from './raw-column-parser.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Result of column selection operation
|
|
31
|
+
*/
|
|
32
|
+
export interface ColumnSelectionResult {
|
|
33
|
+
/**
|
|
34
|
+
* Updated query state
|
|
35
|
+
*/
|
|
36
|
+
state: SelectQueryState;
|
|
37
|
+
/**
|
|
38
|
+
* Columns that were added
|
|
39
|
+
*/
|
|
40
|
+
addedColumns: ProjectionNode[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Service for manipulating query AST (Abstract Syntax Tree)
|
|
45
|
+
*/
|
|
46
|
+
export class QueryAstService {
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new QueryAstService instance
|
|
49
|
+
* @param table - Table definition
|
|
50
|
+
* @param state - Current query state
|
|
51
|
+
*/
|
|
52
|
+
constructor(private readonly table: TableDef, private readonly state: SelectQueryState) {}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Selects columns for the query
|
|
56
|
+
* @param columns - Columns to select (key: alias, value: column definition or expression)
|
|
57
|
+
* @returns Column selection result with updated state and added columns
|
|
58
|
+
*/
|
|
50
59
|
select(
|
|
51
60
|
columns: Record<string, ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode>
|
|
52
61
|
): ColumnSelectionResult {
|
|
@@ -77,16 +86,16 @@ export class QueryAstService {
|
|
|
77
86
|
} as ColumnNode);
|
|
78
87
|
return acc;
|
|
79
88
|
}, []);
|
|
80
|
-
|
|
81
|
-
const nextState = this.state.withColumns(newCols);
|
|
82
|
-
return { state: nextState, addedColumns: newCols };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Selects raw column expressions (best-effort parser for simple references/functions)
|
|
87
|
-
* @param cols - Raw column expressions
|
|
88
|
-
* @returns Column selection result with updated state and added columns
|
|
89
|
-
*/
|
|
89
|
+
|
|
90
|
+
const nextState = this.state.withColumns(newCols);
|
|
91
|
+
return { state: nextState, addedColumns: newCols };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Selects raw column expressions (best-effort parser for simple references/functions)
|
|
96
|
+
* @param cols - Raw column expressions
|
|
97
|
+
* @returns Column selection result with updated state and added columns
|
|
98
|
+
*/
|
|
90
99
|
selectRaw(cols: string[]): ColumnSelectionResult {
|
|
91
100
|
const from = this.state.ast.from;
|
|
92
101
|
const defaultTable = from.type === 'Table' && from.alias ? from.alias : this.table.name;
|
|
@@ -94,15 +103,15 @@ export class QueryAstService {
|
|
|
94
103
|
const nextState = this.state.withColumns(newCols);
|
|
95
104
|
return { state: nextState, addedColumns: newCols };
|
|
96
105
|
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Adds a Common Table Expression (CTE) to the query
|
|
100
|
-
* @param name - Name of the CTE
|
|
101
|
-
* @param query - Query for the CTE
|
|
102
|
-
* @param columns - Optional column names for the CTE
|
|
103
|
-
* @param recursive - Whether the CTE is recursive
|
|
104
|
-
* @returns Updated query state with CTE
|
|
105
|
-
*/
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Adds a Common Table Expression (CTE) to the query
|
|
109
|
+
* @param name - Name of the CTE
|
|
110
|
+
* @param query - Query for the CTE
|
|
111
|
+
* @param columns - Optional column names for the CTE
|
|
112
|
+
* @param recursive - Whether the CTE is recursive
|
|
113
|
+
* @returns Updated query state with CTE
|
|
114
|
+
*/
|
|
106
115
|
withCte(name: string, query: SelectQueryNode, columns?: string[], recursive = false): SelectQueryState {
|
|
107
116
|
const cte: CommonTableExpressionNode = {
|
|
108
117
|
type: 'CommonTableExpression',
|
|
@@ -138,107 +147,135 @@ export class QueryAstService {
|
|
|
138
147
|
withFrom(from: TableSourceNode): SelectQueryState {
|
|
139
148
|
return this.state.withFrom(from);
|
|
140
149
|
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Selects a subquery as a column
|
|
144
|
-
* @param alias - Alias for the subquery
|
|
145
|
-
* @param query - Subquery to select
|
|
146
|
-
* @returns Updated query state with subquery selection
|
|
147
|
-
*/
|
|
148
|
-
selectSubquery(alias: string, query: SelectQueryNode): SelectQueryState {
|
|
149
|
-
const node: ScalarSubqueryNode = { type: 'ScalarSubquery', query, alias };
|
|
150
|
-
return this.state.withColumns([node]);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Adds a JOIN clause to the query
|
|
155
|
-
* @param join - Join node to add
|
|
156
|
-
* @returns Updated query state with JOIN
|
|
157
|
-
*/
|
|
158
|
-
withJoin(join: JoinNode): SelectQueryState {
|
|
159
|
-
return this.state.withJoin(join);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Adds a WHERE clause to the query
|
|
164
|
-
* @param expr - Expression for the WHERE clause
|
|
165
|
-
* @returns Updated query state with WHERE clause
|
|
166
|
-
*/
|
|
167
|
-
withWhere(expr: ExpressionNode): SelectQueryState {
|
|
168
|
-
const combined = this.combineExpressions(this.state.ast.where, expr);
|
|
169
|
-
return this.state.withWhere(combined);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Adds a GROUP BY clause to the query
|
|
174
|
-
* @param col - Column to group by
|
|
175
|
-
* @returns Updated query state with GROUP BY clause
|
|
176
|
-
*/
|
|
177
|
-
withGroupBy(col: ColumnDef |
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
*
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
*
|
|
196
|
-
* @
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Selects a subquery as a column
|
|
153
|
+
* @param alias - Alias for the subquery
|
|
154
|
+
* @param query - Subquery to select
|
|
155
|
+
* @returns Updated query state with subquery selection
|
|
156
|
+
*/
|
|
157
|
+
selectSubquery(alias: string, query: SelectQueryNode): SelectQueryState {
|
|
158
|
+
const node: ScalarSubqueryNode = { type: 'ScalarSubquery', query, alias };
|
|
159
|
+
return this.state.withColumns([node]);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Adds a JOIN clause to the query
|
|
164
|
+
* @param join - Join node to add
|
|
165
|
+
* @returns Updated query state with JOIN
|
|
166
|
+
*/
|
|
167
|
+
withJoin(join: JoinNode): SelectQueryState {
|
|
168
|
+
return this.state.withJoin(join);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Adds a WHERE clause to the query
|
|
173
|
+
* @param expr - Expression for the WHERE clause
|
|
174
|
+
* @returns Updated query state with WHERE clause
|
|
175
|
+
*/
|
|
176
|
+
withWhere(expr: ExpressionNode): SelectQueryState {
|
|
177
|
+
const combined = this.combineExpressions(this.state.ast.where, expr);
|
|
178
|
+
return this.state.withWhere(combined);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Adds a GROUP BY clause to the query
|
|
183
|
+
* @param col - Column to group by
|
|
184
|
+
* @returns Updated query state with GROUP BY clause
|
|
185
|
+
*/
|
|
186
|
+
withGroupBy(col: ColumnDef | OrderingTerm): SelectQueryState {
|
|
187
|
+
const term = this.normalizeOrderingTerm(col);
|
|
188
|
+
return this.state.withGroupBy([term]);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Adds a HAVING clause to the query
|
|
193
|
+
* @param expr - Expression for the HAVING clause
|
|
194
|
+
* @returns Updated query state with HAVING clause
|
|
195
|
+
*/
|
|
196
|
+
withHaving(expr: ExpressionNode): SelectQueryState {
|
|
197
|
+
const combined = this.combineExpressions(this.state.ast.having, expr);
|
|
198
|
+
return this.state.withHaving(combined);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Adds an ORDER BY clause to the query
|
|
203
|
+
* @param col - Column to order by
|
|
204
|
+
* @param direction - Order direction (ASC/DESC)
|
|
205
|
+
* @returns Updated query state with ORDER BY clause
|
|
206
|
+
*/
|
|
207
|
+
withOrderBy(
|
|
208
|
+
term: ColumnDef | OrderingTerm,
|
|
209
|
+
direction: OrderDirection,
|
|
210
|
+
nulls?: 'FIRST' | 'LAST',
|
|
211
|
+
collation?: string
|
|
212
|
+
): SelectQueryState {
|
|
213
|
+
const normalized = this.normalizeOrderingTerm(term);
|
|
214
|
+
return this.state.withOrderBy([{ type: 'OrderBy', term: normalized, direction, nulls, collation }]);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Adds a DISTINCT clause to the query
|
|
219
|
+
* @param cols - Columns to make distinct
|
|
220
|
+
* @returns Updated query state with DISTINCT clause
|
|
221
|
+
*/
|
|
222
|
+
withDistinct(cols: ColumnNode[]): SelectQueryState {
|
|
223
|
+
return this.state.withDistinct(cols);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Adds a LIMIT clause to the query
|
|
228
|
+
* @param limit - Maximum number of rows to return
|
|
229
|
+
* @returns Updated query state with LIMIT clause
|
|
230
|
+
*/
|
|
231
|
+
withLimit(limit: number): SelectQueryState {
|
|
232
|
+
return this.state.withLimit(limit);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Adds an OFFSET clause to the query
|
|
237
|
+
* @param offset - Number of rows to skip
|
|
238
|
+
* @returns Updated query state with OFFSET clause
|
|
239
|
+
*/
|
|
240
|
+
withOffset(offset: number): SelectQueryState {
|
|
241
|
+
return this.state.withOffset(offset);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Combines expressions with AND operator
|
|
246
|
+
* @param existing - Existing expression
|
|
247
|
+
* @param next - New expression to combine
|
|
248
|
+
* @returns Combined expression
|
|
249
|
+
*/
|
|
250
|
+
private combineExpressions(existing: ExpressionNode | undefined, next: ExpressionNode): ExpressionNode {
|
|
251
|
+
return existing ? and(existing, next) : next;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private normalizeOrderingTerm(term: ColumnDef | OrderingTerm): OrderingTerm {
|
|
201
255
|
const from = this.state.ast.from;
|
|
202
256
|
const tableRef = from.type === 'Table' && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
* @returns Updated query state with OFFSET clause
|
|
229
|
-
*/
|
|
230
|
-
withOffset(offset: number): SelectQueryState {
|
|
231
|
-
return this.state.withOffset(offset);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Combines expressions with AND operator
|
|
236
|
-
* @param existing - Existing expression
|
|
237
|
-
* @param next - New expression to combine
|
|
238
|
-
* @returns Combined expression
|
|
239
|
-
*/
|
|
240
|
-
private combineExpressions(existing: ExpressionNode | undefined, next: ExpressionNode): ExpressionNode {
|
|
241
|
-
return existing ? and(existing, next) : next;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
}
|
|
257
|
+
const termType = (term as any)?.type;
|
|
258
|
+
if (termType === 'Column') {
|
|
259
|
+
return term as ColumnNode;
|
|
260
|
+
}
|
|
261
|
+
if (termType === 'AliasRef') {
|
|
262
|
+
return term as AliasRefNode;
|
|
263
|
+
}
|
|
264
|
+
if (isOperandNode(term)) {
|
|
265
|
+
return term as OrderingTerm;
|
|
266
|
+
}
|
|
267
|
+
if (
|
|
268
|
+
termType === 'BinaryExpression' ||
|
|
269
|
+
termType === 'LogicalExpression' ||
|
|
270
|
+
termType === 'NullExpression' ||
|
|
271
|
+
termType === 'InExpression' ||
|
|
272
|
+
termType === 'ExistsExpression' ||
|
|
273
|
+
termType === 'BetweenExpression' ||
|
|
274
|
+
termType === 'ArithmeticExpression'
|
|
275
|
+
) {
|
|
276
|
+
return term as ExpressionNode;
|
|
277
|
+
}
|
|
278
|
+
return buildColumnNode(tableRef, term as ColumnDef);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
}
|