Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]),
];
}

Expand Down
53 changes: 50 additions & 3 deletions packages/cubejs-schema-compiler/test/unit/base-query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand All @@ -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, {
Expand All @@ -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({
Expand Down
Loading