Skip to content

Commit 62c542f

Browse files
committed
fix(schema-compiler): Fix queries with time dimensions without granularities don't hit pre-aggregations with allow_non_strict_date_range_match=true
1 parent dcd283a commit 62c542f

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

packages/cubejs-schema-compiler/src/adapter/BaseTimeDimension.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class BaseTimeDimension extends BaseFilter {
3939
}
4040

4141
// TODO: find and fix all hidden references to granularity to rely on granularityObj instead?
42-
public get granularity(): string | undefined {
42+
public get granularity(): string | null | undefined {
4343
return this.granularityObj?.granularity;
4444
}
4545

@@ -217,7 +217,7 @@ export class BaseTimeDimension extends BaseFilter {
217217
return this.query.dateTimeCast(this.query.paramAllocator.allocateParam(this.dateRange ? this.dateToFormatted() : BUILD_RANGE_END_LOCAL));
218218
}
219219

220-
public dateRangeGranularity() {
220+
public dateRangeGranularity(): string | null {
221221
if (!this.dateRange) {
222222
return null;
223223
}
@@ -262,7 +262,7 @@ export class BaseTimeDimension extends BaseFilter {
262262
}
263263

264264
public resolvedGranularity() {
265-
return this.granularityObj?.resolvedGranularity();
265+
return this.granularityObj ? this.granularityObj.resolvedGranularity() : this.dateRangeGranularity();
266266
}
267267

268268
public isPredefinedGranularity(): boolean {

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -439,18 +439,34 @@ export class PreAggregations {
439439
static sortTimeDimensionsWithRollupGranularity(timeDimensions) {
440440
return timeDimensions && R.sortBy(
441441
R.prop(0),
442-
timeDimensions.map(d => (d.isPredefinedGranularity() ?
443-
[d.expressionPath(), d.rollupGranularity(), null] :
444-
// For custom granularities we need to add its name to the list (for exact matches)
445-
[d.expressionPath(), d.rollupGranularity(), d.granularity]
446-
))
442+
timeDimensions.map(d => {
443+
const res = [d.expressionPath(), d.rollupGranularity()];
444+
if (d.isPredefinedGranularity()) {
445+
res.push(null);
446+
} else if (d.granularity && d.granularity !== res[1]) {
447+
// For custom granularities we need to add its name to the list (for exact matches)
448+
res.push(d.granularity);
449+
}
450+
return res;
451+
})
447452
) || [];
448453
}
449454

450455
static timeDimensionsAsIs(timeDimensions) {
451456
return timeDimensions && R.sortBy(
452457
R.prop(0),
453-
timeDimensions.map(d => [d.expressionPath(), d.granularity]),
458+
timeDimensions.map(d => {
459+
const res = [d.expressionPath()];
460+
const resolvedGranularity = d.resolvedGranularity();
461+
if (d.granularity && d.granularity !== resolvedGranularity) {
462+
// For custom granularities we need to add its name to the list (for exact matches)
463+
res.push(...[resolvedGranularity, d.granularity]);
464+
} else {
465+
// For query timeDimension without granularity we pass the resolved from dataRange as fallback
466+
res.push(resolvedGranularity);
467+
}
468+
return res;
469+
}),
454470
) || [];
455471
}
456472

@@ -628,13 +644,15 @@ export class PreAggregations {
628644
* @returns {Array<Array<string>>}
629645
*/
630646
const expandTimeDimension = (timeDimension) => {
631-
const [dimension, granularity, customGranularity] = timeDimension;
647+
const [dimension, granularity, customOrResolvedGranularity] = timeDimension;
632648
const res = expandGranularity(granularity)
633649
.map((newGranularity) => [dimension, newGranularity]);
634650

635-
if (customGranularity) {
651+
if (customOrResolvedGranularity) {
636652
// For custom granularities we add it upfront to the list (for exact matches)
637-
res.unshift([dimension, customGranularity]);
653+
// For queries with timeDimension but without granularity specified we use resolved
654+
// granularity from date range
655+
res.unshift([dimension, customOrResolvedGranularity]);
638656
}
639657

640658
return res;

packages/cubejs-schema-compiler/test/integration/postgres/pre-aggregations.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ describe('PreAggregations', () => {
229229
dimensions: [sourceAndId, source],
230230
timeDimension: createdAt,
231231
granularity: 'hour',
232+
allowNonStrictDateRangeMatch: true
232233
},
233234
visitorsMultiplied: {
234235
measures: [count],
@@ -546,6 +547,33 @@ describe('PreAggregations', () => {
546547
});
547548
}));
548549

550+
it('simple pre-aggregation (with no granularity in query)', () => compiler.compile().then(() => {
551+
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
552+
measures: [
553+
'visitors.count'
554+
],
555+
timeDimensions: [{
556+
dimension: 'visitors.createdAt',
557+
dateRange: ['2017-01-01 00:00:00.000', '2017-01-29 22:59:59.999']
558+
}],
559+
timezone: 'America/Los_Angeles',
560+
preAggregationsSchema: ''
561+
});
562+
563+
const queryAndParams = query.buildSqlAndParams();
564+
console.log(queryAndParams);
565+
expect(query.preAggregations?.preAggregationForQuery?.canUsePreAggregation).toEqual(true);
566+
expect(queryAndParams[0]).toMatch(/visitors_source_and_id_rollup/);
567+
568+
return dbRunner.evaluateQueryWithPreAggregations(query).then(res => {
569+
expect(res).toEqual(
570+
[{
571+
visitors__count: '5'
572+
}]
573+
);
574+
});
575+
}));
576+
549577
it('leaf measure pre-aggregation', () => compiler.compile().then(() => {
550578
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
551579
measures: [

0 commit comments

Comments
 (0)