Skip to content

Commit a8182dc

Browse files
committed
attempt to make allJoinHints work
1 parent 896af5e commit a8182dc

File tree

2 files changed

+52
-13
lines changed

2 files changed

+52
-13
lines changed

packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -418,10 +418,29 @@ export class BaseQuery {
418418
*/
419419
get allJoinHints() {
420420
if (!this.collectedJoinHints) {
421+
let joinHints = this.collectJoinHints();
422+
// let joinHints = this.collectJoinHintsFromMembers(this.allMembersConcat(false));
423+
424+
// One cube may join the other cube via transitive joined cubes,
425+
// members from which are referenced in the join `on` clauses.
426+
// We need to collect such join hints and push them upfront of the joining one.
427+
// It is important to use queryLevelJoinHints during the calculation if it is set.
428+
429+
const prevJoins = this.join;
430+
431+
let newJoin = this.joinGraph.buildJoin([...this.queryLevelJoinHints, ...joinHints]);
432+
while (!R.equals(this.join, newJoin)) {
433+
this.join = newJoin;
434+
joinHints = R.uniq([joinHints[0], ...this.collectJoinHintsFromMembers(this.joinMembersFromJoin()), ...joinHints]);
435+
newJoin = this.joinGraph.buildJoin([...this.queryLevelJoinHints, ...joinHints]);
436+
}
437+
421438
this.collectedJoinHints = [
422439
...this.queryLevelJoinHints,
423-
...this.collectJoinHints(),
440+
...joinHints,
424441
];
442+
443+
this.join = prevJoins;
425444
}
426445
return this.collectedJoinHints;
427446
}
@@ -2401,7 +2420,20 @@ export class BaseQuery {
24012420
} else if (s.patchedMeasure?.patchedFrom) {
24022421
return [s.patchedMeasure.patchedFrom.cubeName].concat(this.evaluateSymbolSql(s.patchedMeasure.patchedFrom.cubeName, s.patchedMeasure.patchedFrom.name, s.definition()));
24032422
} else {
2404-
return this.evaluateSql(s.cube().name, s.definition().sql);
2423+
const res = this.evaluateSql(s.cube().name, s.definition().sql);
2424+
if (s.isJoinCondition) {
2425+
// In a join between Cube A and Cube B, sql() may reference members from other cubes.
2426+
// These referenced cubes must be added as join hints before Cube B to ensure correct SQL generation.
2427+
const targetCube = s.targetCubeName();
2428+
const { joinHints } = this.safeEvaluateSymbolContext();
2429+
let targetIdx = joinHints.findIndex(e => e === targetCube);
2430+
while (targetIdx > -1) {
2431+
joinHints.splice(targetIdx, 1);
2432+
targetIdx = joinHints.findIndex(e => e === targetCube);
2433+
}
2434+
joinHints.push(targetCube);
2435+
}
2436+
return res;
24052437
}
24062438
}
24072439

@@ -2438,23 +2470,27 @@ export class BaseQuery {
24382470
};
24392471
});
24402472

2441-
const joinMembers = this.join ? this.join.joins.map(j => ({
2442-
getMembers: () => [{
2443-
path: () => null,
2444-
cube: () => this.cubeEvaluator.cubeFromPath(j.originalFrom),
2445-
definition: () => j.join,
2446-
}]
2447-
})) : [];
2448-
24492473
const membersToCollectFrom = [
24502474
...this.allMembersConcat(excludeTimeDimensions),
2451-
...joinMembers,
2475+
...this.joinMembersFromJoin(),
24522476
...customSubQueryJoinMembers,
24532477
];
24542478

24552479
return this.collectJoinHintsFromMembers(membersToCollectFrom);
24562480
}
24572481

2482+
joinMembersFromJoin() {
2483+
return this.join ? this.join.joins.map(j => ({
2484+
getMembers: () => [{
2485+
path: () => null,
2486+
cube: () => this.cubeEvaluator.cubeFromPath(j.originalFrom),
2487+
definition: () => j.join,
2488+
isJoinCondition: true,
2489+
targetCubeName: () => j.originalTo,
2490+
}]
2491+
})) : [];
2492+
}
2493+
24582494
collectJoinHintsFromMembers(members) {
24592495
return [
24602496
...members.map(m => m.joinHint).filter(h => h?.length > 0),
@@ -2770,7 +2806,7 @@ export class BaseQuery {
27702806

27712807
pushJoinHints(joinHints) {
27722808
if (this.safeEvaluateSymbolContext().joinHints && joinHints) {
2773-
if (joinHints.length === 1) {
2809+
if (Array.isArray(joinHints) && joinHints.length === 1) {
27742810
[joinHints] = joinHints;
27752811
}
27762812
this.safeEvaluateSymbolContext().joinHints.push(joinHints);

packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,9 @@ export class CubeSymbols {
773773

774774
protected joinHints() {
775775
const { joinHints } = this.resolveSymbolsCallContext || {};
776+
if (Array.isArray(joinHints)) {
777+
return R.uniq(joinHints);
778+
}
776779
return joinHints;
777780
}
778781

@@ -879,7 +882,7 @@ export class CubeSymbols {
879882
} else if (this.symbols[cubeName]?.[name]) {
880883
cube = this.cubeReferenceProxy(
881884
cubeName,
882-
undefined,
885+
collectJoinHints ? [] : undefined,
883886
name
884887
);
885888
}

0 commit comments

Comments
 (0)