@mikro-orm/core 7.2.2-dev.15 → 7.2.2-dev.17
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/EntityManager.d.ts +5 -0
- package/EntityManager.js +33 -22
- package/package.json +1 -1
- package/unit-of-work/UnitOfWork.js +4 -1
- package/utils/Utils.js +1 -1
package/EntityManager.d.ts
CHANGED
|
@@ -580,6 +580,11 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
580
580
|
* Checks whether this EntityManager is currently operating inside a database transaction.
|
|
581
581
|
*/
|
|
582
582
|
isInTransaction(): boolean;
|
|
583
|
+
/**
|
|
584
|
+
* Checks whether transactions are disabled for this EntityManager.
|
|
585
|
+
* @internal
|
|
586
|
+
*/
|
|
587
|
+
isTransactionDisabled(): boolean;
|
|
583
588
|
/**
|
|
584
589
|
* Gets the transaction context (driver dependent object used to make sure queries are executed on same connection).
|
|
585
590
|
*/
|
package/EntityManager.js
CHANGED
|
@@ -1134,9 +1134,10 @@ export class EntityManager {
|
|
|
1134
1134
|
const generatedFields = new Set();
|
|
1135
1135
|
const allData = [];
|
|
1136
1136
|
const allWhere = [];
|
|
1137
|
+
const dataIndexes = [];
|
|
1138
|
+
const result = [];
|
|
1137
1139
|
const entities = new Map();
|
|
1138
1140
|
const entitiesByData = new Map();
|
|
1139
|
-
const entitiesByAllDataIdx = new Map();
|
|
1140
1141
|
for (let i = 0; i < data.length; i++) {
|
|
1141
1142
|
let row = data[i];
|
|
1142
1143
|
let where;
|
|
@@ -1144,14 +1145,12 @@ export class EntityManager {
|
|
|
1144
1145
|
const entity = row;
|
|
1145
1146
|
if (helper(entity).__managed && helper(entity).__em === em && !this.config.get('upsertManaged')) {
|
|
1146
1147
|
em.#entityFactory.mergeData(meta, entity, row, { initialized: true });
|
|
1147
|
-
|
|
1148
|
-
entitiesByData.set(row, entity);
|
|
1148
|
+
result[i] = entity;
|
|
1149
1149
|
continue;
|
|
1150
1150
|
}
|
|
1151
1151
|
where = helper(entity).getPrimaryKey();
|
|
1152
1152
|
getOnCreateGeneratedFields(meta, entity).forEach(field => generatedFields.add(field));
|
|
1153
1153
|
em.#entityFactory.assignDefaultValues(entity, meta);
|
|
1154
|
-
entitiesByAllDataIdx.set(allData.length, entity);
|
|
1155
1154
|
row = em.#comparator.prepareEntity(entity);
|
|
1156
1155
|
}
|
|
1157
1156
|
else {
|
|
@@ -1161,8 +1160,7 @@ export class EntityManager {
|
|
|
1161
1160
|
const exists = em.#unitOfWork.getById(entityName, where, options.schema);
|
|
1162
1161
|
if (exists) {
|
|
1163
1162
|
em.assign(exists, row);
|
|
1164
|
-
|
|
1165
|
-
entitiesByData.set(row, exists);
|
|
1163
|
+
result[i] = exists;
|
|
1166
1164
|
continue;
|
|
1167
1165
|
}
|
|
1168
1166
|
}
|
|
@@ -1195,22 +1193,25 @@ export class EntityManager {
|
|
|
1195
1193
|
validateParams(row, 'insert data');
|
|
1196
1194
|
allData.push(row);
|
|
1197
1195
|
allWhere.push(where);
|
|
1196
|
+
dataIndexes.push(i);
|
|
1198
1197
|
}
|
|
1199
|
-
if (
|
|
1200
|
-
return [...
|
|
1198
|
+
if (allData.length === 0) {
|
|
1199
|
+
return [...new Set(result)];
|
|
1201
1200
|
}
|
|
1202
1201
|
// `onCreate` generated values are for the insert clause only, they must not overwrite existing rows
|
|
1203
1202
|
if (generatedFields.size > 0 && !options.onConflictMergeFields) {
|
|
1204
1203
|
options.onConflictExcludeFields = [...(options.onConflictExcludeFields ?? []), ...generatedFields];
|
|
1205
1204
|
}
|
|
1206
1205
|
if (em.eventManager.hasListeners(EventType.beforeUpsert, meta)) {
|
|
1207
|
-
for (const
|
|
1208
|
-
const entity =
|
|
1206
|
+
for (const index of dataIndexes) {
|
|
1207
|
+
const entity = data[index];
|
|
1209
1208
|
await em.eventManager.dispatchEvent(EventType.beforeUpsert, { entity, em, meta }, meta);
|
|
1210
1209
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1210
|
+
dataIndexes.forEach((index, idx) => {
|
|
1211
|
+
if (Utils.isEntity(data[index])) {
|
|
1212
|
+
allData[idx] = em.#comparator.prepareEntity(data[index]);
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1214
1215
|
}
|
|
1215
1216
|
const res = await em.withSessionContext(options.ctx ?? em.#transactionContext, ctx => em.driver.nativeUpdateMany(entityName, allWhere, allData, {
|
|
1216
1217
|
upsert: true,
|
|
@@ -1218,15 +1219,16 @@ export class EntityManager {
|
|
|
1218
1219
|
...options,
|
|
1219
1220
|
ctx,
|
|
1220
1221
|
}));
|
|
1221
|
-
entities.clear();
|
|
1222
|
-
entitiesByData.clear();
|
|
1223
1222
|
const loadPK = new Map();
|
|
1224
1223
|
allData.forEach((row, i) => {
|
|
1225
|
-
|
|
1224
|
+
// Managed inputs skipped by the SQL batch still occupy positions in `data`.
|
|
1225
|
+
const index = dataIndexes[i];
|
|
1226
|
+
const item = data[index];
|
|
1227
|
+
em.#unitOfWork.getChangeSetPersister().mapReturnedValues(Utils.isEntity(item) ? item : null, Utils.isEntity(item) ? {} : item,
|
|
1226
1228
|
// A suppressed conflict omits its row; positional mapping would hydrate a different entity.
|
|
1227
1229
|
res.rows?.length === allData.length ? res.rows[i] : undefined, meta, true);
|
|
1228
|
-
const entity = Utils.isEntity(
|
|
1229
|
-
?
|
|
1230
|
+
const entity = Utils.isEntity(item)
|
|
1231
|
+
? item
|
|
1230
1232
|
: em.#entityFactory.create(entityName, row, {
|
|
1231
1233
|
refresh: true,
|
|
1232
1234
|
initialized: true,
|
|
@@ -1237,18 +1239,19 @@ export class EntityManager {
|
|
|
1237
1239
|
}
|
|
1238
1240
|
entities.set(entity, row);
|
|
1239
1241
|
entitiesByData.set(row, entity);
|
|
1242
|
+
result[index] = entity;
|
|
1240
1243
|
});
|
|
1241
1244
|
// skip the reload only when RETURNING brought back a row for every input
|
|
1242
1245
|
// (onConflictWhere can suppress writes, leaving some rows out)
|
|
1243
1246
|
// oxfmt-ignore
|
|
1244
1247
|
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(allWhere[0]) ? Object.keys(allWhere[0]).flatMap(key => Utils.splitPrimaryKeys(key)) : meta.primaryKeys);
|
|
1245
1248
|
const platform = this.getPlatform();
|
|
1246
|
-
const returning = getOnConflictReturningFields(meta, data[0], uniqueFields, options, platform);
|
|
1249
|
+
const returning = getOnConflictReturningFields(meta, data[dataIndexes[0]], uniqueFields, options, platform);
|
|
1247
1250
|
if (options.onConflictWhere && res.rows?.length !== allData.length) {
|
|
1248
1251
|
returning.push(...meta.comparableProps.filter(p => !p.lazy && !p.embeddable).map(p => p.name));
|
|
1249
1252
|
}
|
|
1250
1253
|
const reloadFields = returning.length > 0 &&
|
|
1251
|
-
!((platform.usesReturningStatement() || platform.usesOutputStatement()) && res.rows?.length ===
|
|
1254
|
+
!((platform.usesReturningStatement() || platform.usesOutputStatement()) && res.rows?.length === allData.length);
|
|
1252
1255
|
if (options.onConflictAction === 'ignore' || (!res.rows?.length && loadPK.size > 0) || reloadFields) {
|
|
1253
1256
|
const unique = meta.hydrateProps.filter(p => !p.lazy).map(p => p.name);
|
|
1254
1257
|
const add = new Set(propIndex !== false && propIndex >= 0
|
|
@@ -1258,7 +1261,8 @@ export class EntityManager {
|
|
|
1258
1261
|
Utils.keys(cond).forEach(key => add.add(key));
|
|
1259
1262
|
}
|
|
1260
1263
|
const where = { $or: [] };
|
|
1261
|
-
|
|
1264
|
+
dataIndexes.forEach((index, idx) => {
|
|
1265
|
+
const item = data[index];
|
|
1262
1266
|
where.$or[idx] = {};
|
|
1263
1267
|
const props = Array.isArray(uniqueFields) ? uniqueFields : Object.keys(item);
|
|
1264
1268
|
props.forEach(prop => {
|
|
@@ -1328,7 +1332,7 @@ export class EntityManager {
|
|
|
1328
1332
|
await em.eventManager.dispatchEvent(EventType.afterUpsert, { entity, em, meta }, meta);
|
|
1329
1333
|
}
|
|
1330
1334
|
}
|
|
1331
|
-
return [...
|
|
1335
|
+
return [...new Set(result)];
|
|
1332
1336
|
}
|
|
1333
1337
|
/**
|
|
1334
1338
|
* Runs your callback wrapped inside a database transaction.
|
|
@@ -1985,6 +1989,13 @@ export class EntityManager {
|
|
|
1985
1989
|
isInTransaction() {
|
|
1986
1990
|
return !!this.getContext(false).#transactionContext;
|
|
1987
1991
|
}
|
|
1992
|
+
/**
|
|
1993
|
+
* Checks whether transactions are disabled for this EntityManager.
|
|
1994
|
+
* @internal
|
|
1995
|
+
*/
|
|
1996
|
+
isTransactionDisabled() {
|
|
1997
|
+
return !!this.getContext(false).#disableTransactions;
|
|
1998
|
+
}
|
|
1988
1999
|
/**
|
|
1989
2000
|
* Gets the transaction context (driver dependent object used to make sure queries are executed on same connection).
|
|
1990
2001
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.2.2-dev.
|
|
3
|
+
"version": "7.2.2-dev.17",
|
|
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",
|
|
@@ -467,7 +467,10 @@ export class UnitOfWork {
|
|
|
467
467
|
}
|
|
468
468
|
const groups = this.getChangeSetGroups();
|
|
469
469
|
const platform = this.#em.getPlatform();
|
|
470
|
-
const runInTransaction = !this.#em.isInTransaction() &&
|
|
470
|
+
const runInTransaction = !this.#em.isInTransaction() &&
|
|
471
|
+
!this.#em.isTransactionDisabled() &&
|
|
472
|
+
platform.supportsTransactions() &&
|
|
473
|
+
this.#em.config.get('implicitTransactions');
|
|
471
474
|
if (runInTransaction) {
|
|
472
475
|
const loggerContext = Utils.merge({ id: this.#em._id }, this.#em.getLoggerContext({ disableContextResolution: true }));
|
|
473
476
|
await this.#em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
|
package/utils/Utils.js
CHANGED
|
@@ -153,7 +153,7 @@ export function parseJsonSafe(value) {
|
|
|
153
153
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
154
154
|
export class Utils {
|
|
155
155
|
static PK_SEPARATOR = '~~~';
|
|
156
|
-
static #ORM_VERSION = '7.2.2-dev.
|
|
156
|
+
static #ORM_VERSION = '7.2.2-dev.17';
|
|
157
157
|
/** Default session variable name backing an RLS filter argument (`current_setting('mikro.<filter>.<arg>')`). */
|
|
158
158
|
static getRlsSettingName(filterName, argName) {
|
|
159
159
|
return `mikro.${filterName}.${argName}`;
|