metal-orm 1.0.56 → 1.0.58
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 +41 -33
- package/dist/index.cjs +1461 -195
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +541 -114
- package/dist/index.d.ts +541 -114
- package/dist/index.js +1424 -195
- package/dist/index.js.map +1 -1
- package/package.json +69 -69
- package/src/codegen/naming-strategy.ts +3 -1
- package/src/codegen/typescript.ts +20 -10
- package/src/core/ast/aggregate-functions.ts +14 -0
- package/src/core/ast/builders.ts +38 -20
- package/src/core/ast/expression-builders.ts +70 -2
- package/src/core/ast/expression-nodes.ts +305 -274
- package/src/core/ast/expression-visitor.ts +11 -1
- package/src/core/ast/expression.ts +4 -0
- package/src/core/ast/query.ts +3 -0
- package/src/core/ddl/introspect/catalogs/mysql.ts +5 -0
- package/src/core/ddl/introspect/catalogs/sqlite.ts +3 -0
- package/src/core/ddl/introspect/functions/mssql.ts +13 -0
- package/src/core/ddl/introspect/mssql.ts +4 -0
- package/src/core/ddl/introspect/mysql.ts +4 -0
- package/src/core/ddl/introspect/sqlite.ts +4 -0
- package/src/core/dialect/abstract.ts +552 -531
- package/src/core/dialect/base/function-table-formatter.ts +9 -30
- package/src/core/dialect/base/sql-dialect.ts +24 -0
- package/src/core/dialect/mssql/functions.ts +40 -2
- package/src/core/dialect/mysql/functions.ts +16 -2
- package/src/core/dialect/postgres/functions.ts +66 -2
- package/src/core/dialect/postgres/index.ts +17 -4
- package/src/core/dialect/postgres/table-functions.ts +27 -0
- package/src/core/dialect/sqlite/functions.ts +34 -0
- package/src/core/dialect/sqlite/index.ts +17 -1
- package/src/core/driver/database-driver.ts +9 -1
- package/src/core/driver/mssql-driver.ts +3 -0
- package/src/core/driver/mysql-driver.ts +3 -0
- package/src/core/driver/postgres-driver.ts +3 -0
- package/src/core/driver/sqlite-driver.ts +3 -0
- package/src/core/execution/executors/mssql-executor.ts +5 -0
- package/src/core/execution/executors/mysql-executor.ts +5 -0
- package/src/core/execution/executors/postgres-executor.ts +5 -0
- package/src/core/execution/executors/sqlite-executor.ts +5 -0
- package/src/core/functions/array.ts +26 -0
- package/src/core/functions/control-flow.ts +69 -0
- package/src/core/functions/datetime.ts +50 -0
- package/src/core/functions/definitions/aggregate.ts +16 -0
- package/src/core/functions/definitions/control-flow.ts +24 -0
- package/src/core/functions/definitions/datetime.ts +36 -0
- package/src/core/functions/definitions/helpers.ts +29 -0
- package/src/core/functions/definitions/json.ts +49 -0
- package/src/core/functions/definitions/numeric.ts +55 -0
- package/src/core/functions/definitions/string.ts +43 -0
- package/src/core/functions/function-registry.ts +48 -0
- package/src/core/functions/group-concat-helpers.ts +57 -0
- package/src/core/functions/json.ts +38 -0
- package/src/core/functions/numeric.ts +14 -0
- package/src/core/functions/standard-strategy.ts +86 -115
- package/src/core/functions/standard-table-strategy.ts +13 -0
- package/src/core/functions/table-types.ts +15 -0
- package/src/core/functions/text.ts +57 -0
- package/src/core/sql/sql.ts +59 -38
- package/src/decorators/bootstrap.ts +41 -4
- package/src/index.ts +18 -11
- package/src/orm/entity-meta.ts +6 -3
- package/src/orm/entity.ts +81 -14
- package/src/orm/execute.ts +87 -20
- package/src/orm/hydration-context.ts +10 -0
- package/src/orm/identity-map.ts +19 -0
- package/src/orm/interceptor-pipeline.ts +4 -0
- package/src/orm/lazy-batch.ts +237 -54
- package/src/orm/relations/belongs-to.ts +19 -2
- package/src/orm/relations/has-many.ts +23 -9
- package/src/orm/relations/has-one.ts +19 -2
- package/src/orm/relations/many-to-many.ts +59 -4
- package/src/orm/save-graph-types.ts +2 -2
- package/src/orm/save-graph.ts +18 -18
- package/src/query-builder/relation-conditions.ts +80 -59
- package/src/query-builder/relation-service.ts +399 -95
- package/src/query-builder/relation-types.ts +2 -2
- package/src/query-builder/select.ts +124 -106
- package/src/schema/table-guards.ts +6 -0
- package/src/schema/types.ts +109 -85
package/dist/index.cjs
CHANGED
|
@@ -2,8 +2,8 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __esm = (
|
|
6
|
-
return
|
|
5
|
+
var __esm = (fn8, res) => function __init() {
|
|
6
|
+
return fn8 && (res = (0, fn8[__getOwnPropNames(fn8)[0]])(fn8 = 0)), res;
|
|
7
7
|
};
|
|
8
8
|
var __export = (target, all) => {
|
|
9
9
|
for (var name in all)
|
|
@@ -74,8 +74,10 @@ __export(index_exports, {
|
|
|
74
74
|
acos: () => acos,
|
|
75
75
|
add: () => add,
|
|
76
76
|
addDomainEvent: () => addDomainEvent,
|
|
77
|
+
age: () => age,
|
|
77
78
|
aliasRef: () => aliasRef,
|
|
78
79
|
and: () => and,
|
|
80
|
+
arrayAppend: () => arrayAppend,
|
|
79
81
|
ascii: () => ascii,
|
|
80
82
|
asin: () => asin,
|
|
81
83
|
atan: () => atan,
|
|
@@ -84,16 +86,24 @@ __export(index_exports, {
|
|
|
84
86
|
belongsTo: () => belongsTo,
|
|
85
87
|
belongsToMany: () => belongsToMany,
|
|
86
88
|
between: () => between,
|
|
89
|
+
bitAnd: () => bitAnd,
|
|
90
|
+
bitLength: () => bitLength,
|
|
91
|
+
bitOr: () => bitOr,
|
|
92
|
+
bitXor: () => bitXor,
|
|
87
93
|
bootstrapEntities: () => bootstrapEntities,
|
|
88
94
|
caseWhen: () => caseWhen,
|
|
89
95
|
cast: () => cast,
|
|
96
|
+
cbrt: () => cbrt,
|
|
90
97
|
ceil: () => ceil,
|
|
91
98
|
ceiling: () => ceiling,
|
|
92
99
|
char: () => char,
|
|
93
100
|
charLength: () => charLength,
|
|
101
|
+
chr: () => chr,
|
|
94
102
|
clearExpressionDispatchers: () => clearExpressionDispatchers,
|
|
95
103
|
clearOperandDispatchers: () => clearOperandDispatchers,
|
|
104
|
+
coalesce: () => coalesce,
|
|
96
105
|
col: () => col,
|
|
106
|
+
collate: () => collate,
|
|
97
107
|
columnOperand: () => columnOperand,
|
|
98
108
|
concat: () => concat,
|
|
99
109
|
concatWs: () => concatWs,
|
|
@@ -145,18 +155,23 @@ __export(index_exports, {
|
|
|
145
155
|
getDecoratorMetadata: () => getDecoratorMetadata,
|
|
146
156
|
getSchemaIntrospector: () => getSchemaIntrospector,
|
|
147
157
|
getTableDefFromEntity: () => getTableDefFromEntity,
|
|
158
|
+
greatest: () => greatest,
|
|
148
159
|
groupConcat: () => groupConcat,
|
|
149
160
|
gt: () => gt,
|
|
150
161
|
gte: () => gte,
|
|
151
162
|
hasMany: () => hasMany,
|
|
152
163
|
hasOne: () => hasOne,
|
|
164
|
+
hour: () => hour,
|
|
153
165
|
hydrateRows: () => hydrateRows,
|
|
166
|
+
ifNull: () => ifNull,
|
|
154
167
|
inList: () => inList,
|
|
155
168
|
inSubquery: () => inSubquery,
|
|
169
|
+
initcap: () => initcap,
|
|
156
170
|
instr: () => instr,
|
|
157
171
|
introspectSchema: () => introspectSchema,
|
|
158
172
|
isCaseExpressionNode: () => isCaseExpressionNode,
|
|
159
173
|
isCastExpressionNode: () => isCastExpressionNode,
|
|
174
|
+
isCollateExpressionNode: () => isCollateExpressionNode,
|
|
160
175
|
isExpressionSelectionNode: () => isExpressionSelectionNode,
|
|
161
176
|
isFunctionNode: () => isFunctionNode,
|
|
162
177
|
isNotNull: () => isNotNull,
|
|
@@ -164,11 +179,16 @@ __export(index_exports, {
|
|
|
164
179
|
isOperandNode: () => isOperandNode,
|
|
165
180
|
isValueOperandInput: () => isValueOperandInput,
|
|
166
181
|
isWindowFunctionNode: () => isWindowFunctionNode,
|
|
182
|
+
jsonArrayAgg: () => jsonArrayAgg,
|
|
183
|
+
jsonContains: () => jsonContains,
|
|
184
|
+
jsonLength: () => jsonLength,
|
|
167
185
|
jsonPath: () => jsonPath,
|
|
186
|
+
jsonSet: () => jsonSet,
|
|
168
187
|
jsonify: () => jsonify,
|
|
169
188
|
lag: () => lag,
|
|
170
189
|
lastValue: () => lastValue,
|
|
171
190
|
lead: () => lead,
|
|
191
|
+
least: () => least,
|
|
172
192
|
left: () => left,
|
|
173
193
|
length: () => length,
|
|
174
194
|
like: () => like,
|
|
@@ -177,9 +197,12 @@ __export(index_exports, {
|
|
|
177
197
|
loadBelongsToRelation: () => loadBelongsToRelation,
|
|
178
198
|
loadHasManyRelation: () => loadHasManyRelation,
|
|
179
199
|
loadHasOneRelation: () => loadHasOneRelation,
|
|
200
|
+
localTime: () => localTime,
|
|
201
|
+
localTimestamp: () => localTimestamp,
|
|
180
202
|
locate: () => locate,
|
|
181
203
|
log: () => log,
|
|
182
204
|
log10: () => log10,
|
|
205
|
+
log2: () => log2,
|
|
183
206
|
logBase: () => logBase,
|
|
184
207
|
lower: () => lower,
|
|
185
208
|
lpad: () => lpad,
|
|
@@ -187,7 +210,9 @@ __export(index_exports, {
|
|
|
187
210
|
lte: () => lte,
|
|
188
211
|
ltrim: () => ltrim,
|
|
189
212
|
max: () => max,
|
|
213
|
+
md5: () => md5,
|
|
190
214
|
min: () => min,
|
|
215
|
+
minute: () => minute,
|
|
191
216
|
mod: () => mod,
|
|
192
217
|
month: () => month,
|
|
193
218
|
mul: () => mul,
|
|
@@ -200,12 +225,15 @@ __export(index_exports, {
|
|
|
200
225
|
notLike: () => notLike,
|
|
201
226
|
now: () => now,
|
|
202
227
|
ntile: () => ntile,
|
|
228
|
+
nullif: () => nullif,
|
|
229
|
+
octetLength: () => octetLength,
|
|
203
230
|
or: () => or,
|
|
204
231
|
outerRef: () => outerRef,
|
|
205
232
|
pi: () => pi,
|
|
206
233
|
position: () => position,
|
|
207
234
|
pow: () => pow,
|
|
208
235
|
power: () => power,
|
|
236
|
+
quarter: () => quarter,
|
|
209
237
|
radians: () => radians,
|
|
210
238
|
rand: () => rand,
|
|
211
239
|
random: () => random,
|
|
@@ -213,22 +241,30 @@ __export(index_exports, {
|
|
|
213
241
|
registerExpressionDispatcher: () => registerExpressionDispatcher,
|
|
214
242
|
registerOperandDispatcher: () => registerOperandDispatcher,
|
|
215
243
|
registerSchemaIntrospector: () => registerSchemaIntrospector,
|
|
244
|
+
relationLoaderCache: () => relationLoaderCache,
|
|
216
245
|
renderColumnDefinition: () => renderColumnDefinition,
|
|
217
246
|
renderTypeWithArgs: () => renderTypeWithArgs,
|
|
218
247
|
repeat: () => repeat,
|
|
219
248
|
replace: () => replace,
|
|
249
|
+
reverse: () => reverse,
|
|
220
250
|
right: () => right,
|
|
221
251
|
round: () => round,
|
|
222
252
|
rowNumber: () => rowNumber,
|
|
223
253
|
rowsToQueryResult: () => rowsToQueryResult,
|
|
224
254
|
rpad: () => rpad,
|
|
225
255
|
rtrim: () => rtrim,
|
|
256
|
+
second: () => second,
|
|
226
257
|
sel: () => sel,
|
|
227
258
|
selectFromEntity: () => selectFromEntity,
|
|
259
|
+
sha1: () => sha1,
|
|
260
|
+
sha2: () => sha2,
|
|
261
|
+
shiftLeft: () => shiftLeft,
|
|
262
|
+
shiftRight: () => shiftRight,
|
|
228
263
|
sign: () => sign,
|
|
229
264
|
sin: () => sin,
|
|
230
265
|
space: () => space,
|
|
231
266
|
sqrt: () => sqrt,
|
|
267
|
+
stddev: () => stddev,
|
|
232
268
|
sub: () => sub,
|
|
233
269
|
substr: () => substr,
|
|
234
270
|
sum: () => sum,
|
|
@@ -244,6 +280,7 @@ __export(index_exports, {
|
|
|
244
280
|
upper: () => upper,
|
|
245
281
|
utcNow: () => utcNow,
|
|
246
282
|
valueToOperand: () => valueToOperand,
|
|
283
|
+
variance: () => variance,
|
|
247
284
|
visitExpression: () => visitExpression,
|
|
248
285
|
visitOperand: () => visitOperand,
|
|
249
286
|
weekOfYear: () => weekOfYear,
|
|
@@ -586,7 +623,9 @@ var operandTypes = /* @__PURE__ */ new Set([
|
|
|
586
623
|
"CaseExpression",
|
|
587
624
|
"Cast",
|
|
588
625
|
"WindowFunction",
|
|
589
|
-
"ArithmeticExpression"
|
|
626
|
+
"ArithmeticExpression",
|
|
627
|
+
"BitwiseExpression",
|
|
628
|
+
"Collate"
|
|
590
629
|
]);
|
|
591
630
|
var hasTypeProperty = (value) => typeof value === "object" && value !== null && "type" in value;
|
|
592
631
|
var isOperandNode = (node) => {
|
|
@@ -596,6 +635,7 @@ var isOperandNode = (node) => {
|
|
|
596
635
|
var isFunctionNode = (node) => isOperandNode(node) && node.type === "Function";
|
|
597
636
|
var isCaseExpressionNode = (node) => isOperandNode(node) && node.type === "CaseExpression";
|
|
598
637
|
var isCastExpressionNode = (node) => isOperandNode(node) && node.type === "Cast";
|
|
638
|
+
var isCollateExpressionNode = (node) => isOperandNode(node) && node.type === "Collate";
|
|
599
639
|
var isWindowFunctionNode = (node) => isOperandNode(node) && node.type === "WindowFunction";
|
|
600
640
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isCastExpressionNode(node) || isWindowFunctionNode(node);
|
|
601
641
|
|
|
@@ -720,6 +760,17 @@ var add = (left2, right2) => createArithmeticExpression("+", left2, right2);
|
|
|
720
760
|
var sub = (left2, right2) => createArithmeticExpression("-", left2, right2);
|
|
721
761
|
var mul = (left2, right2) => createArithmeticExpression("*", left2, right2);
|
|
722
762
|
var div = (left2, right2) => createArithmeticExpression("/", left2, right2);
|
|
763
|
+
var createBitwiseExpression = (operator, left2, right2) => ({
|
|
764
|
+
type: "BitwiseExpression",
|
|
765
|
+
left: toOperand(left2),
|
|
766
|
+
operator,
|
|
767
|
+
right: toOperand(right2)
|
|
768
|
+
});
|
|
769
|
+
var bitAnd = (left2, right2) => createBitwiseExpression("&", left2, right2);
|
|
770
|
+
var bitOr = (left2, right2) => createBitwiseExpression("|", left2, right2);
|
|
771
|
+
var bitXor = (left2, right2) => createBitwiseExpression("^", left2, right2);
|
|
772
|
+
var shiftLeft = (left2, right2) => createBitwiseExpression("<<", left2, right2);
|
|
773
|
+
var shiftRight = (left2, right2) => createBitwiseExpression(">>", left2, right2);
|
|
723
774
|
var jsonPath = (col2, path) => ({
|
|
724
775
|
type: "JsonPath",
|
|
725
776
|
column: columnOperand(col2),
|
|
@@ -748,6 +799,11 @@ var notExists = (subquery) => ({
|
|
|
748
799
|
operator: "NOT EXISTS",
|
|
749
800
|
subquery
|
|
750
801
|
});
|
|
802
|
+
var collate = (expression, collation) => ({
|
|
803
|
+
type: "Collate",
|
|
804
|
+
expression: toOperand(expression),
|
|
805
|
+
collation
|
|
806
|
+
});
|
|
751
807
|
|
|
752
808
|
// src/core/ast/window-functions.ts
|
|
753
809
|
var buildWindowFunction = (name, args = [], partitionBy, orderBy) => {
|
|
@@ -893,6 +949,8 @@ var groupConcat = (col2, options) => ({
|
|
|
893
949
|
orderBy: options?.orderBy?.map(toOrderByNode),
|
|
894
950
|
separator: options?.separator !== void 0 ? valueToOperand(options.separator) : void 0
|
|
895
951
|
});
|
|
952
|
+
var stddev = buildAggregate("STDDEV");
|
|
953
|
+
var variance = buildAggregate("VARIANCE");
|
|
896
954
|
|
|
897
955
|
// src/core/ast/expression-visitor.ts
|
|
898
956
|
var DispatcherRegistry = class _DispatcherRegistry {
|
|
@@ -966,6 +1024,9 @@ var visitExpression = (node, visitor) => {
|
|
|
966
1024
|
case "ArithmeticExpression":
|
|
967
1025
|
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
|
|
968
1026
|
break;
|
|
1027
|
+
case "BitwiseExpression":
|
|
1028
|
+
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
|
|
1029
|
+
break;
|
|
969
1030
|
default:
|
|
970
1031
|
break;
|
|
971
1032
|
}
|
|
@@ -1003,6 +1064,9 @@ var visitOperand = (node, visitor) => {
|
|
|
1003
1064
|
case "Cast":
|
|
1004
1065
|
if (visitor.visitCast) return visitor.visitCast(node);
|
|
1005
1066
|
break;
|
|
1067
|
+
case "Collate":
|
|
1068
|
+
if (visitor.visitCollate) return visitor.visitCollate(node);
|
|
1069
|
+
break;
|
|
1006
1070
|
default:
|
|
1007
1071
|
break;
|
|
1008
1072
|
}
|
|
@@ -1073,62 +1137,337 @@ var derivedTable = (query, alias, columnAliases) => ({
|
|
|
1073
1137
|
columnAliases
|
|
1074
1138
|
});
|
|
1075
1139
|
|
|
1140
|
+
// src/core/functions/function-registry.ts
|
|
1141
|
+
var FunctionRegistry = class {
|
|
1142
|
+
constructor() {
|
|
1143
|
+
this.renderers = /* @__PURE__ */ new Map();
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Registers or overrides a renderer for the given function name.
|
|
1147
|
+
*/
|
|
1148
|
+
add(name, renderer) {
|
|
1149
|
+
this.renderers.set(name, renderer);
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Registers a batch of definitions.
|
|
1153
|
+
*/
|
|
1154
|
+
register(definitions) {
|
|
1155
|
+
for (const definition of definitions) {
|
|
1156
|
+
this.add(definition.name, definition.renderer);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Merges another registry into this one, allowing overrides from the other source.
|
|
1161
|
+
*/
|
|
1162
|
+
merge(other) {
|
|
1163
|
+
for (const [name, renderer] of other.renderers.entries()) {
|
|
1164
|
+
this.renderers.set(name, renderer);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Retrieves a renderer by function name.
|
|
1169
|
+
*/
|
|
1170
|
+
get(name) {
|
|
1171
|
+
return this.renderers.get(name);
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
// src/core/functions/definitions/helpers.ts
|
|
1176
|
+
function unaryRenderer(name) {
|
|
1177
|
+
return ({ compiledArgs }) => `${name}(${compiledArgs[0]})`;
|
|
1178
|
+
}
|
|
1179
|
+
function binaryRenderer(name) {
|
|
1180
|
+
return ({ compiledArgs }) => `${name}(${compiledArgs[0]}, ${compiledArgs[1]})`;
|
|
1181
|
+
}
|
|
1182
|
+
function variadicRenderer(name) {
|
|
1183
|
+
return ({ compiledArgs }) => `${name}(${compiledArgs.join(", ")})`;
|
|
1184
|
+
}
|
|
1185
|
+
function noArgsRenderer(name) {
|
|
1186
|
+
return () => `${name}()`;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// src/core/functions/definitions/aggregate.ts
|
|
1190
|
+
var aggregateFunctionDefinitions = [
|
|
1191
|
+
{
|
|
1192
|
+
name: "COUNT",
|
|
1193
|
+
renderer: ({ compiledArgs }) => compiledArgs.length ? `COUNT(${compiledArgs.join(", ")})` : "COUNT(*)"
|
|
1194
|
+
},
|
|
1195
|
+
{ name: "SUM", renderer: unaryRenderer("SUM") },
|
|
1196
|
+
{ name: "AVG", renderer: unaryRenderer("AVG") },
|
|
1197
|
+
{ name: "MIN", renderer: unaryRenderer("MIN") },
|
|
1198
|
+
{ name: "MAX", renderer: unaryRenderer("MAX") },
|
|
1199
|
+
{ name: "STDDEV", renderer: unaryRenderer("STDDEV") },
|
|
1200
|
+
{ name: "VARIANCE", renderer: unaryRenderer("VARIANCE") }
|
|
1201
|
+
];
|
|
1202
|
+
|
|
1203
|
+
// src/core/functions/definitions/string.ts
|
|
1204
|
+
var stringFunctionDefinitions = [
|
|
1205
|
+
{ name: "UPPER", renderer: unaryRenderer("UPPER") },
|
|
1206
|
+
{ name: "LOWER", renderer: unaryRenderer("LOWER") },
|
|
1207
|
+
{ name: "LENGTH", renderer: unaryRenderer("LENGTH") },
|
|
1208
|
+
{ name: "CHAR_LENGTH", renderer: unaryRenderer("CHAR_LENGTH") },
|
|
1209
|
+
{ name: "CHARACTER_LENGTH", renderer: unaryRenderer("CHARACTER_LENGTH") },
|
|
1210
|
+
{ name: "TRIM", renderer: unaryRenderer("TRIM") },
|
|
1211
|
+
{ name: "LTRIM", renderer: unaryRenderer("LTRIM") },
|
|
1212
|
+
{ name: "RTRIM", renderer: unaryRenderer("RTRIM") },
|
|
1213
|
+
{ name: "SUBSTRING", renderer: variadicRenderer("SUBSTRING") },
|
|
1214
|
+
{ name: "SUBSTR", renderer: variadicRenderer("SUBSTR") },
|
|
1215
|
+
{ name: "CONCAT", renderer: variadicRenderer("CONCAT") },
|
|
1216
|
+
{ name: "CONCAT_WS", renderer: variadicRenderer("CONCAT_WS") },
|
|
1217
|
+
{ name: "ASCII", renderer: unaryRenderer("ASCII") },
|
|
1218
|
+
{ name: "CHAR", renderer: variadicRenderer("CHAR") },
|
|
1219
|
+
{
|
|
1220
|
+
name: "POSITION",
|
|
1221
|
+
renderer: ({ compiledArgs }) => `POSITION(${compiledArgs[0]} IN ${compiledArgs[1]})`
|
|
1222
|
+
},
|
|
1223
|
+
{ name: "REPLACE", renderer: ({ compiledArgs }) => `REPLACE(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` },
|
|
1224
|
+
{ name: "REPEAT", renderer: binaryRenderer("REPEAT") },
|
|
1225
|
+
{ name: "LPAD", renderer: ({ compiledArgs }) => `LPAD(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` },
|
|
1226
|
+
{ name: "RPAD", renderer: ({ compiledArgs }) => `RPAD(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` },
|
|
1227
|
+
{ name: "LEFT", renderer: binaryRenderer("LEFT") },
|
|
1228
|
+
{ name: "RIGHT", renderer: binaryRenderer("RIGHT") },
|
|
1229
|
+
{ name: "INSTR", renderer: binaryRenderer("INSTR") },
|
|
1230
|
+
{
|
|
1231
|
+
name: "LOCATE",
|
|
1232
|
+
renderer: ({ compiledArgs }) => compiledArgs.length === 3 ? `LOCATE(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` : `LOCATE(${compiledArgs[0]}, ${compiledArgs[1]})`
|
|
1233
|
+
},
|
|
1234
|
+
{ name: "SPACE", renderer: unaryRenderer("SPACE") },
|
|
1235
|
+
{ name: "REVERSE", renderer: unaryRenderer("REVERSE") },
|
|
1236
|
+
{ name: "INITCAP", renderer: unaryRenderer("INITCAP") },
|
|
1237
|
+
{ name: "MD5", renderer: unaryRenderer("MD5") },
|
|
1238
|
+
{ name: "SHA1", renderer: unaryRenderer("SHA1") },
|
|
1239
|
+
{ name: "SHA2", renderer: ({ compiledArgs }) => `SHA2(${compiledArgs[0]}, ${compiledArgs[1]})` }
|
|
1240
|
+
];
|
|
1241
|
+
|
|
1242
|
+
// src/core/functions/definitions/datetime.ts
|
|
1243
|
+
var dateTimeFunctionDefinitions = [
|
|
1244
|
+
{ name: "NOW", renderer: noArgsRenderer("NOW") },
|
|
1245
|
+
{ name: "CURRENT_DATE", renderer: () => "CURRENT_DATE" },
|
|
1246
|
+
{ name: "CURRENT_TIME", renderer: () => "CURRENT_TIME" },
|
|
1247
|
+
{
|
|
1248
|
+
name: "EXTRACT",
|
|
1249
|
+
renderer: ({ compiledArgs }) => `EXTRACT(${compiledArgs[0]} FROM ${compiledArgs[1]})`
|
|
1250
|
+
},
|
|
1251
|
+
{ name: "YEAR", renderer: ({ compiledArgs }) => `EXTRACT(YEAR FROM ${compiledArgs[0]})` },
|
|
1252
|
+
{ name: "MONTH", renderer: ({ compiledArgs }) => `EXTRACT(MONTH FROM ${compiledArgs[0]})` },
|
|
1253
|
+
{ name: "DAY", renderer: ({ compiledArgs }) => `EXTRACT(DAY FROM ${compiledArgs[0]})` },
|
|
1254
|
+
{ name: "HOUR", renderer: ({ compiledArgs }) => `EXTRACT(HOUR FROM ${compiledArgs[0]})` },
|
|
1255
|
+
{ name: "MINUTE", renderer: ({ compiledArgs }) => `EXTRACT(MINUTE FROM ${compiledArgs[0]})` },
|
|
1256
|
+
{ name: "SECOND", renderer: ({ compiledArgs }) => `EXTRACT(SECOND FROM ${compiledArgs[0]})` },
|
|
1257
|
+
{ name: "QUARTER", renderer: ({ compiledArgs }) => `EXTRACT(QUARTER FROM ${compiledArgs[0]})` },
|
|
1258
|
+
{ name: "DATE_ADD", renderer: ({ compiledArgs }) => `(${compiledArgs[0]} + INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})` },
|
|
1259
|
+
{ name: "DATE_SUB", renderer: ({ compiledArgs }) => `(${compiledArgs[0]} - INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})` },
|
|
1260
|
+
{ name: "DATE_DIFF", renderer: ({ compiledArgs }) => `DATEDIFF(${compiledArgs[0]}, ${compiledArgs[1]})` },
|
|
1261
|
+
{ name: "DATE_FORMAT", renderer: ({ compiledArgs }) => `DATE_FORMAT(${compiledArgs[0]}, ${compiledArgs[1]})` },
|
|
1262
|
+
{ name: "UNIX_TIMESTAMP", renderer: noArgsRenderer("UNIX_TIMESTAMP") },
|
|
1263
|
+
{ name: "FROM_UNIXTIME", renderer: ({ compiledArgs }) => `FROM_UNIXTIME(${compiledArgs[0]})` },
|
|
1264
|
+
{ name: "END_OF_MONTH", renderer: ({ compiledArgs }) => `LAST_DAY(${compiledArgs[0]})` },
|
|
1265
|
+
{ name: "DAY_OF_WEEK", renderer: ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})` },
|
|
1266
|
+
{ name: "WEEK_OF_YEAR", renderer: ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})` },
|
|
1267
|
+
{ name: "DATE_TRUNC", renderer: ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})` },
|
|
1268
|
+
{
|
|
1269
|
+
name: "AGE",
|
|
1270
|
+
renderer: ({ compiledArgs }) => compiledArgs.length === 1 ? `AGE(${compiledArgs[0]})` : `AGE(${compiledArgs[0]}, ${compiledArgs[1]})`
|
|
1271
|
+
},
|
|
1272
|
+
{ name: "LOCALTIME", renderer: () => "LOCALTIME" },
|
|
1273
|
+
{ name: "LOCALTIMESTAMP", renderer: () => "LOCALTIMESTAMP" }
|
|
1274
|
+
];
|
|
1275
|
+
|
|
1276
|
+
// src/core/functions/definitions/numeric.ts
|
|
1277
|
+
var numericFunctionDefinitions = [
|
|
1278
|
+
{ name: "ABS", renderer: unaryRenderer("ABS") },
|
|
1279
|
+
{ name: "BIT_LENGTH", renderer: unaryRenderer("BIT_LENGTH") },
|
|
1280
|
+
{ name: "OCTET_LENGTH", renderer: unaryRenderer("OCTET_LENGTH") },
|
|
1281
|
+
{ name: "CHR", renderer: unaryRenderer("CHR") },
|
|
1282
|
+
{ name: "LOG2", renderer: unaryRenderer("LOG2") },
|
|
1283
|
+
{ name: "CBRT", renderer: unaryRenderer("CBRT") },
|
|
1284
|
+
{ name: "ACOS", renderer: unaryRenderer("ACOS") },
|
|
1285
|
+
{ name: "ASIN", renderer: unaryRenderer("ASIN") },
|
|
1286
|
+
{ name: "ATAN", renderer: unaryRenderer("ATAN") },
|
|
1287
|
+
{ name: "ATAN2", renderer: binaryRenderer("ATAN2") },
|
|
1288
|
+
{ name: "CEIL", renderer: unaryRenderer("CEIL") },
|
|
1289
|
+
{ name: "CEILING", renderer: unaryRenderer("CEILING") },
|
|
1290
|
+
{ name: "COS", renderer: unaryRenderer("COS") },
|
|
1291
|
+
{ name: "COT", renderer: unaryRenderer("COT") },
|
|
1292
|
+
{ name: "DEGREES", renderer: unaryRenderer("DEGREES") },
|
|
1293
|
+
{ name: "EXP", renderer: unaryRenderer("EXP") },
|
|
1294
|
+
{ name: "FLOOR", renderer: unaryRenderer("FLOOR") },
|
|
1295
|
+
{ name: "LN", renderer: unaryRenderer("LN") },
|
|
1296
|
+
{
|
|
1297
|
+
name: "LOG",
|
|
1298
|
+
renderer: ({ compiledArgs }) => compiledArgs.length === 2 ? `LOG(${compiledArgs[0]}, ${compiledArgs[1]})` : `LOG(${compiledArgs[0]})`
|
|
1299
|
+
},
|
|
1300
|
+
{ name: "LOG10", renderer: unaryRenderer("LOG10") },
|
|
1301
|
+
{ name: "LOG_BASE", renderer: binaryRenderer("LOG") },
|
|
1302
|
+
{ name: "MOD", renderer: binaryRenderer("MOD") },
|
|
1303
|
+
{ name: "PI", renderer: noArgsRenderer("PI") },
|
|
1304
|
+
{ name: "POWER", renderer: binaryRenderer("POWER") },
|
|
1305
|
+
{ name: "POW", renderer: binaryRenderer("POW") },
|
|
1306
|
+
{ name: "RADIANS", renderer: unaryRenderer("RADIANS") },
|
|
1307
|
+
{ name: "RANDOM", renderer: noArgsRenderer("RANDOM") },
|
|
1308
|
+
{ name: "RAND", renderer: noArgsRenderer("RAND") },
|
|
1309
|
+
{
|
|
1310
|
+
name: "ROUND",
|
|
1311
|
+
renderer: ({ compiledArgs }) => compiledArgs.length === 2 ? `ROUND(${compiledArgs[0]}, ${compiledArgs[1]})` : `ROUND(${compiledArgs[0]})`
|
|
1312
|
+
},
|
|
1313
|
+
{ name: "SIGN", renderer: unaryRenderer("SIGN") },
|
|
1314
|
+
{ name: "SIN", renderer: unaryRenderer("SIN") },
|
|
1315
|
+
{ name: "SQRT", renderer: unaryRenderer("SQRT") },
|
|
1316
|
+
{ name: "TAN", renderer: unaryRenderer("TAN") },
|
|
1317
|
+
{
|
|
1318
|
+
name: "TRUNC",
|
|
1319
|
+
renderer: ({ compiledArgs }) => compiledArgs.length === 2 ? `TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})` : `TRUNC(${compiledArgs[0]})`
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
name: "TRUNCATE",
|
|
1323
|
+
renderer: ({ compiledArgs }) => `TRUNCATE(${compiledArgs[0]}, ${compiledArgs[1]})`
|
|
1324
|
+
}
|
|
1325
|
+
];
|
|
1326
|
+
|
|
1327
|
+
// src/core/functions/definitions/control-flow.ts
|
|
1328
|
+
var controlFlowFunctionDefinitions = [
|
|
1329
|
+
{
|
|
1330
|
+
name: "COALESCE",
|
|
1331
|
+
renderer: ({ compiledArgs }) => `COALESCE(${compiledArgs.join(", ")})`
|
|
1332
|
+
},
|
|
1333
|
+
{
|
|
1334
|
+
name: "NULLIF",
|
|
1335
|
+
renderer: ({ compiledArgs }) => `NULLIF(${compiledArgs[0]}, ${compiledArgs[1]})`
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
name: "GREATEST",
|
|
1339
|
+
renderer: ({ compiledArgs }) => `GREATEST(${compiledArgs.join(", ")})`
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
name: "LEAST",
|
|
1343
|
+
renderer: ({ compiledArgs }) => `LEAST(${compiledArgs.join(", ")})`
|
|
1344
|
+
},
|
|
1345
|
+
{
|
|
1346
|
+
name: "IFNULL",
|
|
1347
|
+
renderer: ({ compiledArgs }) => `IFNULL(${compiledArgs[0]}, ${compiledArgs[1]})`
|
|
1348
|
+
}
|
|
1349
|
+
];
|
|
1350
|
+
|
|
1351
|
+
// src/core/functions/definitions/json.ts
|
|
1352
|
+
var jsonFunctionDefinitions = [
|
|
1353
|
+
{
|
|
1354
|
+
name: "JSON_LENGTH",
|
|
1355
|
+
renderer: ({ compiledArgs }) => {
|
|
1356
|
+
if (compiledArgs.length === 0 || compiledArgs.length > 2) {
|
|
1357
|
+
throw new Error("JSON_LENGTH expects 1 or 2 arguments");
|
|
1358
|
+
}
|
|
1359
|
+
return `JSON_LENGTH(${compiledArgs.join(", ")})`;
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
name: "JSON_SET",
|
|
1364
|
+
renderer: ({ compiledArgs }) => {
|
|
1365
|
+
if (compiledArgs.length < 3 || (compiledArgs.length - 1) % 2 !== 0) {
|
|
1366
|
+
throw new Error("JSON_SET expects a JSON document followed by one or more path/value pairs");
|
|
1367
|
+
}
|
|
1368
|
+
return `JSON_SET(${compiledArgs.join(", ")})`;
|
|
1369
|
+
}
|
|
1370
|
+
},
|
|
1371
|
+
{
|
|
1372
|
+
name: "JSON_ARRAYAGG",
|
|
1373
|
+
renderer: ({ compiledArgs }) => {
|
|
1374
|
+
if (compiledArgs.length !== 1) {
|
|
1375
|
+
throw new Error("JSON_ARRAYAGG expects exactly one argument");
|
|
1376
|
+
}
|
|
1377
|
+
return `JSON_ARRAYAGG(${compiledArgs[0]})`;
|
|
1378
|
+
}
|
|
1379
|
+
},
|
|
1380
|
+
{
|
|
1381
|
+
name: "JSON_CONTAINS",
|
|
1382
|
+
renderer: ({ compiledArgs }) => {
|
|
1383
|
+
if (compiledArgs.length < 2 || compiledArgs.length > 3) {
|
|
1384
|
+
throw new Error("JSON_CONTAINS expects two or three arguments");
|
|
1385
|
+
}
|
|
1386
|
+
return `JSON_CONTAINS(${compiledArgs.join(", ")})`;
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
1389
|
+
{
|
|
1390
|
+
name: "ARRAY_APPEND",
|
|
1391
|
+
renderer: ({ compiledArgs }) => {
|
|
1392
|
+
if (compiledArgs.length !== 2) {
|
|
1393
|
+
throw new Error("ARRAY_APPEND expects exactly two arguments");
|
|
1394
|
+
}
|
|
1395
|
+
return `ARRAY_APPEND(${compiledArgs[0]}, ${compiledArgs[1]})`;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
];
|
|
1399
|
+
|
|
1400
|
+
// src/core/functions/group-concat-helpers.ts
|
|
1401
|
+
var DEFAULT_GROUP_CONCAT_SEPARATOR = {
|
|
1402
|
+
type: "Literal",
|
|
1403
|
+
value: ","
|
|
1404
|
+
};
|
|
1405
|
+
function buildGroupConcatOrderBy(ctx) {
|
|
1406
|
+
const orderBy = ctx.node.orderBy;
|
|
1407
|
+
if (!orderBy || orderBy.length === 0) {
|
|
1408
|
+
return "";
|
|
1409
|
+
}
|
|
1410
|
+
const parts = orderBy.map((order) => {
|
|
1411
|
+
const term = isOperandNode(order.term) ? ctx.compileOperand(order.term) : (() => {
|
|
1412
|
+
throw new Error("ORDER BY expressions inside functions must be operands");
|
|
1413
|
+
})();
|
|
1414
|
+
const collation = order.collation ? ` COLLATE ${order.collation}` : "";
|
|
1415
|
+
const nulls = order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
1416
|
+
return `${term} ${order.direction}${collation}${nulls}`;
|
|
1417
|
+
});
|
|
1418
|
+
return `ORDER BY ${parts.join(", ")}`;
|
|
1419
|
+
}
|
|
1420
|
+
function formatGroupConcatSeparator(ctx) {
|
|
1421
|
+
if (!ctx.node.separator) {
|
|
1422
|
+
return "";
|
|
1423
|
+
}
|
|
1424
|
+
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
1425
|
+
}
|
|
1426
|
+
function getGroupConcatSeparatorOperand(ctx) {
|
|
1427
|
+
return ctx.node.separator ?? DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
1428
|
+
}
|
|
1429
|
+
function renderStandardGroupConcat(ctx) {
|
|
1430
|
+
const arg = ctx.compiledArgs[0];
|
|
1431
|
+
const orderClause = buildGroupConcatOrderBy(ctx);
|
|
1432
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1433
|
+
const separatorClause = formatGroupConcatSeparator(ctx);
|
|
1434
|
+
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1076
1437
|
// src/core/functions/standard-strategy.ts
|
|
1077
|
-
var StandardFunctionStrategy = class
|
|
1438
|
+
var StandardFunctionStrategy = class {
|
|
1078
1439
|
/**
|
|
1079
1440
|
* Creates a new StandardFunctionStrategy and registers standard functions.
|
|
1080
1441
|
*/
|
|
1081
|
-
constructor() {
|
|
1082
|
-
this.
|
|
1442
|
+
constructor(registry2) {
|
|
1443
|
+
this.registry = registry2 ?? new FunctionRegistry();
|
|
1083
1444
|
this.registerStandard();
|
|
1084
1445
|
}
|
|
1085
1446
|
registerStandard() {
|
|
1086
|
-
this.
|
|
1087
|
-
this.
|
|
1088
|
-
this.
|
|
1089
|
-
this.
|
|
1090
|
-
this.
|
|
1091
|
-
this.
|
|
1092
|
-
this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
|
|
1093
|
-
this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
|
|
1094
|
-
this.add("LENGTH", ({ compiledArgs }) => `LENGTH(${compiledArgs[0]})`);
|
|
1095
|
-
this.add("TRIM", ({ compiledArgs }) => `TRIM(${compiledArgs[0]})`);
|
|
1096
|
-
this.add("LTRIM", ({ compiledArgs }) => `LTRIM(${compiledArgs[0]})`);
|
|
1097
|
-
this.add("RTRIM", ({ compiledArgs }) => `RTRIM(${compiledArgs[0]})`);
|
|
1098
|
-
this.add("SUBSTRING", ({ compiledArgs }) => `SUBSTRING(${compiledArgs.join(", ")})`);
|
|
1099
|
-
this.add("CONCAT", ({ compiledArgs }) => `CONCAT(${compiledArgs.join(", ")})`);
|
|
1100
|
-
this.add("NOW", () => `NOW()`);
|
|
1101
|
-
this.add("CURRENT_DATE", () => `CURRENT_DATE`);
|
|
1102
|
-
this.add("CURRENT_TIME", () => `CURRENT_TIME`);
|
|
1103
|
-
this.add("EXTRACT", ({ compiledArgs }) => `EXTRACT(${compiledArgs[0]} FROM ${compiledArgs[1]})`);
|
|
1104
|
-
this.add("YEAR", ({ compiledArgs }) => `EXTRACT(YEAR FROM ${compiledArgs[0]})`);
|
|
1105
|
-
this.add("MONTH", ({ compiledArgs }) => `EXTRACT(MONTH FROM ${compiledArgs[0]})`);
|
|
1106
|
-
this.add("DAY", ({ compiledArgs }) => `EXTRACT(DAY FROM ${compiledArgs[0]})`);
|
|
1107
|
-
this.add("DATE_ADD", ({ compiledArgs }) => `(${compiledArgs[0]} + INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})`);
|
|
1108
|
-
this.add("DATE_SUB", ({ compiledArgs }) => `(${compiledArgs[0]} - INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})`);
|
|
1109
|
-
this.add("DATE_DIFF", ({ compiledArgs }) => `DATEDIFF(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
1110
|
-
this.add("DATE_FORMAT", ({ compiledArgs }) => `DATE_FORMAT(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
1111
|
-
this.add("UNIX_TIMESTAMP", () => `UNIX_TIMESTAMP()`);
|
|
1112
|
-
this.add("FROM_UNIXTIME", ({ compiledArgs }) => `FROM_UNIXTIME(${compiledArgs[0]})`);
|
|
1113
|
-
this.add("END_OF_MONTH", ({ compiledArgs }) => `LAST_DAY(${compiledArgs[0]})`);
|
|
1114
|
-
this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
|
|
1115
|
-
this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
|
|
1116
|
-
this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
1447
|
+
this.registerDefinitions(aggregateFunctionDefinitions);
|
|
1448
|
+
this.registerDefinitions(stringFunctionDefinitions);
|
|
1449
|
+
this.registerDefinitions(dateTimeFunctionDefinitions);
|
|
1450
|
+
this.registerDefinitions(numericFunctionDefinitions);
|
|
1451
|
+
this.registerDefinitions(controlFlowFunctionDefinitions);
|
|
1452
|
+
this.registerDefinitions(jsonFunctionDefinitions);
|
|
1117
1453
|
this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
|
|
1118
1454
|
}
|
|
1455
|
+
registerDefinitions(definitions) {
|
|
1456
|
+
this.registry.register(definitions);
|
|
1457
|
+
}
|
|
1119
1458
|
/**
|
|
1120
1459
|
* Registers a renderer for a function name.
|
|
1121
1460
|
* @param name - The function name.
|
|
1122
1461
|
* @param renderer - The renderer function.
|
|
1123
1462
|
*/
|
|
1124
1463
|
add(name, renderer) {
|
|
1125
|
-
this.
|
|
1464
|
+
this.registry.add(name, renderer);
|
|
1126
1465
|
}
|
|
1127
1466
|
/**
|
|
1128
1467
|
* @inheritDoc
|
|
1129
1468
|
*/
|
|
1130
1469
|
getRenderer(name) {
|
|
1131
|
-
return this.
|
|
1470
|
+
return this.registry.get(name);
|
|
1132
1471
|
}
|
|
1133
1472
|
/**
|
|
1134
1473
|
* Renders the GROUP_CONCAT function with optional ORDER BY and SEPARATOR.
|
|
@@ -1136,11 +1475,7 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
|
1136
1475
|
* @returns The rendered SQL string.
|
|
1137
1476
|
*/
|
|
1138
1477
|
renderGroupConcat(ctx) {
|
|
1139
|
-
|
|
1140
|
-
const orderClause = this.buildOrderByExpression(ctx);
|
|
1141
|
-
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1142
|
-
const separatorClause = this.formatGroupConcatSeparator(ctx);
|
|
1143
|
-
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
1478
|
+
return renderStandardGroupConcat(ctx);
|
|
1144
1479
|
}
|
|
1145
1480
|
/**
|
|
1146
1481
|
* Builds the ORDER BY clause for functions like GROUP_CONCAT.
|
|
@@ -1148,19 +1483,7 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
|
1148
1483
|
* @returns The ORDER BY SQL clause or empty string.
|
|
1149
1484
|
*/
|
|
1150
1485
|
buildOrderByExpression(ctx) {
|
|
1151
|
-
|
|
1152
|
-
if (!orderBy || orderBy.length === 0) {
|
|
1153
|
-
return "";
|
|
1154
|
-
}
|
|
1155
|
-
const parts = orderBy.map((order) => {
|
|
1156
|
-
const term = isOperandNode(order.term) ? ctx.compileOperand(order.term) : (() => {
|
|
1157
|
-
throw new Error("ORDER BY expressions inside functions must be operands");
|
|
1158
|
-
})();
|
|
1159
|
-
const collation = order.collation ? ` COLLATE ${order.collation}` : "";
|
|
1160
|
-
const nulls = order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
1161
|
-
return `${term} ${order.direction}${collation}${nulls}`;
|
|
1162
|
-
});
|
|
1163
|
-
return `ORDER BY ${parts.join(", ")}`;
|
|
1486
|
+
return buildGroupConcatOrderBy(ctx);
|
|
1164
1487
|
}
|
|
1165
1488
|
/**
|
|
1166
1489
|
* Formats the SEPARATOR clause for GROUP_CONCAT.
|
|
@@ -1168,10 +1491,7 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
|
1168
1491
|
* @returns The SEPARATOR SQL clause or empty string.
|
|
1169
1492
|
*/
|
|
1170
1493
|
formatGroupConcatSeparator(ctx) {
|
|
1171
|
-
|
|
1172
|
-
return "";
|
|
1173
|
-
}
|
|
1174
|
-
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
1494
|
+
return formatGroupConcatSeparator(ctx);
|
|
1175
1495
|
}
|
|
1176
1496
|
/**
|
|
1177
1497
|
* Gets the separator operand for GROUP_CONCAT, defaulting to comma.
|
|
@@ -1179,14 +1499,24 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
|
1179
1499
|
* @returns The separator operand.
|
|
1180
1500
|
*/
|
|
1181
1501
|
getGroupConcatSeparatorOperand(ctx) {
|
|
1182
|
-
return ctx
|
|
1502
|
+
return getGroupConcatSeparatorOperand(ctx);
|
|
1183
1503
|
}
|
|
1184
1504
|
static {
|
|
1185
1505
|
/** Default separator for GROUP_CONCAT, a comma. */
|
|
1186
|
-
this.DEFAULT_GROUP_CONCAT_SEPARATOR =
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1506
|
+
this.DEFAULT_GROUP_CONCAT_SEPARATOR = DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
1507
|
+
}
|
|
1508
|
+
};
|
|
1509
|
+
|
|
1510
|
+
// src/core/functions/standard-table-strategy.ts
|
|
1511
|
+
var StandardTableFunctionStrategy = class {
|
|
1512
|
+
constructor() {
|
|
1513
|
+
this.renderers = /* @__PURE__ */ new Map();
|
|
1514
|
+
}
|
|
1515
|
+
add(key, renderer) {
|
|
1516
|
+
this.renderers.set(key, renderer);
|
|
1517
|
+
}
|
|
1518
|
+
getRenderer(key) {
|
|
1519
|
+
return this.renderers.get(key);
|
|
1190
1520
|
}
|
|
1191
1521
|
};
|
|
1192
1522
|
|
|
@@ -1360,10 +1690,11 @@ var Dialect = class _Dialect {
|
|
|
1360
1690
|
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1361
1691
|
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1362
1692
|
}
|
|
1363
|
-
constructor(functionStrategy) {
|
|
1693
|
+
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1364
1694
|
this.expressionCompilers = /* @__PURE__ */ new Map();
|
|
1365
1695
|
this.operandCompilers = /* @__PURE__ */ new Map();
|
|
1366
1696
|
this.functionStrategy = functionStrategy || new StandardFunctionStrategy();
|
|
1697
|
+
this.tableFunctionStrategy = tableFunctionStrategy || new StandardTableFunctionStrategy();
|
|
1367
1698
|
this.registerDefaultOperandCompilers();
|
|
1368
1699
|
this.registerDefaultExpressionCompilers();
|
|
1369
1700
|
}
|
|
@@ -1372,7 +1703,7 @@ var Dialect = class _Dialect {
|
|
|
1372
1703
|
* @param functionStrategy - Optional function strategy
|
|
1373
1704
|
* @returns New Dialect instance
|
|
1374
1705
|
*/
|
|
1375
|
-
static create(functionStrategy) {
|
|
1706
|
+
static create(functionStrategy, tableFunctionStrategy) {
|
|
1376
1707
|
class TestDialect extends _Dialect {
|
|
1377
1708
|
constructor() {
|
|
1378
1709
|
super(...arguments);
|
|
@@ -1394,7 +1725,7 @@ var Dialect = class _Dialect {
|
|
|
1394
1725
|
throw new Error("Not implemented");
|
|
1395
1726
|
}
|
|
1396
1727
|
}
|
|
1397
|
-
return new TestDialect(functionStrategy);
|
|
1728
|
+
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
1398
1729
|
}
|
|
1399
1730
|
/**
|
|
1400
1731
|
* Registers an expression compiler for a specific node type
|
|
@@ -1495,6 +1826,11 @@ var Dialect = class _Dialect {
|
|
|
1495
1826
|
const right2 = this.compileOperand(arith.right, ctx);
|
|
1496
1827
|
return `${left2} ${arith.operator} ${right2}`;
|
|
1497
1828
|
});
|
|
1829
|
+
this.registerExpressionCompiler("BitwiseExpression", (bitwise, ctx) => {
|
|
1830
|
+
const left2 = this.compileOperand(bitwise.left, ctx);
|
|
1831
|
+
const right2 = this.compileOperand(bitwise.right, ctx);
|
|
1832
|
+
return `${left2} ${bitwise.operator} ${right2}`;
|
|
1833
|
+
});
|
|
1498
1834
|
}
|
|
1499
1835
|
registerDefaultOperandCompilers() {
|
|
1500
1836
|
this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
|
|
@@ -1564,6 +1900,15 @@ var Dialect = class _Dialect {
|
|
|
1564
1900
|
const right2 = this.compileOperand(node.right, ctx);
|
|
1565
1901
|
return `(${left2} ${node.operator} ${right2})`;
|
|
1566
1902
|
});
|
|
1903
|
+
this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
|
|
1904
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
1905
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
1906
|
+
return `(${left2} ${node.operator} ${right2})`;
|
|
1907
|
+
});
|
|
1908
|
+
this.registerOperandCompiler("Collate", (node, ctx) => {
|
|
1909
|
+
const expr = this.compileOperand(node.expression, ctx);
|
|
1910
|
+
return `${expr} COLLATE ${node.collation}`;
|
|
1911
|
+
});
|
|
1567
1912
|
}
|
|
1568
1913
|
// Default fallback, should be overridden by dialects if supported
|
|
1569
1914
|
compileJsonPath(_node) {
|
|
@@ -1596,13 +1941,13 @@ var FunctionTableFormatter = class {
|
|
|
1596
1941
|
* @param dialect - The dialect instance for compiling operands.
|
|
1597
1942
|
* @returns SQL function table expression (e.g., "LATERAL schema.func(args) WITH ORDINALITY AS alias(col1, col2)").
|
|
1598
1943
|
*/
|
|
1599
|
-
static format(
|
|
1600
|
-
const schemaPart = this.formatSchema(
|
|
1601
|
-
const args = this.formatArgs(
|
|
1602
|
-
const base = this.formatBase(
|
|
1603
|
-
const lateral = this.formatLateral(
|
|
1604
|
-
const alias = this.formatAlias(
|
|
1605
|
-
const colAliases = this.formatColumnAliases(
|
|
1944
|
+
static format(fn8, ctx, dialect) {
|
|
1945
|
+
const schemaPart = this.formatSchema(fn8, dialect);
|
|
1946
|
+
const args = this.formatArgs(fn8, ctx, dialect);
|
|
1947
|
+
const base = this.formatBase(fn8, schemaPart, args);
|
|
1948
|
+
const lateral = this.formatLateral(fn8);
|
|
1949
|
+
const alias = this.formatAlias(fn8, dialect);
|
|
1950
|
+
const colAliases = this.formatColumnAliases(fn8, dialect);
|
|
1606
1951
|
return `${lateral}${base}${alias}${colAliases}`;
|
|
1607
1952
|
}
|
|
1608
1953
|
/**
|
|
@@ -1612,9 +1957,9 @@ var FunctionTableFormatter = class {
|
|
|
1612
1957
|
* @returns Schema prefix (e.g., "schema.") or empty string.
|
|
1613
1958
|
* @internal
|
|
1614
1959
|
*/
|
|
1615
|
-
static formatSchema(
|
|
1616
|
-
if (!
|
|
1617
|
-
const quoted = dialect ? dialect.quoteIdentifier(
|
|
1960
|
+
static formatSchema(fn8, dialect) {
|
|
1961
|
+
if (!fn8.schema) return "";
|
|
1962
|
+
const quoted = dialect ? dialect.quoteIdentifier(fn8.schema) : fn8.schema;
|
|
1618
1963
|
return `${quoted}.`;
|
|
1619
1964
|
}
|
|
1620
1965
|
/**
|
|
@@ -1625,8 +1970,8 @@ var FunctionTableFormatter = class {
|
|
|
1625
1970
|
* @returns Comma-separated function arguments.
|
|
1626
1971
|
* @internal
|
|
1627
1972
|
*/
|
|
1628
|
-
static formatArgs(
|
|
1629
|
-
return (
|
|
1973
|
+
static formatArgs(fn8, ctx, dialect) {
|
|
1974
|
+
return (fn8.args || []).map((a) => {
|
|
1630
1975
|
if (ctx && dialect) {
|
|
1631
1976
|
return dialect.compileOperand(a, ctx);
|
|
1632
1977
|
}
|
|
@@ -1642,10 +1987,9 @@ var FunctionTableFormatter = class {
|
|
|
1642
1987
|
* @returns Base function call expression (e.g., "schema.func(args) WITH ORDINALITY").
|
|
1643
1988
|
* @internal
|
|
1644
1989
|
*/
|
|
1645
|
-
static formatBase(
|
|
1646
|
-
const ordinality =
|
|
1647
|
-
|
|
1648
|
-
return `${schemaPart}${quoted}(${args})${ordinality}`;
|
|
1990
|
+
static formatBase(fn8, schemaPart, args) {
|
|
1991
|
+
const ordinality = fn8.withOrdinality ? " WITH ORDINALITY" : "";
|
|
1992
|
+
return `${schemaPart}${fn8.name}(${args})${ordinality}`;
|
|
1649
1993
|
}
|
|
1650
1994
|
/**
|
|
1651
1995
|
* Formats the LATERAL keyword if present.
|
|
@@ -1653,8 +1997,8 @@ var FunctionTableFormatter = class {
|
|
|
1653
1997
|
* @returns "LATERAL " or empty string.
|
|
1654
1998
|
* @internal
|
|
1655
1999
|
*/
|
|
1656
|
-
static formatLateral(
|
|
1657
|
-
return
|
|
2000
|
+
static formatLateral(fn8) {
|
|
2001
|
+
return fn8.lateral ? "LATERAL " : "";
|
|
1658
2002
|
}
|
|
1659
2003
|
/**
|
|
1660
2004
|
* Formats the table alias for the function table.
|
|
@@ -1663,9 +2007,9 @@ var FunctionTableFormatter = class {
|
|
|
1663
2007
|
* @returns " AS alias" or empty string.
|
|
1664
2008
|
* @internal
|
|
1665
2009
|
*/
|
|
1666
|
-
static formatAlias(
|
|
1667
|
-
if (!
|
|
1668
|
-
const quoted = dialect ? dialect.quoteIdentifier(
|
|
2010
|
+
static formatAlias(fn8, dialect) {
|
|
2011
|
+
if (!fn8.alias) return "";
|
|
2012
|
+
const quoted = dialect ? dialect.quoteIdentifier(fn8.alias) : fn8.alias;
|
|
1669
2013
|
return ` AS ${quoted}`;
|
|
1670
2014
|
}
|
|
1671
2015
|
/**
|
|
@@ -1675,9 +2019,9 @@ var FunctionTableFormatter = class {
|
|
|
1675
2019
|
* @returns "(col1, col2, ...)" or empty string.
|
|
1676
2020
|
* @internal
|
|
1677
2021
|
*/
|
|
1678
|
-
static formatColumnAliases(
|
|
1679
|
-
if (!
|
|
1680
|
-
const aliases =
|
|
2022
|
+
static formatColumnAliases(fn8, dialect) {
|
|
2023
|
+
if (!fn8.columnAliases || !fn8.columnAliases.length) return "";
|
|
2024
|
+
const aliases = fn8.columnAliases.map((col2) => dialect ? dialect.quoteIdentifier(col2) : col2).join(", ");
|
|
1681
2025
|
return `(${aliases})`;
|
|
1682
2026
|
}
|
|
1683
2027
|
};
|
|
@@ -1945,8 +2289,24 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1945
2289
|
}
|
|
1946
2290
|
return this.compileTableSource(tableSource);
|
|
1947
2291
|
}
|
|
1948
|
-
compileFunctionTable(
|
|
1949
|
-
|
|
2292
|
+
compileFunctionTable(fn8, ctx) {
|
|
2293
|
+
const key = fn8.key ?? fn8.name;
|
|
2294
|
+
if (ctx) {
|
|
2295
|
+
const renderer = this.tableFunctionStrategy.getRenderer(key);
|
|
2296
|
+
if (renderer) {
|
|
2297
|
+
const compiledArgs = (fn8.args ?? []).map((arg) => this.compileOperand(arg, ctx));
|
|
2298
|
+
return renderer({
|
|
2299
|
+
node: fn8,
|
|
2300
|
+
compiledArgs,
|
|
2301
|
+
compileOperand: (operand) => this.compileOperand(operand, ctx),
|
|
2302
|
+
quoteIdentifier: this.quoteIdentifier.bind(this)
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
if (fn8.key) {
|
|
2306
|
+
throw new Error(`Table function "${key}" is not supported by dialect "${this.dialect}".`);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
return FunctionTableFormatter.format(fn8, ctx, this);
|
|
1950
2310
|
}
|
|
1951
2311
|
compileDerivedTable(table, ctx) {
|
|
1952
2312
|
if (!table.alias) {
|
|
@@ -2105,6 +2465,76 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2105
2465
|
const separator = ctx.compileOperand(separatorOperand);
|
|
2106
2466
|
return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
|
|
2107
2467
|
});
|
|
2468
|
+
this.add("CHR", ({ compiledArgs }) => `CHR(${compiledArgs[0]})`);
|
|
2469
|
+
this.add("HOUR", ({ compiledArgs }) => `EXTRACT(HOUR FROM ${compiledArgs[0]})`);
|
|
2470
|
+
this.add("MINUTE", ({ compiledArgs }) => `EXTRACT(MINUTE FROM ${compiledArgs[0]})`);
|
|
2471
|
+
this.add("SECOND", ({ compiledArgs }) => `EXTRACT(SECOND FROM ${compiledArgs[0]})`);
|
|
2472
|
+
this.add("QUARTER", ({ compiledArgs }) => `EXTRACT(QUARTER FROM ${compiledArgs[0]})`);
|
|
2473
|
+
this.add("JSON_LENGTH", ({ compiledArgs }) => {
|
|
2474
|
+
if (compiledArgs.length !== 1) throw new Error("JSON_LENGTH expects 1 argument on PostgreSQL");
|
|
2475
|
+
return `jsonb_array_length(${compiledArgs[0]})`;
|
|
2476
|
+
});
|
|
2477
|
+
this.add("JSON_ARRAYAGG", ({ compiledArgs }) => {
|
|
2478
|
+
if (compiledArgs.length !== 1) throw new Error("JSON_ARRAYAGG expects 1 argument on PostgreSQL");
|
|
2479
|
+
return `jsonb_agg(${compiledArgs[0]})`;
|
|
2480
|
+
});
|
|
2481
|
+
this.add("JSON_CONTAINS", ({ compiledArgs }) => {
|
|
2482
|
+
if (compiledArgs.length !== 2) throw new Error("JSON_CONTAINS expects 2 arguments on PostgreSQL");
|
|
2483
|
+
return `(${compiledArgs[0]}::jsonb @> ${compiledArgs[1]}::jsonb)`;
|
|
2484
|
+
});
|
|
2485
|
+
this.add("ARRAY_APPEND", ({ compiledArgs }) => {
|
|
2486
|
+
if (compiledArgs.length !== 2) throw new Error("ARRAY_APPEND expects 2 arguments on PostgreSQL");
|
|
2487
|
+
return `array_append(${compiledArgs[0]}, ${compiledArgs[1]})`;
|
|
2488
|
+
});
|
|
2489
|
+
this.add("JSON_SET", ({ node, compiledArgs }) => {
|
|
2490
|
+
if (compiledArgs.length !== 3) throw new Error("JSON_SET expects exactly 3 arguments on PostgreSQL");
|
|
2491
|
+
const pathNode = node.args[1];
|
|
2492
|
+
if (pathNode.type !== "Literal") {
|
|
2493
|
+
throw new Error("PostgreSQL JSON_SET currently supports literal paths only");
|
|
2494
|
+
}
|
|
2495
|
+
const pathArray = this.formatJsonbPathArray(pathNode);
|
|
2496
|
+
return `jsonb_set(${compiledArgs[0]}, ${pathArray}, ${compiledArgs[2]}::jsonb, true)`;
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
formatJsonbPathArray(pathNode) {
|
|
2500
|
+
const rawPath = String(pathNode.value ?? "");
|
|
2501
|
+
if (!rawPath.startsWith("$")) {
|
|
2502
|
+
throw new Error('PostgreSQL JSON_SET paths must start with "$"');
|
|
2503
|
+
}
|
|
2504
|
+
const trimmed = rawPath === "$" ? "" : rawPath.startsWith("$.") ? rawPath.slice(2) : rawPath.slice(1);
|
|
2505
|
+
if (!trimmed) {
|
|
2506
|
+
throw new Error("PostgreSQL JSON_SET requires a non-root path");
|
|
2507
|
+
}
|
|
2508
|
+
if (trimmed.includes("[") || trimmed.includes("]")) {
|
|
2509
|
+
throw new Error("PostgreSQL JSON_SET currently only supports simple dot-separated paths");
|
|
2510
|
+
}
|
|
2511
|
+
const segments = trimmed.split(".").map((segment) => segment.replace(/^['"]?/, "").replace(/['"]?$/, "").trim()).filter(Boolean);
|
|
2512
|
+
if (!segments.length) {
|
|
2513
|
+
throw new Error("PostgreSQL JSON_SET requires at least one path segment");
|
|
2514
|
+
}
|
|
2515
|
+
const escapedSegments = segments.map((segment) => `'${segment.replace(/'/g, "''")}'`);
|
|
2516
|
+
return `ARRAY[${escapedSegments.join(", ")}]`;
|
|
2517
|
+
}
|
|
2518
|
+
};
|
|
2519
|
+
|
|
2520
|
+
// src/core/dialect/postgres/table-functions.ts
|
|
2521
|
+
var PostgresTableFunctionStrategy = class extends StandardTableFunctionStrategy {
|
|
2522
|
+
constructor() {
|
|
2523
|
+
super();
|
|
2524
|
+
this.registerOverrides();
|
|
2525
|
+
}
|
|
2526
|
+
registerOverrides() {
|
|
2527
|
+
this.add("ARRAY_UNNEST", ({ node, compiledArgs, quoteIdentifier }) => {
|
|
2528
|
+
const lateral = node.lateral ?? true;
|
|
2529
|
+
const withOrd = node.withOrdinality ?? false;
|
|
2530
|
+
const base = `unnest(${compiledArgs.join(", ")})${withOrd ? " WITH ORDINALITY" : ""}`;
|
|
2531
|
+
if (node.columnAliases?.length && !node.alias) {
|
|
2532
|
+
throw new Error("tvf(ARRAY_UNNEST) with columnAliases requires an alias.");
|
|
2533
|
+
}
|
|
2534
|
+
const alias = node.alias ? ` AS ${quoteIdentifier(node.alias)}` : "";
|
|
2535
|
+
const cols = node.columnAliases?.length ? `(${node.columnAliases.map(quoteIdentifier).join(", ")})` : "";
|
|
2536
|
+
return `${lateral ? "LATERAL " : ""}${base}${alias}${cols}`;
|
|
2537
|
+
});
|
|
2108
2538
|
}
|
|
2109
2539
|
};
|
|
2110
2540
|
|
|
@@ -2114,8 +2544,20 @@ var PostgresDialect = class extends SqlDialectBase {
|
|
|
2114
2544
|
* Creates a new PostgresDialect instance
|
|
2115
2545
|
*/
|
|
2116
2546
|
constructor() {
|
|
2117
|
-
super(new PostgresFunctionStrategy());
|
|
2547
|
+
super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
|
|
2118
2548
|
this.dialect = "postgres";
|
|
2549
|
+
this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
|
|
2550
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2551
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2552
|
+
const op = node.operator === "^" ? "#" : node.operator;
|
|
2553
|
+
return `${left2} ${op} ${right2}`;
|
|
2554
|
+
});
|
|
2555
|
+
this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
|
|
2556
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2557
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2558
|
+
const op = node.operator === "^" ? "#" : node.operator;
|
|
2559
|
+
return `(${left2} ${op} ${right2})`;
|
|
2560
|
+
});
|
|
2119
2561
|
}
|
|
2120
2562
|
/**
|
|
2121
2563
|
* Quotes an identifier using PostgreSQL double-quote syntax
|
|
@@ -2224,6 +2666,14 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2224
2666
|
}
|
|
2225
2667
|
return `DATE(${date})`;
|
|
2226
2668
|
});
|
|
2669
|
+
this.add("HOUR", ({ compiledArgs }) => `HOUR(${compiledArgs[0]})`);
|
|
2670
|
+
this.add("MINUTE", ({ compiledArgs }) => `MINUTE(${compiledArgs[0]})`);
|
|
2671
|
+
this.add("SECOND", ({ compiledArgs }) => `SECOND(${compiledArgs[0]})`);
|
|
2672
|
+
this.add("QUARTER", ({ compiledArgs }) => `QUARTER(${compiledArgs[0]})`);
|
|
2673
|
+
this.add("ARRAY_APPEND", ({ compiledArgs }) => {
|
|
2674
|
+
if (compiledArgs.length !== 2) throw new Error("ARRAY_APPEND expects 2 arguments (array, value)");
|
|
2675
|
+
return `JSON_ARRAY_APPEND(${compiledArgs[0]}, '$', ${compiledArgs[1]})`;
|
|
2676
|
+
});
|
|
2227
2677
|
}
|
|
2228
2678
|
};
|
|
2229
2679
|
|
|
@@ -2356,6 +2806,30 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2356
2806
|
const separator = ctx.compileOperand(separatorOperand);
|
|
2357
2807
|
return `GROUP_CONCAT(${arg}, ${separator})`;
|
|
2358
2808
|
});
|
|
2809
|
+
this.add("HOUR", ({ compiledArgs }) => `CAST(strftime('%H', ${compiledArgs[0]}) AS INTEGER)`);
|
|
2810
|
+
this.add("MINUTE", ({ compiledArgs }) => `CAST(strftime('%M', ${compiledArgs[0]}) AS INTEGER)`);
|
|
2811
|
+
this.add("SECOND", ({ compiledArgs }) => `CAST(strftime('%S', ${compiledArgs[0]}) AS INTEGER)`);
|
|
2812
|
+
this.add("QUARTER", ({ compiledArgs }) => `((CAST(strftime('%m', ${compiledArgs[0]}) AS INTEGER) + 2) / 3)`);
|
|
2813
|
+
this.add("JSON_LENGTH", ({ compiledArgs }) => {
|
|
2814
|
+
if (compiledArgs.length === 0 || compiledArgs.length > 2) {
|
|
2815
|
+
throw new Error("JSON_LENGTH expects 1 or 2 arguments on SQLite");
|
|
2816
|
+
}
|
|
2817
|
+
return `json_array_length(${compiledArgs.join(", ")})`;
|
|
2818
|
+
});
|
|
2819
|
+
this.add("JSON_ARRAYAGG", ({ compiledArgs }) => {
|
|
2820
|
+
if (compiledArgs.length !== 1) {
|
|
2821
|
+
throw new Error("JSON_ARRAYAGG expects 1 argument on SQLite");
|
|
2822
|
+
}
|
|
2823
|
+
return `json_group_array(${compiledArgs[0]})`;
|
|
2824
|
+
});
|
|
2825
|
+
this.add("JSON_CONTAINS", () => {
|
|
2826
|
+
throw new Error("JSON_CONTAINS is not supported on SQLite");
|
|
2827
|
+
});
|
|
2828
|
+
this.add("ARRAY_APPEND", ({ compiledArgs }) => {
|
|
2829
|
+
if (compiledArgs.length !== 2) throw new Error("ARRAY_APPEND expects 2 arguments (array, value)");
|
|
2830
|
+
return `json_array_append(${compiledArgs[0]}, '$', ${compiledArgs[1]})`;
|
|
2831
|
+
});
|
|
2832
|
+
this.add("CHR", ({ compiledArgs }) => `CHAR(${compiledArgs[0]})`);
|
|
2359
2833
|
}
|
|
2360
2834
|
};
|
|
2361
2835
|
|
|
@@ -2367,6 +2841,22 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
2367
2841
|
constructor() {
|
|
2368
2842
|
super(new SqliteFunctionStrategy());
|
|
2369
2843
|
this.dialect = "sqlite";
|
|
2844
|
+
this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
|
|
2845
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2846
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2847
|
+
if (node.operator === "^") {
|
|
2848
|
+
return `(${left2} | ${right2}) & ~(${left2} & ${right2})`;
|
|
2849
|
+
}
|
|
2850
|
+
return `${left2} ${node.operator} ${right2}`;
|
|
2851
|
+
});
|
|
2852
|
+
this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
|
|
2853
|
+
const left2 = this.compileOperand(node.left, ctx);
|
|
2854
|
+
const right2 = this.compileOperand(node.right, ctx);
|
|
2855
|
+
if (node.operator === "^") {
|
|
2856
|
+
return `((${left2} | ${right2}) & ~(${left2} & ${right2}))`;
|
|
2857
|
+
}
|
|
2858
|
+
return `(${left2} ${node.operator} ${right2})`;
|
|
2859
|
+
});
|
|
2370
2860
|
}
|
|
2371
2861
|
/**
|
|
2372
2862
|
* Quotes an identifier using SQLite double-quote syntax
|
|
@@ -2491,6 +2981,33 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2491
2981
|
const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
|
|
2492
2982
|
return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
|
|
2493
2983
|
});
|
|
2984
|
+
this.add("LENGTH", ({ compiledArgs }) => `LEN(${compiledArgs[0]})`);
|
|
2985
|
+
this.add("CHAR_LENGTH", ({ compiledArgs }) => `LEN(${compiledArgs[0]})`);
|
|
2986
|
+
this.add("CHARACTER_LENGTH", ({ compiledArgs }) => `LEN(${compiledArgs[0]})`);
|
|
2987
|
+
this.add("POSITION", ({ compiledArgs }) => `CHARINDEX(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
2988
|
+
this.add("LOCATE", ({ compiledArgs }) => compiledArgs.length === 3 ? `CHARINDEX(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` : `CHARINDEX(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
2989
|
+
this.add("INSTR", ({ compiledArgs }) => `CHARINDEX(${compiledArgs[1]}, ${compiledArgs[0]})`);
|
|
2990
|
+
this.add("CHR", ({ compiledArgs }) => `CHAR(${compiledArgs[0]})`);
|
|
2991
|
+
this.add("HOUR", ({ compiledArgs }) => `DATEPART(hour, ${compiledArgs[0]})`);
|
|
2992
|
+
this.add("MINUTE", ({ compiledArgs }) => `DATEPART(minute, ${compiledArgs[0]})`);
|
|
2993
|
+
this.add("SECOND", ({ compiledArgs }) => `DATEPART(second, ${compiledArgs[0]})`);
|
|
2994
|
+
this.add("QUARTER", ({ compiledArgs }) => `DATEPART(quarter, ${compiledArgs[0]})`);
|
|
2995
|
+
this.add("JSON_SET", ({ compiledArgs }) => {
|
|
2996
|
+
if (compiledArgs.length !== 3) throw new Error("JSON_SET expects 3 arguments on SQL Server");
|
|
2997
|
+
return `JSON_MODIFY(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})`;
|
|
2998
|
+
});
|
|
2999
|
+
this.add("JSON_LENGTH", () => {
|
|
3000
|
+
throw new Error("JSON_LENGTH is not supported on SQL Server");
|
|
3001
|
+
});
|
|
3002
|
+
this.add("JSON_ARRAYAGG", () => {
|
|
3003
|
+
throw new Error("JSON_ARRAYAGG is not supported on SQL Server");
|
|
3004
|
+
});
|
|
3005
|
+
this.add("JSON_CONTAINS", () => {
|
|
3006
|
+
throw new Error("JSON_CONTAINS is not supported on SQL Server");
|
|
3007
|
+
});
|
|
3008
|
+
this.add("ARRAY_APPEND", () => {
|
|
3009
|
+
throw new Error("ARRAY_APPEND is not supported on SQL Server");
|
|
3010
|
+
});
|
|
2494
3011
|
}
|
|
2495
3012
|
};
|
|
2496
3013
|
|
|
@@ -3595,20 +4112,21 @@ var RelationProjectionHelper = class {
|
|
|
3595
4112
|
var assertNever = (value) => {
|
|
3596
4113
|
throw new Error(`Unhandled relation type: ${JSON.stringify(value)}`);
|
|
3597
4114
|
};
|
|
3598
|
-
var baseRelationCondition = (root, relation, rootAlias) => {
|
|
4115
|
+
var baseRelationCondition = (root, relation, rootAlias, targetTableName) => {
|
|
3599
4116
|
const rootTable = rootAlias || root.name;
|
|
4117
|
+
const targetTable = targetTableName ?? relation.target.name;
|
|
3600
4118
|
const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
|
|
3601
4119
|
const localKey = relation.localKey || defaultLocalKey;
|
|
3602
4120
|
switch (relation.type) {
|
|
3603
4121
|
case RelationKinds.HasMany:
|
|
3604
4122
|
case RelationKinds.HasOne:
|
|
3605
4123
|
return eq(
|
|
3606
|
-
{ type: "Column", table:
|
|
4124
|
+
{ type: "Column", table: targetTable, name: relation.foreignKey },
|
|
3607
4125
|
{ type: "Column", table: rootTable, name: localKey }
|
|
3608
4126
|
);
|
|
3609
4127
|
case RelationKinds.BelongsTo:
|
|
3610
4128
|
return eq(
|
|
3611
|
-
{ type: "Column", table:
|
|
4129
|
+
{ type: "Column", table: targetTable, name: localKey },
|
|
3612
4130
|
{ type: "Column", table: rootTable, name: relation.foreignKey }
|
|
3613
4131
|
);
|
|
3614
4132
|
case RelationKinds.BelongsToMany:
|
|
@@ -3617,7 +4135,7 @@ var baseRelationCondition = (root, relation, rootAlias) => {
|
|
|
3617
4135
|
return assertNever(relation);
|
|
3618
4136
|
}
|
|
3619
4137
|
};
|
|
3620
|
-
var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias) => {
|
|
4138
|
+
var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias, targetTable, targetTableName) => {
|
|
3621
4139
|
const rootKey = relation.localKey || findPrimaryKey(root);
|
|
3622
4140
|
const targetKey = relation.targetKey || findPrimaryKey(relation.target);
|
|
3623
4141
|
const rootTable = rootAlias || root.name;
|
|
@@ -3630,8 +4148,14 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, ro
|
|
|
3630
4148
|
{ type: "Table", name: relation.pivotTable.name, schema: relation.pivotTable.schema },
|
|
3631
4149
|
pivotCondition
|
|
3632
4150
|
);
|
|
4151
|
+
const targetSource = targetTable ?? {
|
|
4152
|
+
type: "Table",
|
|
4153
|
+
name: relation.target.name,
|
|
4154
|
+
schema: relation.target.schema
|
|
4155
|
+
};
|
|
4156
|
+
const effectiveTargetName = targetTableName ?? relation.target.name;
|
|
3633
4157
|
let targetCondition = eq(
|
|
3634
|
-
{ type: "Column", table:
|
|
4158
|
+
{ type: "Column", table: effectiveTargetName, name: targetKey },
|
|
3635
4159
|
{ type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToTarget }
|
|
3636
4160
|
);
|
|
3637
4161
|
if (extra) {
|
|
@@ -3639,24 +4163,25 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, ro
|
|
|
3639
4163
|
}
|
|
3640
4164
|
const targetJoin = createJoinNode(
|
|
3641
4165
|
joinKind,
|
|
3642
|
-
|
|
4166
|
+
targetSource,
|
|
3643
4167
|
targetCondition,
|
|
3644
4168
|
relationName
|
|
3645
4169
|
);
|
|
3646
4170
|
return [pivotJoin, targetJoin];
|
|
3647
4171
|
};
|
|
3648
|
-
var buildRelationJoinCondition = (root, relation, extra, rootAlias) => {
|
|
3649
|
-
const base = baseRelationCondition(root, relation, rootAlias);
|
|
4172
|
+
var buildRelationJoinCondition = (root, relation, extra, rootAlias, targetTableName) => {
|
|
4173
|
+
const base = baseRelationCondition(root, relation, rootAlias, targetTableName);
|
|
3650
4174
|
return extra ? and(base, extra) : base;
|
|
3651
4175
|
};
|
|
3652
|
-
var buildRelationCorrelation = (root, relation, rootAlias) => {
|
|
3653
|
-
return baseRelationCondition(root, relation, rootAlias);
|
|
4176
|
+
var buildRelationCorrelation = (root, relation, rootAlias, targetTableName) => {
|
|
4177
|
+
return baseRelationCondition(root, relation, rootAlias, targetTableName);
|
|
3654
4178
|
};
|
|
3655
4179
|
|
|
3656
4180
|
// src/core/ast/join-metadata.ts
|
|
3657
4181
|
var getJoinRelationName = (join) => join.meta?.relationName;
|
|
3658
4182
|
|
|
3659
4183
|
// src/query-builder/relation-service.ts
|
|
4184
|
+
var hasRelationForeignKey = (relation) => relation.type !== RelationKinds.BelongsToMany;
|
|
3660
4185
|
var RelationService = class {
|
|
3661
4186
|
/**
|
|
3662
4187
|
* Creates a new RelationService instance
|
|
@@ -3681,8 +4206,8 @@ var RelationService = class {
|
|
|
3681
4206
|
* @param extraCondition - Additional join condition
|
|
3682
4207
|
* @returns Relation result with updated state and hydration
|
|
3683
4208
|
*/
|
|
3684
|
-
joinRelation(relationName, joinKind, extraCondition) {
|
|
3685
|
-
const nextState = this.withJoin(this.state, relationName, joinKind, extraCondition);
|
|
4209
|
+
joinRelation(relationName, joinKind, extraCondition, tableSource) {
|
|
4210
|
+
const nextState = this.withJoin(this.state, relationName, joinKind, extraCondition, tableSource);
|
|
3686
4211
|
return { state: nextState, hydration: this.hydration };
|
|
3687
4212
|
}
|
|
3688
4213
|
/**
|
|
@@ -3711,14 +4236,58 @@ var RelationService = class {
|
|
|
3711
4236
|
const relation = this.getRelation(relationName);
|
|
3712
4237
|
const aliasPrefix = options?.aliasPrefix ?? relationName;
|
|
3713
4238
|
const alreadyJoined = state.ast.joins.some((j) => getJoinRelationName(j) === relationName);
|
|
4239
|
+
const { selfFilters, crossFilters } = this.splitFilterExpressions(
|
|
4240
|
+
options?.filter,
|
|
4241
|
+
/* @__PURE__ */ new Set([relation.target.name])
|
|
4242
|
+
);
|
|
4243
|
+
const canUseCte = !alreadyJoined && selfFilters.length > 0;
|
|
4244
|
+
const joinFilters = [...crossFilters];
|
|
4245
|
+
if (!canUseCte) {
|
|
4246
|
+
joinFilters.push(...selfFilters);
|
|
4247
|
+
}
|
|
4248
|
+
const joinCondition = this.combineWithAnd(joinFilters);
|
|
4249
|
+
let tableSourceOverride;
|
|
4250
|
+
if (canUseCte) {
|
|
4251
|
+
const cteInfo = this.createFilteredRelationCte(state, relationName, relation, selfFilters);
|
|
4252
|
+
state = cteInfo.state;
|
|
4253
|
+
tableSourceOverride = cteInfo.table;
|
|
4254
|
+
}
|
|
3714
4255
|
if (!alreadyJoined) {
|
|
3715
|
-
|
|
3716
|
-
|
|
4256
|
+
state = this.withJoin(
|
|
4257
|
+
state,
|
|
4258
|
+
relationName,
|
|
4259
|
+
options?.joinKind ?? JOIN_KINDS.LEFT,
|
|
4260
|
+
joinCondition,
|
|
4261
|
+
tableSourceOverride
|
|
4262
|
+
);
|
|
3717
4263
|
}
|
|
3718
4264
|
const projectionResult = this.projectionHelper.ensureBaseProjection(state, hydration);
|
|
3719
4265
|
state = projectionResult.state;
|
|
3720
4266
|
hydration = projectionResult.hydration;
|
|
3721
|
-
|
|
4267
|
+
if (hasRelationForeignKey(relation)) {
|
|
4268
|
+
const fkColumn = this.table.columns[relation.foreignKey];
|
|
4269
|
+
if (fkColumn) {
|
|
4270
|
+
const hasForeignKeySelected = state.ast.columns.some((col2) => {
|
|
4271
|
+
if (col2.type !== "Column") return false;
|
|
4272
|
+
const node = col2;
|
|
4273
|
+
const alias = node.alias ?? node.name;
|
|
4274
|
+
return alias === relation.foreignKey;
|
|
4275
|
+
});
|
|
4276
|
+
if (!hasForeignKeySelected) {
|
|
4277
|
+
const fkSelectionResult = this.selectColumns(state, hydration, {
|
|
4278
|
+
[relation.foreignKey]: fkColumn
|
|
4279
|
+
});
|
|
4280
|
+
state = fkSelectionResult.state;
|
|
4281
|
+
hydration = fkSelectionResult.hydration;
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
const requestedColumns = options?.columns?.length ? [...options.columns] : Object.keys(relation.target.columns);
|
|
4286
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
4287
|
+
if (!requestedColumns.includes(targetPrimaryKey)) {
|
|
4288
|
+
requestedColumns.push(targetPrimaryKey);
|
|
4289
|
+
}
|
|
4290
|
+
const targetColumns = requestedColumns;
|
|
3722
4291
|
const buildTypedSelection = (columns, prefix, keys, missingMsg) => {
|
|
3723
4292
|
return keys.reduce((acc, key) => {
|
|
3724
4293
|
const def = columns[key];
|
|
@@ -3802,27 +4371,42 @@ var RelationService = class {
|
|
|
3802
4371
|
* @param extraCondition - Additional join condition
|
|
3803
4372
|
* @returns Updated query state with join
|
|
3804
4373
|
*/
|
|
3805
|
-
withJoin(state, relationName, joinKind, extraCondition) {
|
|
4374
|
+
withJoin(state, relationName, joinKind, extraCondition, tableSource) {
|
|
3806
4375
|
const relation = this.getRelation(relationName);
|
|
3807
4376
|
const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
|
|
3808
4377
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
4378
|
+
const targetTableSource = tableSource ?? {
|
|
4379
|
+
type: "Table",
|
|
4380
|
+
name: relation.target.name,
|
|
4381
|
+
schema: relation.target.schema
|
|
4382
|
+
};
|
|
4383
|
+
const targetName2 = this.resolveTargetTableName(targetTableSource, relation);
|
|
3809
4384
|
const joins = buildBelongsToManyJoins(
|
|
3810
4385
|
this.table,
|
|
3811
4386
|
relationName,
|
|
3812
4387
|
relation,
|
|
3813
4388
|
joinKind,
|
|
3814
4389
|
extraCondition,
|
|
3815
|
-
rootAlias
|
|
4390
|
+
rootAlias,
|
|
4391
|
+
targetTableSource,
|
|
4392
|
+
targetName2
|
|
3816
4393
|
);
|
|
3817
4394
|
return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
|
|
3818
4395
|
}
|
|
3819
|
-
const
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
4396
|
+
const targetTable = tableSource ?? {
|
|
4397
|
+
type: "Table",
|
|
4398
|
+
name: relation.target.name,
|
|
4399
|
+
schema: relation.target.schema
|
|
4400
|
+
};
|
|
4401
|
+
const targetName = this.resolveTargetTableName(targetTable, relation);
|
|
4402
|
+
const condition = buildRelationJoinCondition(
|
|
4403
|
+
this.table,
|
|
4404
|
+
relation,
|
|
4405
|
+
extraCondition,
|
|
4406
|
+
rootAlias,
|
|
4407
|
+
targetName
|
|
3825
4408
|
);
|
|
4409
|
+
const joinNode = createJoinNode(joinKind, targetTable, condition, relationName);
|
|
3826
4410
|
return this.astService(state).withJoin(joinNode);
|
|
3827
4411
|
}
|
|
3828
4412
|
/**
|
|
@@ -3839,6 +4423,198 @@ var RelationService = class {
|
|
|
3839
4423
|
hydration: hydration.onColumnsSelected(nextState, addedColumns)
|
|
3840
4424
|
};
|
|
3841
4425
|
}
|
|
4426
|
+
combineWithAnd(expressions) {
|
|
4427
|
+
if (expressions.length === 0) return void 0;
|
|
4428
|
+
if (expressions.length === 1) return expressions[0];
|
|
4429
|
+
return {
|
|
4430
|
+
type: "LogicalExpression",
|
|
4431
|
+
operator: "AND",
|
|
4432
|
+
operands: expressions
|
|
4433
|
+
};
|
|
4434
|
+
}
|
|
4435
|
+
splitFilterExpressions(filter, allowedTables) {
|
|
4436
|
+
const terms = this.flattenAnd(filter);
|
|
4437
|
+
const selfFilters = [];
|
|
4438
|
+
const crossFilters = [];
|
|
4439
|
+
for (const term of terms) {
|
|
4440
|
+
if (this.isExpressionSelfContained(term, allowedTables)) {
|
|
4441
|
+
selfFilters.push(term);
|
|
4442
|
+
} else {
|
|
4443
|
+
crossFilters.push(term);
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
return { selfFilters, crossFilters };
|
|
4447
|
+
}
|
|
4448
|
+
flattenAnd(node) {
|
|
4449
|
+
if (!node) return [];
|
|
4450
|
+
if (node.type === "LogicalExpression" && node.operator === "AND") {
|
|
4451
|
+
return node.operands.flatMap((operand) => this.flattenAnd(operand));
|
|
4452
|
+
}
|
|
4453
|
+
return [node];
|
|
4454
|
+
}
|
|
4455
|
+
isExpressionSelfContained(expr, allowedTables) {
|
|
4456
|
+
const collector = this.collectReferencedTables(expr);
|
|
4457
|
+
if (collector.hasSubquery) return false;
|
|
4458
|
+
if (collector.tables.size === 0) return true;
|
|
4459
|
+
for (const table of collector.tables) {
|
|
4460
|
+
if (!allowedTables.has(table)) {
|
|
4461
|
+
return false;
|
|
4462
|
+
}
|
|
4463
|
+
}
|
|
4464
|
+
return true;
|
|
4465
|
+
}
|
|
4466
|
+
collectReferencedTables(expr) {
|
|
4467
|
+
const collector = {
|
|
4468
|
+
tables: /* @__PURE__ */ new Set(),
|
|
4469
|
+
hasSubquery: false
|
|
4470
|
+
};
|
|
4471
|
+
this.collectFromExpression(expr, collector);
|
|
4472
|
+
return collector;
|
|
4473
|
+
}
|
|
4474
|
+
collectFromExpression(expr, collector) {
|
|
4475
|
+
switch (expr.type) {
|
|
4476
|
+
case "BinaryExpression":
|
|
4477
|
+
this.collectFromOperand(expr.left, collector);
|
|
4478
|
+
this.collectFromOperand(expr.right, collector);
|
|
4479
|
+
break;
|
|
4480
|
+
case "LogicalExpression":
|
|
4481
|
+
expr.operands.forEach((operand) => this.collectFromExpression(operand, collector));
|
|
4482
|
+
break;
|
|
4483
|
+
case "NullExpression":
|
|
4484
|
+
this.collectFromOperand(expr.left, collector);
|
|
4485
|
+
break;
|
|
4486
|
+
case "InExpression":
|
|
4487
|
+
this.collectFromOperand(expr.left, collector);
|
|
4488
|
+
if (Array.isArray(expr.right)) {
|
|
4489
|
+
expr.right.forEach((value) => this.collectFromOperand(value, collector));
|
|
4490
|
+
} else {
|
|
4491
|
+
collector.hasSubquery = true;
|
|
4492
|
+
}
|
|
4493
|
+
break;
|
|
4494
|
+
case "ExistsExpression":
|
|
4495
|
+
collector.hasSubquery = true;
|
|
4496
|
+
break;
|
|
4497
|
+
case "BetweenExpression":
|
|
4498
|
+
this.collectFromOperand(expr.left, collector);
|
|
4499
|
+
this.collectFromOperand(expr.lower, collector);
|
|
4500
|
+
this.collectFromOperand(expr.upper, collector);
|
|
4501
|
+
break;
|
|
4502
|
+
case "ArithmeticExpression":
|
|
4503
|
+
case "BitwiseExpression":
|
|
4504
|
+
this.collectFromOperand(expr.left, collector);
|
|
4505
|
+
this.collectFromOperand(expr.right, collector);
|
|
4506
|
+
break;
|
|
4507
|
+
default:
|
|
4508
|
+
break;
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4511
|
+
collectFromOperand(node, collector) {
|
|
4512
|
+
switch (node.type) {
|
|
4513
|
+
case "Column":
|
|
4514
|
+
collector.tables.add(node.table);
|
|
4515
|
+
break;
|
|
4516
|
+
case "Function":
|
|
4517
|
+
node.args.forEach((arg) => this.collectFromOperand(arg, collector));
|
|
4518
|
+
if (node.separator) {
|
|
4519
|
+
this.collectFromOperand(node.separator, collector);
|
|
4520
|
+
}
|
|
4521
|
+
if (node.orderBy) {
|
|
4522
|
+
node.orderBy.forEach((order) => this.collectFromOrderingTerm(order.term, collector));
|
|
4523
|
+
}
|
|
4524
|
+
break;
|
|
4525
|
+
case "JsonPath":
|
|
4526
|
+
this.collectFromOperand(node.column, collector);
|
|
4527
|
+
break;
|
|
4528
|
+
case "ScalarSubquery":
|
|
4529
|
+
collector.hasSubquery = true;
|
|
4530
|
+
break;
|
|
4531
|
+
case "CaseExpression":
|
|
4532
|
+
node.conditions.forEach(({ when, then }) => {
|
|
4533
|
+
this.collectFromExpression(when, collector);
|
|
4534
|
+
this.collectFromOperand(then, collector);
|
|
4535
|
+
});
|
|
4536
|
+
if (node.else) {
|
|
4537
|
+
this.collectFromOperand(node.else, collector);
|
|
4538
|
+
}
|
|
4539
|
+
break;
|
|
4540
|
+
case "Cast":
|
|
4541
|
+
this.collectFromOperand(node.expression, collector);
|
|
4542
|
+
break;
|
|
4543
|
+
case "WindowFunction":
|
|
4544
|
+
node.args.forEach((arg) => this.collectFromOperand(arg, collector));
|
|
4545
|
+
node.partitionBy?.forEach((part) => this.collectFromOperand(part, collector));
|
|
4546
|
+
node.orderBy?.forEach((order) => this.collectFromOrderingTerm(order.term, collector));
|
|
4547
|
+
break;
|
|
4548
|
+
case "Collate":
|
|
4549
|
+
this.collectFromOperand(node.expression, collector);
|
|
4550
|
+
break;
|
|
4551
|
+
case "ArithmeticExpression":
|
|
4552
|
+
case "BitwiseExpression":
|
|
4553
|
+
this.collectFromOperand(node.left, collector);
|
|
4554
|
+
this.collectFromOperand(node.right, collector);
|
|
4555
|
+
break;
|
|
4556
|
+
case "Literal":
|
|
4557
|
+
case "AliasRef":
|
|
4558
|
+
break;
|
|
4559
|
+
default:
|
|
4560
|
+
break;
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
collectFromOrderingTerm(term, collector) {
|
|
4564
|
+
if (isOperandNode(term)) {
|
|
4565
|
+
this.collectFromOperand(term, collector);
|
|
4566
|
+
return;
|
|
4567
|
+
}
|
|
4568
|
+
this.collectFromExpression(term, collector);
|
|
4569
|
+
}
|
|
4570
|
+
createFilteredRelationCte(state, relationName, relation, filters) {
|
|
4571
|
+
const cteName = this.generateUniqueCteName(state, relationName);
|
|
4572
|
+
const predicate = this.combineWithAnd(filters);
|
|
4573
|
+
if (!predicate) {
|
|
4574
|
+
throw new Error("Unable to build filter CTE without predicates.");
|
|
4575
|
+
}
|
|
4576
|
+
const columns = Object.keys(relation.target.columns).map((name) => ({
|
|
4577
|
+
type: "Column",
|
|
4578
|
+
table: relation.target.name,
|
|
4579
|
+
name
|
|
4580
|
+
}));
|
|
4581
|
+
const cteQuery = {
|
|
4582
|
+
type: "SelectQuery",
|
|
4583
|
+
from: { type: "Table", name: relation.target.name, schema: relation.target.schema },
|
|
4584
|
+
columns,
|
|
4585
|
+
joins: [],
|
|
4586
|
+
where: predicate
|
|
4587
|
+
};
|
|
4588
|
+
const nextState = this.astService(state).withCte(cteName, cteQuery);
|
|
4589
|
+
const tableNode3 = {
|
|
4590
|
+
type: "Table",
|
|
4591
|
+
name: cteName,
|
|
4592
|
+
alias: relation.target.name
|
|
4593
|
+
};
|
|
4594
|
+
return { state: nextState, table: tableNode3 };
|
|
4595
|
+
}
|
|
4596
|
+
generateUniqueCteName(state, relationName) {
|
|
4597
|
+
const existing = new Set((state.ast.ctes ?? []).map((cte) => cte.name));
|
|
4598
|
+
let candidate = `${relationName}__filtered`;
|
|
4599
|
+
let suffix = 1;
|
|
4600
|
+
while (existing.has(candidate)) {
|
|
4601
|
+
candidate = `${relationName}__filtered_${suffix}`;
|
|
4602
|
+
suffix += 1;
|
|
4603
|
+
}
|
|
4604
|
+
return candidate;
|
|
4605
|
+
}
|
|
4606
|
+
resolveTargetTableName(target, relation) {
|
|
4607
|
+
if (target.type === "Table") {
|
|
4608
|
+
return target.alias ?? target.name;
|
|
4609
|
+
}
|
|
4610
|
+
if (target.type === "DerivedTable") {
|
|
4611
|
+
return target.alias;
|
|
4612
|
+
}
|
|
4613
|
+
if (target.type === "FunctionTable") {
|
|
4614
|
+
return target.alias ?? relation.target.name;
|
|
4615
|
+
}
|
|
4616
|
+
return relation.target.name;
|
|
4617
|
+
}
|
|
3842
4618
|
/**
|
|
3843
4619
|
* Gets a relation definition by name
|
|
3844
4620
|
* @param relationName - Name of the relation
|
|
@@ -4189,6 +4965,18 @@ var DefaultHasManyCollection = class {
|
|
|
4189
4965
|
getItems() {
|
|
4190
4966
|
return this.items;
|
|
4191
4967
|
}
|
|
4968
|
+
/**
|
|
4969
|
+
* Array-compatible length for testing frameworks.
|
|
4970
|
+
*/
|
|
4971
|
+
get length() {
|
|
4972
|
+
return this.items.length;
|
|
4973
|
+
}
|
|
4974
|
+
/**
|
|
4975
|
+
* Enables iteration over the collection like an array.
|
|
4976
|
+
*/
|
|
4977
|
+
[Symbol.iterator]() {
|
|
4978
|
+
return this.items[Symbol.iterator]();
|
|
4979
|
+
}
|
|
4192
4980
|
/**
|
|
4193
4981
|
* Adds a new child entity to the collection.
|
|
4194
4982
|
* @param data - Partial data for the new entity
|
|
@@ -4288,6 +5076,17 @@ var hideInternal2 = (obj, keys) => {
|
|
|
4288
5076
|
}
|
|
4289
5077
|
};
|
|
4290
5078
|
var DefaultHasOneReference = class {
|
|
5079
|
+
/**
|
|
5080
|
+
* @param ctx The entity context for tracking changes.
|
|
5081
|
+
* @param meta Metadata for the parent entity.
|
|
5082
|
+
* @param root The parent entity instance.
|
|
5083
|
+
* @param relationName The name of the relation.
|
|
5084
|
+
* @param relation Relation definition.
|
|
5085
|
+
* @param rootTable Table definition of the parent entity.
|
|
5086
|
+
* @param loader Function to load the child entity.
|
|
5087
|
+
* @param createEntity Function to create entity instances from rows.
|
|
5088
|
+
* @param localKey The local key on the parent entity used for the relation.
|
|
5089
|
+
*/
|
|
4291
5090
|
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
|
|
4292
5091
|
this.ctx = ctx;
|
|
4293
5092
|
this.meta = meta;
|
|
@@ -4405,6 +5204,17 @@ var hideInternal3 = (obj, keys) => {
|
|
|
4405
5204
|
}
|
|
4406
5205
|
};
|
|
4407
5206
|
var DefaultBelongsToReference = class {
|
|
5207
|
+
/**
|
|
5208
|
+
* @param ctx The entity context for tracking changes.
|
|
5209
|
+
* @param meta Metadata for the child entity.
|
|
5210
|
+
* @param root The child entity instance (carrying the foreign key).
|
|
5211
|
+
* @param relationName The name of the relation.
|
|
5212
|
+
* @param relation Relation definition.
|
|
5213
|
+
* @param rootTable Table definition of the child entity.
|
|
5214
|
+
* @param loader Function to load the parent entity.
|
|
5215
|
+
* @param createEntity Function to create entity instances from rows.
|
|
5216
|
+
* @param targetKey The primary key of the target (parent) table.
|
|
5217
|
+
*/
|
|
4408
5218
|
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, targetKey) {
|
|
4409
5219
|
this.ctx = ctx;
|
|
4410
5220
|
this.meta = meta;
|
|
@@ -4496,6 +5306,17 @@ var hideInternal4 = (obj, keys) => {
|
|
|
4496
5306
|
}
|
|
4497
5307
|
};
|
|
4498
5308
|
var DefaultManyToManyCollection = class {
|
|
5309
|
+
/**
|
|
5310
|
+
* @param ctx The entity context for tracking changes.
|
|
5311
|
+
* @param meta Metadata for the root entity.
|
|
5312
|
+
* @param root The root entity instance.
|
|
5313
|
+
* @param relationName The name of the relation.
|
|
5314
|
+
* @param relation Relation definition.
|
|
5315
|
+
* @param rootTable Table definition of the root entity.
|
|
5316
|
+
* @param loader Function to load the collection items.
|
|
5317
|
+
* @param createEntity Function to create entity instances from rows.
|
|
5318
|
+
* @param localKey The local key used for joining.
|
|
5319
|
+
*/
|
|
4499
5320
|
constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
|
|
4500
5321
|
this.ctx = ctx;
|
|
4501
5322
|
this.meta = meta;
|
|
@@ -4511,6 +5332,10 @@ var DefaultManyToManyCollection = class {
|
|
|
4511
5332
|
hideInternal4(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
|
|
4512
5333
|
this.hydrateFromCache();
|
|
4513
5334
|
}
|
|
5335
|
+
/**
|
|
5336
|
+
* Loads the collection items if not already loaded.
|
|
5337
|
+
* @returns A promise that resolves to the array of target entities.
|
|
5338
|
+
*/
|
|
4514
5339
|
async load() {
|
|
4515
5340
|
if (this.loaded) return this.items;
|
|
4516
5341
|
const map = await this.loader();
|
|
@@ -4526,9 +5351,30 @@ var DefaultManyToManyCollection = class {
|
|
|
4526
5351
|
this.loaded = true;
|
|
4527
5352
|
return this.items;
|
|
4528
5353
|
}
|
|
5354
|
+
/**
|
|
5355
|
+
* Returns the currently loaded items.
|
|
5356
|
+
* @returns Array of target entities.
|
|
5357
|
+
*/
|
|
4529
5358
|
getItems() {
|
|
4530
5359
|
return this.items;
|
|
4531
5360
|
}
|
|
5361
|
+
/**
|
|
5362
|
+
* Array-compatible length for testing frameworks.
|
|
5363
|
+
*/
|
|
5364
|
+
get length() {
|
|
5365
|
+
return this.items.length;
|
|
5366
|
+
}
|
|
5367
|
+
/**
|
|
5368
|
+
* Enables iteration over the collection like an array.
|
|
5369
|
+
*/
|
|
5370
|
+
[Symbol.iterator]() {
|
|
5371
|
+
return this.items[Symbol.iterator]();
|
|
5372
|
+
}
|
|
5373
|
+
/**
|
|
5374
|
+
* Attaches an entity to the collection.
|
|
5375
|
+
* Registers an 'attach' change in the entity context.
|
|
5376
|
+
* @param target Entity instance or its primary key value.
|
|
5377
|
+
*/
|
|
4532
5378
|
attach(target) {
|
|
4533
5379
|
const entity = this.ensureEntity(target);
|
|
4534
5380
|
const id = this.extractId(entity);
|
|
@@ -4548,6 +5394,11 @@ var DefaultManyToManyCollection = class {
|
|
|
4548
5394
|
{ kind: "attach", entity }
|
|
4549
5395
|
);
|
|
4550
5396
|
}
|
|
5397
|
+
/**
|
|
5398
|
+
* Detaches an entity from the collection.
|
|
5399
|
+
* Registers a 'detach' change in the entity context.
|
|
5400
|
+
* @param target Entity instance or its primary key value.
|
|
5401
|
+
*/
|
|
4551
5402
|
detach(target) {
|
|
4552
5403
|
const id = typeof target === "number" || typeof target === "string" ? target : this.extractId(target);
|
|
4553
5404
|
if (id == null) return;
|
|
@@ -4563,6 +5414,11 @@ var DefaultManyToManyCollection = class {
|
|
|
4563
5414
|
{ kind: "detach", entity: existing }
|
|
4564
5415
|
);
|
|
4565
5416
|
}
|
|
5417
|
+
/**
|
|
5418
|
+
* Syncs the collection with a list of IDs.
|
|
5419
|
+
* Attaches missing IDs and detaches IDs not in the list.
|
|
5420
|
+
* @param ids Array of primary key values to sync with.
|
|
5421
|
+
*/
|
|
4566
5422
|
async syncByIds(ids) {
|
|
4567
5423
|
await this.load();
|
|
4568
5424
|
const normalized = new Set(ids.map((id) => toKey5(id)));
|
|
@@ -4621,10 +5477,27 @@ var DefaultManyToManyCollection = class {
|
|
|
4621
5477
|
};
|
|
4622
5478
|
|
|
4623
5479
|
// src/orm/lazy-batch.ts
|
|
4624
|
-
var
|
|
4625
|
-
|
|
4626
|
-
return acc
|
|
4627
|
-
|
|
5480
|
+
var hasColumns = (columns) => Boolean(columns && columns.length > 0);
|
|
5481
|
+
var buildColumnSelection = (table, columns, missingMsg) => {
|
|
5482
|
+
return columns.reduce((acc, column) => {
|
|
5483
|
+
const def = table.columns[column];
|
|
5484
|
+
if (!def) {
|
|
5485
|
+
throw new Error(missingMsg(column));
|
|
5486
|
+
}
|
|
5487
|
+
acc[column] = def;
|
|
5488
|
+
return acc;
|
|
5489
|
+
}, {});
|
|
5490
|
+
};
|
|
5491
|
+
var filterRow = (row, columns) => {
|
|
5492
|
+
const filtered = {};
|
|
5493
|
+
for (const column of columns) {
|
|
5494
|
+
if (column in row) {
|
|
5495
|
+
filtered[column] = row[column];
|
|
5496
|
+
}
|
|
5497
|
+
}
|
|
5498
|
+
return filtered;
|
|
5499
|
+
};
|
|
5500
|
+
var filterRows = (rows, columns) => rows.map((row) => filterRow(row, columns));
|
|
4628
5501
|
var rowsFromResults = (results) => {
|
|
4629
5502
|
const rows = [];
|
|
4630
5503
|
for (const result of results) {
|
|
@@ -4656,9 +5529,12 @@ var collectKeysFromRoots = (roots, key) => {
|
|
|
4656
5529
|
return collected;
|
|
4657
5530
|
};
|
|
4658
5531
|
var buildInListValues = (keys) => Array.from(keys);
|
|
4659
|
-
var fetchRowsForKeys = async (ctx, table, column, keys) => {
|
|
4660
|
-
|
|
4661
|
-
qb.where(inList(column, buildInListValues(keys)));
|
|
5532
|
+
var fetchRowsForKeys = async (ctx, table, column, keys, selection, filter) => {
|
|
5533
|
+
let qb = new SelectQueryBuilder(table).select(selection);
|
|
5534
|
+
qb = qb.where(inList(column, buildInListValues(keys)));
|
|
5535
|
+
if (filter) {
|
|
5536
|
+
qb = qb.where(filter);
|
|
5537
|
+
}
|
|
4662
5538
|
return executeQuery(ctx, qb);
|
|
4663
5539
|
};
|
|
4664
5540
|
var groupRowsByMany = (rows, keyColumn) => {
|
|
@@ -4685,7 +5561,7 @@ var groupRowsByUnique = (rows, keyColumn) => {
|
|
|
4685
5561
|
}
|
|
4686
5562
|
return lookup;
|
|
4687
5563
|
};
|
|
4688
|
-
var loadHasManyRelation = async (ctx, rootTable,
|
|
5564
|
+
var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
4689
5565
|
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
4690
5566
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
4691
5567
|
const keys = collectKeysFromRoots(roots, localKey);
|
|
@@ -4694,10 +5570,30 @@ var loadHasManyRelation = async (ctx, rootTable, _relationName, relation) => {
|
|
|
4694
5570
|
}
|
|
4695
5571
|
const fkColumn = relation.target.columns[relation.foreignKey];
|
|
4696
5572
|
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
4697
|
-
const
|
|
4698
|
-
|
|
5573
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
5574
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
5575
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
5576
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
5577
|
+
selectedColumns.push(targetPrimaryKey);
|
|
5578
|
+
}
|
|
5579
|
+
const queryColumns = new Set(selectedColumns);
|
|
5580
|
+
queryColumns.add(relation.foreignKey);
|
|
5581
|
+
const selection = buildColumnSelection(
|
|
5582
|
+
relation.target,
|
|
5583
|
+
Array.from(queryColumns),
|
|
5584
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
5585
|
+
);
|
|
5586
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, options?.filter);
|
|
5587
|
+
const grouped = groupRowsByMany(rows, relation.foreignKey);
|
|
5588
|
+
if (!requestedColumns) return grouped;
|
|
5589
|
+
const visibleColumns = new Set(selectedColumns);
|
|
5590
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
5591
|
+
for (const [key, bucket] of grouped.entries()) {
|
|
5592
|
+
filtered.set(key, filterRows(bucket, visibleColumns));
|
|
5593
|
+
}
|
|
5594
|
+
return filtered;
|
|
4699
5595
|
};
|
|
4700
|
-
var loadHasOneRelation = async (ctx, rootTable,
|
|
5596
|
+
var loadHasOneRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
4701
5597
|
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
4702
5598
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
4703
5599
|
const keys = collectKeysFromRoots(roots, localKey);
|
|
@@ -4706,22 +5602,98 @@ var loadHasOneRelation = async (ctx, rootTable, _relationName, relation) => {
|
|
|
4706
5602
|
}
|
|
4707
5603
|
const fkColumn = relation.target.columns[relation.foreignKey];
|
|
4708
5604
|
if (!fkColumn) return /* @__PURE__ */ new Map();
|
|
4709
|
-
const
|
|
4710
|
-
|
|
5605
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
5606
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
5607
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
5608
|
+
if (!selectedColumns.includes(targetPrimaryKey)) {
|
|
5609
|
+
selectedColumns.push(targetPrimaryKey);
|
|
5610
|
+
}
|
|
5611
|
+
const queryColumns = new Set(selectedColumns);
|
|
5612
|
+
queryColumns.add(relation.foreignKey);
|
|
5613
|
+
const selection = buildColumnSelection(
|
|
5614
|
+
relation.target,
|
|
5615
|
+
Array.from(queryColumns),
|
|
5616
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
5617
|
+
);
|
|
5618
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys, selection, options?.filter);
|
|
5619
|
+
const grouped = groupRowsByUnique(rows, relation.foreignKey);
|
|
5620
|
+
if (!requestedColumns) return grouped;
|
|
5621
|
+
const visibleColumns = new Set(selectedColumns);
|
|
5622
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
5623
|
+
for (const [key, row] of grouped.entries()) {
|
|
5624
|
+
filtered.set(key, filterRow(row, visibleColumns));
|
|
5625
|
+
}
|
|
5626
|
+
return filtered;
|
|
4711
5627
|
};
|
|
4712
|
-
var loadBelongsToRelation = async (ctx, rootTable,
|
|
5628
|
+
var loadBelongsToRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
4713
5629
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
4714
|
-
const
|
|
5630
|
+
const getForeignKeys = () => collectKeysFromRoots(roots, relation.foreignKey);
|
|
5631
|
+
let foreignKeys = getForeignKeys();
|
|
5632
|
+
if (!foreignKeys.size) {
|
|
5633
|
+
const pkName = findPrimaryKey(rootTable);
|
|
5634
|
+
const pkColumn2 = rootTable.columns[pkName];
|
|
5635
|
+
const fkColumn = rootTable.columns[relation.foreignKey];
|
|
5636
|
+
if (pkColumn2 && fkColumn) {
|
|
5637
|
+
const missingKeys = /* @__PURE__ */ new Set();
|
|
5638
|
+
const entityByPk = /* @__PURE__ */ new Map();
|
|
5639
|
+
for (const tracked of roots) {
|
|
5640
|
+
const entity = tracked.entity;
|
|
5641
|
+
const pkValue = entity[pkName];
|
|
5642
|
+
if (pkValue === void 0 || pkValue === null) continue;
|
|
5643
|
+
const fkValue = entity[relation.foreignKey];
|
|
5644
|
+
if (fkValue === void 0 || fkValue === null) {
|
|
5645
|
+
missingKeys.add(pkValue);
|
|
5646
|
+
entityByPk.set(pkValue, entity);
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
if (missingKeys.size) {
|
|
5650
|
+
const selection2 = buildColumnSelection(
|
|
5651
|
+
rootTable,
|
|
5652
|
+
[pkName, relation.foreignKey],
|
|
5653
|
+
(column) => `Column '${column}' not found on table '${rootTable.name}'`
|
|
5654
|
+
);
|
|
5655
|
+
const keyRows = await fetchRowsForKeys(ctx, rootTable, pkColumn2, missingKeys, selection2);
|
|
5656
|
+
for (const row of keyRows) {
|
|
5657
|
+
const pkValue = row[pkName];
|
|
5658
|
+
if (pkValue === void 0 || pkValue === null) continue;
|
|
5659
|
+
const entity = entityByPk.get(pkValue);
|
|
5660
|
+
if (!entity) continue;
|
|
5661
|
+
const fkValue = row[relation.foreignKey];
|
|
5662
|
+
if (fkValue !== void 0 && fkValue !== null) {
|
|
5663
|
+
entity[relation.foreignKey] = fkValue;
|
|
5664
|
+
}
|
|
5665
|
+
}
|
|
5666
|
+
foreignKeys = getForeignKeys();
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
4715
5670
|
if (!foreignKeys.size) {
|
|
4716
5671
|
return /* @__PURE__ */ new Map();
|
|
4717
5672
|
}
|
|
4718
5673
|
const targetKey = relation.localKey || findPrimaryKey(relation.target);
|
|
4719
5674
|
const pkColumn = relation.target.columns[targetKey];
|
|
4720
5675
|
if (!pkColumn) return /* @__PURE__ */ new Map();
|
|
4721
|
-
const
|
|
4722
|
-
|
|
5676
|
+
const requestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
5677
|
+
const selectedColumns = requestedColumns ? [...requestedColumns] : Object.keys(relation.target.columns);
|
|
5678
|
+
if (!selectedColumns.includes(targetKey)) {
|
|
5679
|
+
selectedColumns.push(targetKey);
|
|
5680
|
+
}
|
|
5681
|
+
const selection = buildColumnSelection(
|
|
5682
|
+
relation.target,
|
|
5683
|
+
selectedColumns,
|
|
5684
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
5685
|
+
);
|
|
5686
|
+
const rows = await fetchRowsForKeys(ctx, relation.target, pkColumn, foreignKeys, selection, options?.filter);
|
|
5687
|
+
const grouped = groupRowsByUnique(rows, targetKey);
|
|
5688
|
+
if (!requestedColumns) return grouped;
|
|
5689
|
+
const visibleColumns = new Set(selectedColumns);
|
|
5690
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
5691
|
+
for (const [key, row] of grouped.entries()) {
|
|
5692
|
+
filtered.set(key, filterRow(row, visibleColumns));
|
|
5693
|
+
}
|
|
5694
|
+
return filtered;
|
|
4723
5695
|
};
|
|
4724
|
-
var loadBelongsToManyRelation = async (ctx, rootTable,
|
|
5696
|
+
var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
4725
5697
|
const rootKey = relation.localKey || findPrimaryKey(rootTable);
|
|
4726
5698
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
4727
5699
|
const rootIds = collectKeysFromRoots(roots, rootKey);
|
|
@@ -4730,9 +5702,29 @@ var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation)
|
|
|
4730
5702
|
}
|
|
4731
5703
|
const pivotColumn = relation.pivotTable.columns[relation.pivotForeignKeyToRoot];
|
|
4732
5704
|
if (!pivotColumn) return /* @__PURE__ */ new Map();
|
|
4733
|
-
const
|
|
5705
|
+
const pivotColumnsRequested = hasColumns(options?.pivot?.columns) ? [...options.pivot.columns] : void 0;
|
|
5706
|
+
const useIncludeDefaults = options !== void 0;
|
|
5707
|
+
let pivotSelectedColumns;
|
|
5708
|
+
if (pivotColumnsRequested) {
|
|
5709
|
+
pivotSelectedColumns = [...pivotColumnsRequested];
|
|
5710
|
+
} else if (useIncludeDefaults) {
|
|
5711
|
+
const pivotPk = relation.pivotPrimaryKey || findPrimaryKey(relation.pivotTable);
|
|
5712
|
+
pivotSelectedColumns = relation.defaultPivotColumns ?? buildDefaultPivotColumns(relation, pivotPk);
|
|
5713
|
+
} else {
|
|
5714
|
+
pivotSelectedColumns = Object.keys(relation.pivotTable.columns);
|
|
5715
|
+
}
|
|
5716
|
+
const pivotQueryColumns = new Set(pivotSelectedColumns);
|
|
5717
|
+
pivotQueryColumns.add(relation.pivotForeignKeyToRoot);
|
|
5718
|
+
pivotQueryColumns.add(relation.pivotForeignKeyToTarget);
|
|
5719
|
+
const pivotSelection = buildColumnSelection(
|
|
5720
|
+
relation.pivotTable,
|
|
5721
|
+
Array.from(pivotQueryColumns),
|
|
5722
|
+
(column) => `Column '${column}' not found on pivot table '${relation.pivotTable.name}'`
|
|
5723
|
+
);
|
|
5724
|
+
const pivotRows = await fetchRowsForKeys(ctx, relation.pivotTable, pivotColumn, rootIds, pivotSelection);
|
|
4734
5725
|
const rootLookup = /* @__PURE__ */ new Map();
|
|
4735
5726
|
const targetIds = /* @__PURE__ */ new Set();
|
|
5727
|
+
const pivotVisibleColumns = new Set(pivotSelectedColumns);
|
|
4736
5728
|
for (const pivot of pivotRows) {
|
|
4737
5729
|
const rootValue = pivot[relation.pivotForeignKeyToRoot];
|
|
4738
5730
|
const targetValue = pivot[relation.pivotForeignKeyToTarget];
|
|
@@ -4742,7 +5734,7 @@ var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation)
|
|
|
4742
5734
|
const bucket = rootLookup.get(toKey6(rootValue)) ?? [];
|
|
4743
5735
|
bucket.push({
|
|
4744
5736
|
targetId: targetValue,
|
|
4745
|
-
pivot:
|
|
5737
|
+
pivot: pivotVisibleColumns.size ? filterRow(pivot, pivotVisibleColumns) : {}
|
|
4746
5738
|
});
|
|
4747
5739
|
rootLookup.set(toKey6(rootValue), bucket);
|
|
4748
5740
|
targetIds.add(targetValue);
|
|
@@ -4753,8 +5745,19 @@ var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation)
|
|
|
4753
5745
|
const targetKey = relation.targetKey || findPrimaryKey(relation.target);
|
|
4754
5746
|
const targetPkColumn = relation.target.columns[targetKey];
|
|
4755
5747
|
if (!targetPkColumn) return /* @__PURE__ */ new Map();
|
|
4756
|
-
const
|
|
5748
|
+
const targetRequestedColumns = hasColumns(options?.columns) ? [...options.columns] : void 0;
|
|
5749
|
+
const targetSelectedColumns = targetRequestedColumns ? [...targetRequestedColumns] : Object.keys(relation.target.columns);
|
|
5750
|
+
if (!targetSelectedColumns.includes(targetKey)) {
|
|
5751
|
+
targetSelectedColumns.push(targetKey);
|
|
5752
|
+
}
|
|
5753
|
+
const targetSelection = buildColumnSelection(
|
|
5754
|
+
relation.target,
|
|
5755
|
+
targetSelectedColumns,
|
|
5756
|
+
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
5757
|
+
);
|
|
5758
|
+
const targetRows = await fetchRowsForKeys(ctx, relation.target, targetPkColumn, targetIds, targetSelection, options?.filter);
|
|
4757
5759
|
const targetMap = groupRowsByUnique(targetRows, targetKey);
|
|
5760
|
+
const targetVisibleColumns = new Set(targetSelectedColumns);
|
|
4758
5761
|
const result = /* @__PURE__ */ new Map();
|
|
4759
5762
|
for (const [rootId, entries] of rootLookup.entries()) {
|
|
4760
5763
|
const bucket = [];
|
|
@@ -4762,7 +5765,7 @@ var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation)
|
|
|
4762
5765
|
const targetRow = targetMap.get(toKey6(entry.targetId));
|
|
4763
5766
|
if (!targetRow) continue;
|
|
4764
5767
|
bucket.push({
|
|
4765
|
-
...targetRow,
|
|
5768
|
+
...targetRequestedColumns ? filterRow(targetRow, targetVisibleColumns) : targetRow,
|
|
4766
5769
|
_pivot: entry.pivot
|
|
4767
5770
|
});
|
|
4768
5771
|
}
|
|
@@ -4792,12 +5795,13 @@ var relationLoaderCache = (meta, relationName, factory) => {
|
|
|
4792
5795
|
}
|
|
4793
5796
|
return promise;
|
|
4794
5797
|
};
|
|
4795
|
-
var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
|
|
5798
|
+
var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOptions = /* @__PURE__ */ new Map()) => {
|
|
4796
5799
|
const target = { ...row };
|
|
4797
5800
|
const meta = {
|
|
4798
5801
|
ctx,
|
|
4799
5802
|
table,
|
|
4800
5803
|
lazyRelations: [...lazyRelations],
|
|
5804
|
+
lazyRelationOptions: new Map(lazyRelationOptions),
|
|
4801
5805
|
relationCache: /* @__PURE__ */ new Map(),
|
|
4802
5806
|
relationHydration: /* @__PURE__ */ new Map(),
|
|
4803
5807
|
relationWrappers: /* @__PURE__ */ new Map()
|
|
@@ -4838,14 +5842,14 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
|
|
|
4838
5842
|
populateHydrationCache(proxy, row, meta);
|
|
4839
5843
|
return proxy;
|
|
4840
5844
|
};
|
|
4841
|
-
var createEntityFromRow = (ctx, table, row, lazyRelations = []) => {
|
|
5845
|
+
var createEntityFromRow = (ctx, table, row, lazyRelations = [], lazyRelationOptions = /* @__PURE__ */ new Map()) => {
|
|
4842
5846
|
const pkName = findPrimaryKey(table);
|
|
4843
5847
|
const pkValue = row[pkName];
|
|
4844
5848
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
4845
5849
|
const tracked = ctx.getEntity(table, pkValue);
|
|
4846
5850
|
if (tracked) return tracked;
|
|
4847
5851
|
}
|
|
4848
|
-
const entity = createEntityProxy(ctx, table, row, lazyRelations);
|
|
5852
|
+
const entity = createEntityProxy(ctx, table, row, lazyRelations, lazyRelationOptions);
|
|
4849
5853
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
4850
5854
|
ctx.trackManaged(table, pkValue, entity);
|
|
4851
5855
|
} else {
|
|
@@ -4895,6 +5899,58 @@ var populateHydrationCache = (entity, row, meta) => {
|
|
|
4895
5899
|
}
|
|
4896
5900
|
}
|
|
4897
5901
|
};
|
|
5902
|
+
var proxifyRelationWrapper = (wrapper) => {
|
|
5903
|
+
return new Proxy(wrapper, {
|
|
5904
|
+
get(target, prop, receiver) {
|
|
5905
|
+
if (typeof prop === "symbol") {
|
|
5906
|
+
return Reflect.get(target, prop, receiver);
|
|
5907
|
+
}
|
|
5908
|
+
if (prop in target) {
|
|
5909
|
+
return Reflect.get(target, prop, receiver);
|
|
5910
|
+
}
|
|
5911
|
+
const getItems = target.getItems;
|
|
5912
|
+
if (typeof getItems === "function") {
|
|
5913
|
+
const items = getItems.call(target);
|
|
5914
|
+
if (items && prop in items) {
|
|
5915
|
+
const propName = prop;
|
|
5916
|
+
const value = items[propName];
|
|
5917
|
+
return typeof value === "function" ? value.bind(items) : value;
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
const getRef = target.get;
|
|
5921
|
+
if (typeof getRef === "function") {
|
|
5922
|
+
const current = getRef.call(target);
|
|
5923
|
+
if (current && prop in current) {
|
|
5924
|
+
const propName = prop;
|
|
5925
|
+
const value = current[propName];
|
|
5926
|
+
return typeof value === "function" ? value.bind(current) : value;
|
|
5927
|
+
}
|
|
5928
|
+
}
|
|
5929
|
+
return void 0;
|
|
5930
|
+
},
|
|
5931
|
+
set(target, prop, value, receiver) {
|
|
5932
|
+
if (typeof prop === "symbol") {
|
|
5933
|
+
return Reflect.set(target, prop, value, receiver);
|
|
5934
|
+
}
|
|
5935
|
+
if (prop in target) {
|
|
5936
|
+
return Reflect.set(target, prop, value, receiver);
|
|
5937
|
+
}
|
|
5938
|
+
const getRef = target.get;
|
|
5939
|
+
if (typeof getRef === "function") {
|
|
5940
|
+
const current = getRef.call(target);
|
|
5941
|
+
if (current && typeof current === "object") {
|
|
5942
|
+
return Reflect.set(current, prop, value);
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5945
|
+
const getItems = target.getItems;
|
|
5946
|
+
if (typeof getItems === "function") {
|
|
5947
|
+
const items = getItems.call(target);
|
|
5948
|
+
return Reflect.set(items, prop, value);
|
|
5949
|
+
}
|
|
5950
|
+
return Reflect.set(target, prop, value, receiver);
|
|
5951
|
+
}
|
|
5952
|
+
});
|
|
5953
|
+
};
|
|
4898
5954
|
var getRelationWrapper = (meta, relationName, owner) => {
|
|
4899
5955
|
if (meta.relationWrappers.has(relationName)) {
|
|
4900
5956
|
return meta.relationWrappers.get(relationName);
|
|
@@ -4902,12 +5958,13 @@ var getRelationWrapper = (meta, relationName, owner) => {
|
|
|
4902
5958
|
const relation = meta.table.relations[relationName];
|
|
4903
5959
|
if (!relation) return void 0;
|
|
4904
5960
|
const wrapper = instantiateWrapper(meta, relationName, relation, owner);
|
|
4905
|
-
if (wrapper)
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
return
|
|
5961
|
+
if (!wrapper) return void 0;
|
|
5962
|
+
const proxied = proxifyRelationWrapper(wrapper);
|
|
5963
|
+
meta.relationWrappers.set(relationName, proxied);
|
|
5964
|
+
return proxied;
|
|
4909
5965
|
};
|
|
4910
5966
|
var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
5967
|
+
const lazyOptions = meta.lazyRelationOptions.get(relationName);
|
|
4911
5968
|
switch (relation.type) {
|
|
4912
5969
|
case RelationKinds.HasOne: {
|
|
4913
5970
|
const hasOne2 = relation;
|
|
@@ -4915,7 +5972,7 @@ var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
|
4915
5972
|
const loader = () => relationLoaderCache(
|
|
4916
5973
|
meta,
|
|
4917
5974
|
relationName,
|
|
4918
|
-
() => loadHasOneRelation(meta.ctx, meta.table, relationName, hasOne2)
|
|
5975
|
+
() => loadHasOneRelation(meta.ctx, meta.table, relationName, hasOne2, lazyOptions)
|
|
4919
5976
|
);
|
|
4920
5977
|
return new DefaultHasOneReference(
|
|
4921
5978
|
meta.ctx,
|
|
@@ -4935,7 +5992,7 @@ var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
|
4935
5992
|
const loader = () => relationLoaderCache(
|
|
4936
5993
|
meta,
|
|
4937
5994
|
relationName,
|
|
4938
|
-
() => loadHasManyRelation(meta.ctx, meta.table, relationName, hasMany2)
|
|
5995
|
+
() => loadHasManyRelation(meta.ctx, meta.table, relationName, hasMany2, lazyOptions)
|
|
4939
5996
|
);
|
|
4940
5997
|
return new DefaultHasManyCollection(
|
|
4941
5998
|
meta.ctx,
|
|
@@ -4955,7 +6012,7 @@ var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
|
4955
6012
|
const loader = () => relationLoaderCache(
|
|
4956
6013
|
meta,
|
|
4957
6014
|
relationName,
|
|
4958
|
-
() => loadBelongsToRelation(meta.ctx, meta.table, relationName, belongsTo2)
|
|
6015
|
+
() => loadBelongsToRelation(meta.ctx, meta.table, relationName, belongsTo2, lazyOptions)
|
|
4959
6016
|
);
|
|
4960
6017
|
return new DefaultBelongsToReference(
|
|
4961
6018
|
meta.ctx,
|
|
@@ -4975,7 +6032,7 @@ var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
|
4975
6032
|
const loader = () => relationLoaderCache(
|
|
4976
6033
|
meta,
|
|
4977
6034
|
relationName,
|
|
4978
|
-
() => loadBelongsToManyRelation(meta.ctx, meta.table, relationName, many)
|
|
6035
|
+
() => loadBelongsToManyRelation(meta.ctx, meta.table, relationName, many, lazyOptions)
|
|
4979
6036
|
);
|
|
4980
6037
|
return new DefaultManyToManyCollection(
|
|
4981
6038
|
meta.ctx,
|
|
@@ -5014,11 +6071,17 @@ var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
|
5014
6071
|
const compiled = execCtx.dialect.compileSelect(ast);
|
|
5015
6072
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
5016
6073
|
const rows = flattenResults(executed);
|
|
6074
|
+
const lazyRelations = qb.getLazyRelations();
|
|
6075
|
+
const lazyRelationOptions = qb.getLazyRelationOptions();
|
|
5017
6076
|
if (ast.setOps && ast.setOps.length > 0) {
|
|
5018
|
-
|
|
6077
|
+
const proxies = rows.map((row) => createEntityProxy(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
|
|
6078
|
+
await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
|
|
6079
|
+
return proxies;
|
|
5019
6080
|
}
|
|
5020
6081
|
const hydrated = hydrateRows(rows, qb.getHydrationPlan());
|
|
5021
|
-
|
|
6082
|
+
const entities = hydrated.map((row) => createEntityFromRow(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
|
|
6083
|
+
await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
|
|
6084
|
+
return entities;
|
|
5022
6085
|
};
|
|
5023
6086
|
async function executeHydrated(session, qb) {
|
|
5024
6087
|
return executeWithContexts(session.getExecutionContext(), session, qb);
|
|
@@ -5030,6 +6093,52 @@ async function executeHydratedWithContexts(execCtx, hydCtx, qb) {
|
|
|
5030
6093
|
}
|
|
5031
6094
|
return executeWithContexts(execCtx, entityCtx, qb);
|
|
5032
6095
|
}
|
|
6096
|
+
var loadLazyRelationsForTable = async (ctx, table, lazyRelations, lazyRelationOptions) => {
|
|
6097
|
+
if (!lazyRelations.length) return;
|
|
6098
|
+
const tracked = ctx.getEntitiesForTable(table);
|
|
6099
|
+
if (!tracked.length) return;
|
|
6100
|
+
const meta = getEntityMeta(tracked[0].entity);
|
|
6101
|
+
if (!meta) return;
|
|
6102
|
+
for (const relationName of lazyRelations) {
|
|
6103
|
+
const relation = table.relations[relationName];
|
|
6104
|
+
if (!relation) continue;
|
|
6105
|
+
const key = relationName;
|
|
6106
|
+
const options = lazyRelationOptions.get(key);
|
|
6107
|
+
if (!options) {
|
|
6108
|
+
continue;
|
|
6109
|
+
}
|
|
6110
|
+
switch (relation.type) {
|
|
6111
|
+
case RelationKinds.HasOne:
|
|
6112
|
+
await relationLoaderCache(
|
|
6113
|
+
meta,
|
|
6114
|
+
key,
|
|
6115
|
+
() => loadHasOneRelation(ctx, table, key, relation, options)
|
|
6116
|
+
);
|
|
6117
|
+
break;
|
|
6118
|
+
case RelationKinds.HasMany:
|
|
6119
|
+
await relationLoaderCache(
|
|
6120
|
+
meta,
|
|
6121
|
+
key,
|
|
6122
|
+
() => loadHasManyRelation(ctx, table, key, relation, options)
|
|
6123
|
+
);
|
|
6124
|
+
break;
|
|
6125
|
+
case RelationKinds.BelongsTo:
|
|
6126
|
+
await relationLoaderCache(
|
|
6127
|
+
meta,
|
|
6128
|
+
key,
|
|
6129
|
+
() => loadBelongsToRelation(ctx, table, key, relation, options)
|
|
6130
|
+
);
|
|
6131
|
+
break;
|
|
6132
|
+
case RelationKinds.BelongsToMany:
|
|
6133
|
+
await relationLoaderCache(
|
|
6134
|
+
meta,
|
|
6135
|
+
key,
|
|
6136
|
+
() => loadBelongsToManyRelation(ctx, table, key, relation, options)
|
|
6137
|
+
);
|
|
6138
|
+
break;
|
|
6139
|
+
}
|
|
6140
|
+
}
|
|
6141
|
+
};
|
|
5033
6142
|
|
|
5034
6143
|
// src/query-builder/query-resolution.ts
|
|
5035
6144
|
function resolveSelectQuery(query) {
|
|
@@ -5046,7 +6155,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5046
6155
|
* @param hydration - Optional hydration manager
|
|
5047
6156
|
* @param dependencies - Optional query builder dependencies
|
|
5048
6157
|
*/
|
|
5049
|
-
constructor(table, state, hydration, dependencies, lazyRelations) {
|
|
6158
|
+
constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions) {
|
|
5050
6159
|
const deps = resolveSelectQueryBuilderDependencies(dependencies);
|
|
5051
6160
|
this.env = { table, deps };
|
|
5052
6161
|
const initialState = state ?? deps.createState(table);
|
|
@@ -5056,6 +6165,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5056
6165
|
hydration: initialHydration
|
|
5057
6166
|
};
|
|
5058
6167
|
this.lazyRelations = new Set(lazyRelations ?? []);
|
|
6168
|
+
this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
|
|
5059
6169
|
this.columnSelector = deps.createColumnSelector(this.env);
|
|
5060
6170
|
this.relationManager = deps.createRelationManager(this.env);
|
|
5061
6171
|
}
|
|
@@ -5065,8 +6175,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5065
6175
|
* @param lazyRelations - Updated lazy relations set
|
|
5066
6176
|
* @returns New SelectQueryBuilder instance
|
|
5067
6177
|
*/
|
|
5068
|
-
clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
|
|
5069
|
-
return new _SelectQueryBuilder(
|
|
6178
|
+
clone(context = this.context, lazyRelations = new Set(this.lazyRelations), lazyRelationOptions = new Map(this.lazyRelationOptions)) {
|
|
6179
|
+
return new _SelectQueryBuilder(
|
|
6180
|
+
this.env.table,
|
|
6181
|
+
context.state,
|
|
6182
|
+
context.hydration,
|
|
6183
|
+
this.env.deps,
|
|
6184
|
+
lazyRelations,
|
|
6185
|
+
lazyRelationOptions
|
|
6186
|
+
);
|
|
5070
6187
|
}
|
|
5071
6188
|
/**
|
|
5072
6189
|
* Applies an alias to the root FROM table.
|
|
@@ -5313,36 +6430,40 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5313
6430
|
/**
|
|
5314
6431
|
* Includes a relation lazily in the query results
|
|
5315
6432
|
* @param relationName - Name of the relation to include lazily
|
|
6433
|
+
* @param options - Optional include options for lazy loading
|
|
5316
6434
|
* @returns New query builder instance with lazy relation inclusion
|
|
5317
6435
|
*/
|
|
5318
|
-
includeLazy(relationName) {
|
|
5319
|
-
|
|
5320
|
-
nextLazy.add(relationName);
|
|
5321
|
-
return this.clone(this.context, nextLazy);
|
|
5322
|
-
}
|
|
5323
|
-
/**
|
|
5324
|
-
* Selects columns for a related table in a single hop.
|
|
5325
|
-
*/
|
|
5326
|
-
selectRelationColumns(relationName, ...cols) {
|
|
6436
|
+
includeLazy(relationName, options) {
|
|
6437
|
+
let nextContext = this.context;
|
|
5327
6438
|
const relation = this.env.table.relations[relationName];
|
|
5328
|
-
if (
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
)
|
|
6439
|
+
if (relation?.type === RelationKinds.BelongsTo) {
|
|
6440
|
+
const foreignKey = relation.foreignKey;
|
|
6441
|
+
const fkColumn = this.env.table.columns[foreignKey];
|
|
6442
|
+
if (fkColumn) {
|
|
6443
|
+
const hasAlias2 = nextContext.state.ast.columns.some((col2) => {
|
|
6444
|
+
const node = col2;
|
|
6445
|
+
return (node.alias ?? node.name) === foreignKey;
|
|
6446
|
+
});
|
|
6447
|
+
if (!hasAlias2) {
|
|
6448
|
+
nextContext = this.columnSelector.select(nextContext, { [foreignKey]: fkColumn });
|
|
6449
|
+
}
|
|
5337
6450
|
}
|
|
5338
6451
|
}
|
|
5339
|
-
|
|
6452
|
+
const nextLazy = new Set(this.lazyRelations);
|
|
6453
|
+
nextLazy.add(relationName);
|
|
6454
|
+
const nextOptions = new Map(this.lazyRelationOptions);
|
|
6455
|
+
if (options) {
|
|
6456
|
+
nextOptions.set(relationName, options);
|
|
6457
|
+
} else {
|
|
6458
|
+
nextOptions.delete(relationName);
|
|
6459
|
+
}
|
|
6460
|
+
return this.clone(nextContext, nextLazy, nextOptions);
|
|
5340
6461
|
}
|
|
5341
6462
|
/**
|
|
5342
|
-
* Convenience alias for
|
|
6463
|
+
* Convenience alias for including only specific columns from a relation.
|
|
5343
6464
|
*/
|
|
5344
6465
|
includePick(relationName, cols) {
|
|
5345
|
-
return this.
|
|
6466
|
+
return this.include(relationName, { columns: cols });
|
|
5346
6467
|
}
|
|
5347
6468
|
/**
|
|
5348
6469
|
* Selects columns for the root table and relations from an array of entries
|
|
@@ -5355,7 +6476,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5355
6476
|
if (entry.type === "root") {
|
|
5356
6477
|
currBuilder = currBuilder.select(...entry.columns);
|
|
5357
6478
|
} else {
|
|
5358
|
-
currBuilder = currBuilder.
|
|
6479
|
+
currBuilder = currBuilder.include(entry.relationName, { columns: entry.columns });
|
|
5359
6480
|
}
|
|
5360
6481
|
}
|
|
5361
6482
|
return currBuilder;
|
|
@@ -5367,6 +6488,13 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5367
6488
|
getLazyRelations() {
|
|
5368
6489
|
return Array.from(this.lazyRelations);
|
|
5369
6490
|
}
|
|
6491
|
+
/**
|
|
6492
|
+
* Gets lazy relation include options
|
|
6493
|
+
* @returns Map of relation names to include options
|
|
6494
|
+
*/
|
|
6495
|
+
getLazyRelationOptions() {
|
|
6496
|
+
return new Map(this.lazyRelationOptions);
|
|
6497
|
+
}
|
|
5370
6498
|
/**
|
|
5371
6499
|
* Gets the table definition for this query builder
|
|
5372
6500
|
* @returns Table definition
|
|
@@ -7791,6 +8919,14 @@ var repeat = (value, count2) => fn("REPEAT", [value, count2]);
|
|
|
7791
8919
|
var lpad = (value, len, pad) => fn("LPAD", [value, len, pad]);
|
|
7792
8920
|
var rpad = (value, len, pad) => fn("RPAD", [value, len, pad]);
|
|
7793
8921
|
var space = (count2) => fn("SPACE", [count2]);
|
|
8922
|
+
var reverse = (value) => fn("REVERSE", [value]);
|
|
8923
|
+
var initcap = (value) => fn("INITCAP", [value]);
|
|
8924
|
+
var md5 = (value) => fn("MD5", [value]);
|
|
8925
|
+
var sha1 = (value) => fn("SHA1", [value]);
|
|
8926
|
+
var sha2 = (value, bits) => fn("SHA2", [value, bits]);
|
|
8927
|
+
var bitLength = (value) => fn("BIT_LENGTH", [value]);
|
|
8928
|
+
var octetLength = (value) => fn("OCTET_LENGTH", [value]);
|
|
8929
|
+
var chr = (code) => fn("CHR", [code]);
|
|
7794
8930
|
|
|
7795
8931
|
// src/core/ddl/introspect/functions/mssql.ts
|
|
7796
8932
|
var isColumnReference = (value) => typeof value === "object" && value !== null && !("type" in value) && "name" in value && typeof value.name === "string";
|
|
@@ -8349,6 +9485,8 @@ var sqrt = (value) => fn3("SQRT", [value]);
|
|
|
8349
9485
|
var tan = (value) => fn3("TAN", [value]);
|
|
8350
9486
|
var trunc = (value, decimals) => decimals === void 0 ? fn3("TRUNC", [value]) : fn3("TRUNC", [value, decimals]);
|
|
8351
9487
|
var truncate = (value, decimals) => fn3("TRUNCATE", [value, decimals]);
|
|
9488
|
+
var log2 = (value) => fn3("LOG2", [value]);
|
|
9489
|
+
var cbrt = (value) => fn3("CBRT", [value]);
|
|
8352
9490
|
|
|
8353
9491
|
// src/core/functions/datetime.ts
|
|
8354
9492
|
var isColumnDef3 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
|
|
@@ -8360,12 +9498,15 @@ var toOperand4 = (input) => {
|
|
|
8360
9498
|
var fn4 = (key, args) => ({
|
|
8361
9499
|
type: "Function",
|
|
8362
9500
|
name: key,
|
|
9501
|
+
fn: key,
|
|
8363
9502
|
args: args.map(toOperand4)
|
|
8364
9503
|
});
|
|
8365
9504
|
var now = () => fn4("NOW", []);
|
|
8366
9505
|
var currentDate = () => fn4("CURRENT_DATE", []);
|
|
8367
9506
|
var currentTime = () => fn4("CURRENT_TIME", []);
|
|
8368
9507
|
var utcNow = () => fn4("UTC_NOW", []);
|
|
9508
|
+
var localTime = () => fn4("LOCALTIME", []);
|
|
9509
|
+
var localTimestamp = () => fn4("LOCALTIMESTAMP", []);
|
|
8369
9510
|
var extract = (part, date) => fn4("EXTRACT", [part, date]);
|
|
8370
9511
|
var year = (date) => fn4("YEAR", [date]);
|
|
8371
9512
|
var month = (date) => fn4("MONTH", [date]);
|
|
@@ -8380,6 +9521,72 @@ var endOfMonth = (date) => fn4("END_OF_MONTH", [date]);
|
|
|
8380
9521
|
var dayOfWeek = (date) => fn4("DAY_OF_WEEK", [date]);
|
|
8381
9522
|
var weekOfYear = (date) => fn4("WEEK_OF_YEAR", [date]);
|
|
8382
9523
|
var dateTrunc = (part, date) => fn4("DATE_TRUNC", [part, date]);
|
|
9524
|
+
var age = (timestamp, baseTimestamp) => baseTimestamp === void 0 ? fn4("AGE", [timestamp]) : fn4("AGE", [timestamp, baseTimestamp]);
|
|
9525
|
+
var hour = (date) => fn4("HOUR", [date]);
|
|
9526
|
+
var minute = (date) => fn4("MINUTE", [date]);
|
|
9527
|
+
var second = (date) => fn4("SECOND", [date]);
|
|
9528
|
+
var quarter = (date) => fn4("QUARTER", [date]);
|
|
9529
|
+
|
|
9530
|
+
// src/core/functions/control-flow.ts
|
|
9531
|
+
var isColumnDef4 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
|
|
9532
|
+
var toOperand5 = (input) => {
|
|
9533
|
+
if (isOperandNode(input)) return input;
|
|
9534
|
+
if (isColumnDef4(input)) return columnOperand(input);
|
|
9535
|
+
return valueToOperand(input);
|
|
9536
|
+
};
|
|
9537
|
+
var fn5 = (key, args) => ({
|
|
9538
|
+
type: "Function",
|
|
9539
|
+
name: key,
|
|
9540
|
+
fn: key,
|
|
9541
|
+
args: args.map(toOperand5)
|
|
9542
|
+
});
|
|
9543
|
+
var coalesce = (...args) => {
|
|
9544
|
+
if (args.length < 2) throw new Error("coalesce() expects at least 2 arguments");
|
|
9545
|
+
return fn5("COALESCE", args);
|
|
9546
|
+
};
|
|
9547
|
+
var nullif = (val1, val2) => fn5("NULLIF", [val1, val2]);
|
|
9548
|
+
var greatest = (...args) => {
|
|
9549
|
+
if (args.length < 2) throw new Error("greatest() expects at least 2 arguments");
|
|
9550
|
+
return fn5("GREATEST", args);
|
|
9551
|
+
};
|
|
9552
|
+
var least = (...args) => {
|
|
9553
|
+
if (args.length < 2) throw new Error("least() expects at least 2 arguments");
|
|
9554
|
+
return fn5("LEAST", args);
|
|
9555
|
+
};
|
|
9556
|
+
var ifNull = (val, defaultValue) => coalesce(val, defaultValue);
|
|
9557
|
+
|
|
9558
|
+
// src/core/functions/json.ts
|
|
9559
|
+
var isColumnDef5 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
|
|
9560
|
+
var toOperand6 = (input) => {
|
|
9561
|
+
if (isOperandNode(input)) return input;
|
|
9562
|
+
if (isColumnDef5(input)) return columnOperand(input);
|
|
9563
|
+
return valueToOperand(input);
|
|
9564
|
+
};
|
|
9565
|
+
var fn6 = (key, args) => ({
|
|
9566
|
+
type: "Function",
|
|
9567
|
+
name: key,
|
|
9568
|
+
fn: key,
|
|
9569
|
+
args: args.map(toOperand6)
|
|
9570
|
+
});
|
|
9571
|
+
var jsonLength = (target, path) => path === void 0 ? fn6("JSON_LENGTH", [target]) : fn6("JSON_LENGTH", [target, path]);
|
|
9572
|
+
var jsonSet = (target, path, value) => fn6("JSON_SET", [target, path, value]);
|
|
9573
|
+
var jsonArrayAgg = (value) => fn6("JSON_ARRAYAGG", [value]);
|
|
9574
|
+
var jsonContains = (target, candidate, path) => path === void 0 ? fn6("JSON_CONTAINS", [target, candidate]) : fn6("JSON_CONTAINS", [target, candidate, path]);
|
|
9575
|
+
|
|
9576
|
+
// src/core/functions/array.ts
|
|
9577
|
+
var isColumnDef6 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
|
|
9578
|
+
var toOperand7 = (input) => {
|
|
9579
|
+
if (isOperandNode(input)) return input;
|
|
9580
|
+
if (isColumnDef6(input)) return columnOperand(input);
|
|
9581
|
+
return valueToOperand(input);
|
|
9582
|
+
};
|
|
9583
|
+
var fn7 = (key, args) => ({
|
|
9584
|
+
type: "Function",
|
|
9585
|
+
name: key,
|
|
9586
|
+
fn: key,
|
|
9587
|
+
args: args.map(toOperand7)
|
|
9588
|
+
});
|
|
9589
|
+
var arrayAppend = (array, value) => fn7("ARRAY_APPEND", [array, value]);
|
|
8383
9590
|
|
|
8384
9591
|
// src/orm/als.ts
|
|
8385
9592
|
var AsyncLocalStorage = class {
|
|
@@ -8459,7 +9666,7 @@ var DefaultNamingStrategy = class {
|
|
|
8459
9666
|
* @returns Capitalized table name (handles schema-qualified names)
|
|
8460
9667
|
*/
|
|
8461
9668
|
tableToSymbol(table) {
|
|
8462
|
-
const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.name;
|
|
9669
|
+
const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.type === "FunctionTable" ? table.alias ?? table.name : table.name;
|
|
8463
9670
|
if (tableName.includes(".")) {
|
|
8464
9671
|
return tableName.split(".").map((part) => this.capitalize(part)).join("");
|
|
8465
9672
|
}
|
|
@@ -8615,6 +9822,7 @@ var TypeScriptGenerator = class {
|
|
|
8615
9822
|
case "CaseExpression":
|
|
8616
9823
|
case "WindowFunction":
|
|
8617
9824
|
case "Cast":
|
|
9825
|
+
case "Collate":
|
|
8618
9826
|
return this.printOperand(term);
|
|
8619
9827
|
default:
|
|
8620
9828
|
return this.printExpression(term);
|
|
@@ -8677,6 +9885,9 @@ var TypeScriptGenerator = class {
|
|
|
8677
9885
|
visitCast(node) {
|
|
8678
9886
|
return this.printCastOperand(node);
|
|
8679
9887
|
}
|
|
9888
|
+
visitCollate(node) {
|
|
9889
|
+
return this.printCollateOperand(node);
|
|
9890
|
+
}
|
|
8680
9891
|
visitAliasRef(node) {
|
|
8681
9892
|
return `aliasRef('${node.name}')`;
|
|
8682
9893
|
}
|
|
@@ -8688,12 +9899,12 @@ var TypeScriptGenerator = class {
|
|
|
8688
9899
|
printBinaryExpression(binary) {
|
|
8689
9900
|
const left2 = this.printOperand(binary.left);
|
|
8690
9901
|
const right2 = this.printOperand(binary.right);
|
|
8691
|
-
const
|
|
9902
|
+
const fn8 = this.mapOp(binary.operator);
|
|
8692
9903
|
const args = [left2, right2];
|
|
8693
9904
|
if (binary.escape) {
|
|
8694
9905
|
args.push(this.printOperand(binary.escape));
|
|
8695
9906
|
}
|
|
8696
|
-
return `${
|
|
9907
|
+
return `${fn8}(${args.join(", ")})`;
|
|
8697
9908
|
}
|
|
8698
9909
|
/**
|
|
8699
9910
|
* Prints a logical expression to TypeScript code
|
|
@@ -8722,13 +9933,13 @@ var TypeScriptGenerator = class {
|
|
|
8722
9933
|
*/
|
|
8723
9934
|
printInExpression(inExpr) {
|
|
8724
9935
|
const left2 = this.printOperand(inExpr.left);
|
|
8725
|
-
const
|
|
9936
|
+
const fn8 = this.mapOp(inExpr.operator);
|
|
8726
9937
|
if (Array.isArray(inExpr.right)) {
|
|
8727
9938
|
const values = inExpr.right.map((v) => this.printOperand(v)).join(", ");
|
|
8728
|
-
return `${
|
|
9939
|
+
return `${fn8}(${left2}, [${values}])`;
|
|
8729
9940
|
}
|
|
8730
9941
|
const subquery = this.inlineChain(this.buildSelectLines(inExpr.right.query));
|
|
8731
|
-
return `${
|
|
9942
|
+
return `${fn8}(${left2}, (${subquery}))`;
|
|
8732
9943
|
}
|
|
8733
9944
|
/**
|
|
8734
9945
|
* Prints a null expression to TypeScript code
|
|
@@ -8737,8 +9948,8 @@ var TypeScriptGenerator = class {
|
|
|
8737
9948
|
*/
|
|
8738
9949
|
printNullExpression(nullExpr) {
|
|
8739
9950
|
const left2 = this.printOperand(nullExpr.left);
|
|
8740
|
-
const
|
|
8741
|
-
return `${
|
|
9951
|
+
const fn8 = this.mapOp(nullExpr.operator);
|
|
9952
|
+
return `${fn8}(${left2})`;
|
|
8742
9953
|
}
|
|
8743
9954
|
/**
|
|
8744
9955
|
* Prints a BETWEEN expression to TypeScript code
|
|
@@ -8782,9 +9993,9 @@ var TypeScriptGenerator = class {
|
|
|
8782
9993
|
* @param fn - Function node
|
|
8783
9994
|
* @returns TypeScript code representation
|
|
8784
9995
|
*/
|
|
8785
|
-
printFunctionOperand(
|
|
8786
|
-
const args =
|
|
8787
|
-
return `${
|
|
9996
|
+
printFunctionOperand(fn8) {
|
|
9997
|
+
const args = fn8.args.map((a) => this.printOperand(a)).join(", ");
|
|
9998
|
+
return `${fn8.name.toLowerCase()}(${args})`;
|
|
8788
9999
|
}
|
|
8789
10000
|
/**
|
|
8790
10001
|
* Prints a JSON path operand to TypeScript code
|
|
@@ -8848,6 +10059,9 @@ var TypeScriptGenerator = class {
|
|
|
8848
10059
|
const typeLiteral = node.castType.replace(/'/g, "\\'");
|
|
8849
10060
|
return `cast(${this.printOperand(node.expression)}, '${typeLiteral}')`;
|
|
8850
10061
|
}
|
|
10062
|
+
printCollateOperand(node) {
|
|
10063
|
+
return `collate(${this.printOperand(node.expression)}, '${node.collation}')`;
|
|
10064
|
+
}
|
|
8851
10065
|
/**
|
|
8852
10066
|
* Converts method chain lines to inline format
|
|
8853
10067
|
* @param lines - Method chain lines
|
|
@@ -8878,10 +10092,20 @@ var IdentityMap = class {
|
|
|
8878
10092
|
get bucketsMap() {
|
|
8879
10093
|
return this.buckets;
|
|
8880
10094
|
}
|
|
10095
|
+
/**
|
|
10096
|
+
* Retrieves an entity from the identity map if it exists.
|
|
10097
|
+
* @param table The table definition of the entity.
|
|
10098
|
+
* @param pk The primary key value.
|
|
10099
|
+
* @returns The entity instance if found, undefined otherwise.
|
|
10100
|
+
*/
|
|
8881
10101
|
getEntity(table, pk) {
|
|
8882
10102
|
const bucket = this.buckets.get(table.name);
|
|
8883
10103
|
return bucket?.get(this.toIdentityKey(pk))?.entity;
|
|
8884
10104
|
}
|
|
10105
|
+
/**
|
|
10106
|
+
* Registers a tracked entity in the identity map.
|
|
10107
|
+
* @param tracked The tracked entity metadata and instance.
|
|
10108
|
+
*/
|
|
8885
10109
|
register(tracked) {
|
|
8886
10110
|
if (tracked.pk == null) return;
|
|
8887
10111
|
const bucket = this.buckets.get(tracked.table.name) ?? /* @__PURE__ */ new Map();
|
|
@@ -8893,6 +10117,11 @@ var IdentityMap = class {
|
|
|
8893
10117
|
const bucket = this.buckets.get(tracked.table.name);
|
|
8894
10118
|
bucket?.delete(this.toIdentityKey(tracked.pk));
|
|
8895
10119
|
}
|
|
10120
|
+
/**
|
|
10121
|
+
* Returns all tracked entities for a specific table.
|
|
10122
|
+
* @param table The table definition.
|
|
10123
|
+
* @returns Array of tracked entities.
|
|
10124
|
+
*/
|
|
8896
10125
|
getEntitiesForTable(table) {
|
|
8897
10126
|
const bucket = this.buckets.get(table.name);
|
|
8898
10127
|
return bucket ? Array.from(bucket.values()) : [];
|
|
@@ -10017,15 +11246,15 @@ var OrmSession = class {
|
|
|
10017
11246
|
* @returns The result of the function
|
|
10018
11247
|
* @throws If the transaction fails
|
|
10019
11248
|
*/
|
|
10020
|
-
async transaction(
|
|
11249
|
+
async transaction(fn8) {
|
|
10021
11250
|
if (!this.executor.capabilities.transactions) {
|
|
10022
|
-
const result = await
|
|
11251
|
+
const result = await fn8(this);
|
|
10023
11252
|
await this.commit();
|
|
10024
11253
|
return result;
|
|
10025
11254
|
}
|
|
10026
11255
|
await this.executor.beginTransaction();
|
|
10027
11256
|
try {
|
|
10028
|
-
const result = await
|
|
11257
|
+
const result = await fn8(this);
|
|
10029
11258
|
await this.flushWithHooks();
|
|
10030
11259
|
await this.executor.commitTransaction();
|
|
10031
11260
|
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
@@ -10128,11 +11357,11 @@ var Orm = class {
|
|
|
10128
11357
|
* @returns The result of the function
|
|
10129
11358
|
* @throws If the transaction fails
|
|
10130
11359
|
*/
|
|
10131
|
-
async transaction(
|
|
11360
|
+
async transaction(fn8) {
|
|
10132
11361
|
const executor = this.executorFactory.createTransactionalExecutor();
|
|
10133
11362
|
const session = new OrmSession({ orm: this, executor });
|
|
10134
11363
|
try {
|
|
10135
|
-
return await session.transaction(() =>
|
|
11364
|
+
return await session.transaction(() => fn8(session));
|
|
10136
11365
|
} finally {
|
|
10137
11366
|
await session.dispose();
|
|
10138
11367
|
}
|
|
@@ -10958,8 +12187,10 @@ function createPooledExecutorFactory(opts) {
|
|
|
10958
12187
|
acos,
|
|
10959
12188
|
add,
|
|
10960
12189
|
addDomainEvent,
|
|
12190
|
+
age,
|
|
10961
12191
|
aliasRef,
|
|
10962
12192
|
and,
|
|
12193
|
+
arrayAppend,
|
|
10963
12194
|
ascii,
|
|
10964
12195
|
asin,
|
|
10965
12196
|
atan,
|
|
@@ -10968,16 +12199,24 @@ function createPooledExecutorFactory(opts) {
|
|
|
10968
12199
|
belongsTo,
|
|
10969
12200
|
belongsToMany,
|
|
10970
12201
|
between,
|
|
12202
|
+
bitAnd,
|
|
12203
|
+
bitLength,
|
|
12204
|
+
bitOr,
|
|
12205
|
+
bitXor,
|
|
10971
12206
|
bootstrapEntities,
|
|
10972
12207
|
caseWhen,
|
|
10973
12208
|
cast,
|
|
12209
|
+
cbrt,
|
|
10974
12210
|
ceil,
|
|
10975
12211
|
ceiling,
|
|
10976
12212
|
char,
|
|
10977
12213
|
charLength,
|
|
12214
|
+
chr,
|
|
10978
12215
|
clearExpressionDispatchers,
|
|
10979
12216
|
clearOperandDispatchers,
|
|
12217
|
+
coalesce,
|
|
10980
12218
|
col,
|
|
12219
|
+
collate,
|
|
10981
12220
|
columnOperand,
|
|
10982
12221
|
concat,
|
|
10983
12222
|
concatWs,
|
|
@@ -11029,18 +12268,23 @@ function createPooledExecutorFactory(opts) {
|
|
|
11029
12268
|
getDecoratorMetadata,
|
|
11030
12269
|
getSchemaIntrospector,
|
|
11031
12270
|
getTableDefFromEntity,
|
|
12271
|
+
greatest,
|
|
11032
12272
|
groupConcat,
|
|
11033
12273
|
gt,
|
|
11034
12274
|
gte,
|
|
11035
12275
|
hasMany,
|
|
11036
12276
|
hasOne,
|
|
12277
|
+
hour,
|
|
11037
12278
|
hydrateRows,
|
|
12279
|
+
ifNull,
|
|
11038
12280
|
inList,
|
|
11039
12281
|
inSubquery,
|
|
12282
|
+
initcap,
|
|
11040
12283
|
instr,
|
|
11041
12284
|
introspectSchema,
|
|
11042
12285
|
isCaseExpressionNode,
|
|
11043
12286
|
isCastExpressionNode,
|
|
12287
|
+
isCollateExpressionNode,
|
|
11044
12288
|
isExpressionSelectionNode,
|
|
11045
12289
|
isFunctionNode,
|
|
11046
12290
|
isNotNull,
|
|
@@ -11048,11 +12292,16 @@ function createPooledExecutorFactory(opts) {
|
|
|
11048
12292
|
isOperandNode,
|
|
11049
12293
|
isValueOperandInput,
|
|
11050
12294
|
isWindowFunctionNode,
|
|
12295
|
+
jsonArrayAgg,
|
|
12296
|
+
jsonContains,
|
|
12297
|
+
jsonLength,
|
|
11051
12298
|
jsonPath,
|
|
12299
|
+
jsonSet,
|
|
11052
12300
|
jsonify,
|
|
11053
12301
|
lag,
|
|
11054
12302
|
lastValue,
|
|
11055
12303
|
lead,
|
|
12304
|
+
least,
|
|
11056
12305
|
left,
|
|
11057
12306
|
length,
|
|
11058
12307
|
like,
|
|
@@ -11061,9 +12310,12 @@ function createPooledExecutorFactory(opts) {
|
|
|
11061
12310
|
loadBelongsToRelation,
|
|
11062
12311
|
loadHasManyRelation,
|
|
11063
12312
|
loadHasOneRelation,
|
|
12313
|
+
localTime,
|
|
12314
|
+
localTimestamp,
|
|
11064
12315
|
locate,
|
|
11065
12316
|
log,
|
|
11066
12317
|
log10,
|
|
12318
|
+
log2,
|
|
11067
12319
|
logBase,
|
|
11068
12320
|
lower,
|
|
11069
12321
|
lpad,
|
|
@@ -11071,7 +12323,9 @@ function createPooledExecutorFactory(opts) {
|
|
|
11071
12323
|
lte,
|
|
11072
12324
|
ltrim,
|
|
11073
12325
|
max,
|
|
12326
|
+
md5,
|
|
11074
12327
|
min,
|
|
12328
|
+
minute,
|
|
11075
12329
|
mod,
|
|
11076
12330
|
month,
|
|
11077
12331
|
mul,
|
|
@@ -11084,12 +12338,15 @@ function createPooledExecutorFactory(opts) {
|
|
|
11084
12338
|
notLike,
|
|
11085
12339
|
now,
|
|
11086
12340
|
ntile,
|
|
12341
|
+
nullif,
|
|
12342
|
+
octetLength,
|
|
11087
12343
|
or,
|
|
11088
12344
|
outerRef,
|
|
11089
12345
|
pi,
|
|
11090
12346
|
position,
|
|
11091
12347
|
pow,
|
|
11092
12348
|
power,
|
|
12349
|
+
quarter,
|
|
11093
12350
|
radians,
|
|
11094
12351
|
rand,
|
|
11095
12352
|
random,
|
|
@@ -11097,22 +12354,30 @@ function createPooledExecutorFactory(opts) {
|
|
|
11097
12354
|
registerExpressionDispatcher,
|
|
11098
12355
|
registerOperandDispatcher,
|
|
11099
12356
|
registerSchemaIntrospector,
|
|
12357
|
+
relationLoaderCache,
|
|
11100
12358
|
renderColumnDefinition,
|
|
11101
12359
|
renderTypeWithArgs,
|
|
11102
12360
|
repeat,
|
|
11103
12361
|
replace,
|
|
12362
|
+
reverse,
|
|
11104
12363
|
right,
|
|
11105
12364
|
round,
|
|
11106
12365
|
rowNumber,
|
|
11107
12366
|
rowsToQueryResult,
|
|
11108
12367
|
rpad,
|
|
11109
12368
|
rtrim,
|
|
12369
|
+
second,
|
|
11110
12370
|
sel,
|
|
11111
12371
|
selectFromEntity,
|
|
12372
|
+
sha1,
|
|
12373
|
+
sha2,
|
|
12374
|
+
shiftLeft,
|
|
12375
|
+
shiftRight,
|
|
11112
12376
|
sign,
|
|
11113
12377
|
sin,
|
|
11114
12378
|
space,
|
|
11115
12379
|
sqrt,
|
|
12380
|
+
stddev,
|
|
11116
12381
|
sub,
|
|
11117
12382
|
substr,
|
|
11118
12383
|
sum,
|
|
@@ -11128,6 +12393,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
11128
12393
|
upper,
|
|
11129
12394
|
utcNow,
|
|
11130
12395
|
valueToOperand,
|
|
12396
|
+
variance,
|
|
11131
12397
|
visitExpression,
|
|
11132
12398
|
visitOperand,
|
|
11133
12399
|
weekOfYear,
|