diff --git a/src/query-builder/SelectQueryBuilder.ts b/src/query-builder/SelectQueryBuilder.ts index 1bb808addc..5e846efa2d 100644 --- a/src/query-builder/SelectQueryBuilder.ts +++ b/src/query-builder/SelectQueryBuilder.ts @@ -2882,11 +2882,6 @@ export class SelectQueryBuilder }) }) } else { - if (column.isVirtualProperty) { - // Do not add unselected virtual properties to final select - return - } - finalSelects.push({ selection: selectionPath, aliasName: DriverUtils.buildAlias( diff --git a/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts b/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts index 0ba601beef..736804afab 100644 --- a/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts +++ b/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts @@ -247,7 +247,7 @@ export class RawSqlResultsToEntityTransformer { entity, this.driver.prepareHydratedValue(value, column), ) - if (value !== null) + if (value !== null && !column.isVirtualProperty) // we don't mark it as has data because if we will have all nulls in our object - we don't need such object hasData = true }) diff --git a/test/github-issues/10431/entity/Category.ts b/test/github-issues/10431/entity/Category.ts index 7afdfe3533..0e6a905486 100644 --- a/test/github-issues/10431/entity/Category.ts +++ b/test/github-issues/10431/entity/Category.ts @@ -14,7 +14,7 @@ export class Category { @VirtualColumn({ query: (alias) => - `SELECT COUNT(*) FROM category WHERE id = ${alias}.id`, + `SELECT COUNT(*) FROM "category" WHERE "id" = ${alias}."id"`, }) randomVirtualColumn: number diff --git a/test/github-issues/10431/issue-10431.ts b/test/github-issues/10431/issue-10431.ts index 5487032f92..b077e030e2 100644 --- a/test/github-issues/10431/issue-10431.ts +++ b/test/github-issues/10431/issue-10431.ts @@ -8,33 +8,51 @@ import { DataSource } from "../../../src" import { expect } from "chai" import { Category, Product } from "./entity" +import { DriverUtils } from "../../../src/driver/DriverUtils" describe("github issues > #10431 When requesting nested relations on foreign key primary entities, relation becomes empty entity rather than null", () => { let connections: DataSource[] - before( - async () => - (connections = await createTestingConnections({ - entities: [Category, Product], - schemaCreate: true, - dropSchema: true, - })), - ) + + before(async () => { + connections = await createTestingConnections({ + entities: [Category, Product], + schemaCreate: true, + dropSchema: true, + }) + }) beforeEach(() => reloadTestingDatabases(connections)) after(() => closeTestingConnections(connections)) it("should return [] when requested nested relations are empty on ManyToMany relation with @VirtualColumn definitions", () => Promise.all( connections.map(async (connection) => { + // By default, MySQL uses backticks instead of quotes for identifiers + if (DriverUtils.isMySQLFamily(connection.driver)) { + const randomVirtualColumnMetadata = connection + .getMetadata(Category) + .columns.find( + (columnMetadata) => + columnMetadata.propertyName === + "randomVirtualColumn", + )! + + randomVirtualColumnMetadata.query = (alias) => + `SELECT COUNT(*) FROM \`category\` WHERE \`id\` = ${alias}.\`id\`` + } + const productRepo = connection.getRepository(Product) const testProduct = new Product() testProduct.name = "foo" + await productRepo.save(testProduct) + const foundProduct = await productRepo.findOne({ where: { id: testProduct.id, }, relations: { categories: true }, }) + expect(foundProduct?.name).eq("foo") expect(foundProduct?.categories).eql([]) }),