import "reflect-metadata" import { createTestingConnections as createTestingDatasources, closeTestingConnections, reloadTestingDatabases, } from "../../utils/test-utils" import { DataSource } from "../../../src/data-source/DataSource" import { expect } from "chai" import { Product } from "./entity/product" import { Category } from "./entity/category" describe("github issues > #9988 RelationIdLoader reuses the same queryplanner within a transaction", () => { let dataSources: DataSource[] before( async () => (dataSources = await createTestingDatasources({ entities: [Product, Category], enabledDrivers: ["postgres"], schemaCreate: true, dropSchema: true, })), ) beforeEach(() => reloadTestingDatabases(dataSources)) after(() => closeTestingConnections(dataSources)) it("custom repository querybuilders within transactions returns relations for getOne() and getMany", async () => { await Promise.all( dataSources.map(async (dataSource) => { const manager = dataSource.manager // Setup seed const categoryRepo = manager.getRepository(Category) const categoryOne = categoryRepo.create({ id: 1 }) const categoryTwo = categoryRepo.create({ id: 2 }) const productOneId = 1 const productTwoId = 2 await categoryRepo.save(categoryOne) await categoryRepo.save(categoryTwo) const options = (id: number) => ({ relationLoadStrategy: "query", where: { id: productOneId }, relations: { categories: true }, }) // Create a custom repository that uses a query builder without query planner // For both methods, relationLoadStrategy is set to "query", where the bug lies. const productRepo = dataSource.getRepository(Product).extend({ async getOne(): Promise { return this.createQueryBuilder("product") .setFindOptions(options(productOneId)) .getOne() }, async getMany(): Promise { return this.createQueryBuilder("product") .setFindOptions(options(productTwoId)) .getMany() }, }) // Creates a transaction that is shared across all the queries const getOneProduct = await manager.transaction( async (txnManager) => { const customProductRepo = txnManager.withRepository(productRepo) const product = customProductRepo.create({ id: productOneId, categories: [{ id: categoryOne.id }], }) await customProductRepo.save(product) return await customProductRepo.getOne() }, ) expect(getOneProduct.categories.length).to.be.eql(1) const getManyProduct = await manager.transaction( async (txnManager) => { const customProductRepo = txnManager.withRepository(productRepo) const product = customProductRepo.create({ id: productTwoId, categories: [{ id: categoryOne.id }], }) await customProductRepo.save(product) return await customProductRepo.getMany() }, ) expect(getManyProduct[0].categories.length).to.be.eql(1) }), ) }) })