@itwin/imodel-transformer 2.0.0-dev.6 → 2.0.0-dev.7
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/lib/cjs/BranchProvenanceInitializer.js +8 -8
- package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts.map +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.js +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +1 -1
- package/lib/cjs/EntityUnifier.d.ts +1 -1
- package/lib/cjs/EntityUnifier.d.ts.map +1 -1
- package/lib/cjs/EntityUnifier.js +5 -12
- package/lib/cjs/EntityUnifier.js.map +1 -1
- package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
- package/lib/cjs/IModelCloneContext.js +14 -13
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelTransformer.d.ts +13 -15
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +185 -173
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/package.json +1 -1
|
@@ -110,7 +110,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
110
110
|
* @param dbToQuery db to run the query on for scope external source
|
|
111
111
|
* @param aspectProps aspectProps to search for @see ExternalSourceAspectProps
|
|
112
112
|
*/
|
|
113
|
-
static queryScopeExternalSourceAspect(dbToQuery, aspectProps) {
|
|
113
|
+
static async queryScopeExternalSourceAspect(dbToQuery, aspectProps) {
|
|
114
114
|
const sql = `
|
|
115
115
|
SELECT ECInstanceId, Version, JsonProperties
|
|
116
116
|
FROM ${core_backend_1.ExternalSourceAspect.classFullName}
|
|
@@ -121,25 +121,19 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
121
121
|
LIMIT 1
|
|
122
122
|
`;
|
|
123
123
|
// if (aspectProps.scope === undefined) return undefined;
|
|
124
|
-
// const params = new QueryBinder()
|
|
124
|
+
// const params = new QueryBinder();
|
|
125
|
+
// params.bindId("elementId", aspectProps.element.id);
|
|
125
126
|
// params.bindId("scopeId", aspectProps.scope.id);
|
|
126
127
|
// params.bindString("kind", aspectProps.kind);
|
|
127
128
|
// params.bindString("identifier", aspectProps.identifier);
|
|
128
|
-
// const
|
|
129
|
-
// if (
|
|
130
|
-
// const aspectId =
|
|
131
|
-
// const
|
|
132
|
-
// const
|
|
133
|
-
// ? undefined
|
|
134
|
-
// : versionValue.getString();
|
|
135
|
-
// const jsonPropsValue = result.current[2];
|
|
136
|
-
// const jsonProperties = jsonPropsValue.isNull
|
|
137
|
-
// ? undefined
|
|
138
|
-
// : jsonPropsValue.getString();
|
|
129
|
+
// const reader = dbToQuery.createQueryReader(sql, params, {usePrimaryConn: true});
|
|
130
|
+
// if (await reader.step()) {
|
|
131
|
+
// const aspectId = reader.current.id;
|
|
132
|
+
// const version = reader.current.version as string | undefined;
|
|
133
|
+
// const jsonProperties = reader.current.jsonProperties as string | undefined;
|
|
139
134
|
// return { aspectId, version, jsonProperties };
|
|
140
135
|
// }
|
|
141
|
-
//
|
|
142
|
-
// return undefined;
|
|
136
|
+
// return undefined;
|
|
143
137
|
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
144
138
|
return dbToQuery.withPreparedStatement(sql, (statement) => {
|
|
145
139
|
statement.bindId("elementId", aspectProps.element.id);
|
|
@@ -169,7 +163,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
169
163
|
* @throws if no scoping ESA can be found in either the sourceDb or targetDb which describes a master branch relationship between the two databases.
|
|
170
164
|
* @returns "forward" or "reverse"
|
|
171
165
|
*/
|
|
172
|
-
static determineSyncType(sourceDb, targetDb,
|
|
166
|
+
static async determineSyncType(sourceDb, targetDb,
|
|
173
167
|
/** @see [[IModelTransformOptions.targetScopeElementId]] */
|
|
174
168
|
targetScopeElementId) {
|
|
175
169
|
const aspectProps = {
|
|
@@ -186,19 +180,19 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
186
180
|
jsonProperties: undefined,
|
|
187
181
|
};
|
|
188
182
|
/** First check if the targetDb is the branch (branch is the @see provenanceDb) */
|
|
189
|
-
const esaPropsFromTargetDb = this.queryScopeExternalSourceAspect(targetDb, aspectProps);
|
|
183
|
+
const esaPropsFromTargetDb = await this.queryScopeExternalSourceAspect(targetDb, aspectProps);
|
|
190
184
|
if (esaPropsFromTargetDb !== undefined) {
|
|
191
185
|
return "forward"; // we found an esa assuming targetDb is the provenanceDb/branch so this is a forward sync.
|
|
192
186
|
}
|
|
193
187
|
// Now check if the sourceDb is the branch
|
|
194
188
|
aspectProps.identifier = targetDb.iModelId;
|
|
195
|
-
const esaPropsFromSourceDb = this.queryScopeExternalSourceAspect(sourceDb, aspectProps);
|
|
189
|
+
const esaPropsFromSourceDb = await this.queryScopeExternalSourceAspect(sourceDb, aspectProps);
|
|
196
190
|
if (esaPropsFromSourceDb !== undefined) {
|
|
197
191
|
return "reverse"; // we found an esa assuming sourceDb is the provenanceDb/branch so this is a reverse sync.
|
|
198
192
|
}
|
|
199
193
|
throw new Error(this.noEsaSyncDirectionErrorMessage);
|
|
200
194
|
}
|
|
201
|
-
determineSyncType() {
|
|
195
|
+
async determineSyncType() {
|
|
202
196
|
if (this._isProvenanceInitTransform) {
|
|
203
197
|
return "forward";
|
|
204
198
|
}
|
|
@@ -206,7 +200,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
206
200
|
return "not-sync";
|
|
207
201
|
}
|
|
208
202
|
try {
|
|
209
|
-
return IModelTransformer.determineSyncType(this.sourceDb, this.targetDb, this.targetScopeElementId);
|
|
203
|
+
return await IModelTransformer.determineSyncType(this.sourceDb, this.targetDb, this.targetScopeElementId);
|
|
210
204
|
}
|
|
211
205
|
catch (err) {
|
|
212
206
|
if (err instanceof Error &&
|
|
@@ -217,14 +211,14 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
217
211
|
throw err;
|
|
218
212
|
}
|
|
219
213
|
}
|
|
220
|
-
|
|
214
|
+
async getIsReverseSynchronization() {
|
|
221
215
|
if (this._syncType === undefined)
|
|
222
|
-
this._syncType = this.determineSyncType();
|
|
216
|
+
this._syncType = await this.determineSyncType();
|
|
223
217
|
return this._syncType === "reverse";
|
|
224
218
|
}
|
|
225
|
-
|
|
219
|
+
async getIsForwardSynchronization() {
|
|
226
220
|
if (this._syncType === undefined)
|
|
227
|
-
this._syncType = this.determineSyncType();
|
|
221
|
+
this._syncType = await this.determineSyncType();
|
|
228
222
|
return this._syncType === "forward";
|
|
229
223
|
}
|
|
230
224
|
_changesetRanges = undefined;
|
|
@@ -371,14 +365,18 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
371
365
|
/** Return the IModelDb where IModelTransformer will store its provenance.
|
|
372
366
|
* @note This will be [[targetDb]] except when it is a reverse synchronization. In that case it be [[sourceDb]].
|
|
373
367
|
*/
|
|
374
|
-
|
|
375
|
-
return
|
|
368
|
+
async provenanceDb() {
|
|
369
|
+
return (await this.getIsReverseSynchronization())
|
|
370
|
+
? this.sourceDb
|
|
371
|
+
: this.targetDb;
|
|
376
372
|
}
|
|
377
373
|
/** Return the IModelDb where IModelTransformer looks for entities referred to by stored provenance.
|
|
378
374
|
* @note This will be [[sourceDb]] except when it is a reverse synchronization. In that case it be [[targetDb]].
|
|
379
375
|
*/
|
|
380
|
-
|
|
381
|
-
return
|
|
376
|
+
async provenanceSourceDb() {
|
|
377
|
+
return (await this.getIsReverseSynchronization())
|
|
378
|
+
? this.targetDb
|
|
379
|
+
: this.sourceDb;
|
|
382
380
|
}
|
|
383
381
|
/** Create an ExternalSourceAspectProps in a standard way for an Element in an iModel --> iModel transformation. */
|
|
384
382
|
static initElementProvenanceOptions(sourceElementId, targetElementId, args) {
|
|
@@ -445,9 +443,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
445
443
|
*/
|
|
446
444
|
_forceOldRelationshipProvenanceMethod = false;
|
|
447
445
|
/** Create an ExternalSourceAspectProps in a standard way for an Element in an iModel --> iModel transformation. */
|
|
448
|
-
initElementProvenance(sourceElementId, targetElementId) {
|
|
446
|
+
async initElementProvenance(sourceElementId, targetElementId) {
|
|
449
447
|
return IModelTransformer.initElementProvenanceOptions(sourceElementId, targetElementId, {
|
|
450
|
-
isReverseSynchronization: this.
|
|
448
|
+
isReverseSynchronization: await this.getIsReverseSynchronization(),
|
|
451
449
|
targetScopeElementId: this.targetScopeElementId,
|
|
452
450
|
sourceDb: this.sourceDb,
|
|
453
451
|
targetDb: this.targetDb,
|
|
@@ -459,10 +457,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
459
457
|
* The ECInstanceId of the relationship in the branch iModel will be stored in the JsonProperties of the ExternalSourceAspect.
|
|
460
458
|
*/
|
|
461
459
|
async initRelationshipProvenance(sourceRelationship, targetRelInstanceId) {
|
|
462
|
-
return
|
|
460
|
+
return IModelTransformer.initRelationshipProvenanceOptions(sourceRelationship.id, targetRelInstanceId, {
|
|
463
461
|
sourceDb: this.sourceDb,
|
|
464
462
|
targetDb: this.targetDb,
|
|
465
|
-
isReverseSynchronization: this.
|
|
463
|
+
isReverseSynchronization: await this.getIsReverseSynchronization(),
|
|
466
464
|
targetScopeElementId: this.targetScopeElementId,
|
|
467
465
|
forceOldRelationshipProvenanceMethod: this._forceOldRelationshipProvenanceMethod,
|
|
468
466
|
});
|
|
@@ -490,13 +488,13 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
490
488
|
* @note empty string and -1 for changeset and index if it was transformed before federation guid update (pre 1.x) and @see [[IModelTransformOptions.branchRelationshipDataBehavior]] === "unsafe-migrate".
|
|
491
489
|
* @throws if the version is not found in a preexisting scope aspect and @see [[IModelTransformOptions.branchRelationshipDataBehavior]] !== "unsafe-migrate"
|
|
492
490
|
*/
|
|
493
|
-
|
|
491
|
+
async synchronizationVersion() {
|
|
494
492
|
if (this._cachedSynchronizationVersion === undefined) {
|
|
495
|
-
const provenanceScopeAspect = this.tryGetProvenanceScopeAspect();
|
|
493
|
+
const provenanceScopeAspect = await this.tryGetProvenanceScopeAspect();
|
|
496
494
|
if (!provenanceScopeAspect) {
|
|
497
495
|
return { index: -1, id: "" }; // first synchronization.
|
|
498
496
|
}
|
|
499
|
-
const version = this.
|
|
497
|
+
const version = (await this.getIsReverseSynchronization())
|
|
500
498
|
? JSON.parse(provenanceScopeAspect.jsonProperties ?? "{}").reverseSyncVersion
|
|
501
499
|
: provenanceScopeAspect.version;
|
|
502
500
|
if (!version &&
|
|
@@ -518,17 +516,17 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
518
516
|
* @returns provenance scope aspect if it exists in the provenanceDb.
|
|
519
517
|
* Provenance scope aspect is created and inserted into provenanceDb when [[initScopeProvenance]] is invoked.
|
|
520
518
|
*/
|
|
521
|
-
tryGetProvenanceScopeAspect() {
|
|
522
|
-
const scopeProvenanceAspectProps = IModelTransformer.queryScopeExternalSourceAspect(this.provenanceDb, {
|
|
519
|
+
async tryGetProvenanceScopeAspect() {
|
|
520
|
+
const scopeProvenanceAspectProps = await IModelTransformer.queryScopeExternalSourceAspect(await this.provenanceDb(), {
|
|
523
521
|
id: undefined,
|
|
524
522
|
classFullName: core_backend_1.ExternalSourceAspect.classFullName,
|
|
525
523
|
scope: { id: core_common_1.IModel.rootSubjectId },
|
|
526
524
|
kind: core_backend_1.ExternalSourceAspect.Kind.Scope,
|
|
527
525
|
element: { id: this.targetScopeElementId ?? core_common_1.IModel.rootSubjectId },
|
|
528
|
-
identifier: this.provenanceSourceDb.iModelId,
|
|
526
|
+
identifier: (await this.provenanceSourceDb()).iModelId,
|
|
529
527
|
});
|
|
530
528
|
return scopeProvenanceAspectProps !== undefined
|
|
531
|
-
? this.provenanceDb.elements.getAspect(scopeProvenanceAspectProps.aspectId)
|
|
529
|
+
? (await this.provenanceDb()).elements.getAspect(scopeProvenanceAspectProps.aspectId)
|
|
532
530
|
: undefined;
|
|
533
531
|
}
|
|
534
532
|
/**
|
|
@@ -538,6 +536,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
538
536
|
* if this was a [BriefcaseDb]($backend)
|
|
539
537
|
*/
|
|
540
538
|
async initScopeProvenance() {
|
|
539
|
+
const provenanceDb = await this.provenanceDb();
|
|
540
|
+
const sourceProvenanceDb = await this.provenanceSourceDb();
|
|
541
541
|
const aspectProps = {
|
|
542
542
|
id: undefined,
|
|
543
543
|
version: undefined,
|
|
@@ -547,11 +547,11 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
547
547
|
relClassName: core_backend_1.ElementOwnsExternalSourceAspects.classFullName,
|
|
548
548
|
},
|
|
549
549
|
scope: { id: core_common_1.IModel.rootSubjectId }, // the root Subject scopes scope elements
|
|
550
|
-
identifier:
|
|
550
|
+
identifier: sourceProvenanceDb.iModelId,
|
|
551
551
|
kind: core_backend_1.ExternalSourceAspect.Kind.Scope,
|
|
552
552
|
jsonProperties: undefined,
|
|
553
553
|
};
|
|
554
|
-
const foundEsaProps = IModelTransformer.queryScopeExternalSourceAspect(
|
|
554
|
+
const foundEsaProps = await IModelTransformer.queryScopeExternalSourceAspect(provenanceDb, aspectProps); // this query includes "identifier"
|
|
555
555
|
if (foundEsaProps === undefined) {
|
|
556
556
|
aspectProps.version = ""; // empty since never before transformed. Will be updated in [[finalizeTransformation]]
|
|
557
557
|
aspectProps.jsonProperties = {
|
|
@@ -572,7 +572,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
572
572
|
params.bindId("elementId", aspectProps.element.id);
|
|
573
573
|
params.bindId("scopeId", aspectProps.scope.id); // this scope.id can never be invalid, we create it above
|
|
574
574
|
params.bindString("kind", aspectProps.kind);
|
|
575
|
-
const reader =
|
|
575
|
+
const reader = provenanceDb.createQueryReader(sql, params, {
|
|
576
576
|
usePrimaryConn: true,
|
|
577
577
|
});
|
|
578
578
|
const hasConflictingScope = await reader.step();
|
|
@@ -580,7 +580,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
580
580
|
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.InvalidId, "Provenance scope conflict");
|
|
581
581
|
}
|
|
582
582
|
if (!this._options.noProvenance) {
|
|
583
|
-
const id =
|
|
583
|
+
const id = provenanceDb.elements.insertAspect({
|
|
584
584
|
...aspectProps,
|
|
585
585
|
jsonProperties: JSON.stringify(aspectProps.jsonProperties),
|
|
586
586
|
});
|
|
@@ -600,7 +600,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
600
600
|
const oldProps = JSON.parse(JSON.stringify(aspectProps));
|
|
601
601
|
if (this.handleUnsafeMigrate(aspectProps)) {
|
|
602
602
|
core_bentley_1.Logger.logInfo(loggerCategory, "Unsafe migrate made a change to the target scope's external source aspect. Updating aspect in database.", { oldProps, newProps: aspectProps });
|
|
603
|
-
|
|
603
|
+
provenanceDb.elements.updateAspect({
|
|
604
604
|
...aspectProps,
|
|
605
605
|
jsonProperties: JSON.stringify(aspectProps.jsonProperties),
|
|
606
606
|
});
|
|
@@ -739,11 +739,11 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
739
739
|
}
|
|
740
740
|
}
|
|
741
741
|
async forEachTrackedElement(fn) {
|
|
742
|
-
return
|
|
743
|
-
provenanceSourceDb: this.provenanceSourceDb,
|
|
744
|
-
provenanceDb: this.provenanceDb,
|
|
742
|
+
return IModelTransformer.forEachTrackedElement({
|
|
743
|
+
provenanceSourceDb: await this.provenanceSourceDb(),
|
|
744
|
+
provenanceDb: await this.provenanceDb(),
|
|
745
745
|
targetScopeElementId: this.targetScopeElementId,
|
|
746
|
-
isReverseSynchronization: this.
|
|
746
|
+
isReverseSynchronization: await this.getIsReverseSynchronization(),
|
|
747
747
|
fn,
|
|
748
748
|
skipPropagateChangesToRootElements: this._options.skipPropagateChangesToRootElements ?? true,
|
|
749
749
|
});
|
|
@@ -756,7 +756,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
756
756
|
* @returns the elementId that the ESA is stored on, esa.Element.Id
|
|
757
757
|
*/
|
|
758
758
|
async _queryProvenanceForElement(entityInProvenanceSourceId) {
|
|
759
|
-
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
760
759
|
const sql = `
|
|
761
760
|
SELECT esa.Element.Id
|
|
762
761
|
FROM Bis.ExternalSourceAspect esa
|
|
@@ -768,7 +767,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
768
767
|
params.bindString(1, core_backend_1.ExternalSourceAspect.Kind.Element);
|
|
769
768
|
params.bindId(2, this.targetScopeElementId);
|
|
770
769
|
params.bindString(3, entityInProvenanceSourceId);
|
|
771
|
-
const result = this.provenanceDb.createQueryReader(sql, params);
|
|
770
|
+
const result = (await this.provenanceDb()).createQueryReader(sql, params);
|
|
772
771
|
if (await result.step()) {
|
|
773
772
|
return result.current.id;
|
|
774
773
|
}
|
|
@@ -796,7 +795,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
796
795
|
params.bindString(1, core_backend_1.ExternalSourceAspect.Kind.Relationship);
|
|
797
796
|
params.bindId(2, this.targetScopeElementId);
|
|
798
797
|
params.bindString(3, entityInProvenanceSourceId);
|
|
799
|
-
const result = this.provenanceDb.createQueryReader(sql, params);
|
|
798
|
+
const result = (await this.provenanceDb()).createQueryReader(sql, params);
|
|
800
799
|
if (await result.step()) {
|
|
801
800
|
const aspectId = result.current.id;
|
|
802
801
|
const provenanceRelInstId = result.current.provenanceRelInstId;
|
|
@@ -886,41 +885,42 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
886
885
|
/**
|
|
887
886
|
* Detect Element deletes using ExternalSourceAspects in the target iModel and a *brute force* comparison against Elements
|
|
888
887
|
* in the source iModel.
|
|
889
|
-
*
|
|
888
|
+
* deprecated in 1.x. Do not use this. // FIXME<MIKE>: how to better explain this?
|
|
890
889
|
* This method is only called during [[process]] when [[IModelTransformOptions.argsForProcessChanges]] is undefined and the option
|
|
891
890
|
* [[IModelTransformOptions.forceExternalSourceAspectProvenance]] is enabled. It is not
|
|
892
891
|
* necessary when calling [[process]] with [[IModelTransformOptions.argsForProcessChanges]] defined, since changeset information is sufficient.
|
|
893
892
|
* @note you do not need to call this directly unless processing a subset of an iModel.
|
|
894
893
|
* @throws [[IModelError]] If the required provenance information is not available to detect deletes.
|
|
895
894
|
*/
|
|
896
|
-
async detectElementDeletes() {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
`;
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
}
|
|
895
|
+
// public async detectElementDeletes(): Promise<void> {
|
|
896
|
+
// const sql = `
|
|
897
|
+
// SELECT Identifier, Element.Id
|
|
898
|
+
// FROM BisCore.ExternalSourceAspect
|
|
899
|
+
// WHERE Scope.Id=:scopeId
|
|
900
|
+
// AND Kind=:kind
|
|
901
|
+
// `;
|
|
902
|
+
// nodeAssert(
|
|
903
|
+
// !this.isReverseSynchronization,
|
|
904
|
+
// "synchronizations with processChanges already detect element deletes, don't call detectElementDeletes"
|
|
905
|
+
// );
|
|
906
|
+
// // Reported issue: https://github.com/iTwin/itwinjs-core/issues/7989
|
|
907
|
+
// this.provenanceDb.withPreparedStatement(sql, (stmt) => {
|
|
908
|
+
// stmt.bindId("scopeId", this.targetScopeElementId);
|
|
909
|
+
// stmt.bindString("kind", ExternalSourceAspect.Kind.Element);
|
|
910
|
+
// while (DbResult.BE_SQLITE_ROW === stmt.step()) {
|
|
911
|
+
// // ExternalSourceAspect.Identifier is of type string
|
|
912
|
+
// const aspectIdentifier = stmt.getValue(0).getString();
|
|
913
|
+
// if (!Id64.isValidId64(aspectIdentifier)) {
|
|
914
|
+
// continue;
|
|
915
|
+
// }
|
|
916
|
+
// const targetElemId = stmt.getValue(1).getId();
|
|
917
|
+
// const wasDeletedInSource = !EntityUnifier.exists(this.sourceDb, {
|
|
918
|
+
// entityReference: `e${aspectIdentifier}`,
|
|
919
|
+
// });
|
|
920
|
+
// if (wasDeletedInSource) this.importer.deleteElement(targetElemId);
|
|
921
|
+
// }
|
|
922
|
+
// });
|
|
923
|
+
// }
|
|
924
924
|
/** Transform the specified sourceElement into ElementProps for the target iModel.
|
|
925
925
|
* @param sourceElement The Element from the source iModel to transform.
|
|
926
926
|
* @returns ElementProps for the target iModel.
|
|
@@ -1090,13 +1090,13 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1090
1090
|
allReferencesExist = false;
|
|
1091
1091
|
}
|
|
1092
1092
|
if (this._options.danglingReferencesBehavior === "reject") {
|
|
1093
|
-
this.assertReferenceExistsInSource(referenceId, entity);
|
|
1093
|
+
await this.assertReferenceExistsInSource(referenceId, entity);
|
|
1094
1094
|
}
|
|
1095
1095
|
}
|
|
1096
1096
|
return allReferencesExist;
|
|
1097
1097
|
}
|
|
1098
|
-
assertReferenceExistsInSource(referenceId, entity) {
|
|
1099
|
-
const referencedExistsInSource = EntityUnifier_1.EntityUnifier.exists(this.sourceDb, {
|
|
1098
|
+
async assertReferenceExistsInSource(referenceId, entity) {
|
|
1099
|
+
const referencedExistsInSource = await EntityUnifier_1.EntityUnifier.exists(this.sourceDb, {
|
|
1100
1100
|
entityReference: referenceId,
|
|
1101
1101
|
});
|
|
1102
1102
|
if (!referencedExistsInSource) {
|
|
@@ -1176,7 +1176,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1176
1176
|
.flat();
|
|
1177
1177
|
if (unresolvedReferences.length > 0) {
|
|
1178
1178
|
for (const reference of unresolvedReferences) {
|
|
1179
|
-
const processState = this.getElemTransformState(reference);
|
|
1179
|
+
const processState = await this.getElemTransformState(reference);
|
|
1180
1180
|
// must export element first
|
|
1181
1181
|
if (processState.needsElemImport)
|
|
1182
1182
|
await this.exporter.exportElement(reference);
|
|
@@ -1185,16 +1185,16 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1185
1185
|
}
|
|
1186
1186
|
}
|
|
1187
1187
|
}
|
|
1188
|
-
getElemTransformState(elementId) {
|
|
1189
|
-
const dbHasModel = (db, id) => {
|
|
1188
|
+
async getElemTransformState(elementId) {
|
|
1189
|
+
const dbHasModel = async (db, id) => {
|
|
1190
1190
|
const maybeModelId = core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Model);
|
|
1191
1191
|
return EntityUnifier_1.EntityUnifier.exists(db, { entityReference: maybeModelId });
|
|
1192
1192
|
};
|
|
1193
|
-
const isSubModeled = dbHasModel(this.sourceDb, elementId);
|
|
1193
|
+
const isSubModeled = await dbHasModel(this.sourceDb, elementId);
|
|
1194
1194
|
const idOfElemInTarget = this.context.findTargetElementId(elementId);
|
|
1195
1195
|
const isElemInTarget = core_bentley_1.Id64.invalid !== idOfElemInTarget;
|
|
1196
1196
|
const needsModelImport = isSubModeled &&
|
|
1197
|
-
(!isElemInTarget || !dbHasModel(this.targetDb, idOfElemInTarget));
|
|
1197
|
+
(!isElemInTarget || !(await dbHasModel(this.targetDb, idOfElemInTarget)));
|
|
1198
1198
|
return { needsElemImport: !isElemInTarget, needsModelImport };
|
|
1199
1199
|
}
|
|
1200
1200
|
/** Override of [IModelExportHandler.onExportElement]($transformer) that imports an element into the target iModel when it is exported from the source iModel.
|
|
@@ -1288,20 +1288,21 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1288
1288
|
// physical consolidation is an example of a 'joining' transform
|
|
1289
1289
|
// FIXME: verify at finalization time that we don't lose provenance on new elements
|
|
1290
1290
|
// FIXME: make public and improve `initElementProvenance` API for usage by consolidators
|
|
1291
|
+
const provenanceDb = await this.provenanceDb();
|
|
1291
1292
|
if (!this._options.noProvenance) {
|
|
1292
1293
|
let provenance = this._options.forceExternalSourceAspectProvenance ||
|
|
1293
1294
|
this._elementsWithExplicitlyTrackedProvenance.has(sourceElement.id)
|
|
1294
1295
|
? undefined
|
|
1295
1296
|
: sourceElement.federationGuid;
|
|
1296
1297
|
if (!provenance) {
|
|
1297
|
-
const aspectProps = this.initElementProvenance(sourceElement.id, targetElementProps.id);
|
|
1298
|
-
const foundEsaProps = IModelTransformer.queryScopeExternalSourceAspect(
|
|
1298
|
+
const aspectProps = await this.initElementProvenance(sourceElement.id, targetElementProps.id);
|
|
1299
|
+
const foundEsaProps = await IModelTransformer.queryScopeExternalSourceAspect(provenanceDb, aspectProps);
|
|
1299
1300
|
if (foundEsaProps === undefined)
|
|
1300
|
-
aspectProps.id =
|
|
1301
|
+
aspectProps.id = provenanceDb.elements.insertAspect(aspectProps);
|
|
1301
1302
|
else {
|
|
1302
1303
|
// Since initElementProvenance sets a property 'version' on the aspectProps that we wish to persist in the provenanceDb, only grab the id from the foundEsaProps.
|
|
1303
1304
|
aspectProps.id = foundEsaProps.aspectId;
|
|
1304
|
-
|
|
1305
|
+
provenanceDb.elements.updateAspect(aspectProps);
|
|
1305
1306
|
}
|
|
1306
1307
|
provenance = aspectProps;
|
|
1307
1308
|
}
|
|
@@ -1466,7 +1467,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1466
1467
|
* Note that typically, the reverseSyncVersion is saved as the last changeset merged from the branch into master.
|
|
1467
1468
|
* Setting initializeReverseSyncVersion to true during a forward transformation could overwrite this correct reverseSyncVersion and should only be done during the first transformation between a master and branch iModel.
|
|
1468
1469
|
*/
|
|
1469
|
-
updateSynchronizationVersion({ initializeReverseSyncVersion = false, } = {}) {
|
|
1470
|
+
async updateSynchronizationVersion({ initializeReverseSyncVersion = false, } = {}) {
|
|
1470
1471
|
const shouldSkipSyncVersionUpdate = !initializeReverseSyncVersion &&
|
|
1471
1472
|
this._sourceChangeDataState !== "has-changes";
|
|
1472
1473
|
if (shouldSkipSyncVersionUpdate)
|
|
@@ -1474,7 +1475,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1474
1475
|
nodeAssert(this._targetScopeProvenanceProps);
|
|
1475
1476
|
const sourceVersion = `${this.sourceDb.changeset.id};${this.sourceDb.changeset.index}`;
|
|
1476
1477
|
const targetVersion = `${this.targetDb.changeset.id};${this.targetDb.changeset.index}`;
|
|
1477
|
-
if (this.
|
|
1478
|
+
if (await this.getIsReverseSynchronization()) {
|
|
1478
1479
|
const oldVersion = this._targetScopeProvenanceProps.jsonProperties.reverseSyncVersion;
|
|
1479
1480
|
core_bentley_1.Logger.logInfo(loggerCategory, `updating reverse version from ${oldVersion} to ${sourceVersion}`);
|
|
1480
1481
|
this._targetScopeProvenanceProps.jsonProperties.reverseSyncVersion =
|
|
@@ -1504,7 +1505,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1504
1505
|
// Determine which keys to clear and update based on the synchronization direction
|
|
1505
1506
|
let syncChangesetsToClearKey;
|
|
1506
1507
|
let syncChangesetsToUpdateKey;
|
|
1507
|
-
if (this.
|
|
1508
|
+
if (await this.getIsReverseSynchronization()) {
|
|
1508
1509
|
syncChangesetsToClearKey = pendingReverseSyncChangesetIndicesKey;
|
|
1509
1510
|
syncChangesetsToUpdateKey = pendingSyncChangesetIndicesKey;
|
|
1510
1511
|
}
|
|
@@ -1523,7 +1524,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1523
1524
|
return csIndex > startingChangesetIndices.source;
|
|
1524
1525
|
});
|
|
1525
1526
|
// if reverse sync then we may have received provenance changes which should be marked as sync changes
|
|
1526
|
-
if (this.
|
|
1527
|
+
if (await this.getIsReverseSynchronization()) {
|
|
1527
1528
|
nodeAssert(this.sourceDb.changeset.index !== undefined, "changeset didn't exist");
|
|
1528
1529
|
for (let i = startingChangesetIndices.source + 1; i <= this.sourceDb.changeset.index + 1; i++)
|
|
1529
1530
|
jsonProps.pendingReverseSyncChangesetIndices.push(i);
|
|
@@ -1531,16 +1532,16 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1531
1532
|
core_bentley_1.Logger.logTrace(loggerCategory, `new pendingReverseSyncChanges: ${jsonProps.pendingReverseSyncChangesetIndices}`);
|
|
1532
1533
|
core_bentley_1.Logger.logTrace(loggerCategory, `new pendingSyncChanges: ${jsonProps.pendingSyncChangesetIndices}`);
|
|
1533
1534
|
}
|
|
1534
|
-
this.provenanceDb.elements.updateAspect({
|
|
1535
|
+
(await this.provenanceDb()).elements.updateAspect({
|
|
1535
1536
|
...this._targetScopeProvenanceProps,
|
|
1536
1537
|
jsonProperties: JSON.stringify(this._targetScopeProvenanceProps.jsonProperties),
|
|
1537
1538
|
});
|
|
1538
1539
|
this.clearCachedSynchronizationVersion();
|
|
1539
1540
|
}
|
|
1540
1541
|
// FIXME<MIKE>: is this necessary when manually using low level transform APIs? (document if so)
|
|
1541
|
-
finalizeTransformation() {
|
|
1542
|
+
async finalizeTransformation() {
|
|
1542
1543
|
this.importer.finalize();
|
|
1543
|
-
this.updateSynchronizationVersion({
|
|
1544
|
+
await this.updateSynchronizationVersion({
|
|
1544
1545
|
initializeReverseSyncVersion: this._isProvenanceInitTransform,
|
|
1545
1546
|
});
|
|
1546
1547
|
// TODO: ignore if we remove change cache usage
|
|
@@ -1578,6 +1579,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1578
1579
|
const targetFedGuid = this.sourceDb.elements.getFederationGuidFromId(sourceRelationship.targetId);
|
|
1579
1580
|
const targetRelationshipProps = this.onTransformRelationship(sourceRelationship);
|
|
1580
1581
|
const targetRelationshipInstanceId = this.importer.importRelationship(targetRelationshipProps);
|
|
1582
|
+
const provenanceDb = await this.provenanceDb();
|
|
1581
1583
|
if (!this._options.noProvenance &&
|
|
1582
1584
|
core_bentley_1.Id64.isValid(targetRelationshipInstanceId)) {
|
|
1583
1585
|
let provenance = !this._options.forceExternalSourceAspectProvenance
|
|
@@ -1585,10 +1587,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1585
1587
|
: undefined;
|
|
1586
1588
|
if (!provenance) {
|
|
1587
1589
|
const aspectProps = await this.initRelationshipProvenance(sourceRelationship, targetRelationshipInstanceId);
|
|
1588
|
-
const foundEsaProps = IModelTransformer.queryScopeExternalSourceAspect(
|
|
1590
|
+
const foundEsaProps = await IModelTransformer.queryScopeExternalSourceAspect(provenanceDb, aspectProps);
|
|
1589
1591
|
// onExportRelationship doesn't need to call updateAspect if esaProps were found, because relationship provenance doesn't have the same concept of a version as element provenance (which uses last mod time on the elements).
|
|
1590
1592
|
if (undefined === foundEsaProps) {
|
|
1591
|
-
aspectProps.id =
|
|
1593
|
+
aspectProps.id = provenanceDb.elements.insertAspect(aspectProps);
|
|
1592
1594
|
}
|
|
1593
1595
|
provenance = aspectProps;
|
|
1594
1596
|
}
|
|
@@ -1598,7 +1600,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1598
1600
|
/** Override of [IModelExportHandler.onDeleteRelationship]($transformer) that is called when [IModelExporter]($transformer) detects that a [Relationship]($backend) has been deleted from the source iModel.
|
|
1599
1601
|
* This override propagates the delete to the target iModel via [IModelImporter.deleteRelationship]($transformer).
|
|
1600
1602
|
*/
|
|
1601
|
-
onDeleteRelationship(sourceRelInstanceId) {
|
|
1603
|
+
async onDeleteRelationship(sourceRelInstanceId) {
|
|
1602
1604
|
nodeAssert(this._deletedSourceRelationshipData, "should be defined at initialization by now");
|
|
1603
1605
|
const deletedRelData = this._deletedSourceRelationshipData.get(sourceRelInstanceId);
|
|
1604
1606
|
if (!deletedRelData) {
|
|
@@ -1619,7 +1621,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1619
1621
|
}
|
|
1620
1622
|
if (deletedRelData.provenanceAspectId) {
|
|
1621
1623
|
try {
|
|
1622
|
-
this.provenanceDb.elements.deleteAspect(deletedRelData.provenanceAspectId);
|
|
1624
|
+
(await this.provenanceDb()).elements.deleteAspect(deletedRelData.provenanceAspectId);
|
|
1623
1625
|
}
|
|
1624
1626
|
catch (error) {
|
|
1625
1627
|
// This aspect may no longer exist if it was deleted at some other point during the transformation. This is fine.
|
|
@@ -1636,40 +1638,52 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1636
1638
|
* @note This method is called from [[process]] when [[IModelTransformOptions.argsForProcessChanges]] are undefined, so it only needs to be called directly when processing a subset of an iModel.
|
|
1637
1639
|
* @throws [[IModelError]] If the required provenance information is not available to detect deletes.
|
|
1638
1640
|
*/
|
|
1639
|
-
async detectRelationshipDeletes() {
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1641
|
+
// public async detectRelationshipDeletes(): Promise<void> {
|
|
1642
|
+
// if (this.isReverseSynchronization) {
|
|
1643
|
+
// throw new IModelError(
|
|
1644
|
+
// IModelStatus.BadRequest,
|
|
1645
|
+
// "Cannot detect deletes when isReverseSynchronization=true"
|
|
1646
|
+
// );
|
|
1647
|
+
// }
|
|
1648
|
+
// const aspectDeleteIds: Id64String[] = [];
|
|
1649
|
+
// const sql = `
|
|
1650
|
+
// SELECT ECInstanceId, Identifier, JsonProperties
|
|
1651
|
+
// FROM ${ExternalSourceAspect.classFullName} aspect
|
|
1652
|
+
// WHERE aspect.Scope.Id=:scopeId
|
|
1653
|
+
// AND aspect.Kind=:kind
|
|
1654
|
+
// `;
|
|
1655
|
+
// const params = new QueryBinder().bindId(
|
|
1656
|
+
// "scopeId",
|
|
1657
|
+
// this.targetScopeElementId
|
|
1658
|
+
// );
|
|
1659
|
+
// params.bindString("kind", ExternalSourceAspect.Kind.Relationship);
|
|
1660
|
+
// for await (const row of this.targetDb.createQueryReader(sql, params)) {
|
|
1661
|
+
// const sourceRelInstanceId: Id64String = Id64.fromJSON(row[1]);
|
|
1662
|
+
// if (
|
|
1663
|
+
// undefined ===
|
|
1664
|
+
// this.sourceDb.relationships.tryGetInstanceProps(
|
|
1665
|
+
// ElementRefersToElements.classFullName,
|
|
1666
|
+
// sourceRelInstanceId
|
|
1667
|
+
// )
|
|
1668
|
+
// ) {
|
|
1669
|
+
// // this function exists only to support some in-imodel transformations, which must
|
|
1670
|
+
// // use the old (external source aspect) provenance method anyway so we don't need to support
|
|
1671
|
+
// // new provenance
|
|
1672
|
+
// const json: any = JSON.parse(row[2]);
|
|
1673
|
+
// const targetRelInstanceId =
|
|
1674
|
+
// json.targetRelInstanceId ?? json.provenanceRelInstanceId;
|
|
1675
|
+
// if (targetRelInstanceId) {
|
|
1676
|
+
// this.importer.deleteRelationship({
|
|
1677
|
+
// id: targetRelInstanceId,
|
|
1678
|
+
// classFullName: ElementRefersToElements.classFullName,
|
|
1679
|
+
// });
|
|
1680
|
+
// }
|
|
1681
|
+
// aspectDeleteIds.push(row.id);
|
|
1682
|
+
// }
|
|
1683
|
+
// await this._yieldManager.allowYield();
|
|
1684
|
+
// }
|
|
1685
|
+
// this.targetDb.elements.deleteAspect(aspectDeleteIds);
|
|
1686
|
+
// }
|
|
1673
1687
|
/** Transform the specified sourceRelationship into RelationshipProps for the target iModel.
|
|
1674
1688
|
* @param sourceRelationship The Relationship from the source iModel to be transformed.
|
|
1675
1689
|
* @returns RelationshipProps for the target iModel.
|
|
@@ -1710,7 +1724,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1710
1724
|
*/
|
|
1711
1725
|
async onExportElementMultiAspects(sourceAspects) {
|
|
1712
1726
|
// Transform source ElementMultiAspects into target ElementAspectProps
|
|
1713
|
-
const targetAspectPropsArray = sourceAspects.map(async (srcA) =>
|
|
1727
|
+
const targetAspectPropsArray = sourceAspects.map(async (srcA) => this.onTransformElementAspect(srcA));
|
|
1714
1728
|
sourceAspects.forEach(async (a) => {
|
|
1715
1729
|
if (!(await this.doAllReferencesExistInTarget(a))) {
|
|
1716
1730
|
this._partiallyCommittedAspectIds.add(a.id);
|
|
@@ -1883,7 +1897,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1883
1897
|
await this._tryInitChangesetData(this._options.argsForProcessChanges);
|
|
1884
1898
|
await this.context.initialize();
|
|
1885
1899
|
// need exporter initialized to do remapdeletedsourceentities.
|
|
1886
|
-
await this.exporter.initialize(this.getExportInitOpts(this._options.argsForProcessChanges ?? {}));
|
|
1900
|
+
await this.exporter.initialize(await this.getExportInitOpts(this._options.argsForProcessChanges ?? {}));
|
|
1887
1901
|
// Exporter must be initialized prior to processing changesets in order to properly handle entity recreations (an entity delete followed by an insert of that same entity).
|
|
1888
1902
|
await this.processChangesets();
|
|
1889
1903
|
this._initialized = true;
|
|
@@ -1995,7 +2009,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1995
2009
|
async processDeletedOp(change, mapOfDeletedElemIdToScopeEsas, isRelationship, alreadyImportedElementInserts, alreadyImportedModelInserts) {
|
|
1996
2010
|
// we need a connected iModel with changes to remap elements with deletions
|
|
1997
2011
|
const notConnectedModel = this.sourceDb.iTwinId === undefined;
|
|
1998
|
-
const noChanges = this.synchronizationVersion.index ===
|
|
2012
|
+
const noChanges = (await this.synchronizationVersion()).index ===
|
|
2013
|
+
this.sourceDb.changeset.index &&
|
|
1999
2014
|
(this.exporter.sourceDbChanges === undefined ||
|
|
2000
2015
|
!this.exporter.sourceDbChanges.hasChanges);
|
|
2001
2016
|
if (notConnectedModel || noChanges)
|
|
@@ -2004,7 +2019,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2004
2019
|
* if our ChangedECInstance is in the provenanceDb, then we can use the ids we find in the ChangedECInstance to query for ESAs.
|
|
2005
2020
|
* This is because the ESAs are stored on an element Id thats present in the provenanceDb.
|
|
2006
2021
|
*/
|
|
2007
|
-
const changeDataInProvenanceDb = this.sourceDb === this.provenanceDb;
|
|
2022
|
+
const changeDataInProvenanceDb = this.sourceDb === (await this.provenanceDb());
|
|
2008
2023
|
const getTargetIdFromSourceId = async (id) => {
|
|
2009
2024
|
let identifierValue;
|
|
2010
2025
|
let element;
|
|
@@ -2052,7 +2067,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2052
2067
|
targetIdInTarget: targetIdOfRelationshipInTarget,
|
|
2053
2068
|
});
|
|
2054
2069
|
}
|
|
2055
|
-
else if (this.sourceDb === this.provenanceSourceDb) {
|
|
2070
|
+
else if (this.sourceDb === (await this.provenanceSourceDb())) {
|
|
2056
2071
|
const relProvenance = await this._queryProvenanceForRelationship(changedInstanceId, {
|
|
2057
2072
|
classFullName: classFullName ?? "",
|
|
2058
2073
|
sourceId: sourceIdOfRelationshipInSource,
|
|
@@ -2068,7 +2083,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2068
2083
|
}
|
|
2069
2084
|
else {
|
|
2070
2085
|
let targetId = await getTargetIdFromSourceId(changedInstanceId);
|
|
2071
|
-
if (targetId === undefined &&
|
|
2086
|
+
if (targetId === undefined &&
|
|
2087
|
+
this.sourceDb === (await this.provenanceSourceDb())) {
|
|
2072
2088
|
targetId = await this._queryProvenanceForElement(changedInstanceId);
|
|
2073
2089
|
}
|
|
2074
2090
|
// since we are processing one changeset at a time, we can see local source deletes
|
|
@@ -2097,7 +2113,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2097
2113
|
this._sourceChangeDataState = "unconnected";
|
|
2098
2114
|
return;
|
|
2099
2115
|
}
|
|
2100
|
-
const
|
|
2116
|
+
const syncVersion = await this.synchronizationVersion();
|
|
2117
|
+
const noChanges = syncVersion.index === this.sourceDb.changeset.index;
|
|
2101
2118
|
if (noChanges) {
|
|
2102
2119
|
this._sourceChangeDataState = "no-changes";
|
|
2103
2120
|
this._csFileProps = [];
|
|
@@ -2106,9 +2123,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2106
2123
|
const startChangeset = "startChangeset" in args ? args.startChangeset : undefined;
|
|
2107
2124
|
// NOTE: that we do NOT download the changesummary for the last transformed version, we want
|
|
2108
2125
|
// to ignore those already processed changes
|
|
2109
|
-
const startChangesetIndexOrId = startChangeset?.index ??
|
|
2110
|
-
startChangeset?.id ??
|
|
2111
|
-
this.synchronizationVersion.index + 1;
|
|
2126
|
+
const startChangesetIndexOrId = startChangeset?.index ?? startChangeset?.id ?? syncVersion.index + 1;
|
|
2112
2127
|
const endChangesetId = this.sourceDb.changeset.id;
|
|
2113
2128
|
const [startChangesetIndex, endChangesetIndex] = await Promise.all([startChangesetIndexOrId, endChangesetId].map(async (indexOrId) => typeof indexOrId === "number"
|
|
2114
2129
|
? indexOrId
|
|
@@ -2116,21 +2131,21 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2116
2131
|
iModelId: this.sourceDb.iModelId,
|
|
2117
2132
|
changeset: { id: indexOrId },
|
|
2118
2133
|
}).then((changeset) => changeset.index)));
|
|
2119
|
-
const missingChangesets = startChangesetIndex >
|
|
2134
|
+
const missingChangesets = startChangesetIndex > syncVersion.index + 1;
|
|
2120
2135
|
if (!this._options.argsForProcessChanges
|
|
2121
2136
|
?.ignoreMissingChangesetsInSynchronizations &&
|
|
2122
|
-
startChangesetIndex !==
|
|
2123
|
-
|
|
2137
|
+
startChangesetIndex !== syncVersion.index + 1 &&
|
|
2138
|
+
syncVersion.index !== -1) {
|
|
2124
2139
|
throw Error(`synchronization is ${missingChangesets ? "missing changesets" : ""},` +
|
|
2125
2140
|
" startChangesetId should be" +
|
|
2126
2141
|
" exactly the first changeset *after* the previous synchronization to not miss data." +
|
|
2127
2142
|
` You specified '${startChangesetIndexOrId}' which is changeset #${startChangesetIndex}` +
|
|
2128
|
-
` but the previous synchronization for this
|
|
2129
|
-
` which is changeset #${
|
|
2130
|
-
` #${
|
|
2143
|
+
` but the previous synchronization for this targetScopeElem ${syncVersion.id}'` +
|
|
2144
|
+
` which is changeset #${syncVersion.index}. The transformer expected` +
|
|
2145
|
+
` #${syncVersion.index + 1}.`);
|
|
2131
2146
|
}
|
|
2132
2147
|
nodeAssert(this._targetScopeProvenanceProps, "_targetScopeProvenanceProps should be set by now");
|
|
2133
|
-
const changesetsToSkip = this.
|
|
2148
|
+
const changesetsToSkip = (await this.getIsReverseSynchronization())
|
|
2134
2149
|
? this._targetScopeProvenanceProps.jsonProperties
|
|
2135
2150
|
.pendingReverseSyncChangesetIndices
|
|
2136
2151
|
: this._targetScopeProvenanceProps.jsonProperties
|
|
@@ -2204,15 +2219,14 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2204
2219
|
await this.exporter.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
|
|
2205
2220
|
if (this._options.forceExternalSourceAspectProvenance &&
|
|
2206
2221
|
this.shouldDetectDeletes()) {
|
|
2207
|
-
|
|
2208
|
-
await this.detectElementDeletes();
|
|
2209
|
-
//
|
|
2210
|
-
await this.detectRelationshipDeletes();
|
|
2222
|
+
core_bentley_1.Logger.logWarning(loggerCategory, "This workflows was deprecated in v1 and is no longer supported");
|
|
2223
|
+
// await this.detectElementDeletes();
|
|
2224
|
+
// await this.detectRelationshipDeletes();
|
|
2211
2225
|
}
|
|
2212
2226
|
if (this._options.optimizeGeometry)
|
|
2213
2227
|
this.importer.optimizeGeometry(this._options.optimizeGeometry);
|
|
2214
2228
|
this.importer.computeProjectExtents();
|
|
2215
|
-
this.finalizeTransformation();
|
|
2229
|
+
await this.finalizeTransformation();
|
|
2216
2230
|
}
|
|
2217
2231
|
/** previous provenance, either a federation guid, a `${sourceFedGuid}/${targetFedGuid}` pair, or required aspect props */
|
|
2218
2232
|
_lastProvenanceEntityInfo = nullLastProvenanceEntityInfo;
|
|
@@ -2240,13 +2254,13 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2240
2254
|
*/
|
|
2241
2255
|
async processChanges(options) {
|
|
2242
2256
|
// must wait for initialization of synchronization provenance data
|
|
2243
|
-
await this.exporter.exportChanges(this.getExportInitOpts(options));
|
|
2257
|
+
await this.exporter.exportChanges(await this.getExportInitOpts(options));
|
|
2244
2258
|
await this.completePartiallyCommittedElements();
|
|
2245
2259
|
await this.completePartiallyCommittedAspects();
|
|
2246
2260
|
if (this._options.optimizeGeometry)
|
|
2247
2261
|
this.importer.optimizeGeometry(this._options.optimizeGeometry);
|
|
2248
2262
|
this.importer.computeProjectExtents();
|
|
2249
|
-
this.finalizeTransformation();
|
|
2263
|
+
await this.finalizeTransformation();
|
|
2250
2264
|
const defaultSaveTargetChanges = () => {
|
|
2251
2265
|
this.targetDb.saveChanges();
|
|
2252
2266
|
};
|
|
@@ -2255,7 +2269,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2255
2269
|
/** Changeset data must be initialized in order to build correct changeOptions.
|
|
2256
2270
|
* Call [[IModelTransformer.initialize]] for initialization of synchronization provenance data
|
|
2257
2271
|
*/
|
|
2258
|
-
getExportInitOpts(opts) {
|
|
2272
|
+
async getExportInitOpts(opts) {
|
|
2259
2273
|
if (!this._options.argsForProcessChanges)
|
|
2260
2274
|
return {};
|
|
2261
2275
|
const startChangeset = "startChangeset" in opts ? opts.startChangeset : undefined;
|
|
@@ -2269,7 +2283,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2269
2283
|
? { startChangeset }
|
|
2270
2284
|
: {
|
|
2271
2285
|
startChangeset: {
|
|
2272
|
-
index: this.synchronizationVersion.index + 1,
|
|
2286
|
+
index: (await this.synchronizationVersion()).index + 1,
|
|
2273
2287
|
},
|
|
2274
2288
|
}),
|
|
2275
2289
|
};
|
|
@@ -2389,18 +2403,16 @@ class TemplateModelCloner extends IModelTransformer {
|
|
|
2389
2403
|
}
|
|
2390
2404
|
exports.TemplateModelCloner = TemplateModelCloner;
|
|
2391
2405
|
//Deprecate in preference of imodeldb.elements.getFederationGuidFromId()?
|
|
2392
|
-
function queryElemFedGuid(db, elemId) {
|
|
2393
|
-
|
|
2394
|
-
return db.withPreparedStatement(`
|
|
2406
|
+
async function queryElemFedGuid(db, elemId) {
|
|
2407
|
+
const sql = `
|
|
2395
2408
|
SELECT FederationGuid
|
|
2396
2409
|
FROM bis.Element
|
|
2397
2410
|
WHERE ECInstanceId=?
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
});
|
|
2411
|
+
`;
|
|
2412
|
+
const params = new core_common_1.QueryBinder().bindId(1, elemId);
|
|
2413
|
+
const reader = db.createQueryReader(sql, params);
|
|
2414
|
+
(0, core_bentley_1.assert)(await reader.step(), "element not found");
|
|
2415
|
+
const result = reader.current.federationGuid;
|
|
2416
|
+
return result;
|
|
2405
2417
|
}
|
|
2406
2418
|
//# sourceMappingURL=IModelTransformer.js.map
|