Skip to content

Commit 905e873

Browse files
committed
cached granularityHierarchies() for query timezone
1 parent 52e36a5 commit 905e873

File tree

3 files changed

+65
-33
lines changed

3 files changed

+65
-33
lines changed

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

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { BaseTimeDimension } from './BaseTimeDimension';
2626
import { ParamAllocator } from './ParamAllocator';
2727
import { PreAggregations } from './PreAggregations';
2828
import { SqlParser } from '../parser/SqlParser';
29+
import { Granularity } from './Granularity';
2930

3031
const DEFAULT_PREAGGREGATIONS_SCHEMA = 'stb_pre_aggregations';
3132

@@ -1379,7 +1380,47 @@ export class BaseQuery {
13791380
}
13801381

13811382
granularityHierarchies() {
1382-
return R.fromPairs(Object.keys(standardGranularitiesParents).map(k => [k, this.granularityParentHierarchy(k)]));
1383+
return this.cacheValue(
1384+
// If time dimension custom granularity in data model is defined without
1385+
// timezone information they are treated in query timezone.
1386+
// Because of that it's not possible to correctly precalculate
1387+
// granularities hierarchies on startup as they are specific for each timezone.
1388+
['granularityHierarchies', this.timezone],
1389+
() => R.reduce(
1390+
(hierarchies, cube) => R.reduce(
1391+
(acc, [tdName, td]) => {
1392+
const dimensionKey = `${cube}.${tdName}`;
1393+
1394+
// constructing standard granularities for time dimension
1395+
const standardEntries = R.fromPairs(
1396+
R.keys(standardGranularitiesParents).map(gr => [
1397+
`${dimensionKey}.${gr}`,
1398+
standardGranularitiesParents[gr],
1399+
]),
1400+
);
1401+
1402+
// If we have custom granularities in time dimension
1403+
const customEntries = td.granularities
1404+
? R.fromPairs(
1405+
R.keys(td.granularities).map(granularityName => {
1406+
const grObj = new Granularity(this, { dimension: dimensionKey, granularity: granularityName });
1407+
return [
1408+
`${dimensionKey}.${granularityName}`,
1409+
[granularityName, ...standardGranularitiesParents[grObj.minGranularity()]],
1410+
];
1411+
}),
1412+
)
1413+
: {};
1414+
1415+
return R.mergeRight(acc, standardEntries, customEntries);
1416+
},
1417+
hierarchies,
1418+
R.toPairs(this.cubeEvaluator.timeDimensionsForCube(cube)),
1419+
),
1420+
{},
1421+
R.keys(this.cubeEvaluator.evaluatedCubes),
1422+
),
1423+
);
13831424
}
13841425

13851426
granularityParentHierarchy(granularity) {
@@ -1646,7 +1687,8 @@ export class BaseQuery {
16461687

16471688
/**
16481689
*
1649-
* @param {{sql: string, on: {cubeName: string, expression: Function}, joinType: 'LEFT' | 'INNER', alias: string}} customJoin
1690+
* @param {{sql: string, on: {cubeName: string, expression: Function}, joinType: 'LEFT' | 'INNER', alias: string}}
1691+
* customJoin
16501692
* @returns {JoinItem}
16511693
*/
16521694
customSubQueryJoin(customJoin) {

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

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -439,14 +439,14 @@ export class PreAggregations {
439439
static sortTimeDimensionsWithRollupGranularity(timeDimensions) {
440440
return timeDimensions && R.sortBy(
441441
R.prop(0),
442-
timeDimensions.map(d => [d.expressionPath(), d.rollupGranularity(), d.granularityObj?.minGranularity()])
442+
timeDimensions.map(d => [d.expressionPath(), d.rollupGranularity()])
443443
) || [];
444444
}
445445

446446
static timeDimensionsAsIs(timeDimensions) {
447447
return timeDimensions && R.sortBy(
448448
R.prop(0),
449-
timeDimensions.map(d => [d.expressionPath(), d.resolvedGranularity(), d.granularityObj?.minGranularity()]),
449+
timeDimensions.map(d => [d.expressionPath(), d.resolvedGranularity()]),
450450
) || [];
451451
}
452452

@@ -536,9 +536,7 @@ export class PreAggregations {
536536
backAlias(references.sortedTimeDimensions || sortTimeDimensions(references.timeDimensions));
537537
const qryTimeDimensions = references.allowNonStrictDateRangeMatch
538538
? transformedQuery.timeDimensions
539-
: transformedQuery.sortedTimeDimensions.map(t => t.slice(0, 2));
540-
// slices above/below are used to exclude granularity on 3rd position returned from sortTimeDimensionsWithRollupGranularity()
541-
const qryDimensions = transformedQuery.timeDimensions.map(t => t.slice(0, 2));
539+
: transformedQuery.sortedTimeDimensions;
542540
const backAliasMeasures = backAlias(references.measures);
543541
const backAliasSortedDimensions = backAlias(references.sortedDimensions || references.dimensions);
544542
const backAliasDimensions = backAlias(references.dimensions);
@@ -550,7 +548,7 @@ export class PreAggregations {
550548
R.equals(qryTimeDimensions, refTimeDimensions)
551549
) && (
552550
transformedQuery.isAdditive ||
553-
R.equals(qryDimensions, refTimeDimensions)
551+
R.equals(transformedQuery.timeDimensions, refTimeDimensions)
554552
) && (
555553
filterDimensionsSingleValueEqual &&
556554
references.dimensions.length === filterDimensionsSingleValueEqual.size &&
@@ -566,28 +564,13 @@ export class PreAggregations {
566564

567565
/**
568566
* Expand granularity into array of granularity hierarchy.
569-
* resolvedGranularity might be a custom granularity name, in this case
570-
* we insert it into all expanded hierarchies using its minimal granularity passed
571-
* as minGranularity param
572-
* @param {string} resolvedGranularity
573-
* @param {string} minGranularity
567+
* @param {string} granularity Granularity full path in the form of `cube.timeDimension.granularity`
574568
* @returns {Array<string>}
575569
*/
576-
const expandGranularity = (resolvedGranularity, minGranularity) => {
577-
if (!resolvedGranularity) {
578-
return [];
579-
}
580-
581-
let predefinedHierarchy = transformedQuery.granularityHierarchies[resolvedGranularity];
582-
583-
if (predefinedHierarchy) {
584-
return predefinedHierarchy;
585-
}
586-
587-
predefinedHierarchy = transformedQuery.granularityHierarchies[minGranularity];
588-
// Custom granularity should be the first in list for exact match hit
589-
return [resolvedGranularity, ...predefinedHierarchy];
590-
};
570+
const expandGranularity = (granularity) => (
571+
transformedQuery.granularityHierarchies[granularity] ||
572+
[granularity]
573+
);
591574

592575
/**
593576
* Determine whether time dimensions match to the window granularity or not.
@@ -619,8 +602,8 @@ export class PreAggregations {
619602
* @returns {Array<Array<string>>}
620603
*/
621604
const expandTimeDimension = (timeDimension) => {
622-
const [dimension, resolvedGranularity, minGranularity] = timeDimension;
623-
return expandGranularity(resolvedGranularity, minGranularity)
605+
const [dimension, resolvedGranularity] = timeDimension;
606+
return expandGranularity(`${dimension}.${resolvedGranularity}`)
624607
.map((newGranularity) => [dimension, newGranularity]);
625608
};
626609

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ export class CubeEvaluator extends CubeSymbols {
448448

449449
public timeDimensionPathsForCube(cube: any) {
450450
return R.compose(
451-
R.map(nameToDefinition => `${cube}.${nameToDefinition[0]}`),
452-
R.toPairs,
451+
R.map(dimName => `${cube}.${dimName}`),
452+
R.keys,
453453
// @ts-ignore
454454
R.filter((d: any) => d.type === 'time')
455455
// @ts-ignore
@@ -460,12 +460,19 @@ export class CubeEvaluator extends CubeSymbols {
460460
return this.cubeFromPath(cube).measures || {};
461461
}
462462

463+
public timeDimensionsForCube(cube) {
464+
return R.filter(
465+
(d: any) => d.type === 'time',
466+
this.cubeFromPath(cube).dimensions || {}
467+
);
468+
}
469+
463470
public preAggregationsForCube(path: string) {
464471
return this.cubeFromPath(path).preAggregations || {};
465472
}
466473

467474
/**
468-
* Returns pre-aggregations filtered by the spcified selector.
475+
* Returns pre-aggregations filtered by the specified selector.
469476
* @param {{
470477
* scheduled: boolean,
471478
* dataSource: Array<string>,

0 commit comments

Comments
 (0)