diff --git a/src/metadata-builder/JunctionEntityMetadataBuilder.ts b/src/metadata-builder/JunctionEntityMetadataBuilder.ts index e5464329075..76495c88e1f 100644 --- a/src/metadata-builder/JunctionEntityMetadataBuilder.ts +++ b/src/metadata-builder/JunctionEntityMetadataBuilder.ts @@ -143,14 +143,16 @@ export class JunctionEntityMetadataBuilder { referencedEntityMetadata: relation.entityMetadata, columns: junctionColumns, referencedColumns: referencedColumns, - onDelete: relation.onDelete || "CASCADE" + onDelete: relation.onDelete || "CASCADE", + onUpdate: relation.onUpdate || "CASCADE" }), new ForeignKeyMetadata({ entityMetadata: entityMetadata, referencedEntityMetadata: relation.inverseEntityMetadata, columns: inverseJunctionColumns, referencedColumns: inverseReferencedColumns, - onDelete: relation.onDelete || "CASCADE" + onDelete: relation.inverseRelation ? relation.inverseRelation.onDelete : "CASCADE", + onUpdate: relation.inverseRelation ? relation.inverseRelation.onUpdate : "CASCADE", }), ]; diff --git a/test/github-issues/4980/entity/Author.ts b/test/github-issues/4980/entity/Author.ts new file mode 100644 index 00000000000..00aff4d7631 --- /dev/null +++ b/test/github-issues/4980/entity/Author.ts @@ -0,0 +1,26 @@ +import { PrimaryGeneratedColumn, JoinTable, ManyToMany, Entity } from "../../../../src"; +import { Book } from "./Book"; + +@Entity("author") +export class Author { + @PrimaryGeneratedColumn() + id: number; + + @ManyToMany( + () => Book, + book => book.authors, + { onDelete: "CASCADE", onUpdate: "CASCADE" } + ) + @JoinTable({ + name: "author_to_books", + joinColumn: { + name: "author_id", + referencedColumnName: "id", + }, + inverseJoinColumn: { + name: "book_id", + referencedColumnName: "id", + }, + }) + books: Book[]; +} diff --git a/test/github-issues/4980/entity/Book.ts b/test/github-issues/4980/entity/Book.ts new file mode 100644 index 00000000000..2065bfd9302 --- /dev/null +++ b/test/github-issues/4980/entity/Book.ts @@ -0,0 +1,15 @@ +import { PrimaryGeneratedColumn, ManyToMany, Entity } from "../../../../src"; +import { Author } from "./Author"; + +@Entity("book") +export class Book { + @PrimaryGeneratedColumn() + id: number; + + @ManyToMany( + () => Author, + author => author.books, + { onDelete: "NO ACTION", onUpdate: "CASCADE"} + ) + authors: Author[]; +} diff --git a/test/github-issues/4980/issue-4980.ts b/test/github-issues/4980/issue-4980.ts new file mode 100644 index 00000000000..d60e13ed667 --- /dev/null +++ b/test/github-issues/4980/issue-4980.ts @@ -0,0 +1,42 @@ +import { Connection } from "../../../src"; +import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Author } from "./entity/Author"; +import { Book } from "./entity/Book"; +import { expect } from "chai"; + +describe("github issues > #4980 (Postgres) onUpdate: 'CASCADE' doesn't work on many-to-many relation", () => { + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [Author, Book], + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should generate onDelete: CASCADE and onUpdate: CASCADE for 'books' side of many-to-many relation", () => Promise.all(connections.map(async connection => { + const booksRelation = connection.getMetadata(Author).manyToManyRelations.find(mtm => mtm.propertyName === "books"); + expect(booksRelation).not.to.be.undefined; + expect(booksRelation!.onDelete).to.be.equal("CASCADE"); + expect(booksRelation!.onUpdate).to.be.equal("CASCADE"); + }))); + it("should generate onDelete: NO ACTION and onUpdate: CASCADE for 'authors' side of many-to-many relation", () => Promise.all(connections.map(async connection => { + const authorsRelation = connection.getMetadata(Book).manyToManyRelations.find(mtm => mtm.propertyName === "authors"); + expect(authorsRelation).not.to.be.undefined; + expect(authorsRelation!.onDelete).to.be.equal("NO ACTION"); + expect(authorsRelation!.onUpdate).to.be.equal("CASCADE"); + }))); + it("should generate onDelete: NO ACTION and onUpdate: CASCADE for foreign key pointing to Book", () => Promise.all(connections.map(async connection => { + const booksRelation = connection.getMetadata(Author).manyToManyRelations.find(mtm => mtm.propertyName === "books")!; + const booksFk = booksRelation.foreignKeys.find(fk => fk.referencedTablePath === "book"); + expect(booksFk).not.to.be.undefined; + expect(booksFk!.onDelete).to.be.equal("NO ACTION"); + expect(booksFk!.onUpdate).to.be.equal("CASCADE"); + }))); + it("should generate onDelete: CASCADE and onUpdate: CASCADE for foreign key pinting to Author", () => Promise.all(connections.map(async connection => { + // take books relation bc foreign keys are on owning side + const booksRelation = connection.getMetadata(Author).manyToManyRelations.find(mtm => mtm.propertyName === "books")!; + const authorsFk = booksRelation.foreignKeys.find(fk => fk.referencedTablePath === "author"); + expect(authorsFk).not.to.be.undefined; + expect(authorsFk!.onDelete).to.be.equal("CASCADE"); + expect(authorsFk!.onUpdate).to.be.equal("CASCADE"); + }))); +});