@mikro-orm/sql 7.2.4-dev.9 → 7.2.4

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.
@@ -1011,16 +1011,23 @@ export class AbstractSqlDriver extends DatabaseDriver {
1011
1011
  const meta = this.metadata.get(entityName);
1012
1012
  if (options.upsert) {
1013
1013
  if (meta.tptParent) {
1014
+ // the parent table reports a single insertId per batch, the EM sends such rows one by one
1015
+ if (where.filter(cond => Utils.isEmpty(cond)).length > 1) {
1016
+ throw new Error(`Cannot upsert more than one ${meta.className} row without a unique value in one batch`);
1017
+ }
1014
1018
  // TPT parent tables go first, the PK they provide is the conflict target of this table
1015
- await this.nativeUpdateMany(meta.tptParent.class, where, data, options);
1019
+ const res = await this.nativeUpdateMany(meta.tptParent.class, where, data, options);
1016
1020
  for (const [i, row] of data.entries()) {
1017
1021
  if (meta.primaryKeys.some(pk => row[pk] == null)) {
1018
- const found = await this.findOne(meta.tptParent.class, where[i], {
1019
- fields: meta.primaryKeys,
1020
- ctx: options.ctx,
1021
- connectionType: 'write',
1022
- schema: options.schema,
1023
- });
1022
+ // a row without a condition cannot conflict, only the insert knows its PK
1023
+ const found = Utils.isEmpty(where[i])
1024
+ ? { [meta.primaryKeys[0]]: res.insertId }
1025
+ : await this.findOne(meta.tptParent.class, where[i], {
1026
+ fields: meta.primaryKeys,
1027
+ ctx: options.ctx,
1028
+ connectionType: 'write',
1029
+ schema: options.schema,
1030
+ });
1024
1031
  meta.primaryKeys.forEach(pk => (row[pk] = found?.[pk]));
1025
1032
  }
1026
1033
  }
@@ -1040,7 +1047,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
1040
1047
  data = data.map(row => Object.fromEntries(Object.entries(row).filter(([key]) => own(key))));
1041
1048
  options.onConflictMergeFields = options.onConflictMergeFields?.filter(f => own(f));
1042
1049
  options.onConflictExcludeFields = options.onConflictExcludeFields?.filter(f => own(f));
1043
- returning = [];
1050
+ returning = this.getPrimaryKeyFields(meta);
1044
1051
  }
1045
1052
  qb.insert(data)
1046
1053
  .onConflict(uniqueFields)
@@ -1056,7 +1063,12 @@ export class AbstractSqlDriver extends DatabaseDriver {
1056
1063
  qb.where(options.onConflictWhere);
1057
1064
  }
1058
1065
  const res = await this.rethrow(qb.execute('run', false));
1059
- return meta.inheritanceType === 'tpt' ? { ...res, row: undefined, rows: [] } : res;
1066
+ if (meta.inheritanceType === 'tpt') {
1067
+ // child tables do not generate the PK, so every table of the hierarchy reports the one of its first row
1068
+ const insertId = data[0][meta.primaryKeys[0]] ?? res.insertId ?? res.row?.[returning[0]];
1069
+ return { ...res, insertId, row: undefined, rows: [] };
1070
+ }
1071
+ return res;
1060
1072
  }
1061
1073
  const collections = options.processCollections ? data.map(d => this.extractManyToMany(meta, d)) : [];
1062
1074
  const keys = new Set();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.2.4-dev.9",
3
+ "version": "7.2.4",
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
  "keywords": [
6
6
  "data-mapper",
@@ -50,10 +50,10 @@
50
50
  "kysely": "0.29.6"
51
51
  },
52
52
  "devDependencies": {
53
- "@mikro-orm/core": "^7.2.3"
53
+ "@mikro-orm/core": "^7.2.4"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mikro-orm/core": "7.2.4-dev.9"
56
+ "@mikro-orm/core": "7.2.4"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"