From b789031300e752cfd9565371e7989776b18bd3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ad=C3=A1mek?= Date: Tue, 18 Apr 2023 16:14:56 +0200 Subject: [PATCH] fix(query-builder): fix pagination when PK uses `BigIntType` Closes #4227 --- packages/core/src/utils/QueryHelper.ts | 4 ++ packages/knex/src/query/QueryBuilder.ts | 2 + tests/issues/GH4227.test.ts | 52 +++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/issues/GH4227.test.ts diff --git a/packages/core/src/utils/QueryHelper.ts b/packages/core/src/utils/QueryHelper.ts index 3888173b330b..7ed34d6ee4a6 100644 --- a/packages/core/src/utils/QueryHelper.ts +++ b/packages/core/src/utils/QueryHelper.ts @@ -237,6 +237,10 @@ export class QueryHelper { return (cond as ObjectQuery[]).map(v => QueryHelper.processCustomType(prop, v, platform, key, fromQuery)) as unknown as ObjectQuery; } + if (platform.isRaw(cond)) { + return cond; + } + return prop.customType.convertToDatabaseValue(cond, platform, { fromQuery, key, mode: 'query' }); } diff --git a/packages/knex/src/query/QueryBuilder.ts b/packages/knex/src/query/QueryBuilder.ts index bf7e15683e45..ff753d51b522 100644 --- a/packages/knex/src/query/QueryBuilder.ts +++ b/packages/knex/src/query/QueryBuilder.ts @@ -495,6 +495,7 @@ export class QueryBuilder { getKnexQuery(): Knex.QueryBuilder { this.finalize(); const qb = this.getQueryBase(); + (qb as Dictionary).__raw = true; // tag it as there is now way to check via `instanceof` Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type ?? QueryType.SELECT, this._cond, qb), this._cond && !this._onConflict); Utils.runIfNotEmpty(() => qb.groupBy(this.prepareFields(this._groupBy, 'groupBy')), this._groupBy); @@ -1117,6 +1118,7 @@ export class QueryBuilder { // multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O) // https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu const subSubQuery = this.getKnex().select(pks).from(knexQuery); + (subSubQuery as Dictionary).__raw = true; // tag it as there is now way to check via `instanceof` this._limit = undefined; this._offset = undefined; const cond = this._cond; diff --git a/tests/issues/GH4227.test.ts b/tests/issues/GH4227.test.ts new file mode 100644 index 000000000000..612e8ed4455f --- /dev/null +++ b/tests/issues/GH4227.test.ts @@ -0,0 +1,52 @@ +import { Entity, LoadStrategy, OneToMany, ManyToOne, Collection, PrimaryKey, BigIntType } from '@mikro-orm/core'; +import { MikroORM } from '@mikro-orm/postgresql'; + +@Entity() +class BidEntity { + + @PrimaryKey({ type: BigIntType }) + id!: string; + + @ManyToOne('ItemEntity', { + serializer: value => value.id, + serializedName: 'itemId', + }) + item: any; + +} + +@Entity() +class ItemEntity { + + @PrimaryKey({ type: BigIntType }) + id!: string; + + @OneToMany('BidEntity', 'item', { + orphanRemoval: true, + strategy: LoadStrategy.JOINED, + mappedBy: 'item', + }) + bids = new Collection(this); + +} + +let orm: MikroORM; + +beforeAll(async () => { + orm = await MikroORM.init({ + dbName: ':memory:', + entities: [BidEntity, ItemEntity], + }); + await orm.schema.refreshDatabase(); +}); + +afterAll(() => orm.close(true)); + +test('select big int', async () => { + await orm.em + .createQueryBuilder(ItemEntity, 'item') + .select('*') + .leftJoinAndSelect('item.bids', 'bids') + .limit(10) + .getResultAndCount(); +});