Skip to content

Commit aa6bc44

Browse files
committed
Move filtering logic to generateIncludeMembers
1 parent 104c7fc commit aa6bc44

File tree

3 files changed

+75
-31
lines changed

3 files changed

+75
-31
lines changed

packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ export class CubeSymbols {
605605
}
606606
}
607607

608-
const includeMembers = this.generateIncludeMembers(cubeIncludes, type);
608+
const includeMembers = this.generateIncludeMembers(cubeIncludes, type, cube);
609609
this.applyIncludeMembers(includeMembers, cube, type, errorReporter);
610610

611611
const existing = cube.includedMembers ?? [];
@@ -756,7 +756,7 @@ export class CubeSymbols {
756756
splitViewDef = splitViews[viewName];
757757
}
758758

759-
const includeMembers = this.generateIncludeMembers(finalIncludes, type);
759+
const includeMembers = this.generateIncludeMembers(finalIncludes, type, splitViewDef);
760760
this.applyIncludeMembers(includeMembers, splitViewDef, type, errorReporter);
761761
} else {
762762
for (const member of finalIncludes) {
@@ -786,13 +786,84 @@ export class CubeSymbols {
786786
return this.symbols[cubeName]?.cubeObj()?.[type]?.[memberName];
787787
}
788788

789-
protected generateIncludeMembers(members: any[], type: string) {
789+
protected createViewAwareDrillMemberFunction(
790+
originalFunction: Function,
791+
sourceCubeName: string,
792+
targetCubeName: string,
793+
originalDrillMembers: string[]
794+
) {
795+
const cubeEvaluator = this;
796+
797+
return function drillMemberFilter(..._args: any[]) {
798+
// Transform source cube references to target cube references
799+
// e.g., "Orders.id" -> "OrdersSimpleView.id"
800+
const transformedDrillMembers = originalDrillMembers.map(member => {
801+
const memberParts = member.split('.');
802+
if (memberParts[0] === sourceCubeName) {
803+
return `${targetCubeName}.${memberParts[1]}`;
804+
}
805+
return member; // Keep as-is if not from source cube
806+
});
807+
808+
// Get the target cube to check which members actually exist
809+
const targetCubeSymbol = cubeEvaluator.symbols[targetCubeName];
810+
if (!targetCubeSymbol) {
811+
return [];
812+
}
813+
814+
const targetCube = targetCubeSymbol.cubeObj();
815+
if (!targetCube) {
816+
return [];
817+
}
818+
819+
// Build set of available members in the target cube
820+
const availableMembers = new Set<string>();
821+
['measures', 'dimensions', 'segments'].forEach(memberType => {
822+
if (targetCube[memberType]) {
823+
Object.keys(targetCube[memberType]).forEach(memberName => {
824+
availableMembers.add(`${targetCubeName}.${memberName}`);
825+
});
826+
}
827+
});
828+
829+
// Filter drill members to only include available ones
830+
return transformedDrillMembers.filter(member => availableMembers.has(member));
831+
};
832+
}
833+
834+
protected generateIncludeMembers(members: any[], type: string, targetCube?: any) {
790835
return members.map(memberRef => {
791836
const path = memberRef.member.split('.');
792837
const resolvedMember = this.getResolvedMember(type, path[path.length - 2], path[path.length - 1]);
793838
if (!resolvedMember) {
794839
throw new Error(`Can't resolve '${memberRef.member}' while generating include members`);
795840
}
841+
842+
// Store drill member processing info for later use in the member definition
843+
let processedDrillMembers = resolvedMember.drillMembers;
844+
845+
if (type === 'measures' && resolvedMember.drillMembers && targetCube?.isView) {
846+
const sourceCubeName = path[path.length - 2]; // e.g., "Orders"
847+
848+
const evaluatedDrillMembers = this.evaluateReferences(
849+
sourceCubeName,
850+
resolvedMember.drillMembers,
851+
{ originalSorting: true }
852+
);
853+
854+
// Ensure we have an array
855+
const drillMembersArray = Array.isArray(evaluatedDrillMembers)
856+
? evaluatedDrillMembers
857+
: [evaluatedDrillMembers];
858+
859+
// Create a new filtered function for this view
860+
processedDrillMembers = this.createViewAwareDrillMemberFunction(
861+
resolvedMember.drillMembers,
862+
sourceCubeName,
863+
targetCube.name,
864+
drillMembersArray
865+
);
866+
}
796867

797868
// eslint-disable-next-line no-new-func
798869
const sql = new Function(path[0], `return \`\${${memberRef.member}}\`;`);
@@ -809,7 +880,7 @@ export class CubeSymbols {
809880
...(resolvedMember.multiStage && { multiStage: resolvedMember.multiStage }),
810881
...(resolvedMember.timeShift && { timeShift: resolvedMember.timeShift }),
811882
...(resolvedMember.orderBy && { orderBy: resolvedMember.orderBy }),
812-
...(resolvedMember.drillMembers && { drillMembers: resolvedMember.drillMembers }),
883+
...(processedDrillMembers && { drillMembers: processedDrillMembers }),
813884
...(resolvedMember.drillMembersGrouped && { drillMembersGrouped: resolvedMember.drillMembersGrouped }),
814885
};
815886
} else if (type === 'dimensions') {

packages/cubejs-schema-compiler/src/compiler/CubeToMetaTransformer.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -206,31 +206,6 @@ export class CubeToMetaTransformer {
206206
cubeName, drillMembers, { originalSorting: true }
207207
)) || [];
208208

209-
// Filter drill members for views to only include available members
210-
if (drillMembersArray.length > 0) {
211-
const cubeSymbol = this.cubeEvaluator.symbols[cubeName];
212-
if (cubeSymbol) {
213-
const cube = cubeSymbol.cubeObj();
214-
if (cube && cube.isView) {
215-
const availableMembers = new Set();
216-
// Collect all available member names from all types
217-
['measures', 'dimensions', 'segments'].forEach(memberType => {
218-
if (cube[memberType]) {
219-
Object.keys(cube[memberType]).forEach(memberName => {
220-
availableMembers.add(`${cubeName}.${memberName}`);
221-
});
222-
}
223-
});
224-
225-
// Filter drill members to only include those available in the view
226-
const filteredDrillMembers = drillMembersArray.filter(member => availableMembers.has(member));
227-
228-
// Update the drillMembersArray with filtered results
229-
drillMembersArray.splice(0, drillMembersArray.length, ...filteredDrillMembers);
230-
}
231-
}
232-
}
233-
234209
const type = CubeSymbols.toMemberDataType(nameToMetric[1].type);
235210

236211
return {

packages/cubejs-schema-compiler/test/integration/postgres/cube-views.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,6 @@ view(\`OrdersSimpleView\`, {
485485

486486
// Check what dimensions are actually available in this limited view
487487
const availableDimensions = cube.config.dimensions?.map(d => d.name) || [];
488-
console.log('OrdersSimpleView dimensions:', availableDimensions);
489-
console.log('OrdersSimpleView drill members:', countMeasure.drillMembers);
490488

491489
// This view only includes ['id', 'createdAt', 'count'] - should have both id and createdAt
492490
expect(availableDimensions).not.toContain('OrdersSimpleView.id');

0 commit comments

Comments
 (0)