@itwin/imodel-transformer 2.0.0-dev.50 → 2.0.0-dev.52
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/ChangedElementForest.d.ts +14 -0
- package/lib/cjs/ChangedElementForest.d.ts.map +1 -0
- package/lib/cjs/ChangedElementForest.js +86 -0
- package/lib/cjs/ChangedElementForest.js.map +1 -0
- package/lib/cjs/ElementAspectCleanup.d.ts.map +1 -1
- package/lib/cjs/ElementAspectCleanup.js +1 -2
- package/lib/cjs/ElementAspectCleanup.js.map +1 -1
- package/lib/cjs/ElementBulkDelete.d.ts +11 -0
- package/lib/cjs/ElementBulkDelete.d.ts.map +1 -0
- package/lib/cjs/ElementBulkDelete.js +55 -0
- package/lib/cjs/ElementBulkDelete.js.map +1 -0
- package/lib/cjs/IModelExporter.d.ts +19 -3
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js +138 -56
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelImporter.d.ts +26 -10
- package/lib/cjs/IModelImporter.d.ts.map +1 -1
- package/lib/cjs/IModelImporter.js +52 -19
- package/lib/cjs/IModelImporter.js.map +1 -1
- package/lib/cjs/IModelTransformer.d.ts +2 -4
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +11 -13
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/lib/cjs/IModelTransformerError.d.ts +2 -0
- package/lib/cjs/IModelTransformerError.d.ts.map +1 -1
- package/lib/cjs/IModelTransformerError.js +2 -0
- package/lib/cjs/IModelTransformerError.js.map +1 -1
- package/package.json +1 -1
- package/lib/cjs/ElementCascadingDeleter.d.ts +0 -22
- package/lib/cjs/ElementCascadingDeleter.d.ts.map +0 -1
- package/lib/cjs/ElementCascadingDeleter.js +0 -57
- package/lib/cjs/ElementCascadingDeleter.js.map +0 -1
|
@@ -18,6 +18,7 @@ const ElementAspectExportProcessor_1 = require("./ElementAspectExportProcessor")
|
|
|
18
18
|
const ElementAspectExportCoordinator_1 = require("./ElementAspectExportCoordinator");
|
|
19
19
|
const IModelTransformerError_1 = require("./IModelTransformerError");
|
|
20
20
|
const ChangesetScanner_1 = require("./ChangesetScanner");
|
|
21
|
+
const ChangedElementForest_1 = require("./ChangedElementForest");
|
|
21
22
|
const loggerCategory = TransformerLoggerCategory_1.TransformerLoggerCategory.IModelExporter;
|
|
22
23
|
/** Handles the events generated by IModelExporter.
|
|
23
24
|
* @note Change information is available when `IModelExportHandler` methods are invoked via [IModelExporter.exportChanges]($transformer), but not available when invoked via [IModelExporter.exportAll]($transformer).
|
|
@@ -75,8 +76,8 @@ class IModelExportHandler {
|
|
|
75
76
|
* @internal
|
|
76
77
|
*/
|
|
77
78
|
async preExportElement(_element) { }
|
|
78
|
-
/** Called
|
|
79
|
-
async
|
|
79
|
+
/** Called once with the source IDs of all elements deleted by the exported changes. */
|
|
80
|
+
async onDeleteElements(_elementIds) { }
|
|
80
81
|
/** If `true` is returned, then the ElementAspect will be exported.
|
|
81
82
|
* @note This method can optionally be overridden to exclude an individual ElementAspect from the export. The base implementation always returns `true`.
|
|
82
83
|
*/
|
|
@@ -172,6 +173,10 @@ class IModelExporter {
|
|
|
172
173
|
_progressCounter = 0;
|
|
173
174
|
/** Optionally cached entity change information */
|
|
174
175
|
_sourceDbChanges;
|
|
176
|
+
/** State shared by nested calls in one change-processing element traversal. */
|
|
177
|
+
_changedElementTraversal;
|
|
178
|
+
/** Bounds the additional hierarchy retained by the sparse changed-element path. */
|
|
179
|
+
_changedElementForestElementLimit = 100_000;
|
|
175
180
|
/**
|
|
176
181
|
* Retrieve the cached entity change information.
|
|
177
182
|
* @note This will only be initialized after [IModelExporter.exportChanges] is invoked or [IModelExporter.initialize] is called.
|
|
@@ -262,7 +267,9 @@ class IModelExporter {
|
|
|
262
267
|
excludeCodeSpec(codeSpecName) {
|
|
263
268
|
this._excludedCodeSpecNames.add(codeSpecName);
|
|
264
269
|
}
|
|
265
|
-
/** Add a rule to exclude a specific Element.
|
|
270
|
+
/** Add a rule to exclude a specific Element.
|
|
271
|
+
* @note Configure exclusions before starting an export operation. Changing exclusions while an export is in progress is unsupported.
|
|
272
|
+
*/
|
|
266
273
|
excludeElement(elementId) {
|
|
267
274
|
this._excludedElementIds.add(elementId);
|
|
268
275
|
}
|
|
@@ -337,27 +344,33 @@ class IModelExporter {
|
|
|
337
344
|
(0, node_assert_1.strict)(this._sourceDbChanges !== undefined, "sourceDbChanges must be initialized.");
|
|
338
345
|
await this.exportCodeSpecs();
|
|
339
346
|
await this.exportFonts();
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
347
|
+
(0, node_assert_1.strict)(this.beginChangedElementTraversalScope(), "exportChanges must own its changed-element traversal scope");
|
|
348
|
+
try {
|
|
349
|
+
await this._elementAspectExportCoordinator.run(async () => {
|
|
350
|
+
if (initOpts.skipPropagateChangesToRootElements) {
|
|
351
|
+
// The root Subject is in the RepositoryModel. Traverse its children
|
|
352
|
+
// separately, then export other top-level repository elements while
|
|
353
|
+
// excluding the root so no element is visited twice.
|
|
354
|
+
await this.exportChildElements(core_common_1.IModel.rootSubjectId);
|
|
355
|
+
await this.exportModelContents(core_common_1.IModel.repositoryModelId, core_backend_1.Element.classFullName, true);
|
|
356
|
+
await this.exportSubModels(core_common_1.IModel.repositoryModelId);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
await this.exportModel(core_common_1.IModel.repositoryModelId);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
const aspectOnlyOwnerElementIds = new Set(this._sourceDbChanges.aspectOwnerElementIds);
|
|
363
|
+
for (const elementId of this._sourceDbChanges.element.insertIds) {
|
|
364
|
+
aspectOnlyOwnerElementIds.delete(elementId);
|
|
348
365
|
}
|
|
349
|
-
|
|
350
|
-
|
|
366
|
+
for (const elementId of this._sourceDbChanges.element.updateIds) {
|
|
367
|
+
aspectOnlyOwnerElementIds.delete(elementId);
|
|
351
368
|
}
|
|
352
|
-
|
|
353
|
-
const aspectOnlyOwnerElementIds = new Set(this._sourceDbChanges.aspectOwnerElementIds);
|
|
354
|
-
for (const elementId of this._sourceDbChanges.element.insertIds) {
|
|
355
|
-
aspectOnlyOwnerElementIds.delete(elementId);
|
|
369
|
+
await this.exportAspectsForOwners(await this.filterOwnerElementIdsForAspectExport(aspectOnlyOwnerElementIds));
|
|
356
370
|
}
|
|
357
|
-
|
|
358
|
-
|
|
371
|
+
finally {
|
|
372
|
+
this.endChangedElementTraversalScope();
|
|
359
373
|
}
|
|
360
|
-
await this.exportAspectsForOwners(await this.filterOwnerElementIdsForAspectExport(aspectOnlyOwnerElementIds));
|
|
361
374
|
await this.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
|
|
362
375
|
// handle deletes
|
|
363
376
|
if (this.visitElements) {
|
|
@@ -365,22 +378,8 @@ class IModelExporter {
|
|
|
365
378
|
for (const modelId of this._sourceDbChanges.model.deleteIds) {
|
|
366
379
|
await this.handler.onDeleteModel(modelId);
|
|
367
380
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// to know if deleted entities were related, so when processing changes, ignore errors from deletion.
|
|
371
|
-
// Technically, to keep the ignored error scope small, we ignore only the error of looking up a missing element,
|
|
372
|
-
// that approach works at least for the IModelTransformer.
|
|
373
|
-
// In the future, the handler may be responsible for doing the work of finding out which elements were cascade deleted,
|
|
374
|
-
// and returning them for the exporter to use to avoid double-deleting with error ignoring
|
|
375
|
-
try {
|
|
376
|
-
await this.handler.onDeleteElement(elementId);
|
|
377
|
-
}
|
|
378
|
-
catch (err) {
|
|
379
|
-
const isMissingErr = err instanceof core_common_1.IModelError &&
|
|
380
|
-
err.errorNumber === core_bentley_1.IModelStatus.NotFound;
|
|
381
|
-
if (!isMissingErr)
|
|
382
|
-
throw err;
|
|
383
|
-
}
|
|
381
|
+
if (this._sourceDbChanges.element.deleteIds.size > 0) {
|
|
382
|
+
await this.handler.onDeleteElements(new Set(this._sourceDbChanges.element.deleteIds));
|
|
384
383
|
}
|
|
385
384
|
}
|
|
386
385
|
if (this.visitRelationships) {
|
|
@@ -623,6 +622,20 @@ class IModelExporter {
|
|
|
623
622
|
!this._sourceDbChanges.model.updateIds.has(modelId)) {
|
|
624
623
|
return; // this optimization assumes that the Model changes (LastMod) any time an Element in the Model changes
|
|
625
624
|
}
|
|
625
|
+
if (this.canUseChangedElementForest() &&
|
|
626
|
+
elementClassFullName === core_backend_1.Element.classFullName) {
|
|
627
|
+
const forest = await this.getChangedElementForest();
|
|
628
|
+
if (forest !== undefined) {
|
|
629
|
+
core_bentley_1.Logger.logTrace(loggerCategory, `exportModelContents(${modelId}) via changed-element index`);
|
|
630
|
+
for (const rootId of forest.getModelRoots(modelId)) {
|
|
631
|
+
if (skipRootSubject && rootId === core_common_1.IModel.rootSubjectId)
|
|
632
|
+
continue;
|
|
633
|
+
await this.exportElement(rootId);
|
|
634
|
+
await this._yieldManager.allowYield();
|
|
635
|
+
}
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
626
639
|
}
|
|
627
640
|
core_bentley_1.Logger.logTrace(loggerCategory, `exportModelContents(${modelId})`);
|
|
628
641
|
let sql;
|
|
@@ -718,20 +731,19 @@ class IModelExporter {
|
|
|
718
731
|
core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportElement(${elementId})`);
|
|
719
732
|
return;
|
|
720
733
|
}
|
|
721
|
-
// Return early if the elementId is already
|
|
734
|
+
// Return early if the elementId is already excluded so it does not need to be loaded.
|
|
722
735
|
if (this._excludedElementIds.has(elementId)) {
|
|
723
736
|
core_bentley_1.Logger.logInfo(loggerCategory, `Excluded element ${elementId} by Id`);
|
|
724
737
|
await this.handler.onSkipElement(elementId);
|
|
725
738
|
return;
|
|
726
739
|
}
|
|
727
|
-
// are we processing changes?
|
|
728
740
|
const isUpdate = this._sourceDbChanges?.element.insertIds.has(elementId)
|
|
729
741
|
? false
|
|
730
742
|
: this._sourceDbChanges?.element.updateIds.has(elementId)
|
|
731
743
|
? true
|
|
732
744
|
: undefined;
|
|
733
|
-
//
|
|
734
|
-
if (
|
|
745
|
+
// An unchanged element may still connect a changed descendant to its model root.
|
|
746
|
+
if (this._sourceDbChanges !== undefined && isUpdate === undefined) {
|
|
735
747
|
return this.exportChildElements(elementId);
|
|
736
748
|
}
|
|
737
749
|
const element = this.sourceDb.elements.getElement({
|
|
@@ -748,9 +760,7 @@ class IModelExporter {
|
|
|
748
760
|
await this._elementAspectExportCoordinator.addAcceptedOwner(elementId);
|
|
749
761
|
return this.exportChildElements(elementId);
|
|
750
762
|
}
|
|
751
|
-
|
|
752
|
-
await this.handler.onSkipElement(element.id);
|
|
753
|
-
}
|
|
763
|
+
await this.handler.onSkipElement(element.id);
|
|
754
764
|
}
|
|
755
765
|
/** Export the child elements of the specified element from the source iModel.
|
|
756
766
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
@@ -763,7 +773,15 @@ class IModelExporter {
|
|
|
763
773
|
core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportChildElements(${elementId})`);
|
|
764
774
|
return;
|
|
765
775
|
}
|
|
766
|
-
|
|
776
|
+
let childElementIds;
|
|
777
|
+
if (this.canUseChangedElementForest()) {
|
|
778
|
+
const forest = await this.getChangedElementForest();
|
|
779
|
+
if (forest !== undefined) {
|
|
780
|
+
core_bentley_1.Logger.logTrace(loggerCategory, `exportChildElements(${elementId}) via changed-element index`);
|
|
781
|
+
childElementIds = forest.getChildren(elementId);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
childElementIds ??= this.sourceDb.elements.queryChildren(elementId);
|
|
767
785
|
if (childElementIds.length > 0) {
|
|
768
786
|
core_bentley_1.Logger.logTrace(loggerCategory, `exportChildElements(${elementId})`);
|
|
769
787
|
for (const childElementId of childElementIds) {
|
|
@@ -771,6 +789,54 @@ class IModelExporter {
|
|
|
771
789
|
}
|
|
772
790
|
}
|
|
773
791
|
}
|
|
792
|
+
/** Whether change processing may use the sparse hierarchy as the child-id source.
|
|
793
|
+
* Custom traversal overrides retain the previous full element dispatch.
|
|
794
|
+
*/
|
|
795
|
+
canUseChangedElementForest() {
|
|
796
|
+
return (this._sourceDbChanges !== undefined &&
|
|
797
|
+
this._changedElementTraversal?.useForest === true &&
|
|
798
|
+
this.exportElement === IModelExporter.prototype.exportElement &&
|
|
799
|
+
this.exportChildElements === IModelExporter.prototype.exportChildElements);
|
|
800
|
+
}
|
|
801
|
+
getOverriddenElementTraversalMethods() {
|
|
802
|
+
const methods = [];
|
|
803
|
+
if (this.exportElement !== IModelExporter.prototype.exportElement)
|
|
804
|
+
methods.push("exportElement");
|
|
805
|
+
if (this.exportChildElements !== IModelExporter.prototype.exportChildElements)
|
|
806
|
+
methods.push("exportChildElements");
|
|
807
|
+
return methods;
|
|
808
|
+
}
|
|
809
|
+
disableChangedElementForest(reason) {
|
|
810
|
+
if (!this._changedElementTraversal?.useForest)
|
|
811
|
+
return;
|
|
812
|
+
this._changedElementTraversal.useForest = false;
|
|
813
|
+
core_bentley_1.Logger.logInfo(loggerCategory, `Using full element traversal for change processing because ${reason}.`);
|
|
814
|
+
}
|
|
815
|
+
async createChangedElementForest() {
|
|
816
|
+
(0, node_assert_1.strict)(this._sourceDbChanges !== undefined, "changed-element traversal requires sourceDbChanges");
|
|
817
|
+
const excludedElementIds = this._excludedElementIds;
|
|
818
|
+
const candidateCountUpperBound = this._sourceDbChanges.element.insertIds.size +
|
|
819
|
+
this._sourceDbChanges.element.updateIds.size +
|
|
820
|
+
excludedElementIds.size;
|
|
821
|
+
if (candidateCountUpperBound > this._changedElementForestElementLimit) {
|
|
822
|
+
this.disableChangedElementForest(`${candidateCountUpperBound} candidate element references exceed the ${this._changedElementForestElementLimit}-element in-memory index limit`);
|
|
823
|
+
return undefined;
|
|
824
|
+
}
|
|
825
|
+
const forest = await ChangedElementForest_1.ChangedElementForest.create(this.sourceDb, [
|
|
826
|
+
...this._sourceDbChanges.element.insertIds,
|
|
827
|
+
...this._sourceDbChanges.element.updateIds,
|
|
828
|
+
...excludedElementIds,
|
|
829
|
+
], this._changedElementForestElementLimit);
|
|
830
|
+
if (forest === undefined) {
|
|
831
|
+
this.disableChangedElementForest(`the required parent hierarchy exceeds the ${this._changedElementForestElementLimit}-element in-memory index limit`);
|
|
832
|
+
}
|
|
833
|
+
return forest;
|
|
834
|
+
}
|
|
835
|
+
async getChangedElementForest() {
|
|
836
|
+
const traversal = this._changedElementTraversal;
|
|
837
|
+
(0, node_assert_1.strict)(traversal !== undefined, "changed-element index requires an active traversal scope");
|
|
838
|
+
return (traversal.forest ??= this.createChangedElementForest());
|
|
839
|
+
}
|
|
774
840
|
/** Exports all aspects owned by the supplied elements. */
|
|
775
841
|
async exportAspectsForOwners(ownerElementIds) {
|
|
776
842
|
return this._elementAspectExportCoordinator.exportOwners(ownerElementIds);
|
|
@@ -831,8 +897,30 @@ class IModelExporter {
|
|
|
831
897
|
}
|
|
832
898
|
return this.shouldExportModelForAspect(modelFact.parentModelId, elementFacts, modelFacts);
|
|
833
899
|
}
|
|
900
|
+
beginChangedElementTraversalScope() {
|
|
901
|
+
if (this._sourceDbChanges === undefined ||
|
|
902
|
+
this._changedElementTraversal !== undefined) {
|
|
903
|
+
return false;
|
|
904
|
+
}
|
|
905
|
+
this._changedElementTraversal = { useForest: true };
|
|
906
|
+
const overriddenMethods = this.getOverriddenElementTraversalMethods();
|
|
907
|
+
if (this.visitElements && overriddenMethods.length > 0) {
|
|
908
|
+
this.disableChangedElementForest(`${overriddenMethods.join(" and ")} ${overriddenMethods.length === 1 ? "is" : "are"} overridden by the exporter subclass`);
|
|
909
|
+
}
|
|
910
|
+
return true;
|
|
911
|
+
}
|
|
912
|
+
endChangedElementTraversalScope() {
|
|
913
|
+
this._changedElementTraversal = undefined;
|
|
914
|
+
}
|
|
834
915
|
async runScopedElementExport(exportElements) {
|
|
835
|
-
|
|
916
|
+
const ownsChangedElementTraversal = this.beginChangedElementTraversalScope();
|
|
917
|
+
try {
|
|
918
|
+
await this._elementAspectExportCoordinator.run(exportElements);
|
|
919
|
+
}
|
|
920
|
+
finally {
|
|
921
|
+
if (ownsChangedElementTraversal)
|
|
922
|
+
this.endChangedElementTraversalScope();
|
|
923
|
+
}
|
|
836
924
|
}
|
|
837
925
|
/** Apply the element export filter when deciding whether to process an aspect owner. @internal */
|
|
838
926
|
async shouldExportElementForAspect(elementId, elementFact) {
|
|
@@ -910,8 +998,7 @@ class IModelExporter {
|
|
|
910
998
|
ec_className(e.ECClassId, 's') schemaName,
|
|
911
999
|
ec_className(e.ECClassId, 'c') className
|
|
912
1000
|
FROM bis.Element e
|
|
913
|
-
INNER JOIN IdSet(:elementIds) ids ON ids.id = e.ECInstanceId
|
|
914
|
-
OPTIONS ENABLE_EXPERIMENTAL_FEATURES`, queryParams, { usePrimaryConn: true })) {
|
|
1001
|
+
INNER JOIN IdSet(:elementIds) ids ON ids.id = e.ECInstanceId`, queryParams, { usePrimaryConn: true })) {
|
|
915
1002
|
elementFacts.set(row.id, {
|
|
916
1003
|
id: row.id,
|
|
917
1004
|
parentId: row.parentId ?? undefined,
|
|
@@ -923,8 +1010,7 @@ class IModelExporter {
|
|
|
923
1010
|
const categoryQueryParams = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIdBatch);
|
|
924
1011
|
for await (const row of this.sourceDb.createQueryReader(`SELECT g.ECInstanceId id, g.Category.Id categoryId
|
|
925
1012
|
FROM bis.GeometricElement g
|
|
926
|
-
INNER JOIN IdSet(:elementIds) ids ON ids.id = g.ECInstanceId
|
|
927
|
-
OPTIONS ENABLE_EXPERIMENTAL_FEATURES`, categoryQueryParams, { usePrimaryConn: true })) {
|
|
1013
|
+
INNER JOIN IdSet(:elementIds) ids ON ids.id = g.ECInstanceId`, categoryQueryParams, { usePrimaryConn: true })) {
|
|
928
1014
|
const elementFact = elementFacts.get(row.id);
|
|
929
1015
|
if (elementFact !== undefined) {
|
|
930
1016
|
elementFact.categoryId = row.categoryId;
|
|
@@ -944,8 +1030,7 @@ class IModelExporter {
|
|
|
944
1030
|
const queryParams = new core_common_1.QueryBinder().bindIdSet("modelIds", modelIdBatch);
|
|
945
1031
|
for await (const row of this.sourceDb.createQueryReader(`SELECT model.ECInstanceId id, model.ParentModel.Id parentModelId, model.IsTemplate isTemplate
|
|
946
1032
|
FROM bis.Model model
|
|
947
|
-
INNER JOIN IdSet(:modelIds) ids ON ids.id = model.ECInstanceId
|
|
948
|
-
OPTIONS ENABLE_EXPERIMENTAL_FEATURES`, queryParams, { usePrimaryConn: true })) {
|
|
1033
|
+
INNER JOIN IdSet(:modelIds) ids ON ids.id = model.ECInstanceId`, queryParams, { usePrimaryConn: true })) {
|
|
949
1034
|
modelFacts.set(row.id, {
|
|
950
1035
|
id: row.id,
|
|
951
1036
|
parentModelId: row.parentModelId ?? undefined,
|
|
@@ -1448,7 +1533,6 @@ class ChangedInstanceIds {
|
|
|
1448
1533
|
INNER JOIN hierarchy h ON h.parentId = e.ECInstanceId
|
|
1449
1534
|
)
|
|
1450
1535
|
SELECT parentId FROM hierarchy where parentId is not null
|
|
1451
|
-
OPTIONS ENABLE_EXPERIMENTAL_FEATURES
|
|
1452
1536
|
`;
|
|
1453
1537
|
const parentModelIds = new Set();
|
|
1454
1538
|
for await (const row of this._db.createQueryReader(ecQuery, params, {
|
|
@@ -1475,8 +1559,7 @@ class ChangedInstanceIds {
|
|
|
1475
1559
|
SELECT relationship.ECInstanceId
|
|
1476
1560
|
FROM ${relationshipClassName} relationship
|
|
1477
1561
|
INNER JOIN IdSet(:elementIds) ids
|
|
1478
|
-
ON ids.id = relationship.SourceECInstanceId
|
|
1479
|
-
OPTIONS ENABLE_EXPERIMENTAL_FEATURES`;
|
|
1562
|
+
ON ids.id = relationship.SourceECInstanceId`;
|
|
1480
1563
|
const queryBinder = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
|
|
1481
1564
|
const queryReader = this._db.createQueryReader(ecQuery, queryBinder, {
|
|
1482
1565
|
usePrimaryConn: true,
|
|
@@ -1492,8 +1575,7 @@ class ChangedInstanceIds {
|
|
|
1492
1575
|
]) {
|
|
1493
1576
|
const ecQuery = `SELECT aspect.ECInstanceId, aspect.Element.Id
|
|
1494
1577
|
FROM ${aspectClassName} aspect
|
|
1495
|
-
INNER JOIN IdSet(:elementIds) ids ON ids.id = aspect.Element.Id
|
|
1496
|
-
OPTIONS ENABLE_EXPERIMENTAL_FEATURES`;
|
|
1578
|
+
INNER JOIN IdSet(:elementIds) ids ON ids.id = aspect.Element.Id`;
|
|
1497
1579
|
const queryBinder = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
|
|
1498
1580
|
const queryReader = this._db.createQueryReader(ecQuery, queryBinder, {
|
|
1499
1581
|
usePrimaryConn: true,
|