UNPKG

@itwin/core-backend

Version:
371 lines 19.7 kB
/** @packageDocumentation * @module iModels */ import { DbResult, Id64Arg, Id64Array, Id64Set, Id64String } from "@itwin/core-bentley"; import { EcefLocationProps, ElementAspectProps, ElementProps, FilePropertyProps, ModelProps, RelationshipProps, SaveChangesArgs } from "@itwin/core-common"; import { Range3dProps } from "@itwin/core-geometry"; import type { CloudSqlite } from "./CloudSqlite"; import type { ImplicitWriteEnforcement } from "./IModelHost"; import type { ChangeElementModelProps, ChangeElementParentProps, IModelDb, InsertElementOptions, UpdateModelOptions } from "./IModelDb"; import type { SettingsContainer } from "./workspace/Settings"; /** Options for bulk deleting elements from an iModelDb. * @beta */ export interface BulkDeleteElementsArgs { /** * Skips pre-deletion **NO ACTION** foreign key constraint validation checks, which may improve performance for large deletions. * This will improve performance, but if the user supplies elements which have FK constraint violations, it will result in the delete failing and an eventual rollback. */ skipFKConstraintValidations?: boolean; } /** * Result of a bulk element delete operation. * @beta */ export interface BulkDeleteElementsResult { /** * Overall status of the bulk delete operation. * - `Success`: All elements were deleted successfully. `failedIds` will be empty. * - `PartialSuccess`: Some elements were deleted, but others failed. `failedIds` contains the ids that could not be deleted. * - `DeletionFailed`: The delete operation failed entirely (e.g. due to an FK constraint violation). `failedIds` contains the ids that could not be deleted. */ status: BulkDeleteElementsStatus; /** * The raw SQLite result code from the underlying SQL DELETE statement. * `DbResult.BE_SQLITE_OK` on success; a non-OK code indicates a database-level error such as a constraint violation. */ sqlDeleteStatus: DbResult; /** * The set of element ids that could not be deleted. * Empty when `status` is `Success`. Non-empty when `status` is `PartialSuccess` or `DeletionFailed`. */ failedIds: Id64Set; } /** * Status of a bulk element delete operation, mirroring the C++ `BulkDeleteStatus` enum. * @beta */ export declare enum BulkDeleteElementsStatus { /** All supplied elements were deleted successfully. */ Success = 0, /** Some elements were deleted but others could not be, typically due to foreign key constraints on the elements not being deleted. */ PartialSuccess = 1, /** No elements were deleted. This occurs when the SQL DELETE statement itself fails, e.g. due to a FK constraint violation that prevents the entire batch from being processed. */ DeletionFailed = 2 } /** * Represents an explicit editing transaction for an iModel. * * An explicit EditTxn lets callers define a deliberate unit of work by choosing when editing * starts (`start`) and how it ends (`end()` / `end("save")` or `end("abandon")`). This avoids mixing * unrelated edits into one implicit unit of work and makes save/rollback boundaries explicit. * * Explicit EditTxn instances must be active before mutating operations are performed, regardless of enforcement level. * In other words, explicit transaction behavior is independent of `implicitWriteEnforcement`. * * @see [EditTxn transaction model and migration guidance]($docs/learning/backend/EditTxn.md) * * *During indirect changes (commit processing):* Use callback args (`indirectEditTxn`) in callbacks like * [[Relationship.onRootChangedArg]] and [[Relationship.onDeletedDependencyArg]] that fire during indirect processing. * * @beta */ export declare class EditTxn { /** Controls how writes through the implicit transaction are handled. * * This does not relax activation requirements for explicit transactions: explicit EditTxn writes * must always come from the active EditTxn. * * - `allow`: allow implicit writes for backwards compatibility, even while an explicit EditTxn is active. * - `log`: allow implicit writes but log `implicit-txn-write-disallowed` errors. * - `throw`: reject implicit writes with `implicit-txn-write-disallowed`. * * This is initialized from [[IModelHostOptions.implicitWriteEnforcement]] during [[IModelHost.startup]]. * * Defaults to `allow` for backwards compatibility. * @beta */ static implicitWriteEnforcement: ImplicitWriteEnforcement; /** The iModel this EditTxn may modify. */ readonly iModel: IModelDb; /** Default description passed to [[saveChanges]] when saving this transaction. */ description: string; /** True if this transaction currently owns the iModel write surface. */ get isActive(): boolean; constructor(iModel: IModelDb, description: string); verifyWriteable(): void; /** Start this EditTxn, making it the active transaction for the iModel. * @throws EditTxnError if this EditTxn is already active, another EditTxn is already active, or if unsaved changes are present. */ start(): void; /** End this EditTxn, either by saving or abandoning the changes. * @param mode Whether to "save" or "abandon" the changes. Defaults to "save". * @param args Save changes arguments when saving. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if saving changes fails. */ end(): void; end(mode: "save" | "abandon", args?: string | SaveChangesArgs): void; /** Invoked when the owning iModel is closing. * The base implementation commits unsaved changes. Subclasses may override to customize how * their changes are handled before the iModel closes. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if saving on close fails. */ onClose(): void; /** Abandon database changes while keeping this EditTxn active. * @throws EditTxnError if this EditTxn is not active. */ abandonChanges(): void; /** Save changes with additional arguments. * @param args Save changes arguments. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if the iModel is readonly, if indirect changes are active, or if the native save fails. */ saveChanges(args?: string | SaveChangesArgs): void; /** Insert a new element into the iModel. * @param elProps The properties of the new element. * @returns The newly inserted element's Id. * @throws EditTxnError if this EditTxn is not active. * @throws [[ITwinError]] if insertion fails. */ insertElement(elProps: ElementProps, options?: InsertElementOptions): Id64String; /** Update an existing element in the iModel. * @param elProps The properties to update. * @throws EditTxnError if this EditTxn is not active. * @throws [[ITwinError]] if update fails. */ updateElement<T extends ElementProps>(elProps: Partial<T>): void; /** Delete elements from the iModel. * @param ids The Ids of the elements to delete. * @throws EditTxnError if this EditTxn is not active. * @throws [[ITwinError]] if deletion fails. */ deleteElement(ids: Id64Arg): void; /** Change the parent of an element within its model. * * The new parent must be in the same model as the element. Cross-model reparenting is not allowed; * use [[changeElementModel]] only to move root elements between models. * Only the target element is reparented — its children and their model membership are unaffected. * * **Blocked cases** (will throw): * - The new parent is in a different model than the element. * - Element has a `ParentElement`-scoped code (code uniqueness is tied to the parent; use delete+insert instead). * * **Allowed cases**: * - Element has a `Repository`-scoped code (unique across entire iModel — unaffected by the parent change). * - Element has a `RelatedElement`-scoped code (scope element is independent of the parent). * - Element has a `Model`-scoped code (the model does not change, so the code remains valid). * - Element has no meaningful code (empty code). * * Channel verification is performed on the element's model. * Lock enforcement: requires an exclusive lock on the element, and a shared lock on the new parent. * @param props The reparent parameters: element id and new parent id. * @throws EditTxnError if this EditTxn is not active. * @throws [[ITwinError]] if the operation fails. * @beta */ changeElementParent(props: ChangeElementParentProps): void; /** Change the model of a root element, making it a root element in the new model. * * The element must not have a parent. * The element's entire subtree moves with it: BIS requires a parent and all of its children to reside * in the same model, so every descendant of the element is relocated into the target model as well. * The parent-child hierarchy is preserved. The whole subtree is validated before anything is moved, so * a rejected change leaves the iModel untouched. * * **Blocked cases** (will throw): * - Element has a parent (only root elements can be moved between models). * - Any element in the subtree has a `Model`-scoped code (code uniqueness is tied to the source model; use delete+insert instead). * - The moved (root) element has a `ParentElement`-scoped code (use delete+insert instead). A descendant's `ParentElement`-scoped code is allowed, because its parent moves with it. * * **Allowed cases** (for any element in the subtree): * - A `Repository`-scoped code (unique across entire iModel — unaffected by the model change). * - A `RelatedElement`-scoped code (scope element is independent of the model). * - No meaningful code (empty code). * * The source and target models must be of the same class (classFullName must match exactly). * Channel verification is performed on both the source and target models. * Lock enforcement: requires an exclusive lock on every element in the moved subtree, and a shared lock on the target model. * @param props The model change parameters: element id and target model id. * @throws EditTxnError if this EditTxn is not active. * @throws [[ITwinError]] if the operation fails. * @beta */ changeElementModel(props: ChangeElementModelProps): void; /** Collect an element together with all of its descendants by walking the `ElementOwnsChildElements` * hierarchy depth-first. Used to invalidate the cached props of every element affected by a subtree move. */ private collectSubtreeIds; /** * Delete multiple elements from the iModel. * @param ids The ids of the elements to delete. All ids must be well-formed and valid [[Id64String]]s. * @param deleteOptions Options for the delete operation. * @returns A result object containing information about the deletion operation success and the element ids that failed to delete (if any). * @throws [[ITwinError]] if any of the supplied ids are not well-formed/valid [[Id64String]]s. * @beta */ deleteElements(ids: Id64Array, deleteOptions?: BulkDeleteElementsArgs): BulkDeleteElementsResult; /** Insert a new aspect into the iModel. * @param aspectProps The properties of the new aspect. * @returns The newly inserted aspect Id. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if insertion fails. */ insertAspect(aspectProps: ElementAspectProps): Id64String; /** Update an existing aspect in the iModel. * @param aspectProps The properties of the aspect to update. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if update fails. */ updateAspect(aspectProps: ElementAspectProps): void; /** Delete one or more aspects from the iModel. * @param aspectInstanceIds The Ids of the aspects to delete. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if deletion fails. */ deleteAspect(aspectInstanceIds: Id64Arg): void; /** Delete definition elements from the iModel when they are not referenced. * @param definitionElementIds The Ids of the definition elements to attempt to delete. * @returns The set of definition elements that were still in use and therefore not deleted. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if usage queries fail. */ deleteDefinitionElements(definitionElementIds: Id64Array): Id64Set; /** Insert a new model into the iModel. * @param props The data for the new model. * @returns The newly inserted model's Id. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if insertion fails. */ insertModel(props: ModelProps): Id64String; /** Update an existing model in the iModel. * @param props the properties of the model to change * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if update fails. */ updateModel(props: UpdateModelOptions): void; /** Update the geometry guid of a model. * @param modelId The Id of the model to update. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if the update fails. */ updateGeometryGuid(modelId: Id64String): void; /** Delete models from the iModel. * @param ids The Ids of the models to delete. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if deletion fails. */ deleteModel(ids: Id64Arg): void; /** Insert a new relationship into the iModel. * @param props The properties of the new relationship. * @returns The Id of the newly inserted relationship. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if the class is invalid for link-table insertion. */ insertRelationship(props: RelationshipProps): Id64String; /** Update an existing relationship in the iModel. * @param props the properties of the relationship to update. * @throws EditTxnError if this EditTxn is not active. */ updateRelationship(props: RelationshipProps): void; /** Delete a relationship from the iModel. * @param props The properties of the relationship to delete. * @throws EditTxnError if this EditTxn is not active. */ deleteRelationship(props: RelationshipProps): void; /** Delete multiple relationships from the iModel. * @param props The properties of the relationships to delete. * @throws EditTxnError if this EditTxn is not active. */ deleteRelationships(props: ReadonlyArray<RelationshipProps>): void; /** Save a file property to the iModel. * @param prop The file property to save. * @param strValue String value. * @param blobVal Blob value. * @throws EditTxnError if this EditTxn is not active. */ saveFileProperty(prop: FilePropertyProps, strValue: string | undefined, blobVal?: Uint8Array): void; /** Delete a file property from the iModel. * @param prop The file property to delete. * @throws EditTxnError if this EditTxn is not active. */ deleteFileProperty(prop: FilePropertyProps): void; /** Update the project extents of the iModel. * @param newExtents The new project extents. * @throws EditTxnError if this EditTxn is not active. * @throws IModelError if extents are invalid. */ updateProjectExtents(newExtents: Range3dProps): void; /** Update the ECEF location of the iModel. * @param ecef The new ECEF location. * @throws EditTxnError if this EditTxn is not active. */ updateEcefLocation(ecef: EcefLocationProps): void; /** Update the iModel props in the database from the current in-memory state. * @throws EditTxnError if this EditTxn is not active. */ updateIModelProps(): void; private static readonly _settingPropNamespace; private static readonly _viewStoreProperty; /** Save a `SettingDictionary` in this iModel. * @param name The name for the SettingDictionary. If a dictionary by that name already exists, its value is replaced. * @param dict The SettingDictionary object to stringify and save. * @throws EditTxnError if this EditTxn is not active. * @beta */ saveSettingDictionary(name: string, dict: SettingsContainer): void; /** Delete a SettingDictionary from this iModel. * @param name The name of the dictionary to delete. * @throws EditTxnError if this EditTxn is not active. * @beta */ deleteSettingDictionary(name: string): void; /** Save a default ViewStore container reference in this iModel. * @param arg The cloud container properties for the ViewStore. * @throws EditTxnError if this EditTxn is not active. * @beta */ saveDefaultViewStore(arg: CloudSqlite.ContainerProps): void; } /** Execute a callback within an explicit editing transaction. A new [[EditTxn]] is created, started, * and passed to `fn`. If `fn` returns normally (or its returned Promise resolves), the transaction * is committed. If `fn` throws (or its returned Promise rejects), the transaction is abandoned — * none of the changes made during the callback are saved — and the error is re-thrown. * * This is the recommended way to perform a scoped unit of work on an iModel. It ensures that * edits are committed atomically on success and rolled back on failure, without the caller needing * to manage `start` / `end` manually. * * @param iModel The iModel to edit. * @param fn A callback that receives the active [[EditTxn]] and performs edits. * @returns The value returned by `fn`. * @throws EditTxnError if the transaction cannot be started (e.g. unsaved changes or another EditTxn is active). * @throws Re-throws any error thrown by `fn` after abandoning the transaction. * @beta */ export declare function withEditTxn<T>(iModel: IModelDb, fn: (txn: EditTxn) => T): T; /** Execute a callback within an explicit editing transaction, supplying commit arguments. * @param iModel The iModel to edit. * @param saveArgs Description or structured arguments passed to [[EditTxn.saveChanges]] on save. * @param fn A callback that receives the active [[EditTxn]] and performs edits. * @returns The value returned by `fn`. * @beta */ export declare function withEditTxn<T>(iModel: IModelDb, saveArgs: string | SaveChangesArgs, fn: (txn: EditTxn) => T): T; /** Execute an async callback within an explicit editing transaction. * @param iModel The iModel to edit. * @param fn An async callback that receives the active [[EditTxn]] and performs edits. * @returns A Promise that resolves to the value returned by `fn`. * @beta */ export declare function withEditTxn<T>(iModel: IModelDb, fn: (txn: EditTxn) => Promise<T>): Promise<T>; /** Execute an async callback within an explicit editing transaction, supplying commit arguments. * @param iModel The iModel to edit. * @param saveArgs Description or structured arguments passed to [[EditTxn.saveChanges]] on save. * @param fn An async callback that receives the active [[EditTxn]] and performs edits. * @returns A Promise that resolves to the value returned by `fn`. * @beta */ export declare function withEditTxn<T>(iModel: IModelDb, saveArgs: string | SaveChangesArgs, fn: (txn: EditTxn) => Promise<T>): Promise<T>; //# sourceMappingURL=EditTxn.d.ts.map