Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2e9e662
expose joinGraph from transformQueryToCanUseForm()
KSDaemon Sep 29, 2025
1e867bd
get rid of ramda in favor of simple js
KSDaemon Sep 30, 2025
59c2e60
preparing dimensionsMatch()
KSDaemon Sep 30, 2025
9096d1c
fix(schema-compiler): Fix pre-agg matching for 'rollupJoin' / 'rollup…
KSDaemon Sep 30, 2025
d8d73bb
add tests
KSDaemon Sep 30, 2025
145a54d
add test for 3-cube rollupJoin pre-agg
KSDaemon Oct 20, 2025
c4c354b
use rollupsReferences for 'rollupJoin' / 'rollupLambda' pre-agg matching
KSDaemon Oct 20, 2025
1522d40
fix old tests with new required fields
KSDaemon Oct 20, 2025
af336cd
more tests
KSDaemon Oct 20, 2025
a73fd19
implement pre-agg matching using pre-agg join subgraphs
KSDaemon Oct 20, 2025
f7db87b
fix incorrect cache for pre-aggs
KSDaemon Oct 20, 2025
66db298
fix canUsePreAggregationNotAdditive
KSDaemon Oct 20, 2025
9c15e1a
skip test for tesseract
KSDaemon Oct 21, 2025
c9991e7
export type
KSDaemon Oct 22, 2025
1ff6d7d
more types
KSDaemon Oct 22, 2025
0582006
build fullNames for rollupJoin/Lambda in the evaluatedPreAggregationO…
KSDaemon Oct 22, 2025
84bde20
add memberShortNameFromPath() to Evaluator
KSDaemon Oct 22, 2025
c90ec16
fix type
KSDaemon Oct 22, 2025
8233f28
get rid of references.fullName* in favor of fullpath-members
KSDaemon Oct 22, 2025
623e4fb
some refactoring to avoid copy/paste
KSDaemon Oct 22, 2025
b1e4d23
add 'rollupJoin pre-aggregation matching with transitive joins' test
KSDaemon Oct 23, 2025
26cb0c9
fix buildRollupJoin
KSDaemon Oct 23, 2025
4f4a007
fix resolveJoinMembers()
KSDaemon Oct 23, 2025
8e4307e
implement sortMembersByJoinTree()
KSDaemon Oct 23, 2025
09ac100
fix joint hints collection for transitive joins
KSDaemon Oct 27, 2025
d2332b3
remove obsolete
KSDaemon Oct 27, 2025
f4649fe
revert back obsolete
KSDaemon Oct 27, 2025
23726b6
fix joint hints collection for transitive joins
KSDaemon Oct 27, 2025
85d238c
fix joint hints collection for transitive joins
KSDaemon Oct 27, 2025
0db02fc
update joinTreeForHints() with skipQueryJoinMap flag
KSDaemon Oct 27, 2025
3d7c1e1
fix buildRollupJoin()
KSDaemon Oct 27, 2025
c2ea506
fix datamodel for rollupJoin tests
KSDaemon Oct 27, 2025
cc6a5ae
simplify buildRollupJoin() and evaluatedPreAggregationObj()
KSDaemon Oct 27, 2025
1f555b9
fix tests
KSDaemon Oct 27, 2025
c11c2a6
remove obsolete
KSDaemon Oct 27, 2025
6e0a1f3
add test for pre-agg with not-full paths
KSDaemon Oct 28, 2025
ca14e46
more types
KSDaemon Oct 28, 2025
6a7d6d3
improve error message in preAggObjForJoin()
KSDaemon Oct 28, 2025
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
61 changes: 48 additions & 13 deletions packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,16 +387,16 @@ export class BaseQuery {
}

/**
* Is used by native
* This function follows the same logic as in this.collectJoinHints()
* @private
* skipQueryJoinMap is used by PreAggregations to build join tree without user's query all members map
* @public
* @param {Array<(Array<string> | string)>} hints
* @param { boolean } skipQueryJoinMap
* @return {import('../compiler/JoinGraph').FinishedJoinTree}
*/
joinTreeForHints(hints) {
const explicitJoinHintMembers = new Set(hints.filter(j => Array.isArray(j)).flat());
const queryJoinMaps = this.queryJoinMap();
const newCollectedHints = [];
joinTreeForHints(hints, skipQueryJoinMap = false) {
const queryJoinMaps = skipQueryJoinMap ? {} : this.queryJoinMap();
let newCollectedHints = [];

const constructJH = () => R.uniq(this.enrichHintsWithJoinMap([
...newCollectedHints,
Expand All @@ -421,16 +421,20 @@ export class BaseQuery {
const iterationCollectedHints = joinMembersJoinHints.filter(j => !allJoinHintsFlatten.has(j));
newJoinHintsCollectedCnt = iterationCollectedHints.length;
cnt++;
if (newJoin) {
newCollectedHints.push(...joinMembersJoinHints.filter(j => !explicitJoinHintMembers.has(j)));
if (newJoin && newJoin.joins.length > 0) {
// Even if there is no join tree changes, we still
// push correctly ordered join hints, collected from the resolving of members of join tree
// upfront the all existing query members. This ensures the correct cube join order
// with transitive joins even if they are already presented among query members.
newCollectedHints = this.enrichedJoinHintsFromJoinTree(newJoin, joinMembersJoinHints);
}
} while (newJoin?.joins.length > 0 && !this.isJoinTreesEqual(prevJoin, newJoin) && cnt < 10000 && newJoinHintsCollectedCnt > 0);

if (cnt >= 10000) {
throw new UserError('Can not construct joins for the query, potential loop detected');
}

return newJoin;
return this.joinGraph.buildJoin(constructJH());
}

cacheValue(key, fn, { contextPropNames, inputProps, cache } = {}) {
Expand Down Expand Up @@ -505,6 +509,34 @@ export class BaseQuery {
return joinMaps;
}

/**
* @private
* @param { import('../compiler/JoinGraph').FinishedJoinTree } joinTree
* @param { string[] } joinHints
* @return { string[][] }
*/
enrichedJoinHintsFromJoinTree(joinTree, joinHints) {
const joinsMap = {};

for (const j of joinTree.joins) {
joinsMap[j.to] = j.from;
}

return joinHints.map(jh => {
let cubeName = jh;
const path = [cubeName];
while (joinsMap[cubeName]) {
cubeName = joinsMap[cubeName];
path.push(cubeName);
}

if (path.length === 1) {
return path[0];
}
return path.reverse();
});
}

/**
* @private
* @param { (string|string[])[] } hints
Expand Down Expand Up @@ -2666,10 +2698,9 @@ export class BaseQuery {
*/
collectJoinHints(excludeTimeDimensions = false) {
const allMembersJoinHints = this.collectJoinHintsFromMembers(this.allMembersConcat(excludeTimeDimensions));
const explicitJoinHintMembers = new Set(allMembersJoinHints.filter(j => Array.isArray(j)).flat());
const queryJoinMaps = this.queryJoinMap();
const customSubQueryJoinHints = this.collectJoinHintsFromMembers(this.joinMembersFromCustomSubQuery());
const newCollectedHints = [];
let newCollectedHints = [];

// One cube may join the other cube via transitive joined cubes,
// members from which are referenced in the join `on` clauses.
Expand Down Expand Up @@ -2703,8 +2734,12 @@ export class BaseQuery {
const iterationCollectedHints = joinMembersJoinHints.filter(j => !allJoinHintsFlatten.has(j));
newJoinHintsCollectedCnt = iterationCollectedHints.length;
cnt++;
if (newJoin) {
newCollectedHints.push(...joinMembersJoinHints.filter(j => !explicitJoinHintMembers.has(j)));
if (newJoin && newJoin.joins.length > 0) {
// Even if there is no join tree changes, we still
// push correctly ordered join hints, collected from the resolving of members of join tree
// upfront the all existing query members. This ensures the correct cube join order
// with transitive joins even if they are already presented among query members.
newCollectedHints = this.enrichedJoinHintsFromJoinTree(newJoin, joinMembersJoinHints);
}
} while (newJoin?.joins.length > 0 && !this.isJoinTreesEqual(prevJoin, newJoin) && cnt < 10000 && newJoinHintsCollectedCnt > 0);

Expand Down
Loading
Loading