Skip to content

Commit

Permalink
fix(core): fix snapshot of relation properties loaded via joined stra…
Browse files Browse the repository at this point in the history
…tegy

Closes #4129
  • Loading branch information
B4nan committed Mar 17, 2023
1 parent 2bbcb47 commit 6015f3f
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/core/src/unit-of-work/UnitOfWork.ts
Expand Up @@ -101,7 +101,7 @@ export class UnitOfWork {

wrapped.__meta.relations.forEach(prop => {
if (Utils.isPlainObject(data[prop.name as string])) {
data[prop.name as string] = Utils.getPrimaryKeyValues(data[prop.name as string], wrapped.__meta.primaryKeys, true);
data[prop.name as string] = Utils.getPrimaryKeyValues(data[prop.name as string], prop.targetMeta!.primaryKeys, true);
}
});
wrapped.__originalEntityData = data;
Expand Down
109 changes: 109 additions & 0 deletions tests/features/unit-of-work/GH4129.test.ts
@@ -0,0 +1,109 @@
import { Collection, Entity, LoadStrategy, ManyToOne, OneToMany, PrimaryKey, Property, SimpleLogger } from '@mikro-orm/core';
import { MikroORM } from '@mikro-orm/sqlite';
import { mockLogger } from '../../helpers';

@Entity()
class Channel {

@PrimaryKey()
id!: number;

@Property()
name!: string;

@OneToMany(() => DeviceChannel, item => item.channel, { orphanRemoval: true })
links = new Collection<DeviceChannel>(this);

}

@Entity()
class Device {

@PrimaryKey()
id!: number;

@Property()
serial!: string;

@OneToMany(() => DeviceChannel, item => item.device, { orphanRemoval: true })
links = new Collection<DeviceChannel>(this);

}

@Entity()
class DeviceChannel {

@ManyToOne({ entity: () => Device, primary: true })
device!: Device;

@ManyToOne({ entity: () => Channel, primary: true })
channel!: Channel;

@Property()
lastTime!: Date;

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [Device, Channel, DeviceChannel],
dbName: ':memory:',
loggerFactory: options => new SimpleLogger(options),
loadStrategy: LoadStrategy.JOINED,
});
await orm.schema.refreshDatabase();
});

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

beforeEach(async () => {
await orm.schema.clearDatabase();

const chn = orm.em.create(Channel, { id: 1, name: 'ChannelOne', links: [] });
const dev1 = orm.em.create(Device, { id: 2, serial: 'DeviceOne', links: [] });
const link1 = orm.em.create(DeviceChannel, { device: dev1, channel: chn, lastTime: new Date() });
chn.links.add(link1);

await orm.em.flush();
orm.em.clear();
});

test('GH 4129 (1/3)', async () => {
const channel = await orm.em.findOneOrFail(Channel, { name: 'ChannelOne' }, { populate: ['links'] });

for (const link of channel.links) {
link.lastTime = new Date(1678803173316);
}

const mock = mockLogger(orm);
await orm.em.flush();
expect(mock.mock.calls[1][0]).toBe('[query] update `device_channel` set `last_time` = 1678803173316 where (`device_id`, `channel_id`) in ((2, 1))');
});

test('GH 4129 (2/3)', async () => {
const channel = await orm.em.findOneOrFail(Channel, { name: 'ChannelOne' }, { populate: ['links.device', 'links.channel'] });

for (const link of channel.links) {
link.lastTime = new Date(1678803173316);
}

const mock = mockLogger(orm);
await orm.em.flush();
expect(mock.mock.calls[1][0]).toBe('[query] update `device_channel` set `last_time` = 1678803173316 where (`device_id`, `channel_id`) in ((2, 1))');
});

test('GH 4129 (3/3)', async () => {
const channel = await orm.em.findOneOrFail(Channel, { name: 'ChannelOne' }, { populate: ['links.device'] });

for (const link of channel.links) {
link.lastTime = new Date(1678803173316);
}

const mock = mockLogger(orm);
await orm.em.flush();
expect(mock.mock.calls[1][0]).toBe('[query] update `device_channel` set `last_time` = 1678803173316 where (`device_id`, `channel_id`) in ((2, 1))');
});

0 comments on commit 6015f3f

Please sign in to comment.