Skip to content

Commit

Permalink
fix: materialized path being computed as "undefined1." (#8526)
Browse files Browse the repository at this point in the history
* fix: materialized path being computed as "undefined1."

when tree entities are saved implicitly (through another related entity which hasMany tree-entities and "cascade" set to true) the ORM generates materialized-path strings prefixed with "undefined". Resulting in mpaths like "undefined1.2.3"

* fix: materialized path being computed as "undefined1."

removes it.only

* fix: materialized path being computed as "undefined1."

fixes unit tests

* fix: materialized path being computed as "undefined1."

Try to fix unit tests.

* fixing failing test

* fixing test

* fixing test

* fixing test

* Update materialized-path.ts

* Update materialized-path.ts

Co-authored-by: Matthias Schwebler <m.schwebler@sportradar.com>
Co-authored-by: Umed Khudoiberdiev <pleerock.me@gmail.com>
  • Loading branch information
3 people committed Feb 16, 2022
1 parent 93bf96e commit 09f54e0
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/persistence/tree/MaterializedPathSubjectExecutor.ts
Expand Up @@ -97,13 +97,13 @@ export class MaterializedPathSubjectExecutor {
.execute();
}

private getEntityPath(subject: Subject, id: ObjectLiteral): Promise<any> {
private getEntityPath(subject: Subject, id: ObjectLiteral): Promise<string> {
return this.queryRunner.manager
.createQueryBuilder()
.select(subject.metadata.targetName + "." + subject.metadata.materializedPathColumn!.propertyPath, "path")
.from(subject.metadata.target, subject.metadata.targetName)
.whereInIds(id)
.getRawOne()
.then(result => result ? result["path"] : undefined);
.then(result => result ? result["path"] : "");
}
}
15 changes: 11 additions & 4 deletions test/functional/tree-tables/materialized-path/entity/Category.ts
Expand Up @@ -4,8 +4,11 @@ import {TreeParent} from "../../../../../src/decorator/tree/TreeParent";
import {TreeChildren} from "../../../../../src/decorator/tree/TreeChildren";
import {Entity} from "../../../../../src/decorator/entity/Entity";
import {Tree} from "../../../../../src/decorator/tree/Tree";
import {ManyToOne} from "../../../../../src/decorator/relations/ManyToOne";
import {JoinColumn} from "../../../../../src/decorator/relations/JoinColumn";
import {Product} from "./Product";

@Entity()
@Entity({ name: "categories" })
@Tree("materialized-path")
export class Category {

Expand All @@ -21,7 +24,11 @@ export class Category {
@TreeChildren({ cascade: true })
childCategories: Category[];

// @TreeLevelColumn()
// level: number;
@ManyToOne(
() => Product,
(product) => product.categories,
)
@JoinColumn()
product: Product;

}
}
23 changes: 23 additions & 0 deletions test/functional/tree-tables/materialized-path/entity/Product.ts
@@ -0,0 +1,23 @@
import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {Entity} from "../../../../../src/decorator/entity/Entity";
import {Category} from "./Category";
import {OneToMany} from "../../../../../src/decorator/relations/OneToMany";
import {Column} from "../../../../../src/decorator/columns/Column";

@Entity()
export class Product {

@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@OneToMany(
() => Category,
(category) => category.product,
{ cascade: true },
)
categories: Category[];

}
Expand Up @@ -2,12 +2,14 @@ import "reflect-metadata";
import {Category} from "./entity/Category";
import {Connection} from "../../../../src/connection/Connection";
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
import {Product} from "./entity/Product";

describe("tree tables > materialized-path", () => {

let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [Category],
entities: [Product, Category],
logging: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
Expand Down Expand Up @@ -570,4 +572,37 @@ describe("tree tables > materialized-path", () => {
]
});
})));

it("should compute path correctly when tree is implicitly saved (cascade: true) through related entity", () => Promise.all(connections.map(async connection => {
const categoryRepository = connection.getRepository(Category);
const productRepository = connection.getRepository(Product);

// first increment the category primary id once by saving and removing an item
// this is necessary to reproduce the bug behaviour
const existingCategory = new Category();
existingCategory.name = "irrelevant";
await categoryRepository.save(existingCategory);
await categoryRepository.delete(existingCategory);

// set up a product with category tree `{name: "My product", categories: [{name: "root", children: [{name: "child"}]}]}`
const childCategory = new Category();
childCategory.name = "child";
const rootCategory = new Category();
rootCategory.name = "root";
rootCategory.childCategories = [childCategory];
const product = new Product();
product.name = "My product";
product.categories = [rootCategory];

// save it alongside its categories ( cascade )
const savedProduct = await productRepository.save(product);
const pathResult = await connection.createQueryBuilder()
.select("category.mpath", "mpath")
.from("categories", "category")
.where("category.product = :id")
.setParameters({ id: savedProduct.id })
.getRawOne();

pathResult.mpath.should.not.match(/^undefined/);
})));
});

0 comments on commit 09f54e0

Please sign in to comment.