Skip to content

Commit 4b2178f

Browse files
committed
correct additional hints
predecessors comparator OMG! Is it really working?! everything works besides loop detection correct additional hints: everything works besides loop detection
1 parent ac493ab commit 4b2178f

File tree

1 file changed

+20
-70
lines changed

1 file changed

+20
-70
lines changed

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

Lines changed: 20 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
localTimestampToUtc,
2323
timeSeries as timeSeriesBase,
2424
timeSeriesFromCustomInterval,
25-
parseSqlInterval,
2625
findMinGranularityDimension
2726
} from '@cubejs-backend/shared';
2827

@@ -436,81 +435,32 @@ export class BaseQuery {
436435
*/
437436
get allJoinHints() {
438437
if (!this.collectedJoinHints) {
439-
const [rootOfJoin, ...allMembersJoinHints] = this.collectJoinHintsFromMembers(this.allMembersConcat(false));
438+
const allMembersJoinHints = this.collectJoinHintsFromMembers(this.allMembersConcat(false));
440439
const customSubQueryJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromCustomSubQuery());
441-
let joinMembersJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromJoin(this.join));
442-
443-
// One cube may join the other cube via transitive joined cubes,
444-
// members from which are referenced in the join `on` clauses.
445-
// We need to collect such join hints and push them upfront of the joining one
446-
// but only if they don't exist yet. Cause in other case we might affect what
447-
// join path will be constructed in join graph.
448-
// It is important to use queryLevelJoinHints during the calculation if it is set.
449-
450-
const constructJH = () => {
451-
const filteredJoinMembersJoinHints = joinMembersJoinHints.filter(m => !allMembersJoinHints.includes(m));
452-
return [
453-
...this.queryLevelJoinHints,
454-
...(rootOfJoin ? [rootOfJoin] : []),
455-
...filteredJoinMembersJoinHints,
456-
...allMembersJoinHints,
457-
...customSubQueryJoinHints,
458-
];
459-
};
460-
461-
let prevJoins = this.join;
462-
let prevJoinMembersJoinHints = joinMembersJoinHints;
463-
let newJoin = this.joinGraph.buildJoin(constructJH());
464-
465-
const isOrderPreserved = (base, updated) => {
466-
const common = base.filter(value => updated.includes(value));
467-
const bFiltered = updated.filter(value => common.includes(value));
468-
469-
return common.every((x, i) => x === bFiltered[i]);
470-
};
471-
472-
const isJoinTreesEqual = (a, b) => {
473-
if (!a || !b || a.root !== b.root || a.joins.length !== b.joins.length) {
474-
return false;
475-
}
476-
477-
// We don't care about the order of joins on the same level, so
478-
// we can compare them as sets.
479-
const aJoinsSet = new Set(a.joins.map(j => `${j.originalFrom}->${j.originalTo}`));
480-
const bJoinsSet = new Set(b.joins.map(j => `${j.originalFrom}->${j.originalTo}`));
481-
482-
if (aJoinsSet.size !== bJoinsSet.size) {
483-
return false;
484-
}
485-
486-
for (const val of aJoinsSet) {
487-
if (!bJoinsSet.has(val)) {
488-
return false;
489-
}
490-
}
491-
492-
return true;
493-
};
440+
const allJoinHints = [
441+
...this.queryLevelJoinHints,
442+
...allMembersJoinHints,
443+
...customSubQueryJoinHints,
444+
];
494445

495-
// Safeguard against infinite loop in case of cyclic joins somehow managed to slip through
496-
let cnt = 0;
446+
const tempJoin = this.joinGraph.buildJoin(allJoinHints);
497447

498-
while (newJoin?.joins.length > 0 && !isJoinTreesEqual(prevJoins, newJoin) && cnt < 10000) {
499-
prevJoins = newJoin;
500-
joinMembersJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromJoin(newJoin));
501-
if (!isOrderPreserved(prevJoinMembersJoinHints, joinMembersJoinHints)) {
502-
throw new UserError(`Can not construct joins for the query, potential loop detected: ${prevJoinMembersJoinHints.join('->')} vs ${joinMembersJoinHints.join('->')}`);
503-
}
504-
newJoin = this.joinGraph.buildJoin(constructJH());
505-
prevJoinMembersJoinHints = joinMembersJoinHints;
506-
cnt++;
448+
if (!tempJoin) {
449+
this.collectedJoinHints = allJoinHints;
450+
return allJoinHints;
507451
}
508452

509-
if (cnt >= 10000) {
510-
throw new UserError('Can not construct joins for the query, potential loop detected');
511-
}
453+
const joinMembersJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromJoin(tempJoin));
454+
const allJoinHintsFlatten = new Set(allJoinHints.flat());
455+
const newCollectedHints = joinMembersJoinHints.filter(j => !allJoinHintsFlatten.has(j));
512456

513-
this.collectedJoinHints = R.uniq(constructJH());
457+
this.collectedJoinHints = [
458+
...this.queryLevelJoinHints,
459+
tempJoin.root,
460+
...newCollectedHints,
461+
...allMembersJoinHints,
462+
...customSubQueryJoinHints,
463+
];
514464
}
515465
return this.collectedJoinHints;
516466
}

0 commit comments

Comments
 (0)