@itwin/core-backend 5.12.0-dev.9 → 5.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/lib/cjs/Category.d.ts +4 -4
  3. package/lib/cjs/Category.js.map +1 -1
  4. package/lib/cjs/ClassRegistry.d.ts.map +1 -1
  5. package/lib/cjs/ClassRegistry.js +1 -2
  6. package/lib/cjs/ClassRegistry.js.map +1 -1
  7. package/lib/cjs/CodeSpecs.d.ts +3 -3
  8. package/lib/cjs/CodeSpecs.js.map +1 -1
  9. package/lib/cjs/DisplayStyle.d.ts +2 -2
  10. package/lib/cjs/DisplayStyle.js.map +1 -1
  11. package/lib/cjs/ECDb.d.ts.map +1 -1
  12. package/lib/cjs/ECDb.js +8 -3
  13. package/lib/cjs/ECDb.js.map +1 -1
  14. package/lib/cjs/ECSqlRowExecutor.d.ts +23 -10
  15. package/lib/cjs/ECSqlRowExecutor.d.ts.map +1 -1
  16. package/lib/cjs/ECSqlRowExecutor.js +77 -15
  17. package/lib/cjs/ECSqlRowExecutor.js.map +1 -1
  18. package/lib/cjs/Element.d.ts +8 -8
  19. package/lib/cjs/Element.d.ts.map +1 -1
  20. package/lib/cjs/Element.js +2 -2
  21. package/lib/cjs/Element.js.map +1 -1
  22. package/lib/cjs/IModelDb.d.ts +34 -22
  23. package/lib/cjs/IModelDb.d.ts.map +1 -1
  24. package/lib/cjs/IModelDb.js +97 -68
  25. package/lib/cjs/IModelDb.js.map +1 -1
  26. package/lib/cjs/IpcHost.d.ts +26 -0
  27. package/lib/cjs/IpcHost.d.ts.map +1 -1
  28. package/lib/cjs/IpcHost.js +68 -61
  29. package/lib/cjs/IpcHost.js.map +1 -1
  30. package/lib/cjs/Model.d.ts +5 -5
  31. package/lib/cjs/Model.d.ts.map +1 -1
  32. package/lib/cjs/Model.js.map +1 -1
  33. package/lib/cjs/Relationship.d.ts.map +1 -1
  34. package/lib/cjs/Relationship.js +13 -7
  35. package/lib/cjs/Relationship.js.map +1 -1
  36. package/lib/cjs/SQLiteDb.d.ts +43 -0
  37. package/lib/cjs/SQLiteDb.d.ts.map +1 -1
  38. package/lib/cjs/SQLiteDb.js +51 -0
  39. package/lib/cjs/SQLiteDb.js.map +1 -1
  40. package/lib/cjs/Texture.d.ts +1 -1
  41. package/lib/cjs/Texture.js.map +1 -1
  42. package/lib/cjs/ViewDefinition.d.ts +6 -6
  43. package/lib/cjs/ViewDefinition.d.ts.map +1 -1
  44. package/lib/cjs/ViewDefinition.js.map +1 -1
  45. package/lib/cjs/ViewStore.js +1 -1
  46. package/lib/cjs/ViewStore.js.map +1 -1
  47. package/lib/cjs/internal/ECSqlInstanceReshaper.d.ts +23 -0
  48. package/lib/cjs/internal/ECSqlInstanceReshaper.d.ts.map +1 -0
  49. package/lib/cjs/internal/ECSqlInstanceReshaper.js +125 -0
  50. package/lib/cjs/internal/ECSqlInstanceReshaper.js.map +1 -0
  51. package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
  52. package/lib/cjs/internal/annotations/fields.js +9 -4
  53. package/lib/cjs/internal/annotations/fields.js.map +1 -1
  54. package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  55. package/lib/cjs/internal/workspace/WorkspaceImpl.js +7 -2
  56. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  57. package/lib/esm/Category.d.ts +4 -4
  58. package/lib/esm/Category.js.map +1 -1
  59. package/lib/esm/ClassRegistry.d.ts.map +1 -1
  60. package/lib/esm/ClassRegistry.js +1 -2
  61. package/lib/esm/ClassRegistry.js.map +1 -1
  62. package/lib/esm/CodeSpecs.d.ts +3 -3
  63. package/lib/esm/CodeSpecs.js.map +1 -1
  64. package/lib/esm/DisplayStyle.d.ts +2 -2
  65. package/lib/esm/DisplayStyle.js.map +1 -1
  66. package/lib/esm/ECDb.d.ts.map +1 -1
  67. package/lib/esm/ECDb.js +9 -4
  68. package/lib/esm/ECDb.js.map +1 -1
  69. package/lib/esm/ECSqlRowExecutor.d.ts +23 -10
  70. package/lib/esm/ECSqlRowExecutor.d.ts.map +1 -1
  71. package/lib/esm/ECSqlRowExecutor.js +77 -16
  72. package/lib/esm/ECSqlRowExecutor.js.map +1 -1
  73. package/lib/esm/Element.d.ts +8 -8
  74. package/lib/esm/Element.d.ts.map +1 -1
  75. package/lib/esm/Element.js +2 -2
  76. package/lib/esm/Element.js.map +1 -1
  77. package/lib/esm/IModelDb.d.ts +34 -22
  78. package/lib/esm/IModelDb.d.ts.map +1 -1
  79. package/lib/esm/IModelDb.js +99 -70
  80. package/lib/esm/IModelDb.js.map +1 -1
  81. package/lib/esm/IpcHost.d.ts +26 -0
  82. package/lib/esm/IpcHost.d.ts.map +1 -1
  83. package/lib/esm/IpcHost.js +70 -63
  84. package/lib/esm/IpcHost.js.map +1 -1
  85. package/lib/esm/Model.d.ts +5 -5
  86. package/lib/esm/Model.d.ts.map +1 -1
  87. package/lib/esm/Model.js.map +1 -1
  88. package/lib/esm/Relationship.d.ts.map +1 -1
  89. package/lib/esm/Relationship.js +13 -7
  90. package/lib/esm/Relationship.js.map +1 -1
  91. package/lib/esm/SQLiteDb.d.ts +43 -0
  92. package/lib/esm/SQLiteDb.d.ts.map +1 -1
  93. package/lib/esm/SQLiteDb.js +51 -0
  94. package/lib/esm/SQLiteDb.js.map +1 -1
  95. package/lib/esm/Texture.d.ts +1 -1
  96. package/lib/esm/Texture.js.map +1 -1
  97. package/lib/esm/ViewDefinition.d.ts +6 -6
  98. package/lib/esm/ViewDefinition.d.ts.map +1 -1
  99. package/lib/esm/ViewDefinition.js.map +1 -1
  100. package/lib/esm/ViewStore.js +1 -1
  101. package/lib/esm/ViewStore.js.map +1 -1
  102. package/lib/esm/internal/ECSqlInstanceReshaper.d.ts +23 -0
  103. package/lib/esm/internal/ECSqlInstanceReshaper.d.ts.map +1 -0
  104. package/lib/esm/internal/ECSqlInstanceReshaper.js +120 -0
  105. package/lib/esm/internal/ECSqlInstanceReshaper.js.map +1 -0
  106. package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
  107. package/lib/esm/internal/annotations/fields.js +9 -4
  108. package/lib/esm/internal/annotations/fields.js.map +1 -1
  109. package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  110. package/lib/esm/internal/workspace/WorkspaceImpl.js +7 -2
  111. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  112. package/lib/esm/test/IpcHost.test.js +232 -1
  113. package/lib/esm/test/IpcHost.test.js.map +1 -1
  114. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js +139 -1
  115. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js.map +1 -1
  116. package/lib/esm/test/imodel/IModel.test.js +20 -0
  117. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  118. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.d.ts +2 -0
  119. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.d.ts.map +1 -0
  120. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.js +289 -0
  121. package/lib/esm/test/internal/ECSqlInstanceReshaper.test.js.map +1 -0
  122. package/lib/esm/test/schema/ClassRegistry.test.js +2 -2
  123. package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
  124. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.d.ts +2 -0
  125. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.d.ts.map +1 -0
  126. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.js +546 -0
  127. package/lib/esm/test/schema/SchemaViewFragmentLoading.test.js.map +1 -0
  128. package/lib/esm/test/schema/SchemaViewLifecycle.test.js +2 -2
  129. package/lib/esm/test/schema/SchemaViewLifecycle.test.js.map +1 -1
  130. package/lib/esm/test/standalone/MergeConflict.test.js +1 -1
  131. package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
  132. package/lib/esm/test/standalone/SQLiteDb.test.d.ts +1 -1
  133. package/lib/esm/test/standalone/SQLiteDb.test.d.ts.map +1 -1
  134. package/lib/esm/test/standalone/SQLiteDb.test.js +93 -1
  135. package/lib/esm/test/standalone/SQLiteDb.test.js.map +1 -1
  136. package/lib/esm/test/standalone/ViewStoreDb.test.js +30 -0
  137. package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
  138. package/lib/esm/test/standalone/Workspace.test.js +52 -0
  139. package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
  140. package/package.json +14 -15
@@ -16,6 +16,7 @@ import { BriefcaseManager } from "./BriefcaseManager";
16
16
  import { ChannelControl } from "./ChannelControl";
17
17
  import { createChannelControl } from "./internal/ChannelAdmin";
18
18
  import { CheckpointManager, V2CheckpointManager } from "./CheckpointManager";
19
+ import { getRuntimeClass, reshapeInstanceRow } from "./internal/ECSqlInstanceReshaper";
19
20
  import { ClassRegistry, EntityJsClassMap, MetaDataRegistry } from "./ClassRegistry";
20
21
  import { CloudSqlite } from "./CloudSqlite";
21
22
  import { CodeService } from "./CodeService";
@@ -46,11 +47,11 @@ import { IModelNative } from "./internal/NativePlatform";
46
47
  import { createNoOpLockControl } from "./internal/NoLocks";
47
48
  import { createIModelDbFonts } from "./internal/IModelDbFontsImpl";
48
49
  import { _activeTxn, _cache, _close, _hubAccess, _implicitTxn, _instanceKeyCache, _nativeDb, _releaseAllLocks, _resetIModelDb } from "./internal/Symbols";
49
- import { ECVersion, SchemaContext, SchemaJsonLocater, SchemaView } from "@itwin/ecschema-metadata";
50
+ import { ECVersion, SchemaContext, SchemaJsonLocater, SchemaManifest, SchemaViewManager } from "@itwin/ecschema-metadata";
50
51
  import { SchemaMap } from "./Schema";
51
52
  import { ElementLRUCache, InstanceKeyLRUCache } from "./internal/ElementLRUCache";
52
53
  import { IModelIncrementalSchemaLocater } from "./IModelIncrementalSchemaLocater";
53
- import { ECSqlRowExecutor } from "./ECSqlRowExecutor";
54
+ import { ECSqlRowExecutor, releaseECSqlStatement } from "./ECSqlRowExecutor";
54
55
  import { integrityCheckTypeMap, performQuickIntegrityCheck, performSpecificIntegrityCheck } from "./internal/IntegrityCheck";
55
56
  import { ECSqlSyncReader } from "./ECSqlSyncReader";
56
57
  // spell:ignore fontid fontmap
@@ -162,7 +163,9 @@ export class IModelDb extends IModel {
162
163
  _jsClassMap;
163
164
  _schemaMap;
164
165
  _schemaContext;
165
- _schemasPromise;
166
+ // Created lazily on the first getSchemaView call. Owns the SchemaView's lifetime and does all its
167
+ // data access through the SchemaViewDataProvider implemented below.
168
+ _schemaViewManager;
166
169
  /** @deprecated in 5.0.0 - might be removed in next major version. Use [[fonts]]. */
167
170
  _fontMap; // eslint-disable-line @typescript-eslint/no-deprecated
168
171
  _fonts = createIModelDbFonts(this);
@@ -610,16 +613,22 @@ export class IModelDb extends IModel {
610
613
  * @param config Allow to specify certain flags which control how query is executed.
611
614
  * @returns the value returned by `callback`.
612
615
  * @throws IModelError if db is not open.
613
- * Should be used when we want true step by step behaviour from the reader without any intermediate caching involved.
616
+ * Use this method for true step-by-step row consumption without intermediate result or page caching.
617
+ * The prepared ECSQL statement may be reused from the statement cache between completed calls.
614
618
  * @beta
615
619
  * */
616
620
  withQueryReader(ecsql, callback, params, config) {
617
621
  if (!this[_nativeDb].isOpen())
618
622
  throw new IModelError(DbResult.BE_SQLITE_ERROR_NOTOPEN, "db not open");
619
- const executor = new ECSqlRowExecutor(this);
620
- const reader = new ECSqlSyncReader(executor, ecsql, params, config);
621
- const release = () => executor[Symbol.dispose]();
623
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
624
+ const stmt = this._statementCache.findAndRemove(ecsql) ?? new ECSqlStatement();
625
+ const executor = new ECSqlRowExecutor(this, stmt, loggerCategory);
626
+ const release = () => {
627
+ executor[Symbol.dispose]();
628
+ releaseECSqlStatement(stmt, this._statementCache, loggerCategory, executor.canCacheStatement);
629
+ };
622
630
  try {
631
+ const reader = new ECSqlSyncReader(executor, ecsql, params, config);
623
632
  const val = callback(reader);
624
633
  if (val instanceof Promise) {
625
634
  val.then(release, release);
@@ -719,8 +728,7 @@ export class IModelDb extends IModel {
719
728
  const where = [...parentCategories].join(",");
720
729
  const query = `SELECT ECInstanceId as id, Parent.Id as parentId, Properties as appearance FROM BisCore.SubCategory WHERE Parent.Id IN (${where})`;
721
730
  try {
722
- // eslint-disable-next-line @typescript-eslint/no-deprecated
723
- for await (const row of this.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) {
731
+ for await (const row of this.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames })) {
724
732
  result.push(row.toRow());
725
733
  }
726
734
  }
@@ -740,8 +748,7 @@ export class IModelDb extends IModel {
740
748
  const where = [...categoryIds].join(",");
741
749
  const query = `SELECT ECInstanceId as id, Parent.Id as parentId, Properties as appearance FROM BisCore.SubCategory WHERE Parent.Id IN (${where})`;
742
750
  try {
743
- // eslint-disable-next-line @typescript-eslint/no-deprecated
744
- for await (const row of this.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) {
751
+ for await (const row of this.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames })) {
745
752
  result.push(row.toRow());
746
753
  }
747
754
  }
@@ -784,7 +791,7 @@ export class IModelDb extends IModel {
784
791
  }
785
792
  }
786
793
  }
787
- }, QueryBinder.from(params.bindings));
794
+ }, QueryBinder.fromSkippingNullish(params.bindings));
788
795
  return ids;
789
796
  }
790
797
  clearCaches(params) {
@@ -795,11 +802,7 @@ export class IModelDb extends IModel {
795
802
  this._jsClassMap = undefined;
796
803
  this._schemaMap = undefined;
797
804
  this._schemaContext = undefined;
798
- if (this._schemasPromise) {
799
- const old = this._schemasPromise;
800
- this._schemasPromise = undefined;
801
- old.then((view) => view.markOutdated()).catch(() => { });
802
- }
805
+ this._schemaViewManager?.reset();
803
806
  this[_nativeDb].clearECDbCache();
804
807
  }
805
808
  this.elements[_cache].clear();
@@ -1295,53 +1298,74 @@ export class IModelDb extends IModel {
1295
1298
  return this._schemaContext;
1296
1299
  }
1297
1300
  /** Get the schema view for this iModel. The view is built lazily on
1298
- * first call by fetching compact binary schema data via `PRAGMA schema_view` through
1299
- * the ConcurrentQuery thread pool. Subsequent calls return the cached view. Multiple
1300
- * concurrent callers share a single in-flight build.
1301
+ * first call by fetching compact binary schema data through
1302
+ * the ConcurrentQuery thread pool.
1301
1303
  *
1302
1304
  * The returned `SchemaView` is a lightweight, read-only, synchronous API for
1303
1305
  * navigating schema metadata - classes, properties, relationships, enumerations, etc.
1304
1306
  * It is the recommended default for runtime read-only metadata access and is significantly
1305
1307
  * faster and lower-memory than [[schemaContext]]. Use [[schemaContext]] for schema authoring,
1306
1308
  * custom-attribute deserialization, or anywhere you need the full ecschema-metadata object graph.
1309
+ *
1310
+ * Every call shares one accumulating view instance and concurrent calls are serialized, so a
1311
+ * caller never observes a partially loaded view. The instance is discarded by [[clearCaches]],
1312
+ * for example after a schema import; the next call builds a new one. See
1313
+ * [GetSchemaViewArgs]($ecschema-metadata) for the arguments.
1307
1314
  * @beta
1308
1315
  */
1309
- async getSchemaView() {
1310
- if (this._schemasPromise) {
1311
- const ctx = await this._schemasPromise;
1312
- if (!ctx.isOutdated)
1313
- return ctx;
1314
- }
1315
- // Capture the in-flight promise locally so the rejection handler only clears
1316
- // `_schemasPromise` if it still points at this build. A concurrent invalidation +
1317
- // re-fetch could otherwise replace the field before our hydrate fails, and a naive
1318
- // `_schemasPromise = undefined` would clobber that newer reference.
1319
- const inflight = this._hydrateSchemas();
1320
- this._schemasPromise = inflight;
1321
- inflight.catch(() => {
1322
- if (this._schemasPromise === inflight)
1323
- this._schemasPromise = undefined;
1324
- });
1325
- return inflight;
1326
- }
1327
- async _hydrateSchemas() {
1328
- // PRAGMA returns exactly one row with format, formatVersion, data (binary), schemaToken.
1329
- // Important: only call reader.next() once - do NOT use `for await` on PRAGMA results.
1330
- // ConcurrentQuery wraps regular ECSQL in LIMIT/OFFSET for pagination but skips this for
1331
- // PRAGMAs. If the serialized result exceeds the memory threshold, the response is marked
1332
- // "Partial", and a `for await` loop would re-issue the same PRAGMA forever since PRAGMAs
1333
- // don't support OFFSET-based pagination.
1334
- // This implementation uses the non-pinned version of the pragma other than frontend - because backend
1335
- // is always strictly coupled with the native code.
1336
- const reader = this.createQueryReader("PRAGMA schema_view");
1316
+ async getSchemaView(args) {
1317
+ this._schemaViewManager ??= new SchemaViewManager(this._createSchemaViewDataProvider());
1318
+ return this._schemaViewManager.getSchemaView(args);
1319
+ }
1320
+ /** The [SchemaViewDataProvider]($ecschema-metadata) backing this iModel's [[getSchemaView]]: the
1321
+ * transport-specific half of schema-view loading. The backend always uses the latest blob version
1322
+ * since it is strictly coupled with native code.
1323
+ */
1324
+ _createSchemaViewDataProvider() {
1325
+ return {
1326
+ fetchFullBlob: async () => this._fetchSchemaBlob("PRAGMA schema_view"),
1327
+ // Names are ECNames, so a comma can never occur in one. Native re-validates each token as an
1328
+ // ECName and fails the pragma on an unknown name.
1329
+ fetchFragmentBlob: async (schemaNames) => this._fetchSchemaBlob(`PRAGMA schema_view_fragment('${schemaNames.join(",")}')`),
1330
+ fetchManifest: async () => {
1331
+ const schemaRows = [];
1332
+ const schemaSql = "SELECT ECInstanceId, Name, VersionMajor, VersionWrite, VersionMinor FROM meta.ECSchemaDef";
1333
+ for await (const row of this.createQueryReader(schemaSql)) {
1334
+ // ECInstanceId arrives as a hex Id64String. `ec_` metadata rowids carry no briefcase
1335
+ // prefix, so the local id is the full value.
1336
+ schemaRows.push({ ecInstanceId: Id64.getLocalId(row[0]), name: row[1], versionMajor: row[2], versionWrite: row[3], versionMinor: row[4] });
1337
+ }
1338
+ const referenceRows = [];
1339
+ const referenceSql = "SELECT SourceECInstanceId, TargetECInstanceId FROM meta.SchemaHasSchemaReferences";
1340
+ for await (const row of this.createQueryReader(referenceSql))
1341
+ referenceRows.push({ sourceECInstanceId: Id64.getLocalId(row[0]), targetECInstanceId: Id64.getLocalId(row[1]) });
1342
+ return SchemaManifest.fromRows(schemaRows, referenceRows);
1343
+ },
1344
+ fetchSchemaToken: async () => {
1345
+ const reader = this.createQueryReader("PRAGMA checksum(schema_token)");
1346
+ const result = await reader.next();
1347
+ if (result.done)
1348
+ throw new IModelError(DbResult.BE_SQLITE_ERROR, "PRAGMA checksum(schema_token) returned no rows");
1349
+ return result.value.sha3_256;
1350
+ },
1351
+ };
1352
+ }
1353
+ /** Fetch one schema-view blob (full or fragment). Both `PRAGMA schema_view` and
1354
+ * `PRAGMA schema_view_fragment` return a single row with the same columns. */
1355
+ async _fetchSchemaBlob(pragma) {
1356
+ // Only call reader.next() once - do NOT use `for await` on PRAGMA results. ConcurrentQuery wraps
1357
+ // regular ECSQL in LIMIT/OFFSET for pagination but skips this for PRAGMAs; if the serialized result
1358
+ // exceeds the memory threshold the response is marked "Partial", and a `for await` loop would
1359
+ // re-issue the same PRAGMA forever since PRAGMAs don't support OFFSET-based pagination.
1360
+ const reader = this.createQueryReader(pragma);
1337
1361
  const result = await reader.next();
1338
1362
  if (result.done)
1339
- throw new IModelError(DbResult.BE_SQLITE_ERROR, "PRAGMA schema_view returned no rows");
1363
+ throw new IModelError(DbResult.BE_SQLITE_ERROR, `${pragma} returned no rows`);
1340
1364
  const data = result.value.data;
1341
1365
  const token = result.value.schemaToken;
1342
1366
  if (data === undefined || data === null)
1343
- throw new IModelError(DbResult.BE_SQLITE_ERROR, "PRAGMA schema_view returned null data column");
1344
- return SchemaView.fromBinary(data, token ?? "");
1367
+ throw new IModelError(DbResult.BE_SQLITE_ERROR, `${pragma} returned null data column`);
1368
+ return { data, schemaToken: token ?? "" };
1345
1369
  }
1346
1370
  /** Get the linkTableRelationships for this IModel */
1347
1371
  get relationships() {
@@ -2145,7 +2169,7 @@ function processSchemaWriteStatus(status) {
2145
2169
  * @param props The data for the new model.
2146
2170
  * @returns The newly inserted model's Id.
2147
2171
  * @throws [[IModelError]] if insertion fails.
2148
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.insertModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2172
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.insertModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2149
2173
  */
2150
2174
  insertModel(props) {
2151
2175
  return this._iModel[_implicitTxn].insertModel(props);
@@ -2153,7 +2177,7 @@ function processSchemaWriteStatus(status) {
2153
2177
  /** Update an existing model.
2154
2178
  * @param props the properties of the model to change
2155
2179
  * @throws [[IModelError]] if update fails.
2156
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.updateModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2180
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.updateModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2157
2181
  */
2158
2182
  updateModel(props) {
2159
2183
  this._iModel[_implicitTxn].updateModel(props);
@@ -2165,7 +2189,7 @@ function processSchemaWriteStatus(status) {
2165
2189
  * Cached [Tile]($frontend)s are only invalidated after the geometry guid of the model changes.
2166
2190
  * @note This will throw IModelError with [IModelStatus.VersionTooOld]($core-bentley) if a version of the BisCore schema older than 1.0.11 is present in the iModel.
2167
2191
  * @throws [[IModelError]] if the update fails.
2168
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.updateGeometryGuid instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2192
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.updateGeometryGuid instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2169
2193
  * @see [[TxnManager.onModelGeometryChanged]] for the event emitted in response to such a change.
2170
2194
  */
2171
2195
  updateGeometryGuid(modelId) {
@@ -2174,7 +2198,7 @@ function processSchemaWriteStatus(status) {
2174
2198
  /** Delete one or more existing models.
2175
2199
  * @param ids The Ids of the models to be deleted
2176
2200
  * @throws [[IModelError]] if deletion fails.
2177
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.deleteModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2201
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.deleteModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2178
2202
  */
2179
2203
  deleteModel(ids) {
2180
2204
  this._iModel[_implicitTxn].deleteModel(ids);
@@ -2398,7 +2422,7 @@ function processSchemaWriteStatus(status) {
2398
2422
  * However when `elProps.federationGuid` is not present or undefined, a new Guid will be generated and stored on the resultant element. But
2399
2423
  * the value of `elProps.federationGuid` is *not* updated. Generally, it is best to re-read the element after inserting (e.g. via [[getElementProps]])
2400
2424
  * if you intend to continue working with it. That will ensure its values reflect the persistent state.
2401
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.insertElement instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2425
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.insertElement instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2402
2426
  */
2403
2427
  insertElement(elProps, options) {
2404
2428
  return this._iModel[_implicitTxn].insertElement(elProps, options);
@@ -2413,7 +2437,7 @@ function processSchemaWriteStatus(status) {
2413
2437
  * @note The values of `classFullName` and `model` *may not be changed* by this method. Further, it will permute the `elProps` object by adding or
2414
2438
  * overwriting their values to the correct values.
2415
2439
  * @throws [[ITwinError]] if update fails.
2416
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.updateElement instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2440
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.updateElement instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2417
2441
  */
2418
2442
  updateElement(elProps) {
2419
2443
  this._iModel[_implicitTxn].updateElement(elProps);
@@ -2422,7 +2446,7 @@ function processSchemaWriteStatus(status) {
2422
2446
  * @param ids The set of Ids of the element(s) to be deleted
2423
2447
  * @throws [[ITwinError]]
2424
2448
  * @see deleteDefinitionElements
2425
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.deleteElement instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2449
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.deleteElement instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2426
2450
  */
2427
2451
  deleteElement(ids) {
2428
2452
  this._iModel[_implicitTxn].deleteElement(ids);
@@ -2447,7 +2471,7 @@ function processSchemaWriteStatus(status) {
2447
2471
  * DefinitionElements rather than calling this method separately for each one. Ids that are not valid DefinitionElements will be ignored.
2448
2472
  * @returns An IdSet of the DefinitionElements that are used and were therefore not deleted.
2449
2473
  * @see deleteElement
2450
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.deleteDefinitionElements instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2474
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.deleteDefinitionElements instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2451
2475
  */
2452
2476
  deleteDefinitionElements(definitionElementIds) {
2453
2477
  return this._iModel[_implicitTxn].deleteDefinitionElements(definitionElementIds);
@@ -2516,16 +2540,21 @@ function processSchemaWriteStatus(status) {
2516
2540
  * @throws [[IModelError]]
2517
2541
  */
2518
2542
  _queryAspect(aspectInstanceId, aspectClassName) {
2519
- const sql = `SELECT *, ec_classname(ECClassId, 's:c') classFullName FROM ${aspectClassName} WHERE ECInstanceId=:aspectInstanceId`;
2543
+ // `SELECT *` targets a caller/runtime-determined ElementAspect subclass, so its shape can't be decomposed
2544
+ // ahead of time. Query using the non-deprecated UseECSqlPropertyNames format and reshape the row into the
2545
+ // legacy UseJsPropertyNames shape using ECSchema metadata (see ECSqlInstanceReshaper for why a naive,
2546
+ // non-schema-aware rename isn't safe here).
2547
+ const ecClass = getRuntimeClass(this._iModel, aspectClassName);
2548
+ const sql = `SELECT * FROM ${aspectClassName} WHERE ECInstanceId=:aspectInstanceId`;
2520
2549
  const aspect = this._iModel.withQueryReader(sql, (reader) => {
2521
2550
  if (reader.step()) {
2522
- const aspectProps = { ...reader.current.toRow() }; // start with everything that SELECT * returned; classFullName is supplied by the ec_classname alias
2523
- aspectProps.className = undefined; // clear the raw ECClassId-derived property from SELECT * that we don't want in the final instance
2551
+ const aspectProps = reshapeInstanceRow(reader.current.toRow(), ecClass, this._iModel);
2552
+ aspectProps.classFullName = aspectProps.className.replace(".", ":"); // add in property required by EntityProps
2553
+ aspectProps.className = undefined; // clear property from SELECT * that we don't want in the final instance
2524
2554
  return aspectProps;
2525
2555
  }
2526
2556
  return undefined;
2527
- // eslint-disable-next-line @typescript-eslint/no-deprecated
2528
- }, new QueryBinder().bindId("aspectInstanceId", aspectInstanceId), { rowFormat: QueryRowFormat.UseJsPropertyNames });
2557
+ }, new QueryBinder().bindId("aspectInstanceId", aspectInstanceId), { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
2529
2558
  if (undefined === aspect) {
2530
2559
  throw new IModelError(IModelStatus.NotFound, `ElementAspect not found ${aspectInstanceId}, ${aspectClassName}`);
2531
2560
  }
@@ -2629,7 +2658,7 @@ function processSchemaWriteStatus(status) {
2629
2658
  * @returns the id of the newly inserted aspect.
2630
2659
  * @note Aspect Ids may collide with element Ids, so don't put both in a container like Set or Map
2631
2660
  * use [EntityReference]($common) for that instead.
2632
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.insertAspect instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2661
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.insertAspect instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2633
2662
  */
2634
2663
  insertAspect(aspectProps) {
2635
2664
  return this._iModel[_implicitTxn].insertAspect(aspectProps);
@@ -2637,7 +2666,7 @@ function processSchemaWriteStatus(status) {
2637
2666
  /** Update an exist ElementAspect within the iModel.
2638
2667
  * @param aspectProps The properties to use to update the ElementAspect.
2639
2668
  * @throws [[IModelError]] if unable to update the ElementAspect.
2640
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.updateAspect instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2669
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.updateAspect instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2641
2670
  */
2642
2671
  updateAspect(aspectProps) {
2643
2672
  this._iModel[_implicitTxn].updateAspect(aspectProps);
@@ -2645,7 +2674,7 @@ function processSchemaWriteStatus(status) {
2645
2674
  /** Delete one or more ElementAspects from this iModel.
2646
2675
  * @param aspectInstanceIds The set of instance Ids of the ElementAspect(s) to be deleted
2647
2676
  * @throws [[IModelError]] if unable to delete the ElementAspect.
2648
- * @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.deleteAspect instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2677
+ * @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.deleteAspect instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2649
2678
  */
2650
2679
  deleteAspect(aspectInstanceIds) {
2651
2680
  this._iModel[_implicitTxn].deleteAspect(aspectInstanceIds);
@@ -2654,7 +2683,7 @@ function processSchemaWriteStatus(status) {
2654
2683
  * @param props The properties specifying the element to reparent and its new parent.
2655
2684
  * @throws [[ITwinError]] if the operation fails.
2656
2685
  * @beta
2657
- * @deprecated in 5.11.0 - will not be removed until after 2026-08-04. Use EditTxn.changeElementParent instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2686
+ * @deprecated in 5.11.0 - might be removed in next major version. Use EditTxn.changeElementParent instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2658
2687
  */
2659
2688
  changeElementParent(props) {
2660
2689
  this._iModel[_implicitTxn].changeElementParent(props);
@@ -2663,7 +2692,7 @@ function processSchemaWriteStatus(status) {
2663
2692
  * @param props The properties specifying the element to move and its new model.
2664
2693
  * @throws [[ITwinError]] if the operation fails.
2665
2694
  * @beta
2666
- * @deprecated in 5.11.0 - will not be removed until after 2026-08-04. Use EditTxn.changeElementModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2695
+ * @deprecated in 5.11.0 - might be removed in next major version. Use EditTxn.changeElementModel instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2667
2696
  */
2668
2697
  changeElementModel(props) {
2669
2698
  this._iModel[_implicitTxn].changeElementModel(props);
@@ -2710,7 +2739,7 @@ function processSchemaWriteStatus(status) {
2710
2739
  return this._viewStore;
2711
2740
  }
2712
2741
  /**
2713
- * @beta @deprecated in 5.9.0 - will not be removed until after 2026-08-04. Use EditTxn.saveDefaultViewStore instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2742
+ * @beta @deprecated in 5.9.0 - might be removed in next major version. Use EditTxn.saveDefaultViewStore instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2714
2743
  */
2715
2744
  saveDefaultViewStore(arg) {
2716
2745
  this._iModel[_implicitTxn].saveDefaultViewStore(arg);