@itwin/core-backend 5.13.0-dev.9 → 5.13.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 (267) hide show
  1. package/CHANGELOG.md +58 -1
  2. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  3. package/lib/cjs/BriefcaseManager.js +11 -5
  4. package/lib/cjs/BriefcaseManager.js.map +1 -1
  5. package/lib/cjs/Category.d.ts +4 -4
  6. package/lib/cjs/Category.js.map +1 -1
  7. package/lib/cjs/ChangesetECAdaptor.d.ts +5 -0
  8. package/lib/cjs/ChangesetECAdaptor.d.ts.map +1 -1
  9. package/lib/cjs/ChangesetECAdaptor.js +13 -3
  10. package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
  11. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  12. package/lib/cjs/CloudSqlite.js +9 -2
  13. package/lib/cjs/CloudSqlite.js.map +1 -1
  14. package/lib/cjs/CodeSpecs.d.ts +3 -3
  15. package/lib/cjs/CodeSpecs.js.map +1 -1
  16. package/lib/cjs/DisplayStyle.d.ts +2 -2
  17. package/lib/cjs/DisplayStyle.js.map +1 -1
  18. package/lib/cjs/ECDb.d.ts.map +1 -1
  19. package/lib/cjs/ECDb.js +1 -0
  20. package/lib/cjs/ECDb.js.map +1 -1
  21. package/lib/cjs/EditTxn.d.ts.map +1 -1
  22. package/lib/cjs/EditTxn.js +1 -0
  23. package/lib/cjs/EditTxn.js.map +1 -1
  24. package/lib/cjs/Element.d.ts +49 -13
  25. package/lib/cjs/Element.d.ts.map +1 -1
  26. package/lib/cjs/Element.js +121 -25
  27. package/lib/cjs/Element.js.map +1 -1
  28. package/lib/cjs/Entity.d.ts +3 -3
  29. package/lib/cjs/Entity.js +3 -3
  30. package/lib/cjs/Entity.js.map +1 -1
  31. package/lib/cjs/IModelDb.d.ts +72 -22
  32. package/lib/cjs/IModelDb.d.ts.map +1 -1
  33. package/lib/cjs/IModelDb.js +226 -89
  34. package/lib/cjs/IModelDb.js.map +1 -1
  35. package/lib/cjs/Model.d.ts +5 -5
  36. package/lib/cjs/Model.d.ts.map +1 -1
  37. package/lib/cjs/Model.js.map +1 -1
  38. package/lib/cjs/PropertyStore.js +1 -1
  39. package/lib/cjs/PropertyStore.js.map +1 -1
  40. package/lib/cjs/SchemaSync.d.ts +158 -22
  41. package/lib/cjs/SchemaSync.d.ts.map +1 -1
  42. package/lib/cjs/SchemaSync.js +417 -76
  43. package/lib/cjs/SchemaSync.js.map +1 -1
  44. package/lib/cjs/SynchronousChannel.d.ts +72 -0
  45. package/lib/cjs/SynchronousChannel.d.ts.map +1 -0
  46. package/lib/cjs/SynchronousChannel.js +11 -0
  47. package/lib/cjs/SynchronousChannel.js.map +1 -0
  48. package/lib/cjs/Texture.d.ts +1 -1
  49. package/lib/cjs/Texture.js.map +1 -1
  50. package/lib/cjs/TxnManager.d.ts +44 -4
  51. package/lib/cjs/TxnManager.d.ts.map +1 -1
  52. package/lib/cjs/TxnManager.js +80 -19
  53. package/lib/cjs/TxnManager.js.map +1 -1
  54. package/lib/cjs/ViewDefinition.d.ts +6 -6
  55. package/lib/cjs/ViewDefinition.d.ts.map +1 -1
  56. package/lib/cjs/ViewDefinition.js.map +1 -1
  57. package/lib/cjs/annotations/LeaderGeometry.d.ts +22 -7
  58. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
  59. package/lib/cjs/annotations/LeaderGeometry.js +104 -36
  60. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
  61. package/lib/cjs/annotations/TextAnnotationElement.d.ts +1 -1
  62. package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
  63. package/lib/cjs/annotations/TextAnnotationElement.js +25 -10
  64. package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
  65. package/lib/cjs/core-backend.d.ts +1 -0
  66. package/lib/cjs/core-backend.d.ts.map +1 -1
  67. package/lib/cjs/core-backend.js +1 -0
  68. package/lib/cjs/core-backend.js.map +1 -1
  69. package/lib/cjs/internal/IntegrityCheck.d.ts +22 -0
  70. package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -1
  71. package/lib/cjs/internal/IntegrityCheck.js +13 -0
  72. package/lib/cjs/internal/IntegrityCheck.js.map +1 -1
  73. package/lib/cjs/internal/NoReservations.d.ts +6 -0
  74. package/lib/cjs/internal/NoReservations.d.ts.map +1 -0
  75. package/lib/cjs/internal/NoReservations.js +21 -0
  76. package/lib/cjs/internal/NoReservations.js.map +1 -0
  77. package/lib/cjs/internal/SchemaSyncReservations.d.ts +4 -0
  78. package/lib/cjs/internal/SchemaSyncReservations.d.ts.map +1 -0
  79. package/lib/cjs/internal/SchemaSyncReservations.js +128 -0
  80. package/lib/cjs/internal/SchemaSyncReservations.js.map +1 -0
  81. package/lib/cjs/internal/Symbols.d.ts +1 -0
  82. package/lib/cjs/internal/Symbols.d.ts.map +1 -1
  83. package/lib/cjs/internal/Symbols.js +2 -1
  84. package/lib/cjs/internal/Symbols.js.map +1 -1
  85. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  86. package/lib/esm/BriefcaseManager.js +11 -5
  87. package/lib/esm/BriefcaseManager.js.map +1 -1
  88. package/lib/esm/Category.d.ts +4 -4
  89. package/lib/esm/Category.js.map +1 -1
  90. package/lib/esm/ChangesetECAdaptor.d.ts +5 -0
  91. package/lib/esm/ChangesetECAdaptor.d.ts.map +1 -1
  92. package/lib/esm/ChangesetECAdaptor.js +13 -3
  93. package/lib/esm/ChangesetECAdaptor.js.map +1 -1
  94. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  95. package/lib/esm/CloudSqlite.js +10 -3
  96. package/lib/esm/CloudSqlite.js.map +1 -1
  97. package/lib/esm/CodeSpecs.d.ts +3 -3
  98. package/lib/esm/CodeSpecs.js.map +1 -1
  99. package/lib/esm/DisplayStyle.d.ts +2 -2
  100. package/lib/esm/DisplayStyle.js.map +1 -1
  101. package/lib/esm/ECDb.d.ts.map +1 -1
  102. package/lib/esm/ECDb.js +1 -0
  103. package/lib/esm/ECDb.js.map +1 -1
  104. package/lib/esm/EditTxn.d.ts.map +1 -1
  105. package/lib/esm/EditTxn.js +1 -0
  106. package/lib/esm/EditTxn.js.map +1 -1
  107. package/lib/esm/Element.d.ts +49 -13
  108. package/lib/esm/Element.d.ts.map +1 -1
  109. package/lib/esm/Element.js +122 -26
  110. package/lib/esm/Element.js.map +1 -1
  111. package/lib/esm/Entity.d.ts +3 -3
  112. package/lib/esm/Entity.js +3 -3
  113. package/lib/esm/Entity.js.map +1 -1
  114. package/lib/esm/IModelDb.d.ts +72 -22
  115. package/lib/esm/IModelDb.d.ts.map +1 -1
  116. package/lib/esm/IModelDb.js +227 -90
  117. package/lib/esm/IModelDb.js.map +1 -1
  118. package/lib/esm/Model.d.ts +5 -5
  119. package/lib/esm/Model.d.ts.map +1 -1
  120. package/lib/esm/Model.js.map +1 -1
  121. package/lib/esm/PropertyStore.js +1 -1
  122. package/lib/esm/PropertyStore.js.map +1 -1
  123. package/lib/esm/SchemaSync.d.ts +158 -22
  124. package/lib/esm/SchemaSync.d.ts.map +1 -1
  125. package/lib/esm/SchemaSync.js +419 -78
  126. package/lib/esm/SchemaSync.js.map +1 -1
  127. package/lib/esm/SynchronousChannel.d.ts +72 -0
  128. package/lib/esm/SynchronousChannel.d.ts.map +1 -0
  129. package/lib/esm/SynchronousChannel.js +9 -0
  130. package/lib/esm/SynchronousChannel.js.map +1 -0
  131. package/lib/esm/Texture.d.ts +1 -1
  132. package/lib/esm/Texture.js.map +1 -1
  133. package/lib/esm/TxnManager.d.ts +44 -4
  134. package/lib/esm/TxnManager.d.ts.map +1 -1
  135. package/lib/esm/TxnManager.js +81 -20
  136. package/lib/esm/TxnManager.js.map +1 -1
  137. package/lib/esm/ViewDefinition.d.ts +6 -6
  138. package/lib/esm/ViewDefinition.d.ts.map +1 -1
  139. package/lib/esm/ViewDefinition.js.map +1 -1
  140. package/lib/esm/annotations/LeaderGeometry.d.ts +22 -7
  141. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
  142. package/lib/esm/annotations/LeaderGeometry.js +104 -36
  143. package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
  144. package/lib/esm/annotations/TextAnnotationElement.d.ts +1 -1
  145. package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
  146. package/lib/esm/annotations/TextAnnotationElement.js +25 -10
  147. package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
  148. package/lib/esm/core-backend.d.ts +1 -0
  149. package/lib/esm/core-backend.d.ts.map +1 -1
  150. package/lib/esm/core-backend.js +1 -0
  151. package/lib/esm/core-backend.js.map +1 -1
  152. package/lib/esm/internal/IntegrityCheck.d.ts +22 -0
  153. package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -1
  154. package/lib/esm/internal/IntegrityCheck.js +13 -0
  155. package/lib/esm/internal/IntegrityCheck.js.map +1 -1
  156. package/lib/esm/internal/NoReservations.d.ts +6 -0
  157. package/lib/esm/internal/NoReservations.d.ts.map +1 -0
  158. package/lib/esm/internal/NoReservations.js +18 -0
  159. package/lib/esm/internal/NoReservations.js.map +1 -0
  160. package/lib/esm/internal/SchemaSyncReservations.d.ts +4 -0
  161. package/lib/esm/internal/SchemaSyncReservations.d.ts.map +1 -0
  162. package/lib/esm/internal/SchemaSyncReservations.js +125 -0
  163. package/lib/esm/internal/SchemaSyncReservations.js.map +1 -0
  164. package/lib/esm/internal/Symbols.d.ts +1 -0
  165. package/lib/esm/internal/Symbols.d.ts.map +1 -1
  166. package/lib/esm/internal/Symbols.js +1 -0
  167. package/lib/esm/internal/Symbols.js.map +1 -1
  168. package/lib/esm/test/IModelTestUtils.d.ts +1 -1
  169. package/lib/esm/test/IModelTestUtils.d.ts.map +1 -1
  170. package/lib/esm/test/IModelTestUtils.js +8 -3
  171. package/lib/esm/test/IModelTestUtils.js.map +1 -1
  172. package/lib/esm/test/annotations/LeaderGeometry.test.js +178 -2
  173. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
  174. package/lib/esm/test/annotations/TextAnnotation.test.js +48 -18
  175. package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
  176. package/lib/esm/test/ecdb/ECSqlStatement.test.js +177 -0
  177. package/lib/esm/test/ecdb/ECSqlStatement.test.js.map +1 -1
  178. package/lib/esm/test/ecdb/QueryReaders.test.js +2 -16
  179. package/lib/esm/test/ecdb/QueryReaders.test.js.map +1 -1
  180. package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js +2 -2
  181. package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js.map +1 -1
  182. package/lib/esm/test/element/ElementRoundTrip.test.js +80 -2
  183. package/lib/esm/test/element/ElementRoundTrip.test.js.map +1 -1
  184. package/lib/esm/test/hubaccess/Rebase.test.js +3 -1
  185. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
  186. package/lib/esm/test/hubaccess/SemanticRebase.test.js +29 -28
  187. package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
  188. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts +3 -0
  189. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts.map +1 -0
  190. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js +15 -0
  191. package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js.map +1 -0
  192. package/lib/esm/test/imodel/IModelECSql.test.d.ts +2 -0
  193. package/lib/esm/test/imodel/IModelECSql.test.d.ts.map +1 -0
  194. package/lib/esm/test/imodel/IModelECSql.test.js +367 -0
  195. package/lib/esm/test/imodel/IModelECSql.test.js.map +1 -0
  196. package/lib/esm/test/imodel/IModelElements.test.d.ts +2 -0
  197. package/lib/esm/test/imodel/IModelElements.test.d.ts.map +1 -0
  198. package/lib/esm/test/imodel/IModelElements.test.js +969 -0
  199. package/lib/esm/test/imodel/IModelElements.test.js.map +1 -0
  200. package/lib/esm/test/imodel/IModelGeolocation.test.d.ts +2 -0
  201. package/lib/esm/test/imodel/IModelGeolocation.test.d.ts.map +1 -0
  202. package/lib/esm/test/imodel/IModelGeolocation.test.js +539 -0
  203. package/lib/esm/test/imodel/IModelGeolocation.test.js.map +1 -0
  204. package/lib/esm/test/imodel/IModelLifecycle.test.d.ts +2 -0
  205. package/lib/esm/test/imodel/IModelLifecycle.test.d.ts.map +1 -0
  206. package/lib/esm/test/imodel/IModelLifecycle.test.js +499 -0
  207. package/lib/esm/test/imodel/IModelLifecycle.test.js.map +1 -0
  208. package/lib/esm/test/imodel/IModelMetadata.test.d.ts +2 -0
  209. package/lib/esm/test/imodel/IModelMetadata.test.d.ts.map +1 -0
  210. package/lib/esm/test/imodel/IModelMetadata.test.js +274 -0
  211. package/lib/esm/test/imodel/IModelMetadata.test.js.map +1 -0
  212. package/lib/esm/test/imodel/IModelModels.test.d.ts +2 -0
  213. package/lib/esm/test/imodel/IModelModels.test.d.ts.map +1 -0
  214. package/lib/esm/test/imodel/IModelModels.test.js +357 -0
  215. package/lib/esm/test/imodel/IModelModels.test.js.map +1 -0
  216. package/lib/esm/test/imodel/IModelRelationships.test.d.ts +2 -0
  217. package/lib/esm/test/imodel/IModelRelationships.test.d.ts.map +1 -0
  218. package/lib/esm/test/imodel/IModelRelationships.test.js +407 -0
  219. package/lib/esm/test/imodel/IModelRelationships.test.js.map +1 -0
  220. package/lib/esm/test/imodel/IModelTestFixtures.d.ts +53 -0
  221. package/lib/esm/test/imodel/IModelTestFixtures.d.ts.map +1 -0
  222. package/lib/esm/test/imodel/IModelTestFixtures.js +107 -0
  223. package/lib/esm/test/imodel/IModelTestFixtures.js.map +1 -0
  224. package/lib/esm/test/imodel/IModelViews.test.d.ts +2 -0
  225. package/lib/esm/test/imodel/IModelViews.test.d.ts.map +1 -0
  226. package/lib/esm/test/imodel/IModelViews.test.js +199 -0
  227. package/lib/esm/test/imodel/IModelViews.test.js.map +1 -0
  228. package/lib/esm/test/index.d.ts +0 -1
  229. package/lib/esm/test/index.d.ts.map +1 -1
  230. package/lib/esm/test/index.js +0 -1
  231. package/lib/esm/test/index.js.map +1 -1
  232. package/lib/esm/test/standalone/ChangesetReader.test.js +8 -26
  233. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  234. package/lib/esm/test/standalone/DgnDomainMergeConflict.test.d.ts +2 -0
  235. package/lib/esm/test/standalone/DgnDomainMergeConflict.test.d.ts.map +1 -0
  236. package/lib/esm/test/standalone/DgnDomainMergeConflict.test.js +263 -0
  237. package/lib/esm/test/standalone/DgnDomainMergeConflict.test.js.map +1 -0
  238. package/lib/esm/test/standalone/GeometryStream.test.js +1 -3
  239. package/lib/esm/test/standalone/GeometryStream.test.js.map +1 -1
  240. package/lib/esm/test/standalone/IModelWrite.test.d.ts.map +1 -1
  241. package/lib/esm/test/standalone/IModelWrite.test.js +78 -1
  242. package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
  243. package/lib/esm/test/standalone/IntegrityCheck.test.js +29 -10
  244. package/lib/esm/test/standalone/IntegrityCheck.test.js.map +1 -1
  245. package/lib/esm/test/standalone/SQliteChangesetReaderAndChangesetECAdaptor.test.js +23 -0
  246. package/lib/esm/test/standalone/SQliteChangesetReaderAndChangesetECAdaptor.test.js.map +1 -1
  247. package/lib/esm/test/standalone/SchemaSyncDb.test.d.ts +2 -0
  248. package/lib/esm/test/standalone/SchemaSyncDb.test.d.ts.map +1 -0
  249. package/lib/esm/test/standalone/SchemaSyncDb.test.js +201 -0
  250. package/lib/esm/test/standalone/SchemaSyncDb.test.js.map +1 -0
  251. package/lib/esm/test/standalone/SchemaSyncElementReservation.test.d.ts +2 -0
  252. package/lib/esm/test/standalone/SchemaSyncElementReservation.test.d.ts.map +1 -0
  253. package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js +460 -0
  254. package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js.map +1 -0
  255. package/lib/esm/test/standalone/SnapshotDb.test.js +1 -0
  256. package/lib/esm/test/standalone/SnapshotDb.test.js.map +1 -1
  257. package/lib/esm/test/standalone/TxnManager.test.js +108 -8
  258. package/lib/esm/test/standalone/TxnManager.test.js.map +1 -1
  259. package/package.json +14 -17
  260. package/lib/esm/test/RevisionUtility.d.ts +0 -33
  261. package/lib/esm/test/RevisionUtility.d.ts.map +0 -1
  262. package/lib/esm/test/RevisionUtility.js +0 -52
  263. package/lib/esm/test/RevisionUtility.js.map +0 -1
  264. package/lib/esm/test/imodel/IModel.test.d.ts +0 -2
  265. package/lib/esm/test/imodel/IModel.test.d.ts.map +0 -1
  266. package/lib/esm/test/imodel/IModel.test.js +0 -3277
  267. package/lib/esm/test/imodel/IModel.test.js.map +0 -1
@@ -8,7 +8,7 @@
8
8
  import * as fs from "fs";
9
9
  import { join } from "path";
10
10
  import * as touch from "touch";
11
- import { assert, BeEvent, BentleyStatus, ChangeSetStatus, DbChangeStage, DbConflictCause, DbConflictResolution, DbResult, Guid, Id64, IModelStatus, JsonUtils, Logger, LogLevel, LRUMap, OpenMode } from "@itwin/core-bentley";
11
+ import { assert, BeEvent, BentleyStatus, ChangeSetStatus, DbChangeStage, DbConflictCause, DbConflictResolution, DbOpcode, DbResult, Guid, Id64, IModelStatus, JsonUtils, Logger, LogLevel, LRUMap, OpenMode } from "@itwin/core-bentley";
12
12
  import { Base64EncodedString, BriefcaseIdValue, Code, DomainOptions, ECJsNames, ECSqlReader, EditTxnError, EntityMetaData, FontMap, IModel, IModelError, IModelNotFoundResponse, ProfileOptions, QueryBinder, QueryRowFormat, resolveNavPropId, SchemaState, ViewStoreError, ViewStoreRpc } from "@itwin/core-common";
13
13
  import { Range2d, Range3d } from "@itwin/core-geometry";
14
14
  import { BackendLoggerCategory } from "./BackendLoggerCategory";
@@ -45,7 +45,9 @@ import { constructWorkspace, throwWorkspaceDbLoadErrors } from "./internal/works
45
45
  import { SettingsImpl } from "./internal/workspace/SettingsImpl";
46
46
  import { IModelNative } from "./internal/NativePlatform";
47
47
  import { createNoOpLockControl } from "./internal/NoLocks";
48
+ import { createNoOpReservations } from "./internal/NoReservations";
48
49
  import { createIModelDbFonts } from "./internal/IModelDbFontsImpl";
50
+ import { createSchemaSyncReservations } from "./internal/SchemaSyncReservations";
49
51
  import { _activeTxn, _cache, _close, _hubAccess, _implicitTxn, _instanceKeyCache, _nativeDb, _releaseAllLocks, _resetIModelDb } from "./internal/Symbols";
50
52
  import { ECVersion, SchemaContext, SchemaJsonLocater, SchemaManifest, SchemaViewManager } from "@itwin/ecschema-metadata";
51
53
  import { SchemaMap } from "./Schema";
@@ -175,6 +177,8 @@ export class IModelDb extends IModel {
175
177
  /** @internal */
176
178
  _locks = createNoOpLockControl();
177
179
  /** @internal */
180
+ _reservations = createNoOpReservations();
181
+ /** @internal */
178
182
  _codeService;
179
183
  /**
180
184
  * The always-available implicit transaction for this iModel.
@@ -203,6 +207,16 @@ export class IModelDb extends IModel {
203
207
  get codeService() { return this._codeService; }
204
208
  /** The [[LockControl]] that orchestrates [concurrent editing]($docs/learning/backend/ConcurrencyControl.md) of this iModel. */
205
209
  get locks() { return this._locks; } // eslint-disable-line @typescript-eslint/no-non-null-assertion
210
+ /** @beta The [[SynchronousChannel.Reservations]] that orchestrates [concurrent editing]($docs/learning/backend/ConcurrencyControl.md) of this iModel. */
211
+ get reservations() { return this._reservations; } // eslint-disable-line @typescript-eslint/no-non-null-assertion
212
+ /** @internal */
213
+ async initializeSharedElementReservations() {
214
+ this._reservations?.[_close]();
215
+ if (SchemaSync.isEnabled(this))
216
+ this._reservations = await createSchemaSyncReservations(this);
217
+ else
218
+ this._reservations = createNoOpReservations();
219
+ }
206
220
  /** Provides methods for interacting with [font-related information]($docs/learning/backend/Fonts.md) stored in this iModel.
207
221
  * @beta
208
222
  */
@@ -303,7 +317,9 @@ export class IModelDb extends IModel {
303
317
  db[_nativeDb].abandonChanges();
304
318
  db.close();
305
319
  }
306
- catch { }
320
+ catch {
321
+ return;
322
+ }
307
323
  });
308
324
  });
309
325
  }
@@ -363,16 +379,26 @@ export class IModelDb extends IModel {
363
379
  this.views[_close]();
364
380
  this.locks[_close]();
365
381
  this._locks = undefined;
382
+ this.reservations[_close]();
383
+ this._reservations = undefined;
366
384
  this._codeService?.close();
367
385
  this._codeService = undefined;
368
386
  this[_nativeDb].closeFile();
369
387
  }
388
+ /**
389
+ * Save any unsaved schema changes in this iModel.
390
+ * @internal
391
+ */
370
392
  saveSchemaChanges(args) {
371
393
  if (!this[_nativeDb].hasUnsavedChanges())
372
394
  return;
373
395
  const saveArgs = typeof args === "string" ? { description: args } : args;
374
396
  saveArgs === undefined ? this[_nativeDb].saveChanges() : this[_nativeDb].saveChanges(JSON.stringify(saveArgs));
375
397
  }
398
+ /**
399
+ * Abandon any unsaved schema changes in this iModel.
400
+ * @internal
401
+ */
376
402
  abandonSchemaChanges() {
377
403
  if (!this[_nativeDb].hasUnsavedChanges())
378
404
  return;
@@ -919,7 +945,7 @@ export class IModelDb extends IModel {
919
945
  async dropSchemas(schemaNames) {
920
946
  if (schemaNames.length === 0)
921
947
  return;
922
- if (this[_nativeDb].schemaSyncEnabled())
948
+ if (SchemaSync.isEnabled(this))
923
949
  throw new IModelError(DbResult.BE_SQLITE_ERROR, "Cannot drop schemas when schema sync is enabled");
924
950
  if (this[_nativeDb].hasUnsavedChanges())
925
951
  throw new IModelError(ChangeSetStatus.HasUncommittedChanges, "Cannot drop schemas with unsaved changes");
@@ -1005,26 +1031,34 @@ export class IModelDb extends IModel {
1005
1031
  this.cleanupSnapshot(context.resources);
1006
1032
  }
1007
1033
  }
1008
- /** Shared implementation for importing schemas from file or string. */
1009
- async importSchemasInternal(schemas, options, nativeImportOp) {
1010
- // BriefcaseDb-specific validation checks
1011
- if (this.isBriefcaseDb()) {
1012
- if (this.txns.rebaser.isRebasing) {
1013
- throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas while rebasing");
1014
- }
1015
- if (this.txns.isIndirectChanges) {
1016
- throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas while in an indirect change scope");
1017
- }
1018
- // Additional checks when semantic rebase is enabled
1019
- if (IModelHost.useSemanticRebase) {
1020
- if (this[_nativeDb].hasUnsavedChanges()) {
1021
- throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas with unsaved changes when useSemanticRebase flag is on");
1022
- }
1023
- if (this[_nativeDb].schemaSyncEnabled()) {
1024
- throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas when schema sync is enabled and also useSemanticRebase flag is on");
1025
- }
1034
+ /** Refuse a schema import this briefcase is in no state to run. Shared by [[importSchemas]] and
1035
+ * [[BriefcaseDb.upgradeSchemas]], which reach the native importer by different routes.
1036
+ * @internal
1037
+ */
1038
+ assertCanImportSchemas() {
1039
+ if (!this.isBriefcaseDb())
1040
+ return;
1041
+ if (this.txns.rebaser.isRebasing) {
1042
+ throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas while rebasing");
1043
+ }
1044
+ if (this.txns.isIndirectChanges) {
1045
+ throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas while in an indirect change scope");
1046
+ }
1047
+ // Additional checks when semantic rebase is enabled
1048
+ if (IModelHost.useSemanticRebase) {
1049
+ if (this[_nativeDb].hasUnsavedChanges()) {
1050
+ throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas with unsaved changes when useSemanticRebase flag is on");
1051
+ }
1052
+ if (SchemaSync.isEnabled(this)) {
1053
+ throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas when schema sync is enabled and also useSemanticRebase flag is on");
1026
1054
  }
1027
1055
  }
1056
+ }
1057
+ /** Shared implementation for importing schemas from file or string.
1058
+ * @internal
1059
+ */
1060
+ async importSchemasInternal(schemas, options, nativeImportOp) {
1061
+ this.assertCanImportSchemas();
1028
1062
  if (options?.channelUpgrade) {
1029
1063
  const channelUpgrade = options.channelUpgrade;
1030
1064
  try {
@@ -1042,30 +1076,52 @@ export class IModelDb extends IModel {
1042
1076
  if (options?.schemaImportCallbacks?.preSchemaImportCallback)
1043
1077
  preSchemaImportCallbackResult = await this.preSchemaImportCallback(options.schemaImportCallbacks, { iModel: this, data: options.data, schemaData: schemas });
1044
1078
  const maybeCustomNativeContext = options?.ecSchemaXmlContext?.nativeContext;
1045
- if (this[_nativeDb].schemaSyncEnabled()) {
1046
- await SchemaSync.withLockedAccess(this, { openMode: OpenMode.Readonly, operationName: "schema sync" }, async (syncAccess) => {
1047
- const schemaSyncDbUri = syncAccess.getUri();
1048
- this.saveSchemaChanges();
1049
- try {
1050
- nativeImportOp(schemas, { schemaLockHeld: false, ecSchemaXmlContext: maybeCustomNativeContext, schemaSyncDbUri });
1051
- }
1052
- catch (outerErr) {
1053
- if (DbResult.BE_SQLITE_ERROR_DataTransformRequired === outerErr.errorNumber) {
1054
- this.abandonSchemaChanges();
1055
- if (this[_nativeDb].getITwinId() !== Guid.empty)
1056
- await this.acquireSchemaLock();
1057
- try {
1058
- nativeImportOp(schemas, { schemaLockHeld: true, ecSchemaXmlContext: maybeCustomNativeContext, schemaSyncDbUri });
1059
- }
1060
- catch (innerErr) {
1061
- throw new IModelError(innerErr.errorNumber, innerErr.message);
1062
- }
1079
+ if (SchemaSync.isEnabled(this)) {
1080
+ // The shared lock lets concurrent updates through while blocking anyone taking the exclusive lock for an upgrade.
1081
+ if (this[_nativeDb].getITwinId() !== Guid.empty)
1082
+ await this.locks.acquireLocks({ shared: IModel.repositoryModelId });
1083
+ // The native import adopts rows from the attached SchemaSyncDb. Attach and detach commit
1084
+ // implicitly, so abandoning changes cannot undo the adoption. A later failure must roll the
1085
+ // briefcase back before those ec_ rows can be pushed.
1086
+ let txnBeforeAdopt;
1087
+ // Set once the caller's own work is committed. Getting a token or the container write lock happens
1088
+ // before that, and abandonSchemaChanges discards every unsaved change rather than only this import's,
1089
+ // so abandoning on a failure from that window would throw away work the import never touched.
1090
+ let callerChangesSaved = false;
1091
+ try {
1092
+ await SchemaSync.withLockedAccess(this, { openMode: OpenMode.Readonly, operationName: "schema sync" }, async (syncAccess) => {
1093
+ const schemaSyncDbUri = syncAccess.getUri();
1094
+ this.saveSchemaChanges();
1095
+ callerChangesSaved = true;
1096
+ // After saveSchemaChanges, so rolling back cannot reach the caller's own work.
1097
+ if (this.isBriefcaseDb())
1098
+ txnBeforeAdopt = this.txns.getCurrentTxnId();
1099
+ try {
1100
+ nativeImportOp(schemas, { schemaLockHeld: false, ecSchemaXmlContext: maybeCustomNativeContext, schemaSyncDbUri });
1063
1101
  }
1064
- else {
1065
- throw new IModelError(outerErr.errorNumber, outerErr.message);
1102
+ catch (err) {
1103
+ if (SchemaSync.requiresUpgrade(err))
1104
+ throw new IModelError(err.errorNumber, `${err.message} - this schema change needs the upgrade path. Use BriefcaseDb.upgradeSchemas, which takes the exclusive schema lock and pushes the result.`);
1105
+ throw new IModelError(err.errorNumber, err.message);
1066
1106
  }
1107
+ });
1108
+ }
1109
+ catch (err) {
1110
+ if (callerChangesSaved)
1111
+ this.abandonSchemaChanges();
1112
+ if (this.isBriefcaseDb() && undefined !== txnBeforeAdopt && this.txns.getCurrentTxnId() !== txnBeforeAdopt) {
1113
+ // Saving the adopt's txn started a new undo session, because schema changes are kept out of the
1114
+ // user's undo stack, so this reverses across that boundary. The changes themselves reverse like
1115
+ // any other - a rebase does it to every local txn on every pull. It does not reverse DDL: a table
1116
+ // or column the adopt created stays behind with no ec_ row describing it, which is the state a
1117
+ // briefcase already tolerates, and the next successful import finds the table up to date and
1118
+ // carries on. Cancel rather than reverse, so the rows cannot come back through undo either.
1119
+ const status = this[_nativeDb].cancelTo(txnBeforeAdopt, true);
1120
+ if (IModelStatus.Success !== status)
1121
+ Logger.logError(loggerCategory, `Failed to roll back the adopted schema rows after a failed import: ${IModelStatus[status] ?? status}`);
1067
1122
  }
1068
- });
1123
+ throw err;
1124
+ }
1069
1125
  }
1070
1126
  else {
1071
1127
  const nativeImportOptions = {
@@ -2174,7 +2230,7 @@ function processSchemaWriteStatus(status) {
2174
2230
  * @param props The data for the new model.
2175
2231
  * @returns The newly inserted model's Id.
2176
2232
  * @throws [[IModelError]] if insertion fails.
2177
- * @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.
2233
+ * @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.
2178
2234
  */
2179
2235
  insertModel(props) {
2180
2236
  return this._iModel[_implicitTxn].insertModel(props);
@@ -2182,7 +2238,7 @@ function processSchemaWriteStatus(status) {
2182
2238
  /** Update an existing model.
2183
2239
  * @param props the properties of the model to change
2184
2240
  * @throws [[IModelError]] if update fails.
2185
- * @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.
2241
+ * @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.
2186
2242
  */
2187
2243
  updateModel(props) {
2188
2244
  this._iModel[_implicitTxn].updateModel(props);
@@ -2194,7 +2250,7 @@ function processSchemaWriteStatus(status) {
2194
2250
  * Cached [Tile]($frontend)s are only invalidated after the geometry guid of the model changes.
2195
2251
  * @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.
2196
2252
  * @throws [[IModelError]] if the update fails.
2197
- * @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.
2253
+ * @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.
2198
2254
  * @see [[TxnManager.onModelGeometryChanged]] for the event emitted in response to such a change.
2199
2255
  */
2200
2256
  updateGeometryGuid(modelId) {
@@ -2203,7 +2259,7 @@ function processSchemaWriteStatus(status) {
2203
2259
  /** Delete one or more existing models.
2204
2260
  * @param ids The Ids of the models to be deleted
2205
2261
  * @throws [[IModelError]] if deletion fails.
2206
- * @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.
2262
+ * @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.
2207
2263
  */
2208
2264
  deleteModel(ids) {
2209
2265
  this._iModel[_implicitTxn].deleteModel(ids);
@@ -2427,7 +2483,7 @@ function processSchemaWriteStatus(status) {
2427
2483
  * However when `elProps.federationGuid` is not present or undefined, a new Guid will be generated and stored on the resultant element. But
2428
2484
  * the value of `elProps.federationGuid` is *not* updated. Generally, it is best to re-read the element after inserting (e.g. via [[getElementProps]])
2429
2485
  * if you intend to continue working with it. That will ensure its values reflect the persistent state.
2430
- * @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.
2486
+ * @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.
2431
2487
  */
2432
2488
  insertElement(elProps, options) {
2433
2489
  return this._iModel[_implicitTxn].insertElement(elProps, options);
@@ -2442,7 +2498,7 @@ function processSchemaWriteStatus(status) {
2442
2498
  * @note The values of `classFullName` and `model` *may not be changed* by this method. Further, it will permute the `elProps` object by adding or
2443
2499
  * overwriting their values to the correct values.
2444
2500
  * @throws [[ITwinError]] if update fails.
2445
- * @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.
2501
+ * @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.
2446
2502
  */
2447
2503
  updateElement(elProps) {
2448
2504
  this._iModel[_implicitTxn].updateElement(elProps);
@@ -2451,7 +2507,7 @@ function processSchemaWriteStatus(status) {
2451
2507
  * @param ids The set of Ids of the element(s) to be deleted
2452
2508
  * @throws [[ITwinError]]
2453
2509
  * @see deleteDefinitionElements
2454
- * @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.
2510
+ * @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.
2455
2511
  */
2456
2512
  deleteElement(ids) {
2457
2513
  this._iModel[_implicitTxn].deleteElement(ids);
@@ -2462,7 +2518,7 @@ function processSchemaWriteStatus(status) {
2462
2518
  * @param deleteOptions Options for the delete operation.
2463
2519
  * @returns A result object containing information about the deletion operation success and the element ids that failed to delete (if any).
2464
2520
  * @throws [[ITwinError]] if any of the supplied ids are not well-formed/valid [[Id64String]]s.
2465
- * @deprecated in 5.1.9 - will not be removed until after 2026-08-15. Use EditTxn.deleteElements instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2521
+ * @deprecated in 5.1.9 - might be removed in next major version. Use EditTxn.deleteElements instead, within an explicit EditTxn scope (or via withEditTxn). See EditTxn documentation for migration help.
2466
2522
  * @beta
2467
2523
  */
2468
2524
  deleteElements(ids, deleteOptions) {
@@ -2476,7 +2532,7 @@ function processSchemaWriteStatus(status) {
2476
2532
  * DefinitionElements rather than calling this method separately for each one. Ids that are not valid DefinitionElements will be ignored.
2477
2533
  * @returns An IdSet of the DefinitionElements that are used and were therefore not deleted.
2478
2534
  * @see deleteElement
2479
- * @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.
2535
+ * @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.
2480
2536
  */
2481
2537
  deleteDefinitionElements(definitionElementIds) {
2482
2538
  return this._iModel[_implicitTxn].deleteDefinitionElements(definitionElementIds);
@@ -2719,7 +2775,7 @@ function processSchemaWriteStatus(status) {
2719
2775
  * @returns the id of the newly inserted aspect.
2720
2776
  * @note Aspect Ids may collide with element Ids, so don't put both in a container like Set or Map
2721
2777
  * use [EntityReference]($common) for that instead.
2722
- * @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.
2778
+ * @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.
2723
2779
  */
2724
2780
  insertAspect(aspectProps) {
2725
2781
  return this._iModel[_implicitTxn].insertAspect(aspectProps);
@@ -2727,7 +2783,7 @@ function processSchemaWriteStatus(status) {
2727
2783
  /** Update an exist ElementAspect within the iModel.
2728
2784
  * @param aspectProps The properties to use to update the ElementAspect.
2729
2785
  * @throws [[IModelError]] if unable to update the ElementAspect.
2730
- * @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.
2786
+ * @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.
2731
2787
  */
2732
2788
  updateAspect(aspectProps) {
2733
2789
  this._iModel[_implicitTxn].updateAspect(aspectProps);
@@ -2735,7 +2791,7 @@ function processSchemaWriteStatus(status) {
2735
2791
  /** Delete one or more ElementAspects from this iModel.
2736
2792
  * @param aspectInstanceIds The set of instance Ids of the ElementAspect(s) to be deleted
2737
2793
  * @throws [[IModelError]] if unable to delete the ElementAspect.
2738
- * @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.
2794
+ * @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.
2739
2795
  */
2740
2796
  deleteAspect(aspectInstanceIds) {
2741
2797
  this._iModel[_implicitTxn].deleteAspect(aspectInstanceIds);
@@ -2744,7 +2800,7 @@ function processSchemaWriteStatus(status) {
2744
2800
  * @param props The properties specifying the element to reparent and its new parent.
2745
2801
  * @throws [[ITwinError]] if the operation fails.
2746
2802
  * @beta
2747
- * @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.
2803
+ * @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.
2748
2804
  */
2749
2805
  changeElementParent(props) {
2750
2806
  this._iModel[_implicitTxn].changeElementParent(props);
@@ -2753,7 +2809,7 @@ function processSchemaWriteStatus(status) {
2753
2809
  * @param props The properties specifying the element to move and its new model.
2754
2810
  * @throws [[ITwinError]] if the operation fails.
2755
2811
  * @beta
2756
- * @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.
2812
+ * @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.
2757
2813
  */
2758
2814
  changeElementModel(props) {
2759
2815
  this._iModel[_implicitTxn].changeElementModel(props);
@@ -2812,7 +2868,7 @@ function processSchemaWriteStatus(status) {
2812
2868
  return this._viewStore;
2813
2869
  }
2814
2870
  /**
2815
- * @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.
2871
+ * @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.
2816
2872
  */
2817
2873
  saveDefaultViewStore(arg) {
2818
2874
  this._iModel[_implicitTxn].saveDefaultViewStore(arg);
@@ -2830,7 +2886,9 @@ function processSchemaWriteStatus(status) {
2830
2886
  try {
2831
2887
  props.push(imodel.elements.getElementProps(id));
2832
2888
  }
2833
- catch { }
2889
+ catch {
2890
+ return;
2891
+ }
2834
2892
  });
2835
2893
  return props;
2836
2894
  }
@@ -2853,7 +2911,9 @@ function processSchemaWriteStatus(status) {
2853
2911
  break;
2854
2912
  }
2855
2913
  }
2856
- catch { }
2914
+ catch {
2915
+ continue;
2916
+ }
2857
2917
  }
2858
2918
  return finished;
2859
2919
  }
@@ -3063,9 +3123,6 @@ export class BriefcaseDb extends IModelDb {
3063
3123
  get isBriefcase() { return true; }
3064
3124
  /* the BriefcaseId of the briefcase opened with this BriefcaseDb */
3065
3125
  briefcaseId;
3066
- _skipSyncSchemasOnPullAndPush;
3067
- /** @internal */
3068
- get skipSyncSchemasOnPullAndPush() { return this._skipSyncSchemasOnPullAndPush ?? false; }
3069
3126
  /**
3070
3127
  * Event raised just before a BriefcaseDb is opened. Supplies the arguments that will be used to open the BriefcaseDb.
3071
3128
  * Throw an exception to stop the open.
@@ -3148,6 +3205,8 @@ export class BriefcaseDb extends IModelDb {
3148
3205
  }
3149
3206
  constructor(args) {
3150
3207
  super({ ...args, changeset: args.nativeDb.getCurrentChangeset() });
3208
+ // Native invokes this private callback dynamically through the object registered by IModelDb.
3209
+ void this.onChangesetConflict;
3151
3210
  this._openMode = args.openMode;
3152
3211
  this.briefcaseId = args.briefcaseId;
3153
3212
  this.makeLockControl();
@@ -3160,26 +3219,33 @@ export class BriefcaseDb extends IModelDb {
3160
3219
  wasChanges = nativeDb.hasPendingTxns();
3161
3220
  nativeDb.closeFile();
3162
3221
  };
3163
- const isSchemaSyncEnabled = await withBriefcaseDb(briefcase, async (db) => {
3164
- await SchemaSync.pull(db);
3165
- return db[_nativeDb].schemaSyncEnabled();
3166
- });
3167
- if (isSchemaSyncEnabled) {
3222
+ const push = async () => {
3223
+ if (wasChanges)
3224
+ await withBriefcaseDb(briefcase, async (db) => db.pushChanges({ ...briefcase, description, retainLocks: true }));
3225
+ };
3226
+ // Asked of the closed file, so an iModel without schema sync never gets opened for this.
3227
+ if (SchemaSync.isEnabled(briefcase)) {
3228
+ await withBriefcaseDb(briefcase, async (db) => SchemaSync.updateDbSchema(db));
3168
3229
  await SchemaSync.withLockedAccess(briefcase, { openMode: OpenMode.Readonly, operationName: "schema sync" }, async (syncAccess) => {
3169
3230
  const schemaSyncDbUri = syncAccess.getUri();
3170
3231
  executeUpgrade();
3232
+ // Overwriting advances the SchemaSync data version, so a no-op upgrade must not call it.
3233
+ if (!wasChanges)
3234
+ return;
3171
3235
  await withBriefcaseDb(briefcase, async (db) => {
3172
- db[_nativeDb].schemaSyncPush(schemaSyncDbUri);
3236
+ db[_nativeDb].schemaSyncOverwrite(schemaSyncDbUri);
3173
3237
  db[_nativeDb].saveChanges();
3174
3238
  });
3175
- syncAccess.synchronizeWithCloud();
3239
+ // Publish the sync db before the changeset while retaining both locks.
3240
+ syncAccess.closeDb();
3241
+ await syncAccess.container.uploadChanges();
3242
+ await push();
3176
3243
  });
3177
3244
  }
3178
3245
  else {
3179
3246
  executeUpgrade();
3247
+ await push();
3180
3248
  }
3181
- if (wasChanges)
3182
- await withBriefcaseDb(briefcase, async (db) => db.pushChanges({ ...briefcase, description, retainLocks: true }));
3183
3249
  }
3184
3250
  /** Upgrades the schemas in the iModel based on the current version of the software. Follows a sequence of operations -
3185
3251
  * * Acquires a schema lock to prevent other users from making any other changes while upgrade is happening
@@ -3199,6 +3265,22 @@ export class BriefcaseDb extends IModelDb {
3199
3265
  // - push changes
3200
3266
  // - release schema lock
3201
3267
  // good thing computers are fast. Fortunately upgrading should be rare (and the push time will dominate anyway.) Don't try to optimize any of this away.
3268
+ // schemaSyncOverwrite can discard unpushed imports, so hold the exclusive lock across both upgrades.
3269
+ if (SchemaSync.isEnabled(briefcase)) {
3270
+ try {
3271
+ await withBriefcaseDb(briefcase, async (db) => {
3272
+ if (!db.locks.isServerBased)
3273
+ throw new IModelError(DbResult.BE_SQLITE_ERROR, "Cannot upgrade schemas with SchemaSync without server-based locking");
3274
+ await db.acquireSchemaLock();
3275
+ });
3276
+ await this.doUpgrade(briefcase, { profile: ProfileOptions.Upgrade, schemaLockHeld: true }, "Upgraded profile");
3277
+ await this.doUpgrade(briefcase, { domain: DomainOptions.Upgrade, schemaLockHeld: true }, "Upgraded domain schemas");
3278
+ }
3279
+ finally {
3280
+ await withBriefcaseDb(briefcase, async (db) => db.locks[_releaseAllLocks]());
3281
+ }
3282
+ return;
3283
+ }
3202
3284
  try {
3203
3285
  await this.doUpgrade(briefcase, { profile: ProfileOptions.Upgrade }, "Upgraded profile");
3204
3286
  }
@@ -3263,6 +3345,7 @@ export class BriefcaseDb extends IModelDb {
3263
3345
  }
3264
3346
  // load all of the settings from workspaces
3265
3347
  await briefcaseDb.loadWorkspaceSettings();
3348
+ await briefcaseDb.initializeSharedElementReservations();
3266
3349
  if (openMode === OpenMode.ReadWrite && CodeService.createForIModel) {
3267
3350
  try {
3268
3351
  briefcaseDb._codeService = await CodeService.createForIModel(briefcaseDb);
@@ -3318,6 +3401,18 @@ export class BriefcaseDb extends IModelDb {
3318
3401
  return "foreign key";
3319
3402
  }
3320
3403
  };
3404
+ // `dgn_Domain` holds one bookkeeping row per BIS domain present in the briefcase. The row is
3405
+ // created automatically as soon as the domain's schema is imported, so merging a changeset
3406
+ // that registers a domain inserts a row that was just created locally. Both rows describe the
3407
+ // same domain and the incoming one is authoritative, so this duplicate insert is never fatal.
3408
+ // Only a primary key collision on an insert is benign - an update or delete whose "before"
3409
+ // values do not match (`DbConflictCause.Data`) describes a real divergence and must not be
3410
+ // silently discarded here.
3411
+ if (args.tableName === "dgn_Domain" && args.cause === DbConflictCause.Conflict && args.opcode === DbOpcode.Insert) {
3412
+ Logger.logWarning(category, `${interpretConflictCause(args.cause)} conflict on dgn_Domain - resolved by replacing the existing row with the incoming row`);
3413
+ args.dump();
3414
+ return DbConflictResolution.Replace;
3415
+ }
3321
3416
  if (args.cause === DbConflictCause.Data && !args.indirect) {
3322
3417
  /*
3323
3418
  * From SQLite Docs CHANGESET_DATA as the second argument
@@ -3486,10 +3581,12 @@ export class BriefcaseDb extends IModelDb {
3486
3581
  async pullChanges(arg) {
3487
3582
  await this.executeWritable(async () => {
3488
3583
  await BriefcaseManager.pullAndApplyChangesets(this, arg ?? {});
3489
- if (!this.skipSyncSchemasOnPullAndPush)
3490
- await SchemaSync.pull(this);
3584
+ SchemaSync.updateDbSchema(this);
3491
3585
  this.initializeIModelDb("pullMerge");
3492
3586
  });
3587
+ // If this pull enabled or disabled SchemaSync for this briefcase, its reservations must now be re-initialized
3588
+ if (this.reservations.isServerBased !== SchemaSync.isEnabled(this))
3589
+ await this.initializeSharedElementReservations();
3493
3590
  this.txns._onChangesPulled(this.changeset);
3494
3591
  }
3495
3592
  async enableChangesetStatTracking() {
@@ -3569,24 +3666,10 @@ export class BriefcaseDb extends IModelDb {
3569
3666
  if (nativeDb.hasPendingTxns()) {
3570
3667
  throw new IModelError(ChangeSetStatus.HasLocalChanges, "Cannot revert with pending txns");
3571
3668
  }
3572
- const skipSchemaSyncPull = async (func) => {
3573
- if (nativeDb.schemaSyncEnabled()) {
3574
- this._skipSyncSchemasOnPullAndPush = true;
3575
- try {
3576
- return await func();
3577
- }
3578
- finally {
3579
- this._skipSyncSchemasOnPullAndPush = undefined;
3580
- }
3581
- }
3582
- else {
3583
- return func();
3584
- }
3585
- };
3586
3669
  this.clearCaches();
3587
- await skipSchemaSyncPull(async () => this.pullChanges({ ...arg, toIndex: undefined }));
3670
+ await this.pullChanges({ ...arg, toIndex: undefined });
3588
3671
  await this.acquireSchemaLock();
3589
- if (nativeDb.schemaSyncEnabled()) {
3672
+ if (SchemaSync.isEnabled(this)) {
3590
3673
  arg.skipSchemaChanges = true;
3591
3674
  }
3592
3675
  // The native side enables file-based txns during revert. Restore the original setting afterward.
@@ -3607,7 +3690,7 @@ export class BriefcaseDb extends IModelDb {
3607
3690
  pushRetryDelay: arg.pushRetryDelay,
3608
3691
  retainLocks: arg.retainLocks,
3609
3692
  };
3610
- await skipSchemaSyncPull(async () => this.pushChanges(pushArgs));
3693
+ await this.pushChanges(pushArgs);
3611
3694
  this.clearCaches();
3612
3695
  }
3613
3696
  catch (err) {
@@ -3678,9 +3761,62 @@ export class BriefcaseDb extends IModelDb {
3678
3761
  await BriefcaseManager.pullMergePush(this, arg);
3679
3762
  this.initializeIModelDb("pullMerge");
3680
3763
  });
3764
+ // If this pull enabled or disabled SchemaSync for this briefcase, its reservations must now be re-initialized
3765
+ if (this.reservations.isServerBased !== SchemaSync.isEnabled(this))
3766
+ await this.initializeSharedElementReservations();
3681
3767
  this.txns._onChangesPushed(this.changeset);
3682
3768
  BriefcaseManager.deleteRebaseFolders(this);
3683
3769
  }
3770
+ /** Import schemas while allowing changes that move or delete data.
3771
+ *
3772
+ * Takes the exclusive schema lock, requires the briefcase to be at the timeline tip, imports, updates the sync db, and pushes the result.
3773
+ * @note The briefcase must have no local changes.
3774
+ * @see [[BriefcaseDb.upgradeSchemas]] (static) for upgrading the software's profile and domain schemas.
3775
+ * @alpha
3776
+ */
3777
+ async upgradeSchemas(schemaFileNames, arg) {
3778
+ return this.upgradeSchemasInternal(schemaFileNames, arg, (schemas, importOptions) => this[_nativeDb].importSchemas(schemas, importOptions));
3779
+ }
3780
+ /** The [[importSchemaStrings]] counterpart of [[upgradeSchemas]].
3781
+ * @alpha
3782
+ */
3783
+ async upgradeSchemaStrings(serializedXmlSchemas, arg) {
3784
+ return this.upgradeSchemasInternal(serializedXmlSchemas, arg, (schemas, importOptions) => this[_nativeDb].importXmlSchemas(schemas, importOptions));
3785
+ }
3786
+ async upgradeSchemasInternal(schemas, arg, nativeImportOp) {
3787
+ if (schemas.length === 0)
3788
+ return;
3789
+ this.assertCanImportSchemas();
3790
+ if (this[_nativeDb].hasUnsavedChanges() || this.txns.hasLocalChanges)
3791
+ throw new IModelError(ChangeSetStatus.HasLocalChanges, "Cannot upgrade schemas while there are local changes");
3792
+ if (SchemaSync.isEnabled(this) && !this.locks.isServerBased)
3793
+ throw new IModelError(DbResult.BE_SQLITE_ERROR, "Cannot upgrade schemas with SchemaSync without server-based locking");
3794
+ await this.acquireSchemaLock();
3795
+ await this.pullChanges({ accessToken: arg.accessToken });
3796
+ if (!SchemaSync.isEnabled(this)) {
3797
+ await this.importSchemasInternal(schemas, { ecSchemaXmlContext: arg.ecSchemaXmlContext }, nativeImportOp);
3798
+ await this.pushChanges(arg);
3799
+ return;
3800
+ }
3801
+ await SchemaSync.withLockedAccess(this, { openMode: OpenMode.Readonly, operationName: "schema upgrade" }, async (syncAccess) => {
3802
+ this.saveSchemaChanges();
3803
+ try {
3804
+ nativeImportOp(schemas, {
3805
+ schemaLockHeld: true,
3806
+ ecSchemaXmlContext: arg.ecSchemaXmlContext?.nativeContext,
3807
+ schemaSyncDbUri: syncAccess.getUri(),
3808
+ });
3809
+ }
3810
+ catch (err) {
3811
+ this.abandonSchemaChanges();
3812
+ throw new IModelError(err.errorNumber, err.message);
3813
+ }
3814
+ this.clearCaches();
3815
+ syncAccess.closeDb();
3816
+ await syncAccess.container.uploadChanges();
3817
+ await this.pushChanges(arg);
3818
+ });
3819
+ }
3684
3820
  close(options) {
3685
3821
  if (this.isBriefcase && this.isOpen && !this.isReadonly && this.txns.rebaser.inProgress()) {
3686
3822
  this[_nativeDb].abandonChanges();
@@ -3852,6 +3988,7 @@ export class SnapshotDb extends IModelDb {
3852
3988
  const key = CheckpointManager.getKey(checkpoint);
3853
3989
  const db = SnapshotDb.openFile(dbName, { key, container });
3854
3990
  await db.loadWorkspaceSettings();
3991
+ await db.initializeSharedElementReservations();
3855
3992
  return db;
3856
3993
  }
3857
3994
  /** @internal */