Skip to content

Commit c175592

Browse files
committed
add resolveFullMemberPathFn() in BaseQuery
1 parent 1445f68 commit c175592

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
@@ -4662,7 +4673,10 @@ export class BaseQuery {
46624673
*/
46634674
backAliasMembers(members) {
46644675
const query = this;
4665-
return Object.fromEntries(members.flatMap(
4676+
4677+
const buildJoinPath = this.buildJoinPathFn();
4678+
4679+
const aliases = Object.fromEntries(members.flatMap(
46664680
member => {
46674681
const collectedMembers = query.evaluateSymbolSqlWithContext(
46684682
() => query.collectFrom([member], query.collectMemberNamesFor.bind(query), 'collectMemberNamesFor'),
@@ -4680,5 +4694,83 @@ export class BaseQuery {
46804694
.map(d => [query.cubeEvaluator.byPathAnyType(d).aliasMember, memberPath]);
46814695
}
46824696
));
4697+
4698+
/**
4699+
* @type {Record<string, string>}
4700+
*/
4701+
const res = {};
4702+
for (const [original, alias] of Object.entries(aliases)) {
4703+
const [cube, field] = original.split('.');
4704+
const path = buildJoinPath(cube);
4705+
4706+
const [aliasCube, aliasField] = alias.split('.');
4707+
const aliasPath = aliasCube !== cube ? buildJoinPath(aliasCube) : path;
4708+
4709+
if (path) {
4710+
res[`${path}.${field}`] = aliasPath ? `${aliasPath}.${aliasField}` : alias;
4711+
}
4712+
4713+
// Aliases might come from proxied members, in such cases
4714+
// we need to map them to originals too
4715+
if (aliasPath) {
4716+
res[original] = `${aliasPath}.${aliasField}`;
4717+
}
4718+
}
4719+
4720+
return res;
4721+
}
4722+
4723+
buildJoinPathFn() {
4724+
const query = this;
4725+
const { root } = this.join || {};
4726+
4727+
return (target) => {
4728+
const visited = new Set();
4729+
const path = [];
4730+
4731+
/**
4732+
* @param {string} node
4733+
* @returns {boolean}
4734+
*/
4735+
function dfs(node) {
4736+
if (node === target) {
4737+
path.push(node);
4738+
return true;
4739+
}
4740+
4741+
if (visited.has(node)) return false;
4742+
visited.add(node);
4743+
4744+
const neighbors = query.joinGraphPaths[node] || [];
4745+
for (const neighbor of neighbors) {
4746+
if (dfs(neighbor)) {
4747+
path.unshift(node);
4748+
return true;
4749+
}
4750+
}
4751+
4752+
return false;
4753+
}
4754+
4755+
return dfs(root) ? path.join('.') : null;
4756+
};
4757+
}
4758+
4759+
resolveFullMemberPathFn() {
4760+
const { root: queryJoinRoot } = this.join || {};
4761+
4762+
const buildJoinPath = this.buildJoinPathFn();
4763+
4764+
return (member) => {
4765+
const [cube, field] = member.split('.');
4766+
if (!cube || !field) return member;
4767+
4768+
if (cube === queryJoinRoot.root) {
4769+
return member;
4770+
}
4771+
4772+
const path = buildJoinPath(cube);
4773+
return path ? `${path}.${field}` : member;
4774+
};
46834775
}
46844776
}

0 commit comments

Comments
 (0)