@yandjin-mikro-orm/core 6.1.4-rc-sti-changes-1
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 +553 -0
- package/EntityManager.js +1736 -0
- package/LICENSE +21 -0
- package/MikroORM.d.ts +102 -0
- package/MikroORM.js +258 -0
- package/README.md +383 -0
- package/cache/CacheAdapter.d.ts +40 -0
- package/cache/CacheAdapter.js +2 -0
- package/cache/FileCacheAdapter.d.ts +31 -0
- package/cache/FileCacheAdapter.js +90 -0
- package/cache/GeneratedCacheAdapter.d.ts +25 -0
- package/cache/GeneratedCacheAdapter.js +38 -0
- package/cache/MemoryCacheAdapter.d.ts +24 -0
- package/cache/MemoryCacheAdapter.js +44 -0
- package/cache/NullCacheAdapter.d.ts +19 -0
- package/cache/NullCacheAdapter.js +30 -0
- package/cache/index.d.ts +5 -0
- package/cache/index.js +21 -0
- package/connections/Connection.d.ts +85 -0
- package/connections/Connection.js +128 -0
- package/connections/index.d.ts +1 -0
- package/connections/index.js +17 -0
- package/decorators/Check.d.ts +3 -0
- package/decorators/Check.js +17 -0
- package/decorators/CreateRequestContext.d.ts +2 -0
- package/decorators/CreateRequestContext.js +31 -0
- package/decorators/Embeddable.d.ts +8 -0
- package/decorators/Embeddable.js +15 -0
- package/decorators/Embedded.d.ts +13 -0
- package/decorators/Embedded.js +21 -0
- package/decorators/EnsureRequestContext.d.ts +2 -0
- package/decorators/EnsureRequestContext.js +26 -0
- package/decorators/Entity.d.ts +18 -0
- package/decorators/Entity.js +17 -0
- package/decorators/Enum.d.ts +9 -0
- package/decorators/Enum.js +20 -0
- package/decorators/Filter.d.ts +2 -0
- package/decorators/Filter.js +12 -0
- package/decorators/Formula.d.ts +5 -0
- package/decorators/Formula.js +19 -0
- package/decorators/Indexed.d.ts +12 -0
- package/decorators/Indexed.js +25 -0
- package/decorators/ManyToMany.d.ts +21 -0
- package/decorators/ManyToMany.js +17 -0
- package/decorators/ManyToOne.d.ts +15 -0
- package/decorators/ManyToOne.js +17 -0
- package/decorators/OneToMany.d.ts +18 -0
- package/decorators/OneToMany.js +21 -0
- package/decorators/OneToOne.d.ts +12 -0
- package/decorators/OneToOne.js +11 -0
- package/decorators/PrimaryKey.d.ts +8 -0
- package/decorators/PrimaryKey.js +24 -0
- package/decorators/Property.d.ts +218 -0
- package/decorators/Property.js +35 -0
- package/decorators/Subscriber.d.ts +1 -0
- package/decorators/Subscriber.js +2 -0
- package/decorators/hooks.d.ts +16 -0
- package/decorators/hooks.js +60 -0
- package/decorators/index.d.ts +17 -0
- package/decorators/index.js +36 -0
- package/drivers/DatabaseDriver.d.ts +72 -0
- package/drivers/DatabaseDriver.js +358 -0
- package/drivers/IDatabaseDriver.d.ts +193 -0
- package/drivers/IDatabaseDriver.js +4 -0
- package/drivers/index.d.ts +2 -0
- package/drivers/index.js +18 -0
- package/entity/ArrayCollection.d.ts +113 -0
- package/entity/ArrayCollection.js +386 -0
- package/entity/BaseEntity.d.ts +22 -0
- package/entity/BaseEntity.js +47 -0
- package/entity/Collection.d.ts +104 -0
- package/entity/Collection.js +373 -0
- package/entity/EntityAssigner.d.ts +28 -0
- package/entity/EntityAssigner.js +226 -0
- package/entity/EntityFactory.d.ts +41 -0
- package/entity/EntityFactory.js +302 -0
- package/entity/EntityHelper.d.ts +29 -0
- package/entity/EntityHelper.js +250 -0
- package/entity/EntityIdentifier.d.ts +10 -0
- package/entity/EntityIdentifier.js +19 -0
- package/entity/EntityLoader.d.ts +65 -0
- package/entity/EntityLoader.js +579 -0
- package/entity/EntityRepository.d.ts +161 -0
- package/entity/EntityRepository.js +207 -0
- package/entity/EntityValidator.d.ts +19 -0
- package/entity/EntityValidator.js +152 -0
- package/entity/Reference.d.ts +89 -0
- package/entity/Reference.js +242 -0
- package/entity/WrappedEntity.d.ts +67 -0
- package/entity/WrappedEntity.js +146 -0
- package/entity/index.d.ts +13 -0
- package/entity/index.js +29 -0
- package/entity/wrap.d.ts +15 -0
- package/entity/wrap.js +26 -0
- package/enums.d.ts +160 -0
- package/enums.js +169 -0
- package/errors.d.ts +65 -0
- package/errors.js +222 -0
- package/events/EventManager.d.ts +17 -0
- package/events/EventManager.js +77 -0
- package/events/EventSubscriber.d.ts +39 -0
- package/events/EventSubscriber.js +2 -0
- package/events/TransactionEventBroadcaster.d.ts +11 -0
- package/events/TransactionEventBroadcaster.js +17 -0
- package/events/index.d.ts +3 -0
- package/events/index.js +19 -0
- package/exceptions.d.ts +104 -0
- package/exceptions.js +130 -0
- package/hydration/Hydrator.d.ts +23 -0
- package/hydration/Hydrator.js +51 -0
- package/hydration/ObjectHydrator.d.ts +24 -0
- package/hydration/ObjectHydrator.js +332 -0
- package/hydration/index.d.ts +2 -0
- package/hydration/index.js +18 -0
- package/index.d.ts +25 -0
- package/index.js +50 -0
- package/index.mjs +192 -0
- package/logging/DefaultLogger.d.ts +32 -0
- package/logging/DefaultLogger.js +90 -0
- package/logging/Logger.d.ts +56 -0
- package/logging/Logger.js +2 -0
- package/logging/SimpleLogger.d.ts +17 -0
- package/logging/SimpleLogger.js +31 -0
- package/logging/colors.d.ts +9 -0
- package/logging/colors.js +20 -0
- package/logging/index.d.ts +4 -0
- package/logging/index.js +20 -0
- package/metadata/EntitySchema.d.ts +74 -0
- package/metadata/EntitySchema.js +293 -0
- package/metadata/MetadataDiscovery.d.ts +71 -0
- package/metadata/MetadataDiscovery.js +1244 -0
- package/metadata/MetadataProvider.d.ts +11 -0
- package/metadata/MetadataProvider.js +23 -0
- package/metadata/MetadataStorage.d.ts +22 -0
- package/metadata/MetadataStorage.js +87 -0
- package/metadata/MetadataValidator.d.ts +24 -0
- package/metadata/MetadataValidator.js +213 -0
- package/metadata/ReflectMetadataProvider.d.ts +8 -0
- package/metadata/ReflectMetadataProvider.js +48 -0
- package/metadata/index.d.ts +6 -0
- package/metadata/index.js +22 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +18 -0
- package/naming-strategy/AbstractNamingStrategy.js +48 -0
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +12 -0
- package/naming-strategy/EntityCaseNamingStrategy.js +32 -0
- package/naming-strategy/MongoNamingStrategy.d.ts +9 -0
- package/naming-strategy/MongoNamingStrategy.js +25 -0
- package/naming-strategy/NamingStrategy.d.ts +52 -0
- package/naming-strategy/NamingStrategy.js +2 -0
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +10 -0
- package/naming-strategy/UnderscoreNamingStrategy.js +28 -0
- package/naming-strategy/index.d.ts +5 -0
- package/naming-strategy/index.js +21 -0
- package/package.json +70 -0
- package/platforms/ExceptionConverter.d.ts +5 -0
- package/platforms/ExceptionConverter.js +11 -0
- package/platforms/Platform.d.ts +201 -0
- package/platforms/Platform.js +452 -0
- package/platforms/index.d.ts +2 -0
- package/platforms/index.js +18 -0
- package/serialization/EntitySerializer.d.ts +34 -0
- package/serialization/EntitySerializer.js +206 -0
- package/serialization/EntityTransformer.d.ts +8 -0
- package/serialization/EntityTransformer.js +192 -0
- package/serialization/SerializationContext.d.ts +30 -0
- package/serialization/SerializationContext.js +111 -0
- package/serialization/index.d.ts +3 -0
- package/serialization/index.js +19 -0
- package/types/ArrayType.d.ts +13 -0
- package/types/ArrayType.js +47 -0
- package/types/BigIntType.d.ts +16 -0
- package/types/BigIntType.js +45 -0
- package/types/BlobType.d.ts +10 -0
- package/types/BlobType.js +27 -0
- package/types/BooleanType.d.ts +8 -0
- package/types/BooleanType.js +16 -0
- package/types/DateTimeType.d.ts +8 -0
- package/types/DateTimeType.js +16 -0
- package/types/DateType.d.ts +8 -0
- package/types/DateType.js +16 -0
- package/types/DecimalType.d.ts +11 -0
- package/types/DecimalType.js +22 -0
- package/types/DoubleType.d.ts +11 -0
- package/types/DoubleType.js +22 -0
- package/types/EnumArrayType.d.ts +9 -0
- package/types/EnumArrayType.js +32 -0
- package/types/EnumType.d.ts +8 -0
- package/types/EnumType.js +16 -0
- package/types/FloatType.d.ts +8 -0
- package/types/FloatType.js +16 -0
- package/types/IntegerType.d.ts +8 -0
- package/types/IntegerType.js +16 -0
- package/types/IntervalType.d.ts +8 -0
- package/types/IntervalType.js +16 -0
- package/types/JsonType.d.ts +13 -0
- package/types/JsonType.js +34 -0
- package/types/MediumIntType.d.ts +6 -0
- package/types/MediumIntType.js +10 -0
- package/types/SmallIntType.d.ts +8 -0
- package/types/SmallIntType.js +16 -0
- package/types/StringType.d.ts +8 -0
- package/types/StringType.js +16 -0
- package/types/TextType.d.ts +8 -0
- package/types/TextType.js +16 -0
- package/types/TimeType.d.ts +9 -0
- package/types/TimeType.js +23 -0
- package/types/TinyIntType.d.ts +8 -0
- package/types/TinyIntType.js +16 -0
- package/types/Type.d.ts +64 -0
- package/types/Type.js +84 -0
- package/types/Uint8ArrayType.d.ts +11 -0
- package/types/Uint8ArrayType.js +37 -0
- package/types/UnknownType.d.ts +7 -0
- package/types/UnknownType.js +13 -0
- package/types/UuidType.d.ts +7 -0
- package/types/UuidType.js +13 -0
- package/types/index.d.ts +75 -0
- package/types/index.js +77 -0
- package/typings.d.ts +767 -0
- package/typings.js +198 -0
- package/unit-of-work/ChangeSet.d.ts +34 -0
- package/unit-of-work/ChangeSet.js +62 -0
- package/unit-of-work/ChangeSetComputer.d.ts +26 -0
- package/unit-of-work/ChangeSetComputer.js +153 -0
- package/unit-of-work/ChangeSetPersister.d.ts +50 -0
- package/unit-of-work/ChangeSetPersister.js +361 -0
- package/unit-of-work/CommitOrderCalculator.d.ts +62 -0
- package/unit-of-work/CommitOrderCalculator.js +113 -0
- package/unit-of-work/IdentityMap.d.ts +17 -0
- package/unit-of-work/IdentityMap.js +84 -0
- package/unit-of-work/UnitOfWork.d.ts +124 -0
- package/unit-of-work/UnitOfWork.js +1013 -0
- package/unit-of-work/index.d.ts +6 -0
- package/unit-of-work/index.js +22 -0
- package/utils/AbstractSchemaGenerator.d.ts +38 -0
- package/utils/AbstractSchemaGenerator.js +101 -0
- package/utils/Configuration.d.ts +390 -0
- package/utils/Configuration.js +357 -0
- package/utils/ConfigurationLoader.d.ts +29 -0
- package/utils/ConfigurationLoader.js +282 -0
- package/utils/Cursor.d.ts +77 -0
- package/utils/Cursor.js +169 -0
- package/utils/DataloaderUtils.d.ts +43 -0
- package/utils/DataloaderUtils.js +194 -0
- package/utils/EntityComparator.d.ts +73 -0
- package/utils/EntityComparator.js +568 -0
- package/utils/NullHighlighter.d.ts +4 -0
- package/utils/NullHighlighter.js +9 -0
- package/utils/QueryHelper.d.ts +28 -0
- package/utils/QueryHelper.js +228 -0
- package/utils/RawQueryFragment.d.ts +96 -0
- package/utils/RawQueryFragment.js +188 -0
- package/utils/RequestContext.d.ts +34 -0
- package/utils/RequestContext.js +54 -0
- package/utils/TransactionContext.d.ts +19 -0
- package/utils/TransactionContext.js +34 -0
- package/utils/Utils.d.ts +274 -0
- package/utils/Utils.js +1073 -0
- package/utils/clone.d.ts +6 -0
- package/utils/clone.js +127 -0
- package/utils/index.d.ts +13 -0
- package/utils/index.js +29 -0
- package/utils/upsert-utils.d.ts +6 -0
- package/utils/upsert-utils.js +33 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChangeSetPersister = void 0;
|
|
4
|
+
const entity_1 = require("../entity");
|
|
5
|
+
const ChangeSet_1 = require("./ChangeSet");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
const errors_1 = require("../errors");
|
|
8
|
+
const enums_1 = require("../enums");
|
|
9
|
+
class ChangeSetPersister {
|
|
10
|
+
driver;
|
|
11
|
+
metadata;
|
|
12
|
+
hydrator;
|
|
13
|
+
factory;
|
|
14
|
+
validator;
|
|
15
|
+
config;
|
|
16
|
+
platform;
|
|
17
|
+
comparator;
|
|
18
|
+
constructor(driver, metadata, hydrator, factory, validator, config) {
|
|
19
|
+
this.driver = driver;
|
|
20
|
+
this.metadata = metadata;
|
|
21
|
+
this.hydrator = hydrator;
|
|
22
|
+
this.factory = factory;
|
|
23
|
+
this.validator = validator;
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.platform = this.driver.getPlatform();
|
|
26
|
+
this.comparator = this.config.getComparator(this.metadata);
|
|
27
|
+
}
|
|
28
|
+
async executeInserts(changeSets, options, withSchema) {
|
|
29
|
+
if (!withSchema) {
|
|
30
|
+
return this.runForEachSchema(changeSets, 'executeInserts', options);
|
|
31
|
+
}
|
|
32
|
+
const meta = this.metadata.find(changeSets[0].name);
|
|
33
|
+
changeSets.forEach(changeSet => this.processProperties(changeSet));
|
|
34
|
+
if (changeSets.length > 1 && this.config.get('useBatchInserts', this.platform.usesBatchInserts())) {
|
|
35
|
+
return this.persistNewEntities(meta, changeSets, options);
|
|
36
|
+
}
|
|
37
|
+
for (const changeSet of changeSets) {
|
|
38
|
+
await this.persistNewEntity(meta, changeSet, options);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async executeUpdates(changeSets, batched, options, withSchema) {
|
|
42
|
+
if (!withSchema) {
|
|
43
|
+
return this.runForEachSchema(changeSets, 'executeUpdates', options, batched);
|
|
44
|
+
}
|
|
45
|
+
const meta = this.metadata.find(changeSets[0].name);
|
|
46
|
+
changeSets.forEach(changeSet => this.processProperties(changeSet));
|
|
47
|
+
if (batched && changeSets.length > 1 && this.config.get('useBatchUpdates', this.platform.usesBatchUpdates())) {
|
|
48
|
+
return this.persistManagedEntities(meta, changeSets, options);
|
|
49
|
+
}
|
|
50
|
+
for (const changeSet of changeSets) {
|
|
51
|
+
await this.persistManagedEntity(changeSet, options);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async executeDeletes(changeSets, options, withSchema) {
|
|
55
|
+
if (!withSchema) {
|
|
56
|
+
return this.runForEachSchema(changeSets, 'executeDeletes', options);
|
|
57
|
+
}
|
|
58
|
+
const size = this.config.get('batchSize');
|
|
59
|
+
const meta = changeSets[0].meta;
|
|
60
|
+
const pk = utils_1.Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
61
|
+
for (let i = 0; i < changeSets.length; i += size) {
|
|
62
|
+
const chunk = changeSets.slice(i, i + size);
|
|
63
|
+
const pks = chunk.map(cs => cs.getPrimaryKey());
|
|
64
|
+
options = this.propagateSchemaFromMetadata(meta, options);
|
|
65
|
+
await this.driver.nativeDelete(meta.className, { [pk]: { $in: pks } }, options);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async runForEachSchema(changeSets, method, options, ...args) {
|
|
69
|
+
const groups = new Map();
|
|
70
|
+
changeSets.forEach(cs => {
|
|
71
|
+
const group = groups.get(cs.schema) ?? [];
|
|
72
|
+
group.push(cs);
|
|
73
|
+
groups.set(cs.schema, group);
|
|
74
|
+
});
|
|
75
|
+
for (const [key, group] of groups.entries()) {
|
|
76
|
+
options = { ...options, schema: key };
|
|
77
|
+
// @ts-ignore
|
|
78
|
+
await this[method](group, ...args, options, true);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
processProperties(changeSet) {
|
|
82
|
+
const meta = this.metadata.find(changeSet.name);
|
|
83
|
+
for (const prop of meta.relations) {
|
|
84
|
+
this.processProperty(changeSet, prop);
|
|
85
|
+
}
|
|
86
|
+
if (changeSet.type === ChangeSet_1.ChangeSetType.CREATE && this.config.get('validateRequired')) {
|
|
87
|
+
this.validator.validateRequired(changeSet.entity);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async persistNewEntity(meta, changeSet, options) {
|
|
91
|
+
const wrapped = (0, entity_1.helper)(changeSet.entity);
|
|
92
|
+
options = this.propagateSchemaFromMetadata(meta, options, {
|
|
93
|
+
convertCustomTypes: false,
|
|
94
|
+
});
|
|
95
|
+
const res = await this.driver.nativeInsertMany(meta.className, [changeSet.payload], options);
|
|
96
|
+
if (!wrapped.hasPrimaryKey()) {
|
|
97
|
+
this.mapPrimaryKey(meta, res.insertId, changeSet);
|
|
98
|
+
}
|
|
99
|
+
this.mapReturnedValues(changeSet.entity, changeSet.payload, res.row, meta);
|
|
100
|
+
this.markAsPopulated(changeSet, meta);
|
|
101
|
+
wrapped.__initialized = true;
|
|
102
|
+
wrapped.__managed = true;
|
|
103
|
+
if (!this.platform.usesReturningStatement()) {
|
|
104
|
+
await this.reloadVersionValues(meta, [changeSet], options);
|
|
105
|
+
}
|
|
106
|
+
changeSet.persisted = true;
|
|
107
|
+
}
|
|
108
|
+
async persistNewEntities(meta, changeSets, options) {
|
|
109
|
+
const size = this.config.get('batchSize');
|
|
110
|
+
for (let i = 0; i < changeSets.length; i += size) {
|
|
111
|
+
const chunk = changeSets.slice(i, i + size);
|
|
112
|
+
await this.persistNewEntitiesBatch(meta, chunk, options);
|
|
113
|
+
if (!this.platform.usesReturningStatement()) {
|
|
114
|
+
await this.reloadVersionValues(meta, chunk, options);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
propagateSchemaFromMetadata(meta, options, additionalOptions) {
|
|
119
|
+
return {
|
|
120
|
+
...options,
|
|
121
|
+
...additionalOptions,
|
|
122
|
+
schema: options?.schema ?? meta.schema,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
async persistNewEntitiesBatch(meta, changeSets, options) {
|
|
126
|
+
options = this.propagateSchemaFromMetadata(meta, options, {
|
|
127
|
+
convertCustomTypes: false,
|
|
128
|
+
processCollections: false,
|
|
129
|
+
});
|
|
130
|
+
const res = await this.driver.nativeInsertMany(meta.className, changeSets.map(cs => cs.payload), options);
|
|
131
|
+
for (let i = 0; i < changeSets.length; i++) {
|
|
132
|
+
const changeSet = changeSets[i];
|
|
133
|
+
const wrapped = (0, entity_1.helper)(changeSet.entity);
|
|
134
|
+
if (!wrapped.hasPrimaryKey()) {
|
|
135
|
+
const field = meta.getPrimaryProps()[0].fieldNames[0];
|
|
136
|
+
this.mapPrimaryKey(meta, res.rows[i][field], changeSet);
|
|
137
|
+
}
|
|
138
|
+
if (res.rows) {
|
|
139
|
+
this.mapReturnedValues(changeSet.entity, changeSet.payload, res.rows[i], meta);
|
|
140
|
+
}
|
|
141
|
+
this.markAsPopulated(changeSet, meta);
|
|
142
|
+
wrapped.__initialized = true;
|
|
143
|
+
wrapped.__managed = true;
|
|
144
|
+
changeSet.persisted = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async persistManagedEntity(changeSet, options) {
|
|
148
|
+
const meta = this.metadata.find(changeSet.name);
|
|
149
|
+
const res = await this.updateEntity(meta, changeSet, options);
|
|
150
|
+
this.checkOptimisticLock(meta, changeSet, res);
|
|
151
|
+
this.mapReturnedValues(changeSet.entity, changeSet.payload, res.row, meta);
|
|
152
|
+
await this.reloadVersionValues(meta, [changeSet], options);
|
|
153
|
+
changeSet.persisted = true;
|
|
154
|
+
}
|
|
155
|
+
async persistManagedEntities(meta, changeSets, options) {
|
|
156
|
+
const size = this.config.get('batchSize');
|
|
157
|
+
for (let i = 0; i < changeSets.length; i += size) {
|
|
158
|
+
const chunk = changeSets.slice(i, i + size);
|
|
159
|
+
await this.persistManagedEntitiesBatch(meta, chunk, options);
|
|
160
|
+
await this.reloadVersionValues(meta, chunk, options);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
checkConcurrencyKeys(meta, changeSet, cond) {
|
|
164
|
+
const tmp = [];
|
|
165
|
+
cond = utils_1.Utils.isPlainObject(cond) ? cond : { [meta.primaryKeys[0]]: cond };
|
|
166
|
+
for (const key of meta.concurrencyCheckKeys) {
|
|
167
|
+
cond[key] = changeSet.originalEntity[key];
|
|
168
|
+
if (changeSet.payload[key]) {
|
|
169
|
+
tmp.push(key);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (tmp.length === 0 && meta.concurrencyCheckKeys.size > 0) {
|
|
173
|
+
throw errors_1.OptimisticLockError.lockFailed(changeSet.entity);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async persistManagedEntitiesBatch(meta, changeSets, options) {
|
|
177
|
+
await this.checkOptimisticLocks(meta, changeSets, options);
|
|
178
|
+
options = this.propagateSchemaFromMetadata(meta, options, {
|
|
179
|
+
convertCustomTypes: false,
|
|
180
|
+
processCollections: false,
|
|
181
|
+
});
|
|
182
|
+
const cond = changeSets.map(cs => cs.getPrimaryKey(true));
|
|
183
|
+
changeSets.forEach((changeSet, idx) => {
|
|
184
|
+
this.checkConcurrencyKeys(meta, changeSet, cond[idx]);
|
|
185
|
+
});
|
|
186
|
+
const res = await this.driver.nativeUpdateMany(meta.className, cond, changeSets.map(cs => cs.payload), options);
|
|
187
|
+
changeSets.forEach((changeSet, idx) => {
|
|
188
|
+
if (res.rows) {
|
|
189
|
+
this.mapReturnedValues(changeSet.entity, changeSet.payload, res.rows[idx], meta);
|
|
190
|
+
}
|
|
191
|
+
changeSet.persisted = true;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
mapPrimaryKey(meta, value, changeSet) {
|
|
195
|
+
const prop = meta.properties[meta.primaryKeys[0]];
|
|
196
|
+
const insertId = prop.customType ? prop.customType.convertToJSValue(value, this.platform) : value;
|
|
197
|
+
const wrapped = (0, entity_1.helper)(changeSet.entity);
|
|
198
|
+
if (!wrapped.hasPrimaryKey()) {
|
|
199
|
+
wrapped.setPrimaryKey(insertId);
|
|
200
|
+
}
|
|
201
|
+
// some drivers might be returning bigint PKs as numbers when the number is small enough,
|
|
202
|
+
// but we need to have it as string so comparison works in change set tracking, so instead
|
|
203
|
+
// of using the raw value from db, we convert it back to the db value explicitly
|
|
204
|
+
value = prop.customType ? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' }) : value;
|
|
205
|
+
changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
|
|
206
|
+
wrapped.__identifier?.setValue(value);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Sets populate flag to new entities so they are serialized like if they were loaded from the db
|
|
210
|
+
*/
|
|
211
|
+
markAsPopulated(changeSet, meta) {
|
|
212
|
+
(0, entity_1.helper)(changeSet.entity).__schema = this.driver.getSchemaName(meta, changeSet);
|
|
213
|
+
if (!this.config.get('populateAfterFlush')) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
(0, entity_1.helper)(changeSet.entity).populated();
|
|
217
|
+
meta.relations.forEach(prop => {
|
|
218
|
+
const value = changeSet.entity[prop.name];
|
|
219
|
+
if (utils_1.Utils.isEntity(value, true)) {
|
|
220
|
+
value.__helper.populated();
|
|
221
|
+
}
|
|
222
|
+
else if (utils_1.Utils.isCollection(value)) {
|
|
223
|
+
value.populated();
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
async updateEntity(meta, changeSet, options) {
|
|
228
|
+
const cond = changeSet.getPrimaryKey(true);
|
|
229
|
+
options = this.propagateSchemaFromMetadata(meta, options, {
|
|
230
|
+
convertCustomTypes: false,
|
|
231
|
+
});
|
|
232
|
+
if (meta.concurrencyCheckKeys.size === 0 && (!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
|
|
233
|
+
return this.driver.nativeUpdate(changeSet.name, cond, changeSet.payload, options);
|
|
234
|
+
}
|
|
235
|
+
if (meta.versionProperty) {
|
|
236
|
+
cond[meta.versionProperty] = this.platform.quoteVersionValue(changeSet.entity[meta.versionProperty], meta.properties[meta.versionProperty]);
|
|
237
|
+
}
|
|
238
|
+
this.checkConcurrencyKeys(meta, changeSet, cond);
|
|
239
|
+
return this.driver.nativeUpdate(changeSet.name, cond, changeSet.payload, options);
|
|
240
|
+
}
|
|
241
|
+
async checkOptimisticLocks(meta, changeSets, options) {
|
|
242
|
+
if (meta.concurrencyCheckKeys.size === 0 && (!meta.versionProperty || changeSets.every(cs => cs.entity[meta.versionProperty] == null))) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
// skip entity references as they don't have version values loaded
|
|
246
|
+
changeSets = changeSets.filter(cs => (0, entity_1.helper)(cs.entity).__initialized);
|
|
247
|
+
const $or = changeSets.map(cs => {
|
|
248
|
+
const cond = utils_1.Utils.getPrimaryKeyCond(cs.originalEntity, meta.primaryKeys.concat(...meta.concurrencyCheckKeys));
|
|
249
|
+
if (meta.versionProperty) {
|
|
250
|
+
// @ts-ignore
|
|
251
|
+
cond[meta.versionProperty] = this.platform.quoteVersionValue(cs.entity[meta.versionProperty], meta.properties[meta.versionProperty]);
|
|
252
|
+
}
|
|
253
|
+
return cond;
|
|
254
|
+
});
|
|
255
|
+
const primaryKeys = meta.primaryKeys.concat(...meta.concurrencyCheckKeys);
|
|
256
|
+
options = this.propagateSchemaFromMetadata(meta, options, {
|
|
257
|
+
fields: primaryKeys,
|
|
258
|
+
});
|
|
259
|
+
const res = await this.driver.find(meta.root.className, { $or }, options);
|
|
260
|
+
if (res.length !== changeSets.length) {
|
|
261
|
+
const compare = (a, b, keys) => keys.every(k => a[k] === b[k]);
|
|
262
|
+
const entity = changeSets.find(cs => {
|
|
263
|
+
return !res.some(row => compare(utils_1.Utils.getPrimaryKeyCond(cs.entity, primaryKeys), row, primaryKeys));
|
|
264
|
+
}).entity;
|
|
265
|
+
throw errors_1.OptimisticLockError.lockFailed(entity);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
checkOptimisticLock(meta, changeSet, res) {
|
|
269
|
+
if ((meta.versionProperty || meta.concurrencyCheckKeys.size > 0) && res && !res.affectedRows) {
|
|
270
|
+
throw errors_1.OptimisticLockError.lockFailed(changeSet.entity);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* This method also handles reloading of database default values for inserts and raw property updates,
|
|
275
|
+
* so we use a single query in case of both versioning and default values is used.
|
|
276
|
+
*/
|
|
277
|
+
async reloadVersionValues(meta, changeSets, options) {
|
|
278
|
+
const reloadProps = meta.versionProperty && !this.platform.usesReturningStatement() ? [meta.properties[meta.versionProperty]] : [];
|
|
279
|
+
if (changeSets[0].type === ChangeSet_1.ChangeSetType.CREATE) {
|
|
280
|
+
// do not reload things that already had a runtime value
|
|
281
|
+
meta.props
|
|
282
|
+
.filter(prop => prop.persist !== false && (prop.autoincrement || prop.generated || prop.defaultRaw))
|
|
283
|
+
.filter(prop => (changeSets[0].entity[prop.name] == null && prop.defaultRaw !== 'null') || utils_1.Utils.isRawSql(changeSets[0].entity[prop.name]))
|
|
284
|
+
.forEach(prop => reloadProps.push(prop));
|
|
285
|
+
}
|
|
286
|
+
if (changeSets[0].type === ChangeSet_1.ChangeSetType.UPDATE) {
|
|
287
|
+
const returning = new Set();
|
|
288
|
+
changeSets.forEach(cs => {
|
|
289
|
+
utils_1.Utils.keys(cs.payload).forEach(k => {
|
|
290
|
+
if (utils_1.Utils.isRawSql(cs.payload[k]) && utils_1.Utils.isRawSql(cs.entity[k])) {
|
|
291
|
+
returning.add(meta.properties[k]);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
// reload generated columns
|
|
296
|
+
if (!this.platform.usesReturningStatement()) {
|
|
297
|
+
meta.props
|
|
298
|
+
.filter(prop => prop.generated && !prop.primary)
|
|
299
|
+
.forEach(prop => reloadProps.push(prop));
|
|
300
|
+
reloadProps.push(...returning);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (reloadProps.length === 0) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
reloadProps.unshift(...meta.getPrimaryProps());
|
|
307
|
+
const pk = utils_1.Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
308
|
+
const pks = changeSets.map(cs => {
|
|
309
|
+
const val = (0, entity_1.helper)(cs.entity).getPrimaryKey(true);
|
|
310
|
+
if (utils_1.Utils.isPlainObject(val)) {
|
|
311
|
+
return utils_1.Utils.getCompositeKeyValue(val, meta, false, this.platform);
|
|
312
|
+
}
|
|
313
|
+
return val;
|
|
314
|
+
});
|
|
315
|
+
options = this.propagateSchemaFromMetadata(meta, options, {
|
|
316
|
+
fields: utils_1.Utils.unique(reloadProps.map(prop => prop.name)),
|
|
317
|
+
});
|
|
318
|
+
const data = await this.driver.find(meta.className, { [pk]: { $in: pks } }, options);
|
|
319
|
+
const map = new Map();
|
|
320
|
+
data.forEach(item => map.set(utils_1.Utils.getCompositeKeyHash(item, meta, true, this.platform, true), item));
|
|
321
|
+
for (const changeSet of changeSets) {
|
|
322
|
+
const data = map.get((0, entity_1.helper)(changeSet.entity).getSerializedPrimaryKey());
|
|
323
|
+
this.hydrator.hydrate(changeSet.entity, meta, data, this.factory, 'full', false, true);
|
|
324
|
+
Object.assign(changeSet.payload, data); // merge to the changeset payload, so it gets saved to the entity snapshot
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
processProperty(changeSet, prop) {
|
|
328
|
+
const meta = this.metadata.find(changeSet.name);
|
|
329
|
+
const value = changeSet.payload[prop.name]; // for inline embeddables
|
|
330
|
+
if (value instanceof entity_1.EntityIdentifier) {
|
|
331
|
+
changeSet.payload[prop.name] = value.getValue();
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
|
|
335
|
+
changeSet.payload[prop.name] = value.map(val => val instanceof entity_1.EntityIdentifier ? val.getValue() : val);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (prop.name in changeSet.payload) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const values = utils_1.Utils.unwrapProperty(changeSet.payload, meta, prop, true); // for object embeddables
|
|
342
|
+
values.forEach(([value, indexes]) => {
|
|
343
|
+
if (value instanceof entity_1.EntityIdentifier) {
|
|
344
|
+
utils_1.Utils.setPayloadProperty(changeSet.payload, meta, prop, value.getValue(), indexes);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Maps values returned via `returning` statement (postgres) or the inserted id (other sql drivers).
|
|
350
|
+
* No need to handle composite keys here as they need to be set upfront.
|
|
351
|
+
* We do need to map to the change set payload too, as it will be used in the originalEntityData for new entities.
|
|
352
|
+
*/
|
|
353
|
+
mapReturnedValues(entity, payload, row, meta) {
|
|
354
|
+
if (this.platform.usesReturningStatement() && row && utils_1.Utils.hasObjectKeys(row)) {
|
|
355
|
+
const mapped = this.comparator.mapResult(meta.className, row);
|
|
356
|
+
this.hydrator.hydrate(entity, meta, mapped, this.factory, 'full', false, true);
|
|
357
|
+
Object.assign(payload, mapped); // merge to the changeset payload, so it gets saved to the entity snapshot
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
exports.ChangeSetPersister = ChangeSetPersister;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Dictionary, EntityProperty } from '../typings';
|
|
2
|
+
export declare const enum NodeState {
|
|
3
|
+
NOT_VISITED = 0,
|
|
4
|
+
IN_PROGRESS = 1,
|
|
5
|
+
VISITED = 2
|
|
6
|
+
}
|
|
7
|
+
export interface Node {
|
|
8
|
+
hash: string;
|
|
9
|
+
state: NodeState;
|
|
10
|
+
dependencies: Dictionary<Edge>;
|
|
11
|
+
}
|
|
12
|
+
export interface Edge {
|
|
13
|
+
from: string;
|
|
14
|
+
to: string;
|
|
15
|
+
weight: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* CommitOrderCalculator implements topological sorting, which is an ordering
|
|
19
|
+
* algorithm for directed graphs (DG) and/or directed acyclic graphs (DAG) by
|
|
20
|
+
* using a depth-first searching (DFS) to traverse the graph built in memory.
|
|
21
|
+
* This algorithm have a linear running time based on nodes (V) and dependency
|
|
22
|
+
* between the nodes (E), resulting in a computational complexity of O(V + E).
|
|
23
|
+
*
|
|
24
|
+
* Based on https://github.com/doctrine/orm/blob/master/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare class CommitOrderCalculator {
|
|
28
|
+
/** Matrix of nodes, keys are provided hashes and values are the node definition objects. */
|
|
29
|
+
private nodes;
|
|
30
|
+
/** Volatile variable holding calculated nodes during sorting process. */
|
|
31
|
+
private sortedNodeList;
|
|
32
|
+
/**
|
|
33
|
+
* Checks for node existence in graph.
|
|
34
|
+
*/
|
|
35
|
+
hasNode(hash: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Adds a new node to the graph, assigning its hash.
|
|
38
|
+
*/
|
|
39
|
+
addNode(hash: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Adds a new dependency (edge) to the graph using their hashes.
|
|
42
|
+
*/
|
|
43
|
+
addDependency(from: string, to: string, weight: number): void;
|
|
44
|
+
discoverProperty(prop: EntityProperty, entityName: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Return a valid order list of all current nodes.
|
|
47
|
+
* The desired topological sorting is the reverse post order of these searches.
|
|
48
|
+
*
|
|
49
|
+
* @internal Highly performance-sensitive method.
|
|
50
|
+
*/
|
|
51
|
+
sort(): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Visit a given node definition for reordering.
|
|
54
|
+
*
|
|
55
|
+
* @internal Highly performance-sensitive method.
|
|
56
|
+
*/
|
|
57
|
+
private visit;
|
|
58
|
+
/**
|
|
59
|
+
* Visits all target's dependencies if in cycle with given node
|
|
60
|
+
*/
|
|
61
|
+
private visitOpenNode;
|
|
62
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CommitOrderCalculator = exports.NodeState = void 0;
|
|
4
|
+
const enums_1 = require("../enums");
|
|
5
|
+
var NodeState;
|
|
6
|
+
(function (NodeState) {
|
|
7
|
+
NodeState[NodeState["NOT_VISITED"] = 0] = "NOT_VISITED";
|
|
8
|
+
NodeState[NodeState["IN_PROGRESS"] = 1] = "IN_PROGRESS";
|
|
9
|
+
NodeState[NodeState["VISITED"] = 2] = "VISITED";
|
|
10
|
+
})(NodeState || (exports.NodeState = NodeState = {}));
|
|
11
|
+
/**
|
|
12
|
+
* CommitOrderCalculator implements topological sorting, which is an ordering
|
|
13
|
+
* algorithm for directed graphs (DG) and/or directed acyclic graphs (DAG) by
|
|
14
|
+
* using a depth-first searching (DFS) to traverse the graph built in memory.
|
|
15
|
+
* This algorithm have a linear running time based on nodes (V) and dependency
|
|
16
|
+
* between the nodes (E), resulting in a computational complexity of O(V + E).
|
|
17
|
+
*
|
|
18
|
+
* Based on https://github.com/doctrine/orm/blob/master/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
class CommitOrderCalculator {
|
|
22
|
+
/** Matrix of nodes, keys are provided hashes and values are the node definition objects. */
|
|
23
|
+
nodes = {};
|
|
24
|
+
/** Volatile variable holding calculated nodes during sorting process. */
|
|
25
|
+
sortedNodeList = [];
|
|
26
|
+
/**
|
|
27
|
+
* Checks for node existence in graph.
|
|
28
|
+
*/
|
|
29
|
+
hasNode(hash) {
|
|
30
|
+
return hash in this.nodes;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Adds a new node to the graph, assigning its hash.
|
|
34
|
+
*/
|
|
35
|
+
addNode(hash) {
|
|
36
|
+
this.nodes[hash] = { hash, state: 0 /* NodeState.NOT_VISITED */, dependencies: {} };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Adds a new dependency (edge) to the graph using their hashes.
|
|
40
|
+
*/
|
|
41
|
+
addDependency(from, to, weight) {
|
|
42
|
+
this.nodes[from].dependencies[to] = { from, to, weight };
|
|
43
|
+
}
|
|
44
|
+
discoverProperty(prop, entityName) {
|
|
45
|
+
const toOneOwner = (prop.kind === enums_1.ReferenceKind.ONE_TO_ONE && prop.owner) || prop.kind === enums_1.ReferenceKind.MANY_TO_ONE;
|
|
46
|
+
const toManyOwner = prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && prop.owner && !prop.pivotEntity;
|
|
47
|
+
if (!toOneOwner && !toManyOwner) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const propertyType = prop.targetMeta?.root.className;
|
|
51
|
+
if (!propertyType || !this.hasNode(propertyType)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.addDependency(propertyType, entityName, prop.nullable || prop.persist === false ? 0 : 1);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Return a valid order list of all current nodes.
|
|
58
|
+
* The desired topological sorting is the reverse post order of these searches.
|
|
59
|
+
*
|
|
60
|
+
* @internal Highly performance-sensitive method.
|
|
61
|
+
*/
|
|
62
|
+
sort() {
|
|
63
|
+
for (const vertex of Object.values(this.nodes)) {
|
|
64
|
+
if (vertex.state !== 0 /* NodeState.NOT_VISITED */) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
this.visit(vertex);
|
|
68
|
+
}
|
|
69
|
+
const sortedList = this.sortedNodeList.reverse();
|
|
70
|
+
this.nodes = {};
|
|
71
|
+
this.sortedNodeList = [];
|
|
72
|
+
return sortedList;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Visit a given node definition for reordering.
|
|
76
|
+
*
|
|
77
|
+
* @internal Highly performance-sensitive method.
|
|
78
|
+
*/
|
|
79
|
+
visit(node) {
|
|
80
|
+
node.state = 1 /* NodeState.IN_PROGRESS */;
|
|
81
|
+
for (const edge of Object.values(node.dependencies)) {
|
|
82
|
+
const target = this.nodes[edge.to];
|
|
83
|
+
switch (target.state) {
|
|
84
|
+
case 2 /* NodeState.VISITED */: break; // Do nothing, since node was already visited
|
|
85
|
+
case 1 /* NodeState.IN_PROGRESS */:
|
|
86
|
+
this.visitOpenNode(node, target, edge);
|
|
87
|
+
break;
|
|
88
|
+
case 0 /* NodeState.NOT_VISITED */: this.visit(target);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (node.state !== 2 /* NodeState.VISITED */) {
|
|
92
|
+
node.state = 2 /* NodeState.VISITED */;
|
|
93
|
+
this.sortedNodeList.push(node.hash);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Visits all target's dependencies if in cycle with given node
|
|
98
|
+
*/
|
|
99
|
+
visitOpenNode(node, target, edge) {
|
|
100
|
+
if (!target.dependencies[node.hash] || target.dependencies[node.hash].weight >= edge.weight) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
for (const edge of Object.values(target.dependencies)) {
|
|
104
|
+
const targetNode = this.nodes[edge.to];
|
|
105
|
+
if (targetNode.state === 0 /* NodeState.NOT_VISITED */) {
|
|
106
|
+
this.visit(targetNode);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
target.state = 2 /* NodeState.VISITED */;
|
|
110
|
+
this.sortedNodeList.push(target.hash);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.CommitOrderCalculator = CommitOrderCalculator;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AnyEntity, EntityMetadata } from '../typings';
|
|
2
|
+
export declare class IdentityMap {
|
|
3
|
+
private readonly registry;
|
|
4
|
+
store<T>(item: T): void;
|
|
5
|
+
delete<T>(item: T): void;
|
|
6
|
+
getByHash<T>(meta: EntityMetadata<T>, hash: string): T | undefined;
|
|
7
|
+
getStore<T>(meta: EntityMetadata<T>): Map<string, T>;
|
|
8
|
+
clear(): void;
|
|
9
|
+
values(): AnyEntity[];
|
|
10
|
+
[Symbol.iterator](): IterableIterator<AnyEntity>;
|
|
11
|
+
keys(): string[];
|
|
12
|
+
/**
|
|
13
|
+
* For back compatibility only.
|
|
14
|
+
*/
|
|
15
|
+
get<T>(hash: string): T | undefined;
|
|
16
|
+
private getPkHash;
|
|
17
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IdentityMap = void 0;
|
|
4
|
+
const Utils_1 = require("../utils/Utils");
|
|
5
|
+
class IdentityMap {
|
|
6
|
+
registry = new Map();
|
|
7
|
+
store(item) {
|
|
8
|
+
this.getStore(item.__meta.root).set(this.getPkHash(item), item);
|
|
9
|
+
}
|
|
10
|
+
delete(item) {
|
|
11
|
+
this.getStore(item.__meta.root).delete(this.getPkHash(item));
|
|
12
|
+
}
|
|
13
|
+
getByHash(meta, hash) {
|
|
14
|
+
const store = this.getStore(meta);
|
|
15
|
+
return store.has(hash) ? store.get(hash) : undefined;
|
|
16
|
+
}
|
|
17
|
+
getStore(meta) {
|
|
18
|
+
const store = this.registry.get(meta.class);
|
|
19
|
+
if (store) {
|
|
20
|
+
return store;
|
|
21
|
+
}
|
|
22
|
+
const newStore = new Map();
|
|
23
|
+
this.registry.set(meta.class, newStore);
|
|
24
|
+
return newStore;
|
|
25
|
+
}
|
|
26
|
+
clear() {
|
|
27
|
+
this.registry.clear();
|
|
28
|
+
}
|
|
29
|
+
values() {
|
|
30
|
+
const ret = [];
|
|
31
|
+
for (const store of this.registry.values()) {
|
|
32
|
+
ret.push(...store.values());
|
|
33
|
+
}
|
|
34
|
+
return ret;
|
|
35
|
+
}
|
|
36
|
+
*[Symbol.iterator]() {
|
|
37
|
+
for (const store of this.registry.values()) {
|
|
38
|
+
for (const item of store.values()) {
|
|
39
|
+
yield item;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
keys() {
|
|
44
|
+
const ret = [];
|
|
45
|
+
for (const [cls, store] of this.registry) {
|
|
46
|
+
ret.push(...[...store.keys()].map(hash => `${cls.name}-${hash}`));
|
|
47
|
+
}
|
|
48
|
+
return ret;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* For back compatibility only.
|
|
52
|
+
*/
|
|
53
|
+
get(hash) {
|
|
54
|
+
const [name, id] = hash.split('-', 2);
|
|
55
|
+
const cls = [...this.registry.keys()].find(k => k.name === name);
|
|
56
|
+
if (!cls) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const store = this.registry.get(cls);
|
|
60
|
+
return store.has(id) ? store.get(id) : undefined;
|
|
61
|
+
}
|
|
62
|
+
getPkHash(item) {
|
|
63
|
+
const wrapped = item.__helper;
|
|
64
|
+
const meta = wrapped.__meta;
|
|
65
|
+
const pk = wrapped.getPrimaryKey(true);
|
|
66
|
+
if (pk == null) {
|
|
67
|
+
return pk;
|
|
68
|
+
}
|
|
69
|
+
let hash;
|
|
70
|
+
if (meta.simplePK) {
|
|
71
|
+
hash = '' + item[meta.primaryKeys[0]];
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const pks = Utils_1.Utils.getOrderedPrimaryKeys(pk, meta);
|
|
75
|
+
hash = Utils_1.Utils.getPrimaryKeyHash(pks);
|
|
76
|
+
}
|
|
77
|
+
const schema = wrapped.__schema || meta.root.schema;
|
|
78
|
+
if (schema) {
|
|
79
|
+
return schema + ':' + hash;
|
|
80
|
+
}
|
|
81
|
+
return hash;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.IdentityMap = IdentityMap;
|