diff --git a/src/cache/DbQueryResultCache.ts b/src/cache/DbQueryResultCache.ts index 91dbb0092..6f981ff63 100644 --- a/src/cache/DbQueryResultCache.ts +++ b/src/cache/DbQueryResultCache.ts @@ -158,6 +158,7 @@ export class DbQueryResultCache implements QueryResultCache { ? new MssqlParameter(options.identifier, "nvarchar") : options.identifier, }) + .cache(false) // disable cache to avoid infinite loops when cache is alwaysEnable .getRawOne() } else if (options.query) { if (this.connection.driver.options.type === "oracle") { @@ -168,6 +169,7 @@ export class DbQueryResultCache implements QueryResultCache { )}, :query) = 0`, { query: options.query }, ) + .cache(false) // disable cache to avoid infinite loops when cache is alwaysEnable .getRawOne() } @@ -179,6 +181,7 @@ export class DbQueryResultCache implements QueryResultCache { ? new MssqlParameter(options.query, "nvarchar") : options.query, }) + .cache(false) // disable cache to avoid infinite loops when cache is alwaysEnable .getRawOne() } diff --git a/src/query-builder/QueryExpressionMap.ts b/src/query-builder/QueryExpressionMap.ts index c0156e040..3f1867d7b 100644 --- a/src/query-builder/QueryExpressionMap.ts +++ b/src/query-builder/QueryExpressionMap.ts @@ -261,8 +261,9 @@ export class QueryExpressionMap { /** * Indicates if query result cache is enabled or not. + * It is undefined by default to avoid overriding the `alwaysEnabled` config */ - cache: boolean = false + cache?: boolean /** * Time in milliseconds in which cache will expire. diff --git a/src/query-builder/SelectQueryBuilder.ts b/src/query-builder/SelectQueryBuilder.ts index 24c2a9858..ef48e291e 100644 --- a/src/query-builder/SelectQueryBuilder.ts +++ b/src/query-builder/SelectQueryBuilder.ts @@ -3770,7 +3770,7 @@ export class SelectQueryBuilder (cacheOptions.alwaysEnabled && this.expressionMap.cache !== false) || // ...or it's enabled locally explicitly. - this.expressionMap.cache + this.expressionMap.cache === true let cacheError = false if (this.connection.queryResultCache && isCachingEnabled) { try { diff --git a/test/github-issues/9910/entity/User.ts b/test/github-issues/9910/entity/User.ts new file mode 100644 index 000000000..e6a39507c --- /dev/null +++ b/test/github-issues/9910/entity/User.ts @@ -0,0 +1,10 @@ +import { Entity, PrimaryGeneratedColumn, Column } from "../../../../src" + +@Entity() +export class User { + @PrimaryGeneratedColumn() + id: number + + @Column() + name: string +} diff --git a/test/github-issues/9910/issue-9910.ts b/test/github-issues/9910/issue-9910.ts new file mode 100644 index 000000000..baf411373 --- /dev/null +++ b/test/github-issues/9910/issue-9910.ts @@ -0,0 +1,58 @@ +import "reflect-metadata" +import { expect } from "chai" +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, +} from "../../utils/test-utils" +import { DataSource } from "../../../src/data-source/DataSource" +import { User } from "./entity/User" + +describe("github issues > #9910 Incorrect behaivor of 'alwaysEnabled: true' after change from issue #9023", () => { + let connections: DataSource[] + before( + async () => + (connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + cache: { + alwaysEnabled: true, + }, + })), + ) + beforeEach(() => reloadTestingDatabases(connections)) + after(() => closeTestingConnections(connections)) + + it("should automatically cache if alwaysEnabled", () => + Promise.all( + connections.map(async (connection) => { + if (connection.driver.options.type === "spanner") { + return + } + const user1 = new User() + user1.name = "Foo" + await connection.manager.save(user1) + + const users1 = await connection + .createQueryBuilder(User, "user") + .getMany() + expect(users1.length).to.be.equal(1) + + const user2 = new User() + user2.name = "Bar" + await connection.manager.save(user2) + + // result should be cached and second user should not be retrieved + const users2 = await connection + .createQueryBuilder(User, "user") + .getMany() + expect(users2.length).to.be.equal(1) + + // with cache explicitly disabled, the second user should be retrieved + const users3 = await connection + .createQueryBuilder(User, "user") + .cache(false) + .getMany() + expect(users3.length).to.be.equal(2) + }), + )) +})