Skip to content

Commit b53e410

Browse files
authored
fix: empty objects being hydrated when eager loading relations that have a @VirtualColumn (#10432)
* test: add scenario for #10431 * fix: empty objects being hydrated by unselected virtual properties
1 parent 2dc9624 commit b53e410

File tree

5 files changed

+100
-0
lines changed

5 files changed

+100
-0
lines changed

src/query-builder/SelectQueryBuilder.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2882,6 +2882,11 @@ export class SelectQueryBuilder<Entity extends ObjectLiteral>
28822882
})
28832883
})
28842884
} else {
2885+
if (column.isVirtualProperty) {
2886+
// Do not add unselected virtual properties to final select
2887+
return
2888+
}
2889+
28852890
finalSelects.push({
28862891
selection: selectionPath,
28872892
aliasName: DriverUtils.buildAlias(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {
2+
Column,
3+
Entity,
4+
ManyToMany,
5+
PrimaryGeneratedColumn,
6+
VirtualColumn,
7+
} from "../../../../src"
8+
import { Product } from "./Product"
9+
10+
@Entity()
11+
export class Category {
12+
@PrimaryGeneratedColumn()
13+
id: number
14+
15+
@VirtualColumn({
16+
query: (alias) =>
17+
`SELECT COUNT(*) FROM category WHERE id = ${alias}.id`,
18+
})
19+
randomVirtualColumn: number
20+
21+
@ManyToMany(() => Product, (product: Product) => product.categories)
22+
products?: Product[]
23+
24+
@Column("varchar")
25+
name: string
26+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
Column,
3+
Entity,
4+
JoinTable,
5+
ManyToMany,
6+
PrimaryGeneratedColumn,
7+
} from "../../../../src"
8+
import { Category } from "./Category"
9+
10+
@Entity()
11+
export class Product {
12+
@PrimaryGeneratedColumn()
13+
id: number
14+
15+
@Column("varchar")
16+
name: string
17+
18+
@ManyToMany(() => Category, (category: Category) => category.products, {
19+
eager: true,
20+
cascade: ["insert", "update", "remove"],
21+
orphanedRowAction: "delete",
22+
})
23+
@JoinTable()
24+
categories: Category[]
25+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./Category"
2+
export * from "./Product"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import "reflect-metadata"
2+
import {
3+
createTestingConnections,
4+
closeTestingConnections,
5+
reloadTestingDatabases,
6+
} from "../../utils/test-utils"
7+
import { DataSource } from "../../../src"
8+
import { expect } from "chai"
9+
10+
import { Category, Product } from "./entity"
11+
12+
describe("github issues > #10431 When requesting nested relations on foreign key primary entities, relation becomes empty entity rather than null", () => {
13+
let connections: DataSource[]
14+
before(
15+
async () =>
16+
(connections = await createTestingConnections({
17+
entities: [Category, Product],
18+
schemaCreate: true,
19+
dropSchema: true,
20+
})),
21+
)
22+
beforeEach(() => reloadTestingDatabases(connections))
23+
after(() => closeTestingConnections(connections))
24+
25+
it("should return [] when requested nested relations are empty on ManyToMany relation with @VirtualColumn definitions", () =>
26+
Promise.all(
27+
connections.map(async (connection) => {
28+
const productRepo = connection.getRepository(Product)
29+
const testProduct = new Product()
30+
testProduct.name = "foo"
31+
await productRepo.save(testProduct)
32+
const foundProduct = await productRepo.findOne({
33+
where: {
34+
id: testProduct.id,
35+
},
36+
relations: { categories: true },
37+
})
38+
expect(foundProduct?.name).eq("foo")
39+
expect(foundProduct?.categories).eql([])
40+
}),
41+
))
42+
})

0 commit comments

Comments
 (0)