@itwin/core-backend 5.6.0-dev.8 → 5.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  3. package/lib/cjs/BriefcaseManager.js +37 -14
  4. package/lib/cjs/BriefcaseManager.js.map +1 -1
  5. package/lib/cjs/IModelDb.d.ts +90 -24
  6. package/lib/cjs/IModelDb.d.ts.map +1 -1
  7. package/lib/cjs/IModelDb.js +93 -4
  8. package/lib/cjs/IModelDb.js.map +1 -1
  9. package/lib/cjs/SQLiteDb.d.ts.map +1 -1
  10. package/lib/cjs/SQLiteDb.js +0 -1
  11. package/lib/cjs/SQLiteDb.js.map +1 -1
  12. package/lib/cjs/SqliteChangesetReader.d.ts +5 -0
  13. package/lib/cjs/SqliteChangesetReader.d.ts.map +1 -1
  14. package/lib/cjs/SqliteChangesetReader.js +7 -0
  15. package/lib/cjs/SqliteChangesetReader.js.map +1 -1
  16. package/lib/cjs/StashManager.d.ts +1 -2
  17. package/lib/cjs/StashManager.d.ts.map +1 -1
  18. package/lib/cjs/StashManager.js.map +1 -1
  19. package/lib/cjs/TxnManager.d.ts +74 -52
  20. package/lib/cjs/TxnManager.d.ts.map +1 -1
  21. package/lib/cjs/TxnManager.js +114 -26
  22. package/lib/cjs/TxnManager.js.map +1 -1
  23. package/lib/cjs/annotations/TextAnnotationElement.d.ts +1 -1
  24. package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
  25. package/lib/cjs/annotations/TextAnnotationElement.js +14 -1
  26. package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
  27. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts +14 -0
  28. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts.map +1 -1
  29. package/lib/cjs/annotations/TextAnnotationGeometry.js +29 -10
  30. package/lib/cjs/annotations/TextAnnotationGeometry.js.map +1 -1
  31. package/lib/cjs/annotations/TextBlockLayout.js +6 -6
  32. package/lib/cjs/annotations/TextBlockLayout.js.map +1 -1
  33. package/lib/cjs/internal/IntegrityCheck.d.ts +240 -0
  34. package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -0
  35. package/lib/cjs/internal/IntegrityCheck.js +193 -0
  36. package/lib/cjs/internal/IntegrityCheck.js.map +1 -0
  37. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.d.ts.map +1 -1
  38. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  39. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  40. package/lib/esm/BriefcaseManager.js +37 -14
  41. package/lib/esm/BriefcaseManager.js.map +1 -1
  42. package/lib/esm/IModelDb.d.ts +90 -24
  43. package/lib/esm/IModelDb.d.ts.map +1 -1
  44. package/lib/esm/IModelDb.js +93 -4
  45. package/lib/esm/IModelDb.js.map +1 -1
  46. package/lib/esm/SQLiteDb.d.ts.map +1 -1
  47. package/lib/esm/SQLiteDb.js +0 -1
  48. package/lib/esm/SQLiteDb.js.map +1 -1
  49. package/lib/esm/SqliteChangesetReader.d.ts +5 -0
  50. package/lib/esm/SqliteChangesetReader.d.ts.map +1 -1
  51. package/lib/esm/SqliteChangesetReader.js +7 -0
  52. package/lib/esm/SqliteChangesetReader.js.map +1 -1
  53. package/lib/esm/StashManager.d.ts +1 -2
  54. package/lib/esm/StashManager.d.ts.map +1 -1
  55. package/lib/esm/StashManager.js.map +1 -1
  56. package/lib/esm/TxnManager.d.ts +74 -52
  57. package/lib/esm/TxnManager.d.ts.map +1 -1
  58. package/lib/esm/TxnManager.js +114 -26
  59. package/lib/esm/TxnManager.js.map +1 -1
  60. package/lib/esm/annotations/TextAnnotationElement.d.ts +1 -1
  61. package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
  62. package/lib/esm/annotations/TextAnnotationElement.js +14 -1
  63. package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
  64. package/lib/esm/annotations/TextAnnotationGeometry.d.ts +14 -0
  65. package/lib/esm/annotations/TextAnnotationGeometry.d.ts.map +1 -1
  66. package/lib/esm/annotations/TextAnnotationGeometry.js +29 -10
  67. package/lib/esm/annotations/TextAnnotationGeometry.js.map +1 -1
  68. package/lib/esm/annotations/TextBlockLayout.js +6 -6
  69. package/lib/esm/annotations/TextBlockLayout.js.map +1 -1
  70. package/lib/esm/internal/IntegrityCheck.d.ts +240 -0
  71. package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -0
  72. package/lib/esm/internal/IntegrityCheck.js +187 -0
  73. package/lib/esm/internal/IntegrityCheck.js.map +1 -0
  74. package/lib/esm/rpc-impl/RpcBriefcaseUtility.d.ts.map +1 -1
  75. package/lib/esm/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  76. package/lib/esm/test/annotations/LeaderGeometry.test.js +2 -3
  77. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
  78. package/lib/esm/test/annotations/TextAnnotation.test.js +39 -4
  79. package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
  80. package/lib/esm/test/annotations/TextBlock.test.js +49 -42
  81. package/lib/esm/test/annotations/TextBlock.test.js.map +1 -1
  82. package/lib/esm/test/hubaccess/Rebase.test.js +546 -22
  83. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
  84. package/lib/esm/test/imodel/SchemaXmlImport.test.js +87 -44
  85. package/lib/esm/test/imodel/SchemaXmlImport.test.js.map +1 -1
  86. package/lib/esm/test/schema/SchemaImportCallbacks.test.js +4 -4
  87. package/lib/esm/test/schema/SchemaImportCallbacks.test.js.map +1 -1
  88. package/lib/esm/test/standalone/ChangeMerge.test.js +9 -9
  89. package/lib/esm/test/standalone/ChangeMerge.test.js.map +1 -1
  90. package/lib/esm/test/standalone/ChangesetReader.test.js +173 -2
  91. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  92. package/lib/esm/test/standalone/IntegrityCheck.test.d.ts +2 -0
  93. package/lib/esm/test/standalone/IntegrityCheck.test.d.ts.map +1 -0
  94. package/lib/esm/test/standalone/IntegrityCheck.test.js +385 -0
  95. package/lib/esm/test/standalone/IntegrityCheck.test.js.map +1 -0
  96. package/package.json +14 -14
@@ -49,6 +49,7 @@ import { ECVersion, SchemaContext, SchemaJsonLocater } from "@itwin/ecschema-met
49
49
  import { SchemaMap } from "./Schema";
50
50
  import { ElementLRUCache, InstanceKeyLRUCache } from "./internal/ElementLRUCache";
51
51
  import { IModelIncrementalSchemaLocater } from "./IModelIncrementalSchemaLocater";
52
+ import { integrityCheckTypeMap, performQuickIntegrityCheck, performSpecificIntegrityCheck } from "./internal/IntegrityCheck";
52
53
  // spell:ignore fontid fontmap
53
54
  const loggerCategory = BackendLoggerCategory.IModelDb;
54
55
  /** @internal */
@@ -277,11 +278,15 @@ export class IModelDb extends IModel {
277
278
  this.clearCaches();
278
279
  this[_nativeDb].detachDb(alias);
279
280
  }
280
- /** Close this IModel, if it is currently open, and save changes if it was opened in ReadWrite mode. */
281
- close() {
281
+ /** Close this IModel, if it is currently open, and save changes if it was opened in ReadWrite mode.
282
+ * @param options Options for closing the iModel.
283
+ */
284
+ close(options) {
282
285
  if (!this.isOpen)
283
286
  return; // don't continue if already closed
284
287
  this.beforeClose();
288
+ if (options?.optimize)
289
+ this.optimize();
285
290
  IModelDb._openDbs.delete(this._fileKey);
286
291
  this._workspace?.close();
287
292
  this.locks[_close]();
@@ -292,6 +297,90 @@ export class IModelDb extends IModel {
292
297
  this.saveChanges();
293
298
  this[_nativeDb].closeFile();
294
299
  }
300
+ /** Optimize this iModel by vacuuming, and analyzing.
301
+ *
302
+ * @note This operation requires exclusive access to the database and may take some time on large files.
303
+ * @beta
304
+ */
305
+ optimize() {
306
+ // Vacuum to reclaim space and defragment
307
+ this.vacuum();
308
+ // Analyze to update statistics for query optimizer
309
+ this.analyze();
310
+ }
311
+ /**
312
+ * Vacuum the model to reclaim space and defragment.
313
+ * @throws [[IModelError]] if the iModel is not open or is read-only.
314
+ * @beta
315
+ */
316
+ vacuum() {
317
+ if (!this.isOpen || this.isReadonly)
318
+ throw new IModelError(IModelStatus.BadRequest, "IModel is not open or is read-only");
319
+ this[_nativeDb].clearECDbCache();
320
+ this[_nativeDb].vacuum();
321
+ }
322
+ /**
323
+ * Update SQLite query optimizer statistics for this iModel.
324
+ * This helps SQLite choose better query plans.
325
+ *
326
+ * @throws [[IModelError]] if the iModel is not open or is read-only.
327
+ * @beta
328
+ */
329
+ analyze() {
330
+ if (!this.isOpen || this.isReadonly)
331
+ throw new IModelError(IModelStatus.BadRequest, "IModel is not open or is read-only");
332
+ this[_nativeDb].analyze();
333
+ }
334
+ /**
335
+ * Performs integrity checks on this iModel.
336
+ * Types of integrity checks that can be performed are:
337
+ *
338
+ * Default Check:
339
+ * - Quick Check: Runs all integrity checks below and returns whether each check passed or failed, without detailed results.
340
+ *
341
+ * Specific Checks:
342
+ * - Data Columns Check: Checks if all the required columns exist in data tables. Issues are returned as a list of those tables/columns.
343
+ * - EC Profile Check: Checks if the profile table, indexes, and triggers are present. Does not check be_* tables. Issues are returned as a list of tables/indexes/triggers which were not found or have different DDL.
344
+ * - Navigation Class Ids Check: Checks if RelClassId of a Navigation property is a valid ECClassId. It does not check the value to match the relationship class.
345
+ * - Navigation Ids Check: Checks if Id of a Navigation property matches a valid row primary class.
346
+ * - Linktable Foreign Key Class Ids Check: Checks if SourceECClassId or TargetECClassId of a link table matches a valid ECClassId.
347
+ * - Linktable Foreign Key Ids Check: Checks if SourceECInstanceId or TargetECInstanceId of a link table matches a valid row in primary class.
348
+ * - Class Ids Check: Checks persisted ECClassId in all data tables and makes sure they are valid.
349
+ * - Data Schema Check: Checks if all the required data tables and indexes exist for mapped classes. Issues are returned as a list of tables/columns which were not found or have different DDL.
350
+ * - Schema Load Check: Checks if all schemas can be loaded into memory.
351
+ * - Missing Child Rows Check: Checks if all child rows have a corresponding parent row.
352
+ *
353
+ * @param options Options specifying which integrity checks to perform. If no options are provided or all options are false, a quick check will be performed by default.
354
+ * @returns An array of integrity check results.
355
+ * @throws [[IModelError]] if the iModel is not open.
356
+ * @beta
357
+ */
358
+ async integrityCheck(options) {
359
+ if (!this.isOpen)
360
+ throw new IModelError(IModelStatus.BadRequest, "IModel is not open");
361
+ // Default to quick check if no options provided at all, or if not explicitly set and no specific checks are enabled
362
+ if (!options || (!options.quickCheck && (!options.specificChecks || !Object.values(options.specificChecks).some(Boolean)))) {
363
+ options = { ...options, quickCheck: true };
364
+ }
365
+ const integrityCheckResults = [];
366
+ // Perform a quick check if requested
367
+ if (options.quickCheck) {
368
+ const results = await performQuickIntegrityCheck(this);
369
+ const passed = results.every((result) => result.passed);
370
+ integrityCheckResults.push({ check: "Quick Check", passed, results });
371
+ }
372
+ // Perform all specific checks requested
373
+ if (options.specificChecks) {
374
+ for (const [checkKey, checkParams] of Object.entries(integrityCheckTypeMap)) {
375
+ if (options.specificChecks[checkKey]) {
376
+ const results = await performSpecificIntegrityCheck(this, checkKey);
377
+ const passed = results.length === 0;
378
+ integrityCheckResults.push({ check: checkParams.name, passed, results });
379
+ }
380
+ }
381
+ }
382
+ return integrityCheckResults;
383
+ }
295
384
  /** @internal */
296
385
  async refreshContainerForRpc(_userAccessToken) { }
297
386
  /** Event called when the iModel is about to be closed. */
@@ -3259,11 +3348,11 @@ export class BriefcaseDb extends IModelDb {
3259
3348
  });
3260
3349
  this.txns._onChangesPushed(this.changeset);
3261
3350
  }
3262
- close() {
3351
+ close(options) {
3263
3352
  if (this.isBriefcase && this.isOpen && !this.isReadonly && this.txns.rebaser.inProgress()) {
3264
3353
  this.abandonChanges();
3265
3354
  }
3266
- super.close();
3355
+ super.close(options);
3267
3356
  this.onClosed.raiseEvent();
3268
3357
  }
3269
3358
  }