diff --git a/packages/knex/src/query/QueryBuilder.ts b/packages/knex/src/query/QueryBuilder.ts index 9cf11d250c87..0258a5387260 100644 --- a/packages/knex/src/query/QueryBuilder.ts +++ b/packages/knex/src/query/QueryBuilder.ts @@ -482,7 +482,7 @@ export class QueryBuilder = AnyEntity> { } getKnex(): KnexQueryBuilder { - const tableName = this.helper.getTableName(this.entityName) + (this.finalized && [QueryType.SELECT, QueryType.COUNT].includes(this.type) ? ` as ${this.alias}` : ''); + const tableName = this.helper.getTableName(this.entityName) + (this.finalized && this.helper.isTableNameAliasRequired(this.type) ? ` as ${this.alias}` : ''); const qb = this.knex(tableName); if (this.context) { @@ -575,7 +575,7 @@ export class QueryBuilder = AnyEntity> { this.type = type; this._aliasMap[this.alias] = this.entityName; - if (![QueryType.SELECT, QueryType.COUNT].includes(type)) { + if (!this.helper.isTableNameAliasRequired(type)) { delete this._fields; } diff --git a/packages/knex/src/query/QueryBuilderHelper.ts b/packages/knex/src/query/QueryBuilderHelper.ts index 199ae49dbd56..080466e63ac9 100644 --- a/packages/knex/src/query/QueryBuilderHelper.ts +++ b/packages/knex/src/query/QueryBuilderHelper.ts @@ -30,6 +30,7 @@ export class QueryBuilderHelper { mapper(field: string, type?: QueryType): string; mapper(field: string, type?: QueryType, value?: any, alias?: string | null): string; mapper(field: string, type = QueryType.SELECT, value?: any, alias?: string | null): string | Raw { + const isTableNameAliasRequired = this.isTableNameAliasRequired(type); const fields = Utils.splitPrimaryKeys(field); if (fields.length > 1) { @@ -43,11 +44,11 @@ export class QueryBuilderHelper { const noPrefix = prop && prop.persist === false; if (prop?.fieldNameRaw) { - return this.knex.raw(this.prefix(field, true)); + return this.knex.raw(this.prefix(field, isTableNameAliasRequired)); } if (prop?.customType?.convertToJSValueSQL) { - const prefixed = this.prefix(field, true, true); + const prefixed = this.prefix(field, isTableNameAliasRequired, true); const valueSQL = prop.customType.convertToJSValueSQL!(prefixed, this.platform); if (alias === null) { @@ -71,7 +72,7 @@ export class QueryBuilderHelper { return this.knex.raw(ret, value); } - if (![QueryType.SELECT, QueryType.COUNT].includes(type) || this.isPrefixed(ret) || noPrefix) { + if (!isTableNameAliasRequired || this.isPrefixed(ret) || noPrefix) { return ret; } @@ -580,4 +581,8 @@ export class QueryBuilderHelper { return meta ? meta.properties[field] : undefined; } + isTableNameAliasRequired(type: QueryType): boolean { + return [QueryType.SELECT, QueryType.COUNT].includes(type); + } + } diff --git a/tests/features/embeddables/embedded-entities.postgres.test.ts b/tests/features/embeddables/embedded-entities.postgres.test.ts index b957db674fbb..66afbf1acec6 100644 --- a/tests/features/embeddables/embedded-entities.postgres.test.ts +++ b/tests/features/embeddables/embedded-entities.postgres.test.ts @@ -260,6 +260,33 @@ describe('embedded entities in postgresql', () => { }); }); + + test('native update entity', async () => { + const user = new User(); + wrap(user).assign({ + address1: { street: 'Downing street 10', number: 3, postalCode: '123', city: 'London 1', country: 'UK 1' }, + address2: { street: 'Downing street 11', number: 3, city: 'London 2', country: 'UK 2' }, + address3: { street: 'Downing street 12', number: 3, postalCode: '789', city: 'London 3', country: 'UK 3' }, + address4: { street: 'Downing street 10', number: 3, postalCode: '123', city: 'London 1', country: 'UK 1' }, + }, { em: orm.em }); + + await orm.em.persistAndFlush(user); + + await orm.em.nativeUpdate(User, { + address4: { + number: { + $gt: 2, + }, + }, + }, { + after: 2, + }); + orm.em.clear(); + + const userAfterUpdate = await orm.em.findOne(User, user.id); + expect(userAfterUpdate?.after).toBe(2); + }); + test('query by complex custom expressions with JSON operator and casting (GH issue 1261)', async () => { const user = new User(); user.address1 = new Address1('Test', 10, '12000', 'Prague', 'CZ');