@itwin/core-backend 5.9.0-dev.1 → 5.9.0-dev.10
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.
- package/CHANGELOG.md +30 -1
- package/lib/cjs/BackendHubAccess.d.ts +38 -0
- package/lib/cjs/BackendHubAccess.d.ts.map +1 -1
- package/lib/cjs/BackendHubAccess.js.map +1 -1
- package/lib/cjs/BriefcaseManager.js +3 -3
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/Category.d.ts +37 -7
- package/lib/cjs/Category.d.ts.map +1 -1
- package/lib/cjs/Category.js +33 -42
- package/lib/cjs/Category.js.map +1 -1
- package/lib/cjs/ChangesetECAdaptor.d.ts.map +1 -1
- package/lib/cjs/ChangesetECAdaptor.js +5 -2
- package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
- package/lib/cjs/ChannelControl.d.ts +29 -0
- package/lib/cjs/ChannelControl.d.ts.map +1 -1
- package/lib/cjs/ChannelControl.js.map +1 -1
- package/lib/cjs/CheckpointManager.js +1 -1
- package/lib/cjs/CheckpointManager.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts +1 -1
- package/lib/cjs/CloudSqlite.d.ts.map +1 -1
- package/lib/cjs/CloudSqlite.js +68 -13
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/CodeSpecs.d.ts +32 -3
- package/lib/cjs/CodeSpecs.d.ts.map +1 -1
- package/lib/cjs/CodeSpecs.js +48 -20
- package/lib/cjs/CodeSpecs.js.map +1 -1
- package/lib/cjs/DisplayStyle.d.ts +18 -3
- package/lib/cjs/DisplayStyle.d.ts.map +1 -1
- package/lib/cjs/DisplayStyle.js +10 -21
- package/lib/cjs/DisplayStyle.js.map +1 -1
- package/lib/cjs/EditTxn.d.ts +262 -0
- package/lib/cjs/EditTxn.d.ts.map +1 -0
- package/lib/cjs/EditTxn.js +548 -0
- package/lib/cjs/EditTxn.js.map +1 -0
- package/lib/cjs/Element.d.ts +74 -5
- package/lib/cjs/Element.d.ts.map +1 -1
- package/lib/cjs/Element.js +63 -75
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/ElementAspect.d.ts +10 -0
- package/lib/cjs/ElementAspect.d.ts.map +1 -1
- package/lib/cjs/ElementAspect.js +21 -12
- package/lib/cjs/ElementAspect.js.map +1 -1
- package/lib/cjs/ElementTreeWalker.d.ts +56 -3
- package/lib/cjs/ElementTreeWalker.d.ts.map +1 -1
- package/lib/cjs/ElementTreeWalker.js +53 -40
- package/lib/cjs/ElementTreeWalker.js.map +1 -1
- package/lib/cjs/ExternalSource.d.ts +11 -2
- package/lib/cjs/ExternalSource.d.ts.map +1 -1
- package/lib/cjs/ExternalSource.js +10 -8
- package/lib/cjs/ExternalSource.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +66 -22
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +175 -289
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/IModelHost.d.ts +58 -1
- package/lib/cjs/IModelHost.d.ts.map +1 -1
- package/lib/cjs/IModelHost.js +89 -0
- package/lib/cjs/IModelHost.js.map +1 -1
- package/lib/cjs/IpcHost.d.ts.map +1 -1
- package/lib/cjs/IpcHost.js +35 -15
- package/lib/cjs/IpcHost.js.map +1 -1
- package/lib/cjs/LineStyle.d.ts +47 -7
- package/lib/cjs/LineStyle.d.ts.map +1 -1
- package/lib/cjs/LineStyle.js +38 -33
- package/lib/cjs/LineStyle.js.map +1 -1
- package/lib/cjs/LockControl.d.ts +85 -1
- package/lib/cjs/LockControl.d.ts.map +1 -1
- package/lib/cjs/LockControl.js.map +1 -1
- package/lib/cjs/Material.d.ts +8 -1
- package/lib/cjs/Material.d.ts.map +1 -1
- package/lib/cjs/Material.js +6 -12
- package/lib/cjs/Material.js.map +1 -1
- package/lib/cjs/Model.d.ts +59 -20
- package/lib/cjs/Model.d.ts.map +1 -1
- package/lib/cjs/Model.js +38 -80
- package/lib/cjs/Model.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +72 -7
- package/lib/cjs/Relationship.d.ts.map +1 -1
- package/lib/cjs/Relationship.js +39 -21
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/SchemaSync.js +4 -4
- package/lib/cjs/SchemaSync.js.map +1 -1
- package/lib/cjs/SheetIndex.d.ts +9 -0
- package/lib/cjs/SheetIndex.d.ts.map +1 -1
- package/lib/cjs/SheetIndex.js +38 -35
- package/lib/cjs/SheetIndex.js.map +1 -1
- package/lib/cjs/StashManager.js +1 -1
- package/lib/cjs/StashManager.js.map +1 -1
- package/lib/cjs/Texture.d.ts +6 -0
- package/lib/cjs/Texture.d.ts.map +1 -1
- package/lib/cjs/Texture.js +6 -14
- package/lib/cjs/Texture.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts +105 -9
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +194 -15
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/ViewDefinition.d.ts +21 -1
- package/lib/cjs/ViewDefinition.d.ts.map +1 -1
- package/lib/cjs/ViewDefinition.js +27 -66
- package/lib/cjs/ViewDefinition.js.map +1 -1
- package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +14 -6
- package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
- package/lib/cjs/annotations/ElementDrivesTextAnnotation.js +33 -27
- package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -1
- package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
- package/lib/cjs/annotations/TextAnnotationElement.js +6 -5
- package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
- package/lib/cjs/core-backend.d.ts +1 -0
- package/lib/cjs/core-backend.d.ts.map +1 -1
- package/lib/cjs/core-backend.js +1 -0
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/domains/FunctionalElements.d.ts +6 -2
- package/lib/cjs/domains/FunctionalElements.d.ts.map +1 -1
- package/lib/cjs/domains/FunctionalElements.js +8 -13
- package/lib/cjs/domains/FunctionalElements.js.map +1 -1
- package/lib/cjs/domains/GenericElements.d.ts +11 -4
- package/lib/cjs/domains/GenericElements.d.ts.map +1 -1
- package/lib/cjs/domains/GenericElements.js +13 -24
- package/lib/cjs/domains/GenericElements.js.map +1 -1
- package/lib/cjs/internal/ChannelAdmin.d.ts +15 -0
- package/lib/cjs/internal/ChannelAdmin.d.ts.map +1 -1
- package/lib/cjs/internal/ChannelAdmin.js +5 -3
- package/lib/cjs/internal/ChannelAdmin.js.map +1 -1
- package/lib/cjs/internal/HubMock.d.ts +2 -0
- package/lib/cjs/internal/HubMock.d.ts.map +1 -1
- package/lib/cjs/internal/HubMock.js +7 -0
- package/lib/cjs/internal/HubMock.js.map +1 -1
- package/lib/cjs/internal/NoLocks.d.ts.map +1 -1
- package/lib/cjs/internal/NoLocks.js +6 -0
- package/lib/cjs/internal/NoLocks.js.map +1 -1
- package/lib/cjs/internal/ServerBasedLocks.d.ts +12 -0
- package/lib/cjs/internal/ServerBasedLocks.d.ts.map +1 -1
- package/lib/cjs/internal/ServerBasedLocks.js +285 -4
- package/lib/cjs/internal/ServerBasedLocks.js.map +1 -1
- package/lib/cjs/internal/Symbols.d.ts +4 -0
- package/lib/cjs/internal/Symbols.d.ts.map +1 -1
- package/lib/cjs/internal/Symbols.js +5 -1
- package/lib/cjs/internal/Symbols.js.map +1 -1
- package/lib/cjs/internal/annotations/fields.d.ts +3 -2
- package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
- package/lib/cjs/internal/annotations/fields.js +7 -6
- package/lib/cjs/internal/annotations/fields.js.map +1 -1
- package/lib/cjs/internal/workspace/SettingsEditorImpl.d.ts +18 -3
- package/lib/cjs/internal/workspace/SettingsEditorImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/SettingsEditorImpl.js +49 -242
- package/lib/cjs/internal/workspace/SettingsEditorImpl.js.map +1 -1
- package/lib/cjs/internal/workspace/SettingsImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/SettingsImpl.js.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts +0 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.js +70 -41
- package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.d.ts.map +1 -1
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
- package/lib/cjs/workspace/Settings.d.ts +11 -5
- package/lib/cjs/workspace/Settings.d.ts.map +1 -1
- package/lib/cjs/workspace/Settings.js.map +1 -1
- package/lib/cjs/workspace/SettingsDb.d.ts +20 -99
- package/lib/cjs/workspace/SettingsDb.d.ts.map +1 -1
- package/lib/cjs/workspace/SettingsDb.js +23 -7
- package/lib/cjs/workspace/SettingsDb.js.map +1 -1
- package/lib/cjs/workspace/SettingsEditor.d.ts +40 -226
- package/lib/cjs/workspace/SettingsEditor.d.ts.map +1 -1
- package/lib/cjs/workspace/SettingsEditor.js +86 -25
- package/lib/cjs/workspace/SettingsEditor.js.map +1 -1
- package/lib/cjs/workspace/Workspace.d.ts +7 -11
- package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
- package/lib/cjs/workspace/Workspace.js.map +1 -1
- package/lib/cjs/workspace/WorkspaceEditor.d.ts +14 -0
- package/lib/cjs/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/lib/cjs/workspace/WorkspaceEditor.js +1 -1
- package/lib/cjs/workspace/WorkspaceEditor.js.map +1 -1
- package/lib/esm/BackendHubAccess.d.ts +38 -0
- package/lib/esm/BackendHubAccess.d.ts.map +1 -1
- package/lib/esm/BackendHubAccess.js.map +1 -1
- package/lib/esm/BriefcaseManager.js +3 -3
- package/lib/esm/BriefcaseManager.js.map +1 -1
- package/lib/esm/Category.d.ts +37 -7
- package/lib/esm/Category.d.ts.map +1 -1
- package/lib/esm/Category.js +33 -42
- package/lib/esm/Category.js.map +1 -1
- package/lib/esm/ChangesetECAdaptor.d.ts.map +1 -1
- package/lib/esm/ChangesetECAdaptor.js +5 -2
- package/lib/esm/ChangesetECAdaptor.js.map +1 -1
- package/lib/esm/ChannelControl.d.ts +29 -0
- package/lib/esm/ChannelControl.d.ts.map +1 -1
- package/lib/esm/ChannelControl.js.map +1 -1
- package/lib/esm/CheckpointManager.js +1 -1
- package/lib/esm/CheckpointManager.js.map +1 -1
- package/lib/esm/CloudSqlite.d.ts +1 -1
- package/lib/esm/CloudSqlite.d.ts.map +1 -1
- package/lib/esm/CloudSqlite.js +69 -14
- package/lib/esm/CloudSqlite.js.map +1 -1
- package/lib/esm/CodeSpecs.d.ts +32 -3
- package/lib/esm/CodeSpecs.d.ts.map +1 -1
- package/lib/esm/CodeSpecs.js +49 -21
- package/lib/esm/CodeSpecs.js.map +1 -1
- package/lib/esm/DisplayStyle.d.ts +18 -3
- package/lib/esm/DisplayStyle.d.ts.map +1 -1
- package/lib/esm/DisplayStyle.js +10 -21
- package/lib/esm/DisplayStyle.js.map +1 -1
- package/lib/esm/EditTxn.d.ts +262 -0
- package/lib/esm/EditTxn.d.ts.map +1 -0
- package/lib/esm/EditTxn.js +543 -0
- package/lib/esm/EditTxn.js.map +1 -0
- package/lib/esm/Element.d.ts +74 -5
- package/lib/esm/Element.d.ts.map +1 -1
- package/lib/esm/Element.js +64 -76
- package/lib/esm/Element.js.map +1 -1
- package/lib/esm/ElementAspect.d.ts +10 -0
- package/lib/esm/ElementAspect.d.ts.map +1 -1
- package/lib/esm/ElementAspect.js +22 -13
- package/lib/esm/ElementAspect.js.map +1 -1
- package/lib/esm/ElementTreeWalker.d.ts +56 -3
- package/lib/esm/ElementTreeWalker.d.ts.map +1 -1
- package/lib/esm/ElementTreeWalker.js +53 -40
- package/lib/esm/ElementTreeWalker.js.map +1 -1
- package/lib/esm/ExternalSource.d.ts +11 -2
- package/lib/esm/ExternalSource.d.ts.map +1 -1
- package/lib/esm/ExternalSource.js +10 -8
- package/lib/esm/ExternalSource.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +66 -22
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +177 -291
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/IModelHost.d.ts +58 -1
- package/lib/esm/IModelHost.d.ts.map +1 -1
- package/lib/esm/IModelHost.js +91 -2
- package/lib/esm/IModelHost.js.map +1 -1
- package/lib/esm/IpcHost.d.ts.map +1 -1
- package/lib/esm/IpcHost.js +36 -16
- package/lib/esm/IpcHost.js.map +1 -1
- package/lib/esm/LineStyle.d.ts +47 -7
- package/lib/esm/LineStyle.d.ts.map +1 -1
- package/lib/esm/LineStyle.js +38 -33
- package/lib/esm/LineStyle.js.map +1 -1
- package/lib/esm/LockControl.d.ts +85 -1
- package/lib/esm/LockControl.d.ts.map +1 -1
- package/lib/esm/LockControl.js.map +1 -1
- package/lib/esm/Material.d.ts +8 -1
- package/lib/esm/Material.d.ts.map +1 -1
- package/lib/esm/Material.js +6 -12
- package/lib/esm/Material.js.map +1 -1
- package/lib/esm/Model.d.ts +59 -20
- package/lib/esm/Model.d.ts.map +1 -1
- package/lib/esm/Model.js +39 -81
- package/lib/esm/Model.js.map +1 -1
- package/lib/esm/Relationship.d.ts +72 -7
- package/lib/esm/Relationship.d.ts.map +1 -1
- package/lib/esm/Relationship.js +40 -22
- package/lib/esm/Relationship.js.map +1 -1
- package/lib/esm/SchemaSync.js +5 -5
- package/lib/esm/SchemaSync.js.map +1 -1
- package/lib/esm/SheetIndex.d.ts +9 -0
- package/lib/esm/SheetIndex.d.ts.map +1 -1
- package/lib/esm/SheetIndex.js +38 -35
- package/lib/esm/SheetIndex.js.map +1 -1
- package/lib/esm/StashManager.js +1 -1
- package/lib/esm/StashManager.js.map +1 -1
- package/lib/esm/Texture.d.ts +6 -0
- package/lib/esm/Texture.d.ts.map +1 -1
- package/lib/esm/Texture.js +6 -14
- package/lib/esm/Texture.js.map +1 -1
- package/lib/esm/TxnManager.d.ts +105 -9
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +194 -15
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/ViewDefinition.d.ts +21 -1
- package/lib/esm/ViewDefinition.d.ts.map +1 -1
- package/lib/esm/ViewDefinition.js +27 -66
- package/lib/esm/ViewDefinition.js.map +1 -1
- package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +14 -6
- package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
- package/lib/esm/annotations/ElementDrivesTextAnnotation.js +33 -27
- package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -1
- package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
- package/lib/esm/annotations/TextAnnotationElement.js +6 -5
- package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
- package/lib/esm/core-backend.d.ts +1 -0
- package/lib/esm/core-backend.d.ts.map +1 -1
- package/lib/esm/core-backend.js +1 -0
- package/lib/esm/core-backend.js.map +1 -1
- package/lib/esm/domains/FunctionalElements.d.ts +6 -2
- package/lib/esm/domains/FunctionalElements.d.ts.map +1 -1
- package/lib/esm/domains/FunctionalElements.js +8 -13
- package/lib/esm/domains/FunctionalElements.js.map +1 -1
- package/lib/esm/domains/GenericElements.d.ts +11 -4
- package/lib/esm/domains/GenericElements.d.ts.map +1 -1
- package/lib/esm/domains/GenericElements.js +13 -24
- package/lib/esm/domains/GenericElements.js.map +1 -1
- package/lib/esm/internal/ChannelAdmin.d.ts +15 -0
- package/lib/esm/internal/ChannelAdmin.d.ts.map +1 -1
- package/lib/esm/internal/ChannelAdmin.js +6 -4
- package/lib/esm/internal/ChannelAdmin.js.map +1 -1
- package/lib/esm/internal/HubMock.d.ts +2 -0
- package/lib/esm/internal/HubMock.d.ts.map +1 -1
- package/lib/esm/internal/HubMock.js +7 -0
- package/lib/esm/internal/HubMock.js.map +1 -1
- package/lib/esm/internal/NoLocks.d.ts.map +1 -1
- package/lib/esm/internal/NoLocks.js +6 -0
- package/lib/esm/internal/NoLocks.js.map +1 -1
- package/lib/esm/internal/ServerBasedLocks.d.ts +12 -0
- package/lib/esm/internal/ServerBasedLocks.d.ts.map +1 -1
- package/lib/esm/internal/ServerBasedLocks.js +286 -5
- package/lib/esm/internal/ServerBasedLocks.js.map +1 -1
- package/lib/esm/internal/Symbols.d.ts +4 -0
- package/lib/esm/internal/Symbols.d.ts.map +1 -1
- package/lib/esm/internal/Symbols.js +4 -0
- package/lib/esm/internal/Symbols.js.map +1 -1
- package/lib/esm/internal/annotations/fields.d.ts +3 -2
- package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
- package/lib/esm/internal/annotations/fields.js +7 -6
- package/lib/esm/internal/annotations/fields.js.map +1 -1
- package/lib/esm/internal/workspace/SettingsEditorImpl.d.ts +18 -3
- package/lib/esm/internal/workspace/SettingsEditorImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/SettingsEditorImpl.js +52 -246
- package/lib/esm/internal/workspace/SettingsEditorImpl.js.map +1 -1
- package/lib/esm/internal/workspace/SettingsImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/SettingsImpl.js.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts +0 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.js +71 -41
- package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/esm/rpc-impl/RpcBriefcaseUtility.d.ts.map +1 -1
- package/lib/esm/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
- package/lib/esm/test/AnnotationTestUtils.js.map +1 -1
- package/lib/esm/test/ElementDrivesElement.test.d.ts +20 -19
- package/lib/esm/test/ElementDrivesElement.test.d.ts.map +1 -1
- package/lib/esm/test/ElementDrivesElement.test.js +111 -96
- package/lib/esm/test/ElementDrivesElement.test.js.map +1 -1
- package/lib/esm/test/ElementLRUCache.test.js.map +1 -1
- package/lib/esm/test/IModelHost.test.js +56 -2
- package/lib/esm/test/IModelHost.test.js.map +1 -1
- package/lib/esm/test/IModelTestUtils.d.ts +23 -23
- package/lib/esm/test/IModelTestUtils.d.ts.map +1 -1
- package/lib/esm/test/IModelTestUtils.js +466 -449
- package/lib/esm/test/IModelTestUtils.js.map +1 -1
- package/lib/esm/test/IpcHost.test.js +112 -0
- package/lib/esm/test/IpcHost.test.js.map +1 -1
- package/lib/esm/test/PropertyDb.test.js +2 -2
- package/lib/esm/test/PropertyDb.test.js.map +1 -1
- package/lib/esm/test/SquashSchemaAndDataChanges.test.js +27 -18
- package/lib/esm/test/SquashSchemaAndDataChanges.test.js.map +1 -1
- package/lib/esm/test/TestChangeSetUtility.d.ts.map +1 -1
- package/lib/esm/test/TestChangeSetUtility.js +11 -7
- package/lib/esm/test/TestChangeSetUtility.js.map +1 -1
- package/lib/esm/test/TestEditTxn.d.ts +8 -0
- package/lib/esm/test/TestEditTxn.d.ts.map +1 -0
- package/lib/esm/test/TestEditTxn.js +34 -0
- package/lib/esm/test/TestEditTxn.js.map +1 -0
- package/lib/esm/test/TestUtils.d.ts +1 -0
- package/lib/esm/test/TestUtils.d.ts.map +1 -1
- package/lib/esm/test/TestUtils.js +8 -1
- package/lib/esm/test/TestUtils.js.map +1 -1
- package/lib/esm/test/annotations/Fields.test.js +82 -90
- package/lib/esm/test/annotations/Fields.test.js.map +1 -1
- package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
- package/lib/esm/test/annotations/TextAnnotation.test.js +156 -99
- package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
- package/lib/esm/test/annotations/TextBlock.test.js +5 -3
- package/lib/esm/test/annotations/TextBlock.test.js.map +1 -1
- package/lib/esm/test/assets/IncrementalSchemaLocater/configs/old.config.js.map +1 -1
- package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js.map +1 -1
- package/lib/esm/test/categories/Category.test.js +63 -3
- package/lib/esm/test/categories/Category.test.js.map +1 -1
- package/lib/esm/test/codespec/CodeSpec.test.js +88 -5
- package/lib/esm/test/codespec/CodeSpec.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECDb.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlAst.test.js +3 -2
- package/lib/esm/test/ecdb/ECSqlAst.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlQuery.test.js +2 -2
- package/lib/esm/test/ecdb/ECSqlQuery.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlStatement.test.js +0 -1
- package/lib/esm/test/ecdb/ECSqlStatement.test.js.map +1 -1
- package/lib/esm/test/ecdb/QueryReaders.test.js +17 -14
- package/lib/esm/test/ecdb/QueryReaders.test.js.map +1 -1
- package/lib/esm/test/ecdb/SqliteStatement.test.js +2 -2
- package/lib/esm/test/ecdb/SqliteStatement.test.js.map +1 -1
- package/lib/esm/test/ecsql/dataset/ECSqlDatasets.d.ts.map +1 -1
- package/lib/esm/test/ecsql/dataset/ECSqlDatasets.js +30 -28
- package/lib/esm/test/ecsql/dataset/ECSqlDatasets.js.map +1 -1
- package/lib/esm/test/ecsql/src/ECSqlTestGenerator.js.map +1 -1
- package/lib/esm/test/ecsql/src/ECSqlTestParser.js.map +1 -1
- package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js.map +1 -1
- package/lib/esm/test/element/DeleteDefinitionElements.test.js +159 -143
- package/lib/esm/test/element/DeleteDefinitionElements.test.js.map +1 -1
- package/lib/esm/test/element/ElementAspect.test.js +68 -60
- package/lib/esm/test/element/ElementAspect.test.js.map +1 -1
- package/lib/esm/test/element/ElementDependencyGraph.test.d.ts.map +1 -1
- package/lib/esm/test/element/ElementDependencyGraph.test.js +51 -43
- package/lib/esm/test/element/ElementDependencyGraph.test.js.map +1 -1
- package/lib/esm/test/element/ElementRoundTrip.test.js +37 -38
- package/lib/esm/test/element/ElementRoundTrip.test.js.map +1 -1
- package/lib/esm/test/element/ExcludedElements.test.js +2 -2
- package/lib/esm/test/element/ExcludedElements.test.js.map +1 -1
- package/lib/esm/test/element/ExternalSource.test.js +40 -38
- package/lib/esm/test/element/ExternalSource.test.js.map +1 -1
- package/lib/esm/test/element/NullStructArray.test.js +10 -9
- package/lib/esm/test/element/NullStructArray.test.js.map +1 -1
- package/lib/esm/test/element/ProjectInformationRecord.test.js +5 -2
- package/lib/esm/test/element/ProjectInformationRecord.test.js.map +1 -1
- package/lib/esm/test/element/SheetInformationAspect.test.js +43 -11
- package/lib/esm/test/element/SheetInformationAspect.test.js.map +1 -1
- package/lib/esm/test/element/UrlLink.test.js +2 -2
- package/lib/esm/test/element/UrlLink.test.js.map +1 -1
- package/lib/esm/test/font/IModelDbFonts.test.js +87 -73
- package/lib/esm/test/font/IModelDbFonts.test.js.map +1 -1
- package/lib/esm/test/hubaccess/ApplyChangeset.test.js +164 -125
- package/lib/esm/test/hubaccess/ApplyChangeset.test.js.map +1 -1
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js +2 -4
- package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
- package/lib/esm/test/hubaccess/Rebase.test.js +313 -247
- package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SemanticRebase.test.js +322 -247
- package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
- package/lib/esm/test/imodel/Code.test.js +31 -31
- package/lib/esm/test/imodel/Code.test.js.map +1 -1
- package/lib/esm/test/imodel/ElementTreeWalker.test.js +57 -48
- package/lib/esm/test/imodel/ElementTreeWalker.test.js.map +1 -1
- package/lib/esm/test/imodel/IModel.test.js +419 -344
- package/lib/esm/test/imodel/IModel.test.js.map +1 -1
- package/lib/esm/test/imodel/ProjectExtents.test.js +2 -2
- package/lib/esm/test/imodel/ProjectExtents.test.js.map +1 -1
- package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js.map +1 -1
- package/lib/esm/test/incrementalSchemaLocater/TestContext.d.ts.map +1 -1
- package/lib/esm/test/incrementalSchemaLocater/TestContext.js +2 -2
- package/lib/esm/test/incrementalSchemaLocater/TestContext.js.map +1 -1
- package/lib/esm/test/index.d.ts +1 -0
- package/lib/esm/test/index.d.ts.map +1 -1
- package/lib/esm/test/index.js +1 -0
- package/lib/esm/test/index.js.map +1 -1
- package/lib/esm/test/schema/ClassRegistry.test.js +23 -22
- package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
- package/lib/esm/test/schema/FunctionalDomain.test.js +36 -34
- package/lib/esm/test/schema/FunctionalDomain.test.js.map +1 -1
- package/lib/esm/test/schema/GenericDomain.test.js +114 -94
- package/lib/esm/test/schema/GenericDomain.test.js.map +1 -1
- package/lib/esm/test/schema/IModelSchemaContext.test.js +2 -1
- package/lib/esm/test/schema/IModelSchemaContext.test.js.map +1 -1
- package/lib/esm/test/schema/SchemaImportCallbacks.test.js +207 -192
- package/lib/esm/test/schema/SchemaImportCallbacks.test.js.map +1 -1
- package/lib/esm/test/sheetindex/SheetIndex.test.d.ts +1 -3
- package/lib/esm/test/sheetindex/SheetIndex.test.d.ts.map +1 -1
- package/lib/esm/test/sheetindex/SheetIndex.test.js +312 -247
- package/lib/esm/test/sheetindex/SheetIndex.test.js.map +1 -1
- package/lib/esm/test/standalone/ChangeMerge.test.js +101 -82
- package/lib/esm/test/standalone/ChangeMerge.test.js.map +1 -1
- package/lib/esm/test/standalone/ChangesetReader.test.js +114 -85
- package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
- package/lib/esm/test/standalone/DisplayStyle.test.js +43 -40
- package/lib/esm/test/standalone/DisplayStyle.test.js.map +1 -1
- package/lib/esm/test/standalone/Drawing.test.js +4 -3
- package/lib/esm/test/standalone/Drawing.test.js.map +1 -1
- package/lib/esm/test/standalone/EditTxn.test.d.ts +2 -0
- package/lib/esm/test/standalone/EditTxn.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/EditTxn.test.js +219 -0
- package/lib/esm/test/standalone/EditTxn.test.js.map +1 -0
- package/lib/esm/test/standalone/ElementMesh.test.js +16 -13
- package/lib/esm/test/standalone/ElementMesh.test.js.map +1 -1
- package/lib/esm/test/standalone/ExportGraphics.test.js +26 -20
- package/lib/esm/test/standalone/ExportGraphics.test.js.map +1 -1
- package/lib/esm/test/standalone/GeometryChangeEvents.test.js +11 -15
- package/lib/esm/test/standalone/GeometryChangeEvents.test.js.map +1 -1
- package/lib/esm/test/standalone/GeometryStream.test.js +212 -165
- package/lib/esm/test/standalone/GeometryStream.test.js.map +1 -1
- package/lib/esm/test/standalone/HubMock.test.js +31 -25
- package/lib/esm/test/standalone/HubMock.test.js.map +1 -1
- package/lib/esm/test/standalone/IModelLimits.test.js +11 -8
- package/lib/esm/test/standalone/IModelLimits.test.js.map +1 -1
- package/lib/esm/test/standalone/IModelWrite.test.d.ts +2 -2
- package/lib/esm/test/standalone/IModelWrite.test.d.ts.map +1 -1
- package/lib/esm/test/standalone/IModelWrite.test.js +184 -142
- package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
- package/lib/esm/test/standalone/ITwinWorkspace.test.d.ts +2 -0
- package/lib/esm/test/standalone/ITwinWorkspace.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/ITwinWorkspace.test.js +236 -0
- package/lib/esm/test/standalone/ITwinWorkspace.test.js.map +1 -0
- package/lib/esm/test/standalone/InlineGeometryPartReferences.test.js +25 -22
- package/lib/esm/test/standalone/InlineGeometryPartReferences.test.js.map +1 -1
- package/lib/esm/test/standalone/IntegrityCheck.test.js +20 -18
- package/lib/esm/test/standalone/IntegrityCheck.test.js.map +1 -1
- package/lib/esm/test/standalone/MergeConflict.test.d.ts +2 -2
- package/lib/esm/test/standalone/MergeConflict.test.d.ts.map +1 -1
- package/lib/esm/test/standalone/MergeConflict.test.js +49 -33
- package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
- package/lib/esm/test/standalone/RenderMaterialElement.test.js +5 -5
- package/lib/esm/test/standalone/RenderMaterialElement.test.js.map +1 -1
- package/lib/esm/test/standalone/RenderTimeline.test.js +3 -2
- package/lib/esm/test/standalone/RenderTimeline.test.js.map +1 -1
- package/lib/esm/test/standalone/SectionDrawing.test.js +7 -7
- package/lib/esm/test/standalone/SectionDrawing.test.js.map +1 -1
- package/lib/esm/test/standalone/ServerBasedLocks.test.js +928 -22
- package/lib/esm/test/standalone/ServerBasedLocks.test.js.map +1 -1
- package/lib/esm/test/standalone/Settings.test.js +26 -4
- package/lib/esm/test/standalone/Settings.test.js.map +1 -1
- package/lib/esm/test/standalone/SettingsSchemas.test.js +2 -1
- package/lib/esm/test/standalone/SettingsSchemas.test.js.map +1 -1
- package/lib/esm/test/standalone/SnapshotDb.test.js +3 -1
- package/lib/esm/test/standalone/SnapshotDb.test.js.map +1 -1
- package/lib/esm/test/standalone/StandaloneDb.test.js +7 -6
- package/lib/esm/test/standalone/StandaloneDb.test.js.map +1 -1
- package/lib/esm/test/standalone/Texture.test.js +5 -4
- package/lib/esm/test/standalone/Texture.test.js.map +1 -1
- package/lib/esm/test/standalone/TileCache.test.d.ts.map +1 -1
- package/lib/esm/test/standalone/TileCache.test.js +5 -3
- package/lib/esm/test/standalone/TileCache.test.js.map +1 -1
- package/lib/esm/test/standalone/TileTree.test.js +35 -31
- package/lib/esm/test/standalone/TileTree.test.js.map +1 -1
- package/lib/esm/test/standalone/TxnManager.test.js +700 -653
- package/lib/esm/test/standalone/TxnManager.test.js.map +1 -1
- package/lib/esm/test/standalone/ViewDefinition.test.js +295 -229
- package/lib/esm/test/standalone/ViewDefinition.test.js.map +1 -1
- package/lib/esm/test/standalone/Workspace.test.js +72 -22
- package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
- package/lib/esm/test/workspace/SettingsDb.test.js +28 -456
- package/lib/esm/test/workspace/SettingsDb.test.js.map +1 -1
- package/lib/esm/workspace/Settings.d.ts +11 -5
- package/lib/esm/workspace/Settings.d.ts.map +1 -1
- package/lib/esm/workspace/Settings.js.map +1 -1
- package/lib/esm/workspace/SettingsDb.d.ts +20 -99
- package/lib/esm/workspace/SettingsDb.d.ts.map +1 -1
- package/lib/esm/workspace/SettingsDb.js +20 -6
- package/lib/esm/workspace/SettingsDb.js.map +1 -1
- package/lib/esm/workspace/SettingsEditor.d.ts +40 -226
- package/lib/esm/workspace/SettingsEditor.d.ts.map +1 -1
- package/lib/esm/workspace/SettingsEditor.js +85 -24
- package/lib/esm/workspace/SettingsEditor.js.map +1 -1
- package/lib/esm/workspace/Workspace.d.ts +7 -11
- package/lib/esm/workspace/Workspace.d.ts.map +1 -1
- package/lib/esm/workspace/Workspace.js.map +1 -1
- package/lib/esm/workspace/WorkspaceEditor.d.ts +14 -0
- package/lib/esm/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/lib/esm/workspace/WorkspaceEditor.js +1 -1
- package/lib/esm/workspace/WorkspaceEditor.js.map +1 -1
- package/package.json +14 -14
- package/lib/cjs/internal/workspace/SettingsDbImpl.d.ts +0 -38
- package/lib/cjs/internal/workspace/SettingsDbImpl.d.ts.map +0 -1
- package/lib/cjs/internal/workspace/SettingsDbImpl.js +0 -108
- package/lib/cjs/internal/workspace/SettingsDbImpl.js.map +0 -1
- package/lib/cjs/internal/workspace/SettingsSqliteDb.d.ts +0 -14
- package/lib/cjs/internal/workspace/SettingsSqliteDb.d.ts.map +0 -1
- package/lib/cjs/internal/workspace/SettingsSqliteDb.js +0 -40
- package/lib/cjs/internal/workspace/SettingsSqliteDb.js.map +0 -1
- package/lib/esm/internal/workspace/SettingsDbImpl.d.ts +0 -38
- package/lib/esm/internal/workspace/SettingsDbImpl.d.ts.map +0 -1
- package/lib/esm/internal/workspace/SettingsDbImpl.js +0 -104
- package/lib/esm/internal/workspace/SettingsDbImpl.js.map +0 -1
- package/lib/esm/internal/workspace/SettingsSqliteDb.d.ts +0 -14
- package/lib/esm/internal/workspace/SettingsSqliteDb.d.ts.map +0 -1
- package/lib/esm/internal/workspace/SettingsSqliteDb.js +0 -36
- package/lib/esm/internal/workspace/SettingsSqliteDb.js.map +0 -1
|
@@ -59,6 +59,7 @@ import * as path from "path";
|
|
|
59
59
|
import * as semver from "semver";
|
|
60
60
|
import * as sinon from "sinon";
|
|
61
61
|
import { DbResult, Guid, Id64, IModelStatus, Logger, OpenMode, ProcessDetector } from "@itwin/core-bentley";
|
|
62
|
+
import { EditTxn, withEditTxn } from "../../EditTxn";
|
|
62
63
|
import { BisCodeSpec, BriefcaseIdValue, Code, CodeScopeSpec, CodeSpec, ColorByName, ColorDef, DisplayStyleSettings, EcefLocation, FontMap, FontType, GeoCoordStatus, GeographicCRS, GeometryParams, GeometryStreamBuilder, ImageSourceFormat, IModel, IModelError, QueryBinder, RelatedElement, RenderMode, SchemaState, SubCategoryAppearance, TextureMapping, TextureMapUnits, ViewFlags, } from "@itwin/core-common";
|
|
63
64
|
import { Geometry, LineString3d, Loop, Matrix4d, Point3d, PolyfaceBuilder, Range3d, StrokeOptions, Transform, YawPitchRollAngles, } from "@itwin/core-geometry";
|
|
64
65
|
import { V2CheckpointManager } from "../../CheckpointManager";
|
|
@@ -92,8 +93,7 @@ async function generateTestSnapshot(targetFileName, seedAssetName) {
|
|
|
92
93
|
const snapshotFile = IModelTestUtils.prepareOutputFile("IModel", targetFileName);
|
|
93
94
|
const imodel = IModelTestUtils.createSnapshotFromSeed(snapshotFile, seedFile);
|
|
94
95
|
const schemaPathname = path.join(KnownTestLocations.assetsDir, "TestBim.ecschema.xml");
|
|
95
|
-
await imodel.importSchemas([schemaPathname]);
|
|
96
|
-
imodel.saveChanges();
|
|
96
|
+
await imodel.importSchemas([schemaPathname]);
|
|
97
97
|
return imodel;
|
|
98
98
|
}
|
|
99
99
|
describe("iModel", () => {
|
|
@@ -272,30 +272,33 @@ describe("iModel", () => {
|
|
|
272
272
|
assert.notEqual(a2, el3);
|
|
273
273
|
assert.equal(a2.id, el3.id);
|
|
274
274
|
roundtripThroughJson(el3);
|
|
275
|
+
const txn = new EditTxn(imodel2, "code scope mutation test");
|
|
276
|
+
txn.start();
|
|
275
277
|
const newEl = el3.toJSON();
|
|
276
278
|
newEl.federationGuid = undefined;
|
|
277
279
|
newEl.code = { scope: "bad scope", spec: "0x10", value: "new code" };
|
|
278
|
-
expect(() =>
|
|
280
|
+
expect(() => txn.insertElement(newEl)).throws("invalid code scope").to.have.property("metadata");
|
|
279
281
|
newEl.code.scope = "0x34322"; // valid id, but element doesn't exist
|
|
280
|
-
expect(() =>
|
|
282
|
+
expect(() => txn.insertElement(newEl)).throws("invalid code scope").to.have.property("metadata");
|
|
281
283
|
newEl.code.scope = el3.federationGuid;
|
|
282
|
-
const newId =
|
|
284
|
+
const newId = txn.insertElement(newEl); // code scope from FederationGuid should get converted to ElementId
|
|
283
285
|
const a4 = imodel2.elements.getElementProps(newId);
|
|
284
286
|
expect(a4.code.scope).equal(el3.id);
|
|
285
287
|
a4.code.scope = "0x13343";
|
|
286
|
-
expect(() =>
|
|
288
|
+
expect(() => txn.updateElement(a4)).throws("invalid code scope").to.have.property("metadata");
|
|
287
289
|
a4.code.scope = "0x1";
|
|
288
|
-
|
|
290
|
+
txn.updateElement(a4); // should change the code scope to new element
|
|
289
291
|
let a5 = imodel2.elements.getElementProps(newId);
|
|
290
292
|
expect(a5.code.scope).equal("0x1");
|
|
291
293
|
// only pass minimum, but expect model and classFullName to be added.
|
|
292
294
|
const newProps = { id: a4.id, code: a4.code, classFullName: undefined, model: undefined };
|
|
293
295
|
newProps.code.scope = el3.federationGuid; // should convert FederationGuid to ElementId
|
|
294
|
-
|
|
296
|
+
txn.updateElement(newProps);
|
|
295
297
|
expect(newProps.classFullName).eq(a4.classFullName);
|
|
296
298
|
expect(newProps.model).eq(a4.model);
|
|
297
299
|
a5 = imodel2.elements.getElementProps(newId);
|
|
298
300
|
expect(a5.code.scope).equal(el3.id);
|
|
301
|
+
txn.end();
|
|
299
302
|
});
|
|
300
303
|
it("should optionally detect class mismatches", () => {
|
|
301
304
|
// tryGetElement
|
|
@@ -342,20 +345,22 @@ describe("iModel", () => {
|
|
|
342
345
|
const seedElement = imodel2.elements.getElement("0x1d");
|
|
343
346
|
assert.exists(seedElement);
|
|
344
347
|
assert.isTrue(seedElement.federationGuid === "18eb4650-b074-414f-b961-d9cfaa6c8746");
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
348
|
+
withEditTxn(imodel2, (txn) => {
|
|
349
|
+
for (let i = 0; i < 25; i++) {
|
|
350
|
+
const elementProps = {
|
|
351
|
+
classFullName: "Generic:PhysicalObject",
|
|
352
|
+
model: seedElement.model,
|
|
353
|
+
category: seedElement.category,
|
|
354
|
+
code: Code.createEmpty(),
|
|
355
|
+
federationGuid: Guid.createValue(),
|
|
356
|
+
userLabel: `UserLabel-${i}`,
|
|
357
|
+
};
|
|
358
|
+
const element = imodel2.elements.createElement(elementProps);
|
|
359
|
+
element.setUserProperties("performanceTest", { s: `String-${i}`, n: i });
|
|
360
|
+
const elementId = txn.insertElement(element.toJSON());
|
|
361
|
+
assert.isTrue(Id64.isValidId64(elementId));
|
|
362
|
+
}
|
|
363
|
+
});
|
|
359
364
|
});
|
|
360
365
|
it("should insert a RenderMaterial", () => {
|
|
361
366
|
const model = imodel2.models.getModel(IModel.dictionaryId);
|
|
@@ -397,7 +402,7 @@ describe("iModel", () => {
|
|
|
397
402
|
reflectColor,
|
|
398
403
|
patternMap: textureMapProps,
|
|
399
404
|
};
|
|
400
|
-
const renderMaterialId = RenderMaterialElement.insert(
|
|
405
|
+
const renderMaterialId = withEditTxn(imodel2, (txn) => RenderMaterialElement.insert(txn, IModel.dictionaryId, testMaterialName, renderMaterialParams));
|
|
401
406
|
const renderMaterial = imodel2.elements.getElement(renderMaterialId);
|
|
402
407
|
assert((renderMaterial instanceof RenderMaterialElement) === true, "did not retrieve an instance of RenderMaterial");
|
|
403
408
|
expect(renderMaterial.paletteName).to.equal(testPaletteName);
|
|
@@ -435,9 +440,11 @@ describe("iModel", () => {
|
|
|
435
440
|
const testTextureName = "fake texture name";
|
|
436
441
|
const testTextureFormat = ImageSourceFormat.Png;
|
|
437
442
|
const testTextureDescription = "empty description";
|
|
438
|
-
const
|
|
443
|
+
const txn = new EditTxn(imodel5, "apply material to new element");
|
|
444
|
+
txn.start();
|
|
445
|
+
const texId = Texture.insertTexture(txn, IModel.dictionaryId, testTextureName, testTextureFormat, samplePngTexture.base64, testTextureDescription);
|
|
439
446
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
440
|
-
const matId = RenderMaterialElement.insert(
|
|
447
|
+
const matId = RenderMaterialElement.insert(txn, IModel.dictionaryId, "test material name", {
|
|
441
448
|
paletteName: "TestPaletteName",
|
|
442
449
|
patternMap: {
|
|
443
450
|
TextureId: texId,
|
|
@@ -474,8 +481,8 @@ describe("iModel", () => {
|
|
|
474
481
|
Point3d.create(0, 0, 0),
|
|
475
482
|
]));
|
|
476
483
|
}
|
|
477
|
-
const modelId = PhysicalModel.insert(
|
|
478
|
-
const categoryId = SpatialCategory.insert(
|
|
484
|
+
const modelId = PhysicalModel.insert(txn, IModelDb.rootSubjectId, "test_render_material_model_name");
|
|
485
|
+
const categoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "GeoJSON Feature", { color: ColorDef.white.toJSON() });
|
|
479
486
|
/** generate a geometry stream containing the polyface */
|
|
480
487
|
const gsBuilder = new GeometryStreamBuilder();
|
|
481
488
|
const params = new GeometryParams(categoryId);
|
|
@@ -492,8 +499,8 @@ describe("iModel", () => {
|
|
|
492
499
|
category: categoryId,
|
|
493
500
|
geom: geometry,
|
|
494
501
|
};
|
|
495
|
-
|
|
496
|
-
|
|
502
|
+
txn.insertElement(props);
|
|
503
|
+
txn.end();
|
|
497
504
|
});
|
|
498
505
|
it("should insert a DisplayStyle", () => {
|
|
499
506
|
const model = imodel2.models.getModel(IModel.dictionaryId);
|
|
@@ -513,7 +520,9 @@ describe("iModel", () => {
|
|
|
513
520
|
styles: settings,
|
|
514
521
|
},
|
|
515
522
|
};
|
|
516
|
-
const
|
|
523
|
+
const txn = new EditTxn(imodel2, "insert and update DisplayStyle");
|
|
524
|
+
txn.start();
|
|
525
|
+
const styleId = txn.insertElement(props);
|
|
517
526
|
let style = imodel2.elements.getElement(styleId);
|
|
518
527
|
expect(style instanceof DisplayStyle3d).to.be.true;
|
|
519
528
|
expect(style.code.spec).equal(imodel2.codeSpecs.getByName(BisCodeSpec.displayStyle).id);
|
|
@@ -524,7 +533,8 @@ describe("iModel", () => {
|
|
|
524
533
|
style.settings.backgroundColor = ColorDef.red;
|
|
525
534
|
style.settings.monochromeColor = ColorDef.green;
|
|
526
535
|
expect(style.jsonProperties.styles.viewflags.renderMode).to.equal(RenderMode.SmoothShade);
|
|
527
|
-
|
|
536
|
+
txn.updateElement(style.toJSON());
|
|
537
|
+
txn.end();
|
|
528
538
|
style = imodel2.elements.getElement(styleId);
|
|
529
539
|
expect(style instanceof DisplayStyle3d).to.be.true;
|
|
530
540
|
expect(style.settings.viewFlags.renderMode).to.equal(RenderMode.SmoothShade);
|
|
@@ -565,25 +575,27 @@ describe("iModel", () => {
|
|
|
565
575
|
[{ backgroundColor: ColorDef.from(1, 2, 3, 4).tbgr }, defaultViewFlags, false],
|
|
566
576
|
];
|
|
567
577
|
let suffix = 123;
|
|
568
|
-
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
578
|
+
withEditTxn(imodel2, (txn) => {
|
|
579
|
+
for (const test of testCases) {
|
|
580
|
+
const expected = test[0] ?? {};
|
|
581
|
+
const styleId = DisplayStyle3d.insert(txn, IModel.dictionaryId, `TestStyle${suffix++}`, expected);
|
|
582
|
+
const style = imodel2.elements.getElement(styleId).toJSON();
|
|
583
|
+
expect(style.jsonProperties.styles).not.to.be.undefined;
|
|
584
|
+
expect(style.jsonProperties).not.to.be.undefined;
|
|
585
|
+
expect(style.jsonProperties.styles).not.to.be.undefined;
|
|
586
|
+
const actual = style.jsonProperties.styles;
|
|
587
|
+
expect(actual.viewflags).not.to.be.undefined;
|
|
588
|
+
const expectedVf = ViewFlags.fromJSON(test[1]);
|
|
589
|
+
const actualVf = ViewFlags.fromJSON(actual.viewflags);
|
|
590
|
+
expect(actualVf.toJSON()).to.deep.equal(expectedVf.toJSON());
|
|
591
|
+
const expectedBGColor = expected.backgroundColor instanceof ColorDef ? expected.backgroundColor.toJSON() : expected.backgroundColor;
|
|
592
|
+
expect(actual.backgroundColor).to.equal(expectedBGColor);
|
|
593
|
+
// DisplayStyleSettings constructor always initializes json.mapImagery.
|
|
594
|
+
expect(actual.mapImagery).to.deep.equal(expected.mapImagery ?? defaultMapImagery);
|
|
595
|
+
expect(actual.excludedElements).to.deep.equal(expected.excludedElements);
|
|
596
|
+
expect(actual.timePoint).to.deep.equal(expected.timePoint);
|
|
597
|
+
}
|
|
598
|
+
});
|
|
587
599
|
});
|
|
588
600
|
it("should have a valid root subject element", () => {
|
|
589
601
|
const rootSubject = imodel1.elements.getRootSubject();
|
|
@@ -906,7 +918,9 @@ describe("iModel", () => {
|
|
|
906
918
|
newTestElem.asAny.arrayOfStructs = arrayOfStructs;
|
|
907
919
|
newTestElem.asAny.dtUtc = new Date("2015-03-25");
|
|
908
920
|
newTestElem.asAny.p3d = new Point3d(1, 2, 3);
|
|
909
|
-
const
|
|
921
|
+
const txn = new EditTxn(imodel4, "insert and update auto-handled properties");
|
|
922
|
+
txn.start();
|
|
923
|
+
const newTestElemId = txn.insertElement(newTestElem.toJSON());
|
|
910
924
|
assert.isTrue(Id64.isValidId64(newTestElemId), "insert worked");
|
|
911
925
|
const newTestElemFetched = imodel4.elements.getElement(newTestElemId);
|
|
912
926
|
assert.isDefined(newTestElemFetched);
|
|
@@ -925,7 +939,7 @@ describe("iModel", () => {
|
|
|
925
939
|
const editElem = newTestElemFetched;
|
|
926
940
|
editElem.asAny.location = loc2;
|
|
927
941
|
try {
|
|
928
|
-
|
|
942
|
+
txn.updateElement(editElem.toJSON());
|
|
929
943
|
}
|
|
930
944
|
catch {
|
|
931
945
|
assert.fail("Element.update failed");
|
|
@@ -937,46 +951,50 @@ describe("iModel", () => {
|
|
|
937
951
|
// Make array shorter
|
|
938
952
|
assert.equal(afterUpdateElemFetched.asAny.arrayOfInt.length, 300);
|
|
939
953
|
afterUpdateElemFetched.asAny.arrayOfInt = [99, 3];
|
|
940
|
-
|
|
954
|
+
txn.updateElement(afterUpdateElemFetched.toJSON());
|
|
941
955
|
const afterShortenArray = imodel4.elements.getElement(afterUpdateElemFetched.id);
|
|
942
956
|
assert.equal(afterUpdateElemFetched.asAny.arrayOfInt.length, 2);
|
|
943
957
|
assert.deepEqual(afterShortenArray.asAny.arrayOfInt, [99, 3]);
|
|
944
958
|
// Make array longer
|
|
945
959
|
afterShortenArray.asAny.arrayOfInt = [1, 2, 3];
|
|
946
|
-
|
|
960
|
+
txn.updateElement(afterShortenArray.toJSON());
|
|
947
961
|
const afterLengthenArray = imodel4.elements.getElement(afterShortenArray.id);
|
|
948
962
|
assert.equal(afterLengthenArray.asAny.arrayOfInt.length, 3);
|
|
949
963
|
assert.deepEqual(afterLengthenArray.asAny.arrayOfInt, [1, 2, 3]);
|
|
950
964
|
// ------------ delete -----------------
|
|
951
965
|
const elid = afterUpdateElemFetched.id;
|
|
952
|
-
|
|
966
|
+
txn.deleteElement(elid);
|
|
953
967
|
assert.throws(() => imodel4.elements.getElement(elid), IModelError);
|
|
968
|
+
txn.end();
|
|
954
969
|
});
|
|
955
970
|
it("should handle parent and child deletion properly", () => {
|
|
956
|
-
const
|
|
971
|
+
const txn = new EditTxn(imodel4, "handle parent and child deletion");
|
|
972
|
+
txn.start();
|
|
973
|
+
const categoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "MyTestCategory", new SubCategoryAppearance());
|
|
957
974
|
const category = imodel4.elements.getElement(categoryId);
|
|
958
975
|
const subCategory = imodel4.elements.getElement(category.myDefaultSubCategoryId());
|
|
959
|
-
expect(() =>
|
|
976
|
+
expect(() => txn.deleteElement(categoryId)).throws("error deleting element").to.have.property("metadata");
|
|
960
977
|
assert.exists(imodel4.elements.getElement(categoryId), "Category deletes should be blocked in native code");
|
|
961
978
|
assert.exists(imodel4.elements.getElement(subCategory.id), "Children should not be deleted if parent delete is blocked");
|
|
962
|
-
const modelId = PhysicalModel.insert(
|
|
979
|
+
const modelId = PhysicalModel.insert(txn, IModel.rootSubjectId, "MyTestPhysicalModel");
|
|
963
980
|
const elementProps = {
|
|
964
981
|
classFullName: PhysicalObject.classFullName,
|
|
965
982
|
model: modelId,
|
|
966
983
|
category: categoryId,
|
|
967
984
|
code: Code.createEmpty(),
|
|
968
985
|
};
|
|
969
|
-
const parentId =
|
|
986
|
+
const parentId = txn.insertElement(elementProps);
|
|
970
987
|
elementProps.parent = new ElementOwnsChildElements(parentId);
|
|
971
|
-
const childId1 =
|
|
972
|
-
const childId2 =
|
|
988
|
+
const childId1 = txn.insertElement(elementProps);
|
|
989
|
+
const childId2 = txn.insertElement(elementProps);
|
|
973
990
|
assert.exists(imodel4.elements.getElement(parentId));
|
|
974
991
|
assert.exists(imodel4.elements.getElement(childId1));
|
|
975
992
|
assert.exists(imodel4.elements.getElement(childId2));
|
|
976
|
-
|
|
993
|
+
txn.deleteElement(parentId);
|
|
977
994
|
assert.throws(() => imodel4.elements.getElement(parentId), IModelError);
|
|
978
995
|
assert.throws(() => imodel4.elements.getElement(childId1), IModelError);
|
|
979
996
|
assert.throws(() => imodel4.elements.getElement(childId2), IModelError);
|
|
997
|
+
txn.end();
|
|
980
998
|
});
|
|
981
999
|
function checkElementMetaData(entityClass) {
|
|
982
1000
|
assert.isNotNull(entityClass);
|
|
@@ -1002,29 +1020,31 @@ describe("iModel", () => {
|
|
|
1002
1020
|
it("should get metadata for a relationship", async () => {
|
|
1003
1021
|
const imodelPath = IModelTestUtils.prepareOutputFile("IModel", "relationshipMetadata.bim");
|
|
1004
1022
|
const imodel = SnapshotDb.createEmpty(imodelPath, { rootSubject: { name: "relationshipMetadata" } });
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
for await (const row of imodel.createQueryReader(`SELECT * FROM bis.Element LIMIT ${1}`)) {
|
|
1019
|
-
const relId = imodel.relationships.insertInstance({
|
|
1020
|
-
classFullName: "BisCore:ElementHasLinks",
|
|
1021
|
-
sourceId: partitionId,
|
|
1022
|
-
targetId: row.ECInstanceId,
|
|
1023
|
+
await withEditTxn(imodel, async (txn) => {
|
|
1024
|
+
const partitionId = txn.insertElement({
|
|
1025
|
+
classFullName: "BisCore:PhysicalPartition",
|
|
1026
|
+
model: IModel.repositoryModelId,
|
|
1027
|
+
parent: {
|
|
1028
|
+
relClassName: "BisCore:SubjectOwnsPartitionElements",
|
|
1029
|
+
id: IModel.rootSubjectId,
|
|
1030
|
+
},
|
|
1031
|
+
code: new Code({
|
|
1032
|
+
spec: imodel.codeSpecs.getByName(BisCodeSpec.informationPartitionElement).id,
|
|
1033
|
+
scope: IModel.rootSubjectId,
|
|
1034
|
+
value: "physical model",
|
|
1035
|
+
}),
|
|
1023
1036
|
});
|
|
1024
|
-
const
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1037
|
+
for await (const row of imodel.createQueryReader(`SELECT * FROM bis.Element LIMIT ${1}`)) {
|
|
1038
|
+
const relId = txn.insertRelationship({
|
|
1039
|
+
classFullName: "BisCore:ElementHasLinks",
|
|
1040
|
+
sourceId: partitionId,
|
|
1041
|
+
targetId: row.ECInstanceId,
|
|
1042
|
+
});
|
|
1043
|
+
const relationship = imodel.relationships.getInstance("BisCore:ElementHasLinks", relId);
|
|
1044
|
+
const metadata = await relationship.getMetaData();
|
|
1045
|
+
assert.isDefined(metadata, "metadata should be defined");
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1028
1048
|
imodel.close();
|
|
1029
1049
|
});
|
|
1030
1050
|
it("should get metadata for class", () => {
|
|
@@ -1036,31 +1056,33 @@ describe("iModel", () => {
|
|
|
1036
1056
|
it("should iterate through metadata for a relationship", async () => {
|
|
1037
1057
|
const imodelPath = IModelTestUtils.prepareOutputFile("IModel", "relationshipMetadata.bim");
|
|
1038
1058
|
const imodel = SnapshotDb.createEmpty(imodelPath, { rootSubject: { name: "relationshipMetadata" } });
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
for await (const row of imodel.createQueryReader(`SELECT * FROM bis.Element LIMIT ${1}`)) {
|
|
1053
|
-
const relId = imodel.relationships.insertInstance({
|
|
1054
|
-
classFullName: "BisCore:ElementHasLinks",
|
|
1055
|
-
sourceId: partitionId,
|
|
1056
|
-
targetId: row.ECInstanceId,
|
|
1057
|
-
});
|
|
1058
|
-
const relationship = imodel.relationships.getInstance("BisCore:ElementHasLinks", relId);
|
|
1059
|
-
relationship.forEach((propName, propMeta) => {
|
|
1060
|
-
assert.isDefined(propName, "Property name should be defined");
|
|
1061
|
-
assert.isDefined(propMeta, "Property metadata should be defined");
|
|
1059
|
+
await withEditTxn(imodel, async (txn) => {
|
|
1060
|
+
const partitionId = txn.insertElement({
|
|
1061
|
+
classFullName: "BisCore:PhysicalPartition",
|
|
1062
|
+
model: IModel.repositoryModelId,
|
|
1063
|
+
parent: {
|
|
1064
|
+
relClassName: "BisCore:SubjectOwnsPartitionElements",
|
|
1065
|
+
id: IModel.rootSubjectId,
|
|
1066
|
+
},
|
|
1067
|
+
code: new Code({
|
|
1068
|
+
spec: imodel.codeSpecs.getByName(BisCodeSpec.informationPartitionElement).id,
|
|
1069
|
+
scope: IModel.rootSubjectId,
|
|
1070
|
+
value: "physical model",
|
|
1071
|
+
}),
|
|
1062
1072
|
});
|
|
1063
|
-
|
|
1073
|
+
for await (const row of imodel.createQueryReader(`SELECT * FROM bis.Element LIMIT ${1}`)) {
|
|
1074
|
+
const relId = txn.insertRelationship({
|
|
1075
|
+
classFullName: "BisCore:ElementHasLinks",
|
|
1076
|
+
sourceId: partitionId,
|
|
1077
|
+
targetId: row.ECInstanceId,
|
|
1078
|
+
});
|
|
1079
|
+
const relationship = imodel.relationships.getInstance("BisCore:ElementHasLinks", relId);
|
|
1080
|
+
relationship.forEach((propName, propMeta) => {
|
|
1081
|
+
assert.isDefined(propName, "Property name should be defined");
|
|
1082
|
+
assert.isDefined(propMeta, "Property metadata should be defined");
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1064
1086
|
imodel.close();
|
|
1065
1087
|
});
|
|
1066
1088
|
it("update the project extents", async () => {
|
|
@@ -1072,7 +1094,7 @@ describe("iModel", () => {
|
|
|
1072
1094
|
newExtents.high.x += 1087;
|
|
1073
1095
|
newExtents.high.y += 19;
|
|
1074
1096
|
newExtents.high.z += .001;
|
|
1075
|
-
imodel1.updateProjectExtents(newExtents);
|
|
1097
|
+
await withEditTxn(imodel1, async (txn) => txn.updateProjectExtents(newExtents));
|
|
1076
1098
|
const updatedProps = imodel1[_nativeDb].getIModelProps();
|
|
1077
1099
|
assert.isTrue(updatedProps.hasOwnProperty("projectExtents"), "Returned property JSON object has project extents");
|
|
1078
1100
|
const updatedExtents = Range3d.fromJSON(updatedProps.projectExtents);
|
|
@@ -1264,26 +1286,28 @@ describe("iModel", () => {
|
|
|
1264
1286
|
});
|
|
1265
1287
|
it("should create and insert CodeSpecs", () => {
|
|
1266
1288
|
const testImodel = imodel2;
|
|
1289
|
+
const txn = new EditTxn(testImodel, "create and insert CodeSpecs");
|
|
1290
|
+
txn.start();
|
|
1267
1291
|
const codeSpec = CodeSpec.create(testImodel, "CodeSpec1", CodeScopeSpec.Type.Model);
|
|
1268
|
-
const codeSpecId = testImodel.codeSpecs.insert(codeSpec); // throws in case of error
|
|
1292
|
+
const codeSpecId = testImodel.codeSpecs.insert(txn, codeSpec); // throws in case of error
|
|
1269
1293
|
assert.deepEqual(codeSpecId, codeSpec.id);
|
|
1270
1294
|
assert.equal(codeSpec.scopeType, CodeScopeSpec.Type.Model);
|
|
1271
1295
|
assert.equal(codeSpec.scopeReq, CodeScopeSpec.ScopeRequirement.ElementId);
|
|
1272
1296
|
// Should not be able to insert a duplicate.
|
|
1273
1297
|
const codeSpecDup = CodeSpec.create(testImodel, "CodeSpec1", CodeScopeSpec.Type.Model);
|
|
1274
|
-
assert.throws(() => testImodel.codeSpecs.insert(codeSpecDup), "CodeSpec already exists");
|
|
1298
|
+
assert.throws(() => testImodel.codeSpecs.insert(txn, codeSpecDup), "CodeSpec already exists");
|
|
1275
1299
|
// We should be able to insert another CodeSpec with a different name.
|
|
1276
1300
|
const codeSpec2 = CodeSpec.create(testImodel, "CodeSpec2", CodeScopeSpec.Type.Model, CodeScopeSpec.ScopeRequirement.FederationGuid);
|
|
1277
|
-
const codeSpec2Id = testImodel.codeSpecs.insert(codeSpec2); // throws in case of error
|
|
1301
|
+
const codeSpec2Id = testImodel.codeSpecs.insert(txn, codeSpec2); // throws in case of error
|
|
1278
1302
|
assert.deepEqual(codeSpec2Id, codeSpec2.id);
|
|
1279
1303
|
assert.notDeepEqual(codeSpec2Id, codeSpecId);
|
|
1280
1304
|
// make sure CodeScopeSpec.Type.Repository works
|
|
1281
1305
|
const codeSpec3 = CodeSpec.create(testImodel, "CodeSpec3", CodeScopeSpec.Type.Repository, CodeScopeSpec.ScopeRequirement.FederationGuid);
|
|
1282
|
-
const codeSpec3Id = testImodel.codeSpecs.insert(codeSpec3); // throws in case of error
|
|
1306
|
+
const codeSpec3Id = testImodel.codeSpecs.insert(txn, codeSpec3); // throws in case of error
|
|
1283
1307
|
assert.notDeepEqual(codeSpec2Id, codeSpec3Id);
|
|
1284
1308
|
const codeSpec4 = testImodel.codeSpecs.getById(codeSpec3Id);
|
|
1285
1309
|
codeSpec4.name = "CodeSpec4";
|
|
1286
|
-
const codeSpec4Id = testImodel.codeSpecs.insert(codeSpec4); // throws in case of error
|
|
1310
|
+
const codeSpec4Id = testImodel.codeSpecs.insert(txn, codeSpec4); // throws in case of error
|
|
1287
1311
|
assert.notDeepEqual(codeSpec3Id, codeSpec4Id);
|
|
1288
1312
|
assert.equal(codeSpec4.scopeType, CodeScopeSpec.Type.Repository);
|
|
1289
1313
|
assert.equal(codeSpec4.scopeReq, CodeScopeSpec.ScopeRequirement.FederationGuid);
|
|
@@ -1299,6 +1323,7 @@ describe("iModel", () => {
|
|
|
1299
1323
|
assert.isTrue(testImodel.codeSpecs.hasId(codeSpec3.id));
|
|
1300
1324
|
assert.isTrue(testImodel.codeSpecs.hasId(codeSpec4.id));
|
|
1301
1325
|
assert.isFalse(testImodel.codeSpecs.hasId(Id64.invalid));
|
|
1326
|
+
txn.end();
|
|
1302
1327
|
});
|
|
1303
1328
|
it("validate CodeSpec properties", async () => {
|
|
1304
1329
|
const iModelFileName = IModelTestUtils.prepareOutputFile("IModel", "ReadWriteCodeSpec.bim");
|
|
@@ -1307,13 +1332,12 @@ describe("iModel", () => {
|
|
|
1307
1332
|
if (true) {
|
|
1308
1333
|
const iModelDb = IModelTestUtils.createSnapshotFromSeed(iModelFileName, IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim"));
|
|
1309
1334
|
const codeSpec = CodeSpec.create(iModelDb, codeSpecName, CodeScopeSpec.Type.Model, CodeScopeSpec.ScopeRequirement.FederationGuid);
|
|
1310
|
-
const codeSpecId = iModelDb.codeSpecs.insert(codeSpec);
|
|
1335
|
+
const codeSpecId = withEditTxn(iModelDb, (txn) => iModelDb.codeSpecs.insert(txn, codeSpec));
|
|
1311
1336
|
assert.isTrue(Id64.isValidId64(codeSpec.id));
|
|
1312
1337
|
assert.equal(codeSpec.id, codeSpecId);
|
|
1313
1338
|
assert.equal(codeSpec.name, codeSpecName);
|
|
1314
1339
|
assert.equal(codeSpec.scopeType, CodeScopeSpec.Type.Model);
|
|
1315
1340
|
assert.equal(codeSpec.scopeReq, CodeScopeSpec.ScopeRequirement.FederationGuid);
|
|
1316
|
-
iModelDb.saveChanges();
|
|
1317
1341
|
iModelDb.close();
|
|
1318
1342
|
}
|
|
1319
1343
|
// Reopen iModel (ensure CodeSpec cache is cleared) and reconfirm CodeSpec properties
|
|
@@ -1344,7 +1368,9 @@ describe("iModel", () => {
|
|
|
1344
1368
|
});
|
|
1345
1369
|
it("should do CRUD on models", () => {
|
|
1346
1370
|
const testImodel = imodel2;
|
|
1347
|
-
const
|
|
1371
|
+
const txn = new EditTxn(testImodel, "CRUD on models");
|
|
1372
|
+
txn.start();
|
|
1373
|
+
const [modeledElementId, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(txn, Code.createEmpty(), true);
|
|
1348
1374
|
const newModelPersist = testImodel.models.getModel(newModelId);
|
|
1349
1375
|
// Check that it has the properties that we set.
|
|
1350
1376
|
assert.equal(newModelPersist.classFullName, PhysicalModel.classFullName);
|
|
@@ -1352,15 +1378,15 @@ describe("iModel", () => {
|
|
|
1352
1378
|
assert.deepEqual(newModelPersist.modeledElement.id, modeledElementId);
|
|
1353
1379
|
// Update the model
|
|
1354
1380
|
newModelPersist.isPrivate = false;
|
|
1355
|
-
|
|
1381
|
+
txn.updateModel(newModelPersist.toJSON());
|
|
1356
1382
|
// ... and check that it updated the model in the db
|
|
1357
1383
|
const newModelPersist2 = testImodel.models.getModel(newModelId);
|
|
1358
1384
|
assert.isFalse(newModelPersist2.isPrivate);
|
|
1359
1385
|
// Delete the model
|
|
1360
|
-
|
|
1386
|
+
txn.deleteModel(newModelId);
|
|
1361
1387
|
// Test insertModel error handling
|
|
1362
1388
|
try {
|
|
1363
|
-
|
|
1389
|
+
txn.insertModel({
|
|
1364
1390
|
classFullName: DefinitionModel.classFullName,
|
|
1365
1391
|
modeledElement: { id: "0x10000000bad" },
|
|
1366
1392
|
});
|
|
@@ -1368,26 +1394,22 @@ describe("iModel", () => {
|
|
|
1368
1394
|
catch (error) {
|
|
1369
1395
|
assert.isTrue(error instanceof IModelError || error.iTwinErrorId !== undefined);
|
|
1370
1396
|
}
|
|
1397
|
+
txn.end();
|
|
1371
1398
|
});
|
|
1372
1399
|
it("should create model with custom relationship to modeled element", async () => {
|
|
1373
1400
|
const testImodel = imodel1;
|
|
1401
|
+
const txn = new EditTxn(testImodel, "custom relationship to modeled element");
|
|
1374
1402
|
assert.doesNotThrow(() => testImodel.schemaContext.getSchemaItemSync("TestBim:TestModelModelsElement", EntityClass), "TestModelModelsElement is expected to be defined in TestBim.ecschema.xml");
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
}
|
|
1386
|
-
if (true) {
|
|
1387
|
-
[, newModelId2] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(testImodel, Code.createEmpty());
|
|
1388
|
-
const newModel2 = testImodel.models.getModel(newModelId2);
|
|
1389
|
-
relClassName2 = newModel2.modeledElement.relClassName;
|
|
1390
|
-
}
|
|
1403
|
+
txn.start();
|
|
1404
|
+
const newPartition1 = IModelTestUtils.createAndInsertPhysicalPartition(txn, Code.createEmpty());
|
|
1405
|
+
const relClassName1 = "TestBim:TestModelModelsElement";
|
|
1406
|
+
const modeledElementRef = new RelatedElement({ id: newPartition1, relClassName: relClassName1 });
|
|
1407
|
+
const newModelId1 = IModelTestUtils.createAndInsertPhysicalModel(txn, modeledElementRef);
|
|
1408
|
+
assert.isTrue(Id64.isValidId64(newModelId1));
|
|
1409
|
+
const [, newModelId2] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(txn, Code.createEmpty());
|
|
1410
|
+
txn.end();
|
|
1411
|
+
const newModel2 = testImodel.models.getModel(newModelId2);
|
|
1412
|
+
const relClassName2 = newModel2.modeledElement.relClassName;
|
|
1391
1413
|
const model1 = testImodel.models.getModel(newModelId1);
|
|
1392
1414
|
const model2 = testImodel.models.getModel(newModelId2);
|
|
1393
1415
|
const foundRelClassName1 = model1.modeledElement.relClassName;
|
|
@@ -1398,11 +1420,12 @@ describe("iModel", () => {
|
|
|
1398
1420
|
it("should create link table relationship instances", () => {
|
|
1399
1421
|
const snapshotFile2 = IModelTestUtils.prepareOutputFile("IModel", "CreateLinkTable.bim");
|
|
1400
1422
|
const testImodel = StandaloneDb.createEmpty(snapshotFile2, { rootSubject: { name: "test1" }, enableTransactions: true });
|
|
1401
|
-
const
|
|
1423
|
+
const txn = new EditTxn(testImodel, "link table relationship instances");
|
|
1424
|
+
txn.start();
|
|
1402
1425
|
// Create a new physical model
|
|
1403
|
-
const newModelId = PhysicalModel.insert(
|
|
1426
|
+
const newModelId = PhysicalModel.insert(txn, IModel.rootSubjectId, "TestModel");
|
|
1404
1427
|
// create a SpatialCategory
|
|
1405
|
-
const spatialCategoryId = SpatialCategory.insert(
|
|
1428
|
+
const spatialCategoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorByName.darkRed }));
|
|
1406
1429
|
// Create a couple of physical elements.
|
|
1407
1430
|
const elementProps = {
|
|
1408
1431
|
classFullName: PhysicalObject.classFullName,
|
|
@@ -1410,16 +1433,16 @@ describe("iModel", () => {
|
|
|
1410
1433
|
category: spatialCategoryId,
|
|
1411
1434
|
code: Code.createEmpty(),
|
|
1412
1435
|
};
|
|
1413
|
-
const id0 =
|
|
1414
|
-
const id1 =
|
|
1415
|
-
const id2 =
|
|
1436
|
+
const id0 = txn.insertElement(elementProps);
|
|
1437
|
+
const id1 = txn.insertElement(elementProps);
|
|
1438
|
+
const id2 = txn.insertElement(elementProps);
|
|
1416
1439
|
const geometricModel = testImodel.models.getModel(newModelId);
|
|
1417
1440
|
assert.throws(() => geometricModel.queryExtents()); // no geometry
|
|
1418
1441
|
// Create grouping relationships from 0 to 1 and from 0 to 2
|
|
1419
1442
|
const r1 = ElementGroupsMembers.create(testImodel, id0, id1, 1);
|
|
1420
|
-
r1.
|
|
1443
|
+
r1.id = txn.insertRelationship(r1.toJSON());
|
|
1421
1444
|
const r2 = ElementGroupsMembers.create(testImodel, id0, id2);
|
|
1422
|
-
r2.
|
|
1445
|
+
r2.id = txn.insertRelationship(r2.toJSON());
|
|
1423
1446
|
// Look up by id
|
|
1424
1447
|
const g1 = ElementGroupsMembers.getInstance(testImodel, r1.id);
|
|
1425
1448
|
const g2 = ElementGroupsMembers.getInstance(testImodel, r2.id);
|
|
@@ -1434,53 +1457,57 @@ describe("iModel", () => {
|
|
|
1434
1457
|
assert.deepEqual(g1byst, g1);
|
|
1435
1458
|
// Update relationship instance property
|
|
1436
1459
|
r1.asAny.memberPriority = 2;
|
|
1437
|
-
r1.
|
|
1460
|
+
txn.updateRelationship(r1.toJSON());
|
|
1438
1461
|
const g11 = ElementGroupsMembers.getInstance(testImodel, r1.id);
|
|
1439
1462
|
assert.equal(g11.memberPriority, 2, "g11.memberPriority");
|
|
1440
|
-
|
|
1463
|
+
txn.saveChanges("step 1");
|
|
1441
1464
|
// Delete relationship instance property
|
|
1442
|
-
g11.
|
|
1443
|
-
|
|
1465
|
+
txn.deleteRelationship(g11.toJSON());
|
|
1466
|
+
txn.saveChanges("step 2");
|
|
1444
1467
|
assert.throws(() => ElementGroupsMembers.getInstance(testImodel, r1.id), IModelError);
|
|
1445
|
-
const d0 =
|
|
1446
|
-
const d1 =
|
|
1468
|
+
const d0 = txn.insertElement(elementProps);
|
|
1469
|
+
const d1 = txn.insertElement(elementProps);
|
|
1447
1470
|
const ede1 = ElementDrivesElement.create(testImodel, d0, d1, 0);
|
|
1448
|
-
ede1.
|
|
1449
|
-
|
|
1450
|
-
ede1.
|
|
1451
|
-
|
|
1471
|
+
ede1.id = txn.insertRelationship(ede1.toJSON());
|
|
1472
|
+
txn.saveChanges("step 3");
|
|
1473
|
+
txn.deleteRelationship(ede1.toJSON());
|
|
1474
|
+
txn.end("save", "step 4");
|
|
1452
1475
|
testImodel.close();
|
|
1453
1476
|
});
|
|
1454
1477
|
it("should insert DefinitionSets", () => {
|
|
1455
1478
|
const iModelFileName = IModelTestUtils.prepareOutputFile("IModel", "DefinitionSets.bim");
|
|
1456
1479
|
const iModelDb = SnapshotDb.createEmpty(iModelFileName, { rootSubject: { name: "DefinitionSets" }, createClassViews: true });
|
|
1457
|
-
const
|
|
1480
|
+
const txn = new EditTxn(iModelDb, "definition sets");
|
|
1481
|
+
txn.start();
|
|
1482
|
+
const definitionContainerId = DefinitionContainer.insert(txn, IModel.dictionaryId, Code.createEmpty());
|
|
1458
1483
|
assert.exists(iModelDb.elements.getElement(definitionContainerId));
|
|
1459
1484
|
assert.exists(iModelDb.models.getModel(definitionContainerId));
|
|
1460
|
-
const categoryId1 = SpatialCategory.insert(
|
|
1461
|
-
const categoryId2 = SpatialCategory.insert(
|
|
1462
|
-
const categoryId3 = SpatialCategory.insert(
|
|
1463
|
-
const definitionGroupId = DefinitionGroup.create(iModelDb, definitionContainerId, Code.createEmpty()).insert();
|
|
1464
|
-
DefinitionGroupGroupsDefinitions.insert(
|
|
1465
|
-
DefinitionGroupGroupsDefinitions.insert(
|
|
1466
|
-
DefinitionGroupGroupsDefinitions.insert(
|
|
1485
|
+
const categoryId1 = SpatialCategory.insert(txn, definitionContainerId, "Category1", new SubCategoryAppearance());
|
|
1486
|
+
const categoryId2 = SpatialCategory.insert(txn, definitionContainerId, "Category2", new SubCategoryAppearance());
|
|
1487
|
+
const categoryId3 = SpatialCategory.insert(txn, definitionContainerId, "Category3", new SubCategoryAppearance());
|
|
1488
|
+
const definitionGroupId = DefinitionGroup.create(iModelDb, definitionContainerId, Code.createEmpty()).insert(txn);
|
|
1489
|
+
DefinitionGroupGroupsDefinitions.insert(txn, definitionGroupId, categoryId1);
|
|
1490
|
+
DefinitionGroupGroupsDefinitions.insert(txn, definitionGroupId, categoryId2);
|
|
1491
|
+
DefinitionGroupGroupsDefinitions.insert(txn, definitionGroupId, categoryId3);
|
|
1467
1492
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1468
1493
|
const numMembers = iModelDb.withPreparedStatement(`SELECT COUNT(*) FROM ${DefinitionGroupGroupsDefinitions.classFullName}`, (statement) => {
|
|
1469
1494
|
return statement.step() === DbResult.BE_SQLITE_ROW ? statement.getValue(0).getInteger() : 0;
|
|
1470
1495
|
});
|
|
1471
1496
|
assert.equal(numMembers, 3);
|
|
1472
|
-
|
|
1497
|
+
txn.end();
|
|
1473
1498
|
iModelDb.close();
|
|
1474
1499
|
});
|
|
1475
1500
|
it("should set EC properties of various types", async () => {
|
|
1476
1501
|
const testImodel = imodel1;
|
|
1477
1502
|
assert.doesNotThrow(() => testImodel.schemaContext.getSchemaItemSync("TestBim:TestPhysicalObject", EntityClass), "TestPhysicalObject is expected to be defined in TestBim.ecschema.xml");
|
|
1503
|
+
const txn = new EditTxn(testImodel, "set EC properties of various types");
|
|
1504
|
+
txn.start();
|
|
1478
1505
|
// Create a new physical model
|
|
1479
|
-
const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(
|
|
1506
|
+
const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(txn, Code.createEmpty(), true);
|
|
1480
1507
|
// Find or create a SpatialCategory
|
|
1481
1508
|
let spatialCategoryId = SpatialCategory.queryCategoryIdByName(testImodel, IModel.dictionaryId, "MySpatialCategory");
|
|
1482
1509
|
if (undefined === spatialCategoryId) {
|
|
1483
|
-
spatialCategoryId = SpatialCategory.insert(
|
|
1510
|
+
spatialCategoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance());
|
|
1484
1511
|
}
|
|
1485
1512
|
const trelClassName = "TestBim:TestPhysicalObjectRelatedToTestPhysicalObject";
|
|
1486
1513
|
let id1;
|
|
@@ -1493,14 +1520,14 @@ describe("iModel", () => {
|
|
|
1493
1520
|
category: spatialCategoryId,
|
|
1494
1521
|
code: Code.createEmpty(),
|
|
1495
1522
|
};
|
|
1496
|
-
id1 =
|
|
1523
|
+
id1 = txn.insertElement(testImodel.elements.createElement(elementProps).toJSON());
|
|
1497
1524
|
assert.isTrue(Id64.isValidId64(id1));
|
|
1498
1525
|
// The second one should point to the first.
|
|
1499
1526
|
elementProps.id = Id64.invalid;
|
|
1500
1527
|
elementProps.relatedElement = { id: id1, relClassName: trelClassName };
|
|
1501
1528
|
elementProps.parent = { id: id1, relClassName: trelClassName };
|
|
1502
1529
|
elementProps.longProp = 4294967295; // make sure that we can save values in the range 0 ... UINT_MAX
|
|
1503
|
-
id2 =
|
|
1530
|
+
id2 = txn.insertElement(testImodel.elements.createElement(elementProps).toJSON());
|
|
1504
1531
|
assert.isTrue(Id64.isValidId64(id2));
|
|
1505
1532
|
}
|
|
1506
1533
|
if (true) {
|
|
@@ -1519,7 +1546,7 @@ describe("iModel", () => {
|
|
|
1519
1546
|
// Change el2 to point to itself.
|
|
1520
1547
|
const el2Modified = testImodel.elements.getElement(id2);
|
|
1521
1548
|
el2Modified.asAny.relatedElement = { id: id2, relClassName: trelClassName };
|
|
1522
|
-
|
|
1549
|
+
txn.updateElement(el2Modified.toJSON());
|
|
1523
1550
|
// Test that el2 points to itself.
|
|
1524
1551
|
const el2after = testImodel.elements.getElement(id2);
|
|
1525
1552
|
assert.deepEqual(el2after.asAny.relatedElement.id, id2);
|
|
@@ -1529,11 +1556,12 @@ describe("iModel", () => {
|
|
|
1529
1556
|
// Test that we can null out the navigation property
|
|
1530
1557
|
const el2Modified = testImodel.elements.getElement(id2);
|
|
1531
1558
|
el2Modified.asAny.relatedElement = null;
|
|
1532
|
-
|
|
1559
|
+
txn.updateElement(el2Modified.toJSON());
|
|
1533
1560
|
// Test that el2 has no relatedElement property value
|
|
1534
1561
|
const el2after = testImodel.elements.getElement(id2);
|
|
1535
1562
|
assert.isUndefined(el2after.asAny.relatedElement);
|
|
1536
1563
|
}
|
|
1564
|
+
txn.end();
|
|
1537
1565
|
});
|
|
1538
1566
|
it("should be able to create a snapshot IModel", async () => {
|
|
1539
1567
|
const args = {
|
|
@@ -1559,23 +1587,25 @@ describe("iModel", () => {
|
|
|
1559
1587
|
assert.equal(dbguid.byteLength, 16, "query guid property");
|
|
1560
1588
|
const myPropsStr = { name: "MyProp", namespace: "test1", id: 1, subId: 1 };
|
|
1561
1589
|
const myStrVal = "this is a test";
|
|
1562
|
-
iModel.saveFileProperty(myPropsStr, myStrVal);
|
|
1563
|
-
const readFromDb = iModel.queryFilePropertyString(myPropsStr);
|
|
1564
|
-
assert.equal(readFromDb, myStrVal, "query string after save");
|
|
1565
1590
|
const myPropsBlob = { name: "MyBlob", namespace: "test1", id: 10 };
|
|
1566
1591
|
const testRange = new Uint8Array(500);
|
|
1567
1592
|
testRange.fill(11);
|
|
1568
|
-
iModel
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1593
|
+
withEditTxn(iModel, (txn) => {
|
|
1594
|
+
txn.saveFileProperty(myPropsStr, myStrVal);
|
|
1595
|
+
const readFromDb = iModel.queryFilePropertyString(myPropsStr);
|
|
1596
|
+
assert.equal(readFromDb, myStrVal, "query string after save");
|
|
1597
|
+
txn.saveFileProperty(myPropsBlob, undefined, testRange);
|
|
1598
|
+
const blobFromDb = iModel.queryFilePropertyBlob(myPropsBlob);
|
|
1599
|
+
assert.deepEqual(blobFromDb, testRange, "query blob after save");
|
|
1600
|
+
let next = iModel.queryNextAvailableFileProperty(myPropsBlob);
|
|
1601
|
+
assert.equal(11, next, "queryNextAvailableFileProperty blob");
|
|
1602
|
+
next = iModel.queryNextAvailableFileProperty(myPropsStr);
|
|
1603
|
+
assert.equal(2, next, "queryNextAvailableFileProperty str");
|
|
1604
|
+
txn.deleteFileProperty(myPropsStr);
|
|
1605
|
+
assert.isUndefined(iModel.queryFilePropertyString(myPropsStr), "property was deleted");
|
|
1606
|
+
next = iModel.queryNextAvailableFileProperty(myPropsStr);
|
|
1607
|
+
assert.equal(0, next, "queryNextAvailableFileProperty, should return 0 when none present");
|
|
1608
|
+
});
|
|
1579
1609
|
const testLocal = "TestLocal";
|
|
1580
1610
|
const testValue = "this is a test";
|
|
1581
1611
|
const nativeDb = iModel[_nativeDb];
|
|
@@ -1638,8 +1668,9 @@ describe("iModel", () => {
|
|
|
1638
1668
|
assert.isFalse(eventListenedTo);
|
|
1639
1669
|
iModel.geographicCoordinateSystem = gcs;
|
|
1640
1670
|
assert.isTrue(eventListenedTo);
|
|
1641
|
-
iModel
|
|
1642
|
-
|
|
1671
|
+
withEditTxn(iModel, (txn) => {
|
|
1672
|
+
txn.updateIModelProps();
|
|
1673
|
+
});
|
|
1643
1674
|
iModel.close();
|
|
1644
1675
|
const iModel2 = SnapshotDb.openFile(testFile);
|
|
1645
1676
|
assert.isTrue(iModel2.geographicCoordinateSystem !== undefined);
|
|
@@ -1710,9 +1741,10 @@ describe("iModel", () => {
|
|
|
1710
1741
|
datumOrGCS = datum;
|
|
1711
1742
|
const testFile = IModelTestUtils.prepareOutputFile("IModel", fileName);
|
|
1712
1743
|
const iModel = SnapshotDb.createEmpty(testFile, args);
|
|
1713
|
-
iModel
|
|
1714
|
-
|
|
1715
|
-
|
|
1744
|
+
withEditTxn(iModel, (txn) => {
|
|
1745
|
+
iModel.setGeographicCoordinateSystem(fileGCS);
|
|
1746
|
+
txn.updateIModelProps();
|
|
1747
|
+
});
|
|
1716
1748
|
const testPoint1 = [];
|
|
1717
1749
|
testPoint1.push(inputCoord);
|
|
1718
1750
|
const requestProps1 = { target: datumOrGCS, iModelCoords: testPoint1 };
|
|
@@ -1969,8 +2001,9 @@ describe("iModel", () => {
|
|
|
1969
2001
|
const iModel = SnapshotDb.createEmpty(testFile, args);
|
|
1970
2002
|
assert.isTrue(iModel.ecefLocation === undefined);
|
|
1971
2003
|
iModel.ecefLocation = ecef;
|
|
1972
|
-
iModel
|
|
1973
|
-
|
|
2004
|
+
withEditTxn(iModel, (txn) => {
|
|
2005
|
+
txn.updateIModelProps();
|
|
2006
|
+
});
|
|
1974
2007
|
iModel.close();
|
|
1975
2008
|
const iModel2 = SnapshotDb.openFile(testFile);
|
|
1976
2009
|
assert.isTrue(iModel2.ecefLocation !== undefined);
|
|
@@ -1993,8 +2026,9 @@ describe("iModel", () => {
|
|
|
1993
2026
|
const iModel = SnapshotDb.createEmpty(testFile, args);
|
|
1994
2027
|
assert.isTrue(iModel.ecefLocation === undefined);
|
|
1995
2028
|
iModel.ecefLocation = ecef;
|
|
1996
|
-
iModel
|
|
1997
|
-
|
|
2029
|
+
withEditTxn(iModel, (txn) => {
|
|
2030
|
+
txn.updateIModelProps();
|
|
2031
|
+
});
|
|
1998
2032
|
iModel.close();
|
|
1999
2033
|
const iModel2 = SnapshotDb.openFile(testFile);
|
|
2000
2034
|
assert.isTrue(iModel2.ecefLocation !== undefined);
|
|
@@ -2048,16 +2082,18 @@ describe("iModel", () => {
|
|
|
2048
2082
|
const testFile = IModelTestUtils.prepareOutputFile("IModel", "TestSnapshot4.bim");
|
|
2049
2083
|
const iModel = SnapshotDb.createEmpty(testFile, args);
|
|
2050
2084
|
iModel.ecefLocation = ecef;
|
|
2051
|
-
iModel
|
|
2052
|
-
|
|
2085
|
+
withEditTxn(iModel, (txn) => {
|
|
2086
|
+
txn.updateIModelProps();
|
|
2087
|
+
});
|
|
2053
2088
|
iModel.close();
|
|
2054
2089
|
const iModel2 = SnapshotDb.openForApplyChangesets(testFile);
|
|
2055
2090
|
assert.isTrue(iModel2.ecefLocation !== undefined);
|
|
2056
2091
|
assert.isTrue(iModel2.ecefLocation.isAlmostEqual(ecef));
|
|
2057
2092
|
assert.isTrue(iModel2.geographicCoordinateSystem === undefined);
|
|
2058
2093
|
iModel2.geographicCoordinateSystem = gcs;
|
|
2059
|
-
iModel2
|
|
2060
|
-
|
|
2094
|
+
withEditTxn(iModel2, (txn) => {
|
|
2095
|
+
txn.updateIModelProps();
|
|
2096
|
+
});
|
|
2061
2097
|
iModel2.close();
|
|
2062
2098
|
const iModel3 = SnapshotDb.openFile(testFile);
|
|
2063
2099
|
assert.isTrue(iModel3.geographicCoordinateSystem !== undefined);
|
|
@@ -2078,6 +2114,7 @@ describe("iModel", () => {
|
|
|
2078
2114
|
getIModelId: () => iModelId,
|
|
2079
2115
|
getITwinId: () => iTwinId,
|
|
2080
2116
|
getCurrentChangeset: () => changeset,
|
|
2117
|
+
hasUnsavedChanges: () => false,
|
|
2081
2118
|
setIModelDb: () => { },
|
|
2082
2119
|
closeFile: () => { },
|
|
2083
2120
|
clearECDbCache: () => { },
|
|
@@ -2164,20 +2201,22 @@ describe("iModel", () => {
|
|
|
2164
2201
|
};
|
|
2165
2202
|
const seconds = (s) => s * 1000;
|
|
2166
2203
|
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "Standalone" } });
|
|
2167
|
-
db
|
|
2204
|
+
const txn = new EditTxn(db, "busy timeout test");
|
|
2205
|
+
txn.start();
|
|
2168
2206
|
// lock db so another connection cannot write to it.
|
|
2169
|
-
|
|
2207
|
+
txn.saveFileProperty({ name: "test", namespace: "test" }, "");
|
|
2170
2208
|
assert.isAtMost(tryOpen(standaloneFile, { busyTimeout: seconds(0) }), seconds(1), "open should fail with busy error instantly");
|
|
2171
2209
|
assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(1) }), seconds(1), "open should fail with atleast 1 sec delay due to retry");
|
|
2172
2210
|
assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(2) }), seconds(2), "open should fail with atleast 2 sec delay due to retry");
|
|
2173
2211
|
assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(3) }), seconds(3), "open should fail with atleast 3 sec delay due to retry");
|
|
2174
|
-
|
|
2212
|
+
txn.end("abandon");
|
|
2175
2213
|
db.close();
|
|
2176
2214
|
});
|
|
2177
2215
|
it("Cache cleared on abandonChanges", () => {
|
|
2178
2216
|
const standaloneFile = IModelTestUtils.prepareOutputFile("IModel", "StandaloneReadWrite.bim");
|
|
2179
2217
|
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "Standalone" } });
|
|
2180
|
-
db
|
|
2218
|
+
const txn = new EditTxn(db, "cache cleared on abandonChanges");
|
|
2219
|
+
txn.start();
|
|
2181
2220
|
const code = Code.createEmpty();
|
|
2182
2221
|
code.value = "foo";
|
|
2183
2222
|
const props = {
|
|
@@ -2185,29 +2224,32 @@ describe("iModel", () => {
|
|
|
2185
2224
|
model: IModel.dictionaryId,
|
|
2186
2225
|
code,
|
|
2187
2226
|
};
|
|
2188
|
-
const id =
|
|
2227
|
+
const id = txn.insertElement(props);
|
|
2189
2228
|
const element1 = db.elements.getElementProps(id);
|
|
2190
|
-
|
|
2229
|
+
txn.end("abandon");
|
|
2191
2230
|
code.value = "bar";
|
|
2192
2231
|
const props2 = {
|
|
2193
2232
|
classFullName: GenericGraphicalType2d.classFullName,
|
|
2194
2233
|
model: IModel.dictionaryId,
|
|
2195
2234
|
code,
|
|
2196
2235
|
};
|
|
2197
|
-
const
|
|
2236
|
+
const retryTxn = new EditTxn(db, "cache cleared on abandonChanges retry");
|
|
2237
|
+
retryTxn.start();
|
|
2238
|
+
const id2 = retryTxn.insertElement(props2);
|
|
2198
2239
|
expect(id2).to.equal(id);
|
|
2199
2240
|
const element2 = db.elements.getElementProps(id2);
|
|
2200
2241
|
expect(element2).to.not.equal(element1);
|
|
2201
2242
|
// Make sure that the statement caches are not cleared
|
|
2202
2243
|
expect(db._sqliteStatementCache.size).to.be.greaterThan(0);
|
|
2203
2244
|
expect(db._statementCache.size).to.be.greaterThan(0);
|
|
2204
|
-
|
|
2245
|
+
retryTxn.end("abandon");
|
|
2205
2246
|
db.close();
|
|
2206
2247
|
});
|
|
2207
2248
|
it("Only instance caches should be cleared with clearCaches instanceCachesOnly parameter", () => {
|
|
2208
2249
|
const standaloneFile = IModelTestUtils.prepareOutputFile("IModel", "StandaloneReadWrite.bim");
|
|
2209
2250
|
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "Standalone" } });
|
|
2210
|
-
db
|
|
2251
|
+
const txn = new EditTxn(db, "clearCaches instanceCachesOnly");
|
|
2252
|
+
txn.start();
|
|
2211
2253
|
const code = Code.createEmpty();
|
|
2212
2254
|
code.value = "foo";
|
|
2213
2255
|
const props = {
|
|
@@ -2215,7 +2257,7 @@ describe("iModel", () => {
|
|
|
2215
2257
|
model: IModel.dictionaryId,
|
|
2216
2258
|
code,
|
|
2217
2259
|
};
|
|
2218
|
-
const id =
|
|
2260
|
+
const id = txn.insertElement(props);
|
|
2219
2261
|
db.elements.getElementProps(id);
|
|
2220
2262
|
db.models.getModelProps(IModel.dictionaryId);
|
|
2221
2263
|
expect(db.elements[_cache].size).to.be.greaterThan(0);
|
|
@@ -2230,7 +2272,7 @@ describe("iModel", () => {
|
|
|
2230
2272
|
// Make sure that the statement caches are not cleared
|
|
2231
2273
|
expect(db._sqliteStatementCache.size).to.be.greaterThan(0);
|
|
2232
2274
|
expect(db._statementCache.size).to.be.greaterThan(0);
|
|
2233
|
-
|
|
2275
|
+
txn.end("abandon");
|
|
2234
2276
|
db.close();
|
|
2235
2277
|
});
|
|
2236
2278
|
it("Standalone iModel properties", () => {
|
|
@@ -2371,28 +2413,29 @@ describe("iModel", () => {
|
|
|
2371
2413
|
iModel.close();
|
|
2372
2414
|
});
|
|
2373
2415
|
it("Run plain SQL", () => {
|
|
2374
|
-
imodel1
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2416
|
+
withEditTxn(imodel1, () => {
|
|
2417
|
+
imodel1.withPreparedSqliteStatement("CREATE TABLE Test(Id INTEGER PRIMARY KEY, Name TEXT NOT NULL, Code INTEGER)", (stmt) => {
|
|
2418
|
+
assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
|
|
2419
|
+
});
|
|
2420
|
+
imodel1.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(?,?)", (stmt) => {
|
|
2421
|
+
stmt.bindValue(1, "Dummy 1");
|
|
2422
|
+
stmt.bindValue(2, 100);
|
|
2423
|
+
assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
|
|
2424
|
+
});
|
|
2425
|
+
imodel1.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(?,?)", (stmt) => {
|
|
2426
|
+
stmt.bindValues(["Dummy 2", 200]);
|
|
2427
|
+
assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
|
|
2428
|
+
});
|
|
2429
|
+
imodel1.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(:p1,:p2)", (stmt) => {
|
|
2430
|
+
stmt.bindValue(":p1", "Dummy 3");
|
|
2431
|
+
stmt.bindValue(":p2", 300);
|
|
2432
|
+
assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
|
|
2433
|
+
});
|
|
2434
|
+
imodel1.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(:p1,:p2)", (stmt) => {
|
|
2435
|
+
stmt.bindValues({ ":p1": "Dummy 4", ":p2": 400 });
|
|
2436
|
+
assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
|
|
2437
|
+
});
|
|
2394
2438
|
});
|
|
2395
|
-
imodel1.saveChanges();
|
|
2396
2439
|
imodel1.withPreparedSqliteStatement("SELECT Id,Name,Code FROM Test ORDER BY Id", (stmt) => {
|
|
2397
2440
|
for (let i = 1; i <= 4; i++) {
|
|
2398
2441
|
assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW);
|
|
@@ -2501,7 +2544,9 @@ describe("iModel", () => {
|
|
|
2501
2544
|
assert.isFalse(imodel1.containsClass("InvalidSchemaName:Element"));
|
|
2502
2545
|
});
|
|
2503
2546
|
it("should update Element code", () => {
|
|
2504
|
-
const
|
|
2547
|
+
const txn = new EditTxn(imodel4, "update element code");
|
|
2548
|
+
txn.start();
|
|
2549
|
+
const elementId = txn.insertElement({
|
|
2505
2550
|
classFullName: "DgnPlatformTest:TestInformationRecord",
|
|
2506
2551
|
model: IModel.repositoryModelId,
|
|
2507
2552
|
code: Code.createEmpty(),
|
|
@@ -2509,16 +2554,19 @@ describe("iModel", () => {
|
|
|
2509
2554
|
let element = imodel4.elements.getElement(elementId, InformationRecordElement);
|
|
2510
2555
|
assert.isTrue(Code.isValid(element.code));
|
|
2511
2556
|
assert.isTrue(Code.isEmpty(element.code));
|
|
2512
|
-
const codeSpecId = imodel4.codeSpecs.insert("TestCodeSpec", CodeScopeSpec.Type.Model);
|
|
2557
|
+
const codeSpecId = imodel4.codeSpecs.insert(txn, "TestCodeSpec", CodeScopeSpec.Type.Model);
|
|
2513
2558
|
const codeValue = `${element.className}-1`;
|
|
2514
2559
|
element.code = new Code({ spec: codeSpecId, scope: IModel.repositoryModelId, value: codeValue });
|
|
2515
|
-
element.update();
|
|
2560
|
+
element.update(txn);
|
|
2561
|
+
txn.end();
|
|
2516
2562
|
element = imodel4.elements.getElement(elementId, InformationRecordElement);
|
|
2517
2563
|
assert.isTrue(Code.isValid(element.code));
|
|
2518
2564
|
assert.isFalse(Code.isEmpty(element.code));
|
|
2519
2565
|
assert.equal(element.code.value, codeValue);
|
|
2520
2566
|
});
|
|
2521
2567
|
it("should update UserLabel", () => {
|
|
2568
|
+
const txn = new EditTxn(imodel1, "update user label");
|
|
2569
|
+
txn.start();
|
|
2522
2570
|
// type coercion reminder!
|
|
2523
2571
|
const s = "";
|
|
2524
2572
|
assert.isTrue(s === "");
|
|
@@ -2529,16 +2577,16 @@ describe("iModel", () => {
|
|
|
2529
2577
|
model: IModel.dictionaryId,
|
|
2530
2578
|
code: SpatialCategory.createCode(imodel1, IModel.dictionaryId, "TestCategoryForClearUserLabel"),
|
|
2531
2579
|
};
|
|
2532
|
-
const elementId =
|
|
2580
|
+
const elementId = txn.insertElement(elementProps);
|
|
2533
2581
|
let element = imodel1.elements.getElement(elementId);
|
|
2534
2582
|
assert.isUndefined(element.userLabel);
|
|
2535
2583
|
// update element with a defined userLabel
|
|
2536
2584
|
element.userLabel = "UserLabel";
|
|
2537
|
-
element.update();
|
|
2585
|
+
element.update(txn);
|
|
2538
2586
|
element = imodel1.elements.getElement(elementId);
|
|
2539
2587
|
assert.equal(element.userLabel, "UserLabel");
|
|
2540
2588
|
// make sure userLabel is not updated when not part of the specified ElementProps
|
|
2541
|
-
|
|
2589
|
+
txn.updateElement({
|
|
2542
2590
|
id: element.id,
|
|
2543
2591
|
classFullName: element.classFullName,
|
|
2544
2592
|
model: element.model,
|
|
@@ -2558,11 +2606,14 @@ describe("iModel", () => {
|
|
|
2558
2606
|
expect(elProps.isInstanceOfEntity).undefined;
|
|
2559
2607
|
// remove userlabel by setting it to the blank string
|
|
2560
2608
|
element.userLabel = "";
|
|
2561
|
-
element.update();
|
|
2609
|
+
element.update(txn);
|
|
2610
|
+
txn.end();
|
|
2562
2611
|
element = imodel1.elements.getElement(elementId);
|
|
2563
2612
|
assert.isUndefined(element.userLabel); // NOTE: userLabel is cleared when the empty string is specified
|
|
2564
2613
|
});
|
|
2565
2614
|
it("should update FederationGuid", () => {
|
|
2615
|
+
const txn = new EditTxn(imodel1, "update federation guid");
|
|
2616
|
+
txn.start();
|
|
2566
2617
|
// insert element with an undefined FederationGuid
|
|
2567
2618
|
const elementProps = {
|
|
2568
2619
|
classFullName: SpatialCategory.classFullName,
|
|
@@ -2570,7 +2621,7 @@ describe("iModel", () => {
|
|
|
2570
2621
|
federationGuid: Guid.empty,
|
|
2571
2622
|
code: SpatialCategory.createCode(imodel1, IModel.dictionaryId, "TestCategoryForClearFederationGuid"),
|
|
2572
2623
|
};
|
|
2573
|
-
const elementId =
|
|
2624
|
+
const elementId = txn.insertElement(elementProps);
|
|
2574
2625
|
let element = imodel1.elements.getElement(elementId);
|
|
2575
2626
|
assert.isUndefined(element.federationGuid);
|
|
2576
2627
|
assert.isFalse(element.isPrivate);
|
|
@@ -2578,12 +2629,12 @@ describe("iModel", () => {
|
|
|
2578
2629
|
const federationGuid = Guid.createValue();
|
|
2579
2630
|
element.federationGuid = federationGuid;
|
|
2580
2631
|
element.isPrivate = true;
|
|
2581
|
-
element.update();
|
|
2632
|
+
element.update(txn);
|
|
2582
2633
|
element = imodel1.elements.getElement(elementId);
|
|
2583
2634
|
assert.equal(element.federationGuid, federationGuid);
|
|
2584
2635
|
assert.isTrue(element.isPrivate);
|
|
2585
2636
|
// make sure FederationGuid is not updated when not part of the specified ElementProps
|
|
2586
|
-
|
|
2637
|
+
txn.updateElement({
|
|
2587
2638
|
id: element.id,
|
|
2588
2639
|
classFullName: element.classFullName,
|
|
2589
2640
|
model: element.model,
|
|
@@ -2595,20 +2646,23 @@ describe("iModel", () => {
|
|
|
2595
2646
|
// remove federationGuid by setting it to undefined in ElementProps
|
|
2596
2647
|
const elProps = element.toJSON();
|
|
2597
2648
|
elProps.federationGuid = undefined;
|
|
2598
|
-
|
|
2649
|
+
txn.updateElement(elProps);
|
|
2599
2650
|
element = imodel1.elements.getElement(elementId);
|
|
2600
2651
|
assert.isUndefined(element.federationGuid);
|
|
2601
2652
|
// ensure that update doesn't change federationGuid from an element immediately after insert (toJSON should remove undefined value)
|
|
2602
2653
|
const subject5 = Subject.create(imodel1, IModel.rootSubjectId, "Subject5");
|
|
2603
|
-
const s5Id = subject5.insert();
|
|
2654
|
+
const s5Id = subject5.insert(txn);
|
|
2604
2655
|
const s5pre = imodel1.elements.getElement(s5Id);
|
|
2605
2656
|
subject5.description = "new descr";
|
|
2606
|
-
subject5.update();
|
|
2657
|
+
subject5.update(txn);
|
|
2658
|
+
txn.end();
|
|
2607
2659
|
const s5post = imodel1.elements.getElement(s5Id);
|
|
2608
2660
|
expect(s5pre.federationGuid).equal(s5post.federationGuid);
|
|
2609
2661
|
expect(s5post.description).equal(subject5.description);
|
|
2610
2662
|
});
|
|
2611
2663
|
it("should support partial update", () => {
|
|
2664
|
+
const txn = new EditTxn(imodel1, "partial element update");
|
|
2665
|
+
txn.start();
|
|
2612
2666
|
// Insert Subject elements - initializing Description and UserLabel to similar values
|
|
2613
2667
|
let subject1 = Subject.create(imodel1, IModel.rootSubjectId, "Subject1", "Description1");
|
|
2614
2668
|
let subject2 = Subject.create(imodel1, IModel.rootSubjectId, "Subject2", "Description2");
|
|
@@ -2624,10 +2678,10 @@ describe("iModel", () => {
|
|
|
2624
2678
|
subject2.federationGuid = federationGuid2;
|
|
2625
2679
|
subject3.federationGuid = "";
|
|
2626
2680
|
subject4.federationGuid = Guid.empty;
|
|
2627
|
-
const subjectId1 = subject1.insert();
|
|
2628
|
-
const subjectId2 = subject2.insert();
|
|
2629
|
-
const subjectId3 = subject3.insert();
|
|
2630
|
-
const subjectId4 = subject4.insert();
|
|
2681
|
+
const subjectId1 = subject1.insert(txn);
|
|
2682
|
+
const subjectId2 = subject2.insert(txn);
|
|
2683
|
+
const subjectId3 = subject3.insert(txn);
|
|
2684
|
+
const subjectId4 = subject4.insert(txn);
|
|
2631
2685
|
subject1 = imodel1.elements.getElement(subjectId1, Subject);
|
|
2632
2686
|
subject2 = imodel1.elements.getElement(subjectId2, Subject);
|
|
2633
2687
|
subject3 = imodel1.elements.getElement(subjectId3, Subject);
|
|
@@ -2652,7 +2706,7 @@ describe("iModel", () => {
|
|
|
2652
2706
|
assert.equal(subject2.federationGuid, federationGuid2);
|
|
2653
2707
|
assert.isUndefined(subject4.federationGuid);
|
|
2654
2708
|
// test partial update of Description (auto-handled)
|
|
2655
|
-
|
|
2709
|
+
txn.updateElement({ id: subject1.id, description: "Description1-Updated" });
|
|
2656
2710
|
subject1 = imodel1.elements.getElement(subjectId1, Subject);
|
|
2657
2711
|
assert.equal(subject1.description, "Description1-Updated"); // should have been updated
|
|
2658
2712
|
assert.isDefined(subject1.model);
|
|
@@ -2661,7 +2715,7 @@ describe("iModel", () => {
|
|
|
2661
2715
|
assert.equal(subject1.userLabel, "UserLabel1"); // should not have changed
|
|
2662
2716
|
assert.equal(subject1.federationGuid, federationGuid1); // should not have changed
|
|
2663
2717
|
// test partial update of UserLabel (custom-handled)
|
|
2664
|
-
|
|
2718
|
+
txn.updateElement({ id: subject2.id, userLabel: "UserLabel2-Updated" });
|
|
2665
2719
|
subject2 = imodel1.elements.getElement(subjectId2, Subject);
|
|
2666
2720
|
assert.isDefined(subject2.model);
|
|
2667
2721
|
assert.isDefined(subject2.parent);
|
|
@@ -2677,10 +2731,10 @@ describe("iModel", () => {
|
|
|
2677
2731
|
subject2.userLabel = "";
|
|
2678
2732
|
subject3.userLabel = "UserLabel3";
|
|
2679
2733
|
subject4.userLabel = "UserLabel4";
|
|
2680
|
-
subject1.update();
|
|
2681
|
-
subject2.update();
|
|
2682
|
-
subject3.update();
|
|
2683
|
-
subject4.update();
|
|
2734
|
+
subject1.update(txn);
|
|
2735
|
+
subject2.update(txn);
|
|
2736
|
+
subject3.update(txn);
|
|
2737
|
+
subject4.update(txn);
|
|
2684
2738
|
subject1 = imodel1.elements.getElement(subjectId1, Subject);
|
|
2685
2739
|
subject2 = imodel1.elements.getElement(subjectId2, Subject);
|
|
2686
2740
|
subject3 = imodel1.elements.getElement(subjectId3, Subject);
|
|
@@ -2696,7 +2750,7 @@ describe("iModel", () => {
|
|
|
2696
2750
|
assert.equal(subject4.userLabel, "UserLabel4");
|
|
2697
2751
|
// test partial update of Description to undefined
|
|
2698
2752
|
const s3Fed = subject3.federationGuid;
|
|
2699
|
-
|
|
2753
|
+
txn.updateElement({ id: subject3.id, description: undefined });
|
|
2700
2754
|
subject3 = imodel1.elements.getElement(subjectId3, Subject);
|
|
2701
2755
|
assert.isUndefined(subject3.description); // should have been updated
|
|
2702
2756
|
assert.isDefined(subject3.model);
|
|
@@ -2705,7 +2759,8 @@ describe("iModel", () => {
|
|
|
2705
2759
|
assert.equal(subject3.userLabel, "UserLabel3"); // should not have changed
|
|
2706
2760
|
assert.equal(subject3.federationGuid, s3Fed); // should not have changed
|
|
2707
2761
|
// test partial update of UserLabel to undefined
|
|
2708
|
-
|
|
2762
|
+
txn.updateElement({ id: subject4.id, userLabel: undefined });
|
|
2763
|
+
txn.end();
|
|
2709
2764
|
subject4 = imodel1.elements.getElement(subjectId4, Subject);
|
|
2710
2765
|
assert.isDefined(subject4.model);
|
|
2711
2766
|
assert.isDefined(subject4.parent);
|
|
@@ -2717,6 +2772,8 @@ describe("iModel", () => {
|
|
|
2717
2772
|
it('should allow untrimmed codes when using "exact" codeValueBehavior', () => {
|
|
2718
2773
|
const imodelPath = IModelTestUtils.prepareOutputFile("IModel", "codeValueBehavior.bim");
|
|
2719
2774
|
const imodel = SnapshotDb.createEmpty(imodelPath, { rootSubject: { name: "codeValueBehaviors" } });
|
|
2775
|
+
const txn = new EditTxn(imodel, "codeValueBehavior");
|
|
2776
|
+
txn.start();
|
|
2720
2777
|
const getNumberedCodeValAndProps = (n) => {
|
|
2721
2778
|
const trimmedCodeVal = `CodeValue${n}`;
|
|
2722
2779
|
const untrimmedCodeVal = `${trimmedCodeVal}\xa0`;
|
|
@@ -2731,22 +2788,25 @@ describe("iModel", () => {
|
|
|
2731
2788
|
};
|
|
2732
2789
|
expect(imodel.codeValueBehavior).to.equal("trim-unicode-whitespace");
|
|
2733
2790
|
const code1 = getNumberedCodeValAndProps(1);
|
|
2734
|
-
const categ1Id =
|
|
2791
|
+
const categ1Id = txn.insertElement(code1.props);
|
|
2735
2792
|
const categ1 = imodel.elements.getElementProps({ id: categ1Id });
|
|
2736
2793
|
expect(categ1.code.value).to.equal(code1.trimmedCodeVal);
|
|
2737
2794
|
imodel.codeValueBehavior = "exact";
|
|
2738
2795
|
const code2 = getNumberedCodeValAndProps(2);
|
|
2739
|
-
const categ2Id =
|
|
2796
|
+
const categ2Id = txn.insertElement(code2.props);
|
|
2740
2797
|
const categ2 = imodel.elements.getElementProps({ id: categ2Id });
|
|
2741
2798
|
expect(categ2.code.value).to.equal(code2.untrimmedCodeVal);
|
|
2742
2799
|
imodel.codeValueBehavior = "trim-unicode-whitespace";
|
|
2743
2800
|
const code3 = getNumberedCodeValAndProps(3);
|
|
2744
|
-
const categ3Id =
|
|
2801
|
+
const categ3Id = txn.insertElement(code3.props);
|
|
2745
2802
|
const categ3 = imodel.elements.getElement({ id: categ3Id });
|
|
2746
2803
|
expect(categ3.code.value).to.equal(code3.trimmedCodeVal);
|
|
2804
|
+
txn.end();
|
|
2747
2805
|
imodel.close();
|
|
2748
2806
|
});
|
|
2749
2807
|
it("should throw iTwinErrors on element CRUD opertion fails", async () => {
|
|
2808
|
+
const txn = new EditTxn(imodel1, "element CRUD failure cases");
|
|
2809
|
+
txn.start();
|
|
2750
2810
|
const code = Code.createEmpty();
|
|
2751
2811
|
code.value = "foo";
|
|
2752
2812
|
const props = {
|
|
@@ -2754,23 +2814,24 @@ describe("iModel", () => {
|
|
|
2754
2814
|
model: IModel.dictionaryId,
|
|
2755
2815
|
code,
|
|
2756
2816
|
};
|
|
2757
|
-
|
|
2758
|
-
expect(() =>
|
|
2817
|
+
txn.insertElement(props);
|
|
2818
|
+
expect(() => txn.insertElement(props)).throws("Error inserting element [duplicate code]").to.have.property("iTwinErrorId");
|
|
2759
2819
|
const updateProps = {
|
|
2760
2820
|
id: Id64.fromString("0x111111"),
|
|
2761
2821
|
classFullName: GenericGraphicalType2d.classFullName,
|
|
2762
2822
|
model: IModel.dictionaryId,
|
|
2763
2823
|
code,
|
|
2764
2824
|
};
|
|
2765
|
-
expect(() =>
|
|
2766
|
-
expect(() =>
|
|
2767
|
-
expect(() =>
|
|
2768
|
-
expect(() =>
|
|
2825
|
+
expect(() => txn.updateElement(updateProps)).throws(`Error updating element [missing id], id: ${updateProps.id}`).to.have.property("iTwinErrorId");
|
|
2826
|
+
expect(() => txn.deleteElement(updateProps.id)).throws(`Error deleting element [missing id], id: ${updateProps.id}`).to.have.property("iTwinErrorId");
|
|
2827
|
+
expect(() => txn.insertModel({ classFullName: DefinitionModel.classFullName, modeledElement: { id: "0x10000000bad" } })).throws("Error inserting model [error=10004], class=BisCore:DefinitionModel").to.have.property("iTwinErrorId");
|
|
2828
|
+
expect(() => txn.updateModel({
|
|
2769
2829
|
id: Id64.fromString("0x111111"),
|
|
2770
2830
|
modeledElement: { id: Id64.fromString("0x111111") },
|
|
2771
2831
|
classFullName: ""
|
|
2772
2832
|
})).throws(`Error updating model [missing id], id: ${Id64.fromString("0x111111")}`).to.have.property("iTwinErrorId");
|
|
2773
|
-
expect(() =>
|
|
2833
|
+
expect(() => txn.deleteModel(Id64.fromString("0x111111"))).throws(`Error deleting model [missing id], id: ${Id64.fromString("0x111111")}`).to.have.property("iTwinErrorId");
|
|
2834
|
+
txn.end("abandon");
|
|
2774
2835
|
});
|
|
2775
2836
|
it("throws NotFound when attempting to access element props after closing the iModel", () => {
|
|
2776
2837
|
const imodelPath = IModelTestUtils.prepareOutputFile("IModel", "accessAfterClose.bim");
|
|
@@ -2783,11 +2844,12 @@ describe("iModel", () => {
|
|
|
2783
2844
|
it("should throw \"constraint failed (BE_SQLITE_CONSTRAINT_UNIQUE)\" when inserting a relationsip instance with the same prop twice", () => {
|
|
2784
2845
|
const imodelPath = IModelTestUtils.prepareOutputFile("IModel", "insertDuplicateInstance.bim");
|
|
2785
2846
|
const imodel = SnapshotDb.createEmpty(imodelPath, { rootSubject: { name: "insertDuplicateInstance" } });
|
|
2786
|
-
const
|
|
2847
|
+
const txn = new EditTxn(imodel, "insert duplicate relationship instance");
|
|
2848
|
+
txn.start();
|
|
2787
2849
|
// Create a new physical model
|
|
2788
|
-
const newModelId = PhysicalModel.insert(
|
|
2850
|
+
const newModelId = PhysicalModel.insert(txn, IModel.rootSubjectId, "TestModel");
|
|
2789
2851
|
// create a SpatialCategory
|
|
2790
|
-
const spatialCategoryId = SpatialCategory.insert(
|
|
2852
|
+
const spatialCategoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorByName.darkRed }));
|
|
2791
2853
|
// Create a couple of physical elements.
|
|
2792
2854
|
const elementProps = {
|
|
2793
2855
|
classFullName: PhysicalObject.classFullName,
|
|
@@ -2795,16 +2857,17 @@ describe("iModel", () => {
|
|
|
2795
2857
|
category: spatialCategoryId,
|
|
2796
2858
|
code: Code.createEmpty(),
|
|
2797
2859
|
};
|
|
2798
|
-
const id0 =
|
|
2799
|
-
const id1 =
|
|
2860
|
+
const id0 = txn.insertElement(elementProps);
|
|
2861
|
+
const id1 = txn.insertElement(elementProps);
|
|
2800
2862
|
const props = {
|
|
2801
2863
|
classFullName: "BisCore:ElementGroupsMembers",
|
|
2802
2864
|
sourceId: id0,
|
|
2803
2865
|
targetId: id1,
|
|
2804
2866
|
memberPriority: 1,
|
|
2805
2867
|
};
|
|
2806
|
-
|
|
2807
|
-
expect(() =>
|
|
2868
|
+
txn.insertRelationship(props);
|
|
2869
|
+
expect(() => txn.insertRelationship(props)).to.throw(`Failed to insert relationship [${imodelPath}]: rc=2067, constraint failed (BE_SQLITE_CONSTRAINT_UNIQUE)`);
|
|
2870
|
+
txn.end("abandon");
|
|
2808
2871
|
imodel.close();
|
|
2809
2872
|
});
|
|
2810
2873
|
function createElemProps(_imodel, modId, catId, className) {
|
|
@@ -2817,11 +2880,11 @@ describe("iModel", () => {
|
|
|
2817
2880
|
};
|
|
2818
2881
|
return elementProps;
|
|
2819
2882
|
}
|
|
2820
|
-
function insertElement(imodel, mId, cId, cName, propName) {
|
|
2883
|
+
function insertElement(imodel, mId, cId, cName, propName, txn) {
|
|
2821
2884
|
const elementProps = createElemProps(imodel, mId, cId, cName);
|
|
2822
2885
|
const geomElement = imodel.elements.createElement(elementProps);
|
|
2823
2886
|
geomElement.name = propName; // Add a custom property to the element
|
|
2824
|
-
const id =
|
|
2887
|
+
const id = txn.insertElement(geomElement.toJSON());
|
|
2825
2888
|
assert.isTrue(Id64.isValidId64(id), "insert failed");
|
|
2826
2889
|
return id;
|
|
2827
2890
|
}
|
|
@@ -2893,15 +2956,14 @@ describe("iModel", () => {
|
|
|
2893
2956
|
// Ensure ADrivesB table is empty before test
|
|
2894
2957
|
validateADrivesBRowCount(testImodel, 0);
|
|
2895
2958
|
// Create a physical model and spatial category if needed
|
|
2896
|
-
const
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2959
|
+
const setupTxn = new EditTxn(testImodel, "setup invalid relationship class test");
|
|
2960
|
+
setupTxn.start();
|
|
2961
|
+
const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(setupTxn, Code.createEmpty(), true);
|
|
2962
|
+
const spatialCategoryId = SpatialCategory.queryCategoryIdByName(testImodel, IModel.dictionaryId, "MySpatialCategory")
|
|
2963
|
+
?? SpatialCategory.insert(setupTxn, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }));
|
|
2964
|
+
const idB = insertElement(testImodel, newModelId, spatialCategoryId, "TestRelationSchema:ChildB", "ChildBElement", setupTxn);
|
|
2965
|
+
setupTxn.end();
|
|
2903
2966
|
assert.isTrue(Id64.isValidId64(idB), "Insert ChildBElement failed");
|
|
2904
|
-
testImodel.saveChanges();
|
|
2905
2967
|
// Prepare base props for ChildA
|
|
2906
2968
|
const elementProps = createElemProps(testImodel, newModelId, spatialCategoryId, "TestRelationSchema:ChildA");
|
|
2907
2969
|
// Test various relationship class names for navigation property
|
|
@@ -2913,52 +2975,57 @@ describe("iModel", () => {
|
|
|
2913
2975
|
{ name: "trs:CIsRelatedToD", shouldSucceed: false, expectedRows: 0 },
|
|
2914
2976
|
];
|
|
2915
2977
|
for (const { name, shouldSucceed, expectedRows } of testCases) {
|
|
2916
|
-
const
|
|
2917
|
-
|
|
2918
|
-
elementProps.name = "ChildAElement";
|
|
2919
|
-
const geomElement = testImodel.elements.createElement(elementProps);
|
|
2920
|
-
let idA;
|
|
2978
|
+
const txn = new EditTxn(testImodel, `invalid relationship class ${name}`);
|
|
2979
|
+
txn.start();
|
|
2921
2980
|
try {
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
// Validate row count in ADrivesB table
|
|
2934
|
-
validateADrivesBRowCount(testImodel, expectedRows);
|
|
2935
|
-
// If insert succeeded, test update and delete scenarios
|
|
2936
|
-
if (expectedRows === 1 && idA !== undefined) {
|
|
2937
|
-
validateNavProp(testImodel, { id: idB, relClassName: "TestRelationSchema.ADrivesB" });
|
|
2938
|
-
const editElem = testImodel.elements.getElement(idA);
|
|
2939
|
-
editElem.navPropChildB = new RelatedElement({ id: idB, relClassName: "trs.FakeClass" });
|
|
2940
|
-
editElem.name = "ChildAElementUpdated";
|
|
2941
|
-
testImodel.elements.updateElement(editElem);
|
|
2942
|
-
validateADrivesBRowCount(testImodel, 1);
|
|
2943
|
-
validateNavProp(testImodel, { id: idB, relClassName: "TestRelationSchema.ADrivesB" });
|
|
2944
|
-
const editedElem = testImodel.elements.getElement(idA);
|
|
2945
|
-
assert.equal(editedElem.name, "ChildAElementUpdated", `Expected name to be "ChildAElementUpdated" after update, but got "${editedElem.name}"`);
|
|
2946
|
-
assert.strictEqual(editedElem.navPropChildB.relClassName, "TestRelationSchema.ADrivesB", `Expected navPropChildB to be "TestRelationSchema.ADrivesB" after update, but got "${editedElem.navPropChildB}"`);
|
|
2947
|
-
// Set the nav prop value to null
|
|
2948
|
-
editElem.name = "ChildAElementNulled";
|
|
2949
|
-
editElem.navPropChildB = null;
|
|
2950
|
-
testImodel.elements.updateElement(editElem);
|
|
2951
|
-
validateADrivesBRowCount(testImodel, 0);
|
|
2952
|
-
const nulledElem = testImodel.elements.getElement(idA);
|
|
2953
|
-
assert.equal(nulledElem.name, "ChildAElementNulled", `Expected name to be "ChildAElementNulled" after nulling, but got "${nulledElem.name}"`);
|
|
2954
|
-
assert.isUndefined(nulledElem.navPropChildB, `Expected navPropChildB to be undefined after nulling, but got "${nulledElem.navPropChildB}"`);
|
|
2955
|
-
if (shouldSucceed) {
|
|
2956
|
-
// Delete the element
|
|
2957
|
-
testImodel.elements.deleteElement(idA);
|
|
2958
|
-
assert.isUndefined(testImodel.elements.tryGetElement(idA), `Expected element with id ${idA} to be deleted, but it still exists.`);
|
|
2981
|
+
const elemRef = new RelatedElement({ id: idB, relClassName: name });
|
|
2982
|
+
elementProps.navPropChildB = elemRef;
|
|
2983
|
+
elementProps.name = "ChildAElement";
|
|
2984
|
+
const geomElement = testImodel.elements.createElement(elementProps);
|
|
2985
|
+
let idA;
|
|
2986
|
+
try {
|
|
2987
|
+
idA = txn.insertElement(geomElement.toJSON());
|
|
2988
|
+
if (shouldSucceed)
|
|
2989
|
+
assert.isTrue(Id64.isValidId64(idA), `Insert should have succeeded for ${name}.`);
|
|
2990
|
+
else
|
|
2991
|
+
assert.fail(`Insert should have failed for ${name}.`);
|
|
2959
2992
|
}
|
|
2993
|
+
catch (err) {
|
|
2994
|
+
if (shouldSucceed)
|
|
2995
|
+
assert.fail(`Insert should have succeeded for ${name}. Error: ${err.message}`);
|
|
2996
|
+
// If should not succeed, error is expected
|
|
2997
|
+
}
|
|
2998
|
+
// Validate row count in ADrivesB table
|
|
2999
|
+
validateADrivesBRowCount(testImodel, expectedRows);
|
|
3000
|
+
// If insert succeeded, test update and delete scenarios
|
|
3001
|
+
if (expectedRows === 1 && idA !== undefined) {
|
|
3002
|
+
validateNavProp(testImodel, { id: idB, relClassName: "TestRelationSchema.ADrivesB" });
|
|
3003
|
+
const editElem = testImodel.elements.getElement(idA);
|
|
3004
|
+
editElem.navPropChildB = new RelatedElement({ id: idB, relClassName: "trs.FakeClass" });
|
|
3005
|
+
editElem.name = "ChildAElementUpdated";
|
|
3006
|
+
txn.updateElement(editElem);
|
|
3007
|
+
validateADrivesBRowCount(testImodel, 1);
|
|
3008
|
+
validateNavProp(testImodel, { id: idB, relClassName: "TestRelationSchema.ADrivesB" });
|
|
3009
|
+
const editedElem = testImodel.elements.getElement(idA);
|
|
3010
|
+
assert.equal(editedElem.name, "ChildAElementUpdated", `Expected name to be "ChildAElementUpdated" after update, but got "${editedElem.name}"`);
|
|
3011
|
+
assert.strictEqual(editedElem.navPropChildB.relClassName, "TestRelationSchema.ADrivesB", `Expected navPropChildB to be "TestRelationSchema.ADrivesB" after update, but got "${editedElem.navPropChildB}"`);
|
|
3012
|
+
// Set the nav prop value to null
|
|
3013
|
+
editElem.name = "ChildAElementNulled";
|
|
3014
|
+
editElem.navPropChildB = null;
|
|
3015
|
+
txn.updateElement(editElem);
|
|
3016
|
+
validateADrivesBRowCount(testImodel, 0);
|
|
3017
|
+
const nulledElem = testImodel.elements.getElement(idA);
|
|
3018
|
+
assert.equal(nulledElem.name, "ChildAElementNulled", `Expected name to be "ChildAElementNulled" after nulling, but got "${nulledElem.name}"`);
|
|
3019
|
+
assert.isUndefined(nulledElem.navPropChildB, `Expected navPropChildB to be undefined after nulling, but got "${nulledElem.navPropChildB}"`);
|
|
3020
|
+
if (shouldSucceed) {
|
|
3021
|
+
txn.deleteElement(idA);
|
|
3022
|
+
assert.isUndefined(testImodel.elements.tryGetElement(idA), `Expected element with id ${idA} to be deleted, but it still exists.`);
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
finally {
|
|
3027
|
+
txn.end("abandon");
|
|
2960
3028
|
}
|
|
2961
|
-
testImodel.abandonChanges();
|
|
2962
3029
|
}
|
|
2963
3030
|
testImodel.close();
|
|
2964
3031
|
});
|
|
@@ -2971,18 +3038,20 @@ describe("iModel", () => {
|
|
|
2971
3038
|
let categoryB = SpatialCategory.create(imodelDb, IModel.dictionaryId, "B");
|
|
2972
3039
|
categoryA.userLabel = "A";
|
|
2973
3040
|
categoryB.userLabel = "B";
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
3041
|
+
const txn = new EditTxn(imodelDb, "change codeValues");
|
|
3042
|
+
txn.start();
|
|
3043
|
+
categoryA.insert(txn);
|
|
3044
|
+
categoryB.insert(txn);
|
|
3045
|
+
txn.saveChanges();
|
|
2977
3046
|
categoryA = imodelDb.elements.getElement(SpatialCategory.createCode(imodelDb, IModel.dictionaryId, "A"));
|
|
2978
3047
|
categoryB = imodelDb.elements.getElement(SpatialCategory.createCode(imodelDb, IModel.dictionaryId, "B"));
|
|
2979
3048
|
categoryA.code.value = "temp";
|
|
2980
|
-
categoryA.update();
|
|
3049
|
+
categoryA.update(txn);
|
|
2981
3050
|
categoryB.code.value = "A";
|
|
2982
|
-
categoryB.update();
|
|
3051
|
+
categoryB.update(txn);
|
|
2983
3052
|
categoryA.code.value = "B";
|
|
2984
|
-
categoryA.update();
|
|
2985
|
-
|
|
3053
|
+
categoryA.update(txn);
|
|
3054
|
+
txn.end();
|
|
2986
3055
|
categoryA = imodelDb.elements.getElement(SpatialCategory.createCode(imodelDb, IModel.dictionaryId, "A"));
|
|
2987
3056
|
categoryB = imodelDb.elements.getElement(SpatialCategory.createCode(imodelDb, IModel.dictionaryId, "B"));
|
|
2988
3057
|
expect(categoryA.userLabel).to.equal("B", `categoryA.userLabel mismatch in ${imodelDb.name}`);
|
|
@@ -3025,17 +3094,19 @@ describe("iModel", () => {
|
|
|
3025
3094
|
function setupRelationships(numOfRelationships, multipleClasses = false) {
|
|
3026
3095
|
testImodel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IModel", "DeleteRelationshipInstances.bim"), { rootSubject: { name: "DeleteRelationshipInstances" } });
|
|
3027
3096
|
assert.isTrue(testImodel.isOpen);
|
|
3028
|
-
const
|
|
3097
|
+
const txn = new EditTxn(testImodel, "setup delete relationships");
|
|
3098
|
+
txn.start();
|
|
3099
|
+
const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(txn, Code.createEmpty(), true);
|
|
3029
3100
|
let spatialCategoryId = SpatialCategory.queryCategoryIdByName(testImodel, IModel.dictionaryId, "MySpatialCategory");
|
|
3030
3101
|
if (!spatialCategoryId) {
|
|
3031
|
-
spatialCategoryId = SpatialCategory.insert(
|
|
3102
|
+
spatialCategoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance());
|
|
3032
3103
|
}
|
|
3033
3104
|
const relationships = [];
|
|
3034
3105
|
for (let i = 0; i < numOfRelationships; ++i) {
|
|
3035
3106
|
const sourceProps = createElemProps(testImodel, newModelId, spatialCategoryId, "Generic:PhysicalObject");
|
|
3036
|
-
const sourceId =
|
|
3107
|
+
const sourceId = txn.insertElement(sourceProps);
|
|
3037
3108
|
const targetProps = createElemProps(testImodel, newModelId, spatialCategoryId, "Generic:PhysicalObject");
|
|
3038
|
-
const targetId =
|
|
3109
|
+
const targetId = txn.insertElement(targetProps);
|
|
3039
3110
|
let relationshipClass = "BisCore:ElementGroupsMembers";
|
|
3040
3111
|
if (multipleClasses)
|
|
3041
3112
|
relationshipClass = relationshipClasses[i % relationshipClasses.length];
|
|
@@ -3044,10 +3115,10 @@ describe("iModel", () => {
|
|
|
3044
3115
|
sourceId,
|
|
3045
3116
|
targetId,
|
|
3046
3117
|
};
|
|
3047
|
-
relationshipProps.id =
|
|
3118
|
+
relationshipProps.id = txn.insertRelationship(relationshipProps);
|
|
3048
3119
|
relationships.push(relationshipProps);
|
|
3049
3120
|
}
|
|
3050
|
-
|
|
3121
|
+
txn.end();
|
|
3051
3122
|
return relationships;
|
|
3052
3123
|
}
|
|
3053
3124
|
async function getRelationshipCount(iModel, relationshipClass) {
|
|
@@ -3058,16 +3129,18 @@ describe("iModel", () => {
|
|
|
3058
3129
|
it("deleteInstances with an empty array", async () => {
|
|
3059
3130
|
const relationships = setupRelationships(10);
|
|
3060
3131
|
assert.equal(relationships.length, await getRelationshipCount(testImodel, "BisCore.ElementGroupsMembers"));
|
|
3061
|
-
testImodel
|
|
3062
|
-
|
|
3132
|
+
withEditTxn(testImodel, (txn) => {
|
|
3133
|
+
txn.deleteRelationships([]);
|
|
3134
|
+
});
|
|
3063
3135
|
assert.equal(relationships.length, await getRelationshipCount(testImodel, "BisCore.ElementGroupsMembers"));
|
|
3064
3136
|
});
|
|
3065
3137
|
it("deleteInstances with a single relationship instance", async () => {
|
|
3066
3138
|
const relationships = setupRelationships(10);
|
|
3067
3139
|
assert.equal(relationships.length, await getRelationshipCount(testImodel, "BisCore.ElementGroupsMembers"), "Should delete exactly one relationship");
|
|
3068
3140
|
// Delete just one relationship using deleteInstances method
|
|
3069
|
-
testImodel
|
|
3070
|
-
|
|
3141
|
+
withEditTxn(testImodel, (txn) => {
|
|
3142
|
+
txn.deleteRelationships([relationships[0]]);
|
|
3143
|
+
});
|
|
3071
3144
|
const remainingCount = await getRelationshipCount(testImodel, "BisCore.ElementGroupsMembers");
|
|
3072
3145
|
assert.equal(remainingCount, relationships.length - 1, "Should delete exactly one relationship");
|
|
3073
3146
|
});
|
|
@@ -3078,8 +3151,9 @@ describe("iModel", () => {
|
|
|
3078
3151
|
assert.isTrue(await getRelationshipCount(testImodel, "BisCore.ElementDrivesElement") >= Math.floor(relationships.length / 3));
|
|
3079
3152
|
assert.isTrue(await getRelationshipCount(testImodel, "BisCore.ElementRefersToDocuments") >= Math.floor(relationships.length / 3));
|
|
3080
3153
|
// Test deleteInstances with mixed relationship classes
|
|
3081
|
-
testImodel
|
|
3082
|
-
|
|
3154
|
+
withEditTxn(testImodel, (txn) => {
|
|
3155
|
+
txn.deleteRelationships(relationships);
|
|
3156
|
+
});
|
|
3083
3157
|
// Verify all relationships were deleted regardless of their class
|
|
3084
3158
|
assert.equal(0, await getRelationshipCount(testImodel, "BisCore.ElementGroupsMembers"), "All ElementGroupsMembers relationships should be deleted");
|
|
3085
3159
|
assert.equal(0, await getRelationshipCount(testImodel, "BisCore.ElementDrivesElement"), "All ElementDrivesElement relationships should be deleted");
|
|
@@ -3096,8 +3170,9 @@ describe("iModel", () => {
|
|
|
3096
3170
|
for (let i = 0; i < 250; ++i) {
|
|
3097
3171
|
relationshipsToDelete.push(relationships[Math.floor(Math.random() * relationships.length)]);
|
|
3098
3172
|
}
|
|
3099
|
-
testImodel
|
|
3100
|
-
|
|
3173
|
+
withEditTxn(testImodel, (txn) => {
|
|
3174
|
+
txn.deleteRelationships(relationshipsToDelete);
|
|
3175
|
+
});
|
|
3101
3176
|
// Verify all relationships were deleted
|
|
3102
3177
|
for (const relClass of relationshipsToDelete) {
|
|
3103
3178
|
const reader = testImodel.createQueryReader(`SELECT ECInstanceId FROM ${relClass.classFullName} WHERE SourceECInstanceId=? AND TargetECInstanceId=?`, new QueryBinder().bindId(1, relClass.sourceId).bindId(2, relClass.targetId));
|