@itwin/imodel-transformer 2.0.0-dev.72 → 2.0.0-dev.74
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/README.md +11 -0
- package/lib/Algo.d.ts.map +1 -0
- package/lib/{cjs/Algo.js → Algo.js} +1 -4
- package/lib/Algo.js.map +1 -0
- package/lib/BigMap.d.ts.map +1 -0
- package/lib/{cjs/BigMap.js → BigMap.js} +1 -5
- package/lib/BigMap.js.map +1 -0
- package/lib/BranchProvenanceInitializer.d.ts.map +1 -0
- package/lib/{cjs/BranchProvenanceInitializer.js → BranchProvenanceInitializer.js} +34 -37
- package/lib/BranchProvenanceInitializer.js.map +1 -0
- package/lib/ChangedElementForest.d.ts.map +1 -0
- package/lib/{cjs/ChangedElementForest.js → ChangedElementForest.js} +12 -14
- package/lib/ChangedElementForest.js.map +1 -0
- package/lib/{cjs/ChangesetScanner.d.ts → ChangesetScanner.d.ts} +2 -2
- package/lib/ChangesetScanner.d.ts.map +1 -0
- package/lib/{cjs/ChangesetScanner.js → ChangesetScanner.js} +19 -24
- package/lib/ChangesetScanner.js.map +1 -0
- package/lib/ECReferenceTypesCache.d.ts.map +1 -0
- package/lib/{cjs/ECReferenceTypesCache.js → ECReferenceTypesCache.js} +32 -37
- package/lib/ECReferenceTypesCache.js.map +1 -0
- package/lib/ECSqlReaderAsyncIterableIteratorAdapter.d.ts.map +1 -0
- package/lib/{cjs/ECSqlReaderAsyncIterableIteratorAdapter.js → ECSqlReaderAsyncIterableIteratorAdapter.js} +2 -7
- package/lib/ECSqlReaderAsyncIterableIteratorAdapter.js.map +1 -0
- package/lib/ElementAspectCleanup.d.ts.map +1 -0
- package/lib/{cjs/ElementAspectCleanup.js → ElementAspectCleanup.js} +9 -13
- package/lib/ElementAspectCleanup.js.map +1 -0
- package/lib/ElementAspectExportCoordinator.d.ts.map +1 -0
- package/lib/{cjs/ElementAspectExportCoordinator.js → ElementAspectExportCoordinator.js} +1 -5
- package/lib/ElementAspectExportCoordinator.js.map +1 -0
- package/lib/ElementAspectExportProcessor.d.ts.map +1 -0
- package/lib/{cjs/ElementAspectExportProcessor.js → ElementAspectExportProcessor.js} +10 -14
- package/lib/ElementAspectExportProcessor.js.map +1 -0
- package/lib/ElementBulkDelete.d.ts.map +1 -0
- package/lib/{cjs/ElementBulkDelete.js → ElementBulkDelete.js} +9 -12
- package/lib/{cjs/ElementBulkDelete.js.map → ElementBulkDelete.js.map} +1 -1
- package/lib/EntityExistenceCache.d.ts.map +1 -0
- package/lib/{cjs/EntityExistenceCache.js → EntityExistenceCache.js} +4 -8
- package/lib/EntityExistenceCache.js.map +1 -0
- package/lib/EntityUnifier.d.ts.map +1 -0
- package/lib/{cjs/EntityUnifier.js → EntityUnifier.js} +21 -22
- package/lib/EntityUnifier.js.map +1 -0
- package/lib/{cjs/IModelCloneContext.d.ts → IModelCloneContext.d.ts} +2 -2
- package/lib/IModelCloneContext.d.ts.map +1 -0
- package/lib/{cjs/IModelCloneContext.js → IModelCloneContext.js} +52 -56
- package/lib/IModelCloneContext.js.map +1 -0
- package/lib/{cjs/IModelExporter.d.ts → IModelExporter.d.ts} +1 -1
- package/lib/IModelExporter.d.ts.map +1 -0
- package/lib/{cjs/IModelExporter.js → IModelExporter.js} +165 -174
- package/lib/IModelExporter.js.map +1 -0
- package/lib/{cjs/IModelImporter.d.ts → IModelImporter.d.ts} +3 -3
- package/lib/IModelImporter.d.ts.map +1 -0
- package/lib/{cjs/IModelImporter.js → IModelImporter.js} +104 -109
- package/lib/IModelImporter.js.map +1 -0
- package/lib/IModelTransformContext.d.ts.map +1 -0
- package/lib/IModelTransformContext.js +2 -0
- package/lib/IModelTransformContext.js.map +1 -0
- package/lib/{cjs/IModelTransformer.d.ts → IModelTransformer.d.ts} +9 -6
- package/lib/IModelTransformer.d.ts.map +1 -0
- package/lib/{cjs/IModelTransformer.js → IModelTransformer.js} +297 -337
- package/lib/IModelTransformer.js.map +1 -0
- package/lib/IModelTransformerError.d.ts.map +1 -0
- package/lib/{cjs/IModelTransformerError.js → IModelTransformerError.js} +3 -6
- package/lib/IModelTransformerError.js.map +1 -0
- package/lib/{cjs/ProvenanceManager.d.ts → ProvenanceManager.d.ts} +3 -3
- package/lib/ProvenanceManager.d.ts.map +1 -0
- package/lib/{cjs/ProvenanceManager.js → ProvenanceManager.js} +69 -73
- package/lib/ProvenanceManager.js.map +1 -0
- package/lib/SourceClassKinds.d.ts.map +1 -0
- package/lib/{cjs/SourceClassKinds.js → SourceClassKinds.js} +1 -5
- package/lib/SourceClassKinds.js.map +1 -0
- package/lib/SyncTypeResolver.d.ts.map +1 -0
- package/lib/{cjs/SyncTypeResolver.js → SyncTypeResolver.js} +15 -19
- package/lib/SyncTypeResolver.js.map +1 -0
- package/lib/TransformerLoggerCategory.d.ts.map +1 -0
- package/lib/{cjs/TransformerLoggerCategory.js → TransformerLoggerCategory.js} +2 -5
- package/lib/TransformerLoggerCategory.js.map +1 -0
- package/lib/TransformerPackageMetadata.d.ts.map +1 -0
- package/lib/TransformerPackageMetadata.js +8 -0
- package/lib/TransformerPackageMetadata.js.map +1 -0
- package/lib/{cjs/imodel-transformer.d.ts → imodel-transformer.d.ts} +9 -9
- package/lib/imodel-transformer.d.ts.map +1 -0
- package/lib/imodel-transformer.js +88 -0
- package/lib/imodel-transformer.js.map +1 -0
- package/lib/{cjs/schema-processing → schema-processing}/DynamicSchemaUnionStrategy.d.ts +1 -1
- package/lib/schema-processing/DynamicSchemaUnionStrategy.d.ts.map +1 -0
- package/lib/{cjs/schema-processing → schema-processing}/DynamicSchemaUnionStrategy.js +16 -20
- package/lib/schema-processing/DynamicSchemaUnionStrategy.js.map +1 -0
- package/lib/{cjs/schema-processing → schema-processing}/SchemaProcessingCoordinator.d.ts +2 -2
- package/lib/schema-processing/SchemaProcessingCoordinator.d.ts.map +1 -0
- package/lib/{cjs/schema-processing → schema-processing}/SchemaProcessingCoordinator.js +15 -52
- package/lib/schema-processing/SchemaProcessingCoordinator.js.map +1 -0
- package/lib/schema-processing/SchemaProcessingStrategy.d.ts.map +1 -0
- package/lib/{cjs/schema-processing → schema-processing}/SchemaProcessingStrategy.js +1 -5
- package/lib/schema-processing/SchemaProcessingStrategy.js.map +1 -0
- package/lib/schema-processing.d.ts +7 -0
- package/lib/schema-processing.d.ts.map +1 -0
- package/lib/schema-processing.js +11 -0
- package/lib/schema-processing.js.map +1 -0
- package/package.json +14 -14
- package/lib/cjs/Algo.d.ts.map +0 -1
- package/lib/cjs/Algo.js.map +0 -1
- package/lib/cjs/BigMap.d.ts.map +0 -1
- package/lib/cjs/BigMap.js.map +0 -1
- package/lib/cjs/BranchProvenanceInitializer.d.ts.map +0 -1
- package/lib/cjs/BranchProvenanceInitializer.js.map +0 -1
- package/lib/cjs/ChangedElementForest.d.ts.map +0 -1
- package/lib/cjs/ChangedElementForest.js.map +0 -1
- package/lib/cjs/ChangesetScanner.d.ts.map +0 -1
- package/lib/cjs/ChangesetScanner.js.map +0 -1
- package/lib/cjs/ECReferenceTypesCache.d.ts.map +0 -1
- package/lib/cjs/ECReferenceTypesCache.js.map +0 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.d.ts.map +0 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.js.map +0 -1
- package/lib/cjs/ElementAspectCleanup.d.ts.map +0 -1
- package/lib/cjs/ElementAspectCleanup.js.map +0 -1
- package/lib/cjs/ElementAspectExportCoordinator.d.ts.map +0 -1
- package/lib/cjs/ElementAspectExportCoordinator.js.map +0 -1
- package/lib/cjs/ElementAspectExportProcessor.d.ts.map +0 -1
- package/lib/cjs/ElementAspectExportProcessor.js.map +0 -1
- package/lib/cjs/ElementBulkDelete.d.ts.map +0 -1
- package/lib/cjs/EntityExistenceCache.d.ts.map +0 -1
- package/lib/cjs/EntityExistenceCache.js.map +0 -1
- package/lib/cjs/EntityUnifier.d.ts.map +0 -1
- package/lib/cjs/EntityUnifier.js.map +0 -1
- package/lib/cjs/IModelCloneContext.d.ts.map +0 -1
- package/lib/cjs/IModelCloneContext.js.map +0 -1
- package/lib/cjs/IModelExporter.d.ts.map +0 -1
- package/lib/cjs/IModelExporter.js.map +0 -1
- package/lib/cjs/IModelImporter.d.ts.map +0 -1
- package/lib/cjs/IModelImporter.js.map +0 -1
- package/lib/cjs/IModelTransformContext.d.ts.map +0 -1
- package/lib/cjs/IModelTransformContext.js +0 -3
- package/lib/cjs/IModelTransformContext.js.map +0 -1
- package/lib/cjs/IModelTransformer.d.ts.map +0 -1
- package/lib/cjs/IModelTransformer.js.map +0 -1
- package/lib/cjs/IModelTransformerError.d.ts.map +0 -1
- package/lib/cjs/IModelTransformerError.js.map +0 -1
- package/lib/cjs/ProvenanceManager.d.ts.map +0 -1
- package/lib/cjs/ProvenanceManager.js.map +0 -1
- package/lib/cjs/SourceClassKinds.d.ts.map +0 -1
- package/lib/cjs/SourceClassKinds.js.map +0 -1
- package/lib/cjs/SyncTypeResolver.d.ts.map +0 -1
- package/lib/cjs/SyncTypeResolver.js.map +0 -1
- package/lib/cjs/TransformerLoggerCategory.d.ts.map +0 -1
- package/lib/cjs/TransformerLoggerCategory.js.map +0 -1
- package/lib/cjs/TransformerPackageMetadata.d.ts.map +0 -1
- package/lib/cjs/TransformerPackageMetadata.js +0 -47
- package/lib/cjs/TransformerPackageMetadata.js.map +0 -1
- package/lib/cjs/imodel-transformer.d.ts.map +0 -1
- package/lib/cjs/imodel-transformer.js +0 -125
- package/lib/cjs/imodel-transformer.js.map +0 -1
- package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.d.ts.map +0 -1
- package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.js.map +0 -1
- package/lib/cjs/schema-processing/SchemaProcessingCoordinator.d.ts.map +0 -1
- package/lib/cjs/schema-processing/SchemaProcessingCoordinator.js.map +0 -1
- package/lib/cjs/schema-processing/SchemaProcessingStrategy.d.ts.map +0 -1
- package/lib/cjs/schema-processing/SchemaProcessingStrategy.js.map +0 -1
- package/lib/cjs/schema-processing.d.ts +0 -7
- package/lib/cjs/schema-processing.d.ts.map +0 -1
- package/lib/cjs/schema-processing.js +0 -27
- package/lib/cjs/schema-processing.js.map +0 -1
- /package/lib/{cjs/Algo.d.ts → Algo.d.ts} +0 -0
- /package/lib/{cjs/BigMap.d.ts → BigMap.d.ts} +0 -0
- /package/lib/{cjs/BranchProvenanceInitializer.d.ts → BranchProvenanceInitializer.d.ts} +0 -0
- /package/lib/{cjs/ChangedElementForest.d.ts → ChangedElementForest.d.ts} +0 -0
- /package/lib/{cjs/ECReferenceTypesCache.d.ts → ECReferenceTypesCache.d.ts} +0 -0
- /package/lib/{cjs/ECSqlReaderAsyncIterableIteratorAdapter.d.ts → ECSqlReaderAsyncIterableIteratorAdapter.d.ts} +0 -0
- /package/lib/{cjs/ElementAspectCleanup.d.ts → ElementAspectCleanup.d.ts} +0 -0
- /package/lib/{cjs/ElementAspectExportCoordinator.d.ts → ElementAspectExportCoordinator.d.ts} +0 -0
- /package/lib/{cjs/ElementAspectExportProcessor.d.ts → ElementAspectExportProcessor.d.ts} +0 -0
- /package/lib/{cjs/ElementBulkDelete.d.ts → ElementBulkDelete.d.ts} +0 -0
- /package/lib/{cjs/EntityExistenceCache.d.ts → EntityExistenceCache.d.ts} +0 -0
- /package/lib/{cjs/EntityUnifier.d.ts → EntityUnifier.d.ts} +0 -0
- /package/lib/{cjs/IModelTransformContext.d.ts → IModelTransformContext.d.ts} +0 -0
- /package/lib/{cjs/IModelTransformerError.d.ts → IModelTransformerError.d.ts} +0 -0
- /package/lib/{cjs/SourceClassKinds.d.ts → SourceClassKinds.d.ts} +0 -0
- /package/lib/{cjs/SyncTypeResolver.d.ts → SyncTypeResolver.d.ts} +0 -0
- /package/lib/{cjs/TransformerLoggerCategory.d.ts → TransformerLoggerCategory.d.ts} +0 -0
- /package/lib/{cjs/TransformerPackageMetadata.d.ts → TransformerPackageMetadata.d.ts} +0 -0
- /package/lib/{cjs/schema-processing → schema-processing}/SchemaProcessingStrategy.d.ts +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/*---------------------------------------------------------------------------------------------
|
|
3
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -6,28 +5,28 @@
|
|
|
6
5
|
/** @packageDocumentation
|
|
7
6
|
* @module iModels
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const loggerCategory =
|
|
8
|
+
import { BriefcaseManager, DefinitionModel,
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
10
|
+
Element, ElementMultiAspect, ElementRefersToElements, ElementUniqueAspect, GeometricElement, Model, RecipeDefinitionElement, } from "@itwin/core-backend";
|
|
11
|
+
import { assert, Id64, IModelStatus, ITwinError, JsonUtils, Logger, YieldManager, } from "@itwin/core-bentley";
|
|
12
|
+
import { Base64EncodedString, ECJsNames, IModel, IModelError, QueryBinder, } from "@itwin/core-common";
|
|
13
|
+
import { ECVersion, SchemaKey } from "@itwin/ecschema-metadata";
|
|
14
|
+
import { TransformerLoggerCategory } from "./TransformerLoggerCategory.js";
|
|
15
|
+
import { strict as nodeAssert } from "node:assert";
|
|
16
|
+
import { ElementAspectExportProcessor } from "./ElementAspectExportProcessor.js";
|
|
17
|
+
import { ElementAspectExportCoordinator } from "./ElementAspectExportCoordinator.js";
|
|
18
|
+
import { IModelTransformerError, IModelTransformerErrorScope, } from "./IModelTransformerError.js";
|
|
19
|
+
import { ChangesetScanner } from "./ChangesetScanner.js";
|
|
20
|
+
import { SourceClassKinds } from "./SourceClassKinds.js";
|
|
21
|
+
import { ChangedElementForest } from "./ChangedElementForest.js";
|
|
22
|
+
const loggerCategory = TransformerLoggerCategory.IModelExporter;
|
|
24
23
|
/** Handles the events generated by IModelExporter.
|
|
25
24
|
* @note Change information is available when `IModelExportHandler` methods are invoked via [IModelExporter.exportChanges]($transformer), but not available when invoked via [IModelExporter.exportAll]($transformer).
|
|
26
25
|
* @note The handler is intended to be owned by (registered with) and called from the IModelExporter exclusively
|
|
27
26
|
* @see [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md), [IModelExporter]($transformer)
|
|
28
27
|
* @beta
|
|
29
28
|
*/
|
|
30
|
-
class IModelExportHandler {
|
|
29
|
+
export class IModelExportHandler {
|
|
31
30
|
/** If `true` is returned, then the CodeSpec will be exported.
|
|
32
31
|
* @note This method can optionally be overridden to exclude an individual CodeSpec from the export. The base implementation always returns `true`.
|
|
33
32
|
*/
|
|
@@ -131,7 +130,6 @@ class IModelExportHandler {
|
|
|
131
130
|
*/
|
|
132
131
|
async onProgress() { }
|
|
133
132
|
}
|
|
134
|
-
exports.IModelExportHandler = IModelExportHandler;
|
|
135
133
|
/** Base class for exporting data from an iModel.
|
|
136
134
|
* @note Most uses cases will not require a custom subclass of `IModelExporter`. Instead, it is more typical to subclass/customize [IModelExportHandler]($transformer).
|
|
137
135
|
* ElementAspects are exported separately from element callbacks in bounded,
|
|
@@ -140,7 +138,7 @@ exports.IModelExportHandler = IModelExportHandler;
|
|
|
140
138
|
* @see [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md), [[registerHandler]], [IModelTransformer]($transformer), [IModelImporter]($transformer)
|
|
141
139
|
* @beta
|
|
142
140
|
*/
|
|
143
|
-
class IModelExporter {
|
|
141
|
+
export class IModelExporter {
|
|
144
142
|
static _elementAspectOwnerBatchSize = 1000;
|
|
145
143
|
/** The read-only source iModel. */
|
|
146
144
|
sourceDb;
|
|
@@ -193,10 +191,10 @@ class IModelExporter {
|
|
|
193
191
|
/** The handler called by this IModelExporter. */
|
|
194
192
|
get handler() {
|
|
195
193
|
if (undefined === this._handler) {
|
|
196
|
-
|
|
194
|
+
ITwinError.throwError({
|
|
197
195
|
iTwinErrorId: {
|
|
198
|
-
scope:
|
|
199
|
-
key:
|
|
196
|
+
scope: IModelTransformerErrorScope,
|
|
197
|
+
key: IModelTransformerError.ExportHandlerNotRegistered,
|
|
200
198
|
},
|
|
201
199
|
message: "IModelExportHandler not registered",
|
|
202
200
|
});
|
|
@@ -226,9 +224,9 @@ class IModelExporter {
|
|
|
226
224
|
/** Whether change traversal skips root-owned entities. */
|
|
227
225
|
_skipPropagateChangesToRootElements = false;
|
|
228
226
|
_rootElementIds = new Set([
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
227
|
+
IModel.rootSubjectId,
|
|
228
|
+
IModel.repositoryModelId,
|
|
229
|
+
IModel.dictionaryId,
|
|
232
230
|
"0xe", // The reality-data-sources modelId, skipped with root propagation.
|
|
233
231
|
]);
|
|
234
232
|
/** Construct a new IModelExporter
|
|
@@ -237,13 +235,13 @@ class IModelExporter {
|
|
|
237
235
|
*/
|
|
238
236
|
constructor(sourceDb) {
|
|
239
237
|
this.sourceDb = sourceDb;
|
|
240
|
-
this._elementAspectExportProcessor = new
|
|
238
|
+
this._elementAspectExportProcessor = new ElementAspectExportProcessor(this.sourceDb, {
|
|
241
239
|
onExportElementMultiAspects: async (aspects) => this.handler.onExportElementMultiAspects(aspects),
|
|
242
240
|
onExportElementUniqueAspect: async (aspect, isUpdate) => this.handler.onExportElementUniqueAspect(aspect, isUpdate),
|
|
243
241
|
shouldExportElementAspect: async (aspect) => this.handler.shouldExportElementAspect(aspect),
|
|
244
242
|
trackProgress: async () => this.trackProgress(),
|
|
245
243
|
});
|
|
246
|
-
this._elementAspectExportCoordinator = new
|
|
244
|
+
this._elementAspectExportCoordinator = new ElementAspectExportCoordinator(IModelExporter._elementAspectOwnerBatchSize, () => this._elementAspectExportProcessor.excludedElementAspectClassFullNames, async (elementIds) => this._elementAspectExportProcessor.exportAllElementAspects(elementIds), () => this._elementAspectExportProcessor.resetCaches());
|
|
247
245
|
}
|
|
248
246
|
/**
|
|
249
247
|
* Initialize prerequisites of exporting. This is implicitly done by any `export*` calls that need initialization
|
|
@@ -300,8 +298,8 @@ class IModelExporter {
|
|
|
300
298
|
await this.initialize({});
|
|
301
299
|
await this.exportCodeSpecs();
|
|
302
300
|
await this.exportFonts();
|
|
303
|
-
await this._elementAspectExportCoordinator.run(async () => this.exportModel(
|
|
304
|
-
await this.exportRelationships(
|
|
301
|
+
await this._elementAspectExportCoordinator.run(async () => this.exportModel(IModel.repositoryModelId));
|
|
302
|
+
await this.exportRelationships(ElementRefersToElements.classFullName);
|
|
305
303
|
}
|
|
306
304
|
/** Export changes from the source iModel.
|
|
307
305
|
* Inserts, updates, and deletes are determined by inspecting the changeset(s).
|
|
@@ -313,10 +311,10 @@ class IModelExporter {
|
|
|
313
311
|
*/
|
|
314
312
|
async exportChanges(args) {
|
|
315
313
|
if (!this.sourceDb.isBriefcaseDb())
|
|
316
|
-
|
|
314
|
+
ITwinError.throwError({
|
|
317
315
|
iTwinErrorId: {
|
|
318
|
-
scope:
|
|
319
|
-
key:
|
|
316
|
+
scope: IModelTransformerErrorScope,
|
|
317
|
+
key: IModelTransformerError.ExportChangesRequiresBriefcase,
|
|
320
318
|
},
|
|
321
319
|
message: "Must be a briefcase to export changes",
|
|
322
320
|
});
|
|
@@ -334,10 +332,10 @@ class IModelExporter {
|
|
|
334
332
|
}
|
|
335
333
|
await this.initialize(initOpts);
|
|
336
334
|
if (currentChangesetId === "" && !this.sourceDbChanges?.hasChanges) {
|
|
337
|
-
|
|
335
|
+
ITwinError.throwError({
|
|
338
336
|
iTwinErrorId: {
|
|
339
|
-
scope:
|
|
340
|
-
key:
|
|
337
|
+
scope: IModelTransformerErrorScope,
|
|
338
|
+
key: IModelTransformerError.NoChangesets,
|
|
341
339
|
},
|
|
342
340
|
message: "Cannot export changes because the source iModel has no changesets or custom changes. Call exportAll() to export all content.",
|
|
343
341
|
});
|
|
@@ -345,22 +343,22 @@ class IModelExporter {
|
|
|
345
343
|
this._skipPropagateChangesToRootElements =
|
|
346
344
|
initOpts.skipPropagateChangesToRootElements ?? false;
|
|
347
345
|
// _sourceDbChanges are initialized in this.initialize
|
|
348
|
-
(
|
|
346
|
+
nodeAssert(this._sourceDbChanges !== undefined, "sourceDbChanges must be initialized.");
|
|
349
347
|
await this.exportCodeSpecs();
|
|
350
348
|
await this.exportFonts();
|
|
351
|
-
(
|
|
349
|
+
nodeAssert(this.beginChangedElementTraversalScope(), "exportChanges must own its changed-element traversal scope");
|
|
352
350
|
try {
|
|
353
351
|
await this._elementAspectExportCoordinator.run(async () => {
|
|
354
352
|
if (initOpts.skipPropagateChangesToRootElements) {
|
|
355
353
|
// The root Subject is in the RepositoryModel. Traverse its children
|
|
356
354
|
// separately, then export other top-level repository elements while
|
|
357
355
|
// excluding the root so no element is visited twice.
|
|
358
|
-
await this.exportChildElements(
|
|
359
|
-
await this.exportModelContents(
|
|
360
|
-
await this.exportSubModels(
|
|
356
|
+
await this.exportChildElements(IModel.rootSubjectId);
|
|
357
|
+
await this.exportModelContents(IModel.repositoryModelId, Element.classFullName, true);
|
|
358
|
+
await this.exportSubModels(IModel.repositoryModelId);
|
|
361
359
|
}
|
|
362
360
|
else {
|
|
363
|
-
await this.exportModel(
|
|
361
|
+
await this.exportModel(IModel.repositoryModelId);
|
|
364
362
|
}
|
|
365
363
|
});
|
|
366
364
|
const aspectOnlyOwnerElementIds = new Set(this._sourceDbChanges.aspectOwnerElementIds);
|
|
@@ -375,7 +373,7 @@ class IModelExporter {
|
|
|
375
373
|
finally {
|
|
376
374
|
this.endChangedElementTraversalScope();
|
|
377
375
|
}
|
|
378
|
-
await this.exportRelationships(
|
|
376
|
+
await this.exportRelationships(ElementRefersToElements.classFullName);
|
|
379
377
|
// handle deletes
|
|
380
378
|
if (this.visitElements) {
|
|
381
379
|
// must delete models first since they have a constraint on the submodeling element which may also be deleted
|
|
@@ -420,13 +418,13 @@ class IModelExporter {
|
|
|
420
418
|
for await (const row of this.sourceDb.createQueryReader(sql, undefined, {
|
|
421
419
|
usePrimaryConn: true,
|
|
422
420
|
})) {
|
|
423
|
-
const schemaKey = new
|
|
421
|
+
const schemaKey = new SchemaKey(row[0], new ECVersion(row[1], row[2], row[3]));
|
|
424
422
|
const schema = await this.sourceDb.schemaContext.getSchema(schemaKey);
|
|
425
423
|
if (!schema) {
|
|
426
|
-
|
|
424
|
+
ITwinError.throwError({
|
|
427
425
|
iTwinErrorId: {
|
|
428
|
-
scope:
|
|
429
|
-
key:
|
|
426
|
+
scope: IModelTransformerErrorScope,
|
|
427
|
+
key: IModelTransformerError.SchemaLoadFailed,
|
|
430
428
|
},
|
|
431
429
|
message: `Failed to load schema: ${schemaKey.name}`,
|
|
432
430
|
});
|
|
@@ -445,7 +443,7 @@ class IModelExporter {
|
|
|
445
443
|
}
|
|
446
444
|
}
|
|
447
445
|
await Promise.all(schemasToExport.map(async (schema) => {
|
|
448
|
-
|
|
446
|
+
Logger.logTrace(loggerCategory, `exportSchema(${schema.name})`);
|
|
449
447
|
return this.handler.onExportSchema(schema);
|
|
450
448
|
}));
|
|
451
449
|
}
|
|
@@ -457,7 +455,7 @@ class IModelExporter {
|
|
|
457
455
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
458
456
|
*/
|
|
459
457
|
async exportCodeSpecs() {
|
|
460
|
-
|
|
458
|
+
Logger.logTrace(loggerCategory, "exportCodeSpecs()");
|
|
461
459
|
const sql = "SELECT Name FROM BisCore:CodeSpec ORDER BY ECInstanceId";
|
|
462
460
|
for await (const row of this.sourceDb.createQueryReader(sql, undefined, {
|
|
463
461
|
usePrimaryConn: true,
|
|
@@ -485,12 +483,12 @@ class IModelExporter {
|
|
|
485
483
|
}
|
|
486
484
|
// passed changeset test, now apply standard exclusion rules
|
|
487
485
|
if (this._excludedCodeSpecNames.has(codeSpec.name)) {
|
|
488
|
-
|
|
486
|
+
Logger.logInfo(loggerCategory, `Excluding CodeSpec: ${codeSpec.name}`);
|
|
489
487
|
return;
|
|
490
488
|
}
|
|
491
489
|
// CodeSpec has passed standard exclusion rules, now give handler a chance to accept/reject export
|
|
492
490
|
if (await this.handler.shouldExportCodeSpec(codeSpec)) {
|
|
493
|
-
|
|
491
|
+
Logger.logTrace(loggerCategory, `exportCodeSpec(${codeSpecName})${this.getChangeOpSuffix(isUpdate)}`);
|
|
494
492
|
await this.handler.onExportCodeSpec(codeSpec, isUpdate);
|
|
495
493
|
return this.trackProgress();
|
|
496
494
|
}
|
|
@@ -506,7 +504,7 @@ class IModelExporter {
|
|
|
506
504
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
507
505
|
*/
|
|
508
506
|
async exportFonts() {
|
|
509
|
-
|
|
507
|
+
Logger.logTrace(loggerCategory, "exportFonts()");
|
|
510
508
|
for (const font of this.sourceDb.fonts.queryMappedFamilies()) {
|
|
511
509
|
await this.exportFontByFontProps(font);
|
|
512
510
|
}
|
|
@@ -516,7 +514,7 @@ class IModelExporter {
|
|
|
516
514
|
* If not this will only export the first font with this type in the db.
|
|
517
515
|
*/
|
|
518
516
|
async exportFontByName(fontName) {
|
|
519
|
-
|
|
517
|
+
Logger.logTrace(loggerCategory, `exportFontByName(${fontName})`);
|
|
520
518
|
const fontId = this.sourceDb.fonts.findId({
|
|
521
519
|
name: fontName,
|
|
522
520
|
});
|
|
@@ -528,7 +526,7 @@ class IModelExporter {
|
|
|
528
526
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
529
527
|
*/
|
|
530
528
|
async exportFontByFontProps(fontProps) {
|
|
531
|
-
|
|
529
|
+
Logger.logTrace(loggerCategory, `exportFontByFamily(${fontProps.name}, ${fontProps.type})`);
|
|
532
530
|
await this.handler.onExportFont(fontProps, true);
|
|
533
531
|
return this.trackProgress();
|
|
534
532
|
}
|
|
@@ -536,7 +534,7 @@ class IModelExporter {
|
|
|
536
534
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
537
535
|
*/
|
|
538
536
|
async exportFontByFontFamilyDescriptor(fontFamily) {
|
|
539
|
-
|
|
537
|
+
Logger.logTrace(loggerCategory, `exportFontByFamilyDescriptor(${fontFamily.name}, ${fontFamily.type})`);
|
|
540
538
|
const fontId = await this.sourceDb.fonts.acquireId(fontFamily);
|
|
541
539
|
if (undefined !== fontId) {
|
|
542
540
|
await this.exportFontByFontProps({ ...fontFamily, id: fontId });
|
|
@@ -551,7 +549,7 @@ class IModelExporter {
|
|
|
551
549
|
* It is very rare and even problematic for the font table to reach a large size, so it is not a bottleneck in transforming changes.
|
|
552
550
|
* See https://github.com/iTwin/imodel-transformer/pull/135 for removed code.
|
|
553
551
|
*/
|
|
554
|
-
|
|
552
|
+
Logger.logTrace(loggerCategory, `exportFontById(${fontNumber})`);
|
|
555
553
|
const font = this.sourceDb.fonts.findDescriptor(fontNumber);
|
|
556
554
|
if (undefined !== font) {
|
|
557
555
|
await this.exportFontByFontFamilyDescriptor(font);
|
|
@@ -573,7 +571,7 @@ class IModelExporter {
|
|
|
573
571
|
wantGeometry: this.wantGeometry,
|
|
574
572
|
wantBRepData: this.wantGeometry,
|
|
575
573
|
});
|
|
576
|
-
|
|
574
|
+
Logger.logTrace(loggerCategory, `exportModel(${modeledElementId})`);
|
|
577
575
|
if (await this.shouldExportElement(modeledElement)) {
|
|
578
576
|
await this.exportModelContainer(model);
|
|
579
577
|
if (this.visitElements) {
|
|
@@ -600,24 +598,24 @@ class IModelExporter {
|
|
|
600
598
|
await this.handler.onExportModel(model, isUpdate);
|
|
601
599
|
return this.trackProgress();
|
|
602
600
|
}
|
|
603
|
-
_yieldManager = new
|
|
601
|
+
_yieldManager = new YieldManager();
|
|
604
602
|
/** Export the model contents.
|
|
605
603
|
* @param modelId The only required parameter
|
|
606
604
|
* @param elementClassFullName Can be optionally specified if the goal is to export a subset of the model contents
|
|
607
605
|
* @param skipRootSubject Decides whether or not to export the root Subject. It is normally left undefined except for internal implementation purposes.
|
|
608
606
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
609
607
|
*/
|
|
610
|
-
async exportModelContents(modelId, elementClassFullName =
|
|
608
|
+
async exportModelContents(modelId, elementClassFullName = Element.classFullName, skipRootSubject) {
|
|
611
609
|
return this.runScopedElementExport(async () => this.exportModelContentsImpl(modelId, elementClassFullName, skipRootSubject));
|
|
612
610
|
}
|
|
613
611
|
async exportModelContentsImpl(modelId, elementClassFullName, skipRootSubject) {
|
|
614
612
|
if (skipRootSubject) {
|
|
615
613
|
// NOTE: IModelTransformer.processAll should skip the root Subject since it is specific to the individual iModel and is not part of the changes that need to be synchronized
|
|
616
614
|
// NOTE: IModelExporter.exportAll should not skip the root Subject since the goal is to export everything
|
|
617
|
-
|
|
615
|
+
assert(modelId === IModel.repositoryModelId); // flag is only relevant when processing the RepositoryModel
|
|
618
616
|
}
|
|
619
617
|
if (!this.visitElements) {
|
|
620
|
-
|
|
618
|
+
Logger.logTrace(loggerCategory, `visitElements=false, skipping exportModelContents(${modelId})`);
|
|
621
619
|
return;
|
|
622
620
|
}
|
|
623
621
|
if (undefined !== this._sourceDbChanges) {
|
|
@@ -627,12 +625,12 @@ class IModelExporter {
|
|
|
627
625
|
return; // this optimization assumes that the Model changes (LastMod) any time an Element in the Model changes
|
|
628
626
|
}
|
|
629
627
|
if (this.canUseChangedElementForest() &&
|
|
630
|
-
elementClassFullName ===
|
|
628
|
+
elementClassFullName === Element.classFullName) {
|
|
631
629
|
const forest = await this.getChangedElementForest();
|
|
632
630
|
if (forest !== undefined) {
|
|
633
|
-
|
|
631
|
+
Logger.logTrace(loggerCategory, `exportModelContents(${modelId}) via changed-element index`);
|
|
634
632
|
for (const rootId of forest.getModelRoots(modelId)) {
|
|
635
|
-
if (skipRootSubject && rootId ===
|
|
633
|
+
if (skipRootSubject && rootId === IModel.rootSubjectId)
|
|
636
634
|
continue;
|
|
637
635
|
await this.exportElement(rootId);
|
|
638
636
|
await this._yieldManager.allowYield();
|
|
@@ -641,13 +639,13 @@ class IModelExporter {
|
|
|
641
639
|
}
|
|
642
640
|
}
|
|
643
641
|
}
|
|
644
|
-
|
|
642
|
+
Logger.logTrace(loggerCategory, `exportModelContents(${modelId})`);
|
|
645
643
|
const rootFilter = skipRootSubject
|
|
646
644
|
? "e.Parent.Id IS NULL AND e.Model.Id=:modelId AND e.ECInstanceId!=:rootSubjectId"
|
|
647
645
|
: "e.Parent.Id IS NULL AND e.Model.Id=:modelId";
|
|
648
|
-
const params = new
|
|
646
|
+
const params = new QueryBinder().bindId("modelId", modelId);
|
|
649
647
|
if (skipRootSubject) {
|
|
650
|
-
params.bindId("rootSubjectId",
|
|
648
|
+
params.bindId("rootSubjectId", IModel.rootSubjectId);
|
|
651
649
|
}
|
|
652
650
|
if (this.canUseSetBasedTraversal()) {
|
|
653
651
|
return this.exportElementTreesStreamed(`SELECT e.ECInstanceId, 0 FROM ${elementClassFullName} e WHERE ${rootFilter}`, params);
|
|
@@ -687,7 +685,7 @@ class IModelExporter {
|
|
|
687
685
|
WITH RECURSIVE ElementTree (ECInstanceId, Depth) AS (
|
|
688
686
|
${anchorSelect}
|
|
689
687
|
UNION ALL
|
|
690
|
-
SELECT c.ECInstanceId, t.Depth + 1 FROM ${
|
|
688
|
+
SELECT c.ECInstanceId, t.Depth + 1 FROM ${Element.classFullName} c
|
|
691
689
|
JOIN ElementTree t ON c.Parent.Id = t.ECInstanceId
|
|
692
690
|
ORDER BY 2 DESC, 1 ASC
|
|
693
691
|
)
|
|
@@ -715,29 +713,25 @@ class IModelExporter {
|
|
|
715
713
|
return this.runScopedElementExport(async () => this.exportSubModelsImpl(parentModelId));
|
|
716
714
|
}
|
|
717
715
|
async exportSubModelsImpl(parentModelId) {
|
|
718
|
-
|
|
716
|
+
Logger.logTrace(loggerCategory, `exportSubModels(${parentModelId})`);
|
|
717
|
+
// Export DefinitionModels before other Models, each in ECInstanceId order.
|
|
718
|
+
// Classifying in ECSQL avoids loading every sub-model here and again in exportModel.
|
|
719
|
+
// Partition in JS: sorting on the classification in ECSQL raised peak native memory on many-model iModels.
|
|
720
|
+
const sql = `
|
|
721
|
+
SELECT ECInstanceId, IIF(ECClassId IS (${DefinitionModel.classFullName}), 1, 0) isDefinitionModel
|
|
722
|
+
FROM ${Model.classFullName}
|
|
723
|
+
WHERE ParentModel.Id=:parentModelId
|
|
724
|
+
ORDER BY ECInstanceId`;
|
|
725
|
+
const params = new QueryBinder().bindId("parentModelId", parentModelId);
|
|
719
726
|
const definitionModelIds = [];
|
|
720
727
|
const otherModelIds = [];
|
|
721
|
-
const sql = `SELECT ECInstanceId FROM ${core_backend_1.Model.classFullName} WHERE ParentModel.Id=:parentModelId ORDER BY ECInstanceId`;
|
|
722
|
-
const params = new core_common_1.QueryBinder().bindId("parentModelId", parentModelId);
|
|
723
728
|
for await (const row of this.sourceDb.createQueryReader(sql, params, {
|
|
724
729
|
usePrimaryConn: true,
|
|
725
730
|
})) {
|
|
726
|
-
|
|
727
|
-
const model = this.sourceDb.models.getModel(modelId);
|
|
728
|
-
if (model instanceof core_backend_1.DefinitionModel) {
|
|
729
|
-
definitionModelIds.push(modelId);
|
|
730
|
-
}
|
|
731
|
-
else {
|
|
732
|
-
otherModelIds.push(modelId);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
// export DefinitionModels before other types of Models
|
|
736
|
-
for (const definitionModelId of definitionModelIds) {
|
|
737
|
-
await this.exportModel(definitionModelId);
|
|
731
|
+
(row.isDefinitionModel ? definitionModelIds : otherModelIds).push(row.id);
|
|
738
732
|
}
|
|
739
|
-
for (const
|
|
740
|
-
await this.exportModel(
|
|
733
|
+
for (const subModelId of [...definitionModelIds, ...otherModelIds]) {
|
|
734
|
+
await this.exportModel(subModelId);
|
|
741
735
|
}
|
|
742
736
|
}
|
|
743
737
|
/** Returns true if the specified element should be exported.
|
|
@@ -746,22 +740,22 @@ class IModelExporter {
|
|
|
746
740
|
*/
|
|
747
741
|
async shouldExportElement(element) {
|
|
748
742
|
if (this._excludedElementIds.has(element.id)) {
|
|
749
|
-
|
|
743
|
+
Logger.logInfo(loggerCategory, `Excluded element ${element.id} by Id`);
|
|
750
744
|
return false;
|
|
751
745
|
}
|
|
752
|
-
if (element instanceof
|
|
746
|
+
if (element instanceof GeometricElement &&
|
|
753
747
|
this._excludedElementCategoryIds.has(element.category)) {
|
|
754
|
-
|
|
748
|
+
Logger.logInfo(loggerCategory, `Excluded element ${element.id} by Category`);
|
|
755
749
|
return false;
|
|
756
750
|
}
|
|
757
751
|
if (!this.wantTemplateModels &&
|
|
758
|
-
element instanceof
|
|
759
|
-
|
|
752
|
+
element instanceof RecipeDefinitionElement) {
|
|
753
|
+
Logger.logInfo(loggerCategory, `Excluded RecipeDefinitionElement ${element.id} because wantTemplate=false`);
|
|
760
754
|
return false;
|
|
761
755
|
}
|
|
762
756
|
for (const excludedElementClass of this._excludedElementClasses) {
|
|
763
757
|
if (element instanceof excludedElementClass) {
|
|
764
|
-
|
|
758
|
+
Logger.logInfo(loggerCategory, `Excluded element ${element.id} by class: ${excludedElementClass.classFullName}`);
|
|
765
759
|
return false;
|
|
766
760
|
}
|
|
767
761
|
}
|
|
@@ -780,7 +774,7 @@ class IModelExporter {
|
|
|
780
774
|
}
|
|
781
775
|
async exportElementImpl(elementId) {
|
|
782
776
|
if (!this.visitElements) {
|
|
783
|
-
|
|
777
|
+
Logger.logTrace(loggerCategory, `visitElements=false, skipping exportElement(${elementId})`);
|
|
784
778
|
return;
|
|
785
779
|
}
|
|
786
780
|
const childVisit = await this.exportElementShallow(elementId);
|
|
@@ -832,7 +826,7 @@ class IModelExporter {
|
|
|
832
826
|
return "skip";
|
|
833
827
|
// Return early if the elementId is already excluded so it does not need to be loaded.
|
|
834
828
|
if (this._excludedElementIds.has(elementId)) {
|
|
835
|
-
|
|
829
|
+
Logger.logInfo(loggerCategory, `Excluded element ${elementId} by Id`);
|
|
836
830
|
await this.handler.onSkipElement(elementId);
|
|
837
831
|
return "skip";
|
|
838
832
|
}
|
|
@@ -851,7 +845,7 @@ class IModelExporter {
|
|
|
851
845
|
wantGeometry: this.wantGeometry,
|
|
852
846
|
wantBRepData: this.wantGeometry,
|
|
853
847
|
});
|
|
854
|
-
|
|
848
|
+
Logger.logTrace(loggerCategory, `exportElement(${element.id}, "${element.getDisplayLabel()}")${this.getChangeOpSuffix(isUpdate)}`);
|
|
855
849
|
// the order and `await`ing of calls beyond here is depended upon by the IModelTransformer for a current bug workaround
|
|
856
850
|
if (await this.shouldExportElement(element)) {
|
|
857
851
|
await this.handler.preExportElement(element);
|
|
@@ -871,25 +865,25 @@ class IModelExporter {
|
|
|
871
865
|
}
|
|
872
866
|
async exportChildElementsImpl(elementId) {
|
|
873
867
|
if (!this.visitElements) {
|
|
874
|
-
|
|
868
|
+
Logger.logTrace(loggerCategory, `visitElements=false, skipping exportChildElements(${elementId})`);
|
|
875
869
|
return;
|
|
876
870
|
}
|
|
877
871
|
if (this.canUseSetBasedTraversal()) {
|
|
878
|
-
|
|
872
|
+
Logger.logTrace(loggerCategory, `exportChildElements(${elementId})`);
|
|
879
873
|
// Seed the stream with direct children; the helper adds their descendants.
|
|
880
|
-
return this.exportElementTreesStreamed(`SELECT e.ECInstanceId, 0 FROM ${
|
|
874
|
+
return this.exportElementTreesStreamed(`SELECT e.ECInstanceId, 0 FROM ${Element.classFullName} e WHERE e.Parent.Id=:parentId`, new QueryBinder().bindId("parentId", elementId));
|
|
881
875
|
}
|
|
882
876
|
let childElementIds;
|
|
883
877
|
if (this.canUseChangedElementForest()) {
|
|
884
878
|
const forest = await this.getChangedElementForest();
|
|
885
879
|
if (forest !== undefined) {
|
|
886
|
-
|
|
880
|
+
Logger.logTrace(loggerCategory, `exportChildElements(${elementId}) via changed-element index`);
|
|
887
881
|
childElementIds = forest.getChildren(elementId);
|
|
888
882
|
}
|
|
889
883
|
}
|
|
890
884
|
childElementIds ??= this.sourceDb.elements.queryChildren(elementId);
|
|
891
885
|
if (childElementIds.length > 0) {
|
|
892
|
-
|
|
886
|
+
Logger.logTrace(loggerCategory, `exportChildElements(${elementId})`);
|
|
893
887
|
for (const childElementId of childElementIds) {
|
|
894
888
|
await this.exportElement(childElementId);
|
|
895
889
|
}
|
|
@@ -915,10 +909,10 @@ class IModelExporter {
|
|
|
915
909
|
if (!this._changedElementTraversal?.useForest)
|
|
916
910
|
return;
|
|
917
911
|
this._changedElementTraversal.useForest = false;
|
|
918
|
-
|
|
912
|
+
Logger.logInfo(loggerCategory, `Using full element traversal for change processing because ${reason}.`);
|
|
919
913
|
}
|
|
920
914
|
async createChangedElementForest() {
|
|
921
|
-
(
|
|
915
|
+
nodeAssert(this._sourceDbChanges !== undefined, "changed-element traversal requires sourceDbChanges");
|
|
922
916
|
const excludedElementIds = this._excludedElementIds;
|
|
923
917
|
const candidateCountUpperBound = this._sourceDbChanges.element.insertIds.size +
|
|
924
918
|
this._sourceDbChanges.element.updateIds.size +
|
|
@@ -927,7 +921,7 @@ class IModelExporter {
|
|
|
927
921
|
this.disableChangedElementForest(`${candidateCountUpperBound} candidate element references exceed the ${this._changedElementForestElementLimit}-element in-memory index limit`);
|
|
928
922
|
return undefined;
|
|
929
923
|
}
|
|
930
|
-
const forest = await
|
|
924
|
+
const forest = await ChangedElementForest.create(this.sourceDb, [
|
|
931
925
|
...this._sourceDbChanges.element.insertIds,
|
|
932
926
|
...this._sourceDbChanges.element.updateIds,
|
|
933
927
|
...excludedElementIds,
|
|
@@ -939,7 +933,7 @@ class IModelExporter {
|
|
|
939
933
|
}
|
|
940
934
|
async getChangedElementForest() {
|
|
941
935
|
const traversal = this._changedElementTraversal;
|
|
942
|
-
(
|
|
936
|
+
nodeAssert(traversal !== undefined, "changed-element index requires an active traversal scope");
|
|
943
937
|
return (traversal.forest ??= this.createChangedElementForest());
|
|
944
938
|
}
|
|
945
939
|
/** Exports all aspects owned by the supplied elements. */
|
|
@@ -975,7 +969,7 @@ class IModelExporter {
|
|
|
975
969
|
const parentId = elementFact.parentId;
|
|
976
970
|
if (parentId === undefined ||
|
|
977
971
|
(this._skipPropagateChangesToRootElements &&
|
|
978
|
-
parentId ===
|
|
972
|
+
parentId === IModel.rootSubjectId)) {
|
|
979
973
|
return true;
|
|
980
974
|
}
|
|
981
975
|
elementFact = elementFacts.get(parentId);
|
|
@@ -990,8 +984,8 @@ class IModelExporter {
|
|
|
990
984
|
}
|
|
991
985
|
if (modelFact.isTemplate && !this.wantTemplateModels)
|
|
992
986
|
return false;
|
|
993
|
-
if (modelFact.id !==
|
|
994
|
-
modelFact.id !==
|
|
987
|
+
if (modelFact.id !== IModel.repositoryModelId &&
|
|
988
|
+
modelFact.id !== IModel.dictionaryId &&
|
|
995
989
|
modelFact.id !== "0xe" &&
|
|
996
990
|
!(await this.shouldExportElementForAspect(modelFact.id, elementFacts.get(modelFact.id)))) {
|
|
997
991
|
return false;
|
|
@@ -1046,27 +1040,27 @@ class IModelExporter {
|
|
|
1046
1040
|
}
|
|
1047
1041
|
shouldExportElementFact(elementFact) {
|
|
1048
1042
|
if (this._excludedElementIds.has(elementFact.id)) {
|
|
1049
|
-
|
|
1043
|
+
Logger.logInfo(loggerCategory, `Excluded element ${elementFact.id} by Id`);
|
|
1050
1044
|
return false;
|
|
1051
1045
|
}
|
|
1052
1046
|
const elementClass = this.sourceDb.getJsClass(elementFact.classFullName);
|
|
1053
|
-
if ((elementFact.classFullName ===
|
|
1054
|
-
elementClass.prototype instanceof
|
|
1047
|
+
if ((elementFact.classFullName === GeometricElement.classFullName ||
|
|
1048
|
+
elementClass.prototype instanceof GeometricElement) &&
|
|
1055
1049
|
elementFact.categoryId !== undefined &&
|
|
1056
1050
|
this._excludedElementCategoryIds.has(elementFact.categoryId)) {
|
|
1057
|
-
|
|
1051
|
+
Logger.logInfo(loggerCategory, `Excluded element ${elementFact.id} by Category`);
|
|
1058
1052
|
return false;
|
|
1059
1053
|
}
|
|
1060
1054
|
if (!this.wantTemplateModels &&
|
|
1061
|
-
(elementFact.classFullName ===
|
|
1062
|
-
elementClass.prototype instanceof
|
|
1063
|
-
|
|
1055
|
+
(elementFact.classFullName === RecipeDefinitionElement.classFullName ||
|
|
1056
|
+
elementClass.prototype instanceof RecipeDefinitionElement)) {
|
|
1057
|
+
Logger.logInfo(loggerCategory, `Excluded RecipeDefinitionElement ${elementFact.id} because wantTemplate=false`);
|
|
1064
1058
|
return false;
|
|
1065
1059
|
}
|
|
1066
1060
|
for (const excludedElementClass of this._excludedElementClasses) {
|
|
1067
1061
|
if (elementFact.classFullName === excludedElementClass.classFullName ||
|
|
1068
1062
|
elementClass.prototype instanceof excludedElementClass) {
|
|
1069
|
-
|
|
1063
|
+
Logger.logInfo(loggerCategory, `Excluded element ${elementFact.id} by class: ${excludedElementClass.classFullName}`);
|
|
1070
1064
|
return false;
|
|
1071
1065
|
}
|
|
1072
1066
|
}
|
|
@@ -1098,7 +1092,7 @@ class IModelExporter {
|
|
|
1098
1092
|
if (unqueriedElementIds.size === 0)
|
|
1099
1093
|
return;
|
|
1100
1094
|
for (const elementIdBatch of this.getAspectOwnerIdBatches(unqueriedElementIds)) {
|
|
1101
|
-
const queryParams = new
|
|
1095
|
+
const queryParams = new QueryBinder().bindIdSet("elementIds", elementIdBatch);
|
|
1102
1096
|
for await (const row of this.sourceDb.createQueryReader(`SELECT e.ECInstanceId id, e.Parent.Id parentId, e.Model.Id modelId,
|
|
1103
1097
|
ec_className(e.ECClassId, 's') schemaName,
|
|
1104
1098
|
ec_className(e.ECClassId, 'c') className
|
|
@@ -1112,7 +1106,7 @@ class IModelExporter {
|
|
|
1112
1106
|
});
|
|
1113
1107
|
}
|
|
1114
1108
|
if (this._excludedElementCategoryIds.size > 0) {
|
|
1115
|
-
const categoryQueryParams = new
|
|
1109
|
+
const categoryQueryParams = new QueryBinder().bindIdSet("elementIds", elementIdBatch);
|
|
1116
1110
|
for await (const row of this.sourceDb.createQueryReader(`SELECT g.ECInstanceId id, g.Category.Id categoryId
|
|
1117
1111
|
FROM bis.GeometricElement g
|
|
1118
1112
|
INNER JOIN IdSet(:elementIds) ids ON ids.id = g.ECInstanceId`, categoryQueryParams, { usePrimaryConn: true })) {
|
|
@@ -1132,7 +1126,7 @@ class IModelExporter {
|
|
|
1132
1126
|
const currentModelIds = pendingModelIds;
|
|
1133
1127
|
pendingModelIds = new Set();
|
|
1134
1128
|
for (const modelIdBatch of this.getAspectOwnerIdBatches(currentModelIds)) {
|
|
1135
|
-
const queryParams = new
|
|
1129
|
+
const queryParams = new QueryBinder().bindIdSet("modelIds", modelIdBatch);
|
|
1136
1130
|
for await (const row of this.sourceDb.createQueryReader(`SELECT model.ECInstanceId id, model.ParentModel.Id parentModelId, model.IsTemplate isTemplate
|
|
1137
1131
|
FROM bis.Model model
|
|
1138
1132
|
INNER JOIN IdSet(:modelIds) ids ON ids.id = model.ECInstanceId`, queryParams, { usePrimaryConn: true })) {
|
|
@@ -1174,10 +1168,10 @@ class IModelExporter {
|
|
|
1174
1168
|
*/
|
|
1175
1169
|
async exportRelationships(baseRelClassFullName) {
|
|
1176
1170
|
if (!this.visitRelationships) {
|
|
1177
|
-
|
|
1171
|
+
Logger.logTrace(loggerCategory, "visitRelationships=false, skipping exportRelationships()");
|
|
1178
1172
|
return;
|
|
1179
1173
|
}
|
|
1180
|
-
|
|
1174
|
+
Logger.logTrace(loggerCategory, `exportRelationships(${baseRelClassFullName})`);
|
|
1181
1175
|
const changedRelationshipIds = this._sourceDbChanges === undefined
|
|
1182
1176
|
? undefined
|
|
1183
1177
|
: new Set([
|
|
@@ -1187,7 +1181,7 @@ class IModelExporter {
|
|
|
1187
1181
|
if (changedRelationshipIds?.size === 0) {
|
|
1188
1182
|
// Deleted relationships are handled by exportChanges after this traversal; they are no
|
|
1189
1183
|
// longer present in the source iModel and must not cause a full relationship scan here.
|
|
1190
|
-
|
|
1184
|
+
Logger.logTrace(loggerCategory, "No inserted or updated relationships, skipping exportRelationships()");
|
|
1191
1185
|
return;
|
|
1192
1186
|
}
|
|
1193
1187
|
const changedRelationshipJoin = changedRelationshipIds === undefined
|
|
@@ -1207,7 +1201,7 @@ class IModelExporter {
|
|
|
1207
1201
|
// keyset page so the changing boundary can be bound without redefining a property.
|
|
1208
1202
|
const queryParams = changedRelationshipIds === undefined && lastRelationshipId === undefined
|
|
1209
1203
|
? undefined
|
|
1210
|
-
: new
|
|
1204
|
+
: new QueryBinder();
|
|
1211
1205
|
if (queryParams !== undefined) {
|
|
1212
1206
|
if (changedRelationshipIds !== undefined) {
|
|
1213
1207
|
queryParams.bindIdSet("changedRelationshipIds", changedRelationshipIds);
|
|
@@ -1261,27 +1255,27 @@ class IModelExporter {
|
|
|
1261
1255
|
/** Converts a raw `$` instance-access row into [RelationshipProps]($common). */
|
|
1262
1256
|
getRelationshipProps(rawInstance) {
|
|
1263
1257
|
const parsedRow = typeof rawInstance === "string"
|
|
1264
|
-
? JSON.parse(rawInstance,
|
|
1258
|
+
? JSON.parse(rawInstance, Base64EncodedString.reviver)
|
|
1265
1259
|
: rawInstance;
|
|
1266
|
-
if (!
|
|
1267
|
-
|
|
1260
|
+
if (!JsonUtils.isObject(parsedRow))
|
|
1261
|
+
ITwinError.throwError({
|
|
1268
1262
|
iTwinErrorId: {
|
|
1269
|
-
scope:
|
|
1270
|
-
key:
|
|
1263
|
+
scope: IModelTransformerErrorScope,
|
|
1264
|
+
key: IModelTransformerError.InvalidRelationshipData,
|
|
1271
1265
|
},
|
|
1272
1266
|
message: "Expected a Relationship instance query to return an object",
|
|
1273
1267
|
});
|
|
1274
1268
|
const row = {};
|
|
1275
1269
|
for (const [key, value] of Object.entries(parsedRow)) {
|
|
1276
1270
|
const ecPropertyName = key.length === 0 ? key : key[0].toUpperCase() + key.substring(1);
|
|
1277
|
-
row[
|
|
1271
|
+
row[ECJsNames.toJsName(ecPropertyName)] = value;
|
|
1278
1272
|
}
|
|
1279
1273
|
const className = row.className;
|
|
1280
1274
|
if (typeof className !== "string")
|
|
1281
|
-
|
|
1275
|
+
ITwinError.throwError({
|
|
1282
1276
|
iTwinErrorId: {
|
|
1283
|
-
scope:
|
|
1284
|
-
key:
|
|
1277
|
+
scope: IModelTransformerErrorScope,
|
|
1278
|
+
key: IModelTransformerError.InvalidRelationshipData,
|
|
1285
1279
|
},
|
|
1286
1280
|
message: "Expected a Relationship instance query to return a className",
|
|
1287
1281
|
});
|
|
@@ -1296,13 +1290,13 @@ class IModelExporter {
|
|
|
1296
1290
|
*/
|
|
1297
1291
|
async exportRelationship(relClassFullName, relInstanceId) {
|
|
1298
1292
|
if (!this.visitRelationships) {
|
|
1299
|
-
|
|
1293
|
+
Logger.logTrace(loggerCategory, `visitRelationships=false, skipping exportRelationship(${relClassFullName}, ${relInstanceId})`);
|
|
1300
1294
|
return;
|
|
1301
1295
|
}
|
|
1302
1296
|
const changesetFilter = this.checkRelationshipChangesetFilter(relInstanceId);
|
|
1303
1297
|
if (changesetFilter.skip)
|
|
1304
1298
|
return;
|
|
1305
|
-
const queryParams = new
|
|
1299
|
+
const queryParams = new QueryBinder().bindId("relInstanceId", relInstanceId);
|
|
1306
1300
|
const reader = this.sourceDb.createQueryReader(this.getRelationshipQuery(relClassFullName, "LEFT JOIN", "r.ECInstanceId = :relInstanceId"), queryParams, { usePrimaryConn: true });
|
|
1307
1301
|
if (await reader.step()) {
|
|
1308
1302
|
const row = reader.current;
|
|
@@ -1326,10 +1320,10 @@ class IModelExporter {
|
|
|
1326
1320
|
*/
|
|
1327
1321
|
async exportRelationshipInstance(relationship, isUpdate, endpointFedGuids) {
|
|
1328
1322
|
// passed changeset test, now apply standard exclusion rules
|
|
1329
|
-
|
|
1323
|
+
Logger.logTrace(loggerCategory, `exportRelationship(${relationship.classFullName}, ${relationship.id})`);
|
|
1330
1324
|
for (const excludedRelationshipClass of this._excludedRelationshipClasses) {
|
|
1331
1325
|
if (relationship instanceof excludedRelationshipClass) {
|
|
1332
|
-
|
|
1326
|
+
Logger.logInfo(loggerCategory, `Excluded relationship by class: ${excludedRelationshipClass.classFullName}`);
|
|
1333
1327
|
return;
|
|
1334
1328
|
}
|
|
1335
1329
|
}
|
|
@@ -1347,11 +1341,10 @@ class IModelExporter {
|
|
|
1347
1341
|
}
|
|
1348
1342
|
}
|
|
1349
1343
|
}
|
|
1350
|
-
exports.IModelExporter = IModelExporter;
|
|
1351
1344
|
/** Class for holding change information.
|
|
1352
1345
|
* @public
|
|
1353
1346
|
*/
|
|
1354
|
-
class ChangedInstanceOps {
|
|
1347
|
+
export class ChangedInstanceOps {
|
|
1355
1348
|
insertIds = new Set();
|
|
1356
1349
|
updateIds = new Set();
|
|
1357
1350
|
deleteIds = new Set();
|
|
@@ -1376,12 +1369,11 @@ class ChangedInstanceOps {
|
|
|
1376
1369
|
0 === this.deleteIds.size);
|
|
1377
1370
|
}
|
|
1378
1371
|
}
|
|
1379
|
-
exports.ChangedInstanceOps = ChangedInstanceOps;
|
|
1380
1372
|
/**
|
|
1381
1373
|
* Class for discovering modified elements between 2 versions of an iModel.
|
|
1382
1374
|
* @public
|
|
1383
1375
|
*/
|
|
1384
|
-
class ChangedInstanceIds {
|
|
1376
|
+
export class ChangedInstanceIds {
|
|
1385
1377
|
codeSpec = new ChangedInstanceOps();
|
|
1386
1378
|
model = new ChangedInstanceOps();
|
|
1387
1379
|
element = new ChangedInstanceOps();
|
|
@@ -1429,14 +1421,14 @@ class ChangedInstanceIds {
|
|
|
1429
1421
|
*/
|
|
1430
1422
|
async addChangeRecord(change) {
|
|
1431
1423
|
if (change.op === "Deleted" && change.aspectOwnerElementId === undefined) {
|
|
1432
|
-
this._classKinds ??= await
|
|
1424
|
+
this._classKinds ??= await SourceClassKinds.query(this._db);
|
|
1433
1425
|
const kind = this._classKinds.kindOf(change.ecClassId);
|
|
1434
1426
|
// The source no longer has the aspect, so without its owner the target aspect would silently stay.
|
|
1435
1427
|
if (kind === "aspect" || kind === "externalSourceAspect")
|
|
1436
|
-
|
|
1428
|
+
ITwinError.throwError({
|
|
1437
1429
|
iTwinErrorId: {
|
|
1438
|
-
scope:
|
|
1439
|
-
key:
|
|
1430
|
+
scope: IModelTransformerErrorScope,
|
|
1431
|
+
key: IModelTransformerError.AspectOwnerRequired,
|
|
1440
1432
|
},
|
|
1441
1433
|
message: `Deleted ElementAspect change ${change.id} requires the owning element ID.`,
|
|
1442
1434
|
});
|
|
@@ -1446,19 +1438,19 @@ class ChangedInstanceIds {
|
|
|
1446
1438
|
async recordChange(change, unresolvedAspectIds) {
|
|
1447
1439
|
const ecClassId = change.ECClassId;
|
|
1448
1440
|
if (ecClassId === undefined)
|
|
1449
|
-
|
|
1441
|
+
ITwinError.throwError({
|
|
1450
1442
|
iTwinErrorId: {
|
|
1451
|
-
scope:
|
|
1452
|
-
key:
|
|
1443
|
+
scope: IModelTransformerErrorScope,
|
|
1444
|
+
key: IModelTransformerError.ChangedInstanceMetadataMissing,
|
|
1453
1445
|
},
|
|
1454
1446
|
message: `ECClassId was not found for id: ${change.ECInstanceId}! Table is : ${change.$meta.tables}`,
|
|
1455
1447
|
});
|
|
1456
1448
|
const changeType = change.$meta.op;
|
|
1457
1449
|
if (changeType === undefined)
|
|
1458
|
-
|
|
1450
|
+
ITwinError.throwError({
|
|
1459
1451
|
iTwinErrorId: {
|
|
1460
|
-
scope:
|
|
1461
|
-
key:
|
|
1452
|
+
scope: IModelTransformerErrorScope,
|
|
1453
|
+
key: IModelTransformerError.ChangedInstanceMetadataMissing,
|
|
1462
1454
|
},
|
|
1463
1455
|
message: `ChangeType was undefined for id: ${change.ECInstanceId}.`,
|
|
1464
1456
|
});
|
|
@@ -1471,7 +1463,7 @@ class ChangedInstanceIds {
|
|
|
1471
1463
|
}
|
|
1472
1464
|
async applyChangeRecord(change, unresolvedAspectIds) {
|
|
1473
1465
|
// Await only the first time, so later changes are classified without yielding.
|
|
1474
|
-
this._classKinds ??= await
|
|
1466
|
+
this._classKinds ??= await SourceClassKinds.query(this._db);
|
|
1475
1467
|
const { id, ecClassId, op } = change;
|
|
1476
1468
|
switch (this._classKinds.kindOf(ecClassId)) {
|
|
1477
1469
|
case "relationship":
|
|
@@ -1505,8 +1497,8 @@ class ChangedInstanceIds {
|
|
|
1505
1497
|
return this._db.elements.getAspect(aspectId).element.id;
|
|
1506
1498
|
}
|
|
1507
1499
|
catch (error) {
|
|
1508
|
-
if (error instanceof
|
|
1509
|
-
error.errorNumber ===
|
|
1500
|
+
if (error instanceof IModelError &&
|
|
1501
|
+
error.errorNumber === IModelStatus.NotFound) {
|
|
1510
1502
|
return undefined;
|
|
1511
1503
|
}
|
|
1512
1504
|
throw error;
|
|
@@ -1525,16 +1517,16 @@ class ChangedInstanceIds {
|
|
|
1525
1517
|
* @beta
|
|
1526
1518
|
*/
|
|
1527
1519
|
async addCustomElementChange(changeType, ids) {
|
|
1528
|
-
if (
|
|
1520
|
+
if (Id64.sizeOf(ids) === 0) {
|
|
1529
1521
|
return;
|
|
1530
1522
|
}
|
|
1531
|
-
for (const id of
|
|
1523
|
+
for (const id of Id64.iterable(ids)) {
|
|
1532
1524
|
this.handleChange(this.element, changeType, id);
|
|
1533
1525
|
}
|
|
1534
1526
|
if (changeType === "Deleted") {
|
|
1535
1527
|
return;
|
|
1536
1528
|
}
|
|
1537
|
-
const idsSet =
|
|
1529
|
+
const idsSet = Id64.toIdSet(ids, true);
|
|
1538
1530
|
// Parent models have to be marked as 'Updated' to make sure that added change is not skipped by transformer. Transformer starts processing elements from RepositoryModel and then visits all child models.
|
|
1539
1531
|
// Transformer handles update as insert if element is not found in target, for this reason modeled elements will be also marked as updated to trigger their inserts in case a new model (or its parent) needs to be inserted. Otherwise error would be thrown about missing modeled element while inserting new model.
|
|
1540
1532
|
const parentModelIds = await this.markParentModelsAsUpdated(idsSet);
|
|
@@ -1546,7 +1538,7 @@ class ChangedInstanceIds {
|
|
|
1546
1538
|
});
|
|
1547
1539
|
await this.markElementAspectsAsInserted(idsSet);
|
|
1548
1540
|
// Marking only ElementRefersToElements.classFullName as only those are exported in exportRelationships()
|
|
1549
|
-
await this.markElementRelationshipsAsInserted(
|
|
1541
|
+
await this.markElementRelationshipsAsInserted(ElementRefersToElements.classFullName, idsSet);
|
|
1550
1542
|
}
|
|
1551
1543
|
}
|
|
1552
1544
|
/**
|
|
@@ -1563,7 +1555,7 @@ class ChangedInstanceIds {
|
|
|
1563
1555
|
async addCustomModelChange(changeType, ids) {
|
|
1564
1556
|
// Also add the model's modeledElement to the element changes. The modeledElement and model go hand in hand and have the same id.
|
|
1565
1557
|
await this.addCustomElementChange(changeType, ids);
|
|
1566
|
-
for (const id of
|
|
1558
|
+
for (const id of Id64.iterable(ids)) {
|
|
1567
1559
|
this.handleChange(this.model, changeType, id);
|
|
1568
1560
|
}
|
|
1569
1561
|
}
|
|
@@ -1580,16 +1572,16 @@ class ChangedInstanceIds {
|
|
|
1580
1572
|
*/
|
|
1581
1573
|
addCustomAspectChange(changeType, ids, elementIds) {
|
|
1582
1574
|
if (elementIds !== undefined) {
|
|
1583
|
-
for (const elementId of
|
|
1575
|
+
for (const elementId of Id64.iterable(elementIds)) {
|
|
1584
1576
|
this._aspectOwnerElementIds.add(elementId);
|
|
1585
1577
|
}
|
|
1586
1578
|
}
|
|
1587
|
-
for (const id of
|
|
1579
|
+
for (const id of Id64.iterable(ids)) {
|
|
1588
1580
|
if (elementIds === undefined && changeType === "Deleted") {
|
|
1589
|
-
|
|
1581
|
+
ITwinError.throwError({
|
|
1590
1582
|
iTwinErrorId: {
|
|
1591
|
-
scope:
|
|
1592
|
-
key:
|
|
1583
|
+
scope: IModelTransformerErrorScope,
|
|
1584
|
+
key: IModelTransformerError.AspectOwnerRequired,
|
|
1593
1585
|
},
|
|
1594
1586
|
message: "Custom deleted ElementAspect changes require the owning element ID.",
|
|
1595
1587
|
});
|
|
@@ -1597,10 +1589,10 @@ class ChangedInstanceIds {
|
|
|
1597
1589
|
if (elementIds === undefined && changeType !== "Deleted") {
|
|
1598
1590
|
const ownerElementId = this.tryGetAspectOwnerElementId(id);
|
|
1599
1591
|
if (ownerElementId === undefined) {
|
|
1600
|
-
|
|
1592
|
+
ITwinError.throwError({
|
|
1601
1593
|
iTwinErrorId: {
|
|
1602
|
-
scope:
|
|
1603
|
-
key:
|
|
1594
|
+
scope: IModelTransformerErrorScope,
|
|
1595
|
+
key: IModelTransformerError.AspectOwnerRequired,
|
|
1604
1596
|
},
|
|
1605
1597
|
message: "Custom ElementAspect changes require the owning element ID when the source aspect is unavailable.",
|
|
1606
1598
|
});
|
|
@@ -1619,7 +1611,7 @@ class ChangedInstanceIds {
|
|
|
1619
1611
|
* Transformer will insert 'Updated' model to target if it does not exist there already. To handle such case, modeled elements of parent models are also marked as updated. This is done, because model can not be inserted without it's modeled element.
|
|
1620
1612
|
*/
|
|
1621
1613
|
async markParentModelsAsUpdated(elementIds) {
|
|
1622
|
-
const params = new
|
|
1614
|
+
const params = new QueryBinder().bindIdSet("elementIds", elementIds);
|
|
1623
1615
|
const ecQuery = `
|
|
1624
1616
|
WITH RECURSIVE hierarchy (parentId) AS (
|
|
1625
1617
|
SELECT element.Model.Id
|
|
@@ -1658,7 +1650,7 @@ class ChangedInstanceIds {
|
|
|
1658
1650
|
FROM ${relationshipClassName} relationship
|
|
1659
1651
|
INNER JOIN IdSet(:elementIds) ids
|
|
1660
1652
|
ON ids.id = relationship.SourceECInstanceId`;
|
|
1661
|
-
const queryBinder = new
|
|
1653
|
+
const queryBinder = new QueryBinder().bindIdSet("elementIds", elementIds);
|
|
1662
1654
|
const queryReader = this._db.createQueryReader(ecQuery, queryBinder, {
|
|
1663
1655
|
usePrimaryConn: true,
|
|
1664
1656
|
});
|
|
@@ -1668,13 +1660,13 @@ class ChangedInstanceIds {
|
|
|
1668
1660
|
}
|
|
1669
1661
|
async markElementAspectsAsInserted(elementIds) {
|
|
1670
1662
|
for (const aspectClassName of [
|
|
1671
|
-
|
|
1672
|
-
|
|
1663
|
+
ElementUniqueAspect.classFullName,
|
|
1664
|
+
ElementMultiAspect.classFullName,
|
|
1673
1665
|
]) {
|
|
1674
1666
|
const ecQuery = `SELECT aspect.ECInstanceId, aspect.Element.Id
|
|
1675
1667
|
FROM ${aspectClassName} aspect
|
|
1676
1668
|
INNER JOIN IdSet(:elementIds) ids ON ids.id = aspect.Element.Id`;
|
|
1677
|
-
const queryBinder = new
|
|
1669
|
+
const queryBinder = new QueryBinder().bindIdSet("elementIds", elementIds);
|
|
1678
1670
|
const queryReader = this._db.createQueryReader(ecQuery, queryBinder, {
|
|
1679
1671
|
usePrimaryConn: true,
|
|
1680
1672
|
});
|
|
@@ -1719,14 +1711,14 @@ class ChangedInstanceIds {
|
|
|
1719
1711
|
? [
|
|
1720
1712
|
[
|
|
1721
1713
|
startChangeset.index ??
|
|
1722
|
-
(await
|
|
1714
|
+
(await BriefcaseManager.queryChangeset({
|
|
1723
1715
|
iModelId,
|
|
1724
1716
|
changeset: {
|
|
1725
1717
|
id: startChangeset.id ?? opts.iModel.changeset.id,
|
|
1726
1718
|
},
|
|
1727
1719
|
})).index,
|
|
1728
1720
|
opts.iModel.changeset.index ??
|
|
1729
|
-
(await
|
|
1721
|
+
(await BriefcaseManager.queryChangeset({
|
|
1730
1722
|
iModelId,
|
|
1731
1723
|
changeset: { id: opts.iModel.changeset.id },
|
|
1732
1724
|
})).index,
|
|
@@ -1736,14 +1728,14 @@ class ChangedInstanceIds {
|
|
|
1736
1728
|
? opts.changesetRanges
|
|
1737
1729
|
: undefined;
|
|
1738
1730
|
const csFileProps = changesetRanges !== undefined
|
|
1739
|
-
? (await
|
|
1731
|
+
? (await ChangesetScanner.download(opts.iModel, changesetRanges)).flat()
|
|
1740
1732
|
: "csFileProps" in opts
|
|
1741
1733
|
? opts.csFileProps
|
|
1742
1734
|
: undefined;
|
|
1743
1735
|
if (csFileProps === undefined)
|
|
1744
1736
|
return undefined;
|
|
1745
1737
|
const changedInstanceIds = new ChangedInstanceIds(opts.iModel);
|
|
1746
|
-
await
|
|
1738
|
+
await ChangesetScanner.scan(opts.iModel, [csFileProps], {
|
|
1747
1739
|
changedInstanceIds,
|
|
1748
1740
|
collectDeletionRecords: false,
|
|
1749
1741
|
});
|
|
@@ -1767,9 +1759,8 @@ class ChangedInstanceIds {
|
|
|
1767
1759
|
WHERE ECInstanceId IN (SELECT id FROM AspectIds)`, (reader) => {
|
|
1768
1760
|
while (reader.step())
|
|
1769
1761
|
this._aspectOwnerElementIds.add(reader.current[0]);
|
|
1770
|
-
}, new
|
|
1762
|
+
}, new QueryBinder().bindIdSet("aspectIds", unresolvedAspectIds));
|
|
1771
1763
|
}
|
|
1772
1764
|
}
|
|
1773
1765
|
}
|
|
1774
|
-
exports.ChangedInstanceIds = ChangedInstanceIds;
|
|
1775
1766
|
//# sourceMappingURL=IModelExporter.js.map
|