From d458f4fb46a2ecdafd4c6b275ba57a5d3e9606b5 Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Wed, 23 Apr 2025 13:10:51 +0300 Subject: [PATCH 1/2] fix(schema-compiler): Fix not working timeshift in views --- .../cubejs-schema-compiler/src/compiler/CubeSymbols.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts b/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts index d5739e117b0dd..06bdcac184709 100644 --- a/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts +++ b/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts @@ -541,22 +541,28 @@ export class CubeSymbols { title: resolvedMember.title, description: resolvedMember.description, format: resolvedMember.format, + ...(resolvedMember.multiStage && { multiStage: resolvedMember.multiStage }), + ...(resolvedMember.timeShift && { timeShift: resolvedMember.timeShift }), + ...(resolvedMember.orderBy && { orderBy: resolvedMember.orderBy }), }; } else if (type === 'dimensions') { memberDefinition = { - ...(resolvedMember.granularities ? { granularities: resolvedMember.granularities } : {}), sql, type: resolvedMember.type, meta: resolvedMember.meta, title: resolvedMember.title, description: resolvedMember.description, format: resolvedMember.format, + ...(resolvedMember.granularities ? { granularities: resolvedMember.granularities } : {}), + ...(resolvedMember.multiStage && { multiStage: resolvedMember.multiStage }), }; } else if (type === 'segments') { memberDefinition = { sql, meta: resolvedMember.meta, + title: resolvedMember.title, description: resolvedMember.description, + aliases: resolvedMember.aliases, }; } else if (type === 'hierarchies') { memberDefinition = { From e9a9a0aaf95969afeef4e9ff3830d3de600e134c Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Wed, 23 Apr 2025 13:38:30 +0300 Subject: [PATCH 2/2] add tests --- .../unit/__snapshots__/schema.test.ts.snap | 61 +++++++++++++++++++ .../test/unit/base-query.test.ts | 4 +- .../test/unit/schema.test.ts | 15 ++++- .../cubejs-schema-compiler/test/unit/utils.ts | 11 +++- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/packages/cubejs-schema-compiler/test/unit/__snapshots__/schema.test.ts.snap b/packages/cubejs-schema-compiler/test/unit/__snapshots__/schema.test.ts.snap index 3461e646eac5c..69aa7248564fb 100644 --- a/packages/cubejs-schema-compiler/test/unit/__snapshots__/schema.test.ts.snap +++ b/packages/cubejs-schema-compiler/test/unit/__snapshots__/schema.test.ts.snap @@ -1347,3 +1347,64 @@ Array [ }, ] `; + +exports[`Schema Testing Views extends custom granularities and timeshifts 1`] = ` +Object { + "aliasMember": "orders.createdAt", + "description": undefined, + "format": undefined, + "granularities": Object { + "half_year": Object { + "interval": "6 months", + "title": "6 month intervals", + }, + "half_year_by_1st_april": Object { + "interval": "6 months", + "offset": "3 months", + "title": "Half year from Apr to Oct", + }, + "half_year_by_1st_june": Object { + "interval": "6 months", + "origin": "2020-06-01 10:00:00", + }, + "half_year_by_1st_march": Object { + "interval": "6 months", + "origin": "2020-03-01", + }, + }, + "meta": undefined, + "ownedByCube": false, + "sql": [Function], + "title": undefined, + "type": "time", +} +`; + +exports[`Schema Testing Views extends custom granularities and timeshifts 2`] = ` +Object { + "aggType": "count", + "aliasMember": "orders.count_shifted_year", + "description": undefined, + "format": undefined, + "meta": undefined, + "multiStage": true, + "ownedByCube": false, + "sql": [Function], + "timeShift": Array [ + Object { + "interval": "1 year", + "timeDimension": [Function], + "type": "prior", + }, + ], + "timeShiftReferences": Array [ + Object { + "interval": "1 year", + "timeDimension": "createdAt", + "type": "prior", + }, + ], + "title": undefined, + "type": "number", +} +`; diff --git a/packages/cubejs-schema-compiler/test/unit/base-query.test.ts b/packages/cubejs-schema-compiler/test/unit/base-query.test.ts index bfa9a12bf5b9c..3fc1822f338c4 100644 --- a/packages/cubejs-schema-compiler/test/unit/base-query.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/base-query.test.ts @@ -3,7 +3,7 @@ import { BaseQuery, PostgresQuery, MssqlQuery, UserError, CubeStoreQuery } from import { prepareJsCompiler, prepareYamlCompiler } from './PrepareCompiler'; import { createCubeSchema, - createCubeSchemaWithCustomGranularities, + createCubeSchemaWithCustomGranularitiesAndTimeShift, createCubeSchemaYaml, createECommerceSchema, createJoinedCubesSchema, @@ -421,7 +421,7 @@ describe('SQL Generation', () => { describe('Custom granularities', () => { const compilers = /** @type Compilers */ prepareJsCompiler( - createCubeSchemaWithCustomGranularities('orders') + createCubeSchemaWithCustomGranularitiesAndTimeShift('orders') ); const granularityQueries = [ diff --git a/packages/cubejs-schema-compiler/test/unit/schema.test.ts b/packages/cubejs-schema-compiler/test/unit/schema.test.ts index ec9afb6a16dd2..dd16b2b6e12b5 100644 --- a/packages/cubejs-schema-compiler/test/unit/schema.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/schema.test.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import { prepareCompiler, prepareJsCompiler } from './PrepareCompiler'; -import { createCubeSchema, createCubeSchemaWithCustomGranularities, createCubeSchemaWithAccessPolicy } from './utils'; +import { createCubeSchema, createCubeSchemaWithCustomGranularitiesAndTimeShift, createCubeSchemaWithAccessPolicy } from './utils'; const CUBE_COMPONENTS = ['dimensions', 'measures', 'segments', 'hierarchies', 'preAggregations', 'accessPolicy']; @@ -382,7 +382,7 @@ describe('Schema Testing', () => { it('custom granularities in meta', async () => { const { compiler, metaTransformer } = prepareJsCompiler([ - createCubeSchemaWithCustomGranularities('orders') + createCubeSchemaWithCustomGranularitiesAndTimeShift('orders') ]); await compiler.compile(); @@ -521,6 +521,17 @@ describe('Schema Testing', () => { }); describe('Views', () => { + it('extends custom granularities and timeshifts', async () => { + const { compiler, metaTransformer } = prepareJsCompiler([ + createCubeSchemaWithCustomGranularitiesAndTimeShift('orders') + ]); + await compiler.compile(); + + const { measures, dimensions } = metaTransformer.cubeEvaluator.evaluatedCubes.orders_view; + expect(dimensions.createdAt).toMatchSnapshot(); + expect(measures.count_shifted_year).toMatchSnapshot(); + }); + it('throws errors for incorrect referenced includes members', async () => { const orders = fs.readFileSync( path.join(process.cwd(), '/test/unit/fixtures/orders.js'), diff --git a/packages/cubejs-schema-compiler/test/unit/utils.ts b/packages/cubejs-schema-compiler/test/unit/utils.ts index 4ad63e5538b3a..e5a2e9988df74 100644 --- a/packages/cubejs-schema-compiler/test/unit/utils.ts +++ b/packages/cubejs-schema-compiler/test/unit/utils.ts @@ -224,7 +224,7 @@ export function createCubeSchemaWithAccessPolicy(name: string, extraPolicies: st `; } -export function createCubeSchemaWithCustomGranularities(name: string): string { +export function createCubeSchemaWithCustomGranularitiesAndTimeShift(name: string): string { return `cube('${name}', { sql: 'select * from orders', public: true, @@ -293,6 +293,15 @@ export function createCubeSchemaWithCustomGranularities(name: string): string { count: { type: 'count' }, + count_shifted_year: { + type: 'count', + multiStage: true, + timeShift: [{ + timeDimension: \`createdAt\`, + interval: '1 year', + type: 'prior' + }] + }, rollingCountByTrailing2Day: { type: 'count', rollingWindow: {