@mikro-orm/knex 6.0.0-dev.4 → 6.0.0-dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{dist/AbstractSqlConnection.d.ts → AbstractSqlConnection.d.ts} +0 -0
- package/{dist/AbstractSqlConnection.js → AbstractSqlConnection.js} +5 -0
- package/AbstractSqlDriver.d.ts +66 -0
- package/{dist/AbstractSqlDriver.js → AbstractSqlDriver.js} +218 -70
- package/{dist/AbstractSqlPlatform.d.ts → AbstractSqlPlatform.d.ts} +6 -4
- package/{dist/AbstractSqlPlatform.js → AbstractSqlPlatform.js} +18 -7
- package/{dist/MonkeyPatchable.d.ts → MonkeyPatchable.d.ts} +0 -0
- package/{dist/MonkeyPatchable.js → MonkeyPatchable.js} +0 -0
- package/{dist/README.md → README.md} +2 -2
- package/{dist/SqlEntityManager.d.ts → SqlEntityManager.d.ts} +5 -5
- package/{dist/SqlEntityManager.js → SqlEntityManager.js} +0 -1
- package/{dist/SqlEntityRepository.d.ts → SqlEntityRepository.d.ts} +3 -3
- package/{dist/SqlEntityRepository.js → SqlEntityRepository.js} +1 -1
- package/{dist/index.d.ts → index.d.ts} +0 -0
- package/{dist/index.js → index.js} +5 -1
- package/{dist/index.mjs → index.mjs} +0 -0
- package/package.json +27 -22
- package/{dist/query → query}/ArrayCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ArrayCriteriaNode.js +0 -0
- package/{dist/query → query}/CriteriaNode.d.ts +0 -0
- package/{dist/query → query}/CriteriaNode.js +7 -4
- package/{dist/query → query}/CriteriaNodeFactory.d.ts +0 -0
- package/{dist/query → query}/CriteriaNodeFactory.js +0 -0
- package/{dist/query → query}/ObjectCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ObjectCriteriaNode.js +14 -1
- package/{dist/query → query}/QueryBuilder.d.ts +58 -24
- package/{dist/query → query}/QueryBuilder.js +285 -84
- package/{dist/query → query}/QueryBuilderHelper.d.ts +19 -11
- package/{dist/query → query}/QueryBuilderHelper.js +206 -108
- package/{dist/query → query}/ScalarCriteriaNode.d.ts +0 -0
- package/{dist/query → query}/ScalarCriteriaNode.js +0 -0
- package/{dist/query → query}/enums.d.ts +0 -0
- package/{dist/query → query}/enums.js +0 -0
- package/{dist/query → query}/index.d.ts +0 -0
- package/{dist/query → query}/index.js +5 -1
- package/{dist/schema → schema}/DatabaseSchema.d.ts +1 -1
- package/{dist/schema → schema}/DatabaseSchema.js +8 -16
- package/{dist/schema → schema}/DatabaseTable.d.ts +1 -1
- package/{dist/schema → schema}/DatabaseTable.js +2 -1
- package/{dist/schema → schema}/SchemaComparator.d.ts +3 -1
- package/{dist/schema → schema}/SchemaComparator.js +58 -10
- package/{dist/schema → schema}/SchemaGenerator.d.ts +10 -8
- package/{dist/schema → schema}/SchemaGenerator.js +81 -28
- package/{dist/schema → schema}/SchemaHelper.d.ts +9 -4
- package/{dist/schema → schema}/SchemaHelper.js +46 -8
- package/{dist/schema → schema}/index.d.ts +0 -0
- package/{dist/schema → schema}/index.js +5 -1
- package/{dist/typings.d.ts → typings.d.ts} +7 -3
- package/{dist/typings.js → typings.js} +0 -0
- package/CHANGELOG.md +0 -661
- package/dist/AbstractSqlDriver.d.ts +0 -55
- package/dist/LICENSE +0 -21
- package/dist/package.json +0 -99
|
@@ -25,11 +25,21 @@ const CriteriaNodeFactory_1 = require("./CriteriaNodeFactory");
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
class QueryBuilder {
|
|
28
|
+
get mainAlias() {
|
|
29
|
+
this.ensureFromClause();
|
|
30
|
+
return this._mainAlias;
|
|
31
|
+
}
|
|
32
|
+
get alias() {
|
|
33
|
+
return this.mainAlias.aliasName;
|
|
34
|
+
}
|
|
35
|
+
get helper() {
|
|
36
|
+
this.ensureFromClause();
|
|
37
|
+
return this._helper;
|
|
38
|
+
}
|
|
28
39
|
/**
|
|
29
40
|
* @internal
|
|
30
41
|
*/
|
|
31
42
|
constructor(entityName, metadata, driver, context, alias, connectionType, em) {
|
|
32
|
-
this.entityName = entityName;
|
|
33
43
|
this.metadata = metadata;
|
|
34
44
|
this.driver = driver;
|
|
35
45
|
this.context = context;
|
|
@@ -43,23 +53,25 @@ class QueryBuilder {
|
|
|
43
53
|
this.flags = new Set([core_1.QueryFlag.CONVERT_CUSTOM_TYPES]);
|
|
44
54
|
this.finalized = false;
|
|
45
55
|
this._joins = {};
|
|
46
|
-
this.
|
|
56
|
+
this._explicitAlias = false;
|
|
47
57
|
this._cond = {};
|
|
48
58
|
this._orderBy = [];
|
|
49
59
|
this._groupBy = [];
|
|
50
60
|
this._having = {};
|
|
51
61
|
this._joinedProps = new Map();
|
|
52
62
|
this.subQueries = {};
|
|
63
|
+
this._aliases = {};
|
|
53
64
|
this.platform = this.driver.getPlatform();
|
|
54
65
|
this.knex = this.driver.getConnection(this.connectionType).getKnex();
|
|
55
66
|
if (alias) {
|
|
56
67
|
this.aliasCounter++;
|
|
68
|
+
this._explicitAlias = true;
|
|
57
69
|
}
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
-
this.helper = new QueryBuilderHelper_1.QueryBuilderHelper(this.entityName, this.alias, this._aliasMap, this.subQueries, this.metadata, this.knex, this.platform);
|
|
70
|
+
// @ts-expect-error union type does not match the overloaded method signature
|
|
71
|
+
this.from(entityName, alias);
|
|
61
72
|
}
|
|
62
73
|
select(fields, distinct = false) {
|
|
74
|
+
this.ensureNotFinalized();
|
|
63
75
|
this._fields = core_1.Utils.asArray(fields);
|
|
64
76
|
if (distinct) {
|
|
65
77
|
this.flags.add(core_1.QueryFlag.DISTINCT);
|
|
@@ -67,11 +79,22 @@ class QueryBuilder {
|
|
|
67
79
|
return this.init(enums_1.QueryType.SELECT);
|
|
68
80
|
}
|
|
69
81
|
addSelect(fields) {
|
|
82
|
+
this.ensureNotFinalized();
|
|
70
83
|
if (this.type && this.type !== enums_1.QueryType.SELECT) {
|
|
71
84
|
return this;
|
|
72
85
|
}
|
|
73
86
|
return this.select([...core_1.Utils.asArray(this._fields), ...core_1.Utils.asArray(fields)]);
|
|
74
87
|
}
|
|
88
|
+
distinct() {
|
|
89
|
+
this.ensureNotFinalized();
|
|
90
|
+
return this.setFlag(core_1.QueryFlag.DISTINCT);
|
|
91
|
+
}
|
|
92
|
+
/** postgres only */
|
|
93
|
+
distinctOn(fields) {
|
|
94
|
+
this.ensureNotFinalized();
|
|
95
|
+
this._distinctOn = core_1.Utils.asArray(fields);
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
75
98
|
insert(data) {
|
|
76
99
|
return this.init(enums_1.QueryType.INSERT, data);
|
|
77
100
|
}
|
|
@@ -85,7 +108,15 @@ class QueryBuilder {
|
|
|
85
108
|
return this.init(enums_1.QueryType.TRUNCATE);
|
|
86
109
|
}
|
|
87
110
|
count(field, distinct = false) {
|
|
88
|
-
|
|
111
|
+
if (field) {
|
|
112
|
+
this._fields = core_1.Utils.asArray(field);
|
|
113
|
+
}
|
|
114
|
+
else if (this.hasToManyJoins()) {
|
|
115
|
+
this._fields = this.mainAlias.metadata.primaryKeys;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
this._fields = [this.raw('*')];
|
|
119
|
+
}
|
|
89
120
|
if (distinct) {
|
|
90
121
|
this.flags.add(core_1.QueryFlag.DISTINCT);
|
|
91
122
|
}
|
|
@@ -99,6 +130,9 @@ class QueryBuilder {
|
|
|
99
130
|
return this.join(field, alias, cond, 'leftJoin');
|
|
100
131
|
}
|
|
101
132
|
joinAndSelect(field, alias, cond = {}, type = 'innerJoin', path) {
|
|
133
|
+
if (!this.type) {
|
|
134
|
+
this.select('*');
|
|
135
|
+
}
|
|
102
136
|
const prop = this.joinReference(field, alias, cond, type, path);
|
|
103
137
|
this.addSelect(this.getFieldsForJoinedLoad(prop, alias));
|
|
104
138
|
const [fromAlias] = this.helper.splitField(field);
|
|
@@ -124,24 +158,34 @@ class QueryBuilder {
|
|
|
124
158
|
return fields;
|
|
125
159
|
}
|
|
126
160
|
withSubQuery(subQuery, alias) {
|
|
161
|
+
this.ensureNotFinalized();
|
|
127
162
|
this.subQueries[alias] = subQuery.toString();
|
|
128
163
|
return this;
|
|
129
164
|
}
|
|
130
165
|
where(cond, params, operator) {
|
|
166
|
+
this.ensureNotFinalized();
|
|
131
167
|
if (core_1.Utils.isString(cond)) {
|
|
132
168
|
cond = { [`(${cond})`]: core_1.Utils.asArray(params) };
|
|
133
169
|
operator = operator || '$and';
|
|
134
170
|
}
|
|
135
171
|
else {
|
|
136
|
-
cond = core_1.QueryHelper.processWhere(
|
|
172
|
+
cond = core_1.QueryHelper.processWhere({
|
|
173
|
+
where: cond,
|
|
174
|
+
entityName: this.mainAlias.entityName,
|
|
175
|
+
metadata: this.metadata,
|
|
176
|
+
platform: this.platform,
|
|
177
|
+
aliasMap: this.getAliasMap(),
|
|
178
|
+
aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
|
|
179
|
+
convertCustomTypes: this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES),
|
|
180
|
+
});
|
|
137
181
|
}
|
|
138
182
|
const op = operator || params;
|
|
139
183
|
const topLevel = !op || !core_1.Utils.hasObjectKeys(this._cond);
|
|
140
|
-
const criteriaNode = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.entityName, cond);
|
|
184
|
+
const criteriaNode = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond);
|
|
141
185
|
if ([enums_1.QueryType.UPDATE, enums_1.QueryType.DELETE].includes(this.type) && criteriaNode.willAutoJoin(this)) {
|
|
142
186
|
// use sub-query to support joining
|
|
143
187
|
this.setFlag(this.type === enums_1.QueryType.UPDATE ? core_1.QueryFlag.UPDATE_SUB_QUERY : core_1.QueryFlag.DELETE_SUB_QUERY);
|
|
144
|
-
this.select(this.metadata.
|
|
188
|
+
this.select(this.mainAlias.metadata.primaryKeys, true);
|
|
145
189
|
}
|
|
146
190
|
if (topLevel) {
|
|
147
191
|
this._cond = criteriaNode.process(this);
|
|
@@ -166,27 +210,39 @@ class QueryBuilder {
|
|
|
166
210
|
return this.where(cond, params, '$or');
|
|
167
211
|
}
|
|
168
212
|
orderBy(orderBy) {
|
|
213
|
+
this.ensureNotFinalized();
|
|
169
214
|
this._orderBy = [];
|
|
170
215
|
core_1.Utils.asArray(orderBy).forEach(o => {
|
|
171
|
-
const processed = core_1.QueryHelper.processWhere(
|
|
172
|
-
|
|
216
|
+
const processed = core_1.QueryHelper.processWhere({
|
|
217
|
+
where: o,
|
|
218
|
+
entityName: this.mainAlias.entityName,
|
|
219
|
+
metadata: this.metadata,
|
|
220
|
+
platform: this.platform,
|
|
221
|
+
aliasMap: this.getAliasMap(),
|
|
222
|
+
aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
|
|
223
|
+
convertCustomTypes: false,
|
|
224
|
+
});
|
|
225
|
+
this._orderBy.push(CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, processed).process(this));
|
|
173
226
|
});
|
|
174
227
|
return this;
|
|
175
228
|
}
|
|
176
229
|
groupBy(fields) {
|
|
230
|
+
this.ensureNotFinalized();
|
|
177
231
|
this._groupBy = core_1.Utils.asArray(fields);
|
|
178
232
|
return this;
|
|
179
233
|
}
|
|
180
234
|
having(cond = {}, params) {
|
|
235
|
+
this.ensureNotFinalized();
|
|
181
236
|
if (core_1.Utils.isString(cond)) {
|
|
182
237
|
cond = { [`(${cond})`]: core_1.Utils.asArray(params) };
|
|
183
238
|
}
|
|
184
|
-
this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.entityName, cond).process(this);
|
|
239
|
+
this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
|
|
185
240
|
return this;
|
|
186
241
|
}
|
|
187
242
|
onConflict(fields = []) {
|
|
243
|
+
this.ensureNotFinalized();
|
|
188
244
|
this._onConflict = this._onConflict || [];
|
|
189
|
-
this._onConflict.push({ fields: core_1.Utils.asArray(fields) });
|
|
245
|
+
this._onConflict.push({ fields: core_1.Utils.asArray(fields).map(f => f.toString()) });
|
|
190
246
|
return this;
|
|
191
247
|
}
|
|
192
248
|
ignore() {
|
|
@@ -200,14 +256,19 @@ class QueryBuilder {
|
|
|
200
256
|
if (!this._onConflict) {
|
|
201
257
|
throw new Error('You need to call `qb.onConflict()` first to use `qb.merge()`');
|
|
202
258
|
}
|
|
259
|
+
if (Array.isArray(data) && data.length === 0) {
|
|
260
|
+
return this.ignore();
|
|
261
|
+
}
|
|
203
262
|
this._onConflict[this._onConflict.length - 1].merge = data;
|
|
204
263
|
return this;
|
|
205
264
|
}
|
|
206
265
|
/**
|
|
207
266
|
* @internal
|
|
208
267
|
*/
|
|
209
|
-
populate(populate) {
|
|
268
|
+
populate(populate, populateWhere) {
|
|
269
|
+
this.ensureNotFinalized();
|
|
210
270
|
this._populate = populate;
|
|
271
|
+
this._populateWhere = populateWhere;
|
|
211
272
|
return this;
|
|
212
273
|
}
|
|
213
274
|
/**
|
|
@@ -222,6 +283,7 @@ class QueryBuilder {
|
|
|
222
283
|
return raw;
|
|
223
284
|
}
|
|
224
285
|
limit(limit, offset = 0) {
|
|
286
|
+
this.ensureNotFinalized();
|
|
225
287
|
this._limit = limit;
|
|
226
288
|
if (offset) {
|
|
227
289
|
this.offset(offset);
|
|
@@ -229,14 +291,17 @@ class QueryBuilder {
|
|
|
229
291
|
return this;
|
|
230
292
|
}
|
|
231
293
|
offset(offset) {
|
|
294
|
+
this.ensureNotFinalized();
|
|
232
295
|
this._offset = offset;
|
|
233
296
|
return this;
|
|
234
297
|
}
|
|
235
298
|
withSchema(schema) {
|
|
299
|
+
this.ensureNotFinalized();
|
|
236
300
|
this._schema = schema;
|
|
237
301
|
return this;
|
|
238
302
|
}
|
|
239
303
|
setLockMode(mode, tables) {
|
|
304
|
+
this.ensureNotFinalized();
|
|
240
305
|
if (mode != null && mode !== core_1.LockMode.OPTIMISTIC && !this.context) {
|
|
241
306
|
throw core_1.ValidationError.transactionRequired();
|
|
242
307
|
}
|
|
@@ -245,18 +310,22 @@ class QueryBuilder {
|
|
|
245
310
|
return this;
|
|
246
311
|
}
|
|
247
312
|
setFlushMode(flushMode) {
|
|
313
|
+
this.ensureNotFinalized();
|
|
248
314
|
this.flushMode = flushMode;
|
|
249
315
|
return this;
|
|
250
316
|
}
|
|
251
317
|
setFlag(flag) {
|
|
318
|
+
this.ensureNotFinalized();
|
|
252
319
|
this.flags.add(flag);
|
|
253
320
|
return this;
|
|
254
321
|
}
|
|
255
322
|
unsetFlag(flag) {
|
|
323
|
+
this.ensureNotFinalized();
|
|
256
324
|
this.flags.delete(flag);
|
|
257
325
|
return this;
|
|
258
326
|
}
|
|
259
327
|
cache(config = true) {
|
|
328
|
+
this.ensureNotFinalized();
|
|
260
329
|
this._cache = config;
|
|
261
330
|
return this;
|
|
262
331
|
}
|
|
@@ -264,31 +333,46 @@ class QueryBuilder {
|
|
|
264
333
|
* Adds index hint to the FROM clause.
|
|
265
334
|
*/
|
|
266
335
|
indexHint(sql) {
|
|
336
|
+
this.ensureNotFinalized();
|
|
267
337
|
this._indexHint = sql;
|
|
268
338
|
return this;
|
|
269
339
|
}
|
|
340
|
+
from(target, aliasName) {
|
|
341
|
+
this.ensureNotFinalized();
|
|
342
|
+
if (target instanceof QueryBuilder) {
|
|
343
|
+
this.fromSubQuery(target, aliasName);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
const entityName = core_1.Utils.className(target);
|
|
347
|
+
if (aliasName && this._mainAlias && entityName !== this._mainAlias.aliasName) {
|
|
348
|
+
throw new Error(`Cannot override the alias to '${aliasName}' since a query already contains references to '${this._mainAlias.aliasName}'`);
|
|
349
|
+
}
|
|
350
|
+
this.fromEntityName(entityName, aliasName);
|
|
351
|
+
}
|
|
352
|
+
return this;
|
|
353
|
+
}
|
|
270
354
|
getKnexQuery() {
|
|
271
355
|
this.finalize();
|
|
272
356
|
const qb = this.getQueryBase();
|
|
273
|
-
core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this._cond, qb), this._cond && !this._onConflict);
|
|
357
|
+
core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? enums_1.QueryType.SELECT, this._cond, qb), this._cond && !this._onConflict);
|
|
274
358
|
core_1.Utils.runIfNotEmpty(() => qb.groupBy(this.prepareFields(this._groupBy, 'groupBy')), this._groupBy);
|
|
275
|
-
core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this._having, qb, undefined, 'having'), this._having);
|
|
359
|
+
core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? enums_1.QueryType.SELECT, this._having, qb, undefined, 'having'), this._having);
|
|
276
360
|
core_1.Utils.runIfNotEmpty(() => {
|
|
277
|
-
const queryOrder = this.helper.getQueryOrder(this.type, this._orderBy, this._populateMap);
|
|
361
|
+
const queryOrder = this.helper.getQueryOrder(this.type ?? enums_1.QueryType.SELECT, this._orderBy, this._populateMap);
|
|
278
362
|
if (queryOrder) {
|
|
279
363
|
return qb.orderByRaw(queryOrder);
|
|
280
364
|
}
|
|
281
365
|
}, this._orderBy);
|
|
282
366
|
core_1.Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
|
|
283
367
|
core_1.Utils.runIfNotEmpty(() => qb.offset(this._offset), this._offset);
|
|
284
|
-
core_1.Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(this.type, this._onConflict, qb), this._onConflict);
|
|
368
|
+
core_1.Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(this.type ?? enums_1.QueryType.SELECT, this._onConflict, qb), this._onConflict);
|
|
285
369
|
if (this.type === enums_1.QueryType.TRUNCATE && this.platform.usesCascadeStatement()) {
|
|
286
370
|
return this.knex.raw(qb.toSQL().toNative().sql + ' cascade');
|
|
287
371
|
}
|
|
288
372
|
if (this.lockMode) {
|
|
289
373
|
this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
|
|
290
374
|
}
|
|
291
|
-
this.helper.finalize(this.type, qb, this.metadata
|
|
375
|
+
this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata);
|
|
292
376
|
return qb;
|
|
293
377
|
}
|
|
294
378
|
/**
|
|
@@ -310,9 +394,12 @@ class QueryBuilder {
|
|
|
310
394
|
const query = this.getKnexQuery().toSQL();
|
|
311
395
|
return this.platform.formatQuery(query.sql, query.bindings);
|
|
312
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* @internal
|
|
399
|
+
*/
|
|
313
400
|
getAliasForJoinPath(path) {
|
|
314
|
-
if (!path || path === this.entityName) {
|
|
315
|
-
return this.
|
|
401
|
+
if (!path || path === this.mainAlias.entityName) {
|
|
402
|
+
return this.mainAlias.aliasName;
|
|
316
403
|
}
|
|
317
404
|
const join = Object.values(this._joins).find(j => j.path === path);
|
|
318
405
|
if (path.endsWith('[pivot]') && join) {
|
|
@@ -320,25 +407,34 @@ class QueryBuilder {
|
|
|
320
407
|
}
|
|
321
408
|
return join?.inverseAlias || join?.alias;
|
|
322
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* @internal
|
|
412
|
+
*/
|
|
323
413
|
getNextAlias(entityName = 'e') {
|
|
324
414
|
return this.driver.config.getNamingStrategy().aliasName(entityName, this.aliasCounter++);
|
|
325
415
|
}
|
|
416
|
+
/**
|
|
417
|
+
* @internal
|
|
418
|
+
*/
|
|
419
|
+
getAliasMap() {
|
|
420
|
+
return Object.fromEntries(Object.entries(this._aliases).map(([key, value]) => [key, value.entityName]));
|
|
421
|
+
}
|
|
326
422
|
/**
|
|
327
423
|
* Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
|
|
328
424
|
* Use `method` to specify what kind of result you want to get (array/single/meta).
|
|
329
425
|
*/
|
|
330
426
|
async execute(method = 'all', mapResults = true) {
|
|
331
|
-
if (!this.connectionType && method !== 'run' && [enums_1.QueryType.INSERT, enums_1.QueryType.UPDATE, enums_1.QueryType.DELETE, enums_1.QueryType.TRUNCATE].includes(this.type)) {
|
|
427
|
+
if (!this.connectionType && method !== 'run' && [enums_1.QueryType.INSERT, enums_1.QueryType.UPDATE, enums_1.QueryType.DELETE, enums_1.QueryType.TRUNCATE].includes(this.type ?? enums_1.QueryType.SELECT)) {
|
|
332
428
|
this.connectionType = 'write';
|
|
333
429
|
}
|
|
334
430
|
const query = this.getKnexQuery().toSQL();
|
|
335
|
-
const cached = await this.em?.tryCache(this.entityName, this._cache, ['qb.execute', query.sql, query.bindings, method]);
|
|
431
|
+
const cached = await this.em?.tryCache(this.mainAlias.entityName, this._cache, ['qb.execute', query.sql, query.bindings, method]);
|
|
336
432
|
if (cached?.data) {
|
|
337
433
|
return cached.data;
|
|
338
434
|
}
|
|
339
435
|
const type = this.connectionType || (method === 'run' ? 'write' : 'read');
|
|
340
436
|
const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context);
|
|
341
|
-
const meta = this.metadata
|
|
437
|
+
const meta = this.mainAlias.metadata;
|
|
342
438
|
if (!mapResults || !meta) {
|
|
343
439
|
await this.em?.storeCache(this._cache, cached, res);
|
|
344
440
|
return res;
|
|
@@ -363,12 +459,12 @@ class QueryBuilder {
|
|
|
363
459
|
* Executes the query, returning array of results
|
|
364
460
|
*/
|
|
365
461
|
async getResultList() {
|
|
366
|
-
await this.em.tryFlush(this.entityName, { flushMode: this.flushMode });
|
|
462
|
+
await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.flushMode });
|
|
367
463
|
let res = await this.execute('all', true);
|
|
368
464
|
if (this._joinedProps.size > 0) {
|
|
369
|
-
res = this.driver.mergeJoinedResult(res, this.metadata
|
|
465
|
+
res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata);
|
|
370
466
|
}
|
|
371
|
-
return res.map(r => this.em.map(this.entityName, r, { schema: this._schema }));
|
|
467
|
+
return res.map(r => this.em.map(this.mainAlias.entityName, r, { schema: this._schema }));
|
|
372
468
|
}
|
|
373
469
|
/**
|
|
374
470
|
* Executes the query, returning the first result or null
|
|
@@ -380,35 +476,32 @@ class QueryBuilder {
|
|
|
380
476
|
/**
|
|
381
477
|
* Executes count query (without offset and limit), returning total count of results
|
|
382
478
|
*/
|
|
383
|
-
async getCount(field, distinct
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
479
|
+
async getCount(field, distinct) {
|
|
480
|
+
let res;
|
|
481
|
+
if (this.type === enums_1.QueryType.COUNT) {
|
|
482
|
+
res = await this.execute('get', false);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
const qb = this.clone();
|
|
486
|
+
qb.count(field, distinct ?? qb.hasToManyJoins()).limit(undefined).offset(undefined).orderBy([]);
|
|
487
|
+
res = await qb.execute('get', false);
|
|
488
|
+
}
|
|
387
489
|
return res ? +res.count : 0;
|
|
388
490
|
}
|
|
389
491
|
/**
|
|
390
492
|
* Provides promise-like interface so we can await the QB instance.
|
|
391
493
|
*/
|
|
392
494
|
then(onfulfilled, onrejected) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
case enums_1.QueryType.TRUNCATE:
|
|
403
|
-
return this.execute('run');
|
|
404
|
-
case enums_1.QueryType.SELECT:
|
|
405
|
-
return this.getResultList();
|
|
406
|
-
case enums_1.QueryType.COUNT:
|
|
407
|
-
return this.getCount();
|
|
408
|
-
}
|
|
409
|
-
})();
|
|
495
|
+
switch (this.type ?? enums_1.QueryType.SELECT) {
|
|
496
|
+
case enums_1.QueryType.INSERT:
|
|
497
|
+
case enums_1.QueryType.UPDATE:
|
|
498
|
+
case enums_1.QueryType.DELETE:
|
|
499
|
+
case enums_1.QueryType.TRUNCATE:
|
|
500
|
+
return this.execute('run').then(onfulfilled, onrejected);
|
|
501
|
+
case enums_1.QueryType.COUNT:
|
|
502
|
+
return this.getCount().then(onfulfilled, onrejected);
|
|
503
|
+
case enums_1.QueryType.SELECT: return this.getResultList().then(onfulfilled, onrejected);
|
|
410
504
|
}
|
|
411
|
-
return this.innerPromise;
|
|
412
505
|
}
|
|
413
506
|
/**
|
|
414
507
|
* Returns knex instance with sub-query aliased with given alias.
|
|
@@ -425,11 +518,11 @@ class QueryBuilder {
|
|
|
425
518
|
return qb.as(alias);
|
|
426
519
|
}
|
|
427
520
|
clone() {
|
|
428
|
-
const qb = new QueryBuilder(this.entityName, this.metadata, this.driver, this.context, this.
|
|
521
|
+
const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
|
|
429
522
|
Object.assign(qb, this);
|
|
430
523
|
// clone array/object properties
|
|
431
524
|
const properties = [
|
|
432
|
-
'flags', '_populate', '
|
|
525
|
+
'flags', '_populate', '_populateWhere', '_populateMap', '_joins', '_joinedProps', '_cond', '_data', '_orderBy',
|
|
433
526
|
'_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables',
|
|
434
527
|
];
|
|
435
528
|
properties.forEach(prop => qb[prop] = core_1.Utils.copy(this[prop]));
|
|
@@ -437,27 +530,45 @@ class QueryBuilder {
|
|
|
437
530
|
if (this._fields) {
|
|
438
531
|
qb._fields = [...this._fields];
|
|
439
532
|
}
|
|
533
|
+
qb._aliases = { ...this._aliases };
|
|
440
534
|
qb.finalized = false;
|
|
441
535
|
return qb;
|
|
442
536
|
}
|
|
443
537
|
getKnex() {
|
|
444
|
-
const
|
|
445
|
-
const
|
|
538
|
+
const qb = this.knex.queryBuilder();
|
|
539
|
+
const { subQuery, aliasName, entityName } = this.mainAlias;
|
|
540
|
+
const ref = subQuery ? subQuery : this.knex.ref(this.helper.getTableName(entityName));
|
|
541
|
+
if (this.finalized && (this._explicitAlias || this.helper.isTableNameAliasRequired(this.type))) {
|
|
542
|
+
ref.as(aliasName);
|
|
543
|
+
}
|
|
544
|
+
const schema = this.getSchema(this.mainAlias);
|
|
545
|
+
if (schema) {
|
|
546
|
+
ref.withSchema(schema);
|
|
547
|
+
}
|
|
548
|
+
qb.from(ref);
|
|
446
549
|
if (this.context) {
|
|
447
550
|
qb.transacting(this.context);
|
|
448
551
|
}
|
|
449
552
|
return qb;
|
|
450
553
|
}
|
|
451
554
|
joinReference(field, alias, cond, type, path) {
|
|
555
|
+
this.ensureNotFinalized();
|
|
452
556
|
const [fromAlias, fromField] = this.helper.splitField(field);
|
|
453
|
-
const entityName = this.
|
|
557
|
+
const entityName = this._aliases[fromAlias]?.entityName;
|
|
454
558
|
const meta = this.metadata.get(entityName);
|
|
455
559
|
const prop = meta.properties[fromField];
|
|
456
560
|
if (!prop) {
|
|
457
561
|
throw new Error(`Trying to join ${field}, but ${fromField} is not a defined relation on ${meta.className}`);
|
|
458
562
|
}
|
|
459
|
-
this.
|
|
460
|
-
cond = core_1.QueryHelper.processWhere(
|
|
563
|
+
this.createAlias(prop.type, alias);
|
|
564
|
+
cond = core_1.QueryHelper.processWhere({
|
|
565
|
+
where: cond,
|
|
566
|
+
entityName: this.mainAlias.entityName,
|
|
567
|
+
metadata: this.metadata,
|
|
568
|
+
platform: this.platform,
|
|
569
|
+
aliasMap: this.getAliasMap(),
|
|
570
|
+
aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
|
|
571
|
+
});
|
|
461
572
|
let aliasedName = `${fromAlias}.${prop.name}#${alias}`;
|
|
462
573
|
path ?? (path = `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`);
|
|
463
574
|
if (prop.reference === core_1.ReferenceType.ONE_TO_MANY) {
|
|
@@ -467,12 +578,12 @@ class QueryBuilder {
|
|
|
467
578
|
let pivotAlias = alias;
|
|
468
579
|
if (type !== 'pivotJoin') {
|
|
469
580
|
const oldPivotAlias = this.getAliasForJoinPath(path + '[pivot]');
|
|
470
|
-
pivotAlias = oldPivotAlias ?? this.getNextAlias(prop.
|
|
581
|
+
pivotAlias = oldPivotAlias ?? this.getNextAlias(prop.pivotEntity);
|
|
471
582
|
aliasedName = `${fromAlias}.${prop.name}#${pivotAlias}`;
|
|
472
583
|
}
|
|
473
584
|
const joins = this.helper.joinManyToManyReference(prop, fromAlias, alias, pivotAlias, type, cond, path);
|
|
474
585
|
Object.assign(this._joins, joins);
|
|
475
|
-
this.
|
|
586
|
+
this.createAlias(prop.pivotEntity, pivotAlias);
|
|
476
587
|
}
|
|
477
588
|
else if (prop.reference === core_1.ReferenceType.ONE_TO_ONE) {
|
|
478
589
|
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
|
|
@@ -493,24 +604,50 @@ class QueryBuilder {
|
|
|
493
604
|
}
|
|
494
605
|
const join = Object.keys(this._joins).find(k => field === k.substring(0, k.indexOf('#')));
|
|
495
606
|
if (join && type === 'where') {
|
|
496
|
-
return ret.push(...this.helper.mapJoinColumns(this.type, this._joins[join]));
|
|
607
|
+
return ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
|
|
497
608
|
}
|
|
498
609
|
const [a, f] = this.helper.splitField(field);
|
|
499
610
|
const prop = this.helper.getProperty(f, a);
|
|
611
|
+
/* istanbul ignore next */
|
|
500
612
|
if (prop && [core_1.ReferenceType.ONE_TO_MANY, core_1.ReferenceType.MANY_TO_MANY].includes(prop.reference)) {
|
|
501
613
|
return;
|
|
502
614
|
}
|
|
615
|
+
if (prop?.embedded) {
|
|
616
|
+
const fieldName = this.helper.mapper(prop.fieldNames[0], this.type);
|
|
617
|
+
ret.push(fieldName);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (prop?.reference === core_1.ReferenceType.EMBEDDED) {
|
|
621
|
+
if (prop.object) {
|
|
622
|
+
ret.push(this.helper.mapper(prop.fieldNames[0], this.type));
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
const nest = (prop) => {
|
|
626
|
+
for (const childProp of Object.values(prop.embeddedProps)) {
|
|
627
|
+
if (childProp.fieldNames) {
|
|
628
|
+
ret.push(this.helper.mapper(childProp.fieldNames[0], this.type));
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
nest(childProp);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
nest(prop);
|
|
636
|
+
}
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
503
639
|
ret.push(this.helper.mapper(field, this.type));
|
|
504
640
|
});
|
|
505
|
-
const meta = this.metadata
|
|
641
|
+
const meta = this.mainAlias.metadata;
|
|
506
642
|
/* istanbul ignore next */
|
|
507
643
|
const requiresSQLConversion = meta?.props.filter(p => p.customType?.convertToJSValueSQL) ?? [];
|
|
508
|
-
if (this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES) && (fields.includes('*') || fields.includes(`${this.
|
|
644
|
+
if (this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES) && (fields.includes('*') || fields.includes(`${this.mainAlias.aliasName}.*`)) && requiresSQLConversion.length > 0) {
|
|
509
645
|
requiresSQLConversion.forEach(p => ret.push(this.helper.mapper(p.name, this.type)));
|
|
510
646
|
}
|
|
511
647
|
Object.keys(this._populateMap).forEach(f => {
|
|
512
648
|
if (!fields.includes(f.replace(/#\w+$/, '')) && type === 'where') {
|
|
513
|
-
|
|
649
|
+
const cols = this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[f]);
|
|
650
|
+
ret.push(...cols);
|
|
514
651
|
}
|
|
515
652
|
if (this._joins[f].prop.reference !== core_1.ReferenceType.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
|
|
516
653
|
this._joins[f].inverseJoinColumns.forEach(inverseJoinColumn => {
|
|
@@ -521,8 +658,8 @@ class QueryBuilder {
|
|
|
521
658
|
return ret;
|
|
522
659
|
}
|
|
523
660
|
init(type, data, cond) {
|
|
661
|
+
this.ensureNotFinalized();
|
|
524
662
|
this.type = type;
|
|
525
|
-
this._aliasMap[this.alias] = this.entityName;
|
|
526
663
|
if ([enums_1.QueryType.UPDATE, enums_1.QueryType.DELETE].includes(type) && core_1.Utils.hasObjectKeys(this._cond)) {
|
|
527
664
|
throw new Error(`You are trying to call \`qb.where().${type.toLowerCase()}()\`. Calling \`qb.${type.toLowerCase()}()\` before \`qb.where()\` is required.`);
|
|
528
665
|
}
|
|
@@ -530,6 +667,9 @@ class QueryBuilder {
|
|
|
530
667
|
delete this._fields;
|
|
531
668
|
}
|
|
532
669
|
if (data) {
|
|
670
|
+
if (core_1.Utils.isEntity(data)) {
|
|
671
|
+
data = (0, core_1.helper)(data).toJSON();
|
|
672
|
+
}
|
|
533
673
|
this._data = this.helper.processData(data, this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES));
|
|
534
674
|
}
|
|
535
675
|
if (cond) {
|
|
@@ -539,22 +679,23 @@ class QueryBuilder {
|
|
|
539
679
|
}
|
|
540
680
|
getQueryBase() {
|
|
541
681
|
const qb = this.getKnex();
|
|
542
|
-
const
|
|
543
|
-
const metaSchema = meta?.schema && meta.schema !== '*' ? meta.schema : undefined;
|
|
544
|
-
const schema = this._schema ?? metaSchema ?? this.em?.config.get('schema');
|
|
682
|
+
const schema = this.getSchema(this.mainAlias);
|
|
545
683
|
if (schema) {
|
|
546
684
|
qb.withSchema(schema);
|
|
547
685
|
}
|
|
548
686
|
if (this._indexHint) {
|
|
549
|
-
const alias = this.helper.isTableNameAliasRequired(this.type) ? ` as ${this.platform.quoteIdentifier(this.
|
|
687
|
+
const alias = this.helper.isTableNameAliasRequired(this.type) ? ` as ${this.platform.quoteIdentifier(this.mainAlias.aliasName)}` : '';
|
|
550
688
|
const schemaQuoted = schema ? this.platform.quoteIdentifier(schema) + '.' : '';
|
|
551
|
-
const tableName = schemaQuoted + this.platform.quoteIdentifier(this.helper.getTableName(this.entityName)) + alias;
|
|
689
|
+
const tableName = schemaQuoted + this.platform.quoteIdentifier(this.helper.getTableName(this.mainAlias.entityName)) + alias;
|
|
552
690
|
qb.from(this.knex.raw(`${tableName} ${this._indexHint}`));
|
|
553
691
|
}
|
|
554
692
|
switch (this.type) {
|
|
555
693
|
case enums_1.QueryType.SELECT:
|
|
556
694
|
qb.select(this.prepareFields(this._fields));
|
|
557
|
-
if (this.
|
|
695
|
+
if (this._distinctOn) {
|
|
696
|
+
qb.distinctOn(this._distinctOn);
|
|
697
|
+
}
|
|
698
|
+
else if (this.flags.has(core_1.QueryFlag.DISTINCT)) {
|
|
558
699
|
qb.distinct();
|
|
559
700
|
}
|
|
560
701
|
this.helper.processJoins(qb, this._joins, schema);
|
|
@@ -588,7 +729,7 @@ class QueryBuilder {
|
|
|
588
729
|
if (!this.type) {
|
|
589
730
|
this.select('*');
|
|
590
731
|
}
|
|
591
|
-
const meta = this.metadata
|
|
732
|
+
const meta = this.mainAlias.metadata;
|
|
592
733
|
if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
|
|
593
734
|
const relationsToPopulate = this._populate.map(({ field }) => field);
|
|
594
735
|
meta.relations
|
|
@@ -600,7 +741,7 @@ class QueryBuilder {
|
|
|
600
741
|
const [fromAlias, fromField] = this.helper.splitField(field);
|
|
601
742
|
const aliasedField = `${fromAlias}.${fromField}`;
|
|
602
743
|
const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
|
|
603
|
-
if (this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
|
|
744
|
+
if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
|
|
604
745
|
return this._populateMap[join] = this._joins[join].alias;
|
|
605
746
|
}
|
|
606
747
|
if (this.metadata.find(field)?.pivotTable) { // pivot table entity
|
|
@@ -608,16 +749,17 @@ class QueryBuilder {
|
|
|
608
749
|
}
|
|
609
750
|
else if (meta && this.helper.isOneToOneInverse(fromField)) {
|
|
610
751
|
const prop = meta.properties[fromField];
|
|
611
|
-
const alias = this.getNextAlias(prop.
|
|
612
|
-
|
|
613
|
-
this.
|
|
752
|
+
const alias = this.getNextAlias(prop.pivotEntity ?? prop.type);
|
|
753
|
+
const aliasedName = `${fromAlias}.${prop.name}#${alias}`;
|
|
754
|
+
this._joins[aliasedName] = this.helper.joinOneToReference(prop, this.mainAlias.aliasName, alias, 'leftJoin');
|
|
755
|
+
this._populateMap[aliasedName] = this._joins[aliasedName].alias;
|
|
614
756
|
}
|
|
615
757
|
});
|
|
616
|
-
if (meta && (this._fields?.includes('*') || this._fields?.includes(`${this.
|
|
758
|
+
if (meta && (this._fields?.includes('*') || this._fields?.includes(`${this.mainAlias.aliasName}.*`))) {
|
|
617
759
|
meta.props
|
|
618
760
|
.filter(prop => prop.formula && (!prop.lazy || this.flags.has(core_1.QueryFlag.INCLUDE_LAZY_FORMULAS)))
|
|
619
761
|
.map(prop => {
|
|
620
|
-
const alias = this.knex.ref(this.
|
|
762
|
+
const alias = this.knex.ref(this.mainAlias.aliasName).toString();
|
|
621
763
|
const aliased = this.knex.ref(prop.fieldNames[0]).toString();
|
|
622
764
|
return `${prop.formula(alias)} as ${aliased}`;
|
|
623
765
|
})
|
|
@@ -627,13 +769,22 @@ class QueryBuilder {
|
|
|
627
769
|
core_1.QueryHelper.processObjectParams(this._data);
|
|
628
770
|
core_1.QueryHelper.processObjectParams(this._cond);
|
|
629
771
|
core_1.QueryHelper.processObjectParams(this._having);
|
|
630
|
-
|
|
631
|
-
if (
|
|
772
|
+
// automatically enable paginate flag when we detect to-many joins
|
|
773
|
+
if (!this.flags.has(core_1.QueryFlag.DISABLE_PAGINATE) && this.hasToManyJoins()) {
|
|
774
|
+
this.flags.add(core_1.QueryFlag.PAGINATE);
|
|
775
|
+
}
|
|
776
|
+
if (meta && this.flags.has(core_1.QueryFlag.PAGINATE) && (this._limit > 0 || this._offset > 0)) {
|
|
632
777
|
this.wrapPaginateSubQuery(meta);
|
|
633
778
|
}
|
|
634
779
|
if (meta && (this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(core_1.QueryFlag.DELETE_SUB_QUERY))) {
|
|
635
780
|
this.wrapModifySubQuery(meta);
|
|
636
781
|
}
|
|
782
|
+
this.finalized = true;
|
|
783
|
+
}
|
|
784
|
+
hasToManyJoins() {
|
|
785
|
+
return Object.values(this._joins).some(join => {
|
|
786
|
+
return [core_1.ReferenceType.ONE_TO_MANY, core_1.ReferenceType.MANY_TO_MANY].includes(join.prop.reference);
|
|
787
|
+
});
|
|
637
788
|
}
|
|
638
789
|
wrapPaginateSubQuery(meta) {
|
|
639
790
|
const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
|
|
@@ -645,28 +796,38 @@ class QueryBuilder {
|
|
|
645
796
|
const orderBy = [];
|
|
646
797
|
for (const orderMap of this._orderBy) {
|
|
647
798
|
for (const [field, direction] of Object.entries(orderMap)) {
|
|
799
|
+
const [a, f] = this.helper.splitField(field);
|
|
800
|
+
const prop = this.helper.getProperty(f, a);
|
|
801
|
+
const type = this.platform.castColumn(prop);
|
|
648
802
|
orderBy.push({
|
|
649
|
-
[`min(${this.ref(field)})`]: direction,
|
|
803
|
+
[`min(${this.ref(this.helper.mapper(field, this.type, undefined, null))}${type})`]: direction,
|
|
650
804
|
});
|
|
651
805
|
}
|
|
652
806
|
}
|
|
653
807
|
subQuery.orderBy(orderBy);
|
|
654
808
|
}
|
|
655
809
|
subQuery.finalized = true;
|
|
656
|
-
const knexQuery = subQuery.as(this.
|
|
810
|
+
const knexQuery = subQuery.as(this.mainAlias.aliasName).clearSelect().select(pks);
|
|
657
811
|
// multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O)
|
|
658
812
|
// https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
|
|
659
813
|
const subSubQuery = this.getKnex().select(pks).from(knexQuery);
|
|
660
814
|
this._limit = undefined;
|
|
661
815
|
this._offset = undefined;
|
|
816
|
+
const cond = this._cond;
|
|
662
817
|
this.select(this._fields).where({ [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery } });
|
|
818
|
+
if (this._populateWhere === core_1.PopulateHint.INFER) {
|
|
819
|
+
this.andWhere(cond);
|
|
820
|
+
}
|
|
821
|
+
else if (typeof this._populateWhere === 'object') {
|
|
822
|
+
this.andWhere(this._populateWhere);
|
|
823
|
+
}
|
|
663
824
|
}
|
|
664
825
|
wrapModifySubQuery(meta) {
|
|
665
826
|
const subQuery = this.clone();
|
|
666
827
|
subQuery.finalized = true;
|
|
667
828
|
// wrap one more time to get around MySQL limitations
|
|
668
829
|
// https://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause
|
|
669
|
-
const subSubQuery = this.getKnex().select(this.prepareFields(meta.primaryKeys)).from(subQuery.as(this.
|
|
830
|
+
const subSubQuery = this.getKnex().select(this.prepareFields(meta.primaryKeys)).from(subQuery.as(this.mainAlias.aliasName));
|
|
670
831
|
const method = this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) ? 'update' : 'delete';
|
|
671
832
|
this._cond = {}; // otherwise we would trigger validation error
|
|
672
833
|
this[method](this._data).where({
|
|
@@ -675,14 +836,54 @@ class QueryBuilder {
|
|
|
675
836
|
}
|
|
676
837
|
autoJoinPivotTable(field) {
|
|
677
838
|
const pivotMeta = this.metadata.find(field);
|
|
678
|
-
const owner = pivotMeta.
|
|
679
|
-
const inverse = pivotMeta.
|
|
839
|
+
const owner = pivotMeta.relations[0];
|
|
840
|
+
const inverse = pivotMeta.relations[1];
|
|
680
841
|
const prop = this._cond[pivotMeta.name + '.' + owner.name] || this._orderBy[pivotMeta.name + '.' + owner.name] ? inverse : owner;
|
|
681
842
|
const pivotAlias = this.getNextAlias(pivotMeta.name);
|
|
682
|
-
this._joins[field] = this.helper.joinPivotTable(field, prop, this.
|
|
843
|
+
this._joins[field] = this.helper.joinPivotTable(field, prop, this.mainAlias.aliasName, pivotAlias, 'leftJoin');
|
|
683
844
|
core_1.Utils.renameKey(this._cond, `${field}.${owner.name}`, core_1.Utils.getPrimaryKeyHash(owner.fieldNames.map(fieldName => `${pivotAlias}.${fieldName}`)));
|
|
684
845
|
core_1.Utils.renameKey(this._cond, `${field}.${inverse.name}`, core_1.Utils.getPrimaryKeyHash(inverse.fieldNames.map(fieldName => `${pivotAlias}.${fieldName}`)));
|
|
685
846
|
this._populateMap[field] = this._joins[field].alias;
|
|
686
847
|
}
|
|
848
|
+
getSchema(alias) {
|
|
849
|
+
const { metadata } = alias;
|
|
850
|
+
const metaSchema = metadata?.schema && metadata.schema !== '*' ? metadata.schema : undefined;
|
|
851
|
+
return this._schema ?? metaSchema ?? this.em?.config.get('schema');
|
|
852
|
+
}
|
|
853
|
+
createAlias(entityName, aliasName, subQuery) {
|
|
854
|
+
const metadata = this.metadata.find(entityName);
|
|
855
|
+
const alias = { aliasName, entityName, metadata, subQuery };
|
|
856
|
+
this._aliases[aliasName] = alias;
|
|
857
|
+
return alias;
|
|
858
|
+
}
|
|
859
|
+
createMainAlias(entityName, aliasName, subQuery) {
|
|
860
|
+
this._mainAlias = this.createAlias(entityName, aliasName, subQuery);
|
|
861
|
+
this._helper = this.createQueryBuilderHelper();
|
|
862
|
+
return this._mainAlias;
|
|
863
|
+
}
|
|
864
|
+
fromSubQuery(target, aliasName) {
|
|
865
|
+
const subQuery = target.getKnexQuery();
|
|
866
|
+
const { entityName } = target.mainAlias;
|
|
867
|
+
aliasName ?? (aliasName = this.getNextAlias(entityName));
|
|
868
|
+
this.createMainAlias(entityName, aliasName, subQuery);
|
|
869
|
+
}
|
|
870
|
+
fromEntityName(entityName, aliasName) {
|
|
871
|
+
aliasName ?? (aliasName = this._mainAlias?.aliasName ?? this.getNextAlias(entityName));
|
|
872
|
+
this.createMainAlias(entityName, aliasName);
|
|
873
|
+
}
|
|
874
|
+
createQueryBuilderHelper() {
|
|
875
|
+
return new QueryBuilderHelper_1.QueryBuilderHelper(this.mainAlias.entityName, this.mainAlias.aliasName, this._aliases, this.subQueries, this.knex, this.driver);
|
|
876
|
+
}
|
|
877
|
+
ensureFromClause() {
|
|
878
|
+
/* istanbul ignore next */
|
|
879
|
+
if (!this._mainAlias) {
|
|
880
|
+
throw new Error(`Cannot proceed to build a query because the main alias is not set.`);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
ensureNotFinalized() {
|
|
884
|
+
if (this.finalized) {
|
|
885
|
+
throw new Error('This QueryBuilder instance is already finalized, clone it first if you want to modify it.');
|
|
886
|
+
}
|
|
887
|
+
}
|
|
687
888
|
}
|
|
688
889
|
exports.QueryBuilder = QueryBuilder;
|