@mikro-orm/knex 6.0.0-dev.10 → 6.0.0-dev.101
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/AbstractSqlConnection.d.ts +8 -4
- package/AbstractSqlConnection.js +30 -18
- package/AbstractSqlDriver.d.ts +22 -22
- package/AbstractSqlDriver.js +233 -88
- package/AbstractSqlPlatform.d.ts +5 -4
- package/AbstractSqlPlatform.js +34 -5
- package/MonkeyPatchable.d.ts +1 -0
- package/MonkeyPatchable.js +3 -0
- package/README.md +64 -107
- package/SqlEntityManager.d.ts +2 -6
- package/SqlEntityManager.js +5 -9
- package/SqlEntityRepository.d.ts +7 -6
- package/SqlEntityRepository.js +11 -8
- package/index.mjs +22 -6
- package/package.json +8 -8
- package/query/ArrayCriteriaNode.d.ts +3 -3
- package/query/CriteriaNode.d.ts +8 -8
- package/query/CriteriaNode.js +16 -9
- package/query/CriteriaNodeFactory.d.ts +6 -6
- package/query/CriteriaNodeFactory.js +10 -13
- package/query/ObjectCriteriaNode.d.ts +3 -3
- package/query/ObjectCriteriaNode.js +12 -8
- package/query/QueryBuilder.d.ts +41 -19
- package/query/QueryBuilder.js +319 -110
- package/query/QueryBuilderHelper.d.ts +9 -13
- package/query/QueryBuilderHelper.js +123 -97
- package/query/ScalarCriteriaNode.d.ts +3 -2
- package/query/ScalarCriteriaNode.js +9 -6
- package/query/enums.js +1 -1
- package/schema/DatabaseSchema.d.ts +5 -2
- package/schema/DatabaseSchema.js +26 -8
- package/schema/DatabaseTable.d.ts +4 -2
- package/schema/DatabaseTable.js +53 -28
- package/schema/SchemaComparator.js +12 -2
- package/schema/SchemaHelper.d.ts +6 -4
- package/schema/SchemaHelper.js +11 -4
- package/schema/SqlSchemaGenerator.d.ts +3 -6
- package/schema/SqlSchemaGenerator.js +61 -28
- package/typings.d.ts +12 -7
package/query/QueryBuilder.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.QueryBuilder = void 0;
|
|
4
|
+
const util_1 = require("util");
|
|
4
5
|
const core_1 = require("@mikro-orm/core");
|
|
5
6
|
const enums_1 = require("./enums");
|
|
6
7
|
const QueryBuilderHelper_1 = require("./QueryBuilderHelper");
|
|
@@ -25,6 +26,12 @@ const CriteriaNodeFactory_1 = require("./CriteriaNodeFactory");
|
|
|
25
26
|
* ```
|
|
26
27
|
*/
|
|
27
28
|
class QueryBuilder {
|
|
29
|
+
metadata;
|
|
30
|
+
driver;
|
|
31
|
+
context;
|
|
32
|
+
connectionType;
|
|
33
|
+
em;
|
|
34
|
+
logging;
|
|
28
35
|
get mainAlias() {
|
|
29
36
|
this.ensureFromClause();
|
|
30
37
|
return this._mainAlias;
|
|
@@ -36,31 +43,56 @@ class QueryBuilder {
|
|
|
36
43
|
this.ensureFromClause();
|
|
37
44
|
return this._helper;
|
|
38
45
|
}
|
|
46
|
+
/** @internal */
|
|
47
|
+
type;
|
|
48
|
+
/** @internal */
|
|
49
|
+
_fields;
|
|
50
|
+
/** @internal */
|
|
51
|
+
_populate = [];
|
|
52
|
+
/** @internal */
|
|
53
|
+
_populateWhere;
|
|
54
|
+
/** @internal */
|
|
55
|
+
_populateMap = {};
|
|
56
|
+
aliasCounter = 0;
|
|
57
|
+
flags = new Set([core_1.QueryFlag.CONVERT_CUSTOM_TYPES]);
|
|
58
|
+
finalized = false;
|
|
59
|
+
_joins = {};
|
|
60
|
+
_explicitAlias = false;
|
|
61
|
+
_schema;
|
|
62
|
+
_cond = {};
|
|
63
|
+
_data;
|
|
64
|
+
_orderBy = [];
|
|
65
|
+
_groupBy = [];
|
|
66
|
+
_having = {};
|
|
67
|
+
_returning;
|
|
68
|
+
_onConflict;
|
|
69
|
+
_limit;
|
|
70
|
+
_offset;
|
|
71
|
+
_distinctOn;
|
|
72
|
+
_joinedProps = new Map();
|
|
73
|
+
_cache;
|
|
74
|
+
_indexHint;
|
|
75
|
+
_comments = [];
|
|
76
|
+
_hintComments = [];
|
|
77
|
+
flushMode;
|
|
78
|
+
lockMode;
|
|
79
|
+
lockTables;
|
|
80
|
+
subQueries = {};
|
|
81
|
+
_mainAlias;
|
|
82
|
+
_aliases = {};
|
|
83
|
+
_helper;
|
|
84
|
+
platform;
|
|
85
|
+
knex;
|
|
39
86
|
/**
|
|
40
87
|
* @internal
|
|
41
88
|
*/
|
|
42
|
-
constructor(entityName, metadata, driver, context, alias, connectionType, em) {
|
|
89
|
+
constructor(entityName, metadata, driver, context, alias, connectionType, em, logging) {
|
|
43
90
|
this.metadata = metadata;
|
|
44
91
|
this.driver = driver;
|
|
45
92
|
this.context = context;
|
|
46
93
|
this.connectionType = connectionType;
|
|
47
94
|
this.em = em;
|
|
48
|
-
|
|
49
|
-
this._populate = [];
|
|
50
|
-
/** @internal */
|
|
51
|
-
this._populateMap = {};
|
|
52
|
-
this.aliasCounter = 0;
|
|
53
|
-
this.flags = new Set([core_1.QueryFlag.CONVERT_CUSTOM_TYPES]);
|
|
54
|
-
this.finalized = false;
|
|
55
|
-
this._joins = {};
|
|
56
|
-
this._explicitAlias = false;
|
|
57
|
-
this._cond = {};
|
|
58
|
-
this._orderBy = [];
|
|
59
|
-
this._groupBy = [];
|
|
60
|
-
this._having = {};
|
|
61
|
-
this._joinedProps = new Map();
|
|
62
|
-
this.subQueries = {};
|
|
63
|
-
this._aliases = {};
|
|
95
|
+
this.logging = logging;
|
|
64
96
|
this.platform = this.driver.getPlatform();
|
|
65
97
|
this.knex = this.driver.getConnection(this.connectionType).getKnex();
|
|
66
98
|
if (alias) {
|
|
@@ -115,26 +147,26 @@ class QueryBuilder {
|
|
|
115
147
|
this._fields = this.mainAlias.metadata.primaryKeys;
|
|
116
148
|
}
|
|
117
149
|
else {
|
|
118
|
-
this._fields = [
|
|
150
|
+
this._fields = [(0, core_1.raw)('*')];
|
|
119
151
|
}
|
|
120
152
|
if (distinct) {
|
|
121
153
|
this.flags.add(core_1.QueryFlag.DISTINCT);
|
|
122
154
|
}
|
|
123
155
|
return this.init(enums_1.QueryType.COUNT);
|
|
124
156
|
}
|
|
125
|
-
join(field, alias, cond = {}, type = 'innerJoin', path) {
|
|
126
|
-
this.joinReference(field, alias, cond, type, path);
|
|
157
|
+
join(field, alias, cond = {}, type = 'innerJoin', path, schema) {
|
|
158
|
+
this.joinReference(field, alias, cond, type, path, schema);
|
|
127
159
|
return this;
|
|
128
160
|
}
|
|
129
|
-
leftJoin(field, alias, cond = {}) {
|
|
130
|
-
return this.join(field, alias, cond, 'leftJoin');
|
|
161
|
+
leftJoin(field, alias, cond = {}, schema) {
|
|
162
|
+
return this.join(field, alias, cond, 'leftJoin', undefined, schema);
|
|
131
163
|
}
|
|
132
|
-
joinAndSelect(field, alias, cond = {}, type = 'innerJoin', path) {
|
|
164
|
+
joinAndSelect(field, alias, cond = {}, type = 'innerJoin', path, fields, schema) {
|
|
133
165
|
if (!this.type) {
|
|
134
166
|
this.select('*');
|
|
135
167
|
}
|
|
136
|
-
const prop = this.joinReference(field, alias, cond, type, path);
|
|
137
|
-
this.addSelect(this.getFieldsForJoinedLoad(prop, alias));
|
|
168
|
+
const prop = this.joinReference(field, alias, cond, type, path, schema);
|
|
169
|
+
this.addSelect(this.getFieldsForJoinedLoad(prop, alias, fields));
|
|
138
170
|
const [fromAlias] = this.helper.splitField(field);
|
|
139
171
|
const populate = this._joinedProps.get(fromAlias);
|
|
140
172
|
const item = { field: prop.name, strategy: core_1.LoadStrategy.JOINED, children: [] };
|
|
@@ -147,13 +179,16 @@ class QueryBuilder {
|
|
|
147
179
|
this._joinedProps.set(alias, item);
|
|
148
180
|
return this;
|
|
149
181
|
}
|
|
150
|
-
leftJoinAndSelect(field, alias, cond = {}) {
|
|
151
|
-
return this.joinAndSelect(field, alias, cond, 'leftJoin');
|
|
182
|
+
leftJoinAndSelect(field, alias, cond = {}, fields, schema) {
|
|
183
|
+
return this.joinAndSelect(field, alias, cond, 'leftJoin', undefined, fields, schema);
|
|
184
|
+
}
|
|
185
|
+
innerJoinAndSelect(field, alias, cond = {}, fields, schema) {
|
|
186
|
+
return this.joinAndSelect(field, alias, cond, 'innerJoin', undefined, fields, schema);
|
|
152
187
|
}
|
|
153
|
-
getFieldsForJoinedLoad(prop, alias) {
|
|
188
|
+
getFieldsForJoinedLoad(prop, alias, explicitFields) {
|
|
154
189
|
const fields = [];
|
|
155
190
|
prop.targetMeta.props
|
|
156
|
-
.filter(prop => this.platform.shouldHaveColumn(prop, this._populate))
|
|
191
|
+
.filter(prop => explicitFields ? explicitFields.includes(prop.name) || prop.primary : this.platform.shouldHaveColumn(prop, this._populate))
|
|
157
192
|
.forEach(prop => fields.push(...this.driver.mapPropToFieldNames(this, prop, alias)));
|
|
158
193
|
return fields;
|
|
159
194
|
}
|
|
@@ -164,9 +199,15 @@ class QueryBuilder {
|
|
|
164
199
|
}
|
|
165
200
|
where(cond, params, operator) {
|
|
166
201
|
this.ensureNotFinalized();
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
202
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(cond);
|
|
203
|
+
if (rawField) {
|
|
204
|
+
const sql = this.platform.formatQuery(rawField.sql, rawField.params);
|
|
205
|
+
cond = { [(0, core_1.raw)(`(${sql})`)]: core_1.Utils.asArray(params) };
|
|
206
|
+
operator ??= '$and';
|
|
207
|
+
}
|
|
208
|
+
else if (core_1.Utils.isString(cond)) {
|
|
209
|
+
cond = { [(0, core_1.raw)(`(${cond})`, core_1.Utils.asArray(params))]: [] };
|
|
210
|
+
operator ??= '$and';
|
|
170
211
|
}
|
|
171
212
|
else {
|
|
172
213
|
cond = core_1.QueryHelper.processWhere({
|
|
@@ -234,15 +275,22 @@ class QueryBuilder {
|
|
|
234
275
|
having(cond = {}, params) {
|
|
235
276
|
this.ensureNotFinalized();
|
|
236
277
|
if (core_1.Utils.isString(cond)) {
|
|
237
|
-
cond = { [`(${cond})
|
|
278
|
+
cond = { [(0, core_1.raw)(`(${cond})`, params)]: [] };
|
|
238
279
|
}
|
|
239
280
|
this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
|
|
240
281
|
return this;
|
|
241
282
|
}
|
|
242
283
|
onConflict(fields = []) {
|
|
284
|
+
const meta = this.mainAlias.metadata;
|
|
243
285
|
this.ensureNotFinalized();
|
|
244
|
-
this._onConflict
|
|
245
|
-
this._onConflict.push({
|
|
286
|
+
this._onConflict ??= [];
|
|
287
|
+
this._onConflict.push({
|
|
288
|
+
fields: core_1.Utils.asArray(fields).flatMap(f => {
|
|
289
|
+
const key = f.toString();
|
|
290
|
+
/* istanbul ignore next */
|
|
291
|
+
return meta.properties[key]?.fieldNames ?? [key];
|
|
292
|
+
}),
|
|
293
|
+
});
|
|
246
294
|
return this;
|
|
247
295
|
}
|
|
248
296
|
ignore() {
|
|
@@ -262,6 +310,10 @@ class QueryBuilder {
|
|
|
262
310
|
this._onConflict[this._onConflict.length - 1].merge = data;
|
|
263
311
|
return this;
|
|
264
312
|
}
|
|
313
|
+
returning(fields) {
|
|
314
|
+
this._returning = fields != null ? core_1.Utils.asArray(fields) : fields;
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
265
317
|
/**
|
|
266
318
|
* @internal
|
|
267
319
|
*/
|
|
@@ -271,17 +323,6 @@ class QueryBuilder {
|
|
|
271
323
|
this._populateWhere = populateWhere;
|
|
272
324
|
return this;
|
|
273
325
|
}
|
|
274
|
-
/**
|
|
275
|
-
* @internal
|
|
276
|
-
*/
|
|
277
|
-
ref(field) {
|
|
278
|
-
return this.knex.ref(field);
|
|
279
|
-
}
|
|
280
|
-
raw(sql, bindings = []) {
|
|
281
|
-
const raw = this.knex.raw(sql, bindings);
|
|
282
|
-
raw.__raw = true; // tag it as there is now way to check via `instanceof`
|
|
283
|
-
return raw;
|
|
284
|
-
}
|
|
285
326
|
limit(limit, offset = 0) {
|
|
286
327
|
this.ensureNotFinalized();
|
|
287
328
|
this._limit = limit;
|
|
@@ -337,6 +378,24 @@ class QueryBuilder {
|
|
|
337
378
|
this._indexHint = sql;
|
|
338
379
|
return this;
|
|
339
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
|
|
383
|
+
*/
|
|
384
|
+
comment(comment) {
|
|
385
|
+
this.ensureNotFinalized();
|
|
386
|
+
this._comments.push(...core_1.Utils.asArray(comment));
|
|
387
|
+
return this;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
|
|
391
|
+
* Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
|
|
392
|
+
* are ignored as simple comments.
|
|
393
|
+
*/
|
|
394
|
+
hintComment(comment) {
|
|
395
|
+
this.ensureNotFinalized();
|
|
396
|
+
this._hintComments.push(...core_1.Utils.asArray(comment));
|
|
397
|
+
return this;
|
|
398
|
+
}
|
|
340
399
|
from(target, aliasName) {
|
|
341
400
|
this.ensureNotFinalized();
|
|
342
401
|
if (target instanceof QueryBuilder) {
|
|
@@ -354,17 +413,21 @@ class QueryBuilder {
|
|
|
354
413
|
getKnexQuery() {
|
|
355
414
|
this.finalize();
|
|
356
415
|
const qb = this.getQueryBase();
|
|
416
|
+
qb.__raw = true; // tag it as there is now way to check via `instanceof`
|
|
357
417
|
core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? enums_1.QueryType.SELECT, this._cond, qb), this._cond && !this._onConflict);
|
|
358
418
|
core_1.Utils.runIfNotEmpty(() => qb.groupBy(this.prepareFields(this._groupBy, 'groupBy')), this._groupBy);
|
|
359
419
|
core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? enums_1.QueryType.SELECT, this._having, qb, undefined, 'having'), this._having);
|
|
360
420
|
core_1.Utils.runIfNotEmpty(() => {
|
|
361
421
|
const queryOrder = this.helper.getQueryOrder(this.type ?? enums_1.QueryType.SELECT, this._orderBy, this._populateMap);
|
|
362
422
|
if (queryOrder) {
|
|
363
|
-
|
|
423
|
+
qb.orderByRaw(queryOrder);
|
|
424
|
+
return;
|
|
364
425
|
}
|
|
365
426
|
}, this._orderBy);
|
|
366
427
|
core_1.Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
|
|
367
428
|
core_1.Utils.runIfNotEmpty(() => qb.offset(this._offset), this._offset);
|
|
429
|
+
core_1.Utils.runIfNotEmpty(() => this._comments.forEach(comment => qb.comment(comment)), this._comments);
|
|
430
|
+
core_1.Utils.runIfNotEmpty(() => this._hintComments.forEach(comment => qb.hintComment(comment)), this._hintComments);
|
|
368
431
|
core_1.Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(this.type ?? enums_1.QueryType.SELECT, this._onConflict, qb), this._onConflict);
|
|
369
432
|
if (this.type === enums_1.QueryType.TRUNCATE && this.platform.usesCascadeStatement()) {
|
|
370
433
|
return this.knex.raw(qb.toSQL().toNative().sql + ' cascade');
|
|
@@ -372,26 +435,35 @@ class QueryBuilder {
|
|
|
372
435
|
if (this.lockMode) {
|
|
373
436
|
this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
|
|
374
437
|
}
|
|
375
|
-
this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata);
|
|
438
|
+
this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata, this._data, this._returning);
|
|
376
439
|
return qb;
|
|
377
440
|
}
|
|
378
441
|
/**
|
|
379
442
|
* Returns the query with parameters as wildcards.
|
|
380
443
|
*/
|
|
381
444
|
getQuery() {
|
|
382
|
-
return this.
|
|
445
|
+
return this.toQuery().sql;
|
|
446
|
+
}
|
|
447
|
+
#query;
|
|
448
|
+
toQuery() {
|
|
449
|
+
if (this.#query) {
|
|
450
|
+
return this.#query;
|
|
451
|
+
}
|
|
452
|
+
const sql = this.getKnexQuery().toSQL();
|
|
453
|
+
const query = sql.toNative();
|
|
454
|
+
return this.#query = { sql: query.sql, params: query.bindings ?? [], _sql: sql };
|
|
383
455
|
}
|
|
384
456
|
/**
|
|
385
457
|
* Returns the list of all parameters for this query.
|
|
386
458
|
*/
|
|
387
459
|
getParams() {
|
|
388
|
-
return this.
|
|
460
|
+
return this.toQuery().params;
|
|
389
461
|
}
|
|
390
462
|
/**
|
|
391
463
|
* Returns raw interpolated query string with all the parameters inlined.
|
|
392
464
|
*/
|
|
393
465
|
getFormattedQuery() {
|
|
394
|
-
const query = this.
|
|
466
|
+
const query = this.toQuery()._sql;
|
|
395
467
|
return this.platform.formatQuery(query.sql, query.bindings);
|
|
396
468
|
}
|
|
397
469
|
/**
|
|
@@ -433,7 +505,7 @@ class QueryBuilder {
|
|
|
433
505
|
return cached.data;
|
|
434
506
|
}
|
|
435
507
|
const type = this.connectionType || (method === 'run' ? 'write' : 'read');
|
|
436
|
-
const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context);
|
|
508
|
+
const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context, this.logging);
|
|
437
509
|
const meta = this.mainAlias.metadata;
|
|
438
510
|
if (!mapResults || !meta) {
|
|
439
511
|
await this.em?.storeCache(this._cache, cached, res);
|
|
@@ -462,9 +534,29 @@ class QueryBuilder {
|
|
|
462
534
|
await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.flushMode });
|
|
463
535
|
let res = await this.execute('all', true);
|
|
464
536
|
if (this._joinedProps.size > 0) {
|
|
465
|
-
res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata);
|
|
537
|
+
res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata, [...this._joinedProps.values()]);
|
|
538
|
+
}
|
|
539
|
+
const entities = [];
|
|
540
|
+
function propagatePopulateHint(entity, hint) {
|
|
541
|
+
(0, core_1.helper)(entity).__serializationContext.populate ??= hint;
|
|
542
|
+
hint.forEach(pop => {
|
|
543
|
+
const value = entity[pop.field];
|
|
544
|
+
if (core_1.Utils.isEntity(value, true)) {
|
|
545
|
+
(0, core_1.helper)(value).populated();
|
|
546
|
+
propagatePopulateHint(value, pop.children ?? []);
|
|
547
|
+
}
|
|
548
|
+
else if (core_1.Utils.isCollection(value)) {
|
|
549
|
+
value.populated();
|
|
550
|
+
value.getItems(false).forEach(item => propagatePopulateHint(item, pop.children ?? []));
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
for (const r of res) {
|
|
555
|
+
const entity = this.em.map(this.mainAlias.entityName, r, { schema: this._schema });
|
|
556
|
+
propagatePopulateHint(entity, this._populate);
|
|
557
|
+
entities.push(entity);
|
|
466
558
|
}
|
|
467
|
-
return
|
|
559
|
+
return entities;
|
|
468
560
|
}
|
|
469
561
|
/**
|
|
470
562
|
* Executes the query, returning the first result or null
|
|
@@ -482,17 +574,30 @@ class QueryBuilder {
|
|
|
482
574
|
res = await this.execute('get', false);
|
|
483
575
|
}
|
|
484
576
|
else {
|
|
485
|
-
const qb = this.clone();
|
|
577
|
+
const qb = this.type === undefined ? this : this.clone();
|
|
486
578
|
qb.count(field, distinct ?? qb.hasToManyJoins()).limit(undefined).offset(undefined).orderBy([]);
|
|
487
579
|
res = await qb.execute('get', false);
|
|
488
580
|
}
|
|
489
581
|
return res ? +res.count : 0;
|
|
490
582
|
}
|
|
583
|
+
/**
|
|
584
|
+
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
585
|
+
*/
|
|
586
|
+
async getResultAndCount() {
|
|
587
|
+
return Promise.all([
|
|
588
|
+
this.getResultList(),
|
|
589
|
+
this.getCount(),
|
|
590
|
+
]);
|
|
591
|
+
}
|
|
491
592
|
/**
|
|
492
593
|
* Provides promise-like interface so we can await the QB instance.
|
|
493
594
|
*/
|
|
494
595
|
then(onfulfilled, onrejected) {
|
|
495
|
-
|
|
596
|
+
let type = this.type ?? enums_1.QueryType.SELECT;
|
|
597
|
+
if (this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(core_1.QueryFlag.DELETE_SUB_QUERY)) {
|
|
598
|
+
type = enums_1.QueryType.UPDATE;
|
|
599
|
+
}
|
|
600
|
+
switch (type) {
|
|
496
601
|
case enums_1.QueryType.INSERT:
|
|
497
602
|
case enums_1.QueryType.UPDATE:
|
|
498
603
|
case enums_1.QueryType.DELETE:
|
|
@@ -515,7 +620,10 @@ class QueryBuilder {
|
|
|
515
620
|
/* istanbul ignore next */
|
|
516
621
|
alias = meta?.properties[f]?.fieldNames[0] ?? alias;
|
|
517
622
|
}
|
|
518
|
-
|
|
623
|
+
const ret = qb.as(alias);
|
|
624
|
+
// tag the instance, so it is possible to detect it easily
|
|
625
|
+
Object.defineProperty(ret, '__as', { enumerable: false, value: alias });
|
|
626
|
+
return ret;
|
|
519
627
|
}
|
|
520
628
|
clone() {
|
|
521
629
|
const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
|
|
@@ -523,7 +631,8 @@ class QueryBuilder {
|
|
|
523
631
|
// clone array/object properties
|
|
524
632
|
const properties = [
|
|
525
633
|
'flags', '_populate', '_populateWhere', '_populateMap', '_joins', '_joinedProps', '_cond', '_data', '_orderBy',
|
|
526
|
-
'_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables',
|
|
634
|
+
'_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables', '_groupBy', '_having', '_returning',
|
|
635
|
+
'_comments', '_hintComments',
|
|
527
636
|
];
|
|
528
637
|
properties.forEach(prop => qb[prop] = core_1.Utils.copy(this[prop]));
|
|
529
638
|
/* istanbul ignore else */
|
|
@@ -551,14 +660,18 @@ class QueryBuilder {
|
|
|
551
660
|
}
|
|
552
661
|
return qb;
|
|
553
662
|
}
|
|
554
|
-
joinReference(field, alias, cond, type, path) {
|
|
663
|
+
joinReference(field, alias, cond, type, path, schema) {
|
|
555
664
|
this.ensureNotFinalized();
|
|
556
665
|
const [fromAlias, fromField] = this.helper.splitField(field);
|
|
557
|
-
const
|
|
666
|
+
const q = (str) => `'${str}'`;
|
|
667
|
+
if (!this._aliases[fromAlias]) {
|
|
668
|
+
throw new Error(`Trying to join ${q(fromField)} with alias ${q(fromAlias)}, but ${q(fromAlias)} is not a known alias. Available aliases are: ${Object.keys(this._aliases).map(q).join(', ')}.`);
|
|
669
|
+
}
|
|
670
|
+
const entityName = this._aliases[fromAlias].entityName;
|
|
558
671
|
const meta = this.metadata.get(entityName);
|
|
559
672
|
const prop = meta.properties[fromField];
|
|
560
673
|
if (!prop) {
|
|
561
|
-
throw new Error(`Trying to join ${field}, but ${fromField} is not a defined relation on ${meta.className}
|
|
674
|
+
throw new Error(`Trying to join ${q(field)}, but ${q(fromField)} is not a defined relation on ${meta.className}.`);
|
|
562
675
|
}
|
|
563
676
|
this.createAlias(prop.type, alias);
|
|
564
677
|
cond = core_1.QueryHelper.processWhere({
|
|
@@ -570,26 +683,26 @@ class QueryBuilder {
|
|
|
570
683
|
aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
|
|
571
684
|
});
|
|
572
685
|
let aliasedName = `${fromAlias}.${prop.name}#${alias}`;
|
|
573
|
-
path
|
|
574
|
-
if (prop.
|
|
575
|
-
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
|
|
686
|
+
path ??= `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`;
|
|
687
|
+
if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY) {
|
|
688
|
+
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond, schema);
|
|
576
689
|
}
|
|
577
|
-
else if (prop.
|
|
690
|
+
else if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY) {
|
|
578
691
|
let pivotAlias = alias;
|
|
579
692
|
if (type !== 'pivotJoin') {
|
|
580
693
|
const oldPivotAlias = this.getAliasForJoinPath(path + '[pivot]');
|
|
581
694
|
pivotAlias = oldPivotAlias ?? this.getNextAlias(prop.pivotEntity);
|
|
582
695
|
aliasedName = `${fromAlias}.${prop.name}#${pivotAlias}`;
|
|
583
696
|
}
|
|
584
|
-
const joins = this.helper.joinManyToManyReference(prop, fromAlias, alias, pivotAlias, type, cond, path);
|
|
697
|
+
const joins = this.helper.joinManyToManyReference(prop, fromAlias, alias, pivotAlias, type, cond, path, schema);
|
|
585
698
|
Object.assign(this._joins, joins);
|
|
586
699
|
this.createAlias(prop.pivotEntity, pivotAlias);
|
|
587
700
|
}
|
|
588
|
-
else if (prop.
|
|
589
|
-
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
|
|
701
|
+
else if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE) {
|
|
702
|
+
this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond, schema);
|
|
590
703
|
}
|
|
591
704
|
else { // MANY_TO_ONE
|
|
592
|
-
this._joins[aliasedName] = this.helper.joinManyToOneReference(prop, fromAlias, alias, type, cond);
|
|
705
|
+
this._joins[aliasedName] = this.helper.joinManyToOneReference(prop, fromAlias, alias, type, cond, schema);
|
|
593
706
|
}
|
|
594
707
|
if (!this._joins[aliasedName].path && path) {
|
|
595
708
|
this._joins[aliasedName].path = path;
|
|
@@ -599,17 +712,25 @@ class QueryBuilder {
|
|
|
599
712
|
prepareFields(fields, type = 'where') {
|
|
600
713
|
const ret = [];
|
|
601
714
|
fields.forEach(field => {
|
|
715
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(field);
|
|
716
|
+
if (rawField) {
|
|
717
|
+
const sql = this.platform.formatQuery(rawField.sql, rawField.params);
|
|
718
|
+
ret.push(this.knex.raw(sql));
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
602
721
|
if (!core_1.Utils.isString(field)) {
|
|
603
|
-
|
|
722
|
+
ret.push(field);
|
|
723
|
+
return;
|
|
604
724
|
}
|
|
605
725
|
const join = Object.keys(this._joins).find(k => field === k.substring(0, k.indexOf('#')));
|
|
606
726
|
if (join && type === 'where') {
|
|
607
|
-
|
|
727
|
+
ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
|
|
728
|
+
return;
|
|
608
729
|
}
|
|
609
730
|
const [a, f] = this.helper.splitField(field);
|
|
610
731
|
const prop = this.helper.getProperty(f, a);
|
|
611
732
|
/* istanbul ignore next */
|
|
612
|
-
if (prop && [core_1.
|
|
733
|
+
if (prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
613
734
|
return;
|
|
614
735
|
}
|
|
615
736
|
if (prop?.embedded) {
|
|
@@ -617,7 +738,7 @@ class QueryBuilder {
|
|
|
617
738
|
ret.push(fieldName);
|
|
618
739
|
return;
|
|
619
740
|
}
|
|
620
|
-
if (prop?.
|
|
741
|
+
if (prop?.kind === core_1.ReferenceKind.EMBEDDED) {
|
|
621
742
|
if (prop.object) {
|
|
622
743
|
ret.push(this.helper.mapper(prop.fieldNames[0], this.type));
|
|
623
744
|
}
|
|
@@ -636,11 +757,15 @@ class QueryBuilder {
|
|
|
636
757
|
}
|
|
637
758
|
return;
|
|
638
759
|
}
|
|
760
|
+
if (prop && prop.fieldNames.length > 1) {
|
|
761
|
+
ret.push(...prop.fieldNames.map(f => this.helper.mapper(f, this.type)));
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
639
764
|
ret.push(this.helper.mapper(field, this.type));
|
|
640
765
|
});
|
|
641
766
|
const meta = this.mainAlias.metadata;
|
|
642
767
|
/* istanbul ignore next */
|
|
643
|
-
const requiresSQLConversion = meta?.props.filter(p => p.
|
|
768
|
+
const requiresSQLConversion = meta?.props.filter(p => p.hasConvertToJSValueSQL) ?? [];
|
|
644
769
|
if (this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES) && (fields.includes('*') || fields.includes(`${this.mainAlias.aliasName}.*`)) && requiresSQLConversion.length > 0) {
|
|
645
770
|
requiresSQLConversion.forEach(p => ret.push(this.helper.mapper(p.name, this.type)));
|
|
646
771
|
}
|
|
@@ -649,7 +774,7 @@ class QueryBuilder {
|
|
|
649
774
|
const cols = this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[f]);
|
|
650
775
|
ret.push(...cols);
|
|
651
776
|
}
|
|
652
|
-
if (this._joins[f].prop.
|
|
777
|
+
if (this._joins[f].prop.kind !== core_1.ReferenceKind.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
|
|
653
778
|
this._joins[f].inverseJoinColumns.forEach(inverseJoinColumn => {
|
|
654
779
|
core_1.Utils.renameKey(this._cond, inverseJoinColumn, `${this._joins[f].alias}.${inverseJoinColumn}`);
|
|
655
780
|
});
|
|
@@ -668,7 +793,7 @@ class QueryBuilder {
|
|
|
668
793
|
}
|
|
669
794
|
if (data) {
|
|
670
795
|
if (core_1.Utils.isEntity(data)) {
|
|
671
|
-
data = (0, core_1.
|
|
796
|
+
data = this.em?.getComparator().prepareEntity(data) ?? (0, core_1.serialize)(data);
|
|
672
797
|
}
|
|
673
798
|
this._data = this.helper.processData(data, this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES));
|
|
674
799
|
}
|
|
@@ -722,6 +847,24 @@ class QueryBuilder {
|
|
|
722
847
|
}
|
|
723
848
|
return qb;
|
|
724
849
|
}
|
|
850
|
+
applyDiscriminatorCondition() {
|
|
851
|
+
const meta = this.mainAlias.metadata;
|
|
852
|
+
if (!meta?.discriminatorValue) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
const types = Object.values(meta.root.discriminatorMap).map(cls => this.metadata.find(cls));
|
|
856
|
+
const children = [];
|
|
857
|
+
const lookUpChildren = (ret, type) => {
|
|
858
|
+
const children = types.filter(meta2 => meta2.extends === type);
|
|
859
|
+
children.forEach(m => lookUpChildren(ret, m.className));
|
|
860
|
+
ret.push(...children.filter(c => c.discriminatorValue));
|
|
861
|
+
return children;
|
|
862
|
+
};
|
|
863
|
+
lookUpChildren(children, meta.className);
|
|
864
|
+
this.andWhere({
|
|
865
|
+
[meta.root.discriminatorColumn]: children.length > 0 ? { $in: [meta.discriminatorValue, ...children.map(c => c.discriminatorValue)] } : meta.discriminatorValue,
|
|
866
|
+
});
|
|
867
|
+
}
|
|
725
868
|
finalize() {
|
|
726
869
|
if (this.finalized) {
|
|
727
870
|
return;
|
|
@@ -730,10 +873,11 @@ class QueryBuilder {
|
|
|
730
873
|
this.select('*');
|
|
731
874
|
}
|
|
732
875
|
const meta = this.mainAlias.metadata;
|
|
876
|
+
this.applyDiscriminatorCondition();
|
|
733
877
|
if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
|
|
734
878
|
const relationsToPopulate = this._populate.map(({ field }) => field);
|
|
735
879
|
meta.relations
|
|
736
|
-
.filter(prop => prop.
|
|
880
|
+
.filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
|
|
737
881
|
.map(prop => ({ field: prop.name }))
|
|
738
882
|
.forEach(item => this._populate.push(item));
|
|
739
883
|
}
|
|
@@ -742,12 +886,10 @@ class QueryBuilder {
|
|
|
742
886
|
const aliasedField = `${fromAlias}.${fromField}`;
|
|
743
887
|
const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
|
|
744
888
|
if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
if (this.metadata.find(field)?.pivotTable) { // pivot table entity
|
|
748
|
-
this.autoJoinPivotTable(field);
|
|
889
|
+
this._populateMap[join] = this._joins[join].alias;
|
|
890
|
+
return;
|
|
749
891
|
}
|
|
750
|
-
|
|
892
|
+
if (meta && this.helper.isOneToOneInverse(fromField)) {
|
|
751
893
|
const prop = meta.properties[fromField];
|
|
752
894
|
const alias = this.getNextAlias(prop.pivotEntity ?? prop.type);
|
|
753
895
|
const aliasedName = `${fromAlias}.${prop.name}#${alias}`;
|
|
@@ -763,14 +905,20 @@ class QueryBuilder {
|
|
|
763
905
|
const aliased = this.knex.ref(prop.fieldNames[0]).toString();
|
|
764
906
|
return `${prop.formula(alias)} as ${aliased}`;
|
|
765
907
|
})
|
|
766
|
-
.filter(field => !this._fields.
|
|
767
|
-
|
|
908
|
+
.filter(field => !this._fields.some(f => {
|
|
909
|
+
if (f instanceof core_1.RawQueryFragment) {
|
|
910
|
+
return f.sql === field && f.params.length === 0;
|
|
911
|
+
}
|
|
912
|
+
return f === field;
|
|
913
|
+
}))
|
|
914
|
+
.forEach(field => this._fields.push((0, core_1.raw)(field)));
|
|
768
915
|
}
|
|
916
|
+
this.processPopulateWhere();
|
|
769
917
|
core_1.QueryHelper.processObjectParams(this._data);
|
|
770
918
|
core_1.QueryHelper.processObjectParams(this._cond);
|
|
771
919
|
core_1.QueryHelper.processObjectParams(this._having);
|
|
772
|
-
// automatically enable paginate flag when we detect to-many joins
|
|
773
|
-
if (!this.flags.has(core_1.QueryFlag.DISABLE_PAGINATE) && this.hasToManyJoins()) {
|
|
920
|
+
// automatically enable paginate flag when we detect to-many joins, but only if there is no `group by` clause
|
|
921
|
+
if (!this.flags.has(core_1.QueryFlag.DISABLE_PAGINATE) && this._groupBy.length === 0 && this.hasToManyJoins()) {
|
|
774
922
|
this.flags.add(core_1.QueryFlag.PAGINATE);
|
|
775
923
|
}
|
|
776
924
|
if (meta && this.flags.has(core_1.QueryFlag.PAGINATE) && (this._limit > 0 || this._offset > 0)) {
|
|
@@ -781,17 +929,54 @@ class QueryBuilder {
|
|
|
781
929
|
}
|
|
782
930
|
this.finalized = true;
|
|
783
931
|
}
|
|
932
|
+
processPopulateWhere() {
|
|
933
|
+
if (this._populateWhere == null || this._populateWhere === core_1.PopulateHint.ALL) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
const joins = Object.values(this._joins);
|
|
937
|
+
joins.forEach(join => {
|
|
938
|
+
join.cond_ = join.cond;
|
|
939
|
+
join.cond = {};
|
|
940
|
+
});
|
|
941
|
+
const replaceOnConditions = (cond) => {
|
|
942
|
+
Object.keys(cond).forEach(k => {
|
|
943
|
+
if (core_1.Utils.isOperator(k)) {
|
|
944
|
+
if (Array.isArray(cond[k])) {
|
|
945
|
+
return cond[k].forEach((c) => replaceOnConditions(c));
|
|
946
|
+
}
|
|
947
|
+
return replaceOnConditions(cond[k]);
|
|
948
|
+
}
|
|
949
|
+
const [a] = this.helper.splitField(k);
|
|
950
|
+
const join = joins.find(j => j.alias === a);
|
|
951
|
+
if (join) {
|
|
952
|
+
join.cond = { ...join.cond, [k]: cond[k] };
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
};
|
|
956
|
+
if (this._populateWhere === core_1.PopulateHint.INFER) {
|
|
957
|
+
replaceOnConditions(this._cond);
|
|
958
|
+
}
|
|
959
|
+
else if (typeof this._populateWhere === 'object') {
|
|
960
|
+
const cond = CriteriaNodeFactory_1.CriteriaNodeFactory
|
|
961
|
+
.createNode(this.metadata, this.mainAlias.entityName, this._populateWhere)
|
|
962
|
+
.process(this);
|
|
963
|
+
replaceOnConditions(cond);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
784
966
|
hasToManyJoins() {
|
|
785
967
|
return Object.values(this._joins).some(join => {
|
|
786
|
-
return [core_1.
|
|
968
|
+
return [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(join.prop.kind);
|
|
787
969
|
});
|
|
788
970
|
}
|
|
789
971
|
wrapPaginateSubQuery(meta) {
|
|
790
972
|
const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
|
|
791
973
|
const subQuery = this.clone().select(pks).groupBy(pks).limit(this._limit);
|
|
974
|
+
// revert the on conditions added via populateWhere, we want to apply those only once
|
|
975
|
+
Object.values(subQuery._joins).forEach(join => join.cond = join.cond_ ?? {});
|
|
792
976
|
if (this._offset) {
|
|
793
977
|
subQuery.offset(this._offset);
|
|
794
978
|
}
|
|
979
|
+
const addToSelect = [];
|
|
795
980
|
if (this._orderBy.length > 0) {
|
|
796
981
|
const orderBy = [];
|
|
797
982
|
for (const orderMap of this._orderBy) {
|
|
@@ -799,28 +984,38 @@ class QueryBuilder {
|
|
|
799
984
|
const [a, f] = this.helper.splitField(field);
|
|
800
985
|
const prop = this.helper.getProperty(f, a);
|
|
801
986
|
const type = this.platform.castColumn(prop);
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
987
|
+
const fieldName = this.helper.mapper(field, this.type, undefined, null);
|
|
988
|
+
if (!prop?.persist && !prop?.formula) {
|
|
989
|
+
addToSelect.push(fieldName);
|
|
990
|
+
}
|
|
991
|
+
orderBy.push({ [(0, core_1.raw)(`min(${this.knex.ref(fieldName)}${type})`)]: direction });
|
|
805
992
|
}
|
|
806
993
|
}
|
|
807
994
|
subQuery.orderBy(orderBy);
|
|
808
995
|
}
|
|
809
996
|
subQuery.finalized = true;
|
|
810
997
|
const knexQuery = subQuery.as(this.mainAlias.aliasName).clearSelect().select(pks);
|
|
998
|
+
if (addToSelect.length > 0) {
|
|
999
|
+
addToSelect.forEach(prop => {
|
|
1000
|
+
const field = this._fields.find(field => {
|
|
1001
|
+
if (typeof field === 'object' && field && '__as' in field) {
|
|
1002
|
+
return field.__as === prop;
|
|
1003
|
+
}
|
|
1004
|
+
// not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
|
|
1005
|
+
return field.toString().includes(prop);
|
|
1006
|
+
});
|
|
1007
|
+
if (field) {
|
|
1008
|
+
knexQuery.select(field);
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
811
1012
|
// multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O)
|
|
812
1013
|
// https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
|
|
813
1014
|
const subSubQuery = this.getKnex().select(pks).from(knexQuery);
|
|
1015
|
+
subSubQuery.__raw = true; // tag it as there is now way to check via `instanceof`
|
|
814
1016
|
this._limit = undefined;
|
|
815
1017
|
this._offset = undefined;
|
|
816
|
-
const cond = this._cond;
|
|
817
1018
|
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
|
-
}
|
|
824
1019
|
}
|
|
825
1020
|
wrapModifySubQuery(meta) {
|
|
826
1021
|
const subQuery = this.clone();
|
|
@@ -834,17 +1029,6 @@ class QueryBuilder {
|
|
|
834
1029
|
[core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery },
|
|
835
1030
|
});
|
|
836
1031
|
}
|
|
837
|
-
autoJoinPivotTable(field) {
|
|
838
|
-
const pivotMeta = this.metadata.find(field);
|
|
839
|
-
const owner = pivotMeta.relations[0];
|
|
840
|
-
const inverse = pivotMeta.relations[1];
|
|
841
|
-
const prop = this._cond[pivotMeta.name + '.' + owner.name] || this._orderBy[pivotMeta.name + '.' + owner.name] ? inverse : owner;
|
|
842
|
-
const pivotAlias = this.getNextAlias(pivotMeta.name);
|
|
843
|
-
this._joins[field] = this.helper.joinPivotTable(field, prop, this.mainAlias.aliasName, pivotAlias, 'leftJoin');
|
|
844
|
-
core_1.Utils.renameKey(this._cond, `${field}.${owner.name}`, core_1.Utils.getPrimaryKeyHash(owner.fieldNames.map(fieldName => `${pivotAlias}.${fieldName}`)));
|
|
845
|
-
core_1.Utils.renameKey(this._cond, `${field}.${inverse.name}`, core_1.Utils.getPrimaryKeyHash(inverse.fieldNames.map(fieldName => `${pivotAlias}.${fieldName}`)));
|
|
846
|
-
this._populateMap[field] = this._joins[field].alias;
|
|
847
|
-
}
|
|
848
1032
|
getSchema(alias) {
|
|
849
1033
|
const { metadata } = alias;
|
|
850
1034
|
const metaSchema = metadata?.schema && metadata.schema !== '*' ? metadata.schema : undefined;
|
|
@@ -864,11 +1048,11 @@ class QueryBuilder {
|
|
|
864
1048
|
fromSubQuery(target, aliasName) {
|
|
865
1049
|
const subQuery = target.getKnexQuery();
|
|
866
1050
|
const { entityName } = target.mainAlias;
|
|
867
|
-
aliasName
|
|
1051
|
+
aliasName ??= this.getNextAlias(entityName);
|
|
868
1052
|
this.createMainAlias(entityName, aliasName, subQuery);
|
|
869
1053
|
}
|
|
870
1054
|
fromEntityName(entityName, aliasName) {
|
|
871
|
-
aliasName
|
|
1055
|
+
aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(entityName);
|
|
872
1056
|
this.createMainAlias(entityName, aliasName);
|
|
873
1057
|
}
|
|
874
1058
|
createQueryBuilderHelper() {
|
|
@@ -885,5 +1069,30 @@ class QueryBuilder {
|
|
|
885
1069
|
throw new Error('This QueryBuilder instance is already finalized, clone it first if you want to modify it.');
|
|
886
1070
|
}
|
|
887
1071
|
}
|
|
1072
|
+
/* istanbul ignore next */
|
|
1073
|
+
[util_1.inspect.custom](depth) {
|
|
1074
|
+
const object = { ...this };
|
|
1075
|
+
const hidden = ['metadata', 'driver', 'context', 'platform', 'knex', 'type'];
|
|
1076
|
+
Object.keys(object).filter(k => k.startsWith('_')).forEach(k => delete object[k]);
|
|
1077
|
+
Object.keys(object).filter(k => object[k] == null).forEach(k => delete object[k]);
|
|
1078
|
+
hidden.forEach(k => delete object[k]);
|
|
1079
|
+
let prefix = this.type ? this.type.substring(0, 1) + this.type.toLowerCase().substring(1) : '';
|
|
1080
|
+
if (this._data) {
|
|
1081
|
+
object.data = this._data;
|
|
1082
|
+
}
|
|
1083
|
+
if (this._schema) {
|
|
1084
|
+
object.schema = this._schema;
|
|
1085
|
+
}
|
|
1086
|
+
if (!core_1.Utils.isEmpty(this._cond)) {
|
|
1087
|
+
object.where = this._cond;
|
|
1088
|
+
}
|
|
1089
|
+
if (this._onConflict?.[0]) {
|
|
1090
|
+
prefix = 'Upsert';
|
|
1091
|
+
object.onConflict = this._onConflict[0];
|
|
1092
|
+
}
|
|
1093
|
+
const name = this._mainAlias ? `${prefix}QueryBuilder<${this._mainAlias?.entityName}>` : 'QueryBuilder';
|
|
1094
|
+
const ret = (0, util_1.inspect)(object, { depth });
|
|
1095
|
+
return ret === '[Object]' ? `[${name}]` : name + ' ' + ret;
|
|
1096
|
+
}
|
|
888
1097
|
}
|
|
889
1098
|
exports.QueryBuilder = QueryBuilder;
|