Skip to content

Tree entities with embedded primary columns are not built correctly #7415

@Tomaszal

Description

@Tomaszal

Issue Description

Expected Behavior

Tree entities with embedded primary columns should be built correctly, making it possible to use findDescendantsTree, findAncestorsTree, etc.

Actual Behavior

Due to inconsistent column fetching in TreeReposiotry tree building methods the comparison of parents & children fails, thus also failing the tree building process.

protected buildChildrenEntityTree(entity: any, entities: any[], relationMaps: { id: any, parentId: any }[]): void {
    const childProperty = this.metadata.treeChildrenRelation!.propertyName;
    const parentEntityId = this.metadata.primaryColumns[0].getEntityValue(entity);
    const childRelationMaps = relationMaps.filter(relationMap => relationMap.parentId === parentEntityId);
    const childIds = new Set(childRelationMaps.map(relationMap => relationMap.id));
    entity[childProperty] = entities.filter(entity => childIds.has(entity[this.metadata.primaryColumns[0].propertyName]));
    entity[childProperty].forEach((childEntity: any) => {
        this.buildChildrenEntityTree(childEntity, entities, relationMaps);
    });
}

In the above code, parentEntityId is fetched using getEntityValue, which fetches embedded entities. However, the children are filtered by directly accessing the value of the column. Thus this fails when the primary column is an embedded entity. This is also the case when building parent entity tree.

const parentEntityId = this.metadata.primaryColumns[0].getEntityValue(entity);
entity[childProperty] = entities.filter(entity => childIds.has(entity[this.metadata.primaryColumns[0].propertyName]));

Steps to Reproduce

  1. Set up entities as provided below
  2. Try to fetch descendants tree of a1
  3. The tree should have a child a11, however it has no children
@Entity()
@Tree("materialized-path")
class Category {
    @Column((type) => Slug, { prefix: false })
    id: Slug;

    @TreeChildren()
    children: Category[];

    @TreeParent()
    parent: Category;

    constructor(slug: string, parent?: Category) {
        this.id = new Slug(slug);
        if (parent) this.parent = parent;
    }
}

class Slug {
    @PrimaryColumn()
    slug: string;

    constructor(slug: string) {
        this.slug = slug;
    }
}

const a1 = new Category("1");
await manager.save(a1);

const a11 = new Category("1.1", a1);
await manager.save(a11);

const tree = await repository.findDescendantsTree(a1);

My Environment

Dependency Version
Operating System Manjaro 20.2.1 Nibia
Node.js version v15.8.0
Typescript version v3.6.5
TypeORM version v0.2.31

Additional Context

I have already fixed this, just submitting this bug to submit a PR :)

Relevant Database Driver(s)

All drivers which work with Tree Entities should be affected, however I am not sure which those would be (perhaps all of them).

  • aurora-data-api
  • aurora-data-api-pg
  • better-sqlite3
  • cockroachdb
  • cordova
  • expo
  • mongodb
  • mysql
  • nativescript
  • oracle
  • postgres
  • react-native
  • sap
  • sqlite
  • sqlite-abstract
  • sqljs
  • sqlserver

Are you willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time, and I know how to start.
  • Yes, I have the time, but I don't know how to start. I would need guidance.
  • No, I don't have the time, although I believe I could do it if I had the time...
  • No, I don't have the time and I wouldn't even know how to start.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions