@mikro-orm/core 7.0.0-dev.9 → 7.0.0-dev.91
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 +77 -48
- package/EntityManager.js +288 -225
- package/MikroORM.d.ts +40 -31
- package/MikroORM.js +98 -137
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +6 -5
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +11 -7
- package/connections/Connection.js +16 -14
- package/drivers/DatabaseDriver.d.ts +11 -5
- package/drivers/DatabaseDriver.js +23 -11
- package/drivers/IDatabaseDriver.d.ts +25 -4
- package/entity/BaseEntity.d.ts +0 -1
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +95 -30
- package/entity/Collection.js +432 -93
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +17 -9
- package/entity/EntityFactory.d.ts +7 -0
- package/entity/EntityFactory.js +63 -41
- package/entity/EntityHelper.js +26 -12
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +63 -38
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/Reference.d.ts +6 -5
- package/entity/Reference.js +34 -9
- package/entity/WrappedEntity.d.ts +2 -7
- package/entity/WrappedEntity.js +2 -7
- package/entity/defineEntity.d.ts +568 -0
- package/entity/defineEntity.js +529 -0
- package/entity/index.d.ts +3 -2
- package/entity/index.js +3 -2
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +16 -4
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/enums.d.ts +21 -6
- package/enums.js +14 -1
- package/errors.d.ts +10 -2
- package/errors.js +29 -10
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +19 -11
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +35 -25
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +1 -0
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/index.d.ts +1 -0
- package/logging/index.js +1 -0
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +16 -0
- package/metadata/EntitySchema.d.ts +9 -13
- package/metadata/EntitySchema.js +44 -26
- package/metadata/MetadataDiscovery.d.ts +6 -9
- package/metadata/MetadataDiscovery.js +165 -205
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +44 -2
- package/metadata/MetadataStorage.d.ts +1 -6
- package/metadata/MetadataStorage.js +6 -18
- package/metadata/MetadataValidator.d.ts +0 -7
- package/metadata/MetadataValidator.js +0 -10
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +480 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
- package/naming-strategy/AbstractNamingStrategy.js +8 -2
- package/naming-strategy/NamingStrategy.d.ts +11 -1
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +18 -10
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +6 -13
- package/platforms/Platform.js +15 -41
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +32 -14
- package/serialization/EntityTransformer.js +22 -12
- package/serialization/SerializationContext.js +16 -13
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +2 -3
- package/types/BigIntType.d.ts +8 -6
- package/types/BigIntType.js +1 -1
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +2 -1
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +3 -3
- package/types/DoubleType.js +2 -2
- package/types/EnumArrayType.js +1 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -4
- package/types/Type.js +3 -3
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +109 -73
- package/typings.js +38 -35
- package/unit-of-work/ChangeSet.d.ts +0 -3
- package/unit-of-work/ChangeSet.js +2 -2
- package/unit-of-work/ChangeSetComputer.d.ts +1 -3
- package/unit-of-work/ChangeSetComputer.js +11 -9
- package/unit-of-work/ChangeSetPersister.d.ts +5 -4
- package/unit-of-work/ChangeSetPersister.js +51 -19
- package/unit-of-work/UnitOfWork.d.ts +8 -1
- package/unit-of-work/UnitOfWork.js +91 -49
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +11 -9
- package/utils/Configuration.d.ts +757 -206
- package/utils/Configuration.js +140 -188
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +0 -3
- package/utils/Cursor.js +6 -3
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +54 -8
- package/utils/EntityComparator.d.ts +8 -4
- package/utils/EntityComparator.js +52 -17
- package/utils/QueryHelper.d.ts +9 -1
- package/utils/QueryHelper.js +70 -9
- package/utils/RawQueryFragment.d.ts +36 -13
- package/utils/RawQueryFragment.js +36 -16
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +9 -97
- package/utils/Utils.js +83 -302
- package/utils/clone.js +2 -3
- package/utils/env-vars.d.ts +3 -0
- package/utils/env-vars.js +87 -0
- package/utils/fs-utils.d.ts +12 -0
- package/utils/fs-utils.js +97 -0
- package/utils/index.d.ts +2 -1
- package/utils/index.js +2 -1
- package/utils/upsert-utils.d.ts +7 -2
- package/utils/upsert-utils.js +55 -4
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -13
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -32
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -11
- package/decorators/Embedded.d.ts +0 -18
- package/decorators/Embedded.js +0 -18
- package/decorators/Entity.d.ts +0 -18
- package/decorators/Entity.js +0 -12
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -16
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -8
- package/decorators/Formula.d.ts +0 -4
- package/decorators/Formula.js +0 -15
- package/decorators/Indexed.d.ts +0 -19
- package/decorators/Indexed.js +0 -20
- package/decorators/ManyToMany.d.ts +0 -40
- package/decorators/ManyToMany.js +0 -14
- package/decorators/ManyToOne.d.ts +0 -30
- package/decorators/ManyToOne.js +0 -14
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -17
- package/decorators/OneToOne.d.ts +0 -24
- package/decorators/OneToOne.js +0 -7
- package/decorators/PrimaryKey.d.ts +0 -8
- package/decorators/PrimaryKey.js +0 -20
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -32
- package/decorators/Transactional.d.ts +0 -13
- package/decorators/Transactional.js +0 -28
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -47
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -17
- package/entity/ArrayCollection.d.ts +0 -116
- package/entity/ArrayCollection.js +0 -402
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -150
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -44
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -28
|
@@ -20,9 +20,9 @@ export class EntityComparator {
|
|
|
20
20
|
/**
|
|
21
21
|
* Computes difference between two entities.
|
|
22
22
|
*/
|
|
23
|
-
diffEntities(entityName, a, b) {
|
|
23
|
+
diffEntities(entityName, a, b, options) {
|
|
24
24
|
const comparator = this.getEntityComparator(entityName);
|
|
25
|
-
return Utils.callCompiledFunction(comparator, a, b);
|
|
25
|
+
return Utils.callCompiledFunction(comparator, a, b, options);
|
|
26
26
|
}
|
|
27
27
|
matching(entityName, a, b) {
|
|
28
28
|
const diff = this.diffEntities(entityName, a, b);
|
|
@@ -48,7 +48,7 @@ export class EntityComparator {
|
|
|
48
48
|
*/
|
|
49
49
|
getPkGetter(meta) {
|
|
50
50
|
const exists = this.pkGetters.get(meta.className);
|
|
51
|
-
/* v8 ignore next
|
|
51
|
+
/* v8 ignore next */
|
|
52
52
|
if (exists) {
|
|
53
53
|
return exists;
|
|
54
54
|
}
|
|
@@ -98,7 +98,7 @@ export class EntityComparator {
|
|
|
98
98
|
*/
|
|
99
99
|
getPkGetterConverted(meta) {
|
|
100
100
|
const exists = this.pkGettersConverted.get(meta.className);
|
|
101
|
-
/* v8 ignore next
|
|
101
|
+
/* v8 ignore next */
|
|
102
102
|
if (exists) {
|
|
103
103
|
return exists;
|
|
104
104
|
}
|
|
@@ -148,13 +148,14 @@ export class EntityComparator {
|
|
|
148
148
|
*/
|
|
149
149
|
getPkSerializer(meta) {
|
|
150
150
|
const exists = this.pkSerializers.get(meta.className);
|
|
151
|
-
/* v8 ignore next
|
|
151
|
+
/* v8 ignore next */
|
|
152
152
|
if (exists) {
|
|
153
153
|
return exists;
|
|
154
154
|
}
|
|
155
155
|
const lines = [];
|
|
156
156
|
const context = new Map();
|
|
157
157
|
context.set('getCompositeKeyValue', (val) => Utils.flatten(Utils.getCompositeKeyValue(val, meta, 'convertToDatabaseValue', this.platform)));
|
|
158
|
+
context.set('getPrimaryKeyHash', (val) => Utils.getPrimaryKeyHash(Utils.asArray(val)));
|
|
158
159
|
if (meta.primaryKeys.length > 1) {
|
|
159
160
|
lines.push(` const pks = entity.__helper.__pk ? getCompositeKeyValue(entity.__helper.__pk) : [`);
|
|
160
161
|
meta.primaryKeys.forEach(pk => {
|
|
@@ -170,14 +171,23 @@ export class EntityComparator {
|
|
|
170
171
|
}
|
|
171
172
|
else {
|
|
172
173
|
const pk = meta.primaryKeys[0];
|
|
173
|
-
|
|
174
|
+
const prop = meta.properties[pk];
|
|
175
|
+
if (prop.kind !== ReferenceKind.SCALAR) {
|
|
174
176
|
lines.push(` if (entity${this.wrap(pk)} != null && (entity${this.wrap(pk)}.__entity || entity${this.wrap(pk)}.__reference)) return entity${this.wrap(pk)}.__helper.getSerializedPrimaryKey();`);
|
|
175
177
|
}
|
|
176
178
|
const serializedPrimaryKey = meta.props.find(p => p.serializedPrimaryKey);
|
|
177
179
|
if (serializedPrimaryKey) {
|
|
178
180
|
lines.push(` return '' + entity.${serializedPrimaryKey.name};`);
|
|
179
181
|
}
|
|
180
|
-
|
|
182
|
+
else if (prop.customType) {
|
|
183
|
+
const convertorKey = this.registerCustomType(meta.properties[pk], context);
|
|
184
|
+
const idx = this.tmpIndex++;
|
|
185
|
+
lines.push(` const val_${idx} = convertToDatabaseValue_${convertorKey}(entity${this.wrap(pk)});`);
|
|
186
|
+
lines.push(` return getPrimaryKeyHash(val_${idx});`);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
lines.push(` return '' + entity${this.wrap(pk)};`);
|
|
190
|
+
}
|
|
181
191
|
}
|
|
182
192
|
const code = `// compiled pk serializer for entity ${meta.className}\n`
|
|
183
193
|
+ `return function(entity) {\n${lines.join('\n')}\n}`;
|
|
@@ -189,6 +199,7 @@ export class EntityComparator {
|
|
|
189
199
|
* @internal Highly performance-sensitive method.
|
|
190
200
|
*/
|
|
191
201
|
getSnapshotGenerator(entityName) {
|
|
202
|
+
entityName = Utils.className(entityName);
|
|
192
203
|
const exists = this.snapshotGenerators.get(entityName);
|
|
193
204
|
if (exists) {
|
|
194
205
|
return exists;
|
|
@@ -274,10 +285,14 @@ export class EntityComparator {
|
|
|
274
285
|
lines.push(`${padding} if (${value} == null || ${value} instanceof Date) {`);
|
|
275
286
|
lines.push(`${padding} ${key} = ${value};`);
|
|
276
287
|
if (!tz || tz === 'local') {
|
|
288
|
+
lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
|
|
289
|
+
lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
|
|
277
290
|
lines.push(`${padding} } else {`);
|
|
278
291
|
lines.push(`${padding} ${key} = parseDate(${value});`);
|
|
279
292
|
}
|
|
280
293
|
else {
|
|
294
|
+
lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
|
|
295
|
+
lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
|
|
281
296
|
lines.push(`${padding} } else if (typeof ${value} === 'number' || ${value}.includes('+') || ${value}.lastIndexOf('-') > 10 || ${value}.endsWith('Z')) {`);
|
|
282
297
|
lines.push(`${padding} ${key} = parseDate(${value});`);
|
|
283
298
|
lines.push(`${padding} } else {`);
|
|
@@ -352,7 +367,7 @@ export class EntityComparator {
|
|
|
352
367
|
else {
|
|
353
368
|
mapEntityProperties(meta);
|
|
354
369
|
}
|
|
355
|
-
lines.push(` for (let k in result) { if (Object.hasOwn(result, k) && !mapped[k]) ret[k] = result[k]; }`);
|
|
370
|
+
lines.push(` for (let k in result) { if (Object.hasOwn(result, k) && !mapped[k] && ret[k] === undefined) ret[k] = result[k]; }`);
|
|
356
371
|
const code = `// compiled mapper for entity ${meta.className}\n`
|
|
357
372
|
+ `return function(result) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
|
|
358
373
|
const resultMapper = Utils.createFunction(context, code);
|
|
@@ -407,11 +422,21 @@ export class EntityComparator {
|
|
|
407
422
|
}
|
|
408
423
|
getEmbeddedPropertySnapshot(meta, prop, context, level, path, dataKey, object = prop.object) {
|
|
409
424
|
const padding = ' '.repeat(level * 2);
|
|
425
|
+
const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
|
|
410
426
|
let ret = `${level === 1 ? '' : '\n'}`;
|
|
411
427
|
if (object) {
|
|
412
|
-
const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
|
|
413
428
|
ret += `${padding}if (${nullCond}) ret${dataKey} = null;\n`;
|
|
414
429
|
}
|
|
430
|
+
else {
|
|
431
|
+
ret += `${padding}if (${nullCond}) {\n`;
|
|
432
|
+
ret += meta.props.filter(p => p.embedded?.[0] === prop.name
|
|
433
|
+
// object for JSON embeddable
|
|
434
|
+
&& (p.object || (p.persist !== false))).map(childProp => {
|
|
435
|
+
const childDataKey = meta.embeddable || prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
|
|
436
|
+
return `${padding} ret${childDataKey} = null;`;
|
|
437
|
+
}).join('\n') + `\n`;
|
|
438
|
+
ret += `${padding}}\n`;
|
|
439
|
+
}
|
|
415
440
|
const cond = `entity${path.map(k => this.wrap(k)).join('')} != null`;
|
|
416
441
|
ret += `${padding}if (${cond}) {\n`;
|
|
417
442
|
if (object) {
|
|
@@ -456,7 +481,7 @@ export class EntityComparator {
|
|
|
456
481
|
registerCustomType(prop, context) {
|
|
457
482
|
const convertorKey = this.safeKey(prop.name);
|
|
458
483
|
context.set(`convertToDatabaseValue_${convertorKey}`, (val) => {
|
|
459
|
-
/* v8 ignore next
|
|
484
|
+
/* v8 ignore next */
|
|
460
485
|
if (RawQueryFragment.isKnownFragment(val)) {
|
|
461
486
|
return val;
|
|
462
487
|
}
|
|
@@ -531,17 +556,27 @@ export class EntityComparator {
|
|
|
531
556
|
context.set('compareBuffers', compareBuffers);
|
|
532
557
|
context.set('compareObjects', compareObjects);
|
|
533
558
|
context.set('equals', equals);
|
|
534
|
-
meta.comparableProps
|
|
559
|
+
for (const prop of meta.comparableProps) {
|
|
535
560
|
lines.push(this.getPropertyComparator(prop, context));
|
|
536
|
-
}
|
|
561
|
+
}
|
|
562
|
+
// also compare 1:1 inverse sides, important for `factory.mergeData`
|
|
563
|
+
lines.push(`if (options?.includeInverseSides) {`);
|
|
564
|
+
for (const prop of meta.bidirectionalRelations) {
|
|
565
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner && prop.hydrate !== false) {
|
|
566
|
+
lines.push(this.getPropertyComparator(prop, context));
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
lines.push(`}`);
|
|
537
570
|
const code = `// compiled comparator for entity ${meta.className}\n`
|
|
538
|
-
+ `return function(last, current) {\n const diff = {};\n${lines.join('\n')}\n return diff;\n}`;
|
|
571
|
+
+ `return function(last, current, options) {\n const diff = {};\n${lines.join('\n')}\n return diff;\n}`;
|
|
539
572
|
const comparator = Utils.createFunction(context, code);
|
|
540
573
|
this.comparators.set(entityName, comparator);
|
|
541
574
|
return comparator;
|
|
542
575
|
}
|
|
543
576
|
getGenericComparator(prop, cond) {
|
|
544
|
-
return ` if (current${prop}
|
|
577
|
+
return ` if (current${prop} === null && last${prop} === undefined) {\n` +
|
|
578
|
+
` diff${prop} = current${prop};\n` +
|
|
579
|
+
` } else if (current${prop} == null && last${prop} == null) {\n\n` +
|
|
545
580
|
` } else if ((current${prop} != null && last${prop} == null) || (current${prop} == null && last${prop} != null)) {\n` +
|
|
546
581
|
` diff${prop} = current${prop};\n` +
|
|
547
582
|
` } else if (${cond}) {\n` +
|
|
@@ -582,10 +617,10 @@ export class EntityComparator {
|
|
|
582
617
|
if (['buffer', 'uint8array'].includes(type)) {
|
|
583
618
|
return this.getGenericComparator(this.wrap(prop.name), `!compareBuffers(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
584
619
|
}
|
|
585
|
-
if (
|
|
620
|
+
if (type === 'date') {
|
|
586
621
|
return this.getGenericComparator(this.wrap(prop.name), `last${this.wrap(prop.name)}.valueOf() !== current${this.wrap(prop.name)}.valueOf()`);
|
|
587
622
|
}
|
|
588
|
-
if (
|
|
623
|
+
if (type === 'objectid') {
|
|
589
624
|
// We might be comparing PK to object, in case we compare with cached data of populated entity
|
|
590
625
|
// in such case we just ignore the comparison and fallback to `equals()` (which will still mark
|
|
591
626
|
// it as not equal as we compare PK to plain object).
|
|
@@ -607,7 +642,7 @@ export class EntityComparator {
|
|
|
607
642
|
* perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
|
|
608
643
|
*/
|
|
609
644
|
static isComparable(prop, root) {
|
|
610
|
-
const virtual = prop.persist === false || prop.generated;
|
|
645
|
+
const virtual = prop.persist === false || (prop.generated && !prop.primary);
|
|
611
646
|
const inverse = prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner;
|
|
612
647
|
const discriminator = prop.name === root.discriminatorColumn;
|
|
613
648
|
const collection = prop.kind === ReferenceKind.ONE_TO_MANY || prop.kind === ReferenceKind.MANY_TO_MANY;
|
package/utils/QueryHelper.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import type { Dictionary, EntityMetadata, EntityProperty, FilterDef, FilterQuery } from '../typings.js';
|
|
2
2
|
import type { Platform } from '../platforms/Platform.js';
|
|
3
3
|
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
|
|
4
|
+
import type { FilterOptions } from '../drivers/IDatabaseDriver.js';
|
|
5
|
+
/** @internal */
|
|
4
6
|
export declare class QueryHelper {
|
|
5
7
|
static readonly SUPPORTED_OPERATORS: string[];
|
|
6
8
|
static processParams(params: unknown): any;
|
|
7
9
|
static processObjectParams<T extends object>(params?: T): T;
|
|
10
|
+
/**
|
|
11
|
+
* converts `{ account: { $or: [ [Object], [Object] ] } }`
|
|
12
|
+
* to `{ $or: [ { account: [Object] }, { account: [Object] } ] }`
|
|
13
|
+
*/
|
|
14
|
+
static liftGroupOperators<T extends object>(where: Dictionary, meta: EntityMetadata<T>, metadata: MetadataStorage, key?: string): string | undefined;
|
|
8
15
|
static inlinePrimaryKeyObjects<T extends object>(where: Dictionary, meta: EntityMetadata<T>, metadata: MetadataStorage, key?: string): boolean;
|
|
9
16
|
static processWhere<T extends object>(options: ProcessWhereOptions<T>): FilterQuery<T>;
|
|
10
|
-
static getActiveFilters(entityName: string, options:
|
|
17
|
+
static getActiveFilters(entityName: string, options: FilterOptions | undefined, filters: Dictionary<FilterDef>): FilterDef[];
|
|
18
|
+
static mergePropertyFilters(propFilters: FilterOptions | undefined, options: FilterOptions | undefined): FilterOptions | undefined;
|
|
11
19
|
static isFilterActive(entityName: string, filterName: string, filter: FilterDef, options: Dictionary<boolean | Dictionary>): boolean;
|
|
12
20
|
static processCustomType<T extends object>(prop: EntityProperty<T>, cond: FilterQuery<T>, platform: Platform, key?: string, fromQuery?: boolean): FilterQuery<T>;
|
|
13
21
|
private static isSupportedOperator;
|
package/utils/QueryHelper.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Reference } from '../entity/Reference.js';
|
|
2
2
|
import { Utils } from './Utils.js';
|
|
3
|
-
import { GroupOperator, ReferenceKind } from '../enums.js';
|
|
3
|
+
import { ARRAY_OPERATORS, GroupOperator, JSON_KEY_OPERATORS, ReferenceKind } from '../enums.js';
|
|
4
4
|
import { JsonType } from '../types/JsonType.js';
|
|
5
5
|
import { helper } from '../entity/wrap.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isRaw, RawQueryFragment } from './RawQueryFragment.js';
|
|
7
|
+
/** @internal */
|
|
7
8
|
export class QueryHelper {
|
|
8
9
|
static SUPPORTED_OPERATORS = ['>', '<', '<=', '>=', '!', '!='];
|
|
9
10
|
static processParams(params) {
|
|
@@ -33,11 +34,52 @@ export class QueryHelper {
|
|
|
33
34
|
});
|
|
34
35
|
return params;
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* converts `{ account: { $or: [ [Object], [Object] ] } }`
|
|
39
|
+
* to `{ $or: [ { account: [Object] }, { account: [Object] } ] }`
|
|
40
|
+
*/
|
|
41
|
+
static liftGroupOperators(where, meta, metadata, key) {
|
|
42
|
+
if (!Utils.isPlainObject(where)) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const keys = Object.keys(where);
|
|
46
|
+
const groupOperator = keys.find(k => {
|
|
47
|
+
return k in GroupOperator && Array.isArray(where[k]) && where[k].every(cond => {
|
|
48
|
+
return Utils.isPlainObject(cond) && Object.keys(cond).every(k2 => {
|
|
49
|
+
if (Utils.isOperator(k2, false)) {
|
|
50
|
+
if (k2 === '$not') {
|
|
51
|
+
return Object.keys(cond[k2]).every(k3 => meta.primaryKeys.includes(k3));
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return meta.primaryKeys.includes(k2);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
if (groupOperator) {
|
|
60
|
+
return groupOperator;
|
|
61
|
+
}
|
|
62
|
+
for (const k of keys) {
|
|
63
|
+
const value = where[k];
|
|
64
|
+
const prop = meta.properties[k];
|
|
65
|
+
if (!prop || ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const op = this.liftGroupOperators(value, prop.targetMeta, metadata, k);
|
|
69
|
+
if (op) {
|
|
70
|
+
delete where[k];
|
|
71
|
+
where[op] = value[op].map((v) => {
|
|
72
|
+
return { [k]: v };
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
36
78
|
static inlinePrimaryKeyObjects(where, meta, metadata, key) {
|
|
37
79
|
if (Array.isArray(where)) {
|
|
38
80
|
where.forEach((item, i) => {
|
|
39
81
|
if (this.inlinePrimaryKeyObjects(item, meta, metadata, key)) {
|
|
40
|
-
where[i] = Utils.getPrimaryKeyValues(item, meta
|
|
82
|
+
where[i] = Utils.getPrimaryKeyValues(item, meta, false);
|
|
41
83
|
}
|
|
42
84
|
});
|
|
43
85
|
}
|
|
@@ -47,7 +89,7 @@ export class QueryHelper {
|
|
|
47
89
|
if (meta.primaryKeys.every(pk => pk in where) && Utils.getObjectKeysSize(where) === meta.primaryKeys.length) {
|
|
48
90
|
return !!key && !GroupOperator[key] && key !== '$not' && Object.keys(where).every(k => !Utils.isPlainObject(where[k]) || Object.keys(where[k]).every(v => {
|
|
49
91
|
if (Utils.isOperator(v, false)) {
|
|
50
|
-
return
|
|
92
|
+
return true;
|
|
51
93
|
}
|
|
52
94
|
if (meta.properties[k].primary && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[k].kind)) {
|
|
53
95
|
return this.inlinePrimaryKeyObjects(where[k], meta.properties[k].targetMeta, metadata, v);
|
|
@@ -58,7 +100,7 @@ export class QueryHelper {
|
|
|
58
100
|
Object.keys(where).forEach(k => {
|
|
59
101
|
const meta2 = metadata.find(meta.properties[k]?.type) || meta;
|
|
60
102
|
if (this.inlinePrimaryKeyObjects(where[k], meta2, metadata, k)) {
|
|
61
|
-
where[k] = Utils.getPrimaryKeyValues(where[k], meta2
|
|
103
|
+
where[k] = Utils.getPrimaryKeyValues(where[k], meta2, true);
|
|
62
104
|
}
|
|
63
105
|
});
|
|
64
106
|
return false;
|
|
@@ -69,13 +111,14 @@ export class QueryHelper {
|
|
|
69
111
|
const meta = metadata.find(entityName);
|
|
70
112
|
// inline PK-only objects in M:N queries, so we don't join the target entity when not needed
|
|
71
113
|
if (meta && root) {
|
|
114
|
+
QueryHelper.liftGroupOperators(where, meta, metadata);
|
|
72
115
|
QueryHelper.inlinePrimaryKeyObjects(where, meta, metadata);
|
|
73
116
|
}
|
|
74
117
|
if (platform.getConfig().get('ignoreUndefinedInQuery') && where && typeof where === 'object') {
|
|
75
118
|
Utils.dropUndefinedProperties(where);
|
|
76
119
|
}
|
|
77
120
|
where = QueryHelper.processParams(where) ?? {};
|
|
78
|
-
/* v8 ignore next
|
|
121
|
+
/* v8 ignore next */
|
|
79
122
|
if (!root && Utils.isPrimaryKey(where)) {
|
|
80
123
|
return where;
|
|
81
124
|
}
|
|
@@ -118,7 +161,7 @@ export class QueryHelper {
|
|
|
118
161
|
value = QueryHelper.processCustomType(prop, value, platform, undefined, true);
|
|
119
162
|
}
|
|
120
163
|
const isJsonProperty = prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !isRaw(value) && Object.keys(value)[0] !== '$eq';
|
|
121
|
-
if (isJsonProperty) {
|
|
164
|
+
if (isJsonProperty && prop?.kind !== ReferenceKind.EMBEDDED) {
|
|
122
165
|
return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform, aliased);
|
|
123
166
|
}
|
|
124
167
|
if (Array.isArray(value) && !Utils.isOperator(key) && !QueryHelper.isSupportedOperator(key) && !key.includes('?') && options.type !== 'orderBy') {
|
|
@@ -159,6 +202,24 @@ export class QueryHelper {
|
|
|
159
202
|
return filters[f];
|
|
160
203
|
});
|
|
161
204
|
}
|
|
205
|
+
static mergePropertyFilters(propFilters, options) {
|
|
206
|
+
if (!options || !propFilters || options === true || propFilters === true) {
|
|
207
|
+
return options ?? propFilters;
|
|
208
|
+
}
|
|
209
|
+
if (Array.isArray(propFilters)) {
|
|
210
|
+
propFilters = propFilters.reduce((o, item) => {
|
|
211
|
+
o[item] = true;
|
|
212
|
+
return o;
|
|
213
|
+
}, {});
|
|
214
|
+
}
|
|
215
|
+
if (Array.isArray(options)) {
|
|
216
|
+
options = options.reduce((o, item) => {
|
|
217
|
+
o[item] = true;
|
|
218
|
+
return o;
|
|
219
|
+
}, {});
|
|
220
|
+
}
|
|
221
|
+
return Utils.mergeConfig({}, propFilters, options);
|
|
222
|
+
}
|
|
162
223
|
static isFilterActive(entityName, filterName, filter, options) {
|
|
163
224
|
if (filter.entity && !filter.entity.includes(entityName)) {
|
|
164
225
|
return false;
|
|
@@ -180,12 +241,12 @@ export class QueryHelper {
|
|
|
180
241
|
return o;
|
|
181
242
|
}, {});
|
|
182
243
|
}
|
|
183
|
-
if (key &&
|
|
244
|
+
if (key && JSON_KEY_OPERATORS.includes(key)) {
|
|
184
245
|
return Array.isArray(cond)
|
|
185
246
|
? platform.marshallArray(cond)
|
|
186
247
|
: cond;
|
|
187
248
|
}
|
|
188
|
-
if (Array.isArray(cond) && !(key &&
|
|
249
|
+
if (Array.isArray(cond) && !(key && ARRAY_OPERATORS.includes(key))) {
|
|
189
250
|
return cond.map(v => QueryHelper.processCustomType(prop, v, platform, key, fromQuery));
|
|
190
251
|
}
|
|
191
252
|
if (isRaw(cond)) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import type { AnyString, Dictionary, EntityKey } from '../typings.js';
|
|
3
2
|
export declare class RawQueryFragment {
|
|
4
3
|
#private;
|
|
@@ -10,8 +9,6 @@ export declare class RawQueryFragment {
|
|
|
10
9
|
valueOf(): string;
|
|
11
10
|
toJSON(): string;
|
|
12
11
|
toString(): string;
|
|
13
|
-
/** @internal */
|
|
14
|
-
assign(): void;
|
|
15
12
|
clone(): RawQueryFragment;
|
|
16
13
|
static run<T>(cb: (...args: any[]) => Promise<T>): Promise<T>;
|
|
17
14
|
/**
|
|
@@ -21,14 +18,6 @@ export declare class RawQueryFragment {
|
|
|
21
18
|
static isKnownFragment(key: string | RawQueryFragment): boolean;
|
|
22
19
|
static getKnownFragment(key: string | RawQueryFragment, cleanup?: boolean): RawQueryFragment | undefined;
|
|
23
20
|
static remove(key: string): void;
|
|
24
|
-
/** @ignore */
|
|
25
|
-
[inspect.custom](): {
|
|
26
|
-
sql: string;
|
|
27
|
-
params: unknown[];
|
|
28
|
-
} | {
|
|
29
|
-
sql: string;
|
|
30
|
-
params?: undefined;
|
|
31
|
-
};
|
|
32
21
|
}
|
|
33
22
|
export { RawQueryFragment as Raw };
|
|
34
23
|
export declare function isRaw(value: unknown): value is RawQueryFragment;
|
|
@@ -72,8 +61,26 @@ export declare const ALIAS_REPLACEMENT_RE = "\\[::alias::\\]";
|
|
|
72
61
|
* ```ts
|
|
73
62
|
* @Filter({ name: 'long', cond: () => ({ [raw('length(perex)')]: { $gt: 10000 } }) })
|
|
74
63
|
* ```
|
|
64
|
+
*
|
|
65
|
+
* The `raw` helper can be used within indexes and uniques to write database-agnostic SQL expressions. In that case, you can use `'??'` to tag your database identifiers (table name, column names, index name, ...) inside your expression, and pass those identifiers as a second parameter to the `raw` helper. Internally, those will automatically be quoted according to the database in use:
|
|
66
|
+
*
|
|
67
|
+
* ```ts
|
|
68
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("country")
|
|
69
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`country`)
|
|
70
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => raw(`create index ?? on ?? (??)`, ['custom_idx_on_name', table, columns.name]) })
|
|
71
|
+
* @Entity({ schema: 'library' })
|
|
72
|
+
* export class Author { ... }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* You can also use the `quote` tag function to write database-agnostic SQL expressions. The end-result is the same as using the `raw` function regarding database identifiers quoting, only to have a more elegant expression syntax:
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
|
|
79
|
+
* @Entity({ schema: 'library' })
|
|
80
|
+
* export class Author { ... }
|
|
81
|
+
* ```
|
|
75
82
|
*/
|
|
76
|
-
export declare function raw<T extends object = any, R = any>(sql: EntityKey<T> | EntityKey<T>[] | AnyString | ((alias: string) => string) | RawQueryFragment, params?: readonly unknown[] | Dictionary<unknown>): R
|
|
83
|
+
export declare function raw<T extends object = any, R = any>(sql: EntityKey<T> | EntityKey<T>[] | AnyString | ((alias: string) => string) | RawQueryFragment, params?: readonly unknown[] | Dictionary<unknown>): NoInfer<R>;
|
|
77
84
|
/**
|
|
78
85
|
* Alternative to the `raw()` helper allowing to use it as a tagged template function for the simple cases.
|
|
79
86
|
*
|
|
@@ -90,9 +97,25 @@ export declare function raw<T extends object = any, R = any>(sql: EntityKey<T> |
|
|
|
90
97
|
*/
|
|
91
98
|
export declare function sql(sql: readonly string[], ...values: unknown[]): any;
|
|
92
99
|
export declare namespace sql {
|
|
93
|
-
var ref: <T extends object>(...keys: string[]) => RawQueryFragment
|
|
100
|
+
var ref: <T extends object>(...keys: string[]) => NoInfer<RawQueryFragment>;
|
|
94
101
|
var now: (length?: number) => string;
|
|
95
102
|
var lower: <T extends object>(key: string | ((alias: string) => string)) => string;
|
|
96
103
|
var upper: <T extends object>(key: string | ((alias: string) => string)) => string;
|
|
97
104
|
}
|
|
98
105
|
export declare function createSqlFunction<T extends object, R = string>(func: string, key: string | ((alias: string) => string)): R;
|
|
106
|
+
/**
|
|
107
|
+
* Tag function providing quoting of db identifiers (table name, columns names, index names, ...).
|
|
108
|
+
*
|
|
109
|
+
* Within the template literal on which the tag function is applied, all placeholders are considered to be database identifiers, and will thus be quoted as so according to the database in use.
|
|
110
|
+
*
|
|
111
|
+
* ```ts
|
|
112
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("name")
|
|
113
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`name`)
|
|
114
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
|
|
115
|
+
* @Entity({ schema: 'library' })
|
|
116
|
+
* export class Author { ... }
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function quote(expParts: readonly string[], ...values: (string | {
|
|
120
|
+
toString(): string;
|
|
121
|
+
})[]): any;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import { inspect } from 'node:util';
|
|
3
2
|
import { Utils } from './Utils.js';
|
|
4
3
|
export class RawQueryFragment {
|
|
5
4
|
sql;
|
|
@@ -8,7 +7,6 @@ export class RawQueryFragment {
|
|
|
8
7
|
static #storage = new AsyncLocalStorage();
|
|
9
8
|
static #index = 0n;
|
|
10
9
|
static cloneRegistry;
|
|
11
|
-
#assigned = false;
|
|
12
10
|
#used = 0;
|
|
13
11
|
#key;
|
|
14
12
|
constructor(sql, params = []) {
|
|
@@ -17,11 +15,6 @@ export class RawQueryFragment {
|
|
|
17
15
|
this.#key = `[raw]: ${this.sql} (#${RawQueryFragment.#index++})`;
|
|
18
16
|
}
|
|
19
17
|
as(alias) {
|
|
20
|
-
// TODO: to be removed in v7
|
|
21
|
-
/* istanbul ignore next */
|
|
22
|
-
if (alias.startsWith('`') || alias.startsWith('"')) {
|
|
23
|
-
return new RawQueryFragment(`${this.sql} as ${alias}`, this.params);
|
|
24
|
-
}
|
|
25
18
|
return new RawQueryFragment(`${this.sql} as ??`, [...this.params, alias]);
|
|
26
19
|
}
|
|
27
20
|
valueOf() {
|
|
@@ -35,13 +28,6 @@ export class RawQueryFragment {
|
|
|
35
28
|
this.#used++;
|
|
36
29
|
return this.#key;
|
|
37
30
|
}
|
|
38
|
-
/** @internal */
|
|
39
|
-
assign() {
|
|
40
|
-
if (this.#assigned) {
|
|
41
|
-
throw new Error(`Cannot reassign already used RawQueryFragment: '${this.sql}'`);
|
|
42
|
-
}
|
|
43
|
-
this.#assigned = true;
|
|
44
|
-
}
|
|
45
31
|
clone() {
|
|
46
32
|
RawQueryFragment.cloneRegistry?.add(this.#key);
|
|
47
33
|
return new RawQueryFragment(this.sql, this.params);
|
|
@@ -91,9 +77,9 @@ export class RawQueryFragment {
|
|
|
91
77
|
}
|
|
92
78
|
}
|
|
93
79
|
}
|
|
94
|
-
/* v8 ignore next 8 */
|
|
95
80
|
/** @ignore */
|
|
96
|
-
|
|
81
|
+
/* v8 ignore next */
|
|
82
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
97
83
|
if (this.params) {
|
|
98
84
|
return { sql: this.sql, params: this.params };
|
|
99
85
|
}
|
|
@@ -147,6 +133,24 @@ export const ALIAS_REPLACEMENT_RE = '\\[::alias::\\]';
|
|
|
147
133
|
* ```ts
|
|
148
134
|
* @Filter({ name: 'long', cond: () => ({ [raw('length(perex)')]: { $gt: 10000 } }) })
|
|
149
135
|
* ```
|
|
136
|
+
*
|
|
137
|
+
* The `raw` helper can be used within indexes and uniques to write database-agnostic SQL expressions. In that case, you can use `'??'` to tag your database identifiers (table name, column names, index name, ...) inside your expression, and pass those identifiers as a second parameter to the `raw` helper. Internally, those will automatically be quoted according to the database in use:
|
|
138
|
+
*
|
|
139
|
+
* ```ts
|
|
140
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("country")
|
|
141
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`country`)
|
|
142
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => raw(`create index ?? on ?? (??)`, ['custom_idx_on_name', table, columns.name]) })
|
|
143
|
+
* @Entity({ schema: 'library' })
|
|
144
|
+
* export class Author { ... }
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* You can also use the `quote` tag function to write database-agnostic SQL expressions. The end-result is the same as using the `raw` function regarding database identifiers quoting, only to have a more elegant expression syntax:
|
|
148
|
+
*
|
|
149
|
+
* ```ts
|
|
150
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
|
|
151
|
+
* @Entity({ schema: 'library' })
|
|
152
|
+
* export class Author { ... }
|
|
153
|
+
* ```
|
|
150
154
|
*/
|
|
151
155
|
export function raw(sql, params) {
|
|
152
156
|
if (sql instanceof RawQueryFragment) {
|
|
@@ -205,3 +209,19 @@ sql.ref = (...keys) => raw('??', [keys.join('.')]);
|
|
|
205
209
|
sql.now = (length) => raw('current_timestamp' + (length == null ? '' : `(${length})`));
|
|
206
210
|
sql.lower = (key) => createSqlFunction('lower', key);
|
|
207
211
|
sql.upper = (key) => createSqlFunction('upper', key);
|
|
212
|
+
/**
|
|
213
|
+
* Tag function providing quoting of db identifiers (table name, columns names, index names, ...).
|
|
214
|
+
*
|
|
215
|
+
* Within the template literal on which the tag function is applied, all placeholders are considered to be database identifiers, and will thus be quoted as so according to the database in use.
|
|
216
|
+
*
|
|
217
|
+
* ```ts
|
|
218
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("name")
|
|
219
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`name`)
|
|
220
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
|
|
221
|
+
* @Entity({ schema: 'library' })
|
|
222
|
+
* export class Author { ... }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
export function quote(expParts, ...values) {
|
|
226
|
+
return raw(expParts.join('??'), values);
|
|
227
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { EntityManager } from '../EntityManager.js';
|
|
2
|
+
import { type TransactionOptions } from '../enums.js';
|
|
3
|
+
/**
|
|
4
|
+
* Manages transaction lifecycle and propagation for EntityManager.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TransactionManager {
|
|
7
|
+
private readonly em;
|
|
8
|
+
constructor(em: EntityManager);
|
|
9
|
+
/**
|
|
10
|
+
* Main entry point for handling transactional operations with propagation support.
|
|
11
|
+
*/
|
|
12
|
+
handle<T>(cb: (em: EntityManager) => T | Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Executes the callback with the specified propagation type.
|
|
15
|
+
*/
|
|
16
|
+
private executeWithPropagation;
|
|
17
|
+
/**
|
|
18
|
+
* Suspends the current transaction and returns the suspended resources.
|
|
19
|
+
*/
|
|
20
|
+
private suspendTransaction;
|
|
21
|
+
/**
|
|
22
|
+
* Resumes a previously suspended transaction.
|
|
23
|
+
*/
|
|
24
|
+
private resumeTransaction;
|
|
25
|
+
/**
|
|
26
|
+
* Executes operation without transaction context.
|
|
27
|
+
*/
|
|
28
|
+
private executeWithoutTransaction;
|
|
29
|
+
/**
|
|
30
|
+
* Creates new independent transaction, suspending any existing one.
|
|
31
|
+
*/
|
|
32
|
+
private executeWithNewTransaction;
|
|
33
|
+
/**
|
|
34
|
+
* Creates new transaction context.
|
|
35
|
+
*/
|
|
36
|
+
private createNewTransaction;
|
|
37
|
+
/**
|
|
38
|
+
* Executes nested transaction with savepoint.
|
|
39
|
+
*/
|
|
40
|
+
private executeNestedTransaction;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a fork of the EntityManager with the given options.
|
|
43
|
+
*/
|
|
44
|
+
private createFork;
|
|
45
|
+
/**
|
|
46
|
+
* Determines if changes should be propagated to the upper context.
|
|
47
|
+
*/
|
|
48
|
+
private shouldPropagateToUpperContext;
|
|
49
|
+
/**
|
|
50
|
+
* Merges entities from fork to parent EntityManager.
|
|
51
|
+
*/
|
|
52
|
+
private mergeEntitiesToParent;
|
|
53
|
+
/**
|
|
54
|
+
* Registers a deletion handler to unset entity identities after flush.
|
|
55
|
+
*/
|
|
56
|
+
private registerDeletionHandler;
|
|
57
|
+
/**
|
|
58
|
+
* Processes transaction execution.
|
|
59
|
+
*/
|
|
60
|
+
private processTransaction;
|
|
61
|
+
/**
|
|
62
|
+
* Executes transaction workflow with entity synchronization.
|
|
63
|
+
*/
|
|
64
|
+
private executeTransactionFlow;
|
|
65
|
+
}
|