Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DeleteElementTree throws Foreign Key Constraint error when deleting an element that is referenced in other elements as code scope #5576

Closed
DeividasDavidav opened this issue May 30, 2023 · 1 comment

Comments

@DeividasDavidav
Copy link

DeividasDavidav commented May 30, 2023

Describe the bug
When using deleteElementTree() function from ElementTreeWalker.ts to delete an element, if an element is referenced by other elements in their code scopes, it throws Foreign key constraint error.

To Reproduce
Steps to reproduce the behavior:

  1. Create the first element
  2. Create the second element that references the first element in its code scope
  3. Use deleteElementTree() on the first element
  4. See "error deleting element" error (errorNumber: 65553)

Expected behavior
When deleting an element, processElementTree() function in ElementTreeBottomUp class should also process the elements that reference the element in their code scopes.

Possible solution to this issue:

export abstract class ElementTreeBottomUp {

+ protected shouldVisitCodeScopes(_elementId : string, _scope : ElementTreeWalkerScope) { return true; }

  /** The main tree-walking function */
  protected processElementTree(element: Id64String, scope: ElementTreeWalkerScope) {
    const subModel = this._iModel.models.tryGetModel<Model>(element);
    if (subModel !== undefined) {
      if (this.shouldExploreModel(subModel, scope))
        this._processSubModel(subModel, scope);

      if (this.shouldVisitModel(subModel, scope))
        this.visitModel(subModel, scope);
    }

+   if (this.shouldVisitCodeScopes(element, scope))
+     this._processCodeScopes(element, scope);

    if (this.shouldExploreChildren(element, scope))
      this._processChildren(element, scope);

    if (this.shouldVisitElement(element, scope))
      this.visitElement(element, scope);
  }

+ private _processCodeScopes(element: string, parentScope: ElementTreeWalkerScope) {
+   const scope = new ElementTreeWalkerScope(parentScope, element);
+   this._iModel.withPreparedStatement("select ECInstanceId from bis.Element where CodeScope.id=? and Parent.id is null", stmt => {
+       stmt.bindId(1, element);
+       while (stmt.step() === DbResult.BE_SQLITE_ROW) {
+           const elementId = stmt.getValue(0).getId();
+           this.processElementTree(elementId, scope);
+       }
+   });
+ }
} 

Desktop (please complete the applicable information):

  • iTwin.js Version 3.6.1
  • Node Version 18.16.0
@pmconne
Copy link
Member

pmconne commented May 30, 2023

The "element tree" is based on parent-child relationships between elements. Your repro steps describe a different relationship, based on code scope. Your second element is therefore not part of the first element's tree and the behavior you describe is expected.

@swwilson-bsi can correct me if I misunderstand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants