Skip to content

Commit b9418ae

Browse files
committed
add resolveFullMemberPathFn() in BaseQuery
1 parent d6e4faf commit b9418ae

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
@@ -363,6 +363,17 @@ export class BaseQuery {
363363
try {
364364
// TODO allJoinHints should contain join hints form pre-agg
365365
this.join = this.joinGraph.buildJoin(this.allJoinHints);
366+
/**
367+
* @type {Record<string, string[]>}
368+
*/
369+
const queryJoinGraph = {};
370+
for (const { originalFrom, originalTo } of (this.join?.joins || [])) {
371+
if (!queryJoinGraph[originalFrom]) {
372+
queryJoinGraph[originalFrom] = [];
373+
}
374+
queryJoinGraph[originalFrom].push(originalTo);
375+
}
376+
this.joinGraphPaths = queryJoinGraph || {};
366377
} catch (e) {
367378
if (this.useNativeSqlPlanner) {
368379
// Tesseract doesn't require join to be prebuilt and there's a case where single join can't be built for multi-fact query
@@ -4864,7 +4875,10 @@ export class BaseQuery {
48644875
*/
48654876
backAliasMembers(members) {
48664877
const query = this;
4867-
return Object.fromEntries(members.flatMap(
4878+
4879+
const buildJoinPath = this.buildJoinPathFn();
4880+
4881+
const aliases = Object.fromEntries(members.flatMap(
48684882
member => {
48694883
const collectedMembers = query.evaluateSymbolSqlWithContext(
48704884
() => query.collectFrom([member], query.collectMemberNamesFor.bind(query), 'collectMemberNamesFor'),
@@ -4882,5 +4896,83 @@ export class BaseQuery {
48824896
.map(d => [query.cubeEvaluator.byPathAnyType(d).aliasMember, memberPath]);
48834897
}
48844898
));
4899+
4900+
/**
4901+
* @type {Record<string, string>}
4902+
*/
4903+
const res = {};
4904+
for (const [original, alias] of Object.entries(aliases)) {
4905+
const [cube, field] = original.split('.');
4906+
const path = buildJoinPath(cube);
4907+
4908+
const [aliasCube, aliasField] = alias.split('.');
4909+
const aliasPath = aliasCube !== cube ? buildJoinPath(aliasCube) : path;
4910+
4911+
if (path) {
4912+
res[`${path}.${field}`] = aliasPath ? `${aliasPath}.${aliasField}` : alias;
4913+
}
4914+
4915+
// Aliases might come from proxied members, in such cases
4916+
// we need to map them to originals too
4917+
if (aliasPath) {
4918+
res[original] = `${aliasPath}.${aliasField}`;
4919+
}
4920+
}
4921+
4922+
return res;
4923+
}
4924+
4925+
buildJoinPathFn() {
4926+
const query = this;
4927+
const { root } = this.join || {};
4928+
4929+
return (target) => {
4930+
const visited = new Set();
4931+
const path = [];
4932+
4933+
/**
4934+
* @param {string} node
4935+
* @returns {boolean}
4936+
*/
4937+
function dfs(node) {
4938+
if (node === target) {
4939+
path.push(node);
4940+
return true;
4941+
}
4942+
4943+
if (visited.has(node)) return false;
4944+
visited.add(node);
4945+
4946+
const neighbors = query.joinGraphPaths[node] || [];
4947+
for (const neighbor of neighbors) {
4948+
if (dfs(neighbor)) {
4949+
path.unshift(node);
4950+
return true;
4951+
}
4952+
}
4953+
4954+
return false;
4955+
}
4956+
4957+
return dfs(root) ? path.join('.') : null;
4958+
};
4959+
}
4960+
4961+
resolveFullMemberPathFn() {
4962+
const { root: queryJoinRoot } = this.join || {};
4963+
4964+
const buildJoinPath = this.buildJoinPathFn();
4965+
4966+
return (member) => {
4967+
const [cube, field] = member.split('.');
4968+
if (!cube || !field) return member;
4969+
4970+
if (cube === queryJoinRoot.root) {
4971+
return member;
4972+
}
4973+
4974+
const path = buildJoinPath(cube);
4975+
return path ? `${path}.${field}` : member;
4976+
};
48854977
}
48864978
}

0 commit comments

Comments
 (0)