@itwin/core-backend 5.7.0-dev.10 → 5.7.0-dev.12

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.
@@ -55,14 +55,14 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
55
55
  * See LICENSE.md in the project root for license terms and full copyright notice.
56
56
  *--------------------------------------------------------------------------------------------*/
57
57
  import { DbResult, Id64 } from "@itwin/core-bentley";
58
- import { Code, ColorDef, IModel, QueryBinder, SubCategoryAppearance } from "@itwin/core-common";
58
+ import { Code, ColorDef, IModel, QueryBinder, QueryRowFormat, SubCategoryAppearance } from "@itwin/core-common";
59
59
  import { Arc3d, IModelJson, Point3d } from "@itwin/core-geometry";
60
60
  import * as chai from "chai";
61
61
  import { assert, expect } from "chai";
62
62
  import * as path from "node:path";
63
63
  import { DrawingCategory } from "../../Category";
64
64
  import { ChangesetECAdaptor, ChangesetECAdaptor as ECChangesetAdaptor, ECChangeUnifierCache, PartialECChangeUnifier } from "../../ChangesetECAdaptor";
65
- import { _nativeDb, ChannelControl, GraphicalElement2d } from "../../core-backend";
65
+ import { _nativeDb, ChannelControl, GraphicalElement2d, Subject, SubjectOwnsSubjects } from "../../core-backend";
66
66
  import { BriefcaseDb, SnapshotDb } from "../../IModelDb";
67
67
  import { HubMock } from "../../internal/HubMock";
68
68
  import { SqliteChangesetReader } from "../../SqliteChangesetReader";
@@ -1657,4 +1657,175 @@ describe("Changeset Reader API", async () => {
1657
1657
  b1.close();
1658
1658
  });
1659
1659
  });
1660
+ describe("PRAGMA ECSQL Functions", async () => {
1661
+ let iTwinId;
1662
+ let iModel;
1663
+ before(() => {
1664
+ HubMock.startup("ChangesetReaderTest", KnownTestLocations.outputDir);
1665
+ iTwinId = HubMock.iTwinId;
1666
+ });
1667
+ after(() => HubMock.shutdown());
1668
+ beforeEach(async () => {
1669
+ // Create new iModel
1670
+ const adminToken = "super manager token";
1671
+ const iModelName = "PRAGMA_test";
1672
+ const iModelId = await HubMock.createNewIModel({ iTwinId, iModelName, description: "TestSubject", accessToken: adminToken });
1673
+ assert.isNotEmpty(iModelId);
1674
+ iModel = await HubWrappers.downloadAndOpenBriefcase({ iTwinId, iModelId, accessToken: adminToken });
1675
+ });
1676
+ afterEach(() => {
1677
+ // Cleanup
1678
+ iModel.close();
1679
+ });
1680
+ it("should call PRAGMA integrity_check on a new iModel and return no errors", async () => {
1681
+ // Call PRAGMA integrity_check
1682
+ const query = "PRAGMA integrity_check ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES";
1683
+ const result = iModel.createQueryReader(query, undefined, undefined);
1684
+ const results = await result.toArray();
1685
+ // Verify no errors
1686
+ assert(results.length > 0, "Results should be returned from PRAGMA integrity_check");
1687
+ assert(results[0][2] === true, "'check_data_columns' check should be true");
1688
+ assert(results[1][2] === true, "'check_ec_profile' check should be true");
1689
+ assert(results[2][2] === true, "'check_nav_class_ids' check should be true");
1690
+ assert(results[3][2] === true, "'check_nav_ids' check should be true");
1691
+ assert(results[4][2] === true, "'check_linktable_fk_class_ids' check should be true");
1692
+ assert(results[5][2] === true, "'check_linktable_fk_ids' check should be true");
1693
+ assert(results[6][2] === true, "'check_class_ids' check should be true");
1694
+ assert(results[7][2] === true, "'check_data_schema' check should be true");
1695
+ assert(results[8][2] === true, "'check_schema_load' check should be true");
1696
+ });
1697
+ it("should call PRAGMA integrity_check individual checks on a new iModel and return no errors", async () => {
1698
+ // Call check_ec_profile
1699
+ let query = "pragma integrity_check(check_ec_profile) options enable_experimental_features";
1700
+ let result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1701
+ let resultArray = await result.toArray();
1702
+ expect(resultArray.length).to.equal(0); // No errors expected
1703
+ // Call check_data_schema
1704
+ query = "pragma integrity_check(check_data_schema) options enable_experimental_features";
1705
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1706
+ resultArray = await result.toArray();
1707
+ expect(resultArray.length).to.equal(0); // No errors expected
1708
+ // Call check_data_columns
1709
+ query = "pragma integrity_check(check_data_columns) options enable_experimental_features";
1710
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1711
+ resultArray = await result.toArray();
1712
+ expect(resultArray.length).to.equal(0); // No errors expected
1713
+ // Call check_nav_class_ids
1714
+ query = "pragma integrity_check(check_nav_class_ids) options enable_experimental_features";
1715
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1716
+ resultArray = await result.toArray();
1717
+ expect(resultArray.length).to.equal(0); // No errors expected
1718
+ // Call check_nav_ids
1719
+ query = "pragma integrity_check(check_nav_ids) options enable_experimental_features";
1720
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1721
+ resultArray = await result.toArray();
1722
+ expect(resultArray.length).to.equal(0); // No errors expected
1723
+ // Call check_linktable_fk_class_ids
1724
+ query = "pragma integrity_check(check_linktable_fk_class_ids) options enable_experimental_features";
1725
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1726
+ resultArray = await result.toArray();
1727
+ expect(resultArray.length).to.equal(0); // No errors expected
1728
+ // Call check_linktable_fk_ids
1729
+ query = "pragma integrity_check(check_linktable_fk_ids) options enable_experimental_features";
1730
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1731
+ resultArray = await result.toArray();
1732
+ expect(resultArray.length).to.equal(0); // No errors expected
1733
+ // Call check_class_ids
1734
+ query = "pragma integrity_check(check_class_ids) options enable_experimental_features";
1735
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1736
+ resultArray = await result.toArray();
1737
+ expect(resultArray.length).to.equal(0); // No errors expected
1738
+ // Call check_schema_load
1739
+ query = "pragma integrity_check(check_schema_load) options enable_experimental_features";
1740
+ result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1741
+ resultArray = await result.toArray();
1742
+ expect(resultArray.length).to.equal(0); // No errors expected
1743
+ });
1744
+ it("should call PRAGMA integrity_check on a corrupted iModel and return an error", async () => {
1745
+ // Insert two elements
1746
+ iModel.channels.addAllowedChannel(ChannelControl.sharedChannelName);
1747
+ await iModel.locks.acquireLocks({ shared: IModel.repositoryModelId });
1748
+ const element1Id = iModel.elements.insertElement({
1749
+ classFullName: Subject.classFullName,
1750
+ model: IModel.repositoryModelId,
1751
+ parent: new SubjectOwnsSubjects(IModel.rootSubjectId),
1752
+ code: Subject.createCode(iModel, IModel.rootSubjectId, "Subject1"),
1753
+ });
1754
+ const element2Id = iModel.elements.insertElement({
1755
+ classFullName: Subject.classFullName,
1756
+ model: IModel.repositoryModelId,
1757
+ parent: new SubjectOwnsSubjects(IModel.rootSubjectId),
1758
+ code: Subject.createCode(iModel, IModel.rootSubjectId, "Subject2"),
1759
+ });
1760
+ iModel.saveChanges();
1761
+ // Create a relationship between them
1762
+ await iModel.locks.acquireLocks({ exclusive: Id64.toIdSet([element1Id, element2Id]) });
1763
+ const relationship = iModel.relationships.createInstance({
1764
+ classFullName: "BisCore:SubjectRefersToSubject",
1765
+ sourceId: element1Id,
1766
+ targetId: element2Id,
1767
+ });
1768
+ const relationshipId = iModel.relationships.insertInstance(relationship.toJSON());
1769
+ assert.isTrue(Id64.isValidId64(relationshipId));
1770
+ iModel.saveChanges();
1771
+ // Delete one element without deleting the relationship to corrupt the iModel
1772
+ const deleteResult = iModel[_nativeDb].executeSql(`DELETE FROM bis_Element WHERE Id=${element2Id}`);
1773
+ expect(deleteResult).to.equal(DbResult.BE_SQLITE_OK);
1774
+ iModel.saveChanges();
1775
+ // Call PRAGMA integrity_check
1776
+ const query = "PRAGMA integrity_check ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES";
1777
+ const result = iModel.createQueryReader(query, undefined, undefined);
1778
+ const results = await result.toArray();
1779
+ // Verify error is reported
1780
+ assert(results.length > 0, "Results should be returned from PRAGMA integrity_check");
1781
+ assert(results[0][2] === true, "'check_data_columns' check should be true");
1782
+ assert(results[1][2] === true, "'check_ec_profile' check should be true");
1783
+ assert(results[2][2] === true, "'check_nav_class_ids' check should be true");
1784
+ assert(results[3][2] === true, "'check_nav_ids' check should be true");
1785
+ assert(results[4][2] === true, "'check_linktable_fk_class_ids' check should be true");
1786
+ assert(results[5][2] === false, "'check_linktable_fk_ids' check should be false"); // Expecting error report here
1787
+ assert(results[6][2] === true, "'check_class_ids' check should be true");
1788
+ assert(results[7][2] === true, "'check_data_schema' check should be true");
1789
+ assert(results[8][2] === true, "'check_schema_load' check should be true");
1790
+ });
1791
+ it("should call PRAGMA integrity_check(check_linktable_fk_class_ids) on a corrupted iModel and return an error", async () => {
1792
+ // Insert two elements
1793
+ iModel.channels.addAllowedChannel(ChannelControl.sharedChannelName);
1794
+ await iModel.locks.acquireLocks({ shared: IModel.repositoryModelId });
1795
+ const element1Id = iModel.elements.insertElement({
1796
+ classFullName: Subject.classFullName,
1797
+ model: IModel.repositoryModelId,
1798
+ parent: new SubjectOwnsSubjects(IModel.rootSubjectId),
1799
+ code: Subject.createCode(iModel, IModel.rootSubjectId, "Subject1"),
1800
+ });
1801
+ const element2Id = iModel.elements.insertElement({
1802
+ classFullName: Subject.classFullName,
1803
+ model: IModel.repositoryModelId,
1804
+ parent: new SubjectOwnsSubjects(IModel.rootSubjectId),
1805
+ code: Subject.createCode(iModel, IModel.rootSubjectId, "Subject2"),
1806
+ });
1807
+ iModel.saveChanges();
1808
+ // Create a relationship between them
1809
+ await iModel.locks.acquireLocks({ exclusive: Id64.toIdSet([element1Id, element2Id]) });
1810
+ const relationship = iModel.relationships.createInstance({
1811
+ classFullName: "BisCore:SubjectRefersToSubject",
1812
+ sourceId: element1Id,
1813
+ targetId: element2Id,
1814
+ });
1815
+ const relationshipId = iModel.relationships.insertInstance(relationship.toJSON());
1816
+ assert.isTrue(Id64.isValidId64(relationshipId));
1817
+ iModel.saveChanges();
1818
+ // Delete one element without deleting the relationship to corrupt the iModel
1819
+ const deleteResult = iModel[_nativeDb].executeSql(`DELETE FROM bis_Element WHERE Id=${element2Id}`);
1820
+ expect(deleteResult).to.equal(DbResult.BE_SQLITE_OK);
1821
+ iModel.saveChanges();
1822
+ // Call PRAGMA integrity_check
1823
+ const query = "pragma integrity_check(check_linktable_fk_ids) options enable_experimental_features";
1824
+ const result = iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyNames });
1825
+ const resultArray = await result.toArray();
1826
+ expect(resultArray.length).to.equal(1); // 1 error report expected
1827
+ expect(resultArray[0].id).to.equal("0x20000000001");
1828
+ expect(resultArray[0].key_id).to.equal("0x20000000002");
1829
+ });
1830
+ });
1660
1831
  //# sourceMappingURL=ChangesetReader.test.js.map