mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix(tree-entity): closure junction table primary key definition should match parent table (#11422)
* fix #9600 https://github.com/typeorm/typeorm/issues/9600 * implement tests. * implement tests. * implement tests. * move tests fo functional tab. implement remaining tests. implement remaining fields. * fix code rabbit detected errors. * add MySQL-specific type checks to closure-table tests * split closure-table tests for MySQL-specific scenarios * remove redundant MySQL type checks from closure-table tests * move MySQL-specific closure-table tests to a separate file --------- Co-authored-by: Gonçalo Alves <goncalo.alves@knowledgeworks.pt> Co-authored-by: gioboa <giorgiob.boa@gmail.com>
This commit is contained in:
parent
03faa7867e
commit
ce23d4648e
@ -63,6 +63,13 @@ export class ClosureJunctionEntityMetadataBuilder {
|
||||
primary: true,
|
||||
length: primaryColumn.length,
|
||||
type: primaryColumn.type,
|
||||
unsigned: primaryColumn.unsigned,
|
||||
width: primaryColumn.width,
|
||||
precision: primaryColumn.precision,
|
||||
scale: primaryColumn.scale,
|
||||
zerofill: primaryColumn.zerofill,
|
||||
charset: primaryColumn.charset,
|
||||
collation: primaryColumn.collation,
|
||||
},
|
||||
},
|
||||
}),
|
||||
@ -88,6 +95,13 @@ export class ClosureJunctionEntityMetadataBuilder {
|
||||
primary: true,
|
||||
length: primaryColumn.length,
|
||||
type: primaryColumn.type,
|
||||
unsigned: primaryColumn.unsigned,
|
||||
width: primaryColumn.width,
|
||||
precision: primaryColumn.precision,
|
||||
scale: primaryColumn.scale,
|
||||
zerofill: primaryColumn.zerofill,
|
||||
charset: primaryColumn.charset,
|
||||
collation: primaryColumn.collation,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
135
test/functional/tree-tables/closure-table/closure-table-mysql.ts
Normal file
135
test/functional/tree-tables/closure-table/closure-table-mysql.ts
Normal file
@ -0,0 +1,135 @@
|
||||
import "reflect-metadata"
|
||||
import { Foo1Entity } from "./entity/Foo1"
|
||||
import { Foo2Entity } from "./entity/Foo2"
|
||||
import { Foo3Entity } from "./entity/Foo3"
|
||||
import { DataSource } from "../../../../src/data-source/DataSource"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../../utils/test-utils"
|
||||
import { expect } from "chai"
|
||||
|
||||
describe("mysql > tree tables > closure-table", () => {
|
||||
let connections: DataSource[]
|
||||
before(
|
||||
async () =>
|
||||
(connections = await createTestingConnections({
|
||||
entities: [Foo1Entity, Foo2Entity, Foo3Entity],
|
||||
enabledDrivers: ["mysql"],
|
||||
})),
|
||||
)
|
||||
beforeEach(() => reloadTestingDatabases(connections))
|
||||
after(() => closeTestingConnections(connections))
|
||||
|
||||
it("foo1 should create closure columns unsigned", () =>
|
||||
Promise.all(
|
||||
connections.map(async (dataSource) => {
|
||||
const fooMetadata = dataSource.entityMetadatas.find(
|
||||
(el) => el.tableName === "foo1",
|
||||
)!
|
||||
|
||||
expect(fooMetadata).to.exist
|
||||
|
||||
const fooClosureMetadata = dataSource.entityMetadatas.find(
|
||||
(el) => el.tableName === "foo1_closure",
|
||||
)!
|
||||
|
||||
expect(fooClosureMetadata).to.exist
|
||||
|
||||
const ancestorCol = fooClosureMetadata.columns.find(
|
||||
(col) => col.databaseName === "ancestor_id",
|
||||
)!
|
||||
|
||||
expect(ancestorCol).to.exist
|
||||
|
||||
const descendantCol = fooClosureMetadata.columns.find(
|
||||
(col) => col.databaseName === "descendant_id",
|
||||
)!
|
||||
|
||||
expect(descendantCol).to.exist
|
||||
|
||||
expect(ancestorCol.unsigned).to.be.true
|
||||
expect(descendantCol.unsigned).to.be.true
|
||||
}),
|
||||
))
|
||||
|
||||
it("foo2 should create closure columns with specified zerofill, width, precision and scale", () =>
|
||||
Promise.all(
|
||||
connections.map(async (dataSource) => {
|
||||
const fooMetadata = dataSource.entityMetadatas.find(
|
||||
(el) => el.tableName === "foo2",
|
||||
)!
|
||||
|
||||
expect(fooMetadata).to.exist
|
||||
|
||||
const fooClosureMetadata = dataSource.entityMetadatas.find(
|
||||
(el) => el.tableName === "foo2_closure",
|
||||
)!
|
||||
|
||||
expect(fooClosureMetadata).to.exist
|
||||
|
||||
const ancestorCol = fooClosureMetadata.columns.find(
|
||||
(col) => col.databaseName === "ancestor_id",
|
||||
)!
|
||||
|
||||
expect(ancestorCol).to.exist
|
||||
|
||||
const descendantCol = fooClosureMetadata.columns.find(
|
||||
(col) => col.databaseName === "descendant_id",
|
||||
)!
|
||||
|
||||
expect(descendantCol).to.exist
|
||||
|
||||
expect(ancestorCol.zerofill).to.be.true
|
||||
expect(descendantCol.zerofill).to.be.true
|
||||
|
||||
expect(ancestorCol.width).to.be.eq(13)
|
||||
expect(descendantCol.width).to.be.eq(13)
|
||||
|
||||
expect(ancestorCol.precision).to.be.eq(9)
|
||||
expect(descendantCol.precision).to.be.eq(9)
|
||||
|
||||
expect(ancestorCol.scale).to.be.eq(3)
|
||||
expect(descendantCol.scale).to.be.eq(3)
|
||||
}),
|
||||
))
|
||||
|
||||
it("foo3 should create closure columns with specified length, charset and collation", () =>
|
||||
Promise.all(
|
||||
connections.map(async (dataSource) => {
|
||||
const fooMetadata = dataSource.entityMetadatas.find(
|
||||
(el) => el.tableName === "foo3",
|
||||
)!
|
||||
|
||||
expect(fooMetadata).to.exist
|
||||
|
||||
const fooClosureMetadata = dataSource.entityMetadatas.find(
|
||||
(el) => el.tableName === "foo3_closure",
|
||||
)!
|
||||
|
||||
expect(fooClosureMetadata).to.exist
|
||||
|
||||
const ancestorCol = fooClosureMetadata.columns.find(
|
||||
(col) => col.databaseName === "ancestor_id",
|
||||
)!
|
||||
|
||||
expect(ancestorCol).to.exist
|
||||
|
||||
const descendantCol = fooClosureMetadata.columns.find(
|
||||
(col) => col.databaseName === "descendant_id",
|
||||
)!
|
||||
|
||||
expect(descendantCol).to.exist
|
||||
|
||||
expect(ancestorCol.length).to.be.eq("201")
|
||||
expect(descendantCol.length).to.be.eq("201")
|
||||
|
||||
expect(ancestorCol.charset).to.be.eq("latin1")
|
||||
expect(descendantCol.charset).to.be.eq("latin1")
|
||||
|
||||
expect(ancestorCol.collation).to.be.eq("latin1_bin")
|
||||
expect(descendantCol.collation).to.be.eq("latin1_bin")
|
||||
}),
|
||||
))
|
||||
})
|
||||
30
test/functional/tree-tables/closure-table/entity/Foo1.ts
Normal file
30
test/functional/tree-tables/closure-table/entity/Foo1.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
PrimaryGeneratedColumn,
|
||||
Tree,
|
||||
TreeChildren,
|
||||
TreeParent,
|
||||
} from "../../../../../src"
|
||||
|
||||
@Entity({ name: "foo1" })
|
||||
@Tree("closure-table", {
|
||||
closureTableName: "foo1",
|
||||
ancestorColumnName: () => "ancestor_id",
|
||||
descendantColumnName: () => "descendant_id",
|
||||
})
|
||||
export class Foo1Entity {
|
||||
@PrimaryGeneratedColumn({ type: "int", name: "id", unsigned: true })
|
||||
id: number
|
||||
|
||||
@Column({ type: "int", name: "parent_id", unsigned: true })
|
||||
parentId: number
|
||||
|
||||
@TreeParent()
|
||||
@JoinColumn({ name: "parent_id", referencedColumnName: "id" })
|
||||
parent: Foo1Entity
|
||||
|
||||
@TreeChildren()
|
||||
children: Foo1Entity[]
|
||||
}
|
||||
44
test/functional/tree-tables/closure-table/entity/Foo2.ts
Normal file
44
test/functional/tree-tables/closure-table/entity/Foo2.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
PrimaryColumn,
|
||||
Tree,
|
||||
TreeChildren,
|
||||
TreeParent,
|
||||
} from "../../../../../src"
|
||||
|
||||
@Entity({ name: "foo2" })
|
||||
@Tree("closure-table", {
|
||||
closureTableName: "foo2",
|
||||
ancestorColumnName: () => "ancestor_id",
|
||||
descendantColumnName: () => "descendant_id",
|
||||
})
|
||||
export class Foo2Entity {
|
||||
@PrimaryColumn({
|
||||
type: "decimal",
|
||||
name: "id",
|
||||
zerofill: true,
|
||||
width: 13,
|
||||
precision: 9,
|
||||
scale: 3,
|
||||
})
|
||||
id: number
|
||||
|
||||
@Column({
|
||||
type: "decimal",
|
||||
name: "parent_id",
|
||||
zerofill: true,
|
||||
width: 13,
|
||||
precision: 9,
|
||||
scale: 3,
|
||||
})
|
||||
parentId: number
|
||||
|
||||
@TreeParent()
|
||||
@JoinColumn({ name: "parent_id", referencedColumnName: "id" })
|
||||
parent: Foo2Entity
|
||||
|
||||
@TreeChildren()
|
||||
children: Foo2Entity[]
|
||||
}
|
||||
42
test/functional/tree-tables/closure-table/entity/Foo3.ts
Normal file
42
test/functional/tree-tables/closure-table/entity/Foo3.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
PrimaryColumn,
|
||||
Tree,
|
||||
TreeChildren,
|
||||
TreeParent,
|
||||
} from "../../../../../src"
|
||||
|
||||
@Entity({ name: "foo3" })
|
||||
@Tree("closure-table", {
|
||||
closureTableName: "foo3",
|
||||
ancestorColumnName: () => "ancestor_id",
|
||||
descendantColumnName: () => "descendant_id",
|
||||
})
|
||||
export class Foo3Entity {
|
||||
@PrimaryColumn({
|
||||
type: "varchar",
|
||||
name: "id",
|
||||
length: 201,
|
||||
charset: "latin1",
|
||||
collation: "latin1_bin",
|
||||
})
|
||||
id: string
|
||||
|
||||
@Column({
|
||||
type: "varchar",
|
||||
name: "parent_id",
|
||||
length: 201,
|
||||
charset: "latin1",
|
||||
collation: "latin1_bin",
|
||||
})
|
||||
parentId: string
|
||||
|
||||
@TreeParent()
|
||||
@JoinColumn({ name: "parent_id", referencedColumnName: "id" })
|
||||
parent: Foo3Entity
|
||||
|
||||
@TreeChildren()
|
||||
children: Foo3Entity[]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user