From 4783945b22ab3acb0893df52e4534963269444cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ad=C3=A1mek?= Date: Tue, 14 May 2024 18:46:23 +0200 Subject: [PATCH] fix(core): quote column name for the returning statement when using `convertToJSValueSQL` Closes #5563 --- packages/knex/src/query/QueryBuilderHelper.ts | 3 +- tests/features/custom-types/GH5563.test.ts | 58 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/features/custom-types/GH5563.test.ts diff --git a/packages/knex/src/query/QueryBuilderHelper.ts b/packages/knex/src/query/QueryBuilderHelper.ts index 9f23234a6e8c..25a4ef1f456f 100644 --- a/packages/knex/src/query/QueryBuilderHelper.ts +++ b/packages/knex/src/query/QueryBuilderHelper.ts @@ -699,7 +699,8 @@ export class QueryBuilderHelper { if (returningProps.length > 0) { qb.returning(returningProps.flatMap(prop => { if (prop.hasConvertToJSValueSQL) { - const sql = prop.customType!.convertToJSValueSQL!(prop.fieldNames[0], this.platform) + ' as ' + this.platform.quoteIdentifier(prop.fieldNames[0]); + const aliased = this.platform.quoteIdentifier(prop.fieldNames[0]); + const sql = prop.customType!.convertToJSValueSQL!(aliased, this.platform) + ' as ' + this.platform.quoteIdentifier(prop.fieldNames[0]); return [this.knex.raw(sql) as any]; } return prop.fieldNames; diff --git a/tests/features/custom-types/GH5563.test.ts b/tests/features/custom-types/GH5563.test.ts new file mode 100644 index 000000000000..fbda12d7792f --- /dev/null +++ b/tests/features/custom-types/GH5563.test.ts @@ -0,0 +1,58 @@ +import { Entity, MikroORM, PrimaryKey, Property, Type, BaseEntity } from '@mikro-orm/postgresql'; + +class IntervalType extends Type { + + getColumnType() { + return `interval`; + } + + override get runtimeType(): string { + return 'number'; + } + + compareAsType(): string { + return 'number'; + } + + convertToJSValueSQL(key: string) { + return `(extract (epoch from ${key}::interval) * 1000)::int`; + } + + convertToDatabaseValueSQL(key: string) { + return `(${key} || 'milliseconds')::interval`; + } + +} + +@Entity() +export class A extends BaseEntity { + + @PrimaryKey() + id!: number; + + @Property({ type: IntervalType }) + end!: number; + +} + + +let orm: MikroORM; + +beforeAll(async () => { + orm = await MikroORM.init({ + entities: [A], + dbName: '5563', + }); + await orm.schema.refreshDatabase(); +}); + +afterAll(() => orm.close(true)); + +test('update customType', async () => { + const bk = orm.em.create(A, { end: 10 }); + await orm.em.flush(); + orm.em.clear(); + const entityA = await orm.em.findOneOrFail(A, { id: bk.id }); + entityA.assign({ end: 500 }); + await orm.em.flush(); +});