Skip to content

Commit 22286f5

Browse files
authored
fix(schema-compiler): Allow no-cache queries to use pre-aggregations (cube-js#10440)
no-cache mode now only skips the result cache (via forceNoCache in QueryCache) but still routes queries through pre-aggregation tables when available, avoiding expensive source database queries. We initially discussed this exact behavior, but we skipped it. Skipping pre-aggregations doesn't make sense, since the cache parameter controls the in-memory cache.
1 parent 58bfe5e commit 22286f5

2 files changed

Lines changed: 85 additions & 5 deletions

File tree

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ export class BaseQuery {
771771
}
772772
const hasMemberExpressions = this.allMembersConcat(false).some(m => m.isMemberExpression);
773773

774-
if (this.options.cacheMode !== 'no-cache' && !this.options.preAggregationQuery && !this.customSubQueryJoins.length && !hasMemberExpressions) {
774+
if (!this.options.preAggregationQuery && !this.customSubQueryJoins.length && !hasMemberExpressions) {
775775
preAggForQuery =
776776
this.preAggregations.findPreAggregationForQuery();
777777
if (this.options.disableExternalPreAggregations && preAggForQuery?.preAggregation.external) {
@@ -844,10 +844,6 @@ export class BaseQuery {
844844
}
845845

846846
externalPreAggregationQuery() {
847-
if (this.options.cacheMode === 'no-cache') {
848-
return false;
849-
}
850-
851847
if (!this.options.preAggregationQuery && !this.options.disableExternalPreAggregations && this.externalQueryClass) {
852848
const preAggregationForQuery = this.preAggregations.findPreAggregationForQuery();
853849
if (preAggregationForQuery?.preAggregation.external) {

packages/cubejs-schema-compiler/test/unit/pre-aggregations.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,90 @@ describe('pre-aggregations', () => {
506506
expect(preAggregationsDescription[0].preAggregationId).toEqual('orders.simple');
507507
});
508508

509+
it('no-cache should still match pre-aggregations', async () => {
510+
const { compiler, cubeEvaluator, joinGraph } = prepareYamlCompiler(
511+
createSchemaYaml(createECommerceSchema())
512+
);
513+
514+
await compiler.compile();
515+
516+
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
517+
measures: [
518+
'orders_view.count'
519+
],
520+
timeDimensions: [{
521+
dimension: 'orders_view.created_at',
522+
granularity: 'day',
523+
dateRange: ['2023-01-01', '2023-01-10']
524+
}],
525+
timezone: 'America/Los_Angeles',
526+
cacheMode: 'no-cache',
527+
});
528+
529+
const queryPreAggs: any = query.preAggregations?.preAggregationsDescription();
530+
expect(queryPreAggs.length).toBeGreaterThan(0);
531+
expect(queryPreAggs[0].preAggregationId).toEqual('orders.orders_by_day_with_day');
532+
});
533+
534+
it('no-cache should still use external pre-aggregations', async () => {
535+
const { compiler, cubeEvaluator, joinGraph } = prepareYamlCompiler(
536+
createSchemaYaml({
537+
cubes: [
538+
{
539+
name: 'orders',
540+
sql_table: 'orders',
541+
measures: [{
542+
name: 'count',
543+
type: 'count',
544+
}],
545+
dimensions: [
546+
{
547+
name: 'created_at',
548+
sql: 'created_at',
549+
type: 'time',
550+
},
551+
{
552+
name: 'status',
553+
sql: 'status',
554+
type: 'string',
555+
}
556+
],
557+
preAggregations: [
558+
{
559+
name: 'orders_external',
560+
measures: ['count'],
561+
dimensions: ['status'],
562+
timeDimension: 'CUBE.created_at',
563+
granularity: 'day',
564+
external: true,
565+
},
566+
]
567+
}
568+
]
569+
})
570+
);
571+
572+
await compiler.compile();
573+
574+
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
575+
measures: ['orders.count'],
576+
dimensions: ['orders.status'],
577+
timeDimensions: [{
578+
dimension: 'orders.created_at',
579+
granularity: 'day',
580+
dateRange: ['2023-01-01', '2023-01-10']
581+
}],
582+
cacheMode: 'no-cache',
583+
externalQueryClass: PostgresQuery,
584+
});
585+
586+
expect(query.externalPreAggregationQuery()).toBe(true);
587+
588+
const preAggregationsDescription: any = query.preAggregations?.preAggregationsDescription();
589+
expect(preAggregationsDescription.length).toBeGreaterThan(0);
590+
expect(preAggregationsDescription[0].preAggregationId).toEqual('orders.orders_external');
591+
});
592+
509593
describe('rollup with multiplied measure', () => {
510594
let compiler;
511595
let cubeEvaluator;

0 commit comments

Comments
 (0)