Skip to content

Commit 603d00c

Browse files
committed
add resolveFullMemberPathFn() in BaseQuery
1 parent 8d02cf1 commit 603d00c

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

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

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,17 @@ export class BaseQuery {
362362
try {
363363
// TODO allJoinHints should contain join hints form pre-agg
364364
this.join = this.joinGraph.buildJoin(this.allJoinHints);
365+
/**
366+
* @type {Record<string, string[]>}
367+
*/
368+
const queryJoinGraph = {};
369+
for (const { originalFrom, originalTo } of (this.join?.joins || [])) {
370+
if (!queryJoinGraph[originalFrom]) {
371+
queryJoinGraph[originalFrom] = [];
372+
}
373+
queryJoinGraph[originalFrom].push(originalTo);
374+
}
375+
this.joinGraphPaths = queryJoinGraph || {};
365376
} catch (e) {
366377
if (this.useNativeSqlPlanner) {
367378
// Tesseract doesn't require join to be prebuilt and there's a case where single join can't be built for multi-fact query
@@ -4677,7 +4688,10 @@ export class BaseQuery {
46774688
*/
46784689
backAliasMembers(members) {
46794690
const query = this;
4680-
return Object.fromEntries(members.flatMap(
4691+
4692+
const buildJoinPath = this.buildJoinPathFn();
4693+
4694+
const aliases = Object.fromEntries(members.flatMap(
46814695
member => {
46824696
const collectedMembers = query.evaluateSymbolSqlWithContext(
46834697
() => query.collectFrom([member], query.collectMemberNamesFor.bind(query), 'collectMemberNamesFor'),
@@ -4695,5 +4709,83 @@ export class BaseQuery {
46954709
.map(d => [query.cubeEvaluator.byPathAnyType(d).aliasMember, memberPath]);
46964710
}
46974711
));
4712+
4713+
/**
4714+
* @type {Record<string, string>}
4715+
*/
4716+
const res = {};
4717+
for (const [original, alias] of Object.entries(aliases)) {
4718+
const [cube, field] = original.split('.');
4719+
const path = buildJoinPath(cube);
4720+
4721+
const [aliasCube, aliasField] = alias.split('.');
4722+
const aliasPath = aliasCube !== cube ? buildJoinPath(aliasCube) : path;
4723+
4724+
if (path) {
4725+
res[`${path}.${field}`] = aliasPath ? `${aliasPath}.${aliasField}` : alias;
4726+
}
4727+
4728+
// Aliases might come from proxied members, in such cases
4729+
// we need to map them to originals too
4730+
if (aliasPath) {
4731+
res[original] = `${aliasPath}.${aliasField}`;
4732+
}
4733+
}
4734+
4735+
return res;
4736+
}
4737+
4738+
buildJoinPathFn() {
4739+
const query = this;
4740+
const { root } = this.join || {};
4741+
4742+
return (target) => {
4743+
const visited = new Set();
4744+
const path = [];
4745+
4746+
/**
4747+
* @param {string} node
4748+
* @returns {boolean}
4749+
*/
4750+
function dfs(node) {
4751+
if (node === target) {
4752+
path.push(node);
4753+
return true;
4754+
}
4755+
4756+
if (visited.has(node)) return false;
4757+
visited.add(node);
4758+
4759+
const neighbors = query.joinGraphPaths[node] || [];
4760+
for (const neighbor of neighbors) {
4761+
if (dfs(neighbor)) {
4762+
path.unshift(node);
4763+
return true;
4764+
}
4765+
}
4766+
4767+
return false;
4768+
}
4769+
4770+
return dfs(root) ? path.join('.') : null;
4771+
};
4772+
}
4773+
4774+
resolveFullMemberPathFn() {
4775+
const { root: queryJoinRoot } = this.join || {};
4776+
4777+
const buildJoinPath = this.buildJoinPathFn();
4778+
4779+
return (member) => {
4780+
const [cube, field] = member.split('.');
4781+
if (!cube || !field) return member;
4782+
4783+
if (cube === queryJoinRoot.root) {
4784+
return member;
4785+
}
4786+
4787+
const path = buildJoinPath(cube);
4788+
return path ? `${path}.${field}` : member;
4789+
};
46984790
}
46994791
}

0 commit comments

Comments
 (0)