Skip to content

Commit 6673b23

Browse files
committed
refactor(schema-compiler): Move code around to solve circular dependency between CubeSymbols and BaseQuery
1 parent 1ce9a36 commit 6673b23

File tree

4 files changed

+57
-56
lines changed

4 files changed

+57
-56
lines changed

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

Lines changed: 6 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
timeSeriesFromCustomInterval
2525
} from '@cubejs-backend/shared';
2626

27+
import { CubeSymbols } from "../compiler/CubeSymbols";
2728
import { UserError } from '../compiler/UserError';
2829
import { SqlParser } from '../parser/SqlParser';
2930
import { BaseDimension } from './BaseDimension';
@@ -1411,7 +1412,7 @@ export class BaseQuery {
14111412
// TODO condition should something else instead of rank
14121413
multiStageQuery: !!withQuery.measures.find(d => {
14131414
const { type } = this.newMeasure(d).definition();
1414-
return type === 'rank' || BaseQuery.isCalculatedMeasureType(type);
1415+
return type === 'rank' || CubeSymbols.isCalculatedMeasureType(type);
14151416
}),
14161417
disableExternalPreAggregations: true,
14171418
};
@@ -2946,7 +2947,7 @@ export class BaseQuery {
29462947
funDef = this.countDistinctApprox(evaluateSql);
29472948
} else if (symbol.type === 'countDistinct' || symbol.type === 'count' && !symbol.sql && multiplied) {
29482949
funDef = `count(distinct ${evaluateSql})`;
2949-
} else if (BaseQuery.isCalculatedMeasureType(symbol.type)) {
2950+
} else if (CubeSymbols.isCalculatedMeasureType(symbol.type)) {
29502951
// TODO calculated measure type will be ungrouped
29512952
// if (this.multiStageDimensions.length !== this.dimensions.length) {
29522953
// throw new UserError(`Calculated measure '${measurePath}' uses group_by or reduce_by context modifiers while it isn't allowed`);
@@ -2972,23 +2973,12 @@ export class BaseQuery {
29722973
return this.primaryKeyCount(cubeName, true);
29732974
}
29742975
}
2975-
if (BaseQuery.isCalculatedMeasureType(symbol.type)) {
2976+
if (CubeSymbols.isCalculatedMeasureType(symbol.type)) {
29762977
return evaluateSql;
29772978
}
29782979
return `${symbol.type}(${evaluateSql})`;
29792980
}
29802981

2981-
static isCalculatedMeasureType(type) {
2982-
return type === 'number' || type === 'string' || type === 'time' || type === 'boolean';
2983-
}
2984-
2985-
/**
2986-
TODO: support type qualifiers on min and max
2987-
*/
2988-
static toMemberDataType(type) {
2989-
return this.isCalculatedMeasureType(type) ? type : 'number';
2990-
}
2991-
29922982
aggregateOnGroupedColumn(symbol, evaluateSql, topLevelMerge, measurePath) {
29932983
const cumulativeMeasureFilters = (this.safeEvaluateSymbolContext().cumulativeMeasureFilters || {})[measurePath];
29942984
if (cumulativeMeasureFilters) {
@@ -4095,7 +4085,7 @@ export class BaseQuery {
40954085
sqlUtils: {
40964086
convertTz: (field) => field,
40974087
},
4098-
securityContext: BaseQuery.contextSymbolsProxyFrom({}, allocateParam),
4088+
securityContext: CubeSymbols.contextSymbolsProxyFrom({}, allocateParam),
40994089
};
41004090
}
41014091

@@ -4110,41 +4100,7 @@ export class BaseQuery {
41104100
}
41114101

41124102
contextSymbolsProxy(symbols) {
4113-
return BaseQuery.contextSymbolsProxyFrom(symbols, this.paramAllocator.allocateParam.bind(this.paramAllocator));
4114-
}
4115-
4116-
static contextSymbolsProxyFrom(symbols, allocateParam) {
4117-
return new Proxy(symbols, {
4118-
get: (target, name) => {
4119-
const propValue = target[name];
4120-
const methods = (paramValue) => ({
4121-
filter: (column) => {
4122-
if (paramValue) {
4123-
const value = Array.isArray(paramValue) ?
4124-
paramValue.map(allocateParam) :
4125-
allocateParam(paramValue);
4126-
if (typeof column === 'function') {
4127-
return column(value);
4128-
} else {
4129-
return `${column} = ${value}`;
4130-
}
4131-
} else {
4132-
return '1 = 1';
4133-
}
4134-
},
4135-
requiredFilter: (column) => {
4136-
if (!paramValue) {
4137-
throw new UserError(`Filter for ${column} is required`);
4138-
}
4139-
return methods(paramValue).filter(column);
4140-
},
4141-
unsafeValue: () => paramValue
4142-
});
4143-
return methods(target)[name] ||
4144-
typeof propValue === 'object' && propValue !== null && BaseQuery.contextSymbolsProxyFrom(propValue, allocateParam) ||
4145-
methods(propValue);
4146-
}
4147-
});
4103+
return CubeSymbols.contextSymbolsProxyFrom(symbols, this.paramAllocator.allocateParam.bind(this.paramAllocator));
41484104
}
41494105

41504106
static extractFilterMembers(filter) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ export class CubeEvaluator extends CubeSymbols {
468468
ownedByCube = false;
469469
}
470470
// Aliases one to one some another member as in case of views
471-
if (!ownedByCube && !member.filters && BaseQuery.isCalculatedMeasureType(member.type) && pathReferencesUsed.length === 1 && this.pathFromArray(pathReferencesUsed[0]) === evaluatedSql) {
471+
if (!ownedByCube && !member.filters && CubeSymbols.isCalculatedMeasureType(member.type) && pathReferencesUsed.length === 1 && this.pathFromArray(pathReferencesUsed[0]) === evaluatedSql) {
472472
aliasMember = this.pathFromArray(pathReferencesUsed[0]);
473473
}
474474
const foreignCubes = cubeReferencesUsed.filter(usedCube => usedCube !== cube.name);

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { camelize } from 'inflection';
55
import { UserError } from './UserError';
66
import { DynamicReference } from './DynamicReference';
77
import { camelizeCube } from './utils';
8-
import { BaseQuery } from '../adapter';
98

109
import type { ErrorReporter } from './ErrorReporter';
1110

@@ -536,7 +535,7 @@ export class CubeSymbols {
536535
if (type === 'measures') {
537536
memberDefinition = {
538537
sql,
539-
type: BaseQuery.toMemberDataType(resolvedMember.type),
538+
type: CubeSymbols.toMemberDataType(resolvedMember.type),
540539
aggType: resolvedMember.type,
541540
meta: resolvedMember.meta,
542541
title: resolvedMember.title,
@@ -755,7 +754,7 @@ export class CubeSymbols {
755754
return Object.assign({
756755
filterParams: this.filtersProxyDep(),
757756
filterGroup: this.filterGroupFunctionDep(),
758-
securityContext: BaseQuery.contextSymbolsProxyFrom({}, (param) => param),
757+
securityContext: CubeSymbols.contextSymbolsProxyFrom({}, (param) => param),
759758
sqlUtils: {
760759
convertTz: (f) => f
761760

@@ -999,4 +998,49 @@ export class CubeSymbols {
999998
public isCurrentCube(name) {
1000999
return CURRENT_CUBE_CONSTANTS.indexOf(name) >= 0;
10011000
}
1001+
1002+
public static isCalculatedMeasureType(type: string): boolean {
1003+
return type === 'number' || type === 'string' || type === 'time' || type === 'boolean';
1004+
}
1005+
1006+
/**
1007+
TODO: support type qualifiers on min and max
1008+
*/
1009+
public static toMemberDataType(type: string): string {
1010+
return this.isCalculatedMeasureType(type) ? type : 'number';
1011+
}
1012+
1013+
public static contextSymbolsProxyFrom(symbols: object, allocateParam: (param: unknown) => unknown): object {
1014+
return new Proxy(symbols, {
1015+
get: (target, name) => {
1016+
const propValue = target[name];
1017+
const methods = (paramValue) => ({
1018+
filter: (column) => {
1019+
if (paramValue) {
1020+
const value = Array.isArray(paramValue) ?
1021+
paramValue.map(allocateParam) :
1022+
allocateParam(paramValue);
1023+
if (typeof column === 'function') {
1024+
return column(value);
1025+
} else {
1026+
return `${column} = ${value}`;
1027+
}
1028+
} else {
1029+
return '1 = 1';
1030+
}
1031+
},
1032+
requiredFilter: (column) => {
1033+
if (!paramValue) {
1034+
throw new UserError(`Filter for ${column} is required`);
1035+
}
1036+
return methods(paramValue).filter(column);
1037+
},
1038+
unsafeValue: () => paramValue
1039+
});
1040+
return methods(target)[name] ||
1041+
typeof propValue === 'object' && propValue !== null && CubeSymbols.contextSymbolsProxyFrom(propValue, allocateParam) ||
1042+
methods(propValue);
1043+
}
1044+
});
1045+
}
10021046
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import inflection from 'inflection';
22
import R from 'ramda';
33
import camelCase from 'camelcase';
44

5+
import { CubeSymbols } from './CubeSymbols';
56
import { UserError } from './UserError';
6-
import { BaseMeasure, BaseQuery } from '../adapter';
7+
import { BaseMeasure } from '../adapter';
78

89
export class CubeToMetaTransformer {
910
/**
@@ -168,7 +169,7 @@ export class CubeToMetaTransformer {
168169
cubeName, drillMembers, { originalSorting: true }
169170
)) || [];
170171

171-
const type = BaseQuery.toMemberDataType(nameToMetric[1].type);
172+
const type = CubeSymbols.toMemberDataType(nameToMetric[1].type);
172173

173174
return {
174175
name,

0 commit comments

Comments
 (0)