Skip to content

Commit

Permalink
fix(core): skip STI discriminator condition when bulk-deleting entities
Browse files Browse the repository at this point in the history
Closes #5303
  • Loading branch information
B4nan committed Mar 5, 2024
1 parent 38f92a4 commit fa712ca
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/core/src/unit-of-work/ChangeSetPersister.ts
Expand Up @@ -71,7 +71,7 @@ export class ChangeSetPersister {
const chunk = changeSets.slice(i, i + size);
const pks = chunk.map(cs => cs.getPrimaryKey());
options = this.propagateSchemaFromMetadata(meta, options);
await this.driver.nativeDelete(meta.className, { [pk]: { $in: pks } } as FilterQuery<T>, options);
await this.driver.nativeDelete(meta.root.className, { [pk]: { $in: pks } } as FilterQuery<T>, options);
}
}

Expand Down
115 changes: 115 additions & 0 deletions tests/features/single-table-inheritance/GH5303.test.ts
@@ -0,0 +1,115 @@
import { Cascade, Collection, Entity, ManyToOne, MikroORM, OneToMany, PrimaryKey, Property } from '@mikro-orm/sqlite';

@Entity()
class User {

@PrimaryKey()
id!: number;

@OneToMany({
entity: () => CoverPicture,
mappedBy: 'cover_user',
orphanRemoval: true,
eager: true,
cascade: [Cascade.ALL],
})
cover_pictures: Collection<CoverPicture> = new Collection<CoverPicture>(this);

@OneToMany({
entity: () => ProfilePicture,
mappedBy: 'profile_user',
orphanRemoval: true,
eager: true,
cascade: [Cascade.ALL],
})
profile_pictures: Collection<ProfilePicture> = new Collection<ProfilePicture>(this);

}

@Entity({ abstract: true, discriminatorColumn: 'type' })
abstract class BasePicture {

@PrimaryKey()
id!: number;

@Property({ type: 'string', nullable: false })
path: string;

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

}

@Entity({ discriminatorValue: 'cover' })
class CoverPicture extends BasePicture {

@ManyToOne({ entity: () => User })
cover_user: User;

constructor(path: string, user: User) {
super(path);
this.cover_user = user;
}

}

@Entity({ discriminatorValue: 'profile' })
class ProfilePicture extends BasePicture {

@ManyToOne({ entity: () => User })
profile_user: User;

constructor(path: string, user: User) {
super(path);
this.profile_user = user;
}

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
dbName: ':memory:',
entities: [User, BasePicture, CoverPicture, ProfilePicture],
});
await orm.schema.refreshDatabase();
});

afterAll(async () => {
await orm.close(true);
});

test('user should be able to create/update pictures', async () => {
let user = new User();
orm.em.create(User, user);
await orm.em.persist(user).flush();
orm.em.clear();

user = await orm.em.findOneOrFail(User, { id: user.id });
user.cover_pictures.add(new CoverPicture('/path/1', user));
user.profile_pictures.add(new ProfilePicture('/path/2', user));
await orm.em.persist(user).flush();
orm.em.clear();

user = await orm.em.findOneOrFail(User, { id: user.id });
expect(user.cover_pictures.length).toBe(1);
expect(user.profile_pictures.length).toBe(1);

// update pictures
user.cover_pictures.removeAll();
user.profile_pictures.removeAll();

user.cover_pictures.add(new CoverPicture('/path/3', user));
user.profile_pictures.add(new ProfilePicture('/path/4', user));

await orm.em.persist(user).flush();
orm.em.clear();

user = await orm.em.findOneOrFail(User, { id: user.id });
expect(user.cover_pictures.length).toBe(1);
expect(user.profile_pictures.length).toBe(1);
expect(user.cover_pictures[0].path).toBe('/path/3');
expect(user.profile_pictures[0].path).toBe('/path/4');
});

0 comments on commit fa712ca

Please sign in to comment.