@itwin/core-backend 5.15.0-dev.9 → 5.16.0-dev.2

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 (200) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/lib/cjs/BriefcaseManager.d.ts +2 -1
  3. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  4. package/lib/cjs/BriefcaseManager.js +39 -9
  5. package/lib/cjs/BriefcaseManager.js.map +1 -1
  6. package/lib/cjs/ChangeUnifier.d.ts +82 -0
  7. package/lib/cjs/ChangeUnifier.d.ts.map +1 -0
  8. package/lib/cjs/ChangeUnifier.js +163 -0
  9. package/lib/cjs/ChangeUnifier.js.map +1 -0
  10. package/lib/cjs/ChangesetReader.d.ts +21 -2
  11. package/lib/cjs/ChangesetReader.d.ts.map +1 -1
  12. package/lib/cjs/ChangesetReader.js +37 -1
  13. package/lib/cjs/ChangesetReader.js.map +1 -1
  14. package/lib/cjs/CloudSqlite.d.ts +15 -0
  15. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  16. package/lib/cjs/CloudSqlite.js.map +1 -1
  17. package/lib/cjs/ECDb.d.ts +1 -0
  18. package/lib/cjs/ECDb.d.ts.map +1 -1
  19. package/lib/cjs/ECDb.js +4 -1
  20. package/lib/cjs/ECDb.js.map +1 -1
  21. package/lib/cjs/EditTxn.d.ts +5 -0
  22. package/lib/cjs/EditTxn.d.ts.map +1 -1
  23. package/lib/cjs/EditTxn.js +30 -10
  24. package/lib/cjs/EditTxn.js.map +1 -1
  25. package/lib/cjs/GeoCoordConfig.d.ts +1 -0
  26. package/lib/cjs/GeoCoordConfig.d.ts.map +1 -1
  27. package/lib/cjs/GeoCoordConfig.js +12 -8
  28. package/lib/cjs/GeoCoordConfig.js.map +1 -1
  29. package/lib/cjs/IModelDb.d.ts +19 -6
  30. package/lib/cjs/IModelDb.d.ts.map +1 -1
  31. package/lib/cjs/IModelDb.js +50 -9
  32. package/lib/cjs/IModelDb.js.map +1 -1
  33. package/lib/cjs/NativeHost.d.ts.map +1 -1
  34. package/lib/cjs/NativeHost.js +5 -1
  35. package/lib/cjs/NativeHost.js.map +1 -1
  36. package/lib/cjs/Relationship.d.ts +28 -0
  37. package/lib/cjs/Relationship.d.ts.map +1 -1
  38. package/lib/cjs/Relationship.js +78 -0
  39. package/lib/cjs/Relationship.js.map +1 -1
  40. package/lib/cjs/SchemaSync.d.ts.map +1 -1
  41. package/lib/cjs/SchemaSync.js +1 -0
  42. package/lib/cjs/SchemaSync.js.map +1 -1
  43. package/lib/cjs/TxnManager.d.ts +126 -89
  44. package/lib/cjs/TxnManager.d.ts.map +1 -1
  45. package/lib/cjs/TxnManager.js +114 -76
  46. package/lib/cjs/TxnManager.js.map +1 -1
  47. package/lib/cjs/ViewStateHydrator.d.ts.map +1 -1
  48. package/lib/cjs/ViewStateHydrator.js.map +1 -1
  49. package/lib/cjs/ViewStore.d.ts.map +1 -1
  50. package/lib/cjs/ViewStore.js +62 -19
  51. package/lib/cjs/ViewStore.js.map +1 -1
  52. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
  53. package/lib/cjs/annotations/LeaderGeometry.js +3 -0
  54. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
  55. package/lib/cjs/core-backend.d.ts +1 -0
  56. package/lib/cjs/core-backend.d.ts.map +1 -1
  57. package/lib/cjs/core-backend.js +1 -0
  58. package/lib/cjs/core-backend.js.map +1 -1
  59. package/lib/cjs/internal/BriefcaseUtils.d.ts +19 -0
  60. package/lib/cjs/internal/BriefcaseUtils.d.ts.map +1 -0
  61. package/lib/cjs/internal/BriefcaseUtils.js +65 -0
  62. package/lib/cjs/internal/BriefcaseUtils.js.map +1 -0
  63. package/lib/cjs/internal/QueryMetadataCache.d.ts +44 -0
  64. package/lib/cjs/internal/QueryMetadataCache.d.ts.map +1 -0
  65. package/lib/cjs/internal/QueryMetadataCache.js +107 -0
  66. package/lib/cjs/internal/QueryMetadataCache.js.map +1 -0
  67. package/lib/cjs/internal/Symbols.d.ts +9 -0
  68. package/lib/cjs/internal/Symbols.d.ts.map +1 -1
  69. package/lib/cjs/internal/Symbols.js +10 -1
  70. package/lib/cjs/internal/Symbols.js.map +1 -1
  71. package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  72. package/lib/cjs/internal/workspace/WorkspaceImpl.js +20 -6
  73. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  74. package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
  75. package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
  76. package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  77. package/lib/esm/BriefcaseManager.d.ts +2 -1
  78. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  79. package/lib/esm/BriefcaseManager.js +40 -10
  80. package/lib/esm/BriefcaseManager.js.map +1 -1
  81. package/lib/esm/ChangeUnifier.d.ts +82 -0
  82. package/lib/esm/ChangeUnifier.d.ts.map +1 -0
  83. package/lib/esm/ChangeUnifier.js +159 -0
  84. package/lib/esm/ChangeUnifier.js.map +1 -0
  85. package/lib/esm/ChangesetReader.d.ts +21 -2
  86. package/lib/esm/ChangesetReader.d.ts.map +1 -1
  87. package/lib/esm/ChangesetReader.js +38 -2
  88. package/lib/esm/ChangesetReader.js.map +1 -1
  89. package/lib/esm/CloudSqlite.d.ts +15 -0
  90. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  91. package/lib/esm/CloudSqlite.js.map +1 -1
  92. package/lib/esm/ECDb.d.ts +1 -0
  93. package/lib/esm/ECDb.d.ts.map +1 -1
  94. package/lib/esm/ECDb.js +4 -1
  95. package/lib/esm/ECDb.js.map +1 -1
  96. package/lib/esm/EditTxn.d.ts +5 -0
  97. package/lib/esm/EditTxn.d.ts.map +1 -1
  98. package/lib/esm/EditTxn.js +32 -12
  99. package/lib/esm/EditTxn.js.map +1 -1
  100. package/lib/esm/GeoCoordConfig.d.ts +1 -0
  101. package/lib/esm/GeoCoordConfig.d.ts.map +1 -1
  102. package/lib/esm/GeoCoordConfig.js +12 -8
  103. package/lib/esm/GeoCoordConfig.js.map +1 -1
  104. package/lib/esm/IModelDb.d.ts +19 -6
  105. package/lib/esm/IModelDb.d.ts.map +1 -1
  106. package/lib/esm/IModelDb.js +52 -11
  107. package/lib/esm/IModelDb.js.map +1 -1
  108. package/lib/esm/NativeHost.d.ts.map +1 -1
  109. package/lib/esm/NativeHost.js +5 -1
  110. package/lib/esm/NativeHost.js.map +1 -1
  111. package/lib/esm/Relationship.d.ts +28 -0
  112. package/lib/esm/Relationship.d.ts.map +1 -1
  113. package/lib/esm/Relationship.js +78 -0
  114. package/lib/esm/Relationship.js.map +1 -1
  115. package/lib/esm/SchemaSync.d.ts.map +1 -1
  116. package/lib/esm/SchemaSync.js +1 -0
  117. package/lib/esm/SchemaSync.js.map +1 -1
  118. package/lib/esm/TxnManager.d.ts +126 -89
  119. package/lib/esm/TxnManager.d.ts.map +1 -1
  120. package/lib/esm/TxnManager.js +116 -78
  121. package/lib/esm/TxnManager.js.map +1 -1
  122. package/lib/esm/ViewStateHydrator.d.ts.map +1 -1
  123. package/lib/esm/ViewStateHydrator.js.map +1 -1
  124. package/lib/esm/ViewStore.d.ts.map +1 -1
  125. package/lib/esm/ViewStore.js +62 -19
  126. package/lib/esm/ViewStore.js.map +1 -1
  127. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
  128. package/lib/esm/annotations/LeaderGeometry.js +3 -0
  129. package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
  130. package/lib/esm/core-backend.d.ts +1 -0
  131. package/lib/esm/core-backend.d.ts.map +1 -1
  132. package/lib/esm/core-backend.js +1 -0
  133. package/lib/esm/core-backend.js.map +1 -1
  134. package/lib/esm/internal/BriefcaseUtils.d.ts +19 -0
  135. package/lib/esm/internal/BriefcaseUtils.d.ts.map +1 -0
  136. package/lib/esm/internal/BriefcaseUtils.js +61 -0
  137. package/lib/esm/internal/BriefcaseUtils.js.map +1 -0
  138. package/lib/esm/internal/QueryMetadataCache.d.ts +44 -0
  139. package/lib/esm/internal/QueryMetadataCache.d.ts.map +1 -0
  140. package/lib/esm/internal/QueryMetadataCache.js +103 -0
  141. package/lib/esm/internal/QueryMetadataCache.js.map +1 -0
  142. package/lib/esm/internal/Symbols.d.ts +9 -0
  143. package/lib/esm/internal/Symbols.d.ts.map +1 -1
  144. package/lib/esm/internal/Symbols.js +9 -0
  145. package/lib/esm/internal/Symbols.js.map +1 -1
  146. package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  147. package/lib/esm/internal/workspace/WorkspaceImpl.js +20 -6
  148. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  149. package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts +6 -6
  150. package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts.map +1 -1
  151. package/lib/esm/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  152. package/lib/esm/test/annotations/LeaderGeometry.test.js +15 -1
  153. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
  154. package/lib/esm/test/ecdb/CTE.test.js +21 -0
  155. package/lib/esm/test/ecdb/CTE.test.js.map +1 -1
  156. package/lib/esm/test/ecdb/ConcurrentQuery.test.js +144 -30
  157. package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -1
  158. package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts +2 -0
  159. package/lib/esm/test/ecdb/QueryMetadataCache.test.d.ts.map +1 -0
  160. package/lib/esm/test/ecdb/QueryMetadataCache.test.js +630 -0
  161. package/lib/esm/test/ecdb/QueryMetadataCache.test.js.map +1 -0
  162. package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts +2 -0
  163. package/lib/esm/test/element/RelationshipBatchLookup.test.d.ts.map +1 -0
  164. package/lib/esm/test/element/RelationshipBatchLookup.test.js +202 -0
  165. package/lib/esm/test/element/RelationshipBatchLookup.test.js.map +1 -0
  166. package/lib/esm/test/hubaccess/BriefcaseManager.test.js +187 -1
  167. package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
  168. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts +2 -0
  169. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.d.ts.map +1 -0
  170. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js +142 -0
  171. package/lib/esm/test/hubaccess/SchemaImportOrphanColumns.test.js.map +1 -0
  172. package/lib/esm/test/imodel/IModelGeolocation.test.js +8 -6
  173. package/lib/esm/test/imodel/IModelGeolocation.test.js.map +1 -1
  174. package/lib/esm/test/imodel/IModelProps.test.d.ts +2 -0
  175. package/lib/esm/test/imodel/IModelProps.test.d.ts.map +1 -0
  176. package/lib/esm/test/imodel/IModelProps.test.js +411 -0
  177. package/lib/esm/test/imodel/IModelProps.test.js.map +1 -0
  178. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts +2 -0
  179. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.d.ts.map +1 -0
  180. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js +240 -0
  181. package/lib/esm/test/schema/SchemaViewPropertyOverrides.test.js.map +1 -0
  182. package/lib/esm/test/schema/SchemaViewValidation.test.js +2 -8
  183. package/lib/esm/test/schema/SchemaViewValidation.test.js.map +1 -1
  184. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts +2 -0
  185. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.d.ts.map +1 -0
  186. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js +159 -0
  187. package/lib/esm/test/standalone/BriefcaseManagerDelete.test.js.map +1 -0
  188. package/lib/esm/test/standalone/ChangeUnifier.test.d.ts +2 -0
  189. package/lib/esm/test/standalone/ChangeUnifier.test.d.ts.map +1 -0
  190. package/lib/esm/test/standalone/ChangeUnifier.test.js +732 -0
  191. package/lib/esm/test/standalone/ChangeUnifier.test.js.map +1 -0
  192. package/lib/esm/test/standalone/EditTxn.test.js +72 -1
  193. package/lib/esm/test/standalone/EditTxn.test.js.map +1 -1
  194. package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts +2 -0
  195. package/lib/esm/test/standalone/GeoCoordConfig.test.d.ts.map +1 -0
  196. package/lib/esm/test/standalone/GeoCoordConfig.test.js +158 -0
  197. package/lib/esm/test/standalone/GeoCoordConfig.test.js.map +1 -0
  198. package/lib/esm/test/standalone/ViewStoreDb.test.js +53 -0
  199. package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
  200. package/package.json +18 -18
@@ -0,0 +1,82 @@
1
+ import { ChangesetReader } from "./ChangesetReader";
2
+ import { ChangeInstance } from "./ChangesetReaderTypes";
3
+ /**
4
+ * Arguments for [[ChangeUnifier.fromReader]] and [[ChangeUnifier.fromReaders]].
5
+ * @beta
6
+ */
7
+ export interface ChangeUnifierArgs {
8
+ /** Names of the properties to keep, e.g. `["FederationGuid", "Model", "Source", "Target"]`. `ECInstanceId` and `ECClassId` are always kept.
9
+ * All other properties are dropped before the merged instances are stored, which reduces memory use.
10
+ * `undefined` or empty keeps all properties returned by the readers.
11
+ */
12
+ propNames?: string[];
13
+ /** Number of bytes of merged instance data held in memory before sorted runs are spilled to temporary files.
14
+ * Must be a non-negative integer. `0` means never spill. Defaults to 64 MiB.
15
+ */
16
+ memoryBudgetBytes?: number;
17
+ /** Number of instances fetched from the native layer at a time while iterating [[ChangeUnifier.instances]].
18
+ * Must be a positive integer. Defaults to 1000. A batch ends early once it holds 16 MiB of strings and binary data,
19
+ * so large instances (e.g. with unabbreviated geometry streams) do not pile up in memory.
20
+ */
21
+ batchSize?: number;
22
+ }
23
+ /**
24
+ * Merges the per-table rows of one or more [ChangesetReader]($backend)s into complete EC instances in native code, with memory
25
+ * bounded by spilling to temporary files. Readers are consumed when the unifier is created.
26
+ * See [ChangeUnifier]($docs/learning/backend/ChangesetReader.md#changeunifier--native-merging-with-bounded-memory) for usage and
27
+ * how it differs from [PartialChangeUnifier]($backend).
28
+ * @beta
29
+ */
30
+ export declare class ChangeUnifier implements Disposable {
31
+ private static readonly defaultBatchSize;
32
+ private readonly _nativeUnifier;
33
+ private readonly _batchSize;
34
+ private _hasReader;
35
+ private _propFilter;
36
+ private _rowOptions?;
37
+ /** Instances fetched by the most recent native `step()` call. */
38
+ private _batch;
39
+ /** Index of the next instance to return from `_batch`. */
40
+ private _batchIndex;
41
+ private _exhausted;
42
+ private _disposed;
43
+ private constructor();
44
+ /**
45
+ * Create a unifier that merges all rows of `reader`. The reader is drained by this call and can be disposed afterward.
46
+ * @param reader A reader that has not been stepped yet.
47
+ * @param args Options controlling projection, memory use and batching.
48
+ * @throws [[IModelError]] if `args` are invalid, if `reader` has already been stepped or consumed, or if the native layer fails.
49
+ * @beta
50
+ */
51
+ static fromReader(reader: ChangesetReader, args?: ChangeUnifierArgs): ChangeUnifier;
52
+ /**
53
+ * Create a unifier that merges all rows of several readers, e.g. one per changeset. Where property values conflict, later readers win.
54
+ * Each reader is requested and drained before the next, so `readers` can be a generator that opens and disposes them.
55
+ * @param readers Readers of the same iModel, opened with the same `propFilter` and equivalent `rowOptions`, that have not been stepped yet.
56
+ * @param args Options controlling projection, memory use and batching.
57
+ * @throws [[IModelError]] if `args` are invalid, if a reader has already been stepped or consumed, if the readers' `propFilter`
58
+ * or `rowOptions` differ, or if the native layer fails (for example when readers read different iModels). Readers drained
59
+ * before the error remain consumed.
60
+ * @beta
61
+ */
62
+ static fromReaders(readers: Iterable<ChangesetReader>, args?: ChangeUnifierArgs): ChangeUnifier;
63
+ /**
64
+ * Iterate over the merged EC change instances, sorted by (root ECClassId, ECInstanceId, stage).
65
+ * Instances are fetched from the native layer lazily, [[ChangeUnifierArgs.batchSize]] at a time.
66
+ * Each instance is returned only once: iterating again, or calling `instances()` again, continues after the last instance returned.
67
+ * @throws [[IModelError]] if the unifier has been disposed, or if the native layer fails.
68
+ * @beta
69
+ */
70
+ instances(): IterableIterator<ChangeInstance>;
71
+ /**
72
+ * Release native resources, including any temporary spill files.
73
+ * @beta
74
+ */
75
+ [Symbol.dispose](): void;
76
+ private appendReader;
77
+ private closeAfterError;
78
+ private nextInstance;
79
+ /** Complete the native metadata with the options of the readers, in place, so the instance satisfies [[ChangeMeta]]. */
80
+ private toChangeInstance;
81
+ }
82
+ //# sourceMappingURL=ChangeUnifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangeUnifier.d.ts","sourceRoot":"","sources":["../../src/ChangeUnifier.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAgD,MAAM,wBAAwB,CAAC;AAItG;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,iEAAiE;IACjE,OAAO,CAAC,MAAM,CAA8C;IAC5D,0DAA0D;IAC1D,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO;IAgBP;;;;;;OAMG;WACW,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,aAAa;IAI1F;;;;;;;;;OASG;WACW,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,aAAa;IAYtG;;;;;;OAMG;IACK,SAAS,IAAI,gBAAgB,CAAC,cAAc,CAAC;IAKrD;;;OAGG;IACI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;IAa/B,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,YAAY;IAgBpB,wHAAwH;IACxH,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChangeUnifier = void 0;
4
+ /*---------------------------------------------------------------------------------------------
5
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
6
+ * See LICENSE.md in the project root for license terms and full copyright notice.
7
+ *--------------------------------------------------------------------------------------------*/
8
+ /** @packageDocumentation
9
+ * @module ECDb
10
+ */
11
+ const core_bentley_1 = require("@itwin/core-bentley");
12
+ const core_common_1 = require("@itwin/core-common");
13
+ const ChangesetReaderTypes_1 = require("./ChangesetReaderTypes");
14
+ const NativePlatform_1 = require("./internal/NativePlatform");
15
+ const Symbols_1 = require("./internal/Symbols");
16
+ /**
17
+ * Merges the per-table rows of one or more [ChangesetReader]($backend)s into complete EC instances in native code, with memory
18
+ * bounded by spilling to temporary files. Readers are consumed when the unifier is created.
19
+ * See [ChangeUnifier]($docs/learning/backend/ChangesetReader.md#changeunifier--native-merging-with-bounded-memory) for usage and
20
+ * how it differs from [PartialChangeUnifier]($backend).
21
+ * @beta
22
+ */
23
+ class ChangeUnifier {
24
+ static defaultBatchSize = 1000;
25
+ _nativeUnifier;
26
+ _batchSize;
27
+ _hasReader = false;
28
+ _propFilter = ChangesetReaderTypes_1.PropertyFilter.All;
29
+ _rowOptions;
30
+ /** Instances fetched by the most recent native `step()` call. */
31
+ _batch = [];
32
+ /** Index of the next instance to return from `_batch`. */
33
+ _batchIndex = 0;
34
+ _exhausted = false;
35
+ _disposed = false;
36
+ // Private — callers use static factory methods.
37
+ constructor(args) {
38
+ const batchSize = args.batchSize ?? ChangeUnifier.defaultBatchSize;
39
+ if (!Number.isInteger(batchSize) || batchSize <= 0)
40
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "ChangeUnifier: batchSize must be a positive integer.");
41
+ if (args.memoryBudgetBytes !== undefined && (!Number.isSafeInteger(args.memoryBudgetBytes) || args.memoryBudgetBytes < 0))
42
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "ChangeUnifier: memoryBudgetBytes must be a non-negative integer.");
43
+ this._batchSize = batchSize;
44
+ const options = {};
45
+ if (args.propNames !== undefined)
46
+ options.propNames = [...args.propNames];
47
+ if (args.memoryBudgetBytes !== undefined)
48
+ options.memoryBudgetBytes = args.memoryBudgetBytes;
49
+ this._nativeUnifier = new NativePlatform_1.IModelNative.platform.ChangeUnifier(options);
50
+ }
51
+ /**
52
+ * Create a unifier that merges all rows of `reader`. The reader is drained by this call and can be disposed afterward.
53
+ * @param reader A reader that has not been stepped yet.
54
+ * @param args Options controlling projection, memory use and batching.
55
+ * @throws [[IModelError]] if `args` are invalid, if `reader` has already been stepped or consumed, or if the native layer fails.
56
+ * @beta
57
+ */
58
+ static fromReader(reader, args) {
59
+ return ChangeUnifier.fromReaders([reader], args);
60
+ }
61
+ /**
62
+ * Create a unifier that merges all rows of several readers, e.g. one per changeset. Where property values conflict, later readers win.
63
+ * Each reader is requested and drained before the next, so `readers` can be a generator that opens and disposes them.
64
+ * @param readers Readers of the same iModel, opened with the same `propFilter` and equivalent `rowOptions`, that have not been stepped yet.
65
+ * @param args Options controlling projection, memory use and batching.
66
+ * @throws [[IModelError]] if `args` are invalid, if a reader has already been stepped or consumed, if the readers' `propFilter`
67
+ * or `rowOptions` differ, or if the native layer fails (for example when readers read different iModels). Readers drained
68
+ * before the error remain consumed.
69
+ * @beta
70
+ */
71
+ static fromReaders(readers, args) {
72
+ const unifier = new ChangeUnifier(args ?? {});
73
+ try {
74
+ for (const reader of readers)
75
+ unifier.appendReader(reader);
76
+ }
77
+ catch (e) {
78
+ unifier.closeAfterError();
79
+ throw e;
80
+ }
81
+ return unifier;
82
+ }
83
+ /**
84
+ * Iterate over the merged EC change instances, sorted by (root ECClassId, ECInstanceId, stage).
85
+ * Instances are fetched from the native layer lazily, [[ChangeUnifierArgs.batchSize]] at a time.
86
+ * Each instance is returned only once: iterating again, or calling `instances()` again, continues after the last instance returned.
87
+ * @throws [[IModelError]] if the unifier has been disposed, or if the native layer fails.
88
+ * @beta
89
+ */
90
+ *instances() {
91
+ for (let instance = this.nextInstance(); instance !== undefined; instance = this.nextInstance())
92
+ yield instance;
93
+ }
94
+ /**
95
+ * Release native resources, including any temporary spill files.
96
+ * @beta
97
+ */
98
+ [Symbol.dispose]() {
99
+ if (this._disposed)
100
+ return;
101
+ this._disposed = true;
102
+ this._batch = [];
103
+ this._batchIndex = 0;
104
+ this._nativeUnifier.close();
105
+ }
106
+ // ---------------------------------------------------------------------------
107
+ // Private helpers
108
+ // ---------------------------------------------------------------------------
109
+ appendReader(reader) {
110
+ const { propFilter, rowOptions } = reader[Symbols_1._readerOptions];
111
+ if (!this._hasReader) {
112
+ this._propFilter = propFilter;
113
+ // Copied: the reader keeps the caller's object, which may change before later readers are compared with it.
114
+ this._rowOptions = rowOptions === undefined ? undefined : { ...rowOptions };
115
+ this._hasReader = true;
116
+ }
117
+ else if (propFilter !== this._propFilter || !areEquivalentRowOptions(rowOptions, this._rowOptions)) {
118
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "ChangeUnifier: all readers must be opened with the same propFilter and rowOptions.");
119
+ }
120
+ reader[Symbols_1._appendToNativeUnifier](this._nativeUnifier);
121
+ }
122
+ closeAfterError() {
123
+ this._disposed = true;
124
+ try {
125
+ this._nativeUnifier.close();
126
+ }
127
+ catch {
128
+ // The error that caused the unifier to be closed is more relevant to the caller than a failure to close it.
129
+ }
130
+ }
131
+ nextInstance() {
132
+ if (this._disposed)
133
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "ChangeUnifier: cannot iterate instances after the unifier has been disposed.");
134
+ if (this._batchIndex >= this._batch.length) {
135
+ if (this._exhausted)
136
+ return undefined;
137
+ this._batch = this._nativeUnifier.step(this._batchSize);
138
+ this._batchIndex = 0;
139
+ if (this._batch.length === 0) {
140
+ this._exhausted = true;
141
+ return undefined;
142
+ }
143
+ }
144
+ return this.toChangeInstance(this._batch[this._batchIndex++]);
145
+ }
146
+ /** Complete the native metadata with the options of the readers, in place, so the instance satisfies [[ChangeMeta]]. */
147
+ toChangeInstance(instance) {
148
+ const meta = instance.$meta;
149
+ meta.propFilter = this._propFilter;
150
+ if (this._rowOptions !== undefined)
151
+ meta.rowOptions = this._rowOptions;
152
+ return instance;
153
+ }
154
+ }
155
+ exports.ChangeUnifier = ChangeUnifier;
156
+ /** `true` if both options format rows identically, taking the defaults of omitted options into account. */
157
+ function areEquivalentRowOptions(lhs, rhs) {
158
+ return (lhs?.abbreviateBlobs ?? true) === (rhs?.abbreviateBlobs ?? true)
159
+ && (lhs?.classIdsToClassNames ?? false) === (rhs?.classIdsToClassNames ?? false)
160
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
161
+ && (lhs?.useJsName ?? false) === (rhs?.useJsName ?? false);
162
+ }
163
+ //# 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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"}
@@ -28,7 +28,9 @@ const ChangesetReaderTypes_1 = require("./ChangesetReaderTypes");
28
28
  * and both [[inserted]] and [[deleted]] remain `undefined`.
29
29
  *
30
30
  * @note The native reader operates one SQLite table-row at a time. Multi-table EC
31
- * instances must be merged using [PartialChangeUnifier]($backend).
31
+ * instances must be merged using [PartialChangeUnifier]($backend), or natively using
32
+ * [ChangeUnifier]($backend). A reader passed to [ChangeUnifier]($backend) is consumed by it:
33
+ * afterwards [[step]] returns `false` and the reader can no longer be configured, so do not step it.
32
34
  * @beta
33
35
  */
34
36
  class ChangesetReader {
@@ -51,6 +53,8 @@ class ChangesetReader {
51
53
  _cachedInserted = undefined;
52
54
  /** Cached result of the `deleted` getter for the current row. `undefined` when not yet computed or not applicable. */
53
55
  _cachedDeleted = undefined;
56
+ /** `true` once the native reader has been drained by a [ChangeUnifier]($backend). */
57
+ _consumedByUnifier = false;
54
58
  /** The db used for EC schema resolution. */
55
59
  db;
56
60
  /** Returns the active cached row, throwing if no row is current.
@@ -312,9 +316,37 @@ class ChangesetReader {
312
316
  /** Throws if [[step]] has already been called, preventing filter/mode changes mid-iteration.
313
317
  * @internal */
314
318
  throwIfAlreadyStepped() {
319
+ if (this._consumedByUnifier)
320
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "ChangesetReader: the reader has been consumed by a ChangeUnifier and can no longer be configured.");
315
321
  if (this._changeIndex > 0)
316
322
  throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "ChangesetReader: filters and strict mode and batch size must be configured before the first call to step().");
317
323
  }
324
+ /** The property filter and row options this reader was opened with, used by [ChangeUnifier]($backend) to fill `$meta`.
325
+ * @internal */
326
+ get [Symbols_1._readerOptions]() {
327
+ return { propFilter: this._propFilter, rowOptions: this._rowOptions };
328
+ }
329
+ /** Drain all remaining rows of this reader into `nativeUnifier`, natively, honoring the filters and strict mode configured on this reader.
330
+ * Afterwards the reader is consumed: [[step]] returns `false` and configuration methods throw. The reader is marked consumed even if draining fails.
331
+ * @throws [[IModelError]] if the reader has already been stepped successfully or has already been consumed, or if the native layer fails.
332
+ * @internal */
333
+ [Symbols_1._appendToNativeUnifier](nativeUnifier) {
334
+ if (this._consumedByUnifier)
335
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "ChangesetReader: the reader has already been consumed by a ChangeUnifier.");
336
+ if (this._changeIndex > 0)
337
+ throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "ChangesetReader: a reader that has already been stepped cannot be passed to a ChangeUnifier.");
338
+ const nativeRowOpts = this._rowOptions ? this.toNativeRowOptions(this._rowOptions) : {};
339
+ try {
340
+ nativeUnifier.appendFrom(this._nativeReader, nativeRowOpts);
341
+ }
342
+ finally {
343
+ this._consumedByUnifier = true;
344
+ this._cache = [];
345
+ this._cacheIndex = 0;
346
+ this._cachedInserted = undefined;
347
+ this._cachedDeleted = undefined;
348
+ }
349
+ }
318
350
  /** Handle errors that occur while auto closing the reader if there is also an error while opening the reader */
319
351
  handleCloseErrorWhileOpening(e) {
320
352
  try {
@@ -462,6 +494,8 @@ class ChangesetReader {
462
494
  /**
463
495
  * Advance to the next change.
464
496
  * @returns `true` while positioned on a valid change; `false` when the stream is exhausted.
497
+ * Always returns `false` once the reader has been consumed by a [ChangeUnifier]($backend), whose instances
498
+ * already include every row of this reader - do not step a reader after passing it to a [ChangeUnifier]($backend).
465
499
  * @throws if the native layer encounters an error while reading or decoding
466
500
  * the next change.
467
501
  * @beta
@@ -469,6 +503,8 @@ class ChangesetReader {
469
503
  step() {
470
504
  this._cachedInserted = undefined;
471
505
  this._cachedDeleted = undefined;
506
+ if (this._consumedByUnifier)
507
+ return false;
472
508
  if (this._cacheIndex + 1 < this._cache.length) {
473
509
  // Still have rows in cache — advance the pointer
474
510
  this._cacheIndex++;
@@ -1 +1 @@
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 { _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"]}