metal-orm 1.0.85 → 1.0.86
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 +233 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -13
- package/dist/index.d.ts +27 -13
- package/dist/index.js +231 -173
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ast/ast-validation.ts +10 -5
- package/src/core/ast/expression-visitor.ts +19 -0
- package/src/core/ast/query-visitor.ts +171 -125
- package/src/orm/execute.ts +60 -46
- package/src/query-builder/select/select-operations.ts +32 -24
- package/src/query-builder/select.ts +49 -35
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { SelectQueryNode } from './query.js';
|
|
2
2
|
import { visitSelectQuery } from './query-visitor.js';
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
let
|
|
4
|
+
export const findFirstParamOperandName = (ast: SelectQueryNode): string | undefined => {
|
|
5
|
+
let name: string | undefined;
|
|
6
6
|
|
|
7
7
|
visitSelectQuery(ast, {
|
|
8
|
-
visitParam: () => {
|
|
9
|
-
|
|
8
|
+
visitParam: (node) => {
|
|
9
|
+
if (!name) {
|
|
10
|
+
name = node.name;
|
|
11
|
+
}
|
|
10
12
|
}
|
|
11
13
|
});
|
|
12
14
|
|
|
13
|
-
return
|
|
15
|
+
return name;
|
|
14
16
|
};
|
|
17
|
+
|
|
18
|
+
export const hasParamOperandsInQuery = (ast: SelectQueryNode): boolean =>
|
|
19
|
+
!!findFirstParamOperandName(ast);
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
BitwiseExpressionNode,
|
|
22
22
|
ParamNode
|
|
23
23
|
} from './expression-nodes.js';
|
|
24
|
+
import type { SelectQueryNode } from './query.js';
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Visitor for expression nodes
|
|
@@ -34,6 +35,8 @@ export interface ExpressionVisitor<R> {
|
|
|
34
35
|
visitBetweenExpression?(node: BetweenExpressionNode): R;
|
|
35
36
|
visitArithmeticExpression?(node: ArithmeticExpressionNode): R;
|
|
36
37
|
visitBitwiseExpression?(node: BitwiseExpressionNode): R;
|
|
38
|
+
visitOperand?(node: OperandNode): R;
|
|
39
|
+
visitSelectQuery?(node: SelectQueryNode): R;
|
|
37
40
|
otherwise?(node: ExpressionNode): R;
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -50,6 +53,10 @@ export interface OperandVisitor<R> {
|
|
|
50
53
|
visitCaseExpression?(node: CaseExpressionNode): R;
|
|
51
54
|
visitCast?(node: CastExpressionNode): R;
|
|
52
55
|
visitWindowFunction?(node: WindowFunctionNode): R;
|
|
56
|
+
visitArithmeticExpression?(node: ArithmeticExpressionNode): R;
|
|
57
|
+
visitBitwiseExpression?(node: BitwiseExpressionNode): R;
|
|
58
|
+
visitExpression?(node: ExpressionNode): R;
|
|
59
|
+
visitSelectQuery?(node: SelectQueryNode): R;
|
|
53
60
|
visitCollate?(node: CollateExpressionNode): R;
|
|
54
61
|
visitAliasRef?(node: AliasRefNode): R;
|
|
55
62
|
otherwise?(node: OperandNode): R;
|
|
@@ -111,6 +118,12 @@ export const registerOperandDispatcher = (type: string, dispatcher: OperandDispa
|
|
|
111
118
|
operandRegistry = operandRegistry.register(type, dispatcher);
|
|
112
119
|
};
|
|
113
120
|
|
|
121
|
+
export const hasExpressionDispatcher = (type: string): boolean =>
|
|
122
|
+
expressionRegistry.get(type) !== undefined;
|
|
123
|
+
|
|
124
|
+
export const hasOperandDispatcher = (type: string): boolean =>
|
|
125
|
+
operandRegistry.get(type) !== undefined;
|
|
126
|
+
|
|
114
127
|
/**
|
|
115
128
|
* Clears all registered dispatchers. Primarily for tests.
|
|
116
129
|
*/
|
|
@@ -225,6 +238,12 @@ export const visitOperand = <R>(node: OperandNode, visitor: OperandVisitor<R>):
|
|
|
225
238
|
case 'Collate':
|
|
226
239
|
if (visitor.visitCollate) return visitor.visitCollate(node as CollateExpressionNode);
|
|
227
240
|
break;
|
|
241
|
+
case 'ArithmeticExpression':
|
|
242
|
+
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node as ArithmeticExpressionNode);
|
|
243
|
+
break;
|
|
244
|
+
case 'BitwiseExpression':
|
|
245
|
+
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node as BitwiseExpressionNode);
|
|
246
|
+
break;
|
|
228
247
|
default:
|
|
229
248
|
break;
|
|
230
249
|
}
|
|
@@ -15,6 +15,13 @@ import type {
|
|
|
15
15
|
ParamNode
|
|
16
16
|
} from './expression-nodes.js';
|
|
17
17
|
import { isOperandNode } from './expression-nodes.js';
|
|
18
|
+
import {
|
|
19
|
+
hasOperandDispatcher,
|
|
20
|
+
type ExpressionVisitor,
|
|
21
|
+
type OperandVisitor,
|
|
22
|
+
visitExpression,
|
|
23
|
+
visitOperand
|
|
24
|
+
} from './expression-visitor.js';
|
|
18
25
|
|
|
19
26
|
export interface SelectQueryVisitor {
|
|
20
27
|
visitSelectQuery?(node: SelectQueryNode): void;
|
|
@@ -43,142 +50,181 @@ const getNodeType = (value: unknown): string | undefined => {
|
|
|
43
50
|
return undefined;
|
|
44
51
|
};
|
|
45
52
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
visitExpressionNode(term as ExpressionNode, visitor);
|
|
52
|
-
};
|
|
53
|
+
export const visitSelectQuery = (ast: SelectQueryNode, visitor: SelectQueryVisitor): void => {
|
|
54
|
+
const visitExpressionNode = (node: ExpressionNode): void => {
|
|
55
|
+
visitExpression(node, expressionVisitor);
|
|
56
|
+
};
|
|
53
57
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
};
|
|
58
|
+
const visitOperandNode = (node: OperandNode): void => {
|
|
59
|
+
visitOperand(node, operandVisitor);
|
|
60
|
+
};
|
|
58
61
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
visitSelectQuery(source.query, visitor);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (source.type === 'FunctionTable') {
|
|
67
|
-
visitor.visitFunctionTable?.(source);
|
|
68
|
-
source.args?.forEach(arg => visitOperandNode(arg, visitor));
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const visitExpressionNode = (node: ExpressionNode, visitor: SelectQueryVisitor): void => {
|
|
73
|
-
visitor.visitExpression?.(node);
|
|
74
|
-
const type = getNodeType(node);
|
|
75
|
-
if (!type) return;
|
|
76
|
-
switch (type) {
|
|
77
|
-
case 'BinaryExpression':
|
|
78
|
-
visitOperandNode(node.left, visitor);
|
|
79
|
-
visitOperandNode(node.right, visitor);
|
|
80
|
-
if (node.escape) {
|
|
81
|
-
visitOperandNode(node.escape, visitor);
|
|
82
|
-
}
|
|
62
|
+
const visitOrderingTerm = (term: OrderingTerm): void => {
|
|
63
|
+
if (!term || typeof term !== 'object') return;
|
|
64
|
+
if (isOperandNode(term)) {
|
|
65
|
+
visitOperandNode(term);
|
|
83
66
|
return;
|
|
84
|
-
|
|
85
|
-
|
|
67
|
+
}
|
|
68
|
+
const type = getNodeType(term);
|
|
69
|
+
if (type && hasOperandDispatcher(type)) {
|
|
70
|
+
visitOperandNode(term as unknown as OperandNode);
|
|
86
71
|
return;
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
}
|
|
73
|
+
if (type) {
|
|
74
|
+
visitExpressionNode(term as ExpressionNode);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const visitOrderByNode = (node: OrderByNode): void => {
|
|
79
|
+
visitor.visitOrderBy?.(node);
|
|
80
|
+
visitOrderingTerm(node.term);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const visitTableSource = (source: TableSourceNode): void => {
|
|
84
|
+
visitor.visitTableSource?.(source);
|
|
85
|
+
if (source.type === 'DerivedTable') {
|
|
86
|
+
visitor.visitDerivedTable?.(source);
|
|
87
|
+
visitSelectQuery(source.query, visitor);
|
|
89
88
|
return;
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
}
|
|
90
|
+
if (source.type === 'FunctionTable') {
|
|
91
|
+
visitor.visitFunctionTable?.(source);
|
|
92
|
+
source.args?.forEach(arg => visitOperandNode(arg));
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const expressionVisitor: ExpressionVisitor<void> = {
|
|
97
|
+
visitBinaryExpression: (node) => {
|
|
98
|
+
visitor.visitExpression?.(node);
|
|
99
|
+
visitOperandNode(node.left);
|
|
100
|
+
visitOperandNode(node.right);
|
|
101
|
+
if (node.escape) {
|
|
102
|
+
visitOperandNode(node.escape);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
visitLogicalExpression: (node) => {
|
|
106
|
+
visitor.visitExpression?.(node);
|
|
107
|
+
node.operands.forEach(operand => visitExpressionNode(operand));
|
|
108
|
+
},
|
|
109
|
+
visitNullExpression: (node) => {
|
|
110
|
+
visitor.visitExpression?.(node);
|
|
111
|
+
visitOperandNode(node.left);
|
|
112
|
+
},
|
|
113
|
+
visitInExpression: (node) => {
|
|
114
|
+
visitor.visitExpression?.(node);
|
|
115
|
+
visitOperandNode(node.left);
|
|
92
116
|
if (Array.isArray(node.right)) {
|
|
93
|
-
node.right.forEach(operand => visitOperandNode(operand
|
|
117
|
+
node.right.forEach(operand => visitOperandNode(operand));
|
|
94
118
|
} else {
|
|
95
|
-
visitOperandNode(node.right
|
|
119
|
+
visitOperandNode(node.right);
|
|
96
120
|
}
|
|
97
|
-
|
|
98
|
-
|
|
121
|
+
},
|
|
122
|
+
visitExistsExpression: (node) => {
|
|
123
|
+
visitor.visitExpression?.(node);
|
|
99
124
|
visitSelectQuery(node.subquery, visitor);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
visitOperandNode(node.
|
|
104
|
-
visitOperandNode(node.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
125
|
+
},
|
|
126
|
+
visitBetweenExpression: (node) => {
|
|
127
|
+
visitor.visitExpression?.(node);
|
|
128
|
+
visitOperandNode(node.left);
|
|
129
|
+
visitOperandNode(node.lower);
|
|
130
|
+
visitOperandNode(node.upper);
|
|
131
|
+
},
|
|
132
|
+
visitArithmeticExpression: (node) => {
|
|
133
|
+
visitor.visitExpression?.(node);
|
|
134
|
+
visitOperandNode(node.left);
|
|
135
|
+
visitOperandNode(node.right);
|
|
136
|
+
},
|
|
137
|
+
visitBitwiseExpression: (node) => {
|
|
138
|
+
visitor.visitExpression?.(node);
|
|
139
|
+
visitOperandNode(node.left);
|
|
140
|
+
visitOperandNode(node.right);
|
|
141
|
+
},
|
|
142
|
+
visitOperand: (node) => {
|
|
143
|
+
visitOperandNode(node);
|
|
144
|
+
},
|
|
145
|
+
visitSelectQuery: (node) => {
|
|
146
|
+
visitSelectQuery(node, visitor);
|
|
147
|
+
},
|
|
148
|
+
otherwise: (node) => {
|
|
149
|
+
visitor.visitExpression?.(node);
|
|
116
150
|
}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
151
|
+
};
|
|
119
152
|
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
node.
|
|
135
|
-
node.orderBy?.forEach(order => visitOrderByNode(order, visitor));
|
|
153
|
+
const operandVisitor: OperandVisitor<void> = {
|
|
154
|
+
visitColumn: (node) => {
|
|
155
|
+
visitor.visitOperand?.(node);
|
|
156
|
+
},
|
|
157
|
+
visitLiteral: (node) => {
|
|
158
|
+
visitor.visitOperand?.(node);
|
|
159
|
+
},
|
|
160
|
+
visitParam: (node) => {
|
|
161
|
+
visitor.visitOperand?.(node);
|
|
162
|
+
visitor.visitParam?.(node);
|
|
163
|
+
},
|
|
164
|
+
visitFunction: (node) => {
|
|
165
|
+
visitor.visitOperand?.(node);
|
|
166
|
+
node.args?.forEach(arg => visitOperandNode(arg));
|
|
167
|
+
node.orderBy?.forEach(order => visitOrderByNode(order));
|
|
136
168
|
if (node.separator) {
|
|
137
|
-
visitOperandNode(node.separator
|
|
169
|
+
visitOperandNode(node.separator);
|
|
138
170
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
},
|
|
172
|
+
visitJsonPath: (node) => {
|
|
173
|
+
visitor.visitOperand?.(node);
|
|
174
|
+
visitOperandNode(node.column);
|
|
175
|
+
},
|
|
176
|
+
visitScalarSubquery: (node) => {
|
|
177
|
+
visitor.visitOperand?.(node);
|
|
144
178
|
visitSelectQuery(node.query, visitor);
|
|
145
|
-
|
|
146
|
-
|
|
179
|
+
},
|
|
180
|
+
visitCaseExpression: (node) => {
|
|
181
|
+
visitor.visitOperand?.(node);
|
|
147
182
|
node.conditions.forEach(cond => {
|
|
148
|
-
visitExpressionNode(cond.when
|
|
149
|
-
visitOperandNode(cond.then
|
|
183
|
+
visitExpressionNode(cond.when);
|
|
184
|
+
visitOperandNode(cond.then);
|
|
150
185
|
});
|
|
151
186
|
if (node.else) {
|
|
152
|
-
visitOperandNode(node.else
|
|
187
|
+
visitOperandNode(node.else);
|
|
153
188
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
node.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
visitOperandNode(node.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
visitOperandNode(node.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
189
|
+
},
|
|
190
|
+
visitCast: (node) => {
|
|
191
|
+
visitor.visitOperand?.(node);
|
|
192
|
+
visitOperandNode(node.expression);
|
|
193
|
+
},
|
|
194
|
+
visitWindowFunction: (node) => {
|
|
195
|
+
visitor.visitOperand?.(node);
|
|
196
|
+
node.args?.forEach(arg => visitOperandNode(arg));
|
|
197
|
+
node.partitionBy?.forEach(term => visitOperandNode(term));
|
|
198
|
+
node.orderBy?.forEach(order => visitOrderByNode(order));
|
|
199
|
+
},
|
|
200
|
+
visitArithmeticExpression: (node) => {
|
|
201
|
+
visitor.visitOperand?.(node);
|
|
202
|
+
visitOperandNode(node.left);
|
|
203
|
+
visitOperandNode(node.right);
|
|
204
|
+
},
|
|
205
|
+
visitBitwiseExpression: (node) => {
|
|
206
|
+
visitor.visitOperand?.(node);
|
|
207
|
+
visitOperandNode(node.left);
|
|
208
|
+
visitOperandNode(node.right);
|
|
209
|
+
},
|
|
210
|
+
visitExpression: (node) => {
|
|
211
|
+
visitExpressionNode(node);
|
|
212
|
+
},
|
|
213
|
+
visitSelectQuery: (node) => {
|
|
214
|
+
visitSelectQuery(node, visitor);
|
|
215
|
+
},
|
|
216
|
+
visitCollate: (node) => {
|
|
217
|
+
visitor.visitOperand?.(node);
|
|
218
|
+
visitOperandNode(node.expression);
|
|
219
|
+
},
|
|
220
|
+
visitAliasRef: (node) => {
|
|
221
|
+
visitor.visitOperand?.(node);
|
|
222
|
+
},
|
|
223
|
+
otherwise: (node) => {
|
|
224
|
+
visitor.visitOperand?.(node);
|
|
177
225
|
}
|
|
178
|
-
}
|
|
179
|
-
};
|
|
226
|
+
};
|
|
180
227
|
|
|
181
|
-
export const visitSelectQuery = (ast: SelectQueryNode, visitor: SelectQueryVisitor): void => {
|
|
182
228
|
visitor.visitSelectQuery?.(ast);
|
|
183
229
|
|
|
184
230
|
if (ast.ctes) {
|
|
@@ -188,36 +234,36 @@ export const visitSelectQuery = (ast: SelectQueryNode, visitor: SelectQueryVisit
|
|
|
188
234
|
}
|
|
189
235
|
}
|
|
190
236
|
|
|
191
|
-
visitTableSource(ast.from
|
|
237
|
+
visitTableSource(ast.from);
|
|
192
238
|
|
|
193
239
|
ast.columns?.forEach(col => {
|
|
194
|
-
visitOperandNode(col as OperandNode
|
|
240
|
+
visitOperandNode(col as OperandNode);
|
|
195
241
|
});
|
|
196
242
|
|
|
197
243
|
ast.joins?.forEach(join => {
|
|
198
244
|
visitor.visitJoin?.(join);
|
|
199
|
-
visitTableSource(join.table
|
|
200
|
-
visitExpressionNode(join.condition
|
|
245
|
+
visitTableSource(join.table);
|
|
246
|
+
visitExpressionNode(join.condition);
|
|
201
247
|
});
|
|
202
248
|
|
|
203
249
|
if (ast.where) {
|
|
204
|
-
visitExpressionNode(ast.where
|
|
250
|
+
visitExpressionNode(ast.where);
|
|
205
251
|
}
|
|
206
252
|
|
|
207
253
|
ast.groupBy?.forEach(term => {
|
|
208
|
-
visitOrderingTerm(term
|
|
254
|
+
visitOrderingTerm(term);
|
|
209
255
|
});
|
|
210
256
|
|
|
211
257
|
if (ast.having) {
|
|
212
|
-
visitExpressionNode(ast.having
|
|
258
|
+
visitExpressionNode(ast.having);
|
|
213
259
|
}
|
|
214
260
|
|
|
215
261
|
ast.orderBy?.forEach(order => {
|
|
216
|
-
visitOrderByNode(order
|
|
262
|
+
visitOrderByNode(order);
|
|
217
263
|
});
|
|
218
264
|
|
|
219
265
|
ast.distinct?.forEach(col => {
|
|
220
|
-
visitOperandNode(col
|
|
266
|
+
visitOperandNode(col);
|
|
221
267
|
});
|
|
222
268
|
|
|
223
269
|
ast.setOps?.forEach(op => {
|
package/src/orm/execute.ts
CHANGED
|
@@ -22,9 +22,13 @@ import {
|
|
|
22
22
|
loadBelongsToManyRelation
|
|
23
23
|
} from './lazy-batch.js';
|
|
24
24
|
|
|
25
|
-
type Row = Record<string, unknown>;
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
type Row = Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
type ParamOperandOptions = {
|
|
28
|
+
allowParamOperands?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const flattenResults = (results: { columns: string[]; values: unknown[][] }[]): Row[] => {
|
|
28
32
|
const rows: Row[] = [];
|
|
29
33
|
for (const result of results) {
|
|
30
34
|
const { columns, values } = result;
|
|
@@ -39,13 +43,16 @@ const flattenResults = (results: { columns: string[]; values: unknown[][] }[]):
|
|
|
39
43
|
return rows;
|
|
40
44
|
};
|
|
41
45
|
|
|
42
|
-
const executeWithContexts = async <TTable extends TableDef>(
|
|
43
|
-
execCtx: ExecutionContext,
|
|
44
|
-
entityCtx: EntityContext,
|
|
45
|
-
qb: SelectQueryBuilder<unknown, TTable
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
46
|
+
const executeWithContexts = async <TTable extends TableDef>(
|
|
47
|
+
execCtx: ExecutionContext,
|
|
48
|
+
entityCtx: EntityContext,
|
|
49
|
+
qb: SelectQueryBuilder<unknown, TTable>,
|
|
50
|
+
options?: ParamOperandOptions
|
|
51
|
+
): Promise<EntityInstance<TTable>[]> => {
|
|
52
|
+
const ast = qb.getAST();
|
|
53
|
+
const compiled = options?.allowParamOperands
|
|
54
|
+
? execCtx.dialect.compileSelectWithOptions(ast, { allowParams: true })
|
|
55
|
+
: execCtx.dialect.compileSelect(ast);
|
|
49
56
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
50
57
|
const rows = flattenResults(executed);
|
|
51
58
|
const lazyRelations = qb.getLazyRelations() as RelationKey<TTable>[];
|
|
@@ -66,13 +73,16 @@ const executeWithContexts = async <TTable extends TableDef>(
|
|
|
66
73
|
return entities;
|
|
67
74
|
};
|
|
68
75
|
|
|
69
|
-
const executePlainWithContexts = async <TTable extends TableDef>(
|
|
70
|
-
execCtx: ExecutionContext,
|
|
71
|
-
qb: SelectQueryBuilder<unknown, TTable
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
+
const executePlainWithContexts = async <TTable extends TableDef>(
|
|
77
|
+
execCtx: ExecutionContext,
|
|
78
|
+
qb: SelectQueryBuilder<unknown, TTable>,
|
|
79
|
+
options?: ParamOperandOptions
|
|
80
|
+
): Promise<Record<string, unknown>[]> => {
|
|
81
|
+
const ast = qb.getAST();
|
|
82
|
+
const compiled = options?.allowParamOperands
|
|
83
|
+
? execCtx.dialect.compileSelectWithOptions(ast, { allowParams: true })
|
|
84
|
+
: execCtx.dialect.compileSelect(ast);
|
|
85
|
+
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
76
86
|
const rows = flattenResults(executed);
|
|
77
87
|
|
|
78
88
|
if (ast.setOps && ast.setOps.length > 0) {
|
|
@@ -89,12 +99,13 @@ const executePlainWithContexts = async <TTable extends TableDef>(
|
|
|
89
99
|
* @param qb - The select query builder
|
|
90
100
|
* @returns Promise resolving to array of entity instances
|
|
91
101
|
*/
|
|
92
|
-
export async function executeHydrated<TTable extends TableDef>(
|
|
93
|
-
session: OrmSession,
|
|
94
|
-
qb: SelectQueryBuilder<unknown, TTable
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
export async function executeHydrated<TTable extends TableDef>(
|
|
103
|
+
session: OrmSession,
|
|
104
|
+
qb: SelectQueryBuilder<unknown, TTable>,
|
|
105
|
+
options?: ParamOperandOptions
|
|
106
|
+
): Promise<EntityInstance<TTable>[]> {
|
|
107
|
+
return executeWithContexts(session.getExecutionContext(), session, qb, options);
|
|
108
|
+
}
|
|
98
109
|
|
|
99
110
|
/**
|
|
100
111
|
* Executes a hydrated query and returns plain row objects (no entity proxies).
|
|
@@ -103,12 +114,13 @@ export async function executeHydrated<TTable extends TableDef>(
|
|
|
103
114
|
* @param qb - The select query builder
|
|
104
115
|
* @returns Promise resolving to array of plain row objects
|
|
105
116
|
*/
|
|
106
|
-
export async function executeHydratedPlain<TTable extends TableDef>(
|
|
107
|
-
session: OrmSession,
|
|
108
|
-
qb: SelectQueryBuilder<unknown, TTable
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
export async function executeHydratedPlain<TTable extends TableDef>(
|
|
118
|
+
session: OrmSession,
|
|
119
|
+
qb: SelectQueryBuilder<unknown, TTable>,
|
|
120
|
+
options?: ParamOperandOptions
|
|
121
|
+
): Promise<Record<string, unknown>[]> {
|
|
122
|
+
return executePlainWithContexts(session.getExecutionContext(), qb, options);
|
|
123
|
+
}
|
|
112
124
|
|
|
113
125
|
/**
|
|
114
126
|
* Executes a hydrated query using execution and hydration contexts.
|
|
@@ -118,17 +130,18 @@ export async function executeHydratedPlain<TTable extends TableDef>(
|
|
|
118
130
|
* @param qb - The select query builder
|
|
119
131
|
* @returns Promise resolving to array of entity instances
|
|
120
132
|
*/
|
|
121
|
-
export async function executeHydratedWithContexts<TTable extends TableDef>(
|
|
122
|
-
execCtx: ExecutionContext,
|
|
123
|
-
hydCtx: HydrationContext,
|
|
124
|
-
qb: SelectQueryBuilder<unknown, TTable
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
export async function executeHydratedWithContexts<TTable extends TableDef>(
|
|
134
|
+
execCtx: ExecutionContext,
|
|
135
|
+
hydCtx: HydrationContext,
|
|
136
|
+
qb: SelectQueryBuilder<unknown, TTable>,
|
|
137
|
+
options?: ParamOperandOptions
|
|
138
|
+
): Promise<EntityInstance<TTable>[]> {
|
|
139
|
+
const entityCtx = hydCtx.entityContext;
|
|
140
|
+
if (!entityCtx) {
|
|
141
|
+
throw new Error('Hydration context is missing an EntityContext');
|
|
142
|
+
}
|
|
143
|
+
return executeWithContexts(execCtx, entityCtx, qb, options);
|
|
144
|
+
}
|
|
132
145
|
|
|
133
146
|
/**
|
|
134
147
|
* Executes a hydrated query using execution context and returns plain row objects.
|
|
@@ -137,12 +150,13 @@ export async function executeHydratedWithContexts<TTable extends TableDef>(
|
|
|
137
150
|
* @param qb - The select query builder
|
|
138
151
|
* @returns Promise resolving to array of plain row objects
|
|
139
152
|
*/
|
|
140
|
-
export async function executeHydratedPlainWithContexts<TTable extends TableDef>(
|
|
141
|
-
execCtx: ExecutionContext,
|
|
142
|
-
qb: SelectQueryBuilder<unknown, TTable
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
153
|
+
export async function executeHydratedPlainWithContexts<TTable extends TableDef>(
|
|
154
|
+
execCtx: ExecutionContext,
|
|
155
|
+
qb: SelectQueryBuilder<unknown, TTable>,
|
|
156
|
+
options?: ParamOperandOptions
|
|
157
|
+
): Promise<Record<string, unknown>[]> {
|
|
158
|
+
return executePlainWithContexts(execCtx, qb, options);
|
|
159
|
+
}
|
|
146
160
|
|
|
147
161
|
const loadLazyRelationsForTable = async <TTable extends TableDef>(
|
|
148
162
|
ctx: EntityContext,
|