Skip to content

Entities generated from existing DB have wrong cascade settings #1857

@SDemonUA

Description

@SDemonUA

Describe the bug
Entities generated from existing DB have wrong m:1 cascade settings

Having DB:

create table if not exists author
(
	id serial not null
		constraint author_pk
			primary key,
	name varchar(100) not null
);

create table if not exists book
(
	id serial not null
		constraint book_pk
			primary key,
	name varchar(100) not null,
	author_id integer
		constraint book_author_id_fk
			references author
				on delete set null
				deferrable initially deferred
);

create table if not exists sample_page
(
	id serial not null,
	page_number integer not null,
	book_id integer not null
		constraint sample_page_book_id_fk
			references book
				on delete cascade,
	content text default ''::text not null,
	constraint sample_page_pk
		primary key (page_number, book_id)
);

will produce entities

@Entity()
export class Author {

  @PrimaryKey()
  id!: number;

  @Property({ length: 100 })
  name!: string;

}
// --- //
@Entity()
export class Book {
  @PrimaryKey()
  id!: number;

  @Property({ length: 100 })
  name!: string;

  @ManyToOne({ entity: () => Author, cascade: [], nullable: true })
  author?: Author;
}
// --- //
@Entity()
export class SamplePage {
  @Property()
  id!: number;

  @PrimaryKey()
  pageNumber!: number;

  [PrimaryKeyType]: [number, number];

  @ManyToOne({ entity: () => Book, cascade: [Cascade.REMOVE], primary: true })
  book!: Book;

  @Property({ columnType: 'text', default: '' })
  content!: string;
}

Using SQL generator we will get almost the same schema, but code with Cascade.REMOVE works in backwards and removes books when a connected page is removed.

To Reproduce
Steps to reproduce the behavior:

  1. Select page and remove page
const page = await orm.em.findOne<entities.SamplePage>(entities.SamplePage, {
    pageNumber: 44,
    book: 3,
});
await orm.em.removeAndFlush(page);

as a result we will get SQL like:

[query] select "e0".* from "sample_page" as "e0" where "e0"."page_number" = 44 and "e0"."book_id" = 3 limit 1 [took 7 ms]
[query] begin
[query] delete from "sample_page" where ("page_number", "book_id") in ((44, 3)) [took 1 ms]
[query] delete from "book" where "id" in (3) [took 4 ms]

Expected behavior

I expect entities generated from real db would have correct relations w/o such destructive behaviour

Additional context
Data used for tests

insert into author (id, name)
values (1, 'Dickinson'), (2, 'King'), (3, 'Conan Doyle'), (4, 'Asimov');
insert into book (id, name, author_id)
values (1, 'A Christmas Carol', 1), (2, 'The Thing', 2), (3, 'Sherlock Holmes', 3), (4, 'I am a Robot', 4);
insert into sample_page (page_number, book_id, content)
values (44, 1, 'Some content'), (44, 2, 'Some content 2'), (44, 3, 'Some content 3 '), (44, 4, 'Some content 4');

Versions

Dependency Version
node 14.15.4
typescript 4.1.5
mikro-orm 4.4.3
your-driver postgres

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions