@mikro-orm/knex 5.8.9-dev.0 → 5.8.9-dev.2

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.
@@ -35,7 +35,10 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
35
35
  * 1:1 owner side needs to be marked for population so QB auto-joins the owner id
36
36
  */
37
37
  protected autoJoinOneToOneOwner<T extends object, P extends string = never>(meta: EntityMetadata, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, P>[]): PopulateOptions<T>[];
38
- protected joinedProps<T>(meta: EntityMetadata, populate: PopulateOptions<T>[]): PopulateOptions<T>[];
38
+ /**
39
+ * @internal
40
+ */
41
+ joinedProps<T>(meta: EntityMetadata, populate: PopulateOptions<T>[]): PopulateOptions<T>[];
39
42
  /**
40
43
  * @internal
41
44
  */
@@ -49,11 +49,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
49
49
  qb.setLockMode(options.lockMode, options.lockTableAliases);
50
50
  }
51
51
  core_1.Utils.asArray(options.flags).forEach(flag => qb.setFlag(flag));
52
- const result = await this.rethrow(qb.execute('all'));
53
- if (joinedProps.length > 0) {
54
- return this.mergeJoinedResult(result, meta, joinedProps);
55
- }
56
- return result;
52
+ return this.rethrow(qb.execute('all'));
57
53
  }
58
54
  async findOne(entityName, where, options) {
59
55
  const opts = { populate: [], ...(options || {}) };
@@ -135,8 +131,6 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
135
131
  if (qb) {
136
132
  // here we map the aliased results (cartesian product) to an object graph
137
133
  this.mapJoinedProps(ret, meta, populate, qb, ret, map);
138
- // we need to remove the cycles from the mapped values
139
- core_1.Utils.removeCycles(ret, meta);
140
134
  }
141
135
  return ret;
142
136
  }
@@ -151,7 +145,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
151
145
  const meta2 = this.metadata.find(relation.type);
152
146
  const path = parentJoinPath ? `${parentJoinPath}.${relation.name}` : `${meta.name}.${relation.name}`;
153
147
  const relationAlias = qb.getAliasForJoinPath(path);
154
- let relationPojo = {};
148
+ const relationPojo = {};
155
149
  // If the primary key value for the relation is null, we know we haven't joined to anything
156
150
  // and therefore we don't return any record (since all values would be null)
157
151
  const hasPK = meta2.primaryKeys.every(pk => meta2.properties[pk].fieldNames.every(name => {
@@ -190,22 +184,6 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
190
184
  delete root[alias];
191
185
  }
192
186
  });
193
- const key = `${meta.name}-${core_1.Utils.getCompositeKeyHash(result, meta)}`;
194
- const key2 = `${meta2.name}-${core_1.Utils.getCompositeKeyHash(relationPojo, meta2)}`;
195
- if (map[key2]) {
196
- const old = map[key2];
197
- Object.assign(old, relationPojo);
198
- relationPojo = old;
199
- }
200
- else {
201
- map[key2] = relationPojo;
202
- }
203
- if (map[key]) {
204
- result[relation.name] = map[key][relation.name];
205
- }
206
- else {
207
- map[key] = result;
208
- }
209
187
  if ([core_1.ReferenceType.MANY_TO_MANY, core_1.ReferenceType.ONE_TO_MANY].includes(relation.reference)) {
210
188
  result[relation.name] = result[relation.name] || [];
211
189
  this.appendToCollection(meta2, result[relation.name], relationPojo);
@@ -603,6 +581,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
603
581
  .map(prop => ({ field: prop.name, strategy: prop.strategy }));
604
582
  return [...populate, ...toPopulate];
605
583
  }
584
+ /**
585
+ * @internal
586
+ */
606
587
  joinedProps(meta, populate) {
607
588
  return populate.filter(p => {
608
589
  const prop = meta.properties[p.field] || {};
@@ -613,26 +594,33 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
613
594
  * @internal
614
595
  */
615
596
  mergeJoinedResult(rawResults, meta, joinedProps) {
616
- // group by the root entity primary key first
617
- const map = {};
618
597
  const res = [];
619
- rawResults.forEach(item => {
598
+ const map = {};
599
+ for (const item of rawResults) {
620
600
  const pk = core_1.Utils.getCompositeKeyHash(item, meta);
621
601
  if (map[pk]) {
622
- joinedProps.forEach(hint => {
623
- // Sometimes we might join a M:N relation with additional filter on the target entity, and as a result, we get
624
- // the first result with `null` for all target values, which is mapped as empty array. When we see that happen,
625
- // we need to merge the results of the next item.
626
- if (Array.isArray(map[pk][hint.field]) && Array.isArray(item[hint.field]) && map[pk][hint.field].length === 0) {
627
- item[hint.field].forEach((el) => map[pk][hint.field].push(el));
602
+ for (const hint of joinedProps) {
603
+ const prop = meta.properties[hint.field];
604
+ if (!item[hint.field]) {
605
+ continue;
628
606
  }
629
- });
607
+ switch (prop.reference) {
608
+ case core_1.ReferenceType.ONE_TO_MANY:
609
+ case core_1.ReferenceType.MANY_TO_MANY:
610
+ map[pk][hint.field] = this.mergeJoinedResult([...map[pk][hint.field], ...item[hint.field]], prop.targetMeta, hint.children ?? []);
611
+ break;
612
+ case core_1.ReferenceType.MANY_TO_ONE:
613
+ case core_1.ReferenceType.ONE_TO_ONE:
614
+ map[pk][hint.field] = this.mergeJoinedResult([map[pk][hint.field], item[hint.field]], prop.targetMeta, hint.children ?? [])[0];
615
+ break;
616
+ }
617
+ }
630
618
  }
631
619
  else {
632
620
  map[pk] = item;
633
621
  res.push(item);
634
622
  }
635
- });
623
+ }
636
624
  return res;
637
625
  }
638
626
  getFieldsForJoinedLoad(qb, meta, explicitFields, populate = [], parentTableAlias, parentJoinPath) {
@@ -837,7 +825,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
837
825
  buildFields(meta, populate, joinedProps, qb, fields) {
838
826
  const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => p.field === prop.name || p.all));
839
827
  const hasLazyFormulas = meta.props.some(p => p.lazy && p.formula);
840
- const requiresSQLConversion = meta.props.some(p => p.customType?.convertToJSValueSQL);
828
+ const requiresSQLConversion = meta.props.some(p => p.customType?.convertToJSValueSQL && p.persist !== false);
841
829
  const hasExplicitFields = !!fields;
842
830
  const ret = [];
843
831
  if (joinedProps.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/knex",
3
- "version": "5.8.9-dev.0",
3
+ "version": "5.8.9-dev.2",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -66,9 +66,9 @@
66
66
  "@mikro-orm/core": "^5.8.8"
67
67
  },
68
68
  "peerDependencies": {
69
- "@mikro-orm/core": "5.8.9-dev.0",
70
- "@mikro-orm/entity-generator": "5.8.9-dev.0",
71
- "@mikro-orm/migrations": "5.8.9-dev.0",
69
+ "@mikro-orm/core": "5.8.9-dev.2",
70
+ "@mikro-orm/entity-generator": "5.8.9-dev.2",
71
+ "@mikro-orm/migrations": "5.8.9-dev.2",
72
72
  "better-sqlite3": "*",
73
73
  "mssql": "*",
74
74
  "mysql": "*",
@@ -477,14 +477,25 @@ class QueryBuilder {
477
477
  await this.em?.storeCache(this._cache, cached, res);
478
478
  return res;
479
479
  }
480
- if (method === 'all' && Array.isArray(res)) {
480
+ if (method === 'run') {
481
+ return res;
482
+ }
483
+ const joinedProps = this.driver.joinedProps(meta, this._populate);
484
+ let mapped;
485
+ if (Array.isArray(res)) {
481
486
  const map = {};
482
- const mapped = res.map(r => this.driver.mapResult(r, meta, this._populate, this, map));
483
- await this.em?.storeCache(this._cache, cached, mapped);
484
- return mapped;
487
+ mapped = res.map(r => this.driver.mapResult(r, meta, this._populate, this, map));
488
+ if (joinedProps.length > 0) {
489
+ mapped = this.driver.mergeJoinedResult(mapped, this.mainAlias.metadata, joinedProps);
490
+ }
491
+ }
492
+ else {
493
+ mapped = [this.driver.mapResult(res, meta, joinedProps, this)];
485
494
  }
486
- const mapped = this.driver.mapResult(res, meta, this._populate, this);
487
495
  await this.em?.storeCache(this._cache, cached, mapped);
496
+ if (method === 'get') {
497
+ return mapped[0];
498
+ }
488
499
  return mapped;
489
500
  }
490
501
  /**
@@ -498,10 +509,7 @@ class QueryBuilder {
498
509
  */
499
510
  async getResultList() {
500
511
  await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.flushMode });
501
- let res = await this.execute('all', true);
502
- if (this._joinedProps.size > 0) {
503
- res = this.driver.mergeJoinedResult(res, this.mainAlias.metadata, [...this._joinedProps.values()]);
504
- }
512
+ const res = await this.execute('all', true);
505
513
  const entities = [];
506
514
  function propagatePopulateHint(entity, hint) {
507
515
  var _a;
@@ -725,7 +733,7 @@ class QueryBuilder {
725
733
  });
726
734
  const meta = this.mainAlias.metadata;
727
735
  /* istanbul ignore next */
728
- const requiresSQLConversion = meta?.props.filter(p => p.hasConvertToJSValueSQL) ?? [];
736
+ const requiresSQLConversion = meta?.props.filter(p => p.hasConvertToJSValueSQL && p.persist !== false) ?? [];
729
737
  if (this.flags.has(core_1.QueryFlag.CONVERT_CUSTOM_TYPES) && (fields.includes('*') || fields.includes(`${this.mainAlias.aliasName}.*`)) && requiresSQLConversion.length > 0) {
730
738
  requiresSQLConversion.forEach(p => ret.push(this.helper.mapper(p.name, this.type)));
731
739
  }
@@ -363,7 +363,9 @@ class SchemaComparator {
363
363
  log(`'comment' changed for column ${tableName}.${column1.name}`, { column1, column2 });
364
364
  changedProperties.add('comment');
365
365
  }
366
- if (this.diffEnumItems(column1.enumItems, column2.enumItems)) {
366
+ if (!(column1.mappedType instanceof core_1.ArrayType) &&
367
+ !(column2.mappedType instanceof core_1.ArrayType) &&
368
+ this.diffEnumItems(column1.enumItems, column2.enumItems)) {
367
369
  log(`'enumItems' changed for column ${tableName}.${column1.name}`, { column1, column2 });
368
370
  changedProperties.add('enumItems');
369
371
  }