@mikro-orm/knex 6.0.0-dev.6 → 6.0.0-dev.61

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 (42) hide show
  1. package/AbstractSqlConnection.d.ts +5 -2
  2. package/AbstractSqlConnection.js +18 -10
  3. package/AbstractSqlDriver.d.ts +17 -17
  4. package/AbstractSqlDriver.js +110 -47
  5. package/AbstractSqlPlatform.d.ts +2 -2
  6. package/AbstractSqlPlatform.js +14 -7
  7. package/MonkeyPatchable.d.ts +1 -0
  8. package/MonkeyPatchable.js +3 -0
  9. package/README.md +64 -107
  10. package/SqlEntityManager.d.ts +0 -4
  11. package/SqlEntityManager.js +1 -9
  12. package/SqlEntityRepository.d.ts +0 -1
  13. package/SqlEntityRepository.js +0 -1
  14. package/index.d.ts +1 -0
  15. package/index.js +1 -0
  16. package/index.mjs +176 -0
  17. package/package.json +5 -5
  18. package/query/ArrayCriteriaNode.d.ts +3 -3
  19. package/query/CriteriaNode.d.ts +8 -8
  20. package/query/CriteriaNode.js +8 -8
  21. package/query/CriteriaNodeFactory.d.ts +6 -6
  22. package/query/CriteriaNodeFactory.js +11 -11
  23. package/query/ObjectCriteriaNode.d.ts +3 -3
  24. package/query/ObjectCriteriaNode.js +12 -8
  25. package/query/QueryBuilder.d.ts +19 -5
  26. package/query/QueryBuilder.js +191 -47
  27. package/query/QueryBuilderHelper.d.ts +3 -5
  28. package/query/QueryBuilderHelper.js +85 -71
  29. package/query/ScalarCriteriaNode.d.ts +3 -2
  30. package/query/ScalarCriteriaNode.js +9 -6
  31. package/schema/DatabaseSchema.js +3 -3
  32. package/schema/DatabaseTable.d.ts +9 -9
  33. package/schema/DatabaseTable.js +21 -22
  34. package/schema/SchemaComparator.d.ts +4 -4
  35. package/schema/SchemaComparator.js +4 -2
  36. package/schema/SchemaHelper.d.ts +11 -11
  37. package/schema/SchemaHelper.js +3 -3
  38. package/schema/{SchemaGenerator.d.ts → SqlSchemaGenerator.d.ts} +3 -7
  39. package/schema/{SchemaGenerator.js → SqlSchemaGenerator.js} +17 -24
  40. package/schema/index.d.ts +1 -1
  41. package/schema/index.js +1 -1
  42. package/typings.d.ts +14 -13
@@ -1,6 +1,19 @@
1
1
  "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var _QueryBuilder_query;
2
14
  Object.defineProperty(exports, "__esModule", { value: true });
3
15
  exports.QueryBuilder = void 0;
16
+ const util_1 = require("util");
4
17
  const core_1 = require("@mikro-orm/core");
5
18
  const enums_1 = require("./enums");
6
19
  const QueryBuilderHelper_1 = require("./QueryBuilderHelper");
@@ -39,12 +52,13 @@ class QueryBuilder {
39
52
  /**
40
53
  * @internal
41
54
  */
42
- constructor(entityName, metadata, driver, context, alias, connectionType, em) {
55
+ constructor(entityName, metadata, driver, context, alias, connectionType, em, loggerContext) {
43
56
  this.metadata = metadata;
44
57
  this.driver = driver;
45
58
  this.context = context;
46
59
  this.connectionType = connectionType;
47
60
  this.em = em;
61
+ this.loggerContext = loggerContext;
48
62
  /** @internal */
49
63
  this._populate = [];
50
64
  /** @internal */
@@ -63,6 +77,7 @@ class QueryBuilder {
63
77
  this._aliases = {};
64
78
  this.platform = this.driver.getPlatform();
65
79
  this.knex = this.driver.getConnection(this.connectionType).getKnex();
80
+ _QueryBuilder_query.set(this, void 0);
66
81
  if (alias) {
67
82
  this.aliasCounter++;
68
83
  this._explicitAlias = true;
@@ -115,7 +130,7 @@ class QueryBuilder {
115
130
  this._fields = this.mainAlias.metadata.primaryKeys;
116
131
  }
117
132
  else {
118
- this._fields = [this.raw('*')];
133
+ this._fields = [(0, core_1.raw)('*')];
119
134
  }
120
135
  if (distinct) {
121
136
  this.flags.add(core_1.QueryFlag.DISTINCT);
@@ -164,9 +179,15 @@ class QueryBuilder {
164
179
  }
165
180
  where(cond, params, operator) {
166
181
  this.ensureNotFinalized();
167
- if (core_1.Utils.isString(cond)) {
168
- cond = { [`(${cond})`]: core_1.Utils.asArray(params) };
169
- operator = operator || '$and';
182
+ const rawField = core_1.RawQueryFragment.getKnownFragment(cond);
183
+ if (rawField) {
184
+ const sql = this.platform.formatQuery(rawField.sql, rawField.params);
185
+ cond = { [(0, core_1.raw)(`(${sql})`)]: core_1.Utils.asArray(params) };
186
+ operator ??= '$and';
187
+ }
188
+ else if (core_1.Utils.isString(cond)) {
189
+ cond = { [(0, core_1.raw)(`(${cond})`, core_1.Utils.asArray(params))]: [] };
190
+ operator ??= '$and';
170
191
  }
171
192
  else {
172
193
  cond = core_1.QueryHelper.processWhere({
@@ -234,7 +255,7 @@ class QueryBuilder {
234
255
  having(cond = {}, params) {
235
256
  this.ensureNotFinalized();
236
257
  if (core_1.Utils.isString(cond)) {
237
- cond = { [`(${cond})`]: core_1.Utils.asArray(params) };
258
+ cond = { [(0, core_1.raw)(`(${cond})`, params)]: [] };
238
259
  }
239
260
  this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
240
261
  return this;
@@ -277,11 +298,6 @@ class QueryBuilder {
277
298
  ref(field) {
278
299
  return this.knex.ref(field);
279
300
  }
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
301
  limit(limit, offset = 0) {
286
302
  this.ensureNotFinalized();
287
303
  this._limit = limit;
@@ -360,7 +376,8 @@ class QueryBuilder {
360
376
  core_1.Utils.runIfNotEmpty(() => {
361
377
  const queryOrder = this.helper.getQueryOrder(this.type ?? enums_1.QueryType.SELECT, this._orderBy, this._populateMap);
362
378
  if (queryOrder) {
363
- return qb.orderByRaw(queryOrder);
379
+ qb.orderByRaw(queryOrder);
380
+ return;
364
381
  }
365
382
  }, this._orderBy);
366
383
  core_1.Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
@@ -372,26 +389,34 @@ class QueryBuilder {
372
389
  if (this.lockMode) {
373
390
  this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
374
391
  }
375
- this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata);
392
+ this.helper.finalize(this.type ?? enums_1.QueryType.SELECT, qb, this.mainAlias.metadata, this._data);
376
393
  return qb;
377
394
  }
378
395
  /**
379
396
  * Returns the query with parameters as wildcards.
380
397
  */
381
398
  getQuery() {
382
- return this.getKnexQuery().toSQL().toNative().sql;
399
+ return this.toQuery().sql;
400
+ }
401
+ toQuery() {
402
+ if (__classPrivateFieldGet(this, _QueryBuilder_query, "f")) {
403
+ return __classPrivateFieldGet(this, _QueryBuilder_query, "f");
404
+ }
405
+ const sql = this.getKnexQuery().toSQL();
406
+ const query = sql.toNative();
407
+ return __classPrivateFieldSet(this, _QueryBuilder_query, { sql: query.sql, params: query.bindings ?? [], _sql: sql }, "f");
383
408
  }
384
409
  /**
385
410
  * Returns the list of all parameters for this query.
386
411
  */
387
412
  getParams() {
388
- return this.getKnexQuery().toSQL().toNative().bindings;
413
+ return this.toQuery().params;
389
414
  }
390
415
  /**
391
416
  * Returns raw interpolated query string with all the parameters inlined.
392
417
  */
393
418
  getFormattedQuery() {
394
- const query = this.getKnexQuery().toSQL();
419
+ const query = this.toQuery()._sql;
395
420
  return this.platform.formatQuery(query.sql, query.bindings);
396
421
  }
397
422
  /**
@@ -433,7 +458,7 @@ class QueryBuilder {
433
458
  return cached.data;
434
459
  }
435
460
  const type = this.connectionType || (method === 'run' ? 'write' : 'read');
436
- const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context);
461
+ const res = await this.driver.getConnection(type).execute(query.sql, query.bindings, method, this.context, this.loggerContext);
437
462
  const meta = this.mainAlias.metadata;
438
463
  if (!mapResults || !meta) {
439
464
  await this.em?.storeCache(this._cache, cached, res);
@@ -464,7 +489,27 @@ class QueryBuilder {
464
489
  if (this._joinedProps.size > 0) {
465
490
  res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata);
466
491
  }
467
- return res.map(r => this.em.map(this.mainAlias.entityName, r, { schema: this._schema }));
492
+ const entities = [];
493
+ function propagatePopulateHint(entity, hint) {
494
+ (0, core_1.helper)(entity).__serializationContext.populate ??= hint;
495
+ hint.forEach(pop => {
496
+ const value = entity[pop.field];
497
+ if (core_1.Utils.isEntity(value, true)) {
498
+ (0, core_1.helper)(value).populated();
499
+ propagatePopulateHint(value, pop.children ?? []);
500
+ }
501
+ else if (core_1.Utils.isCollection(value)) {
502
+ value.populated();
503
+ value.getItems(false).forEach(item => propagatePopulateHint(item, pop.children ?? []));
504
+ }
505
+ });
506
+ }
507
+ for (const r of res) {
508
+ const entity = this.em.map(this.mainAlias.entityName, r, { schema: this._schema });
509
+ propagatePopulateHint(entity, this._populate);
510
+ entities.push(entity);
511
+ }
512
+ return entities;
468
513
  }
469
514
  /**
470
515
  * Executes the query, returning the first result or null
@@ -488,11 +533,24 @@ class QueryBuilder {
488
533
  }
489
534
  return res ? +res.count : 0;
490
535
  }
536
+ /**
537
+ * Executes the query, returning both array of results and total count query (without offset and limit).
538
+ */
539
+ async getResultAndCount() {
540
+ return Promise.all([
541
+ this.getResultList(),
542
+ this.getCount(),
543
+ ]);
544
+ }
491
545
  /**
492
546
  * Provides promise-like interface so we can await the QB instance.
493
547
  */
494
548
  then(onfulfilled, onrejected) {
495
- switch (this.type ?? enums_1.QueryType.SELECT) {
549
+ let type = this.type ?? enums_1.QueryType.SELECT;
550
+ if (this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(core_1.QueryFlag.DELETE_SUB_QUERY)) {
551
+ type = enums_1.QueryType.UPDATE;
552
+ }
553
+ switch (type) {
496
554
  case enums_1.QueryType.INSERT:
497
555
  case enums_1.QueryType.UPDATE:
498
556
  case enums_1.QueryType.DELETE:
@@ -515,7 +573,10 @@ class QueryBuilder {
515
573
  /* istanbul ignore next */
516
574
  alias = meta?.properties[f]?.fieldNames[0] ?? alias;
517
575
  }
518
- return qb.as(alias);
576
+ const ret = qb.as(alias);
577
+ // tag the instance, so it is possible to detect it easily
578
+ Object.defineProperty(ret, '__as', { enumerable: false, value: alias });
579
+ return ret;
519
580
  }
520
581
  clone() {
521
582
  const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
@@ -570,11 +631,11 @@ class QueryBuilder {
570
631
  aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
571
632
  });
572
633
  let aliasedName = `${fromAlias}.${prop.name}#${alias}`;
573
- path ?? (path = `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`);
574
- if (prop.reference === core_1.ReferenceType.ONE_TO_MANY) {
634
+ path ??= `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? entityName)}.${prop.name}`;
635
+ if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY) {
575
636
  this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
576
637
  }
577
- else if (prop.reference === core_1.ReferenceType.MANY_TO_MANY) {
638
+ else if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY) {
578
639
  let pivotAlias = alias;
579
640
  if (type !== 'pivotJoin') {
580
641
  const oldPivotAlias = this.getAliasForJoinPath(path + '[pivot]');
@@ -585,7 +646,7 @@ class QueryBuilder {
585
646
  Object.assign(this._joins, joins);
586
647
  this.createAlias(prop.pivotEntity, pivotAlias);
587
648
  }
588
- else if (prop.reference === core_1.ReferenceType.ONE_TO_ONE) {
649
+ else if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE) {
589
650
  this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond);
590
651
  }
591
652
  else { // MANY_TO_ONE
@@ -599,17 +660,25 @@ class QueryBuilder {
599
660
  prepareFields(fields, type = 'where') {
600
661
  const ret = [];
601
662
  fields.forEach(field => {
663
+ const rawField = core_1.RawQueryFragment.getKnownFragment(field);
664
+ if (rawField) {
665
+ const sql = this.platform.formatQuery(rawField.sql, rawField.params);
666
+ ret.push(this.knex.raw(sql));
667
+ return;
668
+ }
602
669
  if (!core_1.Utils.isString(field)) {
603
- return ret.push(field);
670
+ ret.push(field);
671
+ return;
604
672
  }
605
673
  const join = Object.keys(this._joins).find(k => field === k.substring(0, k.indexOf('#')));
606
674
  if (join && type === 'where') {
607
- return ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
675
+ ret.push(...this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[join]));
676
+ return;
608
677
  }
609
678
  const [a, f] = this.helper.splitField(field);
610
679
  const prop = this.helper.getProperty(f, a);
611
680
  /* istanbul ignore next */
612
- if (prop && [core_1.ReferenceType.ONE_TO_MANY, core_1.ReferenceType.MANY_TO_MANY].includes(prop.reference)) {
681
+ if (prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
613
682
  return;
614
683
  }
615
684
  if (prop?.embedded) {
@@ -617,7 +686,7 @@ class QueryBuilder {
617
686
  ret.push(fieldName);
618
687
  return;
619
688
  }
620
- if (prop?.reference === core_1.ReferenceType.EMBEDDED) {
689
+ if (prop?.kind === core_1.ReferenceKind.EMBEDDED) {
621
690
  if (prop.object) {
622
691
  ret.push(this.helper.mapper(prop.fieldNames[0], this.type));
623
692
  }
@@ -649,7 +718,7 @@ class QueryBuilder {
649
718
  const cols = this.helper.mapJoinColumns(this.type ?? enums_1.QueryType.SELECT, this._joins[f]);
650
719
  ret.push(...cols);
651
720
  }
652
- if (this._joins[f].prop.reference !== core_1.ReferenceType.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
721
+ if (this._joins[f].prop.kind !== core_1.ReferenceKind.ONE_TO_ONE && this._joins[f].inverseJoinColumns) {
653
722
  this._joins[f].inverseJoinColumns.forEach(inverseJoinColumn => {
654
723
  core_1.Utils.renameKey(this._cond, inverseJoinColumn, `${this._joins[f].alias}.${inverseJoinColumn}`);
655
724
  });
@@ -668,7 +737,7 @@ class QueryBuilder {
668
737
  }
669
738
  if (data) {
670
739
  if (core_1.Utils.isEntity(data)) {
671
- data = (0, core_1.helper)(data).toJSON();
740
+ data = this.em?.getComparator().prepareEntity(data) ?? (0, core_1.serialize)(data);
672
741
  }
673
742
  this._data = this.helper.processData(data, this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES));
674
743
  }
@@ -733,7 +802,7 @@ class QueryBuilder {
733
802
  if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
734
803
  const relationsToPopulate = this._populate.map(({ field }) => field);
735
804
  meta.relations
736
- .filter(prop => prop.reference === core_1.ReferenceType.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
805
+ .filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
737
806
  .map(prop => ({ field: prop.name }))
738
807
  .forEach(item => this._populate.push(item));
739
808
  }
@@ -742,7 +811,8 @@ class QueryBuilder {
742
811
  const aliasedField = `${fromAlias}.${fromField}`;
743
812
  const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
744
813
  if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
745
- return this._populateMap[join] = this._joins[join].alias;
814
+ this._populateMap[join] = this._joins[join].alias;
815
+ return;
746
816
  }
747
817
  if (this.metadata.find(field)?.pivotTable) { // pivot table entity
748
818
  this.autoJoinPivotTable(field);
@@ -763,9 +833,15 @@ class QueryBuilder {
763
833
  const aliased = this.knex.ref(prop.fieldNames[0]).toString();
764
834
  return `${prop.formula(alias)} as ${aliased}`;
765
835
  })
766
- .filter(field => !this._fields.includes(field))
767
- .forEach(field => this.addSelect(field));
836
+ .filter(field => !this._fields.some(f => {
837
+ if (f instanceof core_1.RawQueryFragment) {
838
+ return f.sql === field && f.params.length === 0;
839
+ }
840
+ return f === field;
841
+ }))
842
+ .forEach(field => this._fields.push((0, core_1.raw)(field)));
768
843
  }
844
+ this.processPopulateWhere();
769
845
  core_1.QueryHelper.processObjectParams(this._data);
770
846
  core_1.QueryHelper.processObjectParams(this._cond);
771
847
  core_1.QueryHelper.processObjectParams(this._having);
@@ -781,17 +857,54 @@ class QueryBuilder {
781
857
  }
782
858
  this.finalized = true;
783
859
  }
860
+ processPopulateWhere() {
861
+ if (this._populateWhere == null || this._populateWhere === core_1.PopulateHint.ALL) {
862
+ return;
863
+ }
864
+ const joins = Object.values(this._joins);
865
+ joins.forEach(join => {
866
+ join.cond_ = join.cond;
867
+ join.cond = {};
868
+ });
869
+ const replaceOnConditions = (cond) => {
870
+ Object.keys(cond).forEach(k => {
871
+ if (core_1.Utils.isOperator(k)) {
872
+ if (Array.isArray(cond[k])) {
873
+ return cond[k].forEach((c) => replaceOnConditions(c));
874
+ }
875
+ return replaceOnConditions(cond[k]);
876
+ }
877
+ const [a] = this.helper.splitField(k);
878
+ const join = joins.find(j => j.alias === a);
879
+ if (join) {
880
+ join.cond = { ...join.cond, [k]: cond[k] };
881
+ }
882
+ });
883
+ };
884
+ if (this._populateWhere === core_1.PopulateHint.INFER) {
885
+ replaceOnConditions(this._cond);
886
+ }
887
+ else if (typeof this._populateWhere === 'object') {
888
+ const cond = CriteriaNodeFactory_1.CriteriaNodeFactory
889
+ .createNode(this.metadata, this.mainAlias.entityName, this._populateWhere)
890
+ .process(this);
891
+ replaceOnConditions(cond);
892
+ }
893
+ }
784
894
  hasToManyJoins() {
785
895
  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);
896
+ return [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(join.prop.kind);
787
897
  });
788
898
  }
789
899
  wrapPaginateSubQuery(meta) {
790
900
  const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
791
901
  const subQuery = this.clone().select(pks).groupBy(pks).limit(this._limit);
902
+ // revert the on conditions added via populateWhere, we want to apply those only once
903
+ Object.values(subQuery._joins).forEach(join => join.cond = join.cond_ ?? {});
792
904
  if (this._offset) {
793
905
  subQuery.offset(this._offset);
794
906
  }
907
+ const addToSelect = [];
795
908
  if (this._orderBy.length > 0) {
796
909
  const orderBy = [];
797
910
  for (const orderMap of this._orderBy) {
@@ -799,28 +912,37 @@ class QueryBuilder {
799
912
  const [a, f] = this.helper.splitField(field);
800
913
  const prop = this.helper.getProperty(f, a);
801
914
  const type = this.platform.castColumn(prop);
802
- orderBy.push({
803
- [`min(${this.ref(this.helper.mapper(field, this.type, undefined, null))}${type})`]: direction,
804
- });
915
+ const fieldName = this.helper.mapper(field, this.type, undefined, null);
916
+ if (!prop?.persist && !prop?.formula) {
917
+ addToSelect.push(fieldName);
918
+ }
919
+ orderBy.push({ [(0, core_1.raw)(`min(${this.ref(fieldName)}${type})`)]: direction });
805
920
  }
806
921
  }
807
922
  subQuery.orderBy(orderBy);
808
923
  }
809
924
  subQuery.finalized = true;
810
925
  const knexQuery = subQuery.as(this.mainAlias.aliasName).clearSelect().select(pks);
926
+ if (addToSelect.length > 0) {
927
+ addToSelect.forEach(prop => {
928
+ const field = this._fields.find(field => {
929
+ if (typeof field === 'object' && field && '__as' in field) {
930
+ return field.__as === prop;
931
+ }
932
+ // not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
933
+ return field.toString().includes(prop);
934
+ });
935
+ if (field) {
936
+ knexQuery.select(field);
937
+ }
938
+ });
939
+ }
811
940
  // multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O)
812
941
  // https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
813
942
  const subSubQuery = this.getKnex().select(pks).from(knexQuery);
814
943
  this._limit = undefined;
815
944
  this._offset = undefined;
816
- const cond = this._cond;
817
945
  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
946
  }
825
947
  wrapModifySubQuery(meta) {
826
948
  const subQuery = this.clone();
@@ -864,11 +986,11 @@ class QueryBuilder {
864
986
  fromSubQuery(target, aliasName) {
865
987
  const subQuery = target.getKnexQuery();
866
988
  const { entityName } = target.mainAlias;
867
- aliasName ?? (aliasName = this.getNextAlias(entityName));
989
+ aliasName ??= this.getNextAlias(entityName);
868
990
  this.createMainAlias(entityName, aliasName, subQuery);
869
991
  }
870
992
  fromEntityName(entityName, aliasName) {
871
- aliasName ?? (aliasName = this._mainAlias?.aliasName ?? this.getNextAlias(entityName));
993
+ aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(entityName);
872
994
  this.createMainAlias(entityName, aliasName);
873
995
  }
874
996
  createQueryBuilderHelper() {
@@ -885,5 +1007,27 @@ class QueryBuilder {
885
1007
  throw new Error('This QueryBuilder instance is already finalized, clone it first if you want to modify it.');
886
1008
  }
887
1009
  }
1010
+ /* istanbul ignore next */
1011
+ [(_QueryBuilder_query = new WeakMap(), util_1.inspect.custom)](depth) {
1012
+ const object = { ...this };
1013
+ const hidden = ['metadata', 'driver', 'context', 'platform', 'knex', 'type'];
1014
+ Object.keys(object).filter(k => k.startsWith('_')).forEach(k => delete object[k]);
1015
+ Object.keys(object).filter(k => object[k] == null).forEach(k => delete object[k]);
1016
+ hidden.forEach(k => delete object[k]);
1017
+ let prefix = this.type ? this.type.substring(0, 1) + this.type.toLowerCase().substring(1) : '';
1018
+ if (this._data) {
1019
+ object.data = this._data;
1020
+ }
1021
+ if (!core_1.Utils.isEmpty(this._cond)) {
1022
+ object.where = this._cond;
1023
+ }
1024
+ if (this._onConflict?.[0]) {
1025
+ prefix = 'Upsert';
1026
+ object.onConflict = this._onConflict[0];
1027
+ }
1028
+ const name = this._mainAlias ? `${prefix}QueryBuilder<${this._mainAlias?.entityName}>` : 'QueryBuilder';
1029
+ const ret = (0, util_1.inspect)(object, { depth });
1030
+ return ret === '[Object]' ? `[${name}]` : name + ' ' + ret;
1031
+ }
888
1032
  }
889
1033
  exports.QueryBuilder = QueryBuilder;
@@ -1,5 +1,5 @@
1
1
  import type { Knex } from 'knex';
2
- import type { Dictionary, EntityData, EntityMetadata, EntityProperty, FlatQueryOrderMap, QBFilterQuery } from '@mikro-orm/core';
2
+ import type { Dictionary, EntityData, EntityKey, EntityMetadata, EntityProperty, FlatQueryOrderMap, QBFilterQuery } from '@mikro-orm/core';
3
3
  import { LockMode } from '@mikro-orm/core';
4
4
  import { QueryType } from './enums';
5
5
  import type { Field, JoinOptions } from '../typings';
@@ -43,16 +43,14 @@ export declare class QueryBuilderHelper {
43
43
  }[], qb: Knex.QueryBuilder): void;
44
44
  appendQueryCondition(type: QueryType, cond: any, qb: Knex.QueryBuilder, operator?: '$and' | '$or', method?: 'where' | 'having'): void;
45
45
  private appendQuerySubCondition;
46
- private processCustomExpression;
47
46
  private processObjectSubCondition;
48
47
  private getOperatorReplacement;
49
48
  getQueryOrder(type: QueryType, orderBy: FlatQueryOrderMap | FlatQueryOrderMap[], populate: Dictionary<string>): string;
50
49
  getQueryOrderFromObject(type: QueryType, orderBy: FlatQueryOrderMap, populate: Dictionary<string>): string;
51
- finalize(type: QueryType, qb: Knex.QueryBuilder, meta?: EntityMetadata): void;
52
- splitField(field: string, greedyAlias?: boolean): [string, string];
50
+ finalize(type: QueryType, qb: Knex.QueryBuilder, meta?: EntityMetadata, data?: Dictionary): void;
51
+ splitField<T>(field: EntityKey<T>, greedyAlias?: boolean): [string, EntityKey<T>];
53
52
  getLockSQL(qb: Knex.QueryBuilder, lockMode: LockMode, lockTables?: string[]): void;
54
53
  updateVersionProperty(qb: Knex.QueryBuilder, data: Dictionary): void;
55
- static isCustomExpression(field: string, hasAlias?: boolean): boolean;
56
54
  private prefix;
57
55
  private appendGroupCondition;
58
56
  private isPrefixed;