@itwin/imodel-transformer 2.0.0-dev.6 → 2.0.0-dev.60

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.
Files changed (123) hide show
  1. package/README.md +13 -27
  2. package/lib/cjs/Algo.js.map +1 -1
  3. package/lib/cjs/BigMap.d.ts.map +1 -1
  4. package/lib/cjs/BigMap.js.map +1 -1
  5. package/lib/cjs/BranchProvenanceInitializer.d.ts.map +1 -1
  6. package/lib/cjs/BranchProvenanceInitializer.js +34 -34
  7. package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
  8. package/lib/cjs/ChangedElementForest.d.ts +14 -0
  9. package/lib/cjs/ChangedElementForest.d.ts.map +1 -0
  10. package/lib/cjs/ChangedElementForest.js +86 -0
  11. package/lib/cjs/ChangedElementForest.js.map +1 -0
  12. package/lib/cjs/ChangesetScanner.d.ts +61 -0
  13. package/lib/cjs/ChangesetScanner.d.ts.map +1 -0
  14. package/lib/cjs/ChangesetScanner.js +104 -0
  15. package/lib/cjs/ChangesetScanner.js.map +1 -0
  16. package/lib/cjs/ECReferenceTypesCache.d.ts +0 -3
  17. package/lib/cjs/ECReferenceTypesCache.d.ts.map +1 -1
  18. package/lib/cjs/ECReferenceTypesCache.js +61 -104
  19. package/lib/cjs/ECReferenceTypesCache.js.map +1 -1
  20. package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.d.ts.map +1 -1
  21. package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.js.map +1 -1
  22. package/lib/cjs/ElementAspectCleanup.d.ts +16 -0
  23. package/lib/cjs/ElementAspectCleanup.d.ts.map +1 -0
  24. package/lib/cjs/ElementAspectCleanup.js +87 -0
  25. package/lib/cjs/ElementAspectCleanup.js.map +1 -0
  26. package/lib/cjs/ElementAspectExportCoordinator.d.ts +44 -0
  27. package/lib/cjs/ElementAspectExportCoordinator.d.ts.map +1 -0
  28. package/lib/cjs/ElementAspectExportCoordinator.js +148 -0
  29. package/lib/cjs/ElementAspectExportCoordinator.js.map +1 -0
  30. package/lib/cjs/ElementAspectExportProcessor.d.ts +44 -0
  31. package/lib/cjs/ElementAspectExportProcessor.d.ts.map +1 -0
  32. package/lib/cjs/ElementAspectExportProcessor.js +152 -0
  33. package/lib/cjs/ElementAspectExportProcessor.js.map +1 -0
  34. package/lib/cjs/ElementBulkDelete.d.ts +11 -0
  35. package/lib/cjs/ElementBulkDelete.d.ts.map +1 -0
  36. package/lib/cjs/ElementBulkDelete.js +55 -0
  37. package/lib/cjs/ElementBulkDelete.js.map +1 -0
  38. package/lib/cjs/EntityExistenceCache.d.ts +43 -0
  39. package/lib/cjs/EntityExistenceCache.d.ts.map +1 -0
  40. package/lib/cjs/EntityExistenceCache.js +91 -0
  41. package/lib/cjs/EntityExistenceCache.js.map +1 -0
  42. package/lib/cjs/EntityMap.d.ts.map +1 -1
  43. package/lib/cjs/EntityMap.js.map +1 -1
  44. package/lib/cjs/EntityUnifier.d.ts +8 -8
  45. package/lib/cjs/EntityUnifier.d.ts.map +1 -1
  46. package/lib/cjs/EntityUnifier.js +56 -32
  47. package/lib/cjs/EntityUnifier.js.map +1 -1
  48. package/lib/cjs/IModelCloneContext.d.ts +9 -3
  49. package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
  50. package/lib/cjs/IModelCloneContext.js +66 -31
  51. package/lib/cjs/IModelCloneContext.js.map +1 -1
  52. package/lib/cjs/IModelExporter.d.ts +143 -30
  53. package/lib/cjs/IModelExporter.d.ts.map +1 -1
  54. package/lib/cjs/IModelExporter.js +893 -178
  55. package/lib/cjs/IModelExporter.js.map +1 -1
  56. package/lib/cjs/IModelImporter.d.ts +71 -30
  57. package/lib/cjs/IModelImporter.d.ts.map +1 -1
  58. package/lib/cjs/IModelImporter.js +269 -132
  59. package/lib/cjs/IModelImporter.js.map +1 -1
  60. package/lib/cjs/IModelTransformContext.d.ts +54 -0
  61. package/lib/cjs/IModelTransformContext.d.ts.map +1 -0
  62. package/lib/cjs/IModelTransformContext.js +3 -0
  63. package/lib/cjs/IModelTransformContext.js.map +1 -0
  64. package/lib/cjs/IModelTransformer.d.ts +130 -196
  65. package/lib/cjs/IModelTransformer.d.ts.map +1 -1
  66. package/lib/cjs/IModelTransformer.js +697 -1155
  67. package/lib/cjs/IModelTransformer.js.map +1 -1
  68. package/lib/cjs/IModelTransformerError.d.ts +84 -0
  69. package/lib/cjs/IModelTransformerError.d.ts.map +1 -0
  70. package/lib/cjs/IModelTransformerError.js +93 -0
  71. package/lib/cjs/IModelTransformerError.js.map +1 -0
  72. package/lib/cjs/ProvenanceManager.d.ts +177 -0
  73. package/lib/cjs/ProvenanceManager.d.ts.map +1 -0
  74. package/lib/cjs/ProvenanceManager.js +719 -0
  75. package/lib/cjs/ProvenanceManager.js.map +1 -0
  76. package/lib/cjs/SyncTypeResolver.d.ts +34 -0
  77. package/lib/cjs/SyncTypeResolver.d.ts.map +1 -0
  78. package/lib/cjs/SyncTypeResolver.js +98 -0
  79. package/lib/cjs/SyncTypeResolver.js.map +1 -0
  80. package/lib/cjs/TransformerLoggerCategory.d.ts +1 -1
  81. package/lib/cjs/TransformerLoggerCategory.js +1 -1
  82. package/lib/cjs/TransformerLoggerCategory.js.map +1 -1
  83. package/lib/cjs/TransformerPackageMetadata.d.ts +8 -0
  84. package/lib/cjs/TransformerPackageMetadata.d.ts.map +1 -0
  85. package/lib/cjs/TransformerPackageMetadata.js +47 -0
  86. package/lib/cjs/TransformerPackageMetadata.js.map +1 -0
  87. package/lib/cjs/imodel-transformer.d.ts +27 -0
  88. package/lib/cjs/imodel-transformer.d.ts.map +1 -1
  89. package/lib/cjs/imodel-transformer.js +61 -34
  90. package/lib/cjs/imodel-transformer.js.map +1 -1
  91. package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.d.ts +29 -0
  92. package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.d.ts.map +1 -0
  93. package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.js +212 -0
  94. package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.js.map +1 -0
  95. package/lib/cjs/schema-processing/SchemaProcessingCoordinator.d.ts +25 -0
  96. package/lib/cjs/schema-processing/SchemaProcessingCoordinator.d.ts.map +1 -0
  97. package/lib/cjs/schema-processing/SchemaProcessingCoordinator.js +196 -0
  98. package/lib/cjs/schema-processing/SchemaProcessingCoordinator.js.map +1 -0
  99. package/lib/cjs/schema-processing/SchemaProcessingStrategy.d.ts +59 -0
  100. package/lib/cjs/schema-processing/SchemaProcessingStrategy.d.ts.map +1 -0
  101. package/lib/cjs/schema-processing/SchemaProcessingStrategy.js +28 -0
  102. package/lib/cjs/schema-processing/SchemaProcessingStrategy.js.map +1 -0
  103. package/lib/cjs/schema-processing.d.ts +7 -0
  104. package/lib/cjs/schema-processing.d.ts.map +1 -0
  105. package/lib/cjs/schema-processing.js +27 -0
  106. package/lib/cjs/schema-processing.js.map +1 -0
  107. package/package.json +65 -43
  108. package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts +0 -16
  109. package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts.map +0 -1
  110. package/lib/cjs/DetachedExportElementAspectsStrategy.js +0 -106
  111. package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +0 -1
  112. package/lib/cjs/ElementCascadingDeleter.d.ts +0 -22
  113. package/lib/cjs/ElementCascadingDeleter.d.ts.map +0 -1
  114. package/lib/cjs/ElementCascadingDeleter.js +0 -57
  115. package/lib/cjs/ElementCascadingDeleter.js.map +0 -1
  116. package/lib/cjs/ExportElementAspectsStrategy.d.ts +0 -35
  117. package/lib/cjs/ExportElementAspectsStrategy.d.ts.map +0 -1
  118. package/lib/cjs/ExportElementAspectsStrategy.js +0 -52
  119. package/lib/cjs/ExportElementAspectsStrategy.js.map +0 -1
  120. package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts +0 -12
  121. package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts.map +0 -1
  122. package/lib/cjs/ExportElementAspectsWithElementsStrategy.js +0 -47
  123. package/lib/cjs/ExportElementAspectsWithElementsStrategy.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ /** @packageDocumentation
2
+ * @module Utils
3
+ */
4
+ import { EntityReference } from "@itwin/core-common";
5
+ import { IModelDb } from "@itwin/core-backend";
6
+ /** A positive-only read-through cache of entity existence checks, scoped to a single transformation run.
7
+ *
8
+ * Entities are created continuously as a transformation progresses, so a negative
9
+ * ("does not exist") result may become stale at any moment — therefore only positive
10
+ * results are ever cached. Positive results can only be invalidated by deletes, which the
11
+ * transformer routes through [[invalidate]] and [[clearDb]].
12
+ *
13
+ * The cache is keyed by [IModelDb]($core-backend) instance, so same-iModel transformations
14
+ * (where sourceDb === targetDb) share a single set and source/target roles cannot be confused.
15
+ *
16
+ * [IModelImporter]($transformer) delete operations invalidate registered caches. Deletes performed
17
+ * directly through an `EditTxn` while a transformation is active are out-of-band and must not be
18
+ * mixed with transformer operations. A successful high-level `process()` clears the cache when the
19
+ * transformation finalizes; low-level or failed transformations clear it when the transformer is
20
+ * disposed.
21
+ * @internal
22
+ */
23
+ export declare class EntityExistenceCache {
24
+ private _existsByDb;
25
+ private getDbSet;
26
+ /** Check whether an entity exists in `db`, consulting the cache first.
27
+ * A `true` result is cached; a `false` result is never cached and will be re-queried.
28
+ */
29
+ exists(db: IModelDb, entityReference: EntityReference): Promise<boolean>;
30
+ /** Read through the cache to check which of the supplied entities exist in `db`, populating it on a miss. */
31
+ existsAll(db: IModelDb, entityReferences: Iterable<EntityReference>): Promise<ReadonlySet<EntityReference>>;
32
+ /** Record that an entity is known to exist in `db` (e.g. it was just imported). */
33
+ markExists(db: IModelDb, entityReference: EntityReference): void;
34
+ /** Remove a single entity from the cache for `db`, forcing a re-query on next check. */
35
+ invalidate(db: IModelDb, entityReference: EntityReference): void;
36
+ /** Drop all cached results for `db`. Used when a delete may cascade to entities the
37
+ * caller cannot enumerate (e.g. element tree deletes that remove descendants and submodels).
38
+ */
39
+ clearDb(db: IModelDb): void;
40
+ /** Drop all cached results. */
41
+ clear(): void;
42
+ }
43
+ //# sourceMappingURL=EntityExistenceCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityExistenceCache.d.ts","sourceRoot":"","sources":["../../src/EntityExistenceCache.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,WAAW,CAA6C;IAEhE,OAAO,CAAC,QAAQ;IAShB;;OAEG;IACU,MAAM,CACjB,EAAE,EAAE,QAAQ,EACZ,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,OAAO,CAAC,CAMlB;IAED,6GAA6G;IAChG,SAAS,CACpB,EAAE,EAAE,QAAQ,EACZ,gBAAgB,EAAE,QAAQ,CAAC,eAAe,CAAC,GAC1C,OAAO,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAkBvC;IAED,mFAAmF;IAC5E,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,GAAG,IAAI,CAEtE;IAED,wFAAwF;IACjF,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,GAAG,IAAI,CAEtE;IAED;;OAEG;IACI,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAEjC;IAED,+BAA+B;IACxB,KAAK,IAAI,IAAI,CAEnB;CACF"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ /** @packageDocumentation
7
+ * @module Utils
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EntityExistenceCache = void 0;
11
+ const EntityUnifier_1 = require("./EntityUnifier");
12
+ /** A positive-only read-through cache of entity existence checks, scoped to a single transformation run.
13
+ *
14
+ * Entities are created continuously as a transformation progresses, so a negative
15
+ * ("does not exist") result may become stale at any moment — therefore only positive
16
+ * results are ever cached. Positive results can only be invalidated by deletes, which the
17
+ * transformer routes through [[invalidate]] and [[clearDb]].
18
+ *
19
+ * The cache is keyed by [IModelDb]($core-backend) instance, so same-iModel transformations
20
+ * (where sourceDb === targetDb) share a single set and source/target roles cannot be confused.
21
+ *
22
+ * [IModelImporter]($transformer) delete operations invalidate registered caches. Deletes performed
23
+ * directly through an `EditTxn` while a transformation is active are out-of-band and must not be
24
+ * mixed with transformer operations. A successful high-level `process()` clears the cache when the
25
+ * transformation finalizes; low-level or failed transformations clear it when the transformer is
26
+ * disposed.
27
+ * @internal
28
+ */
29
+ class EntityExistenceCache {
30
+ _existsByDb = new Map();
31
+ getDbSet(db) {
32
+ let set = this._existsByDb.get(db);
33
+ if (set === undefined) {
34
+ set = new Set();
35
+ this._existsByDb.set(db, set);
36
+ }
37
+ return set;
38
+ }
39
+ /** Check whether an entity exists in `db`, consulting the cache first.
40
+ * A `true` result is cached; a `false` result is never cached and will be re-queried.
41
+ */
42
+ async exists(db, entityReference) {
43
+ const set = this.getDbSet(db);
44
+ if (set.has(entityReference))
45
+ return true;
46
+ const found = await EntityUnifier_1.EntityUnifier.exists(db, { entityReference });
47
+ if (found)
48
+ set.add(entityReference);
49
+ return found;
50
+ }
51
+ /** Read through the cache to check which of the supplied entities exist in `db`, populating it on a miss. */
52
+ async existsAll(db, entityReferences) {
53
+ const dbSet = this.getDbSet(db);
54
+ const found = new Set();
55
+ const unverified = [];
56
+ for (const entityReference of entityReferences) {
57
+ if (dbSet.has(entityReference))
58
+ found.add(entityReference);
59
+ else
60
+ unverified.push(entityReference);
61
+ }
62
+ if (unverified.length === 0)
63
+ return found;
64
+ const queried = await EntityUnifier_1.EntityUnifier.existsAll(db, unverified);
65
+ for (const entityReference of queried) {
66
+ dbSet.add(entityReference);
67
+ found.add(entityReference);
68
+ }
69
+ return found;
70
+ }
71
+ /** Record that an entity is known to exist in `db` (e.g. it was just imported). */
72
+ markExists(db, entityReference) {
73
+ this.getDbSet(db).add(entityReference);
74
+ }
75
+ /** Remove a single entity from the cache for `db`, forcing a re-query on next check. */
76
+ invalidate(db, entityReference) {
77
+ this._existsByDb.get(db)?.delete(entityReference);
78
+ }
79
+ /** Drop all cached results for `db`. Used when a delete may cascade to entities the
80
+ * caller cannot enumerate (e.g. element tree deletes that remove descendants and submodels).
81
+ */
82
+ clearDb(db) {
83
+ this._existsByDb.delete(db);
84
+ }
85
+ /** Drop all cached results. */
86
+ clear() {
87
+ this._existsByDb.clear();
88
+ }
89
+ }
90
+ exports.EntityExistenceCache = EntityExistenceCache;
91
+ //# sourceMappingURL=EntityExistenceCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityExistenceCache.js","sourceRoot":"","sources":["../../src/EntityExistenceCache.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;AAChG;;GAEG;;;AAIH,mDAAgD;AAEhD;;;;;;;;;;;;;;;;GAgBG;AACH;IACU,WAAW,GAAG,IAAI,GAAG,EAAkC,CAAC;IAExD,QAAQ,CAAC,EAAY;QAC3B,IAAI,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,MAAM,CACjB,EAAY,EACZ,eAAgC;QAEhC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,6BAAa,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;QAClE,IAAI,KAAK;YAAE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6GAA6G;IACtG,KAAK,CAAC,SAAS,CACpB,EAAY,EACZ,gBAA2C;QAE3C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;QACzC,MAAM,UAAU,GAAsB,EAAE,CAAC;QAEzC,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE,CAAC;YAC/C,IAAI,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;;gBACtD,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,6BAAa,CAAC,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9D,KAAK,MAAM,eAAe,IAAI,OAAO,EAAE,CAAC;YACtC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAC3B,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mFAAmF;IAC5E,UAAU,CAAC,EAAY,EAAE,eAAgC;QAC9D,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACzC,CAAC;IAED,wFAAwF;IACjF,UAAU,CAAC,EAAY,EAAE,eAAgC;QAC9D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,EAAY;QACzB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,+BAA+B;IACxB,KAAK;QACV,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Utils\n */\n\nimport { EntityReference } from \"@itwin/core-common\";\nimport { IModelDb } from \"@itwin/core-backend\";\nimport { EntityUnifier } from \"./EntityUnifier\";\n\n/** A positive-only read-through cache of entity existence checks, scoped to a single transformation run.\n *\n * Entities are created continuously as a transformation progresses, so a negative\n * (\"does not exist\") result may become stale at any moment — therefore only positive\n * results are ever cached. Positive results can only be invalidated by deletes, which the\n * transformer routes through [[invalidate]] and [[clearDb]].\n *\n * The cache is keyed by [IModelDb]($core-backend) instance, so same-iModel transformations\n * (where sourceDb === targetDb) share a single set and source/target roles cannot be confused.\n *\n * [IModelImporter]($transformer) delete operations invalidate registered caches. Deletes performed\n * directly through an `EditTxn` while a transformation is active are out-of-band and must not be\n * mixed with transformer operations. A successful high-level `process()` clears the cache when the\n * transformation finalizes; low-level or failed transformations clear it when the transformer is\n * disposed.\n * @internal\n */\nexport class EntityExistenceCache {\n private _existsByDb = new Map<IModelDb, Set<EntityReference>>();\n\n private getDbSet(db: IModelDb): Set<EntityReference> {\n let set = this._existsByDb.get(db);\n if (set === undefined) {\n set = new Set();\n this._existsByDb.set(db, set);\n }\n return set;\n }\n\n /** Check whether an entity exists in `db`, consulting the cache first.\n * A `true` result is cached; a `false` result is never cached and will be re-queried.\n */\n public async exists(\n db: IModelDb,\n entityReference: EntityReference\n ): Promise<boolean> {\n const set = this.getDbSet(db);\n if (set.has(entityReference)) return true;\n const found = await EntityUnifier.exists(db, { entityReference });\n if (found) set.add(entityReference);\n return found;\n }\n\n /** Read through the cache to check which of the supplied entities exist in `db`, populating it on a miss. */\n public async existsAll(\n db: IModelDb,\n entityReferences: Iterable<EntityReference>\n ): Promise<ReadonlySet<EntityReference>> {\n const dbSet = this.getDbSet(db);\n const found = new Set<EntityReference>();\n const unverified: EntityReference[] = [];\n\n for (const entityReference of entityReferences) {\n if (dbSet.has(entityReference)) found.add(entityReference);\n else unverified.push(entityReference);\n }\n\n if (unverified.length === 0) return found;\n\n const queried = await EntityUnifier.existsAll(db, unverified);\n for (const entityReference of queried) {\n dbSet.add(entityReference);\n found.add(entityReference);\n }\n return found;\n }\n\n /** Record that an entity is known to exist in `db` (e.g. it was just imported). */\n public markExists(db: IModelDb, entityReference: EntityReference): void {\n this.getDbSet(db).add(entityReference);\n }\n\n /** Remove a single entity from the cache for `db`, forcing a re-query on next check. */\n public invalidate(db: IModelDb, entityReference: EntityReference): void {\n this._existsByDb.get(db)?.delete(entityReference);\n }\n\n /** Drop all cached results for `db`. Used when a delete may cascade to entities the\n * caller cannot enumerate (e.g. element tree deletes that remove descendants and submodels).\n */\n public clearDb(db: IModelDb): void {\n this._existsByDb.delete(db);\n }\n\n /** Drop all cached results. */\n public clear(): void {\n this._existsByDb.clear();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityMap.d.ts","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AAGvE,gBAAgB;AAChB,MAAM,MAAM,SAAS,GAAG,eAAe,CAAC;AAExC,gBAAgB;AAChB,qBAAa,SAAS,CAAC,CAAC;IACtB,OAAO,CAAC,IAAI,CAAmB;WAEjB,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS;IAIjD,KAAK,IAAI,IAAI;IAIb,GAAG,CAAC,MAAM,EAAE,cAAc;IAI1B,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAIjD,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAK5C,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,SAAS;IAI1C,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,SAAS;IAIrC,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO;IAIvC,WAAW,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO;IAIlC,IAAI;IAIJ,MAAM;IAIN,OAAO;IAIP,CAAC,MAAM,CAAC,QAAQ,CAAC;IAIxB,IAAW,IAAI,WAEd;CACF"}
1
+ {"version":3,"file":"EntityMap.d.ts","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AAGvE,gBAAgB;AAChB,MAAM,MAAM,SAAS,GAAG,eAAe,CAAC;AAExC,gBAAgB;AAChB,qBAAa,SAAS,CAAC,CAAC;IACtB,OAAO,CAAC,IAAI,CAAmB;IAE/B,OAAc,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,CAEvD;IAEM,KAAK,IAAI,IAAI,CAEnB;IAEM,GAAG,CAAC,MAAM,EAAE,cAAc,WAEhC;IAEM,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAEvD;IAEM,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAGlD;IAEM,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,SAAS,CAEhD;IAEM,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,SAAS,CAE3C;IAEM,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAE7C;IAEM,WAAW,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAExC;IAEM,IAAI,wBAEV;IAEM,MAAM,mBAEZ;IAEM,OAAO,6BAEb;IAEM,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAEvB;IAED,IAAW,IAAI,WAEd;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityMap.js","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":";;;AAQA,sDAAuE;AACvE,qCAAkC;AAKlC,gBAAgB;AAChB,MAAa,SAAS;IACZ,IAAI,GAAG,IAAI,eAAM,EAAK,CAAC;IAExB,MAAM,CAAC,OAAO,CAAC,MAAsB;QAC1C,OAAO,+BAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEM,KAAK;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAEM,GAAG,CAAC,MAAsB;QAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC;IAEM,GAAG,CAAC,MAAsB,EAAE,GAAM;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,CAAC;IAEM,QAAQ,CAAC,CAAY,EAAE,GAAM;QAClC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,GAAG,CAAC,MAAsB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC;IAEM,QAAQ,CAAC,CAAY;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAEM,MAAM,CAAC,MAAsB;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAEM,WAAW,CAAC,CAAY;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAEM,IAAI;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAEM,CAAC,MAAM,CAAC,QAAQ,CAAC;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtC,CAAC;IAED,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;CACF;AA3DD,8BA2DC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Utils\n */\nimport { EntityReference } from \"@itwin/core-common\";\nimport { ConcreteEntity, EntityReferences } from \"@itwin/core-backend\";\nimport { BigMap } from \"./BigMap\";\n\n/** @internal */\nexport type EntityKey = EntityReference;\n\n/** @internal */\nexport class EntityMap<V> {\n private _map = new BigMap<V>();\n\n public static makeKey(entity: ConcreteEntity): EntityKey {\n return EntityReferences.from(entity);\n }\n\n public clear(): void {\n return this._map.clear();\n }\n\n public has(entity: ConcreteEntity) {\n return this._map.has(EntityMap.makeKey(entity));\n }\n\n public set(entity: ConcreteEntity, val: V): EntityMap<V> {\n return this.setByKey(EntityMap.makeKey(entity), val);\n }\n\n public setByKey(k: EntityKey, val: V): EntityMap<V> {\n this._map.set(k, val);\n return this;\n }\n\n public get(entity: ConcreteEntity): V | undefined {\n return this.getByKey(EntityMap.makeKey(entity));\n }\n\n public getByKey(k: EntityKey): V | undefined {\n return this._map.get(k);\n }\n\n public delete(entity: ConcreteEntity): boolean {\n return this.deleteByKey(EntityMap.makeKey(entity));\n }\n\n public deleteByKey(k: EntityKey): boolean {\n return this._map.delete(k);\n }\n\n public keys() {\n return this._map.keys();\n }\n\n public values() {\n return this._map.values();\n }\n\n public entries() {\n return this._map.entries();\n }\n\n public [Symbol.iterator]() {\n return this._map[Symbol.iterator]();\n }\n\n public get size() {\n return this._map.size;\n }\n}\n"]}
1
+ {"version":3,"file":"EntityMap.js","sourceRoot":"","sources":["../../src/EntityMap.ts"],"names":[],"mappings":";;;AAQA,sDAAuE;AACvE,qCAAkC;AAKlC,gBAAgB;AAChB;IACU,IAAI,GAAG,IAAI,eAAM,EAAK,CAAC;IAExB,MAAM,CAAC,OAAO,CAAC,MAAsB;QAC1C,OAAO,+BAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEM,KAAK;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAEM,GAAG,CAAC,MAAsB;QAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC;IAEM,GAAG,CAAC,MAAsB,EAAE,GAAM;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,CAAC;IAEM,QAAQ,CAAC,CAAY,EAAE,GAAM;QAClC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,GAAG,CAAC,MAAsB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC;IAEM,QAAQ,CAAC,CAAY;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAEM,MAAM,CAAC,MAAsB;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAEM,WAAW,CAAC,CAAY;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAEM,IAAI;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAEM,CAAC,MAAM,CAAC,QAAQ,CAAC;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtC,CAAC;IAED,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Utils\n */\nimport { EntityReference } from \"@itwin/core-common\";\nimport { ConcreteEntity, EntityReferences } from \"@itwin/core-backend\";\nimport { BigMap } from \"./BigMap\";\n\n/** @internal */\nexport type EntityKey = EntityReference;\n\n/** @internal */\nexport class EntityMap<V> {\n private _map = new BigMap<V>();\n\n public static makeKey(entity: ConcreteEntity): EntityKey {\n return EntityReferences.from(entity);\n }\n\n public clear(): void {\n return this._map.clear();\n }\n\n public has(entity: ConcreteEntity) {\n return this._map.has(EntityMap.makeKey(entity));\n }\n\n public set(entity: ConcreteEntity, val: V): EntityMap<V> {\n return this.setByKey(EntityMap.makeKey(entity), val);\n }\n\n public setByKey(k: EntityKey, val: V): EntityMap<V> {\n this._map.set(k, val);\n return this;\n }\n\n public get(entity: ConcreteEntity): V | undefined {\n return this.getByKey(EntityMap.makeKey(entity));\n }\n\n public getByKey(k: EntityKey): V | undefined {\n return this._map.get(k);\n }\n\n public delete(entity: ConcreteEntity): boolean {\n return this.deleteByKey(EntityMap.makeKey(entity));\n }\n\n public deleteByKey(k: EntityKey): boolean {\n return this._map.delete(k);\n }\n\n public keys() {\n return this._map.keys();\n }\n\n public values() {\n return this._map.values();\n }\n\n public entries() {\n return this._map.entries();\n }\n\n public [Symbol.iterator]() {\n return this._map[Symbol.iterator]();\n }\n\n public get size() {\n return this._map.size;\n }\n}\n"]}
@@ -4,18 +4,18 @@
4
4
  * for entity-generic operations in the transformer
5
5
  */
6
6
  import { EntityReference } from "@itwin/core-common";
7
- import { ConcreteEntity, ConcreteEntityProps, IModelDb } from "@itwin/core-backend";
7
+ import { ConcreteEntity, IModelDb } from "@itwin/core-backend";
8
8
  /** @internal */
9
9
  export declare namespace EntityUnifier {
10
- export function getReadableType(entity: ConcreteEntity): "element" | "element aspect" | "relationship" | "unknown entity type";
11
- type EntityUpdater = (entityProps: ConcreteEntityProps) => void;
12
- /** needs to return a widened type otherwise typescript complains when result is used with a narrow type */
13
- export function updaterFor(db: IModelDb, entity: ConcreteEntity): EntityUpdater;
14
- export function exists(db: IModelDb, arg: {
10
+ function getReadableType(entity: ConcreteEntity): "element" | "element aspect" | "relationship" | "unknown entity type";
11
+ function exists(db: IModelDb, arg: {
15
12
  entity: ConcreteEntity;
16
13
  } | {
17
14
  entityReference: EntityReference;
18
- }): boolean;
19
- export {};
15
+ }): Promise<boolean>;
16
+ /** Batched existence check: returns the subset of `entityReferences` that exist in `db`,
17
+ * using one query per concrete entity type instead of one query per reference.
18
+ */
19
+ function existsAll(db: IModelDb, entityReferences: Iterable<EntityReference>): Promise<Set<EntityReference>>;
20
20
  }
21
21
  //# sourceMappingURL=EntityUnifier.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityUnifier.d.ts","sourceRoot":"","sources":["../../src/EntityUnifier.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAGH,OAAO,EAEL,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,mBAAmB,EAKnB,QAAQ,EAET,MAAM,qBAAqB,CAAC;AAG7B,gBAAgB;AAChB,yBAAiB,aAAa,CAAC;IAC7B,MAAM,UAAU,eAAe,CAAC,MAAM,EAAE,cAAc,yEAKrD;IAED,KAAK,aAAa,GAAG,CAAC,WAAW,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAEhE,2GAA2G;IAC3G,MAAM,UAAU,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,iBAc9D;IAED,MAAM,UAAU,MAAM,CACpB,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE;QAAE,MAAM,EAAE,cAAc,CAAA;KAAE,GAAG;QAAE,eAAe,EAAE,eAAe,CAAA;KAAE,WAyBvE;;CACF"}
1
+ {"version":3,"file":"EntityUnifier.d.ts","sourceRoot":"","sources":["../../src/EntityUnifier.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EAEL,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EAMd,QAAQ,EAGT,MAAM,qBAAqB,CAAC;AAU7B,gBAAgB;AAChB,yBAAiB,aAAa,CAAC;IAC7B,SAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,yEAKrD;IAED,SAAsB,MAAM,CAC1B,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE;QAAE,MAAM,EAAE,cAAc,CAAA;KAAE,GAAG;QAAE,eAAe,EAAE,eAAe,CAAA;KAAE,oBAqBvE;IAED;;OAEG;IACH,SAAsB,SAAS,CAC7B,EAAE,EAAE,QAAQ,EACZ,gBAAgB,EAAE,QAAQ,CAAC,eAAe,CAAC,GAC1C,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CA8B/B;CACF"}
@@ -10,10 +10,15 @@
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EntityUnifier = void 0;
13
- const assert = require("assert");
14
13
  const core_common_1 = require("@itwin/core-common");
15
14
  const core_backend_1 = require("@itwin/core-backend");
16
15
  const core_bentley_1 = require("@itwin/core-bentley");
16
+ const bisCoreRootClasses = {
17
+ [core_common_1.ConcreteEntityTypes.Model]: core_backend_1.Model,
18
+ [core_common_1.ConcreteEntityTypes.Element]: core_backend_1.Element,
19
+ [core_common_1.ConcreteEntityTypes.ElementAspect]: core_backend_1.ElementAspect,
20
+ [core_common_1.ConcreteEntityTypes.Relationship]: core_backend_1.Relationship,
21
+ };
17
22
  /** @internal */
18
23
  var EntityUnifier;
19
24
  (function (EntityUnifier) {
@@ -28,40 +33,59 @@ var EntityUnifier;
28
33
  return "unknown entity type";
29
34
  }
30
35
  EntityUnifier.getReadableType = getReadableType;
31
- /** needs to return a widened type otherwise typescript complains when result is used with a narrow type */
32
- function updaterFor(db, entity) {
33
- if (entity instanceof core_backend_1.Element)
34
- return db.elements.updateElement.bind(db.elements);
35
- else if (entity instanceof core_backend_1.Relationship)
36
- return db.relationships.updateInstance.bind(db.relationships);
37
- else if (entity instanceof core_backend_1.ElementAspect)
38
- return db.elements.updateAspect.bind(db.elements);
39
- else
40
- assert(false, `unreachable; entity was '${entity.constructor.name}' not an Element, Relationship, or ElementAspect`);
41
- }
42
- EntityUnifier.updaterFor = updaterFor;
43
- function exists(db, arg) {
44
- const [type, id] = "entityReference" in arg
45
- ? core_backend_1.EntityReferences.split(arg.entityReference)
46
- : [undefined, arg.entity.id];
47
- const classFullName = "entityReference" in arg
48
- ? // eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-non-null-assertion
49
- core_common_1.ConcreteEntityTypes.toBisCoreRootClassFullName(type)
50
- : `[${arg.entity.schemaName}].[${arg.entity.className}]`;
51
- if (id === undefined || core_bentley_1.Id64.isInvalid(id))
36
+ async function exists(db, arg) {
37
+ let classFullName;
38
+ let id;
39
+ if ("entityReference" in arg) {
40
+ const [type, entityId] = core_backend_1.EntityReferences.split(arg.entityReference);
41
+ classFullName = bisCoreRootClasses[type].classFullName;
42
+ id = entityId;
43
+ }
44
+ else {
45
+ classFullName = `[${arg.entity.schemaName}].[${arg.entity.className}]`;
46
+ id = arg.entity.id;
47
+ }
48
+ if (core_bentley_1.Id64.isInvalid(id))
52
49
  return false;
53
- // eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
54
- return db.withPreparedStatement(`SELECT 1 FROM ${classFullName} WHERE ECInstanceId=?`, (stmt) => {
55
- stmt.bindId(1, id);
56
- const matchesResult = stmt.step();
57
- if (matchesResult === core_bentley_1.DbResult.BE_SQLITE_ROW)
58
- return true;
59
- if (matchesResult === core_bentley_1.DbResult.BE_SQLITE_DONE)
60
- return false;
61
- else
62
- throw new core_common_1.IModelError(matchesResult, "query failed");
50
+ const query = `SELECT 1 FROM ${classFullName} WHERE ECInstanceId=:id`;
51
+ const params = new core_common_1.QueryBinder().bindId("id", id);
52
+ const reader = db.createQueryReader(query, params, {
53
+ usePrimaryConn: true,
63
54
  });
55
+ return reader.step();
64
56
  }
65
57
  EntityUnifier.exists = exists;
58
+ /** Batched existence check: returns the subset of `entityReferences` that exist in `db`,
59
+ * using one query per concrete entity type instead of one query per reference.
60
+ */
61
+ async function existsAll(db, entityReferences) {
62
+ const idsByType = new Map();
63
+ for (const entityReference of entityReferences) {
64
+ const [type, id] = core_backend_1.EntityReferences.split(entityReference);
65
+ if (core_bentley_1.Id64.isInvalid(id))
66
+ continue;
67
+ let ids = idsByType.get(type);
68
+ if (ids === undefined) {
69
+ ids = new Set();
70
+ idsByType.set(type, ids);
71
+ }
72
+ ids.add(id);
73
+ }
74
+ const found = new Set();
75
+ for (const [type, ids] of idsByType) {
76
+ const classFullName = bisCoreRootClasses[type].classFullName;
77
+ // Join IdSet so SQLite looks up each id by primary key; InVirtualSet scans the whole table.
78
+ const query = `SELECT e.ECInstanceId FROM ${classFullName} e INNER JOIN IdSet(:ids) s ON s.id = e.ECInstanceId`;
79
+ const params = new core_common_1.QueryBinder().bindIdSet("ids", core_bentley_1.OrderedId64Iterable.sortArray([...ids]));
80
+ const reader = db.createQueryReader(query, params, {
81
+ usePrimaryConn: true,
82
+ });
83
+ while (await reader.step()) {
84
+ found.add(core_backend_1.EntityReferences.fromEntityType(reader.current[0], type));
85
+ }
86
+ }
87
+ return found;
88
+ }
89
+ EntityUnifier.existsAll = existsAll;
66
90
  })(EntityUnifier || (exports.EntityUnifier = EntityUnifier = {}));
67
91
  //# sourceMappingURL=EntityUnifier.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityUnifier.js","sourceRoot":"","sources":["../../src/EntityUnifier.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;AAChG;;;;GAIG;;;AAEH,iCAAiC;AACjC,oDAI4B;AAC5B,sDAS6B;AAC7B,sDAAqD;AAErD,gBAAgB;AAChB,IAAiB,aAAa,CAuD7B;AAvDD,WAAiB,aAAa;IAC5B,SAAgB,eAAe,CAAC,MAAsB;QACpD,IAAI,MAAM,YAAY,sBAAO;YAAE,OAAO,SAAS,CAAC;aAC3C,IAAI,MAAM,YAAY,4BAAa;YAAE,OAAO,gBAAgB,CAAC;aAC7D,IAAI,MAAM,YAAY,2BAAY;YAAE,OAAO,cAAc,CAAC;;YAC1D,OAAO,qBAAqB,CAAC;IACpC,CAAC;IALe,6BAAe,kBAK9B,CAAA;IAID,2GAA2G;IAC3G,SAAgB,UAAU,CAAC,EAAY,EAAE,MAAsB;QAC7D,IAAI,MAAM,YAAY,sBAAO;YAC3B,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAkB,CAAC;aACjE,IAAI,MAAM,YAAY,2BAAY;YACrC,OAAO,EAAE,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,CACzC,EAAE,CAAC,aAAa,CACA,CAAC;aAChB,IAAI,MAAM,YAAY,4BAAa;YACtC,OAAO,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAkB,CAAC;;YAEnE,MAAM,CACJ,KAAK,EACL,4BAA4B,MAAM,CAAC,WAAW,CAAC,IAAI,kDAAkD,CACtG,CAAC;IACN,CAAC;IAde,wBAAU,aAczB,CAAA;IAED,SAAgB,MAAM,CACpB,EAAY,EACZ,GAAsE;QAEtE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,GACd,iBAAiB,IAAI,GAAG;YACtB,CAAC,CAAC,+BAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC;YAC7C,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,aAAa,GACjB,iBAAiB,IAAI,GAAG;YACtB,CAAC,CAAC,wFAAwF;gBACxF,iCAAmB,CAAC,0BAA0B,CAAC,IAAK,CAAC;YACvD,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC;QAE7D,IAAI,EAAE,KAAK,SAAS,IAAI,mBAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QAEzD,gFAAgF;QAChF,OAAO,EAAE,CAAC,qBAAqB,CAC7B,iBAAiB,aAAa,uBAAuB,EACrD,CAAC,IAAI,EAAE,EAAE;YACP,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,aAAa,KAAK,uBAAQ,CAAC,aAAa;gBAAE,OAAO,IAAI,CAAC;YAC1D,IAAI,aAAa,KAAK,uBAAQ,CAAC,cAAc;gBAAE,OAAO,KAAK,CAAC;;gBACvD,MAAM,IAAI,yBAAW,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAC5D,CAAC,CACF,CAAC;IACJ,CAAC;IA3Be,oBAAM,SA2BrB,CAAA;AACH,CAAC,EAvDgB,aAAa,6BAAb,aAAa,QAuD7B","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Utils\n * utilities that unify operations, especially CRUD operations, on entities\n * for entity-generic operations in the transformer\n */\n\nimport * as assert from \"assert\";\nimport {\n ConcreteEntityTypes,\n EntityReference,\n IModelError,\n} from \"@itwin/core-common\";\nimport {\n ConcreteEntity,\n ConcreteEntityProps,\n // eslint-disable-next-line @typescript-eslint/no-redeclare\n Element,\n ElementAspect,\n EntityReferences,\n IModelDb,\n Relationship,\n} from \"@itwin/core-backend\";\nimport { DbResult, Id64 } from \"@itwin/core-bentley\";\n\n/** @internal */\nexport namespace EntityUnifier {\n export function getReadableType(entity: ConcreteEntity) {\n if (entity instanceof Element) return \"element\";\n else if (entity instanceof ElementAspect) return \"element aspect\";\n else if (entity instanceof Relationship) return \"relationship\";\n else return \"unknown entity type\";\n }\n\n type EntityUpdater = (entityProps: ConcreteEntityProps) => void;\n\n /** needs to return a widened type otherwise typescript complains when result is used with a narrow type */\n export function updaterFor(db: IModelDb, entity: ConcreteEntity) {\n if (entity instanceof Element)\n return db.elements.updateElement.bind(db.elements) as EntityUpdater;\n else if (entity instanceof Relationship)\n return db.relationships.updateInstance.bind(\n db.relationships\n ) as EntityUpdater;\n else if (entity instanceof ElementAspect)\n return db.elements.updateAspect.bind(db.elements) as EntityUpdater;\n else\n assert(\n false,\n `unreachable; entity was '${entity.constructor.name}' not an Element, Relationship, or ElementAspect`\n );\n }\n\n export function exists(\n db: IModelDb,\n arg: { entity: ConcreteEntity } | { entityReference: EntityReference }\n ) {\n const [type, id] =\n \"entityReference\" in arg\n ? EntityReferences.split(arg.entityReference)\n : [undefined, arg.entity.id];\n const classFullName =\n \"entityReference\" in arg\n ? // eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-non-null-assertion\n ConcreteEntityTypes.toBisCoreRootClassFullName(type!)\n : `[${arg.entity.schemaName}].[${arg.entity.className}]`;\n\n if (id === undefined || Id64.isInvalid(id)) return false;\n\n // eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated\n return db.withPreparedStatement(\n `SELECT 1 FROM ${classFullName} WHERE ECInstanceId=?`,\n (stmt) => {\n stmt.bindId(1, id);\n const matchesResult = stmt.step();\n if (matchesResult === DbResult.BE_SQLITE_ROW) return true;\n if (matchesResult === DbResult.BE_SQLITE_DONE) return false;\n else throw new IModelError(matchesResult, \"query failed\");\n }\n );\n }\n}\n"]}
1
+ {"version":3,"file":"EntityUnifier.js","sourceRoot":"","sources":["../../src/EntityUnifier.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Utils\n * utilities that unify operations, especially CRUD operations, on entities\n * for entity-generic operations in the transformer\n */\n\nimport {\n ConcreteEntityTypes,\n EntityReference,\n QueryBinder,\n} from \"@itwin/core-common\";\nimport {\n ConcreteEntity,\n // eslint-disable-next-line @typescript-eslint/no-redeclare\n Element,\n ElementAspect,\n Entity,\n EntityReferences,\n IModelDb,\n Model,\n Relationship,\n} from \"@itwin/core-backend\";\nimport { Id64, Id64String, OrderedId64Iterable } from \"@itwin/core-bentley\";\n\nconst bisCoreRootClasses: Record<ConcreteEntityTypes, typeof Entity> = {\n [ConcreteEntityTypes.Model]: Model,\n [ConcreteEntityTypes.Element]: Element,\n [ConcreteEntityTypes.ElementAspect]: ElementAspect,\n [ConcreteEntityTypes.Relationship]: Relationship,\n};\n\n/** @internal */\nexport namespace EntityUnifier {\n export function getReadableType(entity: ConcreteEntity) {\n if (entity instanceof Element) return \"element\";\n else if (entity instanceof ElementAspect) return \"element aspect\";\n else if (entity instanceof Relationship) return \"relationship\";\n else return \"unknown entity type\";\n }\n\n export async function exists(\n db: IModelDb,\n arg: { entity: ConcreteEntity } | { entityReference: EntityReference }\n ) {\n let classFullName: string;\n let id: Id64String;\n if (\"entityReference\" in arg) {\n const [type, entityId] = EntityReferences.split(arg.entityReference);\n classFullName = bisCoreRootClasses[type].classFullName;\n id = entityId;\n } else {\n classFullName = `[${arg.entity.schemaName}].[${arg.entity.className}]`;\n id = arg.entity.id;\n }\n\n if (Id64.isInvalid(id)) return false;\n\n const query = `SELECT 1 FROM ${classFullName} WHERE ECInstanceId=:id`;\n const params = new QueryBinder().bindId(\"id\", id);\n const reader = db.createQueryReader(query, params, {\n usePrimaryConn: true,\n });\n return reader.step();\n }\n\n /** Batched existence check: returns the subset of `entityReferences` that exist in `db`,\n * using one query per concrete entity type instead of one query per reference.\n */\n export async function existsAll(\n db: IModelDb,\n entityReferences: Iterable<EntityReference>\n ): Promise<Set<EntityReference>> {\n const idsByType = new Map<ConcreteEntityTypes, Set<Id64String>>();\n for (const entityReference of entityReferences) {\n const [type, id] = EntityReferences.split(entityReference);\n if (Id64.isInvalid(id)) continue;\n let ids = idsByType.get(type);\n if (ids === undefined) {\n ids = new Set();\n idsByType.set(type, ids);\n }\n ids.add(id);\n }\n\n const found = new Set<EntityReference>();\n for (const [type, ids] of idsByType) {\n const classFullName = bisCoreRootClasses[type].classFullName;\n // Join IdSet so SQLite looks up each id by primary key; InVirtualSet scans the whole table.\n const query = `SELECT e.ECInstanceId FROM ${classFullName} e INNER JOIN IdSet(:ids) s ON s.id = e.ECInstanceId`;\n const params = new QueryBinder().bindIdSet(\n \"ids\",\n OrderedId64Iterable.sortArray([...ids])\n );\n const reader = db.createQueryReader(query, params, {\n usePrimaryConn: true,\n });\n while (await reader.step()) {\n found.add(EntityReferences.fromEntityType(reader.current[0], type));\n }\n }\n return found;\n }\n}\n"]}
@@ -1,18 +1,24 @@
1
1
  import { Id64String } from "@itwin/core-bentley";
2
2
  import { ElementAspectProps, ElementProps, EntityReference } from "@itwin/core-common";
3
3
  import { Element, ElementAspect, IModelElementCloneContext, IModelJsNative } from "@itwin/core-backend";
4
+ import { EntityExistenceCache } from "./EntityExistenceCache";
5
+ import type { IModelTransformContext } from "./IModelTransformContext";
4
6
  /** The context for transforming a *source* Element to a *target* Element and remapping internal identifiers to the target iModel.
5
- * @beta
7
+ * @internal
6
8
  */
7
- export declare class IModelCloneContext extends IModelElementCloneContext {
9
+ export declare class IModelCloneContext extends IModelElementCloneContext implements IModelTransformContext {
8
10
  private _refTypesCache;
9
11
  private _aspectRemapTable;
12
+ /** A positive-only cache of entity existence checks, scoped to the current transformation run.
13
+ * @internal
14
+ */
15
+ readonly existenceCache: EntityExistenceCache;
10
16
  /** perform necessary initialization to use a clone context, namely caching the reference types in the source's schemas */
11
17
  initialize(): Promise<void>;
12
18
  /** Clone the specified source Element into ElementProps for the target iModel.
13
19
  * @internal
14
20
  */
15
- cloneElement(sourceElement: Element, cloneOptions?: IModelJsNative.CloneElementOptions): ElementProps;
21
+ cloneElement(sourceElement: Element, cloneOptions?: IModelJsNative.CloneElementOptions): Promise<ElementProps>;
16
22
  /** Add a rule that remaps the specified source ElementAspect to the specified target ElementAspect. */
17
23
  remapElementAspect(aspectSourceId: Id64String, aspectTargetId: Id64String): void;
18
24
  /** Remove a rule that remaps the specified source ElementAspect */
@@ -1 +1 @@
1
- {"version":3,"file":"IModelCloneContext.d.ts","sourceRoot":"","sources":["../../src/IModelCloneContext.ts"],"names":[],"mappings":"AAQA,OAAO,EAAkB,UAAU,EAAU,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAKL,kBAAkB,EAClB,YAAY,EACZ,eAAe,EAMhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,OAAO,EACP,aAAa,EAEb,yBAAyB,EACzB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAQ7B;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,yBAAyB;IAC/D,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,iBAAiB,CAAqC;IAE9D,0HAA0H;IACpG,UAAU;IAIhC;;OAEG;IACa,YAAY,CAC1B,aAAa,EAAE,OAAO,EACtB,YAAY,CAAC,EAAE,cAAc,CAAC,mBAAmB,GAChD,YAAY;IA6Cf,uGAAuG;IAChG,kBAAkB,CACvB,cAAc,EAAE,UAAU,EAC1B,cAAc,EAAE,UAAU,GACzB,IAAI;IAIP,mEAAmE;IAC5D,mBAAmB,CAAC,cAAc,EAAE,UAAU,GAAG,IAAI;IAI5D;;OAEG;IACI,kBAAkB,CAAC,cAAc,EAAE,UAAU,GAAG,UAAU;IAIjE;;OAEG;IACU,kBAAkB,CAC7B,cAAc,EAAE,eAAe,GAC9B,OAAO,CAAC,eAAe,CAAC;IA6H3B;;OAEG;IACU,kBAAkB,CAC7B,mBAAmB,EAAE,aAAa,GACjC,OAAO,CAAC,kBAAkB,CAAC;CA4C/B"}
1
+ {"version":3,"file":"IModelCloneContext.d.ts","sourceRoot":"","sources":["../../src/IModelCloneContext.ts"],"names":[],"mappings":"AAQA,OAAO,EAAQ,UAAU,EAAU,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAKL,kBAAkB,EAClB,YAAY,EACZ,eAAe,EAKhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,OAAO,EACP,aAAa,EAEb,yBAAyB,EACzB,cAAc,EACf,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAIvE;;GAEG;AACH,qBAAa,kBACX,SAAQ,yBACR,YAAW,sBAAsB;IAEjC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,iBAAiB,CAA4B;IAErD;;OAEG;IACH,SAAgB,cAAc,uBAA8B;IAE5D,0HAA0H;IACpG,UAAU,kBAE/B;IAED;;OAEG;IACmB,YAAY,CAChC,aAAa,EAAE,OAAO,EACtB,YAAY,CAAC,EAAE,cAAc,CAAC,mBAAmB,GAChD,OAAO,CAAC,YAAY,CAAC,CAgFvB;IAED,uGAAuG;IAChG,kBAAkB,CACvB,cAAc,EAAE,UAAU,EAC1B,cAAc,EAAE,UAAU,GACzB,IAAI,CAEN;IAED,mEAAmE;IAC5D,mBAAmB,CAAC,cAAc,EAAE,UAAU,GAAG,IAAI,CAE3D;IAED;;OAEG;IACI,kBAAkB,CAAC,cAAc,EAAE,UAAU,GAAG,UAAU,CAEhE;IAED;;OAEG;IACU,kBAAkB,CAC7B,cAAc,EAAE,eAAe,GAC9B,OAAO,CAAC,eAAe,CAAC,CA+H1B;IAED;;OAEG;IACU,kBAAkB,CAC7B,mBAAmB,EAAE,aAAa,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAqD7B;CACF"}
@@ -8,20 +8,26 @@ exports.IModelCloneContext = void 0;
8
8
  /** @packageDocumentation
9
9
  * @module iModels
10
10
  */
11
- const assert = require("assert");
11
+ const node_assert_1 = require("node:assert");
12
12
  const core_bentley_1 = require("@itwin/core-bentley");
13
13
  const core_common_1 = require("@itwin/core-common");
14
14
  const core_backend_1 = require("@itwin/core-backend");
15
+ const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
15
16
  const ECReferenceTypesCache_1 = require("./ECReferenceTypesCache");
16
- const EntityUnifier_1 = require("./EntityUnifier");
17
+ const EntityExistenceCache_1 = require("./EntityExistenceCache");
17
18
  const TransformerLoggerCategory_1 = require("./TransformerLoggerCategory");
19
+ const BigMap_1 = require("./BigMap");
18
20
  const loggerCategory = TransformerLoggerCategory_1.TransformerLoggerCategory.IModelCloneContext;
19
21
  /** The context for transforming a *source* Element to a *target* Element and remapping internal identifiers to the target iModel.
20
- * @beta
22
+ * @internal
21
23
  */
22
24
  class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
23
25
  _refTypesCache = new ECReferenceTypesCache_1.ECReferenceTypesCache();
24
- _aspectRemapTable = new Map();
26
+ _aspectRemapTable = new BigMap_1.BigMap();
27
+ /** A positive-only cache of entity existence checks, scoped to the current transformation run.
28
+ * @internal
29
+ */
30
+ existenceCache = new EntityExistenceCache_1.EntityExistenceCache();
25
31
  /** perform necessary initialization to use a clone context, namely caching the reference types in the source's schemas */
26
32
  async initialize() {
27
33
  await this._refTypesCache.initAllSchemasInIModel(this.sourceDb);
@@ -29,16 +35,39 @@ class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
29
35
  /** Clone the specified source Element into ElementProps for the target iModel.
30
36
  * @internal
31
37
  */
32
- cloneElement(sourceElement, cloneOptions) {
38
+ async cloneElement(sourceElement, cloneOptions) {
33
39
  const targetElementProps = this["_nativeContext"].cloneElement(sourceElement.id, cloneOptions);
40
+ // Native same-iModel cloning clears codes for inserts, but identity mappings are updates.
41
+ if (!this.isBetweenIModels &&
42
+ this.findTargetElementId(sourceElement.id) === sourceElement.id) {
43
+ targetElementProps.code.value = sourceElement.code.value;
44
+ if (!core_bentley_1.Id64.isValidId64(targetElementProps.code.spec)) {
45
+ const mappedCodeSpecId = this.findTargetCodeSpecId(sourceElement.code.spec);
46
+ targetElementProps.code.spec = core_bentley_1.Id64.isValidId64(mappedCodeSpecId)
47
+ ? mappedCodeSpecId
48
+ : sourceElement.code.spec;
49
+ }
50
+ if (!core_bentley_1.Id64.isValidId64(targetElementProps.code.scope)) {
51
+ const mappedCodeScopeId = this.findTargetElementId(sourceElement.code.scope);
52
+ targetElementProps.code.scope = core_bentley_1.Id64.isValidId64(mappedCodeScopeId)
53
+ ? mappedCodeScopeId
54
+ : sourceElement.code.scope;
55
+ }
56
+ }
34
57
  // Ensure that all NavigationProperties in targetElementProps have a defined value so "clearing" changes will be part of the JSON used for update
35
- sourceElement.forEach((name, property) => {
58
+ const sourceElementClass = sourceElement.iModel.schemaContext.getSchemaItemSync(sourceElement.schemaItemKey, ecschema_metadata_1.EntityClass);
59
+ (0, node_assert_1.strict)(sourceElementClass !== undefined, `Cannot get metadata for ${sourceElement.classFullName}.`);
60
+ for (const property of sourceElementClass.getPropertiesSync()) {
61
+ // Exclude custom properties because C++ has already handled them.
62
+ if (property.customAttributes?.has("BisCore.CustomHandledProperty"))
63
+ continue;
64
+ const name = property.name;
36
65
  if (property.isNavigation() &&
37
66
  undefined === sourceElement[core_common_1.ECJsNames.toJsName(name)]) {
38
67
  targetElementProps[core_common_1.ECJsNames.toJsName(name)] =
39
68
  core_common_1.RelatedElement.none;
40
69
  }
41
- }, false); // exclude custom because C++ has already handled them
70
+ }
42
71
  if (this.isBetweenIModels) {
43
72
  // The native C++ cloneElement strips off federationGuid, want to put it back if transformation is between iModels
44
73
  targetElementProps.federationGuid = sourceElement.federationGuid;
@@ -55,7 +84,7 @@ class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
55
84
  targetElementProps.code = core_common_1.Code.createEmpty();
56
85
  }
57
86
  const jsClass = this.sourceDb.getJsClass(sourceElement.classFullName);
58
- jsClass["onCloned"](this, sourceElement.toJSON(), targetElementProps);
87
+ await jsClass["onCloned"](this, sourceElement.toJSON(), targetElementProps);
59
88
  return targetElementProps;
60
89
  }
61
90
  /** Add a rule that remaps the specified source ElementAspect to the specified target ElementAspect. */
@@ -98,7 +127,7 @@ class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
98
127
  }
99
128
  // Check if the model exists, `findTargetElementId` may have worked because the element exists when the model doesn't.
100
129
  // That can occur in the transformer since a submodeled element is imported before its submodel.
101
- if (EntityUnifier_1.EntityUnifier.exists(this.targetDb, { entityReference: targetId }))
130
+ if (await this.existenceCache.exists(this.targetDb, targetId))
102
131
  return targetId;
103
132
  break;
104
133
  }
@@ -132,7 +161,9 @@ class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
132
161
  WHERE ECInstanceId=?
133
162
  `;
134
163
  const params = new core_common_1.QueryBinder().bindId(1, rawId);
135
- const reader = this.sourceDb.createQueryReader(sql, params);
164
+ const reader = this.sourceDb.createQueryReader(sql, params, {
165
+ usePrimaryConn: true,
166
+ });
136
167
  const relInSource = await (async () => {
137
168
  if (await reader.step()) {
138
169
  const sourceId = reader.current[0];
@@ -162,22 +193,23 @@ class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
162
193
  if (!core_backend_1.EntityReferences.isValid(relInTarget.sourceId) ||
163
194
  !core_backend_1.EntityReferences.isValid(relInTarget.targetId))
164
195
  break;
165
- // eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
166
- const relInTargetId = this.targetDb.withPreparedStatement(`
196
+ const relInTargetSql = `
167
197
  SELECT ECInstanceId
168
198
  FROM BisCore:ElementRefersToElements
169
199
  WHERE SourceECInstanceId=?
170
200
  AND TargetECInstanceId=?
171
- `, (stmt) => {
172
- stmt.bindId(1, core_backend_1.EntityReferences.toId64(relInTarget.sourceId));
173
- stmt.bindId(2, core_backend_1.EntityReferences.toId64(relInTarget.targetId));
174
- const status = stmt.step();
175
- if (status === core_bentley_1.DbResult.BE_SQLITE_ROW)
176
- return stmt.getValue(0).getId();
177
- if (status !== core_bentley_1.DbResult.BE_SQLITE_DONE)
178
- throw new core_common_1.IModelError(status, "unexpected query failure");
179
- return core_bentley_1.Id64.invalid;
180
- });
201
+ `;
202
+ const relInTargetParams = new core_common_1.QueryBinder();
203
+ relInTargetParams.bindId(1, core_backend_1.EntityReferences.toId64(relInTarget.sourceId));
204
+ relInTargetParams.bindId(2, core_backend_1.EntityReferences.toId64(relInTarget.targetId));
205
+ const relInTargetResult = await this.targetDb
206
+ .createQueryReader(relInTargetSql, relInTargetParams, {
207
+ usePrimaryConn: true,
208
+ })
209
+ .next();
210
+ const relInTargetId = relInTargetResult.done
211
+ ? core_bentley_1.Id64.invalid
212
+ : relInTargetResult.value.id;
181
213
  return `r${relInTargetId}`;
182
214
  }
183
215
  }
@@ -191,27 +223,30 @@ class IModelCloneContext extends core_backend_1.IModelElementCloneContext {
191
223
  const targetElementAspectProps = sourceElementAspect.toJSON();
192
224
  targetElementAspectProps.id = undefined;
193
225
  const targetEntityIds = [];
194
- sourceElementAspect.forEach((name, property) => {
226
+ const sourceElementAspectClass = sourceElementAspect.iModel.schemaContext.getSchemaItemSync(sourceElementAspect.schemaItemKey, ecschema_metadata_1.EntityClass);
227
+ (0, node_assert_1.strict)(sourceElementAspectClass !== undefined, `Cannot get metadata for ${sourceElementAspect.classFullName}.`);
228
+ for (const property of sourceElementAspectClass.getPropertiesSync()) {
229
+ const ecName = property.name;
230
+ const name = core_common_1.ECJsNames.toJsName(ecName);
195
231
  if (property.isNavigation()) {
196
- const sourceNavProp = sourceElementAspect.asAny[core_common_1.ECJsNames.toJsName(name)];
232
+ const sourceNavProp = sourceElementAspect.asAny[name];
197
233
  if (sourceNavProp?.id) {
198
- const navPropRefType = this._refTypesCache.getNavPropRefType(sourceElementAspect.schemaName, sourceElementAspect.className, core_common_1.ECJsNames.toJsName(name));
199
- assert(navPropRefType !== undefined, `nav prop ref type for '${name}' was not in the cache, this is a bug.`);
234
+ const navPropRefType = this._refTypesCache.getNavPropRefType(sourceElementAspect.schemaName, sourceElementAspect.className, name);
235
+ (0, node_assert_1.strict)(navPropRefType !== undefined, `nav prop ref type for '${name}' was not in the cache, this is a bug.`);
200
236
  targetEntityIds.push(this.findTargetEntityId(core_backend_1.EntityReferences.fromEntityType(sourceNavProp.id, navPropRefType)).then((targetEntityReference) => {
201
237
  const targetEntityId = core_backend_1.EntityReferences.toId64(targetEntityReference);
202
238
  // spread the property in case toJSON did not deep-clone
203
- targetElementAspectProps[core_common_1.ECJsNames.toJsName(name)] = {
204
- ...targetElementAspectProps[core_common_1.ECJsNames.toJsName(name)],
239
+ targetElementAspectProps[name] = {
240
+ ...targetElementAspectProps[name],
205
241
  id: targetEntityId,
206
242
  };
207
243
  }));
208
244
  }
209
245
  }
210
246
  else if (property.isPrimitive() && "Id" === property.extendedTypeName) {
211
- targetElementAspectProps[core_common_1.ECJsNames.toJsName(name)] =
212
- this.findTargetElementId(sourceElementAspect.asAny[core_common_1.ECJsNames.toJsName(name)]);
247
+ targetElementAspectProps[name] = this.findTargetElementId(sourceElementAspect.asAny[name]);
213
248
  }
214
- });
249
+ }
215
250
  await Promise.all(targetEntityIds);
216
251
  return targetElementAspectProps;
217
252
  }