Skip to content

Commit

Permalink
fix(core): fix snapshotting of composite properties
Browse files Browse the repository at this point in the history
Closes #1079
  • Loading branch information
B4nan committed Dec 2, 2020
1 parent ea99abe commit b5f19f2
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 7 deletions.
14 changes: 8 additions & 6 deletions packages/core/src/metadata/MetadataDiscovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -736,18 +736,20 @@ export class MetadataDiscovery {

const meta = this.metadata.get(prop.type);
prop.columnTypes = [];
meta.primaryKeys.forEach(primaryKey => {
const pk = meta.properties[primaryKey];
meta.getPrimaryProps().forEach(pk => {
this.initCustomType(pk);
this.initColumnType(pk);

if (pk.customType) {
prop.columnTypes.push(pk.customType.getColumnType(pk, this.platform));
prop.customType = pk.customType;
if (!pk.customType) {
prop.columnTypes.push(...pk.columnTypes);
return;
}

prop.columnTypes.push(...pk.columnTypes);
prop.columnTypes.push(pk.customType.getColumnType(pk, this.platform));

if (!meta.compositePK) {
prop.customType = pk.customType;
}
});
}

Expand Down
2 changes: 1 addition & 1 deletion packages/knex/src/AbstractSqlDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra

// wrong order if we just delete and insert to the end (only owning sides can have fixed order)
if (coll.property.owner && coll.property.fixedOrder && !equals && Array.isArray(deleteDiff)) {
deleteDiff.length = insertDiff.length = 0;
(deleteDiff as unknown[]).length = insertDiff.length = 0;
deleteDiff.push(...snapshot);
insertDiff.push(...current);
}
Expand Down
133 changes: 133 additions & 0 deletions tests/issues/GH1079.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Entity, PrimaryKey, MikroORM, ManyToOne, Enum, PrimaryKeyType, Property, BigIntType, Logger } from '@mikro-orm/core';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
import { v4 } from 'uuid';

@Entity()
class User {

@PrimaryKey({ type: BigIntType })
_id!: string;

}

@Entity()
class Wallet {

[PrimaryKeyType]: [string, string];

@PrimaryKey()
currencyRef!: string;

@ManyToOne({ primary: true, entity: () => User })
owner!: User;

@Property({ type: String, nullable: false, default: '0' })
mainBalance!: string;

}

class AbstractDeposit {

@Property({ type: String, nullable: false })
amount!: string;

@Property({ type: String, nullable: false })
gatewayKey!: string;

@Property()
createdAt: Date = new Date();

@Property({ onUpdate: () => new Date() })
updatedAt: Date = new Date();

}

enum DepositStatus {
UNPAID = 'UNPAID',
PENDING = 'PENDING',
COMPLETED = 'COMPLETED',
FAILED = 'FAILED'
}


@Entity()
export class Deposit extends AbstractDeposit {

[PrimaryKeyType]: [string, string, string];

@PrimaryKey()
txRef!: string;

@ManyToOne({ primary: true, entity: () => Wallet })
wallet!: Wallet;

@Enum({
nullable: false,
items: () => DepositStatus,
})
status: DepositStatus = DepositStatus.UNPAID;

}

describe('GH issue 1079', () => {

let orm: MikroORM<PostgreSqlDriver>;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [User, Wallet, Deposit, AbstractDeposit],
dbName: `mikro_orm_test_gh_1079`,
type: 'postgresql',
});
await orm.getSchemaGenerator().ensureDatabase();
await orm.getSchemaGenerator().dropSchema();
await orm.getSchemaGenerator().createSchema();
});

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

test(`GH issue 1079`, async () => {
const user = new User();
const wallet = new Wallet();
const deposit = new Deposit();
user._id = '1';
wallet.currencyRef = 'USD';
wallet.owner = user;
wallet.mainBalance = '456';
deposit.wallet = wallet;
deposit.amount = '123';
deposit.txRef = '456';
deposit.gatewayKey = '789';

const mock = jest.fn();
const logger = new Logger(mock, ['query']);
Object.assign(orm.config, { logger });

await orm.em.fork().persistAndFlush(deposit);

const w = await orm.em.findOneOrFail(Wallet, {
currencyRef: 'USD',
owner: { _id: '1' },
});

const deposit2 = orm.em.create(Deposit, {
wallet: w,
gatewayKey: 'STRIPE',
amount: '98765',
txRef: v4(),
});
await orm.em.persistAndFlush(deposit2);

const queries: string[] = mock.mock.calls.map(c => c[0]);
expect(queries[0]).toMatch(`begin`);
expect(queries[1]).toMatch(`insert into "user" ("_id") values ($1) returning "_id"`);
expect(queries[2]).toMatch(`insert into "wallet" ("currency_ref", "main_balance", "owner__id") values ($1, $2, $3)`);
expect(queries[3]).toMatch(`insert into "deposit" ("amount", "created_at", "gateway_key", "status", "tx_ref", "updated_at", "wallet_currency_ref", "wallet_owner__id") values ($1, $2, $3, $4, $5, $6, $7, $8)`);
expect(queries[4]).toMatch(`commit`);
expect(queries[5]).toMatch(`select "e0".* from "wallet" as "e0" left join "user" as "e1" on "e0"."owner__id" = "e1"."_id" where "e0"."currency_ref" = $1 and "e1"."_id" = $2 limit $3`);
expect(queries[6]).toMatch(`begin`);
expect(queries[7]).toMatch(`insert into "deposit" ("amount", "created_at", "gateway_key", "status", "tx_ref", "updated_at", "wallet_currency_ref", "wallet_owner__id") values ($1, $2, $3, $4, $5, $6, $7, $8)`);
expect(queries[8]).toMatch(`commit`);
});

});

0 comments on commit b5f19f2

Please sign in to comment.