Skip to content

Commit

Permalink
fix(core): support composite PKs in em.upsertMany()
Browse files Browse the repository at this point in the history
Closes #4923
  • Loading branch information
B4nan committed Nov 17, 2023
1 parent c491af9 commit 85c38d4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/EntityManager.ts
Expand Up @@ -893,7 +893,7 @@ export class EntityManager<D extends IDatabaseDriver = IDatabaseDriver> {
});

// skip if we got the PKs via returning statement (`rows`)
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(allWhere![0]) ? Object.keys(allWhere![0]) : meta!.primaryKeys) as (keyof Entity)[];
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(allWhere![0]) ? Object.keys(allWhere![0]).flatMap(key => Utils.splitPrimaryKeys(key)) : meta!.primaryKeys) as (keyof Entity)[];
const returning = getOnConflictReturningFields(meta, data[0], uniqueFields, options) as string[];
const reloadFields = returning.length > 0 && !this.getPlatform().usesReturningStatement();

Expand Down
2 changes: 1 addition & 1 deletion packages/knex/src/AbstractSqlDriver.ts
Expand Up @@ -479,7 +479,7 @@ export abstract class AbstractSqlDriver<Connection extends AbstractSqlConnection
const meta = this.metadata.get<T>(entityName);

if (options.upsert) {
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(where[0]) ? Object.keys(where[0]) : meta!.primaryKeys) as (keyof T)[];
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(where[0]) ? Object.keys(where[0]).flatMap(key => Utils.splitPrimaryKeys(key)) : meta!.primaryKeys) as (keyof T)[];
const qb = this.createQueryBuilder<T>(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
const returning = getOnConflictReturningFields(meta, data[0], uniqueFields, options);
qb.insert(data as T[])
Expand Down
57 changes: 57 additions & 0 deletions tests/features/upsert/GH4923.test.ts
@@ -0,0 +1,57 @@
import { Entity, IDatabaseDriver, MikroORM, PrimaryKey, Property, Utils } from '@mikro-orm/core';
import { PLATFORMS } from '../../bootstrap';

@Entity()
class User {

@PrimaryKey()
foo!: number;

@PrimaryKey()
bar!: number;

@Property({ defaultRaw: `CURRENT_TIMESTAMP` })
createdAt?: Date;

}

const options = {
'sqlite': { dbName: ':memory:' },
'better-sqlite': { dbName: ':memory:' },
'mysql': { dbName: 'mikro_orm_upsert', port: 3308 },
'mariadb': { dbName: 'mikro_orm_upsert', port: 3309 },
'postgresql': { dbName: 'mikro_orm_upsert' },
};

describe.each(Utils.keys(options))('GH #4923 [%s]', type => {
let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init<IDatabaseDriver>({
entities: [User],
driver: PLATFORMS[type],
...options[type],
});
await orm.schema.refreshDatabase();
});

beforeEach(async () => {
await orm.schema.clearDatabase();
await orm.em.insert(User, { foo: 1, bar: 2 });
});

afterAll(() => orm.close());

test('GH #4923 em.upsert()', async () => {
const result = await orm.em.upsert(User, { foo: 1, bar: 2 });
expect(result).toBeInstanceOf(User);
});

test('GH #4923 em.upsertMany()', async () => {
const result = await orm.em.upsertMany(User, [
{ foo: 1, bar: 2 },
]);
expect(result).toHaveLength(1);
});

});

0 comments on commit 85c38d4

Please sign in to comment.