@mikro-orm/knex 6.0.0-dev.12 → 6.0.0-dev.120

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.
Files changed (41) hide show
  1. package/AbstractSqlConnection.d.ts +8 -4
  2. package/AbstractSqlConnection.js +30 -18
  3. package/AbstractSqlDriver.d.ts +21 -23
  4. package/AbstractSqlDriver.js +378 -221
  5. package/AbstractSqlPlatform.d.ts +5 -4
  6. package/AbstractSqlPlatform.js +34 -5
  7. package/MonkeyPatchable.d.ts +1 -0
  8. package/MonkeyPatchable.js +3 -0
  9. package/PivotCollectionPersister.d.ts +17 -0
  10. package/PivotCollectionPersister.js +128 -0
  11. package/README.md +64 -107
  12. package/SqlEntityManager.d.ts +2 -6
  13. package/SqlEntityManager.js +5 -9
  14. package/SqlEntityRepository.d.ts +7 -6
  15. package/SqlEntityRepository.js +11 -8
  16. package/index.mjs +23 -6
  17. package/package.json +8 -8
  18. package/query/ArrayCriteriaNode.d.ts +3 -3
  19. package/query/CriteriaNode.d.ts +8 -8
  20. package/query/CriteriaNode.js +16 -9
  21. package/query/CriteriaNodeFactory.d.ts +6 -6
  22. package/query/CriteriaNodeFactory.js +17 -13
  23. package/query/ObjectCriteriaNode.d.ts +3 -3
  24. package/query/ObjectCriteriaNode.js +12 -8
  25. package/query/QueryBuilder.d.ts +44 -20
  26. package/query/QueryBuilder.js +371 -130
  27. package/query/QueryBuilderHelper.d.ts +10 -15
  28. package/query/QueryBuilderHelper.js +197 -158
  29. package/query/ScalarCriteriaNode.d.ts +3 -2
  30. package/query/ScalarCriteriaNode.js +9 -6
  31. package/query/enums.js +1 -1
  32. package/schema/DatabaseSchema.d.ts +5 -2
  33. package/schema/DatabaseSchema.js +27 -9
  34. package/schema/DatabaseTable.d.ts +4 -2
  35. package/schema/DatabaseTable.js +66 -32
  36. package/schema/SchemaComparator.js +15 -3
  37. package/schema/SchemaHelper.d.ts +6 -4
  38. package/schema/SchemaHelper.js +11 -4
  39. package/schema/SqlSchemaGenerator.d.ts +3 -6
  40. package/schema/SqlSchemaGenerator.js +61 -28
  41. package/typings.d.ts +13 -7
@@ -26,6 +26,12 @@ const CriteriaNodeFactory_1 = require("./CriteriaNodeFactory");
26
26
  * ```
27
27
  */
28
28
  class QueryBuilder {
29
+ metadata;
30
+ driver;
31
+ context;
32
+ connectionType;
33
+ em;
34
+ logging;
29
35
  get mainAlias() {
30
36
  this.ensureFromClause();
31
37
  return this._mainAlias;
@@ -37,31 +43,56 @@ class QueryBuilder {
37
43
  this.ensureFromClause();
38
44
  return this._helper;
39
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;
40
86
  /**
41
87
  * @internal
42
88
  */
43
- constructor(entityName, metadata, driver, context, alias, connectionType, em) {
89
+ constructor(entityName, metadata, driver, context, alias, connectionType, em, logging) {
44
90
  this.metadata = metadata;
45
91
  this.driver = driver;
46
92
  this.context = context;
47
93
  this.connectionType = connectionType;
48
94
  this.em = em;
49
- /** @internal */
50
- this._populate = [];
51
- /** @internal */
52
- this._populateMap = {};
53
- this.aliasCounter = 0;
54
- this.flags = new Set([core_1.QueryFlag.CONVERT_CUSTOM_TYPES]);
55
- this.finalized = false;
56
- this._joins = {};
57
- this._explicitAlias = false;
58
- this._cond = {};
59
- this._orderBy = [];
60
- this._groupBy = [];
61
- this._having = {};
62
- this._joinedProps = new Map();
63
- this.subQueries = {};
64
- this._aliases = {};
95
+ this.logging = logging;
65
96
  this.platform = this.driver.getPlatform();
66
97
  this.knex = this.driver.getConnection(this.connectionType).getKnex();
67
98
  if (alias) {
@@ -116,27 +147,39 @@ class QueryBuilder {
116
147
  this._fields = this.mainAlias.metadata.primaryKeys;
117
148
  }
118
149
  else {
119
- this._fields = [this.raw('*')];
150
+ this._fields = [(0, core_1.raw)('*')];
120
151
  }
121
152
  if (distinct) {
122
153
  this.flags.add(core_1.QueryFlag.DISTINCT);
123
154
  }
124
155
  return this.init(enums_1.QueryType.COUNT);
125
156
  }
126
- join(field, alias, cond = {}, type = 'innerJoin', path) {
127
- 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);
159
+ return this;
160
+ }
161
+ innerJoin(field, alias, cond = {}, schema) {
162
+ this.join(field, alias, cond, 'innerJoin', undefined, schema);
128
163
  return this;
129
164
  }
130
- leftJoin(field, alias, cond = {}) {
131
- return this.join(field, alias, cond, 'leftJoin');
165
+ leftJoin(field, alias, cond = {}, schema) {
166
+ return this.join(field, alias, cond, 'leftJoin', undefined, schema);
132
167
  }
133
- joinAndSelect(field, alias, cond = {}, type = 'innerJoin', path) {
168
+ joinAndSelect(field, alias, cond = {}, type = 'innerJoin', path, fields, schema) {
134
169
  if (!this.type) {
135
170
  this.select('*');
136
171
  }
137
- const prop = this.joinReference(field, alias, cond, type, path);
138
- this.addSelect(this.getFieldsForJoinedLoad(prop, alias));
172
+ let subquery;
173
+ if (Array.isArray(field)) {
174
+ subquery = field[1] instanceof QueryBuilder ? field[1].getFormattedQuery() : field[1].toString();
175
+ field = field[0];
176
+ }
177
+ const prop = this.joinReference(field, alias, cond, type, path, schema);
139
178
  const [fromAlias] = this.helper.splitField(field);
179
+ if (subquery) {
180
+ this._joins[`${fromAlias}.${prop.name}#${alias}`].subquery = subquery;
181
+ }
182
+ this.addSelect(this.getFieldsForJoinedLoad(prop, alias, fields));
140
183
  const populate = this._joinedProps.get(fromAlias);
141
184
  const item = { field: prop.name, strategy: core_1.LoadStrategy.JOINED, children: [] };
142
185
  if (populate) {
@@ -148,13 +191,16 @@ class QueryBuilder {
148
191
  this._joinedProps.set(alias, item);
149
192
  return this;
150
193
  }
151
- leftJoinAndSelect(field, alias, cond = {}) {
152
- return this.joinAndSelect(field, alias, cond, 'leftJoin');
194
+ leftJoinAndSelect(field, alias, cond = {}, fields, schema) {
195
+ return this.joinAndSelect(field, alias, cond, 'leftJoin', undefined, fields, schema);
196
+ }
197
+ innerJoinAndSelect(field, alias, cond = {}, fields, schema) {
198
+ return this.joinAndSelect(field, alias, cond, 'innerJoin', undefined, fields, schema);
153
199
  }
154
- getFieldsForJoinedLoad(prop, alias) {
200
+ getFieldsForJoinedLoad(prop, alias, explicitFields) {
155
201
  const fields = [];
156
202
  prop.targetMeta.props
157
- .filter(prop => this.platform.shouldHaveColumn(prop, this._populate))
203
+ .filter(prop => explicitFields ? explicitFields.includes(prop.name) || prop.primary : this.platform.shouldHaveColumn(prop, this._populate))
158
204
  .forEach(prop => fields.push(...this.driver.mapPropToFieldNames(this, prop, alias)));
159
205
  return fields;
160
206
  }
@@ -165,9 +211,15 @@ class QueryBuilder {
165
211
  }
166
212
  where(cond, params, operator) {
167
213
  this.ensureNotFinalized();
168
- if (core_1.Utils.isString(cond)) {
169
- cond = { [`(${cond})`]: core_1.Utils.asArray(params) };
170
- operator = operator || '$and';
214
+ const rawField = core_1.RawQueryFragment.getKnownFragment(cond);
215
+ if (rawField) {
216
+ const sql = this.platform.formatQuery(rawField.sql, rawField.params);
217
+ cond = { [(0, core_1.raw)(`(${sql})`)]: core_1.Utils.asArray(params) };
218
+ operator ??= '$and';
219
+ }
220
+ else if (core_1.Utils.isString(cond)) {
221
+ cond = { [(0, core_1.raw)(`(${cond})`, core_1.Utils.asArray(params))]: [] };
222
+ operator ??= '$and';
171
223
  }
172
224
  else {
173
225
  cond = core_1.QueryHelper.processWhere({
@@ -222,6 +274,7 @@ class QueryBuilder {
222
274
  aliasMap: this.getAliasMap(),
223
275
  aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
224
276
  convertCustomTypes: false,
277
+ type: 'orderBy',
225
278
  });
226
279
  this._orderBy.push(CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, processed).process(this));
227
280
  });
@@ -235,15 +288,22 @@ class QueryBuilder {
235
288
  having(cond = {}, params) {
236
289
  this.ensureNotFinalized();
237
290
  if (core_1.Utils.isString(cond)) {
238
- cond = { [`(${cond})`]: core_1.Utils.asArray(params) };
291
+ cond = { [(0, core_1.raw)(`(${cond})`, params)]: [] };
239
292
  }
240
293
  this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
241
294
  return this;
242
295
  }
243
296
  onConflict(fields = []) {
297
+ const meta = this.mainAlias.metadata;
244
298
  this.ensureNotFinalized();
245
- this._onConflict = this._onConflict || [];
246
- this._onConflict.push({ fields: core_1.Utils.asArray(fields).map(f => f.toString()) });
299
+ this._onConflict ??= [];
300
+ this._onConflict.push({
301
+ fields: core_1.Utils.asArray(fields).flatMap(f => {
302
+ const key = f.toString();
303
+ /* istanbul ignore next */
304
+ return meta.properties[key]?.fieldNames ?? [key];
305
+ }),
306
+ });
247
307
  return this;
248
308
  }
249
309
  ignore() {
@@ -263,6 +323,10 @@ class QueryBuilder {
263
323
  this._onConflict[this._onConflict.length - 1].merge = data;
264
324
  return this;
265
325
  }
326
+ returning(fields) {
327
+ this._returning = fields != null ? core_1.Utils.asArray(fields) : fields;
328
+ return this;
329
+ }
266
330
  /**
267
331
  * @internal
268
332
  */
@@ -272,17 +336,6 @@ class QueryBuilder {
272
336
  this._populateWhere = populateWhere;
273
337
  return this;
274
338
  }
275
- /**
276
- * @internal
277
- */
278
- ref(field) {
279
- return this.knex.ref(field);
280
- }
281
- raw(sql, bindings = []) {
282
- const raw = this.knex.raw(sql, bindings);
283
- raw.__raw = true; // tag it as there is now way to check via `instanceof`
284
- return raw;
285
- }
286
339
  limit(limit, offset = 0) {
287
340
  this.ensureNotFinalized();
288
341
  this._limit = limit;
@@ -338,6 +391,24 @@ class QueryBuilder {
338
391
  this._indexHint = sql;
339
392
  return this;
340
393
  }
394
+ /**
395
+ * Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
396
+ */
397
+ comment(comment) {
398
+ this.ensureNotFinalized();
399
+ this._comments.push(...core_1.Utils.asArray(comment));
400
+ return this;
401
+ }
402
+ /**
403
+ * Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
404
+ * Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
405
+ * are ignored as simple comments.
406
+ */
407
+ hintComment(comment) {
408
+ this.ensureNotFinalized();
409
+ this._hintComments.push(...core_1.Utils.asArray(comment));
410
+ return this;
411
+ }
341
412
  from(target, aliasName) {
342
413
  this.ensureNotFinalized();
343
414
  if (target instanceof QueryBuilder) {
@@ -355,17 +426,21 @@ class QueryBuilder {
355
426
  getKnexQuery() {
356
427
  this.finalize();
357
428
  const qb = this.getQueryBase();
429
+ qb.__raw = true; // tag it as there is now way to check via `instanceof`
358
430
  core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? enums_1.QueryType.SELECT, this._cond, qb), this._cond && !this._onConflict);
359
431
  core_1.Utils.runIfNotEmpty(() => qb.groupBy(this.prepareFields(this._groupBy, 'groupBy')), this._groupBy);
360
432
  core_1.Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? enums_1.QueryType.SELECT, this._having, qb, undefined, 'having'), this._having);
361
433
  core_1.Utils.runIfNotEmpty(() => {
362
434
  const queryOrder = this.helper.getQueryOrder(this.type ?? enums_1.QueryType.SELECT, this._orderBy, this._populateMap);
363
435
  if (queryOrder) {
364
- return qb.orderByRaw(queryOrder);
436
+ qb.orderByRaw(queryOrder);
437
+ return;
365
438
  }
366
439
  }, this._orderBy);
367
440
  core_1.Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
368
441
  core_1.Utils.runIfNotEmpty(() => qb.offset(this._offset), this._offset);
442
+ core_1.Utils.runIfNotEmpty(() => this._comments.forEach(comment => qb.comment(comment)), this._comments);
443
+ core_1.Utils.runIfNotEmpty(() => this._hintComments.forEach(comment => qb.hintComment(comment)), this._hintComments);
369
444
  core_1.Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(this.type ?? enums_1.QueryType.SELECT, this._onConflict, qb), this._onConflict);
370
445
  if (this.type === enums_1.QueryType.TRUNCATE && this.platform.usesCascadeStatement()) {
371
446
  return this.knex.raw(qb.toSQL().toNative().sql + ' cascade');
@@ -373,26 +448,35 @@ class QueryBuilder {
373
448
  if (this.lockMode) {
374
449
  this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
375
450
  }
376
- this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata);
451
+ this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata, this._data, this._returning);
377
452
  return qb;
378
453
  }
379
454
  /**
380
455
  * Returns the query with parameters as wildcards.
381
456
  */
382
457
  getQuery() {
383
- return this.getKnexQuery().toSQL().toNative().sql;
458
+ return this.toQuery().sql;
459
+ }
460
+ #query;
461
+ toQuery() {
462
+ if (this.#query) {
463
+ return this.#query;
464
+ }
465
+ const sql = this.getKnexQuery().toSQL();
466
+ const query = sql.toNative();
467
+ return this.#query = { sql: query.sql, params: query.bindings ?? [], _sql: sql };
384
468
  }
385
469
  /**
386
470
  * Returns the list of all parameters for this query.
387
471
  */
388
472
  getParams() {
389
- return this.getKnexQuery().toSQL().toNative().bindings;
473
+ return this.toQuery().params;
390
474
  }
391
475
  /**
392
476
  * Returns raw interpolated query string with all the parameters inlined.
393
477
  */
394
478
  getFormattedQuery() {
395
- const query = this.getKnexQuery().toSQL();
479
+ const query = this.toQuery()._sql;
396
480
  return this.platform.formatQuery(query.sql, query.bindings);
397
481
  }
398
482
  /**
@@ -424,7 +508,10 @@ class QueryBuilder {
424
508
  * Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
425
509
  * Use `method` to specify what kind of result you want to get (array/single/meta).
426
510
  */
427
- async execute(method = 'all', mapResults = true) {
511
+ async execute(method = 'all', options) {
512
+ options = typeof options === 'boolean' ? { mapResults: options } : (options ?? {});
513
+ options.mergeResults ??= true;
514
+ options.mapResults ??= true;
428
515
  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)) {
429
516
  this.connectionType = 'write';
430
517
  }
@@ -433,21 +520,33 @@ class QueryBuilder {
433
520
  if (cached?.data) {
434
521
  return cached.data;
435
522
  }
436
- const type = this.connectionType || (method === 'run' ? 'write' : 'read');
437
- const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context);
523
+ const write = method === 'run' || !this.platform.getConfig().get('preferReadReplicas');
524
+ const type = this.connectionType || (write ? 'write' : 'read');
525
+ const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context, this.logging);
438
526
  const meta = this.mainAlias.metadata;
439
- if (!mapResults || !meta) {
527
+ if (!options.mapResults || !meta) {
440
528
  await this.em?.storeCache(this._cache, cached, res);
441
529
  return res;
442
530
  }
443
- if (method === 'all' && Array.isArray(res)) {
531
+ if (method === 'run') {
532
+ return res;
533
+ }
534
+ const joinedProps = this.driver.joinedProps(meta, this._populate);
535
+ let mapped;
536
+ if (Array.isArray(res)) {
444
537
  const map = {};
445
- const mapped = res.map(r => this.driver.mapResult(r, meta, this._populate, this, map));
446
- await this.em?.storeCache(this._cache, cached, mapped);
447
- return mapped;
538
+ mapped = res.map(r => this.driver.mapResult(r, meta, this._populate, this, map));
539
+ if (options.mergeResults && joinedProps.length > 0) {
540
+ mapped = this.driver.mergeJoinedResult(mapped, this.mainAlias.metadata, joinedProps);
541
+ }
542
+ }
543
+ else {
544
+ mapped = [this.driver.mapResult(res, meta, joinedProps, this)];
448
545
  }
449
- const mapped = this.driver.mapResult(res, meta, this._populate, this);
450
546
  await this.em?.storeCache(this._cache, cached, mapped);
547
+ if (method === 'get') {
548
+ return mapped[0];
549
+ }
451
550
  return mapped;
452
551
  }
453
552
  /**
@@ -461,11 +560,28 @@ class QueryBuilder {
461
560
  */
462
561
  async getResultList() {
463
562
  await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.flushMode });
464
- let res = await this.execute('all', true);
465
- if (this._joinedProps.size > 0) {
466
- res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata);
563
+ const res = await this.execute('all', true);
564
+ const entities = [];
565
+ function propagatePopulateHint(entity, hint) {
566
+ (0, core_1.helper)(entity).__serializationContext.populate ??= hint;
567
+ hint.forEach(pop => {
568
+ const value = entity[pop.field];
569
+ if (core_1.Utils.isEntity(value, true)) {
570
+ (0, core_1.helper)(value).populated();
571
+ propagatePopulateHint(value, pop.children ?? []);
572
+ }
573
+ else if (core_1.Utils.isCollection(value)) {
574
+ value.populated();
575
+ value.getItems(false).forEach(item => propagatePopulateHint(item, pop.children ?? []));
576
+ }
577
+ });
578
+ }
579
+ for (const r of res) {
580
+ const entity = this.em.map(this.mainAlias.entityName, r, { schema: this._schema });
581
+ propagatePopulateHint(entity, this._populate);
582
+ entities.push(entity);
467
583
  }
468
- return res.map(r => this.em.map(this.mainAlias.entityName, r, { schema: this._schema }));
584
+ return entities;
469
585
  }
470
586
  /**
471
587
  * Executes the query, returning the first result or null
@@ -483,17 +599,30 @@ class QueryBuilder {
483
599
  res = await this.execute('get', false);
484
600
  }
485
601
  else {
486
- const qb = this.clone();
602
+ const qb = this.type === undefined ? this : this.clone();
487
603
  qb.count(field, distinct ?? qb.hasToManyJoins()).limit(undefined).offset(undefined).orderBy([]);
488
604
  res = await qb.execute('get', false);
489
605
  }
490
606
  return res ? +res.count : 0;
491
607
  }
608
+ /**
609
+ * Executes the query, returning both array of results and total count query (without offset and limit).
610
+ */
611
+ async getResultAndCount() {
612
+ return Promise.all([
613
+ this.getResultList(),
614
+ this.getCount(),
615
+ ]);
616
+ }
492
617
  /**
493
618
  * Provides promise-like interface so we can await the QB instance.
494
619
  */
495
620
  then(onfulfilled, onrejected) {
496
- switch (this.type ?? enums_1.QueryType.SELECT) {
621
+ let type = this.type ?? enums_1.QueryType.SELECT;
622
+ if (this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(core_1.QueryFlag.DELETE_SUB_QUERY)) {
623
+ type = enums_1.QueryType.UPDATE;
624
+ }
625
+ switch (type) {
497
626
  case enums_1.QueryType.INSERT:
498
627
  case enums_1.QueryType.UPDATE:
499
628
  case enums_1.QueryType.DELETE:
@@ -516,7 +645,10 @@ class QueryBuilder {
516
645
  /* istanbul ignore next */
517
646
  alias = meta?.properties[f]?.fieldNames[0] ?? alias;
518
647
  }
519
- return qb.as(alias);
648
+ const ret = qb.as(alias);
649
+ // tag the instance, so it is possible to detect it easily
650
+ Object.defineProperty(ret, '__as', { enumerable: false, value: alias });
651
+ return ret;
520
652
  }
521
653
  clone() {
522
654
  const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
@@ -524,7 +656,8 @@ class QueryBuilder {
524
656
  // clone array/object properties
525
657
  const properties = [
526
658
  'flags', '_populate', '_populateWhere', '_populateMap', '_joins', '_joinedProps', '_cond', '_data', '_orderBy',
527
- '_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables',
659
+ '_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables', '_groupBy', '_having', '_returning',
660
+ '_comments', '_hintComments',
528
661
  ];
529
662
  properties.forEach(prop => qb[prop] = core_1.Utils.copy(this[prop]));
530
663
  /* istanbul ignore else */
@@ -552,14 +685,39 @@ class QueryBuilder {
552
685
  }
553
686
  return qb;
554
687
  }
555
- joinReference(field, alias, cond, type, path) {
688
+ joinReference(field, alias, cond, type, path, schema) {
556
689
  this.ensureNotFinalized();
690
+ if (typeof field === 'object') {
691
+ const prop = {
692
+ name: '__subquery__',
693
+ kind: core_1.ReferenceKind.MANY_TO_ONE,
694
+ };
695
+ if (field instanceof QueryBuilder) {
696
+ prop.type = field.mainAlias.entityName;
697
+ prop.targetMeta = field.mainAlias.metadata;
698
+ field = field.getKnexQuery();
699
+ }
700
+ this._joins[`${this.alias}.${prop.name}#${alias}`] = {
701
+ prop,
702
+ alias,
703
+ type,
704
+ cond,
705
+ schema,
706
+ subquery: field.toString(),
707
+ ownerAlias: this.alias,
708
+ };
709
+ return prop;
710
+ }
557
711
  const [fromAlias, fromField] = this.helper.splitField(field);
558
- const entityName = this._aliases[fromAlias]?.entityName;
712
+ const q = (str) => `'${str}'`;
713
+ if (!this._aliases[fromAlias]) {
714
+ 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(', ')}.`);
715
+ }
716
+ const entityName = this._aliases[fromAlias].entityName;
559
717
  const meta = this.metadata.get(entityName);
560
718
  const prop = meta.properties[fromField];
561
719
  if (!prop) {
562
- throw new Error(`Trying to join ${field}, but ${fromField} is not a defined relation on ${meta.className}`);
720
+ throw new Error(`Trying to join ${q(field)}, but ${q(fromField)} is not a defined relation on ${meta.className}.`);
563
721
  }
564
722
  this.createAlias(prop.type, alias);
565
723
  cond = core_1.QueryHelper.processWhere({
@@ -571,26 +729,26 @@ class QueryBuilder {
571
729
  aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
572
730
  });
573
731
  let aliasedName = `${fromAlias}.${prop.name}#${alias}`;
574
- path ?? (path = `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`);
575
- if (prop.reference === core_1.ReferenceType.ONE_TO_MANY) {
576
- this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
732
+ path ??= `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`;
733
+ if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY) {
734
+ this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond, schema);
577
735
  }
578
- else if (prop.reference === core_1.ReferenceType.MANY_TO_MANY) {
736
+ else if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY) {
579
737
  let pivotAlias = alias;
580
738
  if (type !== 'pivotJoin') {
581
739
  const oldPivotAlias = this.getAliasForJoinPath(path + '[pivot]');
582
740
  pivotAlias = oldPivotAlias ?? this.getNextAlias(prop.pivotEntity);
583
741
  aliasedName = `${fromAlias}.${prop.name}#${pivotAlias}`;
584
742
  }
585
- const joins = this.helper.joinManyToManyReference(prop, fromAlias, alias, pivotAlias, type, cond, path);
743
+ const joins = this.helper.joinManyToManyReference(prop, fromAlias, alias, pivotAlias, type, cond, path, schema);
586
744
  Object.assign(this._joins, joins);
587
745
  this.createAlias(prop.pivotEntity, pivotAlias);
588
746
  }
589
- else if (prop.reference === core_1.ReferenceType.ONE_TO_ONE) {
590
- this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
747
+ else if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE) {
748
+ this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond, schema);
591
749
  }
592
750
  else { // MANY_TO_ONE
593
- this._joins[aliasedName] = this.helper.joinManyToOneReference(prop, fromAlias, alias, type, cond);
751
+ this._joins[aliasedName] = this.helper.joinManyToOneReference(prop, fromAlias, alias, type, cond, schema);
594
752
  }
595
753
  if (!this._joins[aliasedName].path && path) {
596
754
  this._joins[aliasedName].path = path;
@@ -599,34 +757,49 @@ class QueryBuilder {
599
757
  }
600
758
  prepareFields(fields, type = 'where') {
601
759
  const ret = [];
760
+ const getFieldName = (name) => {
761
+ if (type === 'groupBy') {
762
+ return this.helper.mapper(name, this.type, undefined, null);
763
+ }
764
+ return this.helper.mapper(name, this.type);
765
+ };
602
766
  fields.forEach(field => {
767
+ const rawField = core_1.RawQueryFragment.getKnownFragment(field);
768
+ if (rawField) {
769
+ const sql = this.platform.formatQuery(rawField.sql, rawField.params);
770
+ ret.push(this.knex.raw(sql));
771
+ return;
772
+ }
603
773
  if (!core_1.Utils.isString(field)) {
604
- return ret.push(field);
774
+ ret.push(field);
775
+ return;
605
776
  }
606
777
  const join = Object.keys(this._joins).find(k => field === k.substring(0, k.indexOf('#')));
607
778
  if (join && type === 'where') {
608
- return ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
779
+ ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
780
+ return;
609
781
  }
610
782
  const [a, f] = this.helper.splitField(field);
611
783
  const prop = this.helper.getProperty(f, a);
612
784
  /* istanbul ignore next */
613
- if (prop && [core_1.ReferenceType.ONE_TO_MANY, core_1.ReferenceType.MANY_TO_MANY].includes(prop.reference)) {
785
+ if (prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
614
786
  return;
615
787
  }
616
788
  if (prop?.embedded) {
617
- const fieldName = this.helper.mapper(prop.fieldNames[0], this.type);
618
- ret.push(fieldName);
789
+ const name = prop.embeddedPath?.join('.') ?? prop.fieldNames[0];
790
+ const aliased = this._aliases[a] ? `${a}.${name}` : name;
791
+ ret.push(getFieldName(aliased));
619
792
  return;
620
793
  }
621
- if (prop?.reference === core_1.ReferenceType.EMBEDDED) {
794
+ if (prop?.kind === core_1.ReferenceKind.EMBEDDED) {
622
795
  if (prop.object) {
623
- ret.push(this.helper.mapper(prop.fieldNames[0], this.type));
796
+ ret.push(getFieldName(prop.fieldNames[0]));
624
797
  }
625
798
  else {
626
799
  const nest = (prop) => {
627
800
  for (const childProp of Object.values(prop.embeddedProps)) {
628
- if (childProp.fieldNames) {
629
- ret.push(this.helper.mapper(childProp.fieldNames[0], this.type));
801
+ if (childProp.fieldNames && (childProp.kind !== core_1.ReferenceKind.EMBEDDED || childProp.object) && childProp.persist !== false) {
802
+ ret.push(getFieldName(childProp.fieldNames[0]));
630
803
  }
631
804
  else {
632
805
  nest(childProp);
@@ -637,11 +810,15 @@ class QueryBuilder {
637
810
  }
638
811
  return;
639
812
  }
640
- ret.push(this.helper.mapper(field, this.type));
813
+ if (prop && prop.fieldNames.length > 1) {
814
+ ret.push(...prop.fieldNames.map(f => getFieldName(f)));
815
+ return;
816
+ }
817
+ ret.push(getFieldName(field));
641
818
  });
642
819
  const meta = this.mainAlias.metadata;
643
820
  /* istanbul ignore next */
644
- const requiresSQLConversion = meta?.props.filter(p => p.customType?.convertToJSValueSQL) ?? [];
821
+ const requiresSQLConversion = meta?.props.filter(p => p.hasConvertToJSValueSQL && p.persist !== false) ?? [];
645
822
  if (this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES) && (fields.includes('*') || fields.includes(`${this.mainAlias.aliasName}.*`)) && requiresSQLConversion.length > 0) {
646
823
  requiresSQLConversion.forEach(p => ret.push(this.helper.mapper(p.name, this.type)));
647
824
  }
@@ -650,7 +827,7 @@ class QueryBuilder {
650
827
  const cols = this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[f]);
651
828
  ret.push(...cols);
652
829
  }
653
- if (this._joins[f].prop.reference !== core_1.ReferenceType.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
830
+ if (this._joins[f].prop.kind !== core_1.ReferenceKind.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
654
831
  this._joins[f].inverseJoinColumns.forEach(inverseJoinColumn => {
655
832
  core_1.Utils.renameKey(this._cond, inverseJoinColumn, `${this._joins[f].alias}.${inverseJoinColumn}`);
656
833
  });
@@ -669,9 +846,9 @@ class QueryBuilder {
669
846
  }
670
847
  if (data) {
671
848
  if (core_1.Utils.isEntity(data)) {
672
- data = (0, core_1.helper)(data).toJSON();
849
+ data = this.em?.getComparator().prepareEntity(data) ?? (0, core_1.serialize)(data);
673
850
  }
674
- this._data = this.helper.processData(data, this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES));
851
+ this._data = this.helper.processData(data, this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES), false);
675
852
  }
676
853
  if (cond) {
677
854
  this.where(cond);
@@ -681,6 +858,8 @@ class QueryBuilder {
681
858
  getQueryBase() {
682
859
  const qb = this.getKnex();
683
860
  const schema = this.getSchema(this.mainAlias);
861
+ // Joined tables doesn't need to belong to the same schema as the main table
862
+ const joinSchema = this._schema ?? this.em?.schema ?? schema;
684
863
  if (schema) {
685
864
  qb.withSchema(schema);
686
865
  }
@@ -699,12 +878,12 @@ class QueryBuilder {
699
878
  else if (this.flags.has(core_1.QueryFlag.DISTINCT)) {
700
879
  qb.distinct();
701
880
  }
702
- this.helper.processJoins(qb, this._joins, schema);
881
+ this.helper.processJoins(qb, this._joins, joinSchema);
703
882
  break;
704
883
  case enums_1.QueryType.COUNT: {
705
884
  const m = this.flags.has(core_1.QueryFlag.DISTINCT) ? 'countDistinct' : 'count';
706
885
  qb[m]({ count: this._fields.map(f => this.helper.mapper(f, this.type)) });
707
- this.helper.processJoins(qb, this._joins, schema);
886
+ this.helper.processJoins(qb, this._joins, joinSchema);
708
887
  break;
709
888
  }
710
889
  case enums_1.QueryType.INSERT:
@@ -723,6 +902,24 @@ class QueryBuilder {
723
902
  }
724
903
  return qb;
725
904
  }
905
+ applyDiscriminatorCondition() {
906
+ const meta = this.mainAlias.metadata;
907
+ if (!meta?.discriminatorValue) {
908
+ return;
909
+ }
910
+ const types = Object.values(meta.root.discriminatorMap).map(cls => this.metadata.find(cls));
911
+ const children = [];
912
+ const lookUpChildren = (ret, type) => {
913
+ const children = types.filter(meta2 => meta2.extends === type);
914
+ children.forEach(m => lookUpChildren(ret, m.className));
915
+ ret.push(...children.filter(c => c.discriminatorValue));
916
+ return children;
917
+ };
918
+ lookUpChildren(children, meta.className);
919
+ this.andWhere({
920
+ [meta.root.discriminatorColumn]: children.length > 0 ? { $in: [meta.discriminatorValue, ...children.map(c => c.discriminatorValue)] } : meta.discriminatorValue,
921
+ });
922
+ }
726
923
  finalize() {
727
924
  if (this.finalized) {
728
925
  return;
@@ -731,10 +928,11 @@ class QueryBuilder {
731
928
  this.select('*');
732
929
  }
733
930
  const meta = this.mainAlias.metadata;
931
+ this.applyDiscriminatorCondition();
734
932
  if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
735
933
  const relationsToPopulate = this._populate.map(({ field }) => field);
736
934
  meta.relations
737
- .filter(prop => prop.reference === core_1.ReferenceType.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
935
+ .filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
738
936
  .map(prop => ({ field: prop.name }))
739
937
  .forEach(item => this._populate.push(item));
740
938
  }
@@ -743,12 +941,10 @@ class QueryBuilder {
743
941
  const aliasedField = `${fromAlias}.${fromField}`;
744
942
  const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
745
943
  if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
746
- return this._populateMap[join] = this._joins[join].alias;
747
- }
748
- if (this.metadata.find(field)?.pivotTable) { // pivot table entity
749
- this.autoJoinPivotTable(field);
944
+ this._populateMap[join] = this._joins[join].alias;
945
+ return;
750
946
  }
751
- else if (meta && this.helper.isOneToOneInverse(fromField)) {
947
+ if (meta && this.helper.isOneToOneInverse(fromField)) {
752
948
  const prop = meta.properties[fromField];
753
949
  const alias = this.getNextAlias(prop.pivotEntity ?? prop.type);
754
950
  const aliasedName = `${fromAlias}.${prop.name}#${alias}`;
@@ -764,14 +960,20 @@ class QueryBuilder {
764
960
  const aliased = this.knex.ref(prop.fieldNames[0]).toString();
765
961
  return `${prop.formula(alias)} as ${aliased}`;
766
962
  })
767
- .filter(field => !this._fields.includes(field))
768
- .forEach(field => this.addSelect(field));
963
+ .filter(field => !this._fields.some(f => {
964
+ if (f instanceof core_1.RawQueryFragment) {
965
+ return f.sql === field && f.params.length === 0;
966
+ }
967
+ return f === field;
968
+ }))
969
+ .forEach(field => this._fields.push((0, core_1.raw)(field)));
769
970
  }
971
+ this.processPopulateWhere();
770
972
  core_1.QueryHelper.processObjectParams(this._data);
771
973
  core_1.QueryHelper.processObjectParams(this._cond);
772
974
  core_1.QueryHelper.processObjectParams(this._having);
773
- // automatically enable paginate flag when we detect to-many joins
774
- if (!this.flags.has(core_1.QueryFlag.DISABLE_PAGINATE) && this.hasToManyJoins()) {
975
+ // automatically enable paginate flag when we detect to-many joins, but only if there is no `group by` clause
976
+ if (!this.flags.has(core_1.QueryFlag.DISABLE_PAGINATE) && this._groupBy.length === 0 && this.hasToManyJoins()) {
775
977
  this.flags.add(core_1.QueryFlag.PAGINATE);
776
978
  }
777
979
  if (meta && this.flags.has(core_1.QueryFlag.PAGINATE) && (this._limit > 0 || this._offset > 0)) {
@@ -782,17 +984,54 @@ class QueryBuilder {
782
984
  }
783
985
  this.finalized = true;
784
986
  }
987
+ processPopulateWhere() {
988
+ if (this._populateWhere == null || this._populateWhere === core_1.PopulateHint.ALL) {
989
+ return;
990
+ }
991
+ const joins = Object.values(this._joins);
992
+ joins.forEach(join => {
993
+ join.cond_ = join.cond;
994
+ join.cond = {};
995
+ });
996
+ const replaceOnConditions = (cond) => {
997
+ Object.keys(cond).forEach(k => {
998
+ if (core_1.Utils.isOperator(k)) {
999
+ if (Array.isArray(cond[k])) {
1000
+ return cond[k].forEach((c) => replaceOnConditions(c));
1001
+ }
1002
+ return replaceOnConditions(cond[k]);
1003
+ }
1004
+ const [a] = this.helper.splitField(k);
1005
+ const join = joins.find(j => j.alias === a);
1006
+ if (join) {
1007
+ join.cond = { ...join.cond, [k]: cond[k] };
1008
+ }
1009
+ });
1010
+ };
1011
+ if (this._populateWhere === core_1.PopulateHint.INFER) {
1012
+ replaceOnConditions(this._cond);
1013
+ }
1014
+ else if (typeof this._populateWhere === 'object') {
1015
+ const cond = CriteriaNodeFactory_1.CriteriaNodeFactory
1016
+ .createNode(this.metadata, this.mainAlias.entityName, this._populateWhere)
1017
+ .process(this);
1018
+ replaceOnConditions(cond);
1019
+ }
1020
+ }
785
1021
  hasToManyJoins() {
786
1022
  return Object.values(this._joins).some(join => {
787
- return [core_1.ReferenceType.ONE_TO_MANY, core_1.ReferenceType.MANY_TO_MANY].includes(join.prop.reference);
1023
+ return [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(join.prop.kind);
788
1024
  });
789
1025
  }
790
1026
  wrapPaginateSubQuery(meta) {
791
1027
  const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
792
1028
  const subQuery = this.clone().select(pks).groupBy(pks).limit(this._limit);
1029
+ // revert the on conditions added via populateWhere, we want to apply those only once
1030
+ Object.values(subQuery._joins).forEach(join => join.cond = join.cond_ ?? {});
793
1031
  if (this._offset) {
794
1032
  subQuery.offset(this._offset);
795
1033
  }
1034
+ const addToSelect = [];
796
1035
  if (this._orderBy.length > 0) {
797
1036
  const orderBy = [];
798
1037
  for (const orderMap of this._orderBy) {
@@ -800,28 +1039,38 @@ class QueryBuilder {
800
1039
  const [a, f] = this.helper.splitField(field);
801
1040
  const prop = this.helper.getProperty(f, a);
802
1041
  const type = this.platform.castColumn(prop);
803
- orderBy.push({
804
- [`min(${this.ref(this.helper.mapper(field, this.type, undefined, null))}${type})`]: direction,
805
- });
1042
+ const fieldName = this.helper.mapper(field, this.type, undefined, null);
1043
+ if (!prop?.persist && !prop?.formula) {
1044
+ addToSelect.push(fieldName);
1045
+ }
1046
+ orderBy.push({ [(0, core_1.raw)(`min(${this.knex.ref(fieldName)}${type})`)]: direction });
806
1047
  }
807
1048
  }
808
1049
  subQuery.orderBy(orderBy);
809
1050
  }
810
1051
  subQuery.finalized = true;
811
1052
  const knexQuery = subQuery.as(this.mainAlias.aliasName).clearSelect().select(pks);
1053
+ if (addToSelect.length > 0) {
1054
+ addToSelect.forEach(prop => {
1055
+ const field = this._fields.find(field => {
1056
+ if (typeof field === 'object' && field && '__as' in field) {
1057
+ return field.__as === prop;
1058
+ }
1059
+ // not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
1060
+ return field.toString().includes(prop);
1061
+ });
1062
+ if (field) {
1063
+ knexQuery.select(field);
1064
+ }
1065
+ });
1066
+ }
812
1067
  // multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O)
813
1068
  // https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
814
1069
  const subSubQuery = this.getKnex().select(pks).from(knexQuery);
1070
+ subSubQuery.__raw = true; // tag it as there is now way to check via `instanceof`
815
1071
  this._limit = undefined;
816
1072
  this._offset = undefined;
817
- const cond = this._cond;
818
1073
  this.select(this._fields).where({ [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery } });
819
- if (this._populateWhere === core_1.PopulateHint.INFER) {
820
- this.andWhere(cond);
821
- }
822
- else if (typeof this._populateWhere === 'object') {
823
- this.andWhere(this._populateWhere);
824
- }
825
1074
  }
826
1075
  wrapModifySubQuery(meta) {
827
1076
  const subQuery = this.clone();
@@ -835,21 +1084,10 @@ class QueryBuilder {
835
1084
  [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery },
836
1085
  });
837
1086
  }
838
- autoJoinPivotTable(field) {
839
- const pivotMeta = this.metadata.find(field);
840
- const owner = pivotMeta.relations[0];
841
- const inverse = pivotMeta.relations[1];
842
- const prop = this._cond[pivotMeta.name + '.' + owner.name] || this._orderBy[pivotMeta.name + '.' + owner.name] ? inverse : owner;
843
- const pivotAlias = this.getNextAlias(pivotMeta.name);
844
- this._joins[field] = this.helper.joinPivotTable(field, prop, this.mainAlias.aliasName, pivotAlias, 'leftJoin');
845
- core_1.Utils.renameKey(this._cond, `${field}.${owner.name}`, core_1.Utils.getPrimaryKeyHash(owner.fieldNames.map(fieldName => `${pivotAlias}.${fieldName}`)));
846
- core_1.Utils.renameKey(this._cond, `${field}.${inverse.name}`, core_1.Utils.getPrimaryKeyHash(inverse.fieldNames.map(fieldName => `${pivotAlias}.${fieldName}`)));
847
- this._populateMap[field] = this._joins[field].alias;
848
- }
849
1087
  getSchema(alias) {
850
1088
  const { metadata } = alias;
851
1089
  const metaSchema = metadata?.schema && metadata.schema !== '*' ? metadata.schema : undefined;
852
- return this._schema ?? metaSchema ?? this.em?.config.get('schema');
1090
+ return this._schema ?? metaSchema ?? this.em?.schema ?? this.em?.config.get('schema');
853
1091
  }
854
1092
  createAlias(entityName, aliasName, subQuery) {
855
1093
  const metadata = this.metadata.find(entityName);
@@ -865,11 +1103,11 @@ class QueryBuilder {
865
1103
  fromSubQuery(target, aliasName) {
866
1104
  const subQuery = target.getKnexQuery();
867
1105
  const { entityName } = target.mainAlias;
868
- aliasName ?? (aliasName = this.getNextAlias(entityName));
1106
+ aliasName ??= this.getNextAlias(entityName);
869
1107
  this.createMainAlias(entityName, aliasName, subQuery);
870
1108
  }
871
1109
  fromEntityName(entityName, aliasName) {
872
- aliasName ?? (aliasName = this._mainAlias?.aliasName ?? this.getNextAlias(entityName));
1110
+ aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(entityName);
873
1111
  this.createMainAlias(entityName, aliasName);
874
1112
  }
875
1113
  createQueryBuilderHelper() {
@@ -897,6 +1135,9 @@ class QueryBuilder {
897
1135
  if (this._data) {
898
1136
  object.data = this._data;
899
1137
  }
1138
+ if (this._schema) {
1139
+ object.schema = this._schema;
1140
+ }
900
1141
  if (!core_1.Utils.isEmpty(this._cond)) {
901
1142
  object.where = this._cond;
902
1143
  }