From cc4346dba5659161d73e767149a7aa8d99dbdede Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Fri, 24 Oct 2025 18:59:56 +0300 Subject: [PATCH] fix(schema-compiler): Fix incorrect cache that affects query joins + tests --- .../src/adapter/BaseQuery.js | 8 ++- .../test/unit/base-query.test.ts | 53 +++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js index 53b3295d798c3..6189832b4f7e8 100644 --- a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js +++ b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js @@ -2745,9 +2745,15 @@ export class BaseQuery { } collectJoinHintsFromMembers(members) { + // Extract cube names from members to make cache key member-cubes-specific + const memberCubes = members + .map(m => m.cube?.()?.name) + .filter(Boolean) + .sort(); + return [ ...members.map(m => m.joinHint).filter(h => h?.length > 0), - ...this.collectFrom(members, this.collectJoinHintsFor.bind(this), 'collectJoinHintsFromMembers'), + ...this.collectFrom(members, this.collectJoinHintsFor.bind(this), ['collectJoinHintsFromMembers', ...memberCubes]), ]; } diff --git a/packages/cubejs-schema-compiler/test/unit/base-query.test.ts b/packages/cubejs-schema-compiler/test/unit/base-query.test.ts index c70c7902c5888..26bf4782b1558 100644 --- a/packages/cubejs-schema-compiler/test/unit/base-query.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/base-query.test.ts @@ -961,7 +961,7 @@ describe('SQL Generation', () => { ]); - it('Base joins - one-one join', async () => { + it('one-one join', async () => { await compilers.compiler.compile(); const query = new PostgresQuery(compilers, { @@ -980,7 +980,7 @@ describe('SQL Generation', () => { expect(queryAndParams[0]).toContain('LEFT JOIN card3_tbl AS "cards_c" ON "cards_b".other_id = "cards_c".id'); }); - it('Base joins - multiplied join', async () => { + it('multiplied join', async () => { await compilers.compiler.compile(); const query = new PostgresQuery(compilers, { @@ -994,12 +994,59 @@ describe('SQL Generation', () => { timezone: 'America/Los_Angeles', }); - const queryAndParams = query.buildSqlAndParams(); + const _queryAndParams = query.buildSqlAndParams(); /* expect(queryAndParams[0]).toContain('LEFT JOIN card2_tbl AS "cards_b" ON "cards_a".other_id = "cards_b".id'); expect(queryAndParams[0]).toContain('LEFT JOIN card3_tbl AS "cards_c" ON "cards_b".other_id = "cards_c".id'); */ }); + + it('join hint cache', async () => { + // Create a schema with a segment that uses FILTER_PARAMS + const filterParamsCompilers = /** @type Compilers */ prepareJsCompiler([ + createCubeSchema({ + name: 'cardsA', + sqlTable: 'card_tbl', + joins: `{ + cardsB: { + sql: \`\${CUBE}.other_id = \${cardsB}.id\`, + relationship: 'one_to_one' + }, + }` + }).replace(`sql: \`\${CUBE}.location = 'San Francisco'\``, `sql: \`\${FILTER_PARAMS.cardsA.location.filter('location')}\``), + createCubeSchema({ + name: 'cardsB', + sqlTable: 'card2_tbl', + }), + ]); + await filterParamsCompilers.compiler.compile(); + + // First query requires a join + const queryWithJoin = new PostgresQuery(filterParamsCompilers, { + dimensions: [ + 'cardsA.id', + 'cardsB.id', + ], + segments: [ + 'cardsA.sfUsers', + ], + }); + const queryAndParamsWithJoin = queryWithJoin.buildSqlAndParams(); + expect(queryAndParamsWithJoin[0]).toContain('LEFT JOIN card2_tbl AS "cards_b" ON "cards_a".other_id = "cards_b".id'); + + // Second query does not require a join and should not be impacted by the first query + const queryWithoutJoin = new PostgresQuery(filterParamsCompilers, { + dimensions: [ + 'cardsA.id', + ], + segments: [ + 'cardsA.sfUsers', + ], + }); + const queryAndParamsWithoutJoin = queryWithoutJoin.buildSqlAndParams(); + expect(queryAndParamsWithoutJoin[0]).not.toContain('JOIN'); + }); }); + describe('Common - JS', () => { const compilers = /** @type Compilers */ prepareJsCompiler( createCubeSchema({