@mikro-orm/core 7.1.9-dev.8 → 7.1.9
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.
|
@@ -834,7 +834,7 @@ export class MetadataDiscovery {
|
|
|
834
834
|
pivotMeta.properties[primaryProp.name] = primaryProp;
|
|
835
835
|
pivotMeta.compositePK = false;
|
|
836
836
|
}
|
|
837
|
-
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary: !
|
|
837
|
+
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary: !prop.fixedOrder, nullable: false });
|
|
838
838
|
this.initFieldName(discriminatorProp);
|
|
839
839
|
pivotMeta.properties[discriminatorColumn] = discriminatorProp;
|
|
840
840
|
const columnTypes = this.getPrimaryKeyColumnTypes(meta);
|
|
@@ -849,7 +849,7 @@ export class MetadataDiscovery {
|
|
|
849
849
|
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, columnTypes, [...prop.joinColumns], { type: meta.className, persist: false });
|
|
850
850
|
}
|
|
851
851
|
else {
|
|
852
|
-
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, columnTypes, [...prop.joinColumns], { type: meta.className, primary:
|
|
852
|
+
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, columnTypes, [...prop.joinColumns], { type: meta.className, primary: !prop.fixedOrder, nullable: false });
|
|
853
853
|
}
|
|
854
854
|
pivotMeta.properties[targetMeta.className + '_inverse'] = this.definePivotProperty(prop, targetMeta.className + '_inverse', targetMeta.class, prop.discriminator, false, false);
|
|
855
855
|
// Create virtual M:1 relation to the polymorphic owner for single-query join loading
|
|
@@ -871,11 +871,11 @@ export class MetadataDiscovery {
|
|
|
871
871
|
const discriminatorColumn = prop.discriminatorColumn;
|
|
872
872
|
const targets = prop.polymorphTargets;
|
|
873
873
|
pivotMeta.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.class, prop.discriminator, true, false);
|
|
874
|
-
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary:
|
|
874
|
+
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary: !prop.fixedOrder, nullable: false });
|
|
875
875
|
this.initFieldName(discriminatorProp);
|
|
876
876
|
pivotMeta.properties[discriminatorColumn] = discriminatorProp;
|
|
877
877
|
const firstTargetColumnTypes = this.getPrimaryKeyColumnTypes(targets[0]);
|
|
878
|
-
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, firstTargetColumnTypes, [...prop.inverseJoinColumns], { type: targets[0].className, primary:
|
|
878
|
+
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, firstTargetColumnTypes, [...prop.inverseJoinColumns], { type: targets[0].className, primary: !prop.fixedOrder, nullable: false });
|
|
879
879
|
pivotMeta.polymorphicDiscriminatorMap ??= {};
|
|
880
880
|
for (const targetMeta of targets) {
|
|
881
881
|
const relationName = `${prop.discriminator}_${targetMeta.tableName}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.1.9
|
|
3
|
+
"version": "7.1.9",
|
|
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",
|
|
@@ -29,15 +29,18 @@ export class ChangeSet {
|
|
|
29
29
|
else {
|
|
30
30
|
this.primaryKey = this.originalEntity[this.meta.primaryKeys[0]];
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
32
|
+
const primaryProp = this.meta.getPrimaryProp();
|
|
33
|
+
const relationPK = !this.meta.compositePK && !!primaryProp.targetMeta?.compositePK;
|
|
34
|
+
// arrays are already the ordered tuple of the target's primary keys
|
|
35
|
+
if (relationPK && Utils.isPlainObject(this.primaryKey)) {
|
|
36
|
+
const pk = this.primaryKey;
|
|
37
|
+
this.primaryKey = primaryProp.targetMeta.primaryKeys.map(childPK => pk[childPK]);
|
|
39
38
|
}
|
|
40
39
|
if (object && this.primaryKey != null) {
|
|
40
|
+
// the whole tuple belongs to the single relation PK, it must not be spread over the (single) PK prop
|
|
41
|
+
if (relationPK) {
|
|
42
|
+
return { [primaryProp.name]: this.primaryKey };
|
|
43
|
+
}
|
|
41
44
|
return Utils.primaryKeyToObject(this.meta, this.primaryKey);
|
|
42
45
|
}
|
|
43
46
|
return this.primaryKey ?? null;
|
|
@@ -3,7 +3,7 @@ import { PolymorphicRef } from '../entity/PolymorphicRef.js';
|
|
|
3
3
|
import { helper } from '../entity/wrap.js';
|
|
4
4
|
import { ChangeSetType } from './ChangeSet.js';
|
|
5
5
|
import { isRaw } from '../utils/RawQueryFragment.js';
|
|
6
|
-
import { Utils } from '../utils/Utils.js';
|
|
6
|
+
import { equals, Utils } from '../utils/Utils.js';
|
|
7
7
|
import { OptimisticLockError, ValidationError } from '../errors.js';
|
|
8
8
|
import { ReferenceKind } from '../enums.js';
|
|
9
9
|
/** @internal Executes change sets against the database, handling inserts, updates, and deletes. */
|
|
@@ -237,7 +237,8 @@ export class ChangeSetPersister {
|
|
|
237
237
|
for (const changeSet of changeSets) {
|
|
238
238
|
if (res.rows) {
|
|
239
239
|
const row = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
|
|
240
|
-
|
|
240
|
+
// STI batches can mix child types, so map through the change set's own metadata
|
|
241
|
+
this.mapReturnedValues(changeSet.entity, changeSet.payload, row, changeSet.meta);
|
|
241
242
|
}
|
|
242
243
|
changeSet.persisted = true;
|
|
243
244
|
}
|
|
@@ -337,7 +338,8 @@ export class ChangeSetPersister {
|
|
|
337
338
|
});
|
|
338
339
|
const res = await this.#driver.find(meta.root.class, { $or }, options);
|
|
339
340
|
if (res.length !== changeSets.length) {
|
|
340
|
-
|
|
341
|
+
// a FK pointing to a composite PK is an array, so the values need to be compared deeply
|
|
342
|
+
const compare = (a, b, keys) => keys.every(k => equals(a[k], b[k]));
|
|
341
343
|
const entity = changeSets.find(cs => {
|
|
342
344
|
return !res.some(row => compare(Utils.getPrimaryKeyCond(cs.entity, primaryKeys), row, primaryKeys));
|
|
343
345
|
}).entity;
|
|
@@ -378,7 +380,8 @@ export class ChangeSetPersister {
|
|
|
378
380
|
changeSets.forEach(cs => {
|
|
379
381
|
Utils.keys(cs.payload).forEach(k => {
|
|
380
382
|
if (isRaw(cs.payload[k]) && isRaw(cs.entity[k])) {
|
|
381
|
-
|
|
383
|
+
// STI batches can mix child types, so the property might not exist on `meta`
|
|
384
|
+
returning.add(cs.meta.properties[k]);
|
|
382
385
|
}
|
|
383
386
|
});
|
|
384
387
|
});
|
|
@@ -403,12 +406,14 @@ export class ChangeSetPersister {
|
|
|
403
406
|
options = this.prepareOptions(meta, options, {
|
|
404
407
|
fields: Utils.unique(reloadProps.map(prop => prop.name)),
|
|
405
408
|
});
|
|
406
|
-
|
|
409
|
+
// a mixed STI batch shares one table but the child discriminator would filter out the siblings
|
|
410
|
+
const target = changeSets.some(cs => cs.meta !== meta) && meta.root.discriminatorColumn ? meta.root : meta;
|
|
411
|
+
const data = await this.#driver.find(target.class, { [pk]: { $in: pks } }, options);
|
|
407
412
|
const map = new Map();
|
|
408
413
|
data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, false, this.#platform, true), item));
|
|
409
414
|
for (const changeSet of changeSets) {
|
|
410
415
|
const data = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
|
|
411
|
-
this.#hydrator.hydrate(changeSet.entity, meta, data, this.#factory, 'full', false, true);
|
|
416
|
+
this.#hydrator.hydrate(changeSet.entity, changeSet.meta, data, this.#factory, 'full', false, true);
|
|
412
417
|
Object.assign(changeSet.payload, data); // merge to the changeset payload, so it gets saved to the entity snapshot
|
|
413
418
|
}
|
|
414
419
|
}
|
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.1.9
|
|
156
|
+
static #ORM_VERSION = '7.1.9';
|
|
157
157
|
/**
|
|
158
158
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
159
159
|
*/
|
|
@@ -462,7 +462,9 @@ export class Utils {
|
|
|
462
462
|
}
|
|
463
463
|
static getPrimaryKeyCond(entity, primaryKeys) {
|
|
464
464
|
const cond = primaryKeys.reduce((o, pk) => {
|
|
465
|
-
|
|
465
|
+
const value = entity[pk];
|
|
466
|
+
// FKs pointing to a composite PK are arrays, which `extractPK` rejects
|
|
467
|
+
o[pk] = Utils.isPrimaryKey(value, true) ? value : Utils.extractPK(value);
|
|
466
468
|
return o;
|
|
467
469
|
}, {});
|
|
468
470
|
if (Object.values(cond).some(v => v === null)) {
|