@itwin/core-backend 5.15.0-dev.2 → 5.15.0-dev.20

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 (272) hide show
  1. package/CHANGELOG.md +52 -1
  2. package/lib/cjs/BlobContainerService.d.ts +2 -0
  3. package/lib/cjs/BlobContainerService.d.ts.map +1 -1
  4. package/lib/cjs/BlobContainerService.js.map +1 -1
  5. package/lib/cjs/BriefcaseManager.d.ts +4 -3
  6. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  7. package/lib/cjs/BriefcaseManager.js +39 -9
  8. package/lib/cjs/BriefcaseManager.js.map +1 -1
  9. package/lib/cjs/ChangeUnifier.d.ts +82 -0
  10. package/lib/cjs/ChangeUnifier.d.ts.map +1 -0
  11. package/lib/cjs/ChangeUnifier.js +163 -0
  12. package/lib/cjs/ChangeUnifier.js.map +1 -0
  13. package/lib/cjs/ChangesetReader.d.ts +21 -2
  14. package/lib/cjs/ChangesetReader.d.ts.map +1 -1
  15. package/lib/cjs/ChangesetReader.js +37 -1
  16. package/lib/cjs/ChangesetReader.js.map +1 -1
  17. package/lib/cjs/ChangesetReaderTypes.d.ts +1 -1
  18. package/lib/cjs/ChangesetReaderTypes.js.map +1 -1
  19. package/lib/cjs/CloudSqlite.d.ts +15 -0
  20. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  21. package/lib/cjs/CloudSqlite.js.map +1 -1
  22. package/lib/cjs/ECDb.d.ts +1 -0
  23. package/lib/cjs/ECDb.d.ts.map +1 -1
  24. package/lib/cjs/ECDb.js +4 -1
  25. package/lib/cjs/ECDb.js.map +1 -1
  26. package/lib/cjs/ECSqlRowExecutor.d.ts +3 -3
  27. package/lib/cjs/ECSqlRowExecutor.d.ts.map +1 -1
  28. package/lib/cjs/ECSqlRowExecutor.js +2 -2
  29. package/lib/cjs/ECSqlRowExecutor.js.map +1 -1
  30. package/lib/cjs/ECSqlStatement.d.ts +5 -0
  31. package/lib/cjs/ECSqlStatement.d.ts.map +1 -1
  32. package/lib/cjs/ECSqlStatement.js +15 -2
  33. package/lib/cjs/ECSqlStatement.js.map +1 -1
  34. package/lib/cjs/ECSqlSyncReader.d.ts.map +1 -1
  35. package/lib/cjs/ECSqlSyncReader.js +2 -2
  36. package/lib/cjs/ECSqlSyncReader.js.map +1 -1
  37. package/lib/cjs/EditTxn.d.ts +61 -19
  38. package/lib/cjs/EditTxn.d.ts.map +1 -1
  39. package/lib/cjs/EditTxn.js +84 -29
  40. package/lib/cjs/EditTxn.js.map +1 -1
  41. package/lib/cjs/Element.d.ts +29 -2
  42. package/lib/cjs/Element.d.ts.map +1 -1
  43. package/lib/cjs/Element.js +38 -2
  44. package/lib/cjs/Element.js.map +1 -1
  45. package/lib/cjs/GeoCoordConfig.d.ts +1 -0
  46. package/lib/cjs/GeoCoordConfig.d.ts.map +1 -1
  47. package/lib/cjs/GeoCoordConfig.js +12 -8
  48. package/lib/cjs/GeoCoordConfig.js.map +1 -1
  49. package/lib/cjs/GeographicCRSServices.d.ts +50 -2
  50. package/lib/cjs/GeographicCRSServices.d.ts.map +1 -1
  51. package/lib/cjs/GeographicCRSServices.js +11 -1
  52. package/lib/cjs/GeographicCRSServices.js.map +1 -1
  53. package/lib/cjs/IModelDb.d.ts +22 -9
  54. package/lib/cjs/IModelDb.d.ts.map +1 -1
  55. package/lib/cjs/IModelDb.js +54 -12
  56. package/lib/cjs/IModelDb.js.map +1 -1
  57. package/lib/cjs/NativeHost.d.ts.map +1 -1
  58. package/lib/cjs/NativeHost.js +5 -1
  59. package/lib/cjs/NativeHost.js.map +1 -1
  60. package/lib/cjs/Relationship.d.ts +28 -0
  61. package/lib/cjs/Relationship.d.ts.map +1 -1
  62. package/lib/cjs/Relationship.js +78 -0
  63. package/lib/cjs/Relationship.js.map +1 -1
  64. package/lib/cjs/SchemaSync.d.ts.map +1 -1
  65. package/lib/cjs/SchemaSync.js +1 -0
  66. package/lib/cjs/SchemaSync.js.map +1 -1
  67. package/lib/cjs/TxnManager.d.ts +126 -89
  68. package/lib/cjs/TxnManager.d.ts.map +1 -1
  69. package/lib/cjs/TxnManager.js +114 -76
  70. package/lib/cjs/TxnManager.js.map +1 -1
  71. package/lib/cjs/ViewStateHydrator.d.ts.map +1 -1
  72. package/lib/cjs/ViewStateHydrator.js.map +1 -1
  73. package/lib/cjs/ViewStore.d.ts.map +1 -1
  74. package/lib/cjs/ViewStore.js +62 -19
  75. package/lib/cjs/ViewStore.js.map +1 -1
  76. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
  77. package/lib/cjs/annotations/LeaderGeometry.js +3 -0
  78. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
  79. package/lib/cjs/core-backend.d.ts +1 -0
  80. package/lib/cjs/core-backend.d.ts.map +1 -1
  81. package/lib/cjs/core-backend.js +1 -0
  82. package/lib/cjs/core-backend.js.map +1 -1
  83. package/lib/cjs/internal/BriefcaseUtils.d.ts +19 -0
  84. package/lib/cjs/internal/BriefcaseUtils.d.ts.map +1 -0
  85. package/lib/cjs/internal/BriefcaseUtils.js +65 -0
  86. package/lib/cjs/internal/BriefcaseUtils.js.map +1 -0
  87. package/lib/cjs/internal/QueryMetadataCache.d.ts +44 -0
  88. package/lib/cjs/internal/QueryMetadataCache.d.ts.map +1 -0
  89. package/lib/cjs/internal/QueryMetadataCache.js +107 -0
  90. package/lib/cjs/internal/QueryMetadataCache.js.map +1 -0
  91. package/lib/cjs/internal/Symbols.d.ts +9 -0
  92. package/lib/cjs/internal/Symbols.d.ts.map +1 -1
  93. package/lib/cjs/internal/Symbols.js +10 -1
  94. package/lib/cjs/internal/Symbols.js.map +1 -1
  95. package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  96. package/lib/cjs/internal/workspace/WorkspaceImpl.js +20 -6
  97. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  98. package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
  99. package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
  100. package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  101. package/lib/cjs/workspace/SettingsEditor.d.ts +4 -3
  102. package/lib/cjs/workspace/SettingsEditor.d.ts.map +1 -1
  103. package/lib/cjs/workspace/SettingsEditor.js +7 -5
  104. package/lib/cjs/workspace/SettingsEditor.js.map +1 -1
  105. package/lib/esm/BlobContainerService.d.ts +2 -0
  106. package/lib/esm/BlobContainerService.d.ts.map +1 -1
  107. package/lib/esm/BlobContainerService.js.map +1 -1
  108. package/lib/esm/BriefcaseManager.d.ts +4 -3
  109. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  110. package/lib/esm/BriefcaseManager.js +40 -10
  111. package/lib/esm/BriefcaseManager.js.map +1 -1
  112. package/lib/esm/ChangeUnifier.d.ts +82 -0
  113. package/lib/esm/ChangeUnifier.d.ts.map +1 -0
  114. package/lib/esm/ChangeUnifier.js +159 -0
  115. package/lib/esm/ChangeUnifier.js.map +1 -0
  116. package/lib/esm/ChangesetReader.d.ts +21 -2
  117. package/lib/esm/ChangesetReader.d.ts.map +1 -1
  118. package/lib/esm/ChangesetReader.js +38 -2
  119. package/lib/esm/ChangesetReader.js.map +1 -1
  120. package/lib/esm/ChangesetReaderTypes.d.ts +1 -1
  121. package/lib/esm/ChangesetReaderTypes.js.map +1 -1
  122. package/lib/esm/CloudSqlite.d.ts +15 -0
  123. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  124. package/lib/esm/CloudSqlite.js.map +1 -1
  125. package/lib/esm/ECDb.d.ts +1 -0
  126. package/lib/esm/ECDb.d.ts.map +1 -1
  127. package/lib/esm/ECDb.js +4 -1
  128. package/lib/esm/ECDb.js.map +1 -1
  129. package/lib/esm/ECSqlRowExecutor.d.ts +3 -3
  130. package/lib/esm/ECSqlRowExecutor.d.ts.map +1 -1
  131. package/lib/esm/ECSqlRowExecutor.js +2 -2
  132. package/lib/esm/ECSqlRowExecutor.js.map +1 -1
  133. package/lib/esm/ECSqlStatement.d.ts +5 -0
  134. package/lib/esm/ECSqlStatement.d.ts.map +1 -1
  135. package/lib/esm/ECSqlStatement.js +15 -2
  136. package/lib/esm/ECSqlStatement.js.map +1 -1
  137. package/lib/esm/ECSqlSyncReader.d.ts.map +1 -1
  138. package/lib/esm/ECSqlSyncReader.js +3 -3
  139. package/lib/esm/ECSqlSyncReader.js.map +1 -1
  140. package/lib/esm/EditTxn.d.ts +61 -19
  141. package/lib/esm/EditTxn.d.ts.map +1 -1
  142. package/lib/esm/EditTxn.js +85 -30
  143. package/lib/esm/EditTxn.js.map +1 -1
  144. package/lib/esm/Element.d.ts +29 -2
  145. package/lib/esm/Element.d.ts.map +1 -1
  146. package/lib/esm/Element.js +41 -5
  147. package/lib/esm/Element.js.map +1 -1
  148. package/lib/esm/GeoCoordConfig.d.ts +1 -0
  149. package/lib/esm/GeoCoordConfig.d.ts.map +1 -1
  150. package/lib/esm/GeoCoordConfig.js +12 -8
  151. package/lib/esm/GeoCoordConfig.js.map +1 -1
  152. package/lib/esm/GeographicCRSServices.d.ts +50 -2
  153. package/lib/esm/GeographicCRSServices.d.ts.map +1 -1
  154. package/lib/esm/GeographicCRSServices.js +10 -1
  155. package/lib/esm/GeographicCRSServices.js.map +1 -1
  156. package/lib/esm/IModelDb.d.ts +22 -9
  157. package/lib/esm/IModelDb.d.ts.map +1 -1
  158. package/lib/esm/IModelDb.js +56 -14
  159. package/lib/esm/IModelDb.js.map +1 -1
  160. package/lib/esm/NativeHost.d.ts.map +1 -1
  161. package/lib/esm/NativeHost.js +5 -1
  162. package/lib/esm/NativeHost.js.map +1 -1
  163. package/lib/esm/Relationship.d.ts +28 -0
  164. package/lib/esm/Relationship.d.ts.map +1 -1
  165. package/lib/esm/Relationship.js +78 -0
  166. package/lib/esm/Relationship.js.map +1 -1
  167. package/lib/esm/SchemaSync.d.ts.map +1 -1
  168. package/lib/esm/SchemaSync.js +1 -0
  169. package/lib/esm/SchemaSync.js.map +1 -1
  170. package/lib/esm/TxnManager.d.ts +126 -89
  171. package/lib/esm/TxnManager.d.ts.map +1 -1
  172. package/lib/esm/TxnManager.js +116 -78
  173. package/lib/esm/TxnManager.js.map +1 -1
  174. package/lib/esm/ViewStateHydrator.d.ts.map +1 -1
  175. package/lib/esm/ViewStateHydrator.js.map +1 -1
  176. package/lib/esm/ViewStore.d.ts.map +1 -1
  177. package/lib/esm/ViewStore.js +62 -19
  178. package/lib/esm/ViewStore.js.map +1 -1
  179. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
  180. package/lib/esm/annotations/LeaderGeometry.js +3 -0
  181. package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
  182. package/lib/esm/core-backend.d.ts +1 -0
  183. package/lib/esm/core-backend.d.ts.map +1 -1
  184. package/lib/esm/core-backend.js +1 -0
  185. package/lib/esm/core-backend.js.map +1 -1
  186. package/lib/esm/internal/BriefcaseUtils.d.ts +19 -0
  187. package/lib/esm/internal/BriefcaseUtils.d.ts.map +1 -0
  188. package/lib/esm/internal/BriefcaseUtils.js +61 -0
  189. package/lib/esm/internal/BriefcaseUtils.js.map +1 -0
  190. package/lib/esm/internal/QueryMetadataCache.d.ts +44 -0
  191. package/lib/esm/internal/QueryMetadataCache.d.ts.map +1 -0
  192. package/lib/esm/internal/QueryMetadataCache.js +103 -0
  193. package/lib/esm/internal/QueryMetadataCache.js.map +1 -0
  194. package/lib/esm/internal/Symbols.d.ts +9 -0
  195. package/lib/esm/internal/Symbols.d.ts.map +1 -1
  196. package/lib/esm/internal/Symbols.js +9 -0
  197. package/lib/esm/internal/Symbols.js.map +1 -1
  198. package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  199. package/lib/esm/internal/workspace/WorkspaceImpl.js +20 -6
  200. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  201. package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
  202. package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
  203. package/lib/esm/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  204. package/lib/esm/test/annotations/LeaderGeometry.test.js +15 -1
  205. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
  206. package/lib/esm/test/ecdb/ConcurrentQuery.test.js +144 -30
  207. package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -1
  208. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js +140 -0
  209. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js.map +1 -1
  210. package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts +2 -0
  211. package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts.map +1 -0
  212. package/lib/esm/test/ecdb/QueryMetadataCache.test.js +630 -0
  213. package/lib/esm/test/ecdb/QueryMetadataCache.test.js.map +1 -0
  214. package/lib/esm/test/element/DeleteDefinitionElements.test.js +403 -249
  215. package/lib/esm/test/element/DeleteDefinitionElements.test.js.map +1 -1
  216. package/lib/esm/test/element/ElementSubModelInsert.test.d.ts +2 -0
  217. package/lib/esm/test/element/ElementSubModelInsert.test.d.ts.map +1 -0
  218. package/lib/esm/test/element/ElementSubModelInsert.test.js +183 -0
  219. package/lib/esm/test/element/ElementSubModelInsert.test.js.map +1 -0
  220. package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts +2 -0
  221. package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts.map +1 -0
  222. package/lib/esm/test/element/RelationshipBatchLookup.test.js +202 -0
  223. package/lib/esm/test/element/RelationshipBatchLookup.test.js.map +1 -0
  224. package/lib/esm/test/hubaccess/BriefcaseManager.test.js +187 -1
  225. package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
  226. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts +2 -0
  227. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts.map +1 -0
  228. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js +142 -0
  229. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js.map +1 -0
  230. package/lib/esm/test/imodel/IModelGeolocation.test.js +13 -11
  231. package/lib/esm/test/imodel/IModelGeolocation.test.js.map +1 -1
  232. package/lib/esm/test/imodel/IModelProps.test.d.ts +2 -0
  233. package/lib/esm/test/imodel/IModelProps.test.d.ts.map +1 -0
  234. package/lib/esm/test/imodel/IModelProps.test.js +411 -0
  235. package/lib/esm/test/imodel/IModelProps.test.js.map +1 -0
  236. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts +2 -0
  237. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts.map +1 -0
  238. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js +240 -0
  239. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js.map +1 -0
  240. package/lib/esm/test/schema/SchemaViewValidation.test.js +2 -8
  241. package/lib/esm/test/schema/SchemaViewValidation.test.js.map +1 -1
  242. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts +2 -0
  243. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts.map +1 -0
  244. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js +159 -0
  245. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js.map +1 -0
  246. package/lib/esm/test/standalone/ChangeUnifier.test.d.ts +2 -0
  247. package/lib/esm/test/standalone/ChangeUnifier.test.d.ts.map +1 -0
  248. package/lib/esm/test/standalone/ChangeUnifier.test.js +732 -0
  249. package/lib/esm/test/standalone/ChangeUnifier.test.js.map +1 -0
  250. package/lib/esm/test/standalone/DeleteElements.test.js +962 -83
  251. package/lib/esm/test/standalone/DeleteElements.test.js.map +1 -1
  252. package/lib/esm/test/standalone/EditTxn.test.js +72 -1
  253. package/lib/esm/test/standalone/EditTxn.test.js.map +1 -1
  254. package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts +2 -0
  255. package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts.map +1 -0
  256. package/lib/esm/test/standalone/GeoCoordConfig.test.js +158 -0
  257. package/lib/esm/test/standalone/GeoCoordConfig.test.js.map +1 -0
  258. package/lib/esm/test/standalone/SessionApplyIndirect.test.d.ts +2 -0
  259. package/lib/esm/test/standalone/SessionApplyIndirect.test.d.ts.map +1 -0
  260. package/lib/esm/test/standalone/SessionApplyIndirect.test.js +211 -0
  261. package/lib/esm/test/standalone/SessionApplyIndirect.test.js.map +1 -0
  262. package/lib/esm/test/standalone/ViewStoreDb.test.js +53 -0
  263. package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
  264. package/lib/esm/test/workspace/SettingsContainers.test.d.ts +2 -0
  265. package/lib/esm/test/workspace/SettingsContainers.test.d.ts.map +1 -0
  266. package/lib/esm/test/workspace/SettingsContainers.test.js +95 -0
  267. package/lib/esm/test/workspace/SettingsContainers.test.js.map +1 -0
  268. package/lib/esm/workspace/SettingsEditor.d.ts +4 -3
  269. package/lib/esm/workspace/SettingsEditor.d.ts.map +1 -1
  270. package/lib/esm/workspace/SettingsEditor.js +7 -5
  271. package/lib/esm/workspace/SettingsEditor.js.map +1 -1
  272. package/package.json +18 -18
@@ -0,0 +1,159 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ /** @packageDocumentation
6
+ * @module ECDb
7
+ */
8
+ import { IModelStatus } from "@itwin/core-bentley";
9
+ import { IModelError } from "@itwin/core-common";
10
+ import { PropertyFilter } from "./ChangesetReaderTypes";
11
+ import { IModelNative } from "./internal/NativePlatform";
12
+ import { _appendToNativeUnifier, _readerOptions } from "./internal/Symbols";
13
+ /**
14
+ * Merges the per-table rows of one or more [ChangesetReader]($backend)s into complete EC instances in native code, with memory
15
+ * bounded by spilling to temporary files. Readers are consumed when the unifier is created.
16
+ * See [ChangeUnifier]($docs/learning/backend/ChangesetReader.md#changeunifier--native-merging-with-bounded-memory) for usage and
17
+ * how it differs from [PartialChangeUnifier]($backend).
18
+ * @beta
19
+ */
20
+ export class ChangeUnifier {
21
+ static defaultBatchSize = 1000;
22
+ _nativeUnifier;
23
+ _batchSize;
24
+ _hasReader = false;
25
+ _propFilter = PropertyFilter.All;
26
+ _rowOptions;
27
+ /** Instances fetched by the most recent native `step()` call. */
28
+ _batch = [];
29
+ /** Index of the next instance to return from `_batch`. */
30
+ _batchIndex = 0;
31
+ _exhausted = false;
32
+ _disposed = false;
33
+ // Private — callers use static factory methods.
34
+ constructor(args) {
35
+ const batchSize = args.batchSize ?? ChangeUnifier.defaultBatchSize;
36
+ if (!Number.isInteger(batchSize) || batchSize <= 0)
37
+ throw new IModelError(IModelStatus.BadArg, "ChangeUnifier: batchSize must be a positive integer.");
38
+ if (args.memoryBudgetBytes !== undefined && (!Number.isSafeInteger(args.memoryBudgetBytes) || args.memoryBudgetBytes < 0))
39
+ throw new IModelError(IModelStatus.BadArg, "ChangeUnifier: memoryBudgetBytes must be a non-negative integer.");
40
+ this._batchSize = batchSize;
41
+ const options = {};
42
+ if (args.propNames !== undefined)
43
+ options.propNames = [...args.propNames];
44
+ if (args.memoryBudgetBytes !== undefined)
45
+ options.memoryBudgetBytes = args.memoryBudgetBytes;
46
+ this._nativeUnifier = new IModelNative.platform.ChangeUnifier(options);
47
+ }
48
+ /**
49
+ * Create a unifier that merges all rows of `reader`. The reader is drained by this call and can be disposed afterward.
50
+ * @param reader A reader that has not been stepped yet.
51
+ * @param args Options controlling projection, memory use and batching.
52
+ * @throws [[IModelError]] if `args` are invalid, if `reader` has already been stepped or consumed, or if the native layer fails.
53
+ * @beta
54
+ */
55
+ static fromReader(reader, args) {
56
+ return ChangeUnifier.fromReaders([reader], args);
57
+ }
58
+ /**
59
+ * Create a unifier that merges all rows of several readers, e.g. one per changeset. Where property values conflict, later readers win.
60
+ * Each reader is requested and drained before the next, so `readers` can be a generator that opens and disposes them.
61
+ * @param readers Readers of the same iModel, opened with the same `propFilter` and equivalent `rowOptions`, that have not been stepped yet.
62
+ * @param args Options controlling projection, memory use and batching.
63
+ * @throws [[IModelError]] if `args` are invalid, if a reader has already been stepped or consumed, if the readers' `propFilter`
64
+ * or `rowOptions` differ, or if the native layer fails (for example when readers read different iModels). Readers drained
65
+ * before the error remain consumed.
66
+ * @beta
67
+ */
68
+ static fromReaders(readers, args) {
69
+ const unifier = new ChangeUnifier(args ?? {});
70
+ try {
71
+ for (const reader of readers)
72
+ unifier.appendReader(reader);
73
+ }
74
+ catch (e) {
75
+ unifier.closeAfterError();
76
+ throw e;
77
+ }
78
+ return unifier;
79
+ }
80
+ /**
81
+ * Iterate over the merged EC change instances, sorted by (root ECClassId, ECInstanceId, stage).
82
+ * Instances are fetched from the native layer lazily, [[ChangeUnifierArgs.batchSize]] at a time.
83
+ * Each instance is returned only once: iterating again, or calling `instances()` again, continues after the last instance returned.
84
+ * @throws [[IModelError]] if the unifier has been disposed, or if the native layer fails.
85
+ * @beta
86
+ */
87
+ *instances() {
88
+ for (let instance = this.nextInstance(); instance !== undefined; instance = this.nextInstance())
89
+ yield instance;
90
+ }
91
+ /**
92
+ * Release native resources, including any temporary spill files.
93
+ * @beta
94
+ */
95
+ [Symbol.dispose]() {
96
+ if (this._disposed)
97
+ return;
98
+ this._disposed = true;
99
+ this._batch = [];
100
+ this._batchIndex = 0;
101
+ this._nativeUnifier.close();
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Private helpers
105
+ // ---------------------------------------------------------------------------
106
+ appendReader(reader) {
107
+ const { propFilter, rowOptions } = reader[_readerOptions];
108
+ if (!this._hasReader) {
109
+ this._propFilter = propFilter;
110
+ // Copied: the reader keeps the caller's object, which may change before later readers are compared with it.
111
+ this._rowOptions = rowOptions === undefined ? undefined : { ...rowOptions };
112
+ this._hasReader = true;
113
+ }
114
+ else if (propFilter !== this._propFilter || !areEquivalentRowOptions(rowOptions, this._rowOptions)) {
115
+ throw new IModelError(IModelStatus.BadArg, "ChangeUnifier: all readers must be opened with the same propFilter and rowOptions.");
116
+ }
117
+ reader[_appendToNativeUnifier](this._nativeUnifier);
118
+ }
119
+ closeAfterError() {
120
+ this._disposed = true;
121
+ try {
122
+ this._nativeUnifier.close();
123
+ }
124
+ catch {
125
+ // The error that caused the unifier to be closed is more relevant to the caller than a failure to close it.
126
+ }
127
+ }
128
+ nextInstance() {
129
+ if (this._disposed)
130
+ throw new IModelError(IModelStatus.BadRequest, "ChangeUnifier: cannot iterate instances after the unifier has been disposed.");
131
+ if (this._batchIndex >= this._batch.length) {
132
+ if (this._exhausted)
133
+ return undefined;
134
+ this._batch = this._nativeUnifier.step(this._batchSize);
135
+ this._batchIndex = 0;
136
+ if (this._batch.length === 0) {
137
+ this._exhausted = true;
138
+ return undefined;
139
+ }
140
+ }
141
+ return this.toChangeInstance(this._batch[this._batchIndex++]);
142
+ }
143
+ /** Complete the native metadata with the options of the readers, in place, so the instance satisfies [[ChangeMeta]]. */
144
+ toChangeInstance(instance) {
145
+ const meta = instance.$meta;
146
+ meta.propFilter = this._propFilter;
147
+ if (this._rowOptions !== undefined)
148
+ meta.rowOptions = this._rowOptions;
149
+ return instance;
150
+ }
151
+ }
152
+ /** `true` if both options format rows identically, taking the defaults of omitted options into account. */
153
+ function areEquivalentRowOptions(lhs, rhs) {
154
+ return (lhs?.abbreviateBlobs ?? true) === (rhs?.abbreviateBlobs ?? true)
155
+ && (lhs?.classIdsToClassNames ?? false) === (rhs?.classIdsToClassNames ?? false)
156
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
157
+ && (lhs?.useJsName ?? false) === (rhs?.useJsName ?? false);
158
+ }
159
+ //# sourceMappingURL=ChangeUnifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangeUnifier.js","sourceRoot":"","sources":["../../src/ChangeUnifier.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module ECDb\r\n */\r\nimport { IModelStatus } from \"@itwin/core-bentley\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { IModelJsNative } from \"@bentley/imodeljs-native\";\r\nimport { ChangesetReader } from \"./ChangesetReader\";\r\nimport { ChangeInstance, ChangeMeta, PropertyFilter, RowFormatOptions } from \"./ChangesetReaderTypes\";\r\nimport { IModelNative } from \"./internal/NativePlatform\";\r\nimport { _appendToNativeUnifier, _readerOptions } from \"./internal/Symbols\";\r\n\r\n/**\r\n * Arguments for [[ChangeUnifier.fromReader]] and [[ChangeUnifier.fromReaders]].\r\n * @beta\r\n */\r\nexport interface ChangeUnifierArgs {\r\n /** Names of the properties to keep, e.g. `[\"FederationGuid\", \"Model\", \"Source\", \"Target\"]`. `ECInstanceId` and `ECClassId` are always kept.\r\n * All other properties are dropped before the merged instances are stored, which reduces memory use.\r\n * `undefined` or empty keeps all properties returned by the readers.\r\n */\r\n propNames?: string[];\r\n /** Number of bytes of merged instance data held in memory before sorted runs are spilled to temporary files.\r\n * Must be a non-negative integer. `0` means never spill. Defaults to 64 MiB.\r\n */\r\n memoryBudgetBytes?: number;\r\n /** Number of instances fetched from the native layer at a time while iterating [[ChangeUnifier.instances]].\r\n * Must be a positive integer. Defaults to 1000. A batch ends early once it holds 16 MiB of strings and binary data,\r\n * so large instances (e.g. with unabbreviated geometry streams) do not pile up in memory.\r\n */\r\n batchSize?: number;\r\n}\r\n\r\n/**\r\n * Merges the per-table rows of one or more [ChangesetReader]($backend)s into complete EC instances in native code, with memory\r\n * bounded by spilling to temporary files. Readers are consumed when the unifier is created.\r\n * See [ChangeUnifier]($docs/learning/backend/ChangesetReader.md#changeunifier--native-merging-with-bounded-memory) for usage and\r\n * how it differs from [PartialChangeUnifier]($backend).\r\n * @beta\r\n */\r\nexport class ChangeUnifier implements Disposable {\r\n private static readonly defaultBatchSize = 1000;\r\n private readonly _nativeUnifier: IModelJsNative.ChangeUnifier;\r\n private readonly _batchSize: number;\r\n private _hasReader = false;\r\n private _propFilter = PropertyFilter.All;\r\n private _rowOptions?: RowFormatOptions;\r\n /** Instances fetched by the most recent native `step()` call. */\r\n private _batch: IModelJsNative.UnifiedChangeInstance[] = [];\r\n /** Index of the next instance to return from `_batch`. */\r\n private _batchIndex = 0;\r\n private _exhausted = false;\r\n private _disposed = false;\r\n\r\n // Private — callers use static factory methods.\r\n private constructor(args: ChangeUnifierArgs) {\r\n const batchSize = args.batchSize ?? ChangeUnifier.defaultBatchSize;\r\n if (!Number.isInteger(batchSize) || batchSize <= 0)\r\n throw new IModelError(IModelStatus.BadArg, \"ChangeUnifier: batchSize must be a positive integer.\");\r\n if (args.memoryBudgetBytes !== undefined && (!Number.isSafeInteger(args.memoryBudgetBytes) || args.memoryBudgetBytes < 0))\r\n throw new IModelError(IModelStatus.BadArg, \"ChangeUnifier: memoryBudgetBytes must be a non-negative integer.\");\r\n\r\n this._batchSize = batchSize;\r\n const options: IModelJsNative.ChangeUnifierOptions = {};\r\n if (args.propNames !== undefined)\r\n options.propNames = [...args.propNames];\r\n if (args.memoryBudgetBytes !== undefined)\r\n options.memoryBudgetBytes = args.memoryBudgetBytes;\r\n this._nativeUnifier = new IModelNative.platform.ChangeUnifier(options);\r\n }\r\n\r\n /**\r\n * Create a unifier that merges all rows of `reader`. The reader is drained by this call and can be disposed afterward.\r\n * @param reader A reader that has not been stepped yet.\r\n * @param args Options controlling projection, memory use and batching.\r\n * @throws [[IModelError]] if `args` are invalid, if `reader` has already been stepped or consumed, or if the native layer fails.\r\n * @beta\r\n */\r\n public static fromReader(reader: ChangesetReader, args?: ChangeUnifierArgs): ChangeUnifier {\r\n return ChangeUnifier.fromReaders([reader], args);\r\n }\r\n\r\n /**\r\n * Create a unifier that merges all rows of several readers, e.g. one per changeset. Where property values conflict, later readers win.\r\n * Each reader is requested and drained before the next, so `readers` can be a generator that opens and disposes them.\r\n * @param readers Readers of the same iModel, opened with the same `propFilter` and equivalent `rowOptions`, that have not been stepped yet.\r\n * @param args Options controlling projection, memory use and batching.\r\n * @throws [[IModelError]] if `args` are invalid, if a reader has already been stepped or consumed, if the readers' `propFilter`\r\n * or `rowOptions` differ, or if the native layer fails (for example when readers read different iModels). Readers drained\r\n * before the error remain consumed.\r\n * @beta\r\n */\r\n public static fromReaders(readers: Iterable<ChangesetReader>, args?: ChangeUnifierArgs): ChangeUnifier {\r\n const unifier = new ChangeUnifier(args ?? {});\r\n try {\r\n for (const reader of readers)\r\n unifier.appendReader(reader);\r\n } catch (e) {\r\n unifier.closeAfterError();\r\n throw e;\r\n }\r\n return unifier;\r\n }\r\n\r\n /**\r\n * Iterate over the merged EC change instances, sorted by (root ECClassId, ECInstanceId, stage).\r\n * Instances are fetched from the native layer lazily, [[ChangeUnifierArgs.batchSize]] at a time.\r\n * Each instance is returned only once: iterating again, or calling `instances()` again, continues after the last instance returned.\r\n * @throws [[IModelError]] if the unifier has been disposed, or if the native layer fails.\r\n * @beta\r\n */\r\n public *instances(): IterableIterator<ChangeInstance> {\r\n for (let instance = this.nextInstance(); instance !== undefined; instance = this.nextInstance())\r\n yield instance;\r\n }\r\n\r\n /**\r\n * Release native resources, including any temporary spill files.\r\n * @beta\r\n */\r\n public [Symbol.dispose](): void {\r\n if (this._disposed)\r\n return;\r\n this._disposed = true;\r\n this._batch = [];\r\n this._batchIndex = 0;\r\n this._nativeUnifier.close();\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Private helpers\r\n // ---------------------------------------------------------------------------\r\n\r\n private appendReader(reader: ChangesetReader): void {\r\n const { propFilter, rowOptions } = reader[_readerOptions];\r\n if (!this._hasReader) {\r\n this._propFilter = propFilter;\r\n // Copied: the reader keeps the caller's object, which may change before later readers are compared with it.\r\n this._rowOptions = rowOptions === undefined ? undefined : { ...rowOptions };\r\n this._hasReader = true;\r\n } else if (propFilter !== this._propFilter || !areEquivalentRowOptions(rowOptions, this._rowOptions)) {\r\n throw new IModelError(IModelStatus.BadArg, \"ChangeUnifier: all readers must be opened with the same propFilter and rowOptions.\");\r\n }\r\n reader[_appendToNativeUnifier](this._nativeUnifier);\r\n }\r\n\r\n private closeAfterError(): void {\r\n this._disposed = true;\r\n try {\r\n this._nativeUnifier.close();\r\n } catch {\r\n // The error that caused the unifier to be closed is more relevant to the caller than a failure to close it.\r\n }\r\n }\r\n\r\n private nextInstance(): ChangeInstance | undefined {\r\n if (this._disposed)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangeUnifier: cannot iterate instances after the unifier has been disposed.\");\r\n if (this._batchIndex >= this._batch.length) {\r\n if (this._exhausted)\r\n return undefined;\r\n this._batch = this._nativeUnifier.step(this._batchSize);\r\n this._batchIndex = 0;\r\n if (this._batch.length === 0) {\r\n this._exhausted = true;\r\n return undefined;\r\n }\r\n }\r\n return this.toChangeInstance(this._batch[this._batchIndex++]);\r\n }\r\n\r\n /** Complete the native metadata with the options of the readers, in place, so the instance satisfies [[ChangeMeta]]. */\r\n private toChangeInstance(instance: IModelJsNative.UnifiedChangeInstance): ChangeInstance {\r\n const meta = instance.$meta as ChangeMeta;\r\n meta.propFilter = this._propFilter;\r\n if (this._rowOptions !== undefined)\r\n meta.rowOptions = this._rowOptions;\r\n return instance as ChangeInstance;\r\n }\r\n}\r\n\r\n/** `true` if both options format rows identically, taking the defaults of omitted options into account. */\r\nfunction areEquivalentRowOptions(lhs: RowFormatOptions | undefined, rhs: RowFormatOptions | undefined): boolean {\r\n return (lhs?.abbreviateBlobs ?? true) === (rhs?.abbreviateBlobs ?? true)\r\n && (lhs?.classIdsToClassNames ?? false) === (rhs?.classIdsToClassNames ?? false)\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n && (lhs?.useJsName ?? false) === (rhs?.useJsName ?? false);\r\n}\r\n"]}
@@ -3,7 +3,9 @@
3
3
  */
4
4
  import { Id64String } from "@itwin/core-bentley";
5
5
  import { IModelDb } from "./IModelDb";
6
- import { ChangeInstance, ChangesetReaderArgs, ChangeSource } from "./ChangesetReaderTypes";
6
+ import { _appendToNativeUnifier, _readerOptions } from "./internal/Symbols";
7
+ import { IModelJsNative } from "@bentley/imodeljs-native";
8
+ import { ChangeInstance, ChangesetReaderArgs, ChangeSource, PropertyFilter, RowFormatOptions } from "./ChangesetReaderTypes";
7
9
  import { AnyDb, SqliteChangeOp } from "./SqliteChangesetReader";
8
10
  /**
9
11
  * Reads EC-typed changeset data natively from a changeset file, changeset group,
@@ -17,7 +19,9 @@ import { AnyDb, SqliteChangeOp } from "./SqliteChangesetReader";
17
19
  * and both [[inserted]] and [[deleted]] remain `undefined`.
18
20
  *
19
21
  * @note The native reader operates one SQLite table-row at a time. Multi-table EC
20
- * instances must be merged using [PartialChangeUnifier]($backend).
22
+ * instances must be merged using [PartialChangeUnifier]($backend), or natively using
23
+ * [ChangeUnifier]($backend). A reader passed to [ChangeUnifier]($backend) is consumed by it:
24
+ * afterwards [[step]] returns `false` and the reader can no longer be configured, so do not step it.
21
25
  * @beta
22
26
  */
23
27
  export declare class ChangesetReader implements Disposable, ChangeSource {
@@ -39,6 +43,8 @@ export declare class ChangesetReader implements Disposable, ChangeSource {
39
43
  private _cachedInserted;
40
44
  /** Cached result of the `deleted` getter for the current row. `undefined` when not yet computed or not applicable. */
41
45
  private _cachedDeleted;
46
+ /** `true` once the native reader has been drained by a [ChangeUnifier]($backend). */
47
+ private _consumedByUnifier;
42
48
  /** The db used for EC schema resolution. */
43
49
  readonly db: AnyDb;
44
50
  /** Returns the active cached row, throwing if no row is current.
@@ -180,6 +186,17 @@ export declare class ChangesetReader implements Disposable, ChangeSource {
180
186
  /** Throws if [[step]] has already been called, preventing filter/mode changes mid-iteration.
181
187
  * @internal */
182
188
  private throwIfAlreadyStepped;
189
+ /** The property filter and row options this reader was opened with, used by [ChangeUnifier]($backend) to fill `$meta`.
190
+ * @internal */
191
+ get [_readerOptions](): {
192
+ readonly propFilter: PropertyFilter;
193
+ readonly rowOptions: RowFormatOptions | undefined;
194
+ };
195
+ /** Drain all remaining rows of this reader into `nativeUnifier`, natively, honoring the filters and strict mode configured on this reader.
196
+ * Afterwards the reader is consumed: [[step]] returns `false` and configuration methods throw. The reader is marked consumed even if draining fails.
197
+ * @throws [[IModelError]] if the reader has already been stepped successfully or has already been consumed, or if the native layer fails.
198
+ * @internal */
199
+ [_appendToNativeUnifier](nativeUnifier: IModelJsNative.ChangeUnifier): void;
183
200
  /** Handle errors that occur while auto closing the reader if there is also an error while opening the reader */
184
201
  private handleCloseErrorWhileOpening;
185
202
  /**
@@ -279,6 +296,8 @@ export declare class ChangesetReader implements Disposable, ChangeSource {
279
296
  /**
280
297
  * Advance to the next change.
281
298
  * @returns `true` while positioned on a valid change; `false` when the stream is exhausted.
299
+ * Always returns `false` once the reader has been consumed by a [ChangeUnifier]($backend), whose instances
300
+ * already include every row of this reader - do not step a reader after passing it to a [ChangeUnifier]($backend).
282
301
  * @throws if the native layer encounters an error while reading or decoding
283
302
  * the next change.
284
303
  * @beta
@@ -1 +1 @@
1
- {"version":3,"file":"ChangesetReader.d.ts","sourceRoot":"","sources":["../../src/ChangesetReader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChangesetReader.d.ts","sourceRoot":"","sources":["../../src/ChangesetReader.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@
8
8
  import { DbOpcode, IModelStatus } from "@itwin/core-bentley";
9
9
  import { IModelError } from "@itwin/core-common";
10
10
  import { IModelNative } from "./internal/NativePlatform";
11
- import { _nativeDb } from "./internal/Symbols";
11
+ import { _appendToNativeUnifier, _nativeDb, _readerOptions } from "./internal/Symbols";
12
12
  import { PropertyFilter } from "./ChangesetReaderTypes";
13
13
  // ---------------------------------------------------------------------------
14
14
  // ChangesetReader
@@ -25,7 +25,9 @@ import { PropertyFilter } from "./ChangesetReaderTypes";
25
25
  * and both [[inserted]] and [[deleted]] remain `undefined`.
26
26
  *
27
27
  * @note The native reader operates one SQLite table-row at a time. Multi-table EC
28
- * instances must be merged using [PartialChangeUnifier]($backend).
28
+ * instances must be merged using [PartialChangeUnifier]($backend), or natively using
29
+ * [ChangeUnifier]($backend). A reader passed to [ChangeUnifier]($backend) is consumed by it:
30
+ * afterwards [[step]] returns `false` and the reader can no longer be configured, so do not step it.
29
31
  * @beta
30
32
  */
31
33
  export class ChangesetReader {
@@ -48,6 +50,8 @@ export class ChangesetReader {
48
50
  _cachedInserted = undefined;
49
51
  /** Cached result of the `deleted` getter for the current row. `undefined` when not yet computed or not applicable. */
50
52
  _cachedDeleted = undefined;
53
+ /** `true` once the native reader has been drained by a [ChangeUnifier]($backend). */
54
+ _consumedByUnifier = false;
51
55
  /** The db used for EC schema resolution. */
52
56
  db;
53
57
  /** Returns the active cached row, throwing if no row is current.
@@ -309,9 +313,37 @@ export class ChangesetReader {
309
313
  /** Throws if [[step]] has already been called, preventing filter/mode changes mid-iteration.
310
314
  * @internal */
311
315
  throwIfAlreadyStepped() {
316
+ if (this._consumedByUnifier)
317
+ throw new IModelError(IModelStatus.BadRequest, "ChangesetReader: the reader has been consumed by a ChangeUnifier and can no longer be configured.");
312
318
  if (this._changeIndex > 0)
313
319
  throw new IModelError(IModelStatus.BadRequest, "ChangesetReader: filters and strict mode and batch size must be configured before the first call to step().");
314
320
  }
321
+ /** The property filter and row options this reader was opened with, used by [ChangeUnifier]($backend) to fill `$meta`.
322
+ * @internal */
323
+ get [_readerOptions]() {
324
+ return { propFilter: this._propFilter, rowOptions: this._rowOptions };
325
+ }
326
+ /** Drain all remaining rows of this reader into `nativeUnifier`, natively, honoring the filters and strict mode configured on this reader.
327
+ * Afterwards the reader is consumed: [[step]] returns `false` and configuration methods throw. The reader is marked consumed even if draining fails.
328
+ * @throws [[IModelError]] if the reader has already been stepped successfully or has already been consumed, or if the native layer fails.
329
+ * @internal */
330
+ [_appendToNativeUnifier](nativeUnifier) {
331
+ if (this._consumedByUnifier)
332
+ throw new IModelError(IModelStatus.BadRequest, "ChangesetReader: the reader has already been consumed by a ChangeUnifier.");
333
+ if (this._changeIndex > 0)
334
+ throw new IModelError(IModelStatus.BadRequest, "ChangesetReader: a reader that has already been stepped cannot be passed to a ChangeUnifier.");
335
+ const nativeRowOpts = this._rowOptions ? this.toNativeRowOptions(this._rowOptions) : {};
336
+ try {
337
+ nativeUnifier.appendFrom(this._nativeReader, nativeRowOpts);
338
+ }
339
+ finally {
340
+ this._consumedByUnifier = true;
341
+ this._cache = [];
342
+ this._cacheIndex = 0;
343
+ this._cachedInserted = undefined;
344
+ this._cachedDeleted = undefined;
345
+ }
346
+ }
315
347
  /** Handle errors that occur while auto closing the reader if there is also an error while opening the reader */
316
348
  handleCloseErrorWhileOpening(e) {
317
349
  try {
@@ -459,6 +491,8 @@ export class ChangesetReader {
459
491
  /**
460
492
  * Advance to the next change.
461
493
  * @returns `true` while positioned on a valid change; `false` when the stream is exhausted.
494
+ * Always returns `false` once the reader has been consumed by a [ChangeUnifier]($backend), whose instances
495
+ * already include every row of this reader - do not step a reader after passing it to a [ChangeUnifier]($backend).
462
496
  * @throws if the native layer encounters an error while reading or decoding
463
497
  * the next change.
464
498
  * @beta
@@ -466,6 +500,8 @@ export class ChangesetReader {
466
500
  step() {
467
501
  this._cachedInserted = undefined;
468
502
  this._cachedDeleted = undefined;
503
+ if (this._consumedByUnifier)
504
+ return false;
469
505
  if (this._cacheIndex + 1 < this._cache.length) {
470
506
  // Still have rows in cache — advance the pointer
471
507
  this._cacheIndex++;
@@ -1 +1 @@
1
- {"version":3,"file":"ChangesetReader.js","sourceRoot":"","sources":["../../src/ChangesetReader.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAc,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAqD,cAAc,EAAoB,MAAM,wBAAwB,CAAC;AAI7H,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,eAAe;IAClB,MAAM,CAAU,4BAA4B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,SAAS;IACjE,aAAa,GAAmC,IAAI,YAAY,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;IAC7G,+EAA+E;IACvE,WAAW,CAAoB;IAC/B,kBAAkB,CAAU;IAC5B,WAAW,GAAmB,cAAc,CAAC,GAAG,CAAC;IACjD,YAAY,GAAG,CAAC,CAAC;IACzB,yDAAyD;IACjD,MAAM,GAAsC,EAAE,CAAC;IACvD;;;;OAIG;IACK,WAAW,GAAG,CAAC,CAAC;IACxB,uHAAuH;IAC/G,eAAe,GAA+B,SAAS,CAAC;IAChE,sHAAsH;IAC9G,cAAc,GAA+B,SAAS,CAAC;IAE/D,4CAA4C;IAC5B,EAAE,CAAQ;IAE1B;mBACe;IACf,IAAY,WAAW;QACrB,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM;YACxC,MAAM,IAAI,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,sDAAsD,CAAC,CAAC;QACzG,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED;mBACe;IACf,IAAY,UAAU;QACpB,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC;QAC1E,IAAI,IAAI,CAAC,WAAW,KAAK,cAAc,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,KAAK,cAAc,CAAC,yBAAyB;YAAE,OAAO,GAAG,CAAC;QACjI,IAAI,IAAI,CAAC,WAAW,KAAK,cAAc,CAAC,cAAc;YAAE,OAAO,EAAE,CAAC,CAAC,+GAA+G;QAClL,IAAI,IAAI,CAAC,WAAW,EAAE,eAAe,KAAK,KAAK;YAAE,OAAO,CAAC,CAAC;QAC1D,OAAO,EAAE,CAAC,CAAC,qBAAqB;IAClC,CAAC;IAED;;;;;OAKG;IACH,IAAW,SAAS,KAAc,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAE/E;;;;;OAKG;IACH,IAAW,SAAS,KAAa,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAE9E;;;;;OAKG;IACH,IAAW,gBAAgB,KAAc,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAE7F;;;;;;;;OAQG;IACH,IAAW,QAAQ;QACjB,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,eAAe,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9F,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS;YACxB,OAAO,SAAS,CAAC;QACnB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,eAAe,GAAG;YAC7B,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI;YACrB,KAAK,EAAE;gBACL,EAAE;gBACF,MAAM,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAChC,aAAa,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;gBAClC,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG;gBAC9B,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,sBAAsB,EAAE,GAAG,CAAC,SAAS,CAAC,sBAAsB;gBAC5D,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,gBAAgB,EAAE,GAAG,CAAC,QAAQ,CAAC,gBAAgB;aAChD;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,IAAW,OAAO;QAChB,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,cAAc,CAAC;QAClE,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9F,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS;YACxB,OAAO,SAAS,CAAC;QACnB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG;YAC5B,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI;YACrB,KAAK,EAAE;gBACL,EAAE;gBACF,MAAM,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAChC,aAAa,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;gBAClC,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG;gBAC9B,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,sBAAsB,EAAE,GAAG,CAAC,SAAS,CAAC,sBAAsB;gBAC5D,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,gBAAgB,EAAE,GAAG,CAAC,QAAQ,CAAC,gBAAgB;aAChD;SACF,CAAC,CAAC;IACL,CAAC;IAED,gDAAgD;IAChD,YAAoB,EAAS;QAC3B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED;mBACe;IACP,kBAAkB,CAAC,IAAsB;QAC/C,OAAO;YACL,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;YAC/C,4DAA4D;YAC5D,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,yBAAyB;IACzB,8EAA8E;IAE9E;;;;;;;;;OASG;IACI,MAAM,CAAC,QAAQ,CAAC,IAAyD;QAC9E,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC;QACzD,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC7G,CAAC;QACD,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,SAAS,CAAC,IAAiG;QACvH,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;YAClC,MAAM,IAAI,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,gDAAgD,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC;QACzD,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACrL,CAAC;QACD,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,gBAAgB,CAC5B,IAA0H;QAE1H,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC;QACzD,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,sBAAsB,IAAI,KAAK,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC7M,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,mBAAmB,CAC/B,IAAwF;QAExF,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC;QACzD,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC1K,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,OAAO,CACnB,IAA2G;QAE3G,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,cAAc,CAAC,GAAG,CAAC;QACzD,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC1K,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;mBACe;IACP,qBAAqB;QAC3B,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC;YACvB,MAAM,IAAI,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,6GAA6G,CAAC,CAAC;IAClK,CAAC;IAED,gHAAgH;IACxG,4BAA4B,CAAC,CAAU;QAC7C,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,6CAA6C,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;;kEAEtE,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gDACvF,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,YAAY,CAAC,SAAiB;QACnC,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;YAChD,MAAM,IAAI,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,wDAAwD,CAAC,CAAC;QACvG,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;IACtC,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;;;;;OAOG;IACI,mBAAmB,CAAC,UAAuB;QAChD,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,CAAC;IAED;;;;;;OAMG;IACI,gBAAgB,CAAC,GAAwB;QAC9C,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IAED;;;;;;;OAOG;IACI,mBAAmB,CAAC,UAAuB;QAChD,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,CAAC;IAED;;;;OAIG;IACI,qBAAqB;QAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,qBAAqB,EAAE,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACI,kBAAkB;QACvB,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACI,qBAAqB;QAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,qBAAqB,EAAE,CAAC;IAC7C,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E;;;;;;;;;;;;;;;;;OAiBG;IACI,gBAAgB;QACrB,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,CAAC;IACxC,CAAC;IAED;;;;;;;;;;;;;OAaG;IACI,iBAAiB;QACtB,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;IACzC,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;;;;OAMG;IACI,IAAI;QACT,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC9C,iDAAiD;YACjD,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,+DAA+D;YAC/D,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YACtE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,IAAW,EAAE;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC;QAChD,OAAO,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU;YAC5C,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACtC,CAAC,CAAC,SAAS,CAAC;IAClB,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;;;;;OAOG;IACI,KAAK;QACV,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED;;;;;OAKG;IACI,CAAC,MAAM,CAAC,OAAO,CAAC;QACrB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module ECDb\r\n */\r\nimport { DbOpcode, Id64String, IModelStatus } from \"@itwin/core-bentley\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { IModelDb } from \"./IModelDb\";\r\nimport { IModelNative } from \"./internal/NativePlatform\";\r\nimport { _nativeDb } from \"./internal/Symbols\";\r\nimport { IModelJsNative } from \"@bentley/imodeljs-native\";\r\nimport { ChangeInstance, ChangesetReaderArgs, ChangeSource, PropertyFilter, RowFormatOptions } from \"./ChangesetReaderTypes\";\r\nimport { AnyDb, SqliteChangeOp } from \"./SqliteChangesetReader\";\r\n\r\n\r\n// ---------------------------------------------------------------------------\r\n// ChangesetReader\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Reads EC-typed changeset data natively from a changeset file, changeset group,\r\n * in-memory transaction, or local un-pushed changes.\r\n *\r\n * Implements [ChangeSource]($backend) so rows can be fed directly into\r\n * [PartialChangeUnifier]($backend) to merge partial (per-table) instances into\r\n * complete EC instances.\r\n *\r\n * When the current row is a non-EC internal SQLite table, [[isECTable]] is `false`\r\n * and both [[inserted]] and [[deleted]] remain `undefined`.\r\n *\r\n * @note The native reader operates one SQLite table-row at a time. Multi-table EC\r\n * instances must be merged using [PartialChangeUnifier]($backend).\r\n * @beta\r\n */\r\nexport class ChangesetReader implements Disposable, ChangeSource {\r\n private static readonly defaultSpillThresholdInBytes = 50 * 1024 * 1024; // 50 MiB\r\n private readonly _nativeReader: IModelJsNative.ChangesetReader = new IModelNative.platform.ChangesetReader();\r\n // Internal options — keep ECClassId as raw Id so the unifier can use it as-is.\r\n private _rowOptions?: RowFormatOptions;\r\n private _batchSizeOverride?: number;\r\n private _propFilter: PropertyFilter = PropertyFilter.All;\r\n private _changeIndex = 0;\r\n /** Rows fetched in the most recent native batch call. */\r\n private _cache: IModelJsNative.ChangesetRowData[] = [];\r\n /**\r\n * Index of the current row in `_cache`.\r\n * Equals `_cache.length` (i.e. out-of-bounds) when no row is active:\r\n * initial state, after exhaustion, or after close().\r\n */\r\n private _cacheIndex = 0;\r\n /** Cached result of the `inserted` getter for the current row. `undefined` when not yet computed or not applicable. */\r\n private _cachedInserted: ChangeInstance | undefined = undefined;\r\n /** Cached result of the `deleted` getter for the current row. `undefined` when not yet computed or not applicable. */\r\n private _cachedDeleted: ChangeInstance | undefined = undefined;\r\n\r\n /** The db used for EC schema resolution. */\r\n public readonly db: AnyDb;\r\n\r\n /** Returns the active cached row, throwing if no row is current.\r\n * @internal */\r\n private get _currentRow(): IModelJsNative.ChangesetRowData {\r\n if (this._cacheIndex >= this._cache.length)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: no current row — call step() first.\");\r\n return this._cache[this._cacheIndex];\r\n }\r\n\r\n /** Returns the batch size to use for native step() calls based on the active property filter.\r\n * @internal */\r\n private get _batchSize(): number {\r\n if (this._batchSizeOverride !== undefined) return this._batchSizeOverride;\r\n if (this._propFilter === PropertyFilter.InstanceKey || this._propFilter === PropertyFilter.InstanceKeyAndIdentifiers) return 100;\r\n if (this._propFilter === PropertyFilter.BisCoreElement) return 20; // because BisCore Element class do not contain any GeomStream property so abbreviateBlobs is not relevant here\r\n if (this._rowOptions?.abbreviateBlobs === false) return 5;\r\n return 10; // PropertyFilter.All\r\n }\r\n\r\n /**\r\n * `true` when the current row belongs to an EC-mapped table.\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get isECTable(): boolean { return this._currentRow.metadata.isECTable; }\r\n\r\n /**\r\n * Name of the SQLite table for the current change row.\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get tableName(): string { return this._currentRow.metadata.tableName; }\r\n\r\n /**\r\n * `true` when the current change was applied indirectly\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get isIndirectChange(): boolean { return this._currentRow.metadata.isIndirectChange; }\r\n\r\n /**\r\n * Post-change (inserted or updated-new) EC instance, computed lazily after each [[step]] call.\r\n * `undefined` when the current row is a Delete or a non-EC table row or [[step]] returned false.\r\n * For UPDATE,inserted instances indicate the new state of the instance after the change has been applied and\r\n * deleted instances indicate the old state of the instance before the change has been applied.\r\n * For INSERT, inserted instances indicate the new state of the instance after the change has been applied and deleted instances are undefined.\r\n * For DELETE, deleted instances indicate the old state of the instance before the change has been applied and inserted instances are undefined.\r\n * @beta\r\n */\r\n public get inserted(): ChangeInstance | undefined {\r\n if (this._cachedInserted !== undefined) return this._cachedInserted;\r\n const row = this._cacheIndex < this._cache.length ? this._cache[this._cacheIndex] : undefined;\r\n if (!row || !row.newValues)\r\n return undefined;\r\n const op = this.op;\r\n return (this._cachedInserted = {\r\n ...row.newValues.data,\r\n $meta: {\r\n op,\r\n tables: [row.metadata.tableName],\r\n changeIndexes: [this._changeIndex],\r\n stage: \"New\",\r\n instanceKey: row.newValues.key,\r\n propFilter: this._propFilter,\r\n changeFetchedPropNames: row.newValues.changeFetchedPropNames,\r\n rowOptions: this._rowOptions,\r\n isIndirectChange: row.metadata.isIndirectChange,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Pre-change (deleted or updated-old) EC instance, computed lazily after each [[step]] call.\r\n * `undefined` when the current row is an Insert or a non-EC table row or [[step]] returned false.\r\n * @beta\r\n */\r\n public get deleted(): ChangeInstance | undefined {\r\n if (this._cachedDeleted !== undefined) return this._cachedDeleted;\r\n const row = this._cacheIndex < this._cache.length ? this._cache[this._cacheIndex] : undefined;\r\n if (!row || !row.oldValues)\r\n return undefined;\r\n const op = this.op;\r\n return (this._cachedDeleted = {\r\n ...row.oldValues.data,\r\n $meta: {\r\n op,\r\n tables: [row.metadata.tableName],\r\n changeIndexes: [this._changeIndex],\r\n stage: \"Old\",\r\n instanceKey: row.oldValues.key,\r\n propFilter: this._propFilter,\r\n changeFetchedPropNames: row.oldValues.changeFetchedPropNames,\r\n rowOptions: this._rowOptions,\r\n isIndirectChange: row.metadata.isIndirectChange,\r\n },\r\n });\r\n }\r\n\r\n // Private — callers use static factory methods.\r\n private constructor(db: AnyDb) {\r\n this.db = db;\r\n }\r\n\r\n /** Map public RowFormatOptions to the native adaptor options.\r\n * @internal */\r\n private toNativeRowOptions(opts: RowFormatOptions): IModelJsNative.ECSqlRowAdaptorOptions {\r\n return {\r\n abbreviateBlobs: opts.abbreviateBlobs,\r\n classIdsToClassNames: opts.classIdsToClassNames,\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n useJsName: opts.useJsName,\r\n };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Static factory methods\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Open a changeset file from disk.\r\n * @param args.fileName Absolute path to the changeset file.\r\n * @param args.db Database at or after the changeset's ending state, used for schema resolution.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @throws if the native layer fails to open the file.\r\n * @beta\r\n */\r\n public static openFile(args: { readonly fileName: string } & ChangesetReaderArgs): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openFile(args.db[_nativeDb], args.fileName, args.invert ?? false, reader._propFilter);\r\n }\r\n catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Concatenate multiple changeset files and read them as a single logical stream.\r\n * @param args.changesetFiles Ordered list of changeset file paths.\r\n * @param args.db Database with schema at or ahead of the last changeset.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of the changeset data in the change group exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for processing large changeset groups under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if `changesetFiles` is empty, or if the native layer fails to open\r\n * the group.\r\n * @beta\r\n */\r\n public static openGroup(args: { readonly changesetFiles: string[], spillThresholdInBytes?: number } & ChangesetReaderArgs): ChangesetReader {\r\n if (args.changesetFiles.length === 0)\r\n throw new IModelError(IModelStatus.BadArg, \"changesetFiles must contain at least one file.\");\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openGroup(args.db[_nativeDb], args.changesetFiles, args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n }\r\n catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Read pending (not yet pushed) local changes from an open IModelDb.\r\n * @param args.db Must be an [IModelDb]($backend) (not [ECDb]($backend)).\r\n * @param args.includeInMemoryChanges Also include in-memory (not yet saved to disk) changes.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of all local un-pushed saved changes exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for iModels with large local change backlogs under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if the native layer\r\n * fails to open the local changes.\r\n * @beta\r\n */\r\n public static openLocalChanges(\r\n args: Omit<ChangesetReaderArgs, \"db\"> & { db: IModelDb; includeInMemoryChanges?: boolean, spillThresholdInBytes?: number },\r\n ): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openLocalChanges(args.db[_nativeDb], args.includeInMemoryChanges ?? false, args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n } catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Read the in-memory (not yet saved to disk) changes of an open IModelDb.\r\n * @param args.db Must be an [IModelDb]($backend).\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of the in-memory (unsaved) change data exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for large in-memory transactions under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if the native layer encounters an error while opening the in-memory changes.\r\n * @beta\r\n */\r\n public static openInMemoryChanges(\r\n args: Omit<ChangesetReaderArgs, \"db\"> & { db: IModelDb, spillThresholdInBytes?: number },\r\n ): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openInMemoryChanges(args.db[_nativeDb], args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n } catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Read a single saved transaction by its id.\r\n * @param args.db Must be an [IModelDb]($backend) ([ECDb]($backend) does not support transactions).\r\n * @param args.txnId The id of the saved transaction to read.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of the transaction's change data exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for large transactions under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if `txnId` is not found, or\r\n * the native layer fails to open the transaction data.\r\n * @beta\r\n */\r\n public static openTxn(\r\n args: Omit<ChangesetReaderArgs, \"db\"> & { db: IModelDb; txnId: Id64String, spillThresholdInBytes?: number },\r\n ): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openTxn(args.db[_nativeDb], args.txnId, args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n } catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /** Throws if [[step]] has already been called, preventing filter/mode changes mid-iteration.\r\n * @internal */\r\n private throwIfAlreadyStepped(): void {\r\n if (this._changeIndex > 0)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: filters and strict mode and batch size must be configured before the first call to step().\");\r\n }\r\n\r\n /** Handle errors that occur while auto closing the reader if there is also an error while opening the reader */\r\n private handleCloseErrorWhileOpening(e: unknown): void {\r\n try {\r\n this.close();\r\n } catch (closeError) {\r\n throw new IModelError(IModelStatus.BadArg, `Failed to open ChangesetReader with error ${e instanceof Error ? e.message : String(e)}.\r\n Additionally, that triggered an automatic closure of the reader\r\n releasing native resources which also failed with failure ${closeError instanceof Error ? closeError.message : String(closeError)}.\r\n Check native error logs for more details.`);\r\n }\r\n }\r\n\r\n /**\r\n * Set the number of rows to fetch and cache while stepping.\r\n * This is an advanced option that can be used to tune performance for large changesets.\r\n * Increasing the batch size improves throughput at the cost of higher peak memory; decreasing it keeps memory consumption lower.\r\n *\r\n * Default batch sizes when `setBatchSize` is not called:\r\n * - `InstanceKey` or `InstanceKeyAndIdentifiers` filter: **100**.\r\n * - `BisCoreElement` filter (any `abbreviateBlobs` setting): **20**.\r\n * - `All` filter, `abbreviateBlobs: false`: **5**.\r\n * - `All` filter (blobs abbreviated or unset): **10**.\r\n *\r\n * @param batchSize Number of rows to fetch and cache while stepping. Must be a positive integer.\r\n * @throws [[IModelError]] if [[step]] has already been called successfully, or if `batchSize` is not a positive integer.\r\n * @beta\r\n */\r\n public setBatchSize(batchSize: number): void {\r\n this.throwIfAlreadyStepped();\r\n if (!Number.isInteger(batchSize) || batchSize <= 0)\r\n throw new IModelError(IModelStatus.BadArg, \"ChangesetReader: batchSize must be a positive integer.\");\r\n this._batchSizeOverride = batchSize;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Filtering\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Restrict iteration to changes from the named SQLite tables.\r\n * That means the rows for changes from other tables will be skipped entirely and won't be visible through the reader.\r\n * @param tableNames SQLite table names to include.\r\n * Note: Table names must be provided in the correct case for proper filtering.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.\r\n * @beta\r\n */\r\n public setTableNameFilters(tableNames: Set<string>): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.setTableNameFilters(Array.from(tableNames));\r\n }\r\n\r\n /**\r\n * Restrict iteration to changes with the given operation types.\r\n * That means the rows for changes with other operation types will be skipped entirely and won't be visible through the reader.\r\n * @param ops Operations to include.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.\r\n * @beta\r\n */\r\n public setOpCodeFilters(ops: Set<SqliteChangeOp>): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.setOpCodeFilters(Array.from(ops));\r\n }\r\n\r\n /**\r\n * Restrict iteration to changes for the given EC class names.\r\n * That means the rows for changes from other EC classes will be skipped entirely and won't be visible through the reader.\r\n * @param classNames EC class names to include. The classNames should be in the full name format(i.e. \"SchemaName:ClassName\").\r\n * Note: Schema names and class names must be provided in the correct case for proper filtering. Derived classes are not automatically included, so they must be specified explicitly if needed.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.\r\n * @beta\r\n */\r\n public setClassNameFilters(classNames: Set<string>): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.setClassNameFilters(Array.from(classNames));\r\n }\r\n\r\n /**\r\n * Remove the table-name filters\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public clearTableNameFilters(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.clearTableNameFilters();\r\n }\r\n\r\n /**\r\n * Remove the op-code filters\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public clearOpCodeFilters(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.clearOpCodeFilters();\r\n }\r\n\r\n /**\r\n * Remove the class-name filters\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public clearClassNameFilters(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.clearClassNameFilters();\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Strict mode\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Enable strict mode on the reader.\r\n *\r\n * Strict mode affects how the reader handles a **column-count mismatch** between a change\r\n * record and the corresponding live database table. Such a mismatch can occur when columns\r\n * have been added to a table after the changeset was created.\r\n *\r\n * When strict mode is **enabled**: if the number of columns recorded in a change row differs\r\n * from the number of columns currently present in the live table, the reader throws an error\r\n * instead of processing that row.\r\n *\r\n * Use strict mode when you need to be certain that every change row is interpreted against\r\n * exactly the schema that was in effect when the changeset was written.\r\n *\r\n * @see [[disableStrictMode]] — the default (lenient) behaviour.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public enableStrictMode(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.enableStrictMode();\r\n }\r\n\r\n /**\r\n * Disable strict mode on the reader (this is the default).\r\n *\r\n * When strict mode is **disabled**: if the number of columns recorded in a change row differs\r\n * from the number of columns currently present in the live table, the reader takes the\r\n * **minimum** of the two column counts and proceeds normally with that subset. This is safe\r\n * because SQLite only ever appends new columns at the end of a table and never removes them —\r\n * so older change records simply lack the trailing columns that were added later, and those\r\n * missing columns are silently ignored.\r\n *\r\n * @see [[enableStrictMode]] — throw on column-count mismatches instead.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public disableStrictMode(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.disableStrictMode();\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Iteration\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Advance to the next change.\r\n * @returns `true` while positioned on a valid change; `false` when the stream is exhausted.\r\n * @throws if the native layer encounters an error while reading or decoding\r\n * the next change.\r\n * @beta\r\n */\r\n public step(): boolean {\r\n this._cachedInserted = undefined;\r\n this._cachedDeleted = undefined;\r\n if (this._cacheIndex + 1 < this._cache.length) {\r\n // Still have rows in cache — advance the pointer\r\n this._cacheIndex++;\r\n } else {\r\n // Cache empty or fully consumed — fetch next batch from native\r\n const nativeRowOpts = this._rowOptions ? this.toNativeRowOptions(this._rowOptions) : {};\r\n this._cache = this._nativeReader.step(this._batchSize, nativeRowOpts);\r\n this._cacheIndex = 0;\r\n if (this._cache.length === 0) return false;\r\n }\r\n this._changeIndex++;\r\n return true;\r\n }\r\n\r\n /**\r\n * SQLite opcode of the current change.\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get op(): SqliteChangeOp {\r\n const opCode = this._currentRow.metadata.opCode;\r\n return opCode === DbOpcode.Insert ? \"Inserted\"\r\n : opCode === DbOpcode.Update ? \"Updated\"\r\n : \"Deleted\";\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Lifecycle\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Close the reader and release all native resources.\r\n *\r\n * @throws if the native layer encounters an error during cleanup. Native resources\r\n * are not fully released when this throws — check the native error\r\n * logs for details.\r\n * @beta\r\n */\r\n public close(): void {\r\n this._changeIndex = 0;\r\n this._cache = [];\r\n this._cacheIndex = 0;\r\n this._cachedInserted = undefined;\r\n this._cachedDeleted = undefined;\r\n this._nativeReader.close();\r\n }\r\n\r\n /**\r\n * Implements the `Disposable` contract — delegates to [[close]].\r\n *\r\n * @throws if the native layer fails to release its resources (re-thrown from [[close]]).\r\n * @beta\r\n */\r\n public [Symbol.dispose](): void {\r\n this.close();\r\n }\r\n}\r\n\r\n"]}
1
+ {"version":3,"file":"ChangesetReader.js","sourceRoot":"","sources":["../../src/ChangesetReader.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module ECDb\r\n */\r\nimport { DbOpcode, Id64String, IModelStatus } from \"@itwin/core-bentley\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { IModelDb } from \"./IModelDb\";\r\nimport { IModelNative } from \"./internal/NativePlatform\";\r\nimport { _appendToNativeUnifier, _nativeDb, _readerOptions } from \"./internal/Symbols\";\r\nimport { IModelJsNative } from \"@bentley/imodeljs-native\";\r\nimport { ChangeInstance, ChangesetReaderArgs, ChangeSource, PropertyFilter, RowFormatOptions } from \"./ChangesetReaderTypes\";\r\nimport { AnyDb, SqliteChangeOp } from \"./SqliteChangesetReader\";\r\n\r\n\r\n// ---------------------------------------------------------------------------\r\n// ChangesetReader\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Reads EC-typed changeset data natively from a changeset file, changeset group,\r\n * in-memory transaction, or local un-pushed changes.\r\n *\r\n * Implements [ChangeSource]($backend) so rows can be fed directly into\r\n * [PartialChangeUnifier]($backend) to merge partial (per-table) instances into\r\n * complete EC instances.\r\n *\r\n * When the current row is a non-EC internal SQLite table, [[isECTable]] is `false`\r\n * and both [[inserted]] and [[deleted]] remain `undefined`.\r\n *\r\n * @note The native reader operates one SQLite table-row at a time. Multi-table EC\r\n * instances must be merged using [PartialChangeUnifier]($backend), or natively using\r\n * [ChangeUnifier]($backend). A reader passed to [ChangeUnifier]($backend) is consumed by it:\r\n * afterwards [[step]] returns `false` and the reader can no longer be configured, so do not step it.\r\n * @beta\r\n */\r\nexport class ChangesetReader implements Disposable, ChangeSource {\r\n private static readonly defaultSpillThresholdInBytes = 50 * 1024 * 1024; // 50 MiB\r\n private readonly _nativeReader: IModelJsNative.ChangesetReader = new IModelNative.platform.ChangesetReader();\r\n // Internal options — keep ECClassId as raw Id so the unifier can use it as-is.\r\n private _rowOptions?: RowFormatOptions;\r\n private _batchSizeOverride?: number;\r\n private _propFilter: PropertyFilter = PropertyFilter.All;\r\n private _changeIndex = 0;\r\n /** Rows fetched in the most recent native batch call. */\r\n private _cache: IModelJsNative.ChangesetRowData[] = [];\r\n /**\r\n * Index of the current row in `_cache`.\r\n * Equals `_cache.length` (i.e. out-of-bounds) when no row is active:\r\n * initial state, after exhaustion, or after close().\r\n */\r\n private _cacheIndex = 0;\r\n /** Cached result of the `inserted` getter for the current row. `undefined` when not yet computed or not applicable. */\r\n private _cachedInserted: ChangeInstance | undefined = undefined;\r\n /** Cached result of the `deleted` getter for the current row. `undefined` when not yet computed or not applicable. */\r\n private _cachedDeleted: ChangeInstance | undefined = undefined;\r\n /** `true` once the native reader has been drained by a [ChangeUnifier]($backend). */\r\n private _consumedByUnifier = false;\r\n\r\n /** The db used for EC schema resolution. */\r\n public readonly db: AnyDb;\r\n\r\n /** Returns the active cached row, throwing if no row is current.\r\n * @internal */\r\n private get _currentRow(): IModelJsNative.ChangesetRowData {\r\n if (this._cacheIndex >= this._cache.length)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: no current row — call step() first.\");\r\n return this._cache[this._cacheIndex];\r\n }\r\n\r\n /** Returns the batch size to use for native step() calls based on the active property filter.\r\n * @internal */\r\n private get _batchSize(): number {\r\n if (this._batchSizeOverride !== undefined) return this._batchSizeOverride;\r\n if (this._propFilter === PropertyFilter.InstanceKey || this._propFilter === PropertyFilter.InstanceKeyAndIdentifiers) return 100;\r\n if (this._propFilter === PropertyFilter.BisCoreElement) return 20; // because BisCore Element class do not contain any GeomStream property so abbreviateBlobs is not relevant here\r\n if (this._rowOptions?.abbreviateBlobs === false) return 5;\r\n return 10; // PropertyFilter.All\r\n }\r\n\r\n /**\r\n * `true` when the current row belongs to an EC-mapped table.\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get isECTable(): boolean { return this._currentRow.metadata.isECTable; }\r\n\r\n /**\r\n * Name of the SQLite table for the current change row.\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get tableName(): string { return this._currentRow.metadata.tableName; }\r\n\r\n /**\r\n * `true` when the current change was applied indirectly\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get isIndirectChange(): boolean { return this._currentRow.metadata.isIndirectChange; }\r\n\r\n /**\r\n * Post-change (inserted or updated-new) EC instance, computed lazily after each [[step]] call.\r\n * `undefined` when the current row is a Delete or a non-EC table row or [[step]] returned false.\r\n * For UPDATE,inserted instances indicate the new state of the instance after the change has been applied and\r\n * deleted instances indicate the old state of the instance before the change has been applied.\r\n * For INSERT, inserted instances indicate the new state of the instance after the change has been applied and deleted instances are undefined.\r\n * For DELETE, deleted instances indicate the old state of the instance before the change has been applied and inserted instances are undefined.\r\n * @beta\r\n */\r\n public get inserted(): ChangeInstance | undefined {\r\n if (this._cachedInserted !== undefined) return this._cachedInserted;\r\n const row = this._cacheIndex < this._cache.length ? this._cache[this._cacheIndex] : undefined;\r\n if (!row || !row.newValues)\r\n return undefined;\r\n const op = this.op;\r\n return (this._cachedInserted = {\r\n ...row.newValues.data,\r\n $meta: {\r\n op,\r\n tables: [row.metadata.tableName],\r\n changeIndexes: [this._changeIndex],\r\n stage: \"New\",\r\n instanceKey: row.newValues.key,\r\n propFilter: this._propFilter,\r\n changeFetchedPropNames: row.newValues.changeFetchedPropNames,\r\n rowOptions: this._rowOptions,\r\n isIndirectChange: row.metadata.isIndirectChange,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Pre-change (deleted or updated-old) EC instance, computed lazily after each [[step]] call.\r\n * `undefined` when the current row is an Insert or a non-EC table row or [[step]] returned false.\r\n * @beta\r\n */\r\n public get deleted(): ChangeInstance | undefined {\r\n if (this._cachedDeleted !== undefined) return this._cachedDeleted;\r\n const row = this._cacheIndex < this._cache.length ? this._cache[this._cacheIndex] : undefined;\r\n if (!row || !row.oldValues)\r\n return undefined;\r\n const op = this.op;\r\n return (this._cachedDeleted = {\r\n ...row.oldValues.data,\r\n $meta: {\r\n op,\r\n tables: [row.metadata.tableName],\r\n changeIndexes: [this._changeIndex],\r\n stage: \"Old\",\r\n instanceKey: row.oldValues.key,\r\n propFilter: this._propFilter,\r\n changeFetchedPropNames: row.oldValues.changeFetchedPropNames,\r\n rowOptions: this._rowOptions,\r\n isIndirectChange: row.metadata.isIndirectChange,\r\n },\r\n });\r\n }\r\n\r\n // Private — callers use static factory methods.\r\n private constructor(db: AnyDb) {\r\n this.db = db;\r\n }\r\n\r\n /** Map public RowFormatOptions to the native adaptor options.\r\n * @internal */\r\n private toNativeRowOptions(opts: RowFormatOptions): IModelJsNative.ECSqlRowAdaptorOptions {\r\n return {\r\n abbreviateBlobs: opts.abbreviateBlobs,\r\n classIdsToClassNames: opts.classIdsToClassNames,\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n useJsName: opts.useJsName,\r\n };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Static factory methods\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Open a changeset file from disk.\r\n * @param args.fileName Absolute path to the changeset file.\r\n * @param args.db Database at or after the changeset's ending state, used for schema resolution.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @throws if the native layer fails to open the file.\r\n * @beta\r\n */\r\n public static openFile(args: { readonly fileName: string } & ChangesetReaderArgs): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openFile(args.db[_nativeDb], args.fileName, args.invert ?? false, reader._propFilter);\r\n }\r\n catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Concatenate multiple changeset files and read them as a single logical stream.\r\n * @param args.changesetFiles Ordered list of changeset file paths.\r\n * @param args.db Database with schema at or ahead of the last changeset.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of the changeset data in the change group exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for processing large changeset groups under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if `changesetFiles` is empty, or if the native layer fails to open\r\n * the group.\r\n * @beta\r\n */\r\n public static openGroup(args: { readonly changesetFiles: string[], spillThresholdInBytes?: number } & ChangesetReaderArgs): ChangesetReader {\r\n if (args.changesetFiles.length === 0)\r\n throw new IModelError(IModelStatus.BadArg, \"changesetFiles must contain at least one file.\");\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openGroup(args.db[_nativeDb], args.changesetFiles, args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n }\r\n catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Read pending (not yet pushed) local changes from an open IModelDb.\r\n * @param args.db Must be an [IModelDb]($backend) (not [ECDb]($backend)).\r\n * @param args.includeInMemoryChanges Also include in-memory (not yet saved to disk) changes.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of all local un-pushed saved changes exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for iModels with large local change backlogs under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if the native layer\r\n * fails to open the local changes.\r\n * @beta\r\n */\r\n public static openLocalChanges(\r\n args: Omit<ChangesetReaderArgs, \"db\"> & { db: IModelDb; includeInMemoryChanges?: boolean, spillThresholdInBytes?: number },\r\n ): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openLocalChanges(args.db[_nativeDb], args.includeInMemoryChanges ?? false, args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n } catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Read the in-memory (not yet saved to disk) changes of an open IModelDb.\r\n * @param args.db Must be an [IModelDb]($backend).\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of the in-memory (unsaved) change data exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for large in-memory transactions under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if the native layer encounters an error while opening the in-memory changes.\r\n * @beta\r\n */\r\n public static openInMemoryChanges(\r\n args: Omit<ChangesetReaderArgs, \"db\"> & { db: IModelDb, spillThresholdInBytes?: number },\r\n ): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openInMemoryChanges(args.db[_nativeDb], args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n } catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /**\r\n * Read a single saved transaction by its id.\r\n * @param args.db Must be an [IModelDb]($backend) ([ECDb]($backend) does not support transactions).\r\n * @param args.txnId The id of the saved transaction to read.\r\n * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).\r\n * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.\r\n * @param args.propFilter Controls which properties are included. Defaults to `All`.\r\n * @param args.spillThresholdInBytes When the total size of the transaction's change data exceeds this threshold (in bytes),\r\n * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.\r\n * This keeps peak memory usage bounded, making the API suitable for large transactions under low-memory conditions.\r\n * Defaults to 50 MiB.\r\n * @throws if `txnId` is not found, or\r\n * the native layer fails to open the transaction data.\r\n * @beta\r\n */\r\n public static openTxn(\r\n args: Omit<ChangesetReaderArgs, \"db\"> & { db: IModelDb; txnId: Id64String, spillThresholdInBytes?: number },\r\n ): ChangesetReader {\r\n const reader = new ChangesetReader(args.db);\r\n reader._rowOptions = args.rowOptions;\r\n const propFilter = args.propFilter ?? PropertyFilter.All;\r\n reader._propFilter = propFilter;\r\n try {\r\n reader._nativeReader.openTxn(args.db[_nativeDb], args.txnId, args.invert ?? false, reader._propFilter, args.spillThresholdInBytes ?? this.defaultSpillThresholdInBytes);\r\n } catch (e) {\r\n reader.handleCloseErrorWhileOpening(e);\r\n throw e;\r\n }\r\n return reader;\r\n }\r\n\r\n /** Throws if [[step]] has already been called, preventing filter/mode changes mid-iteration.\r\n * @internal */\r\n private throwIfAlreadyStepped(): void {\r\n if (this._consumedByUnifier)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: the reader has been consumed by a ChangeUnifier and can no longer be configured.\");\r\n if (this._changeIndex > 0)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: filters and strict mode and batch size must be configured before the first call to step().\");\r\n }\r\n\r\n /** The property filter and row options this reader was opened with, used by [ChangeUnifier]($backend) to fill `$meta`.\r\n * @internal */\r\n public get [_readerOptions](): { readonly propFilter: PropertyFilter, readonly rowOptions: RowFormatOptions | undefined } {\r\n return { propFilter: this._propFilter, rowOptions: this._rowOptions };\r\n }\r\n\r\n /** Drain all remaining rows of this reader into `nativeUnifier`, natively, honoring the filters and strict mode configured on this reader.\r\n * Afterwards the reader is consumed: [[step]] returns `false` and configuration methods throw. The reader is marked consumed even if draining fails.\r\n * @throws [[IModelError]] if the reader has already been stepped successfully or has already been consumed, or if the native layer fails.\r\n * @internal */\r\n public [_appendToNativeUnifier](nativeUnifier: IModelJsNative.ChangeUnifier): void {\r\n if (this._consumedByUnifier)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: the reader has already been consumed by a ChangeUnifier.\");\r\n if (this._changeIndex > 0)\r\n throw new IModelError(IModelStatus.BadRequest, \"ChangesetReader: a reader that has already been stepped cannot be passed to a ChangeUnifier.\");\r\n\r\n const nativeRowOpts = this._rowOptions ? this.toNativeRowOptions(this._rowOptions) : {};\r\n try {\r\n nativeUnifier.appendFrom(this._nativeReader, nativeRowOpts);\r\n } finally {\r\n this._consumedByUnifier = true;\r\n this._cache = [];\r\n this._cacheIndex = 0;\r\n this._cachedInserted = undefined;\r\n this._cachedDeleted = undefined;\r\n }\r\n }\r\n\r\n /** Handle errors that occur while auto closing the reader if there is also an error while opening the reader */\r\n private handleCloseErrorWhileOpening(e: unknown): void {\r\n try {\r\n this.close();\r\n } catch (closeError) {\r\n throw new IModelError(IModelStatus.BadArg, `Failed to open ChangesetReader with error ${e instanceof Error ? e.message : String(e)}.\r\n Additionally, that triggered an automatic closure of the reader\r\n releasing native resources which also failed with failure ${closeError instanceof Error ? closeError.message : String(closeError)}.\r\n Check native error logs for more details.`);\r\n }\r\n }\r\n\r\n /**\r\n * Set the number of rows to fetch and cache while stepping.\r\n * This is an advanced option that can be used to tune performance for large changesets.\r\n * Increasing the batch size improves throughput at the cost of higher peak memory; decreasing it keeps memory consumption lower.\r\n *\r\n * Default batch sizes when `setBatchSize` is not called:\r\n * - `InstanceKey` or `InstanceKeyAndIdentifiers` filter: **100**.\r\n * - `BisCoreElement` filter (any `abbreviateBlobs` setting): **20**.\r\n * - `All` filter, `abbreviateBlobs: false`: **5**.\r\n * - `All` filter (blobs abbreviated or unset): **10**.\r\n *\r\n * @param batchSize Number of rows to fetch and cache while stepping. Must be a positive integer.\r\n * @throws [[IModelError]] if [[step]] has already been called successfully, or if `batchSize` is not a positive integer.\r\n * @beta\r\n */\r\n public setBatchSize(batchSize: number): void {\r\n this.throwIfAlreadyStepped();\r\n if (!Number.isInteger(batchSize) || batchSize <= 0)\r\n throw new IModelError(IModelStatus.BadArg, \"ChangesetReader: batchSize must be a positive integer.\");\r\n this._batchSizeOverride = batchSize;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Filtering\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Restrict iteration to changes from the named SQLite tables.\r\n * That means the rows for changes from other tables will be skipped entirely and won't be visible through the reader.\r\n * @param tableNames SQLite table names to include.\r\n * Note: Table names must be provided in the correct case for proper filtering.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.\r\n * @beta\r\n */\r\n public setTableNameFilters(tableNames: Set<string>): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.setTableNameFilters(Array.from(tableNames));\r\n }\r\n\r\n /**\r\n * Restrict iteration to changes with the given operation types.\r\n * That means the rows for changes with other operation types will be skipped entirely and won't be visible through the reader.\r\n * @param ops Operations to include.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.\r\n * @beta\r\n */\r\n public setOpCodeFilters(ops: Set<SqliteChangeOp>): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.setOpCodeFilters(Array.from(ops));\r\n }\r\n\r\n /**\r\n * Restrict iteration to changes for the given EC class names.\r\n * That means the rows for changes from other EC classes will be skipped entirely and won't be visible through the reader.\r\n * @param classNames EC class names to include. The classNames should be in the full name format(i.e. \"SchemaName:ClassName\").\r\n * Note: Schema names and class names must be provided in the correct case for proper filtering. Derived classes are not automatically included, so they must be specified explicitly if needed.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.\r\n * @beta\r\n */\r\n public setClassNameFilters(classNames: Set<string>): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.setClassNameFilters(Array.from(classNames));\r\n }\r\n\r\n /**\r\n * Remove the table-name filters\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public clearTableNameFilters(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.clearTableNameFilters();\r\n }\r\n\r\n /**\r\n * Remove the op-code filters\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public clearOpCodeFilters(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.clearOpCodeFilters();\r\n }\r\n\r\n /**\r\n * Remove the class-name filters\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public clearClassNameFilters(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.clearClassNameFilters();\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Strict mode\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Enable strict mode on the reader.\r\n *\r\n * Strict mode affects how the reader handles a **column-count mismatch** between a change\r\n * record and the corresponding live database table. Such a mismatch can occur when columns\r\n * have been added to a table after the changeset was created.\r\n *\r\n * When strict mode is **enabled**: if the number of columns recorded in a change row differs\r\n * from the number of columns currently present in the live table, the reader throws an error\r\n * instead of processing that row.\r\n *\r\n * Use strict mode when you need to be certain that every change row is interpreted against\r\n * exactly the schema that was in effect when the changeset was written.\r\n *\r\n * @see [[disableStrictMode]] — the default (lenient) behaviour.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public enableStrictMode(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.enableStrictMode();\r\n }\r\n\r\n /**\r\n * Disable strict mode on the reader (this is the default).\r\n *\r\n * When strict mode is **disabled**: if the number of columns recorded in a change row differs\r\n * from the number of columns currently present in the live table, the reader takes the\r\n * **minimum** of the two column counts and proceeds normally with that subset. This is safe\r\n * because SQLite only ever appends new columns at the end of a table and never removes them —\r\n * so older change records simply lack the trailing columns that were added later, and those\r\n * missing columns are silently ignored.\r\n *\r\n * @see [[enableStrictMode]] — throw on column-count mismatches instead.\r\n * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.\r\n * @beta\r\n */\r\n public disableStrictMode(): void {\r\n this.throwIfAlreadyStepped();\r\n this._nativeReader.disableStrictMode();\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Iteration\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Advance to the next change.\r\n * @returns `true` while positioned on a valid change; `false` when the stream is exhausted.\r\n * Always returns `false` once the reader has been consumed by a [ChangeUnifier]($backend), whose instances\r\n * already include every row of this reader - do not step a reader after passing it to a [ChangeUnifier]($backend).\r\n * @throws if the native layer encounters an error while reading or decoding\r\n * the next change.\r\n * @beta\r\n */\r\n public step(): boolean {\r\n this._cachedInserted = undefined;\r\n this._cachedDeleted = undefined;\r\n if (this._consumedByUnifier)\r\n return false;\r\n if (this._cacheIndex + 1 < this._cache.length) {\r\n // Still have rows in cache — advance the pointer\r\n this._cacheIndex++;\r\n } else {\r\n // Cache empty or fully consumed — fetch next batch from native\r\n const nativeRowOpts = this._rowOptions ? this.toNativeRowOptions(this._rowOptions) : {};\r\n this._cache = this._nativeReader.step(this._batchSize, nativeRowOpts);\r\n this._cacheIndex = 0;\r\n if (this._cache.length === 0) return false;\r\n }\r\n this._changeIndex++;\r\n return true;\r\n }\r\n\r\n /**\r\n * SQLite opcode of the current change.\r\n * Valid only after a successful call to [[step]].\r\n * @throws [[IModelError]] if called before a successful [[step]] call.\r\n * @beta\r\n */\r\n public get op(): SqliteChangeOp {\r\n const opCode = this._currentRow.metadata.opCode;\r\n return opCode === DbOpcode.Insert ? \"Inserted\"\r\n : opCode === DbOpcode.Update ? \"Updated\"\r\n : \"Deleted\";\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Lifecycle\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Close the reader and release all native resources.\r\n *\r\n * @throws if the native layer encounters an error during cleanup. Native resources\r\n * are not fully released when this throws — check the native error\r\n * logs for details.\r\n * @beta\r\n */\r\n public close(): void {\r\n this._changeIndex = 0;\r\n this._cache = [];\r\n this._cacheIndex = 0;\r\n this._cachedInserted = undefined;\r\n this._cachedDeleted = undefined;\r\n this._nativeReader.close();\r\n }\r\n\r\n /**\r\n * Implements the `Disposable` contract — delegates to [[close]].\r\n *\r\n * @throws if the native layer fails to release its resources (re-thrown from [[close]]).\r\n * @beta\r\n */\r\n public [Symbol.dispose](): void {\r\n this.close();\r\n }\r\n}\r\n\r\n"]}
@@ -40,7 +40,7 @@ export interface RowFormatOptions {
40
40
  * When `true`, all property keys and struct sub-keys are returned in camelCase
41
41
  * (e.g. `id`, `className`, `lastMod`). Navigation property sub-keys use
42
42
  * `{ id, relClassName }` instead of `{ Id, RelECClassId }`.
43
- * @deprecated We should stick to ECProperty names as is instead.
43
+ * @deprecated in 5.14.0 - will not be removed until after 2027-10-02. We should stick to ECProperty names as is instead.
44
44
  */
45
45
  useJsName?: boolean;
46
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChangesetReaderTypes.js","sourceRoot":"","sources":["../../src/ChangesetReaderTypes.ts"],"names":[],"mappings":"AASA,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAN,IAAY,cAaX;AAbD,WAAY,cAAc;IACxB,kDAAkD;IAClD,iDAAO,CAAA;IACP;;;uBAGmB;IACnB,uEAAkB,CAAA;IAClB,2CAA2C;IAC3C,iEAAe,CAAA;IACf;2HACuH;IACvH,6FAA6B,CAAA;AAC/B,CAAC,EAbW,cAAc,KAAd,cAAc,QAazB","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module ECDb\r\n */\r\nimport { AnyDb, SqliteChangeOp, SqliteValueStage } from \"./SqliteChangesetReader\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Type aliases\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Controls which properties are included in the output of [ChangesetReader]($backend).\r\n * @beta\r\n */\r\nexport enum PropertyFilter {\r\n /** All EC properties mapped to changed tables. */\r\n All = 0,\r\n /** For classes whose base class is `BisCore:Element`, only `BisCore:Element` properties\r\n * mapped to changed tables are returned. If no `BisCore:Element` class property changed,\r\n * only `ECInstanceId` and `ECClassId` are returned. For other classes all mapped properties\r\n * are returned. */\r\n BisCoreElement = 1,\r\n /** Only `ECInstanceId` and `ECClassId`. */\r\n InstanceKey = 2,\r\n /** `ECInstanceId` and `ECClassId`, plus identifiers read only from the changeset, such as an aspect's owning `Element`.\r\n * See [the full list]($docs/learning/backend/ChangesetReader.md#identifiers-returned-by-instancekeyandidentifiers). */\r\n InstanceKeyAndIdentifiers = 3,\r\n}\r\n\r\n/**\r\n * Row-formatting options for [ChangesetReader]($backend) factory methods.\r\n * Controls how EC property values are represented in the returned instances.\r\n * @beta\r\n */\r\nexport interface RowFormatOptions {\r\n /**\r\n * When `false`, binary properties are returned as full `Uint8Array` values.\r\n * When `true` (or omitted), binary properties are summarized as `{ bytes: N }`.\r\n */\r\n abbreviateBlobs?: boolean;\r\n /**\r\n * When `true`, all classId values are converted from hex strings\r\n * to fully-qualified class names (e.g. `\"BisCore.DrawingModel\"`).\r\n */\r\n classIdsToClassNames?: boolean;\r\n /**\r\n * When `true`, all property keys and struct sub-keys are returned in camelCase\r\n * (e.g. `id`, `className`, `lastMod`). Navigation property sub-keys use\r\n * `{ id, relClassName }` instead of `{ Id, RelECClassId }`.\r\n * @deprecated We should stick to ECProperty names as is instead.\r\n */\r\n useJsName?: boolean;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public interfaces\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Metadata attached to every [[ChangeInstance]].\r\n * @beta\r\n */\r\nexport interface ChangeMeta {\r\n /** SQLite tables that contributed columns to this change row. */\r\n tables: string[];\r\n /** Operation that produced this change. */\r\n op: SqliteChangeOp;\r\n /** Whether this is the pre-change (`\"Old\"`) or post-change (`\"New\"`) snapshot. */\r\n stage: SqliteValueStage;\r\n /** Change-stream index positions. */\r\n changeIndexes: number[];\r\n /**\r\n * ECInstanceId and class Id in format \"<ECInstanceId>-<ECClassId>\".\r\n */\r\n instanceKey: string;\r\n /** Reader property filter that was active when this change row was captured. */\r\n propFilter: PropertyFilter;\r\n /** EC property names fetched from the current row of changeset or transaction or any other change stream.\r\n For compound data properties like point2d, point3d or navigation properties,\r\n the full name of the property is returned in case all the components of the property are fetched from the change.\r\n If all of the components are not fetched from the changes(meaning they did not change),\r\n then the individual component names which changed are returned smartly by using `.` as a separator (e.g. \"MyPoint.X\", \"MyPoint.Y\" for a point3d property \"MyPoint\" if only X and Y changed).\r\n For struct properties the property names are always returned in the \"StructProp.MemberName\" format.\r\n So if only X changed for a point2d property named \"Myp2d\" inide a struct \"CustomStruct\", the returned property name will be \"CustomStruct.Myp2d.X\".\r\n Similaly if both X and Y changed for the same point2d property, the returned property name will be \"CustomStruct.Myp2d\". */\r\n changeFetchedPropNames: string[];\r\n /** Row adaptor options that were active when this change row was captured. */\r\n rowOptions?: RowFormatOptions;\r\n /** `true` when the change was applied indirectly */\r\n isIndirectChange: boolean;\r\n}\r\n\r\n/**\r\n * An EC instance produced by [ChangesetReader]($backend) after each `step()`.\r\n * Contains the EC property bag plus mandatory `$meta` metadata.\r\n * @beta\r\n */\r\nexport interface ChangeInstance {\r\n /** Metadata describing the origin and identity of this change. */\r\n $meta: ChangeMeta;\r\n /** EC property bag (ECClassId, ECInstanceId, user-defined properties, ...). */\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * Contract for any reader that produces EC-typed changed instances compatible with\r\n * [PartialChangeUnifier]($backend).\r\n * @beta\r\n */\r\nexport interface ChangeSource {\r\n /** The SQLite opcode of the current change row. */\r\n readonly op: SqliteChangeOp;\r\n /**\r\n * The newly-inserted or post-update EC instance.\r\n * `undefined` when the current row is a Delete, or when `isECTable` is `false`.\r\n */\r\n readonly inserted?: ChangeInstance;\r\n /**\r\n * The deleted or pre-update EC instance.\r\n * `undefined` when the current row is an Insert, or when `isECTable` is `false`.\r\n */\r\n readonly deleted?: ChangeInstance;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// ChangesetReader args / options\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Arguments common to all [ChangesetReader]($backend) `open*` factory methods.\r\n * @beta\r\n */\r\nexport interface ChangesetReaderArgs {\r\n /** The db used to resolve EC schema. Must be at or ahead of the changeset being read. */\r\n readonly db: AnyDb;\r\n /** invert the changeset operations */\r\n readonly invert?: boolean;\r\n /** Row adaptor options controlling how EC property values are formatted. */\r\n readonly rowOptions?: RowFormatOptions;\r\n /** Controls which properties are included in the change output. Defaults to PropertyFilter.All. */\r\n readonly propFilter?: PropertyFilter;\r\n}"]}
1
+ {"version":3,"file":"ChangesetReaderTypes.js","sourceRoot":"","sources":["../../src/ChangesetReaderTypes.ts"],"names":[],"mappings":"AASA,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAN,IAAY,cAaX;AAbD,WAAY,cAAc;IACxB,kDAAkD;IAClD,iDAAO,CAAA;IACP;;;uBAGmB;IACnB,uEAAkB,CAAA;IAClB,2CAA2C;IAC3C,iEAAe,CAAA;IACf;2HACuH;IACvH,6FAA6B,CAAA;AAC/B,CAAC,EAbW,cAAc,KAAd,cAAc,QAazB","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module ECDb\r\n */\r\nimport { AnyDb, SqliteChangeOp, SqliteValueStage } from \"./SqliteChangesetReader\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Type aliases\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Controls which properties are included in the output of [ChangesetReader]($backend).\r\n * @beta\r\n */\r\nexport enum PropertyFilter {\r\n /** All EC properties mapped to changed tables. */\r\n All = 0,\r\n /** For classes whose base class is `BisCore:Element`, only `BisCore:Element` properties\r\n * mapped to changed tables are returned. If no `BisCore:Element` class property changed,\r\n * only `ECInstanceId` and `ECClassId` are returned. For other classes all mapped properties\r\n * are returned. */\r\n BisCoreElement = 1,\r\n /** Only `ECInstanceId` and `ECClassId`. */\r\n InstanceKey = 2,\r\n /** `ECInstanceId` and `ECClassId`, plus identifiers read only from the changeset, such as an aspect's owning `Element`.\r\n * See [the full list]($docs/learning/backend/ChangesetReader.md#identifiers-returned-by-instancekeyandidentifiers). */\r\n InstanceKeyAndIdentifiers = 3,\r\n}\r\n\r\n/**\r\n * Row-formatting options for [ChangesetReader]($backend) factory methods.\r\n * Controls how EC property values are represented in the returned instances.\r\n * @beta\r\n */\r\nexport interface RowFormatOptions {\r\n /**\r\n * When `false`, binary properties are returned as full `Uint8Array` values.\r\n * When `true` (or omitted), binary properties are summarized as `{ bytes: N }`.\r\n */\r\n abbreviateBlobs?: boolean;\r\n /**\r\n * When `true`, all classId values are converted from hex strings\r\n * to fully-qualified class names (e.g. `\"BisCore.DrawingModel\"`).\r\n */\r\n classIdsToClassNames?: boolean;\r\n /**\r\n * When `true`, all property keys and struct sub-keys are returned in camelCase\r\n * (e.g. `id`, `className`, `lastMod`). Navigation property sub-keys use\r\n * `{ id, relClassName }` instead of `{ Id, RelECClassId }`.\r\n * @deprecated in 5.14.0 - will not be removed until after 2027-10-02. We should stick to ECProperty names as is instead.\r\n */\r\n useJsName?: boolean;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public interfaces\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Metadata attached to every [[ChangeInstance]].\r\n * @beta\r\n */\r\nexport interface ChangeMeta {\r\n /** SQLite tables that contributed columns to this change row. */\r\n tables: string[];\r\n /** Operation that produced this change. */\r\n op: SqliteChangeOp;\r\n /** Whether this is the pre-change (`\"Old\"`) or post-change (`\"New\"`) snapshot. */\r\n stage: SqliteValueStage;\r\n /** Change-stream index positions. */\r\n changeIndexes: number[];\r\n /**\r\n * ECInstanceId and class Id in format \"<ECInstanceId>-<ECClassId>\".\r\n */\r\n instanceKey: string;\r\n /** Reader property filter that was active when this change row was captured. */\r\n propFilter: PropertyFilter;\r\n /** EC property names fetched from the current row of changeset or transaction or any other change stream.\r\n For compound data properties like point2d, point3d or navigation properties,\r\n the full name of the property is returned in case all the components of the property are fetched from the change.\r\n If all of the components are not fetched from the changes(meaning they did not change),\r\n then the individual component names which changed are returned smartly by using `.` as a separator (e.g. \"MyPoint.X\", \"MyPoint.Y\" for a point3d property \"MyPoint\" if only X and Y changed).\r\n For struct properties the property names are always returned in the \"StructProp.MemberName\" format.\r\n So if only X changed for a point2d property named \"Myp2d\" inide a struct \"CustomStruct\", the returned property name will be \"CustomStruct.Myp2d.X\".\r\n Similaly if both X and Y changed for the same point2d property, the returned property name will be \"CustomStruct.Myp2d\". */\r\n changeFetchedPropNames: string[];\r\n /** Row adaptor options that were active when this change row was captured. */\r\n rowOptions?: RowFormatOptions;\r\n /** `true` when the change was applied indirectly */\r\n isIndirectChange: boolean;\r\n}\r\n\r\n/**\r\n * An EC instance produced by [ChangesetReader]($backend) after each `step()`.\r\n * Contains the EC property bag plus mandatory `$meta` metadata.\r\n * @beta\r\n */\r\nexport interface ChangeInstance {\r\n /** Metadata describing the origin and identity of this change. */\r\n $meta: ChangeMeta;\r\n /** EC property bag (ECClassId, ECInstanceId, user-defined properties, ...). */\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * Contract for any reader that produces EC-typed changed instances compatible with\r\n * [PartialChangeUnifier]($backend).\r\n * @beta\r\n */\r\nexport interface ChangeSource {\r\n /** The SQLite opcode of the current change row. */\r\n readonly op: SqliteChangeOp;\r\n /**\r\n * The newly-inserted or post-update EC instance.\r\n * `undefined` when the current row is a Delete, or when `isECTable` is `false`.\r\n */\r\n readonly inserted?: ChangeInstance;\r\n /**\r\n * The deleted or pre-update EC instance.\r\n * `undefined` when the current row is an Insert, or when `isECTable` is `false`.\r\n */\r\n readonly deleted?: ChangeInstance;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// ChangesetReader args / options\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Arguments common to all [ChangesetReader]($backend) `open*` factory methods.\r\n * @beta\r\n */\r\nexport interface ChangesetReaderArgs {\r\n /** The db used to resolve EC schema. Must be at or ahead of the changeset being read. */\r\n readonly db: AnyDb;\r\n /** invert the changeset operations */\r\n readonly invert?: boolean;\r\n /** Row adaptor options controlling how EC property values are formatted. */\r\n readonly rowOptions?: RowFormatOptions;\r\n /** Controls which properties are included in the change output. Defaults to PropertyFilter.All. */\r\n readonly propFilter?: PropertyFilter;\r\n}"]}
@@ -159,6 +159,21 @@ export declare namespace CloudSqlite {
159
159
  * @note this value is only present when running in daemon mode.
160
160
  */
161
161
  readonly memoryClientManifest?: string;
162
+ /** The number of blocks downloaded on demand by the CloudContainer's metadata connection.
163
+ * This counter is specific to that connection, not an aggregate for the container or cache. Downloads by
164
+ * database connections opened from this container (including iModel connections) are not included.
165
+ * This applies in both daemon and daemonless modes; in daemon mode, the counter belongs to the
166
+ * daemon client serving the metadata connection, not all clients connected to the daemon.
167
+ */
168
+ readonly onDemandBlocksDownloaded?: string;
169
+ /** The number of bytes downloaded on demand by this connection.
170
+ * @see [[onDemandBlocksDownloaded]] for the connection scope in daemon and daemonless modes.
171
+ */
172
+ readonly onDemandBytesDownloaded?: string;
173
+ /** The cumulative time spent downloading blocks on demand by this connection, in milliseconds.
174
+ * @see [[onDemandBlocksDownloaded]] for the connection scope in daemon and daemonless modes.
175
+ */
176
+ readonly onDemandDownloadTimeMs?: string;
162
177
  }
163
178
  /** The base name of a CloudSqlite database, without any version information.
164
179
  * The name must conform to the following constraints: