diff --git a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js index 24b8d4ffa380b..53b3295d798c3 100644 --- a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js +++ b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js @@ -4009,7 +4009,17 @@ export class BaseQuery { const dimensionSql = this.dimensionSql(dimension); return `select ${aggFunction}(${this.convertTz(dimensionSql)}) from ${this.cubeSql(cube)} ${this.asSyntaxTable} ${this.cubeAlias(cube)}`; } - return null; + + // Handle case that requires joins + const subQuery = this.newSubQuery({ + dimensions: [dimension.dimension], + rowLimit: null, + }); + + const dimensionSql = subQuery.dimensionSql(dimension); + const fromClause = subQuery.query(); + + return `select ${aggFunction}(${subQuery.convertTz(dimensionSql)}) from ${fromClause}`; } cubeCardinalityQueries() { // TODO collect sub queries diff --git a/packages/cubejs-schema-compiler/test/integration/postgres/pre-aggregations.test.ts b/packages/cubejs-schema-compiler/test/integration/postgres/pre-aggregations.test.ts index 43fd4b6ced43b..5235d0b98917a 100644 --- a/packages/cubejs-schema-compiler/test/integration/postgres/pre-aggregations.test.ts +++ b/packages/cubejs-schema-compiler/test/integration/postgres/pre-aggregations.test.ts @@ -599,7 +599,49 @@ describe('PreAggregations', () => { } ] }); - `); + + cube('cube_pre_agg_proxy_a', { + sql: \`SELECT '2025-10-01 12:00:00'::timestamp as starts_at\`, + + dimensions: { + starts_at: { + sql: \`\${CUBE}.starts_at\`, + type: 'time' + } + } + }); + + cube('cube_pre_agg_proxy_b', { + sql: \`SELECT 'id' as id\`, + + joins: { + cube_pre_agg_proxy_a: { + relationship: 'one_to_one', + sql: '1 = 1' + } + }, + + dimensions: { + id: { + sql: \`\${CUBE}.id\`, + type: 'string', + primary_key: true + }, + + terminal_date: { + type: 'time', + sql: \`\${cube_pre_agg_proxy_a.starts_at}\` + } + }, + + pre_aggregations: { + main: { + time_dimension: terminal_date, + granularity: 'day' + } + } + }); + `); it('simple pre-aggregation', async () => { await compiler.compile(); @@ -2773,4 +2815,39 @@ describe('PreAggregations', () => { expect(loadSql[0]).not.toMatch(/GROUP BY/); expect(loadSql[0]).toMatch(/THEN 1 END `real_time_lambda_visitors__count`/); }); + + it('querying proxied to external cube pre-aggregation time-dimension', async () => { + await compiler.compile(); + + const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, { + measures: [], + dimensions: [], + timezone: 'America/Los_Angeles', + preAggregationsSchema: '', + timeDimensions: [{ + dimension: 'cube_pre_agg_proxy_b.terminal_date', + granularity: 'day', + }], + order: [], + }); + + const queryAndParams = query.buildSqlAndParams(); + console.log(queryAndParams); + const preAggregationsDescription = query.preAggregations?.preAggregationsDescription(); + console.log(JSON.stringify(preAggregationsDescription, null, 2)); + + expect((preAggregationsDescription)[0].loadSql[0]).toMatch(/main/); + + const queries = dbRunner.tempTablePreAggregations(preAggregationsDescription); + + console.log(JSON.stringify(queries.concat(queryAndParams))); + + return dbRunner.evaluateQueryWithPreAggregations(query).then(res => { + expect(res).toEqual( + [{ + cube_pre_agg_proxy_b__terminal_date_day: '2025-10-01T00:00:00.000Z', + }] + ); + }); + }); });