diff --git a/packages/knex/src/query/QueryBuilderHelper.ts b/packages/knex/src/query/QueryBuilderHelper.ts index e0ffc81cdad0..199ae49dbd56 100644 --- a/packages/knex/src/query/QueryBuilderHelper.ts +++ b/packages/knex/src/query/QueryBuilderHelper.ts @@ -516,7 +516,12 @@ export class QueryBuilderHelper { if (!this.isPrefixed(field)) { const alias = always ? (quote ? this.alias : this.platform.quoteIdentifier(this.alias)) + '.' : ''; - ret = alias + this.fieldName(field, this.alias); + const fieldName = this.fieldName(field, this.alias); + if (fieldName.startsWith('(')) { + ret = '(' + alias + fieldName.slice(1); + } else { + ret = alias + fieldName; + } } else { const [a, f] = field.split('.'); ret = a + '.' + this.fieldName(f, a); diff --git a/tests/features/embeddables/__snapshots__/embedded-entities.postgres.test.ts.snap b/tests/features/embeddables/__snapshots__/embedded-entities.postgres.test.ts.snap index 4c35f56ab59a..59bbd29bb839 100644 --- a/tests/features/embeddables/__snapshots__/embedded-entities.postgres.test.ts.snap +++ b/tests/features/embeddables/__snapshots__/embedded-entities.postgres.test.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`embedded entities in postgresql schema: embeddables 1 1`] = ` -"create table \\"user\\" (\\"id\\" serial primary key, \\"address1_street\\" varchar(255) not null, \\"address1_postal_code\\" varchar(255) not null, \\"address1_city\\" varchar(255) not null, \\"address1_country\\" varchar(255) not null, \\"addr_street\\" varchar(255) null, \\"addr_postal_code\\" varchar(255) null, \\"addr_city\\" varchar(255) null, \\"addr_country\\" varchar(255) null, \\"street\\" varchar(255) not null, \\"postal_code\\" varchar(255) not null, \\"city\\" varchar(255) not null, \\"country\\" varchar(255) not null, \\"address4\\" jsonb not null, \\"addresses\\" jsonb not null, \\"after\\" int4 null); +"create table \\"user\\" (\\"id\\" serial primary key, \\"address1_street\\" varchar(255) not null, \\"address1_number\\" int4 not null, \\"address1_postal_code\\" varchar(255) not null, \\"address1_city\\" varchar(255) not null, \\"address1_country\\" varchar(255) not null, \\"addr_street\\" varchar(255) null, \\"addr_postal_code\\" varchar(255) null, \\"addr_city\\" varchar(255) null, \\"addr_country\\" varchar(255) null, \\"street\\" varchar(255) not null, \\"number\\" int4 not null, \\"postal_code\\" varchar(255) not null, \\"city\\" varchar(255) not null, \\"country\\" varchar(255) not null, \\"address4\\" jsonb not null, \\"addresses\\" jsonb not null, \\"after\\" int4 null); " `; diff --git a/tests/features/embeddables/embedded-entities.postgres.test.ts b/tests/features/embeddables/embedded-entities.postgres.test.ts index 3f1375bc37f4..b957db674fbb 100644 --- a/tests/features/embeddables/embedded-entities.postgres.test.ts +++ b/tests/features/embeddables/embedded-entities.postgres.test.ts @@ -7,6 +7,9 @@ class Address1 { @Property() street?: string; + @Property() + number?: number; + @Property() postalCode?: string; @@ -16,8 +19,9 @@ class Address1 { @Property() country?: string; - constructor(street?: string, postalCode?: string, city?: string, country?: string) { + constructor(street?: string, number?: number, postalCode?: string, city?: string, country?: string) { this.street = street; + this.number = number; this.postalCode = postalCode; this.city = city; this.country = country; @@ -141,12 +145,12 @@ describe('embedded entities in postgresql', () => { test('persist and load', async () => { const user = new User(); - user.address1 = new Address1('Downing street 10', '123', 'London 1', 'UK 1'); + user.address1 = new Address1('Downing street 10', 10, '123', 'London 1', 'UK 1'); user.address2 = new Address2('Downing street 11', 'London 2', 'UK 2'); - user.address3 = new Address1('Downing street 12', '789', 'London 3', 'UK 3'); - user.address4 = new Address1('Downing street 13', '10', 'London 4', 'UK 4'); - user.addresses.push(new Address1('Downing street 13A', '10A', 'London 4A', 'UK 4A')); - user.addresses.push(new Address1('Downing street 13B', '10B', 'London 4B', 'UK 4B')); + user.address3 = new Address1('Downing street 12', 10, '789', 'London 3', 'UK 3'); + user.address4 = new Address1('Downing street 13', 10, '10', 'London 4', 'UK 4'); + user.addresses.push(new Address1('Downing street 13A', 10, '10A', 'London 4A', 'UK 4A')); + user.addresses.push(new Address1('Downing street 13B', 10, '10B', 'London 4B', 'UK 4B')); const mock = jest.fn(); const logger = new Logger(mock, ['query']); @@ -154,7 +158,7 @@ describe('embedded entities in postgresql', () => { await orm.em.persistAndFlush(user); orm.em.clear(); expect(mock.mock.calls[0][0]).toMatch('begin'); - expect(mock.mock.calls[1][0]).toMatch('insert into "user" ("addr_city", "addr_country", "addr_postal_code", "addr_street", "address1_city", "address1_country", "address1_postal_code", "address1_street", "address4", "addresses", "city", "country", "postal_code", "street") values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) returning "id"'); + expect(mock.mock.calls[1][0]).toMatch('insert into "user" ("addr_city", "addr_country", "addr_postal_code", "addr_street", "address1_city", "address1_country", "address1_number", "address1_postal_code", "address1_street", "address4", "addresses", "city", "country", "number", "postal_code", "street") values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) returning "id"'); expect(mock.mock.calls[2][0]).toMatch('commit'); const u = await orm.em.findOneOrFail(User, user.id); @@ -162,6 +166,7 @@ describe('embedded entities in postgresql', () => { expect(u.address1).toBeInstanceOf(Address1); expect(u.address1).toEqual({ street: 'Downing street 10', + number: 10, postalCode: '123', city: 'London 1', country: 'UK 1', @@ -176,6 +181,7 @@ describe('embedded entities in postgresql', () => { expect(u.address3).toBeInstanceOf(Address1); expect(u.address3).toEqual({ street: 'Downing street 12', + number: 10, postalCode: '789', city: 'London 3', country: 'UK 3', @@ -183,6 +189,7 @@ describe('embedded entities in postgresql', () => { expect(u.address4).toBeInstanceOf(Address1); expect(u.address4).toEqual({ street: 'Downing street 13', + number: 10, postalCode: '10', city: 'London 4', country: 'UK 4', @@ -215,6 +222,10 @@ describe('embedded entities in postgresql', () => { const u4 = await orm.em.findOneOrFail(User, { address4: { postalCode: '999' } }); expect(u4).toBe(u1); expect(mock.mock.calls[10][0]).toMatch('select "e0".* from "user" as "e0" where "e0"."address4"->>\'postalCode\' = $1 limit $2'); + + const u5 = await orm.em.findOneOrFail(User, { address4: { number: { $gt: 2 } } }); + expect(u5).toBe(u1); + expect(mock.mock.calls[11][0]).toMatch('select "e0".* from "user" as "e0" where ("e0"."address4"->>\'number\')::float8 > $1 limit $2'); }); test('assign', async () => { @@ -251,9 +262,9 @@ describe('embedded entities in postgresql', () => { test('query by complex custom expressions with JSON operator and casting (GH issue 1261)', async () => { const user = new User(); - user.address1 = new Address1('Test', '12000', 'Prague', 'CZ'); - user.address3 = new Address1('Test', '12000', 'Prague', 'CZ'); - user.address4 = new Address1('Test', '12000', 'Prague', 'CZ'); + user.address1 = new Address1('Test', 10, '12000', 'Prague', 'CZ'); + user.address3 = new Address1('Test', 10, '12000', 'Prague', 'CZ'); + user.address4 = new Address1('Test', 10, '12000', 'Prague', 'CZ'); await orm.em.persistAndFlush(user); orm.em.clear();