From e5049b192d13ea41747e1340715e288084a0015d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ad=C3=A1mek?= Date: Thu, 22 Oct 2020 21:44:58 +0200 Subject: [PATCH] fix(core): fix mapping of params with custom types Closes #940 --- .../core/src/metadata/MetadataDiscovery.ts | 3 + packages/core/src/typings.ts | 1 + packages/core/src/utils/QueryHelper.ts | 7 +- packages/knex/src/schema/SchemaGenerator.ts | 2 +- tests/issues/GH940.test.ts | 70 +++++++++++++++++++ 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/issues/GH940.test.ts diff --git a/packages/core/src/metadata/MetadataDiscovery.ts b/packages/core/src/metadata/MetadataDiscovery.ts index 579fdd0398e1..ac7eac005440 100644 --- a/packages/core/src/metadata/MetadataDiscovery.ts +++ b/packages/core/src/metadata/MetadataDiscovery.ts @@ -289,6 +289,7 @@ export class MetadataDiscovery { private initManyToManyFields(meta: EntityMetadata, prop: EntityProperty): void { const meta2 = this.metadata.get(prop.type); + prop.referencedPKs = meta2.primaryKeys; Utils.defaultValue(prop, 'fixedOrder', !!prop.fixedOrderColumn); if (!prop.pivotTable && prop.owner && this.platform.usesPivotTable()) { @@ -321,6 +322,7 @@ export class MetadataDiscovery { private initManyToOneFields(prop: EntityProperty): void { const meta2 = this.metadata.get(prop.type); + prop.referencedPKs = meta2.primaryKeys; const fieldNames = Utils.flatten(meta2.primaryKeys.map(primaryKey => meta2.properties[primaryKey].fieldNames)); Utils.defaultValue(prop, 'referencedTableName', meta2.collection); @@ -335,6 +337,7 @@ export class MetadataDiscovery { private initOneToManyFields(prop: EntityProperty): void { const meta2 = this.metadata.get(prop.type); + prop.referencedPKs = meta2.primaryKeys; if (!prop.joinColumns) { prop.joinColumns = [this.namingStrategy.joinColumnName(prop.name)]; diff --git a/packages/core/src/typings.ts b/packages/core/src/typings.ts index 56d09f427245..3334fd7eb498 100644 --- a/packages/core/src/typings.ts +++ b/packages/core/src/typings.ts @@ -169,6 +169,7 @@ export interface EntityProperty = any> { inverseJoinColumns: string[]; referencedColumnNames: string[]; referencedTableName: string; + referencedPKs: string[]; serializer?: (value: any) => any; serializedName?: string; comment?: string; diff --git a/packages/core/src/utils/QueryHelper.ts b/packages/core/src/utils/QueryHelper.ts index 3695b6a6e582..02637b0b9caa 100644 --- a/packages/core/src/utils/QueryHelper.ts +++ b/packages/core/src/utils/QueryHelper.ts @@ -177,7 +177,12 @@ export class QueryHelper { static processCustomType(prop: EntityProperty, cond: FilterQuery, platform: Platform, key?: string, fromQuery?: boolean): FilterQuery { if (Utils.isPlainObject(cond)) { return Object.keys(cond).reduce((o, k) => { - o[k] = QueryHelper.processCustomType(prop, cond[k], platform, k, fromQuery); + if (Utils.isOperator(k, true) || prop.referencedPKs.includes(k)) { + o[k] = QueryHelper.processCustomType(prop, cond[k], platform, k, fromQuery); + } else { + o[k] = cond[k]; + } + return o; }, {}); } diff --git a/packages/knex/src/schema/SchemaGenerator.ts b/packages/knex/src/schema/SchemaGenerator.ts index 753a103c8413..15f20b5d0b91 100644 --- a/packages/knex/src/schema/SchemaGenerator.ts +++ b/packages/knex/src/schema/SchemaGenerator.ts @@ -463,7 +463,7 @@ export class SchemaGenerator { .forEach(prop => this.createForeignKey(table, meta, prop, undefined, createdColumns)); } - private createForeignKey(table: TableBuilder, meta: EntityMetadata, prop: EntityProperty, diff?: IsSame, createdColumns: string[] = []): void { + private createForeignKey(table: TableBuilder, meta: EntityMetadata, prop: EntityProperty, diff?: IsSame, createdColumns: string[]): void { if (this.helper.supportsSchemaConstraints()) { this.createForeignKeyReference(table, prop); diff --git a/tests/issues/GH940.test.ts b/tests/issues/GH940.test.ts new file mode 100644 index 000000000000..703551bda9a0 --- /dev/null +++ b/tests/issues/GH940.test.ts @@ -0,0 +1,70 @@ +import { BigIntType, Collection, Entity, ManyToOne, MikroORM, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; +import { SchemaGenerator, SqliteDriver } from '@mikro-orm/sqlite'; + +@Entity() +class User { + + @PrimaryKey({ type: BigIntType }) + id!: string; + + @OneToMany('UserOrganization', 'user') + organizations = new Collection(this); + +} + +@Entity() +class UserOrganization { + + @PrimaryKey({ type: BigIntType }) + id!: string; + + @ManyToOne(() => User) + user: User; + + @Property() + isAdmin: boolean; + + constructor(user: User, isAdmin: boolean) { + this.user = user; + this.isAdmin = isAdmin; + } + +} + +describe('GH issue 940', () => { + + let orm: MikroORM; + + beforeAll(async () => { + orm = await MikroORM.init({ + entities: [User, UserOrganization], + dbName: `:memory:`, + type: 'sqlite', + port: 3307, + }); + await new SchemaGenerator(orm.em).createSchema(); + }); + + afterAll(async () => await orm.close(true)); + + test('A boolean in the nested where conditions is kept even if the primary key is BigIntType', async () => { + + const user1 = new User(); + const user2 = new User(); + const user1org = new UserOrganization(user1, true); + const user2org = new UserOrganization(user2, false); + + await orm.em.persistAndFlush([user1org, user2org]); + + const users = await orm.em.find(User, { organizations: { isAdmin: true } }); + expect(users).toMatchObject([ + { + id: user1.id, + organizations: { + 0: { id: user1org.id, isAdmin: true }, + }, + }, + ]); + }); + +});