From ec93ab534958336de8cd8e9cffcfbc7c09899ca8 Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Fri, 28 Mar 2025 16:00:03 +0200 Subject: [PATCH 1/3] chore(schema-compiler)!: Drop support for top-level includes/excludes in views --- .../src/compiler/CubeSymbols.ts | 34 +++--------------- .../src/compiler/CubeValidator.ts | 2 -- .../test/unit/views.test.ts | 36 ------------------- 3 files changed, 4 insertions(+), 68 deletions(-) diff --git a/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts b/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts index 981731a16ecdd..9c3b0a2e738d8 100644 --- a/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts +++ b/packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts @@ -282,7 +282,7 @@ export class CubeSymbols { } protected prepareIncludes(cube: CubeDefinition, errorReporter: ErrorReporter, splitViews: SplitViews) { - if (!cube.includes && !cube.cubes) { + if (!cube.cubes) { return; } @@ -324,18 +324,8 @@ export class CubeSymbols { cubeIncludes = this.membersFromCubes(cube, cubes, type, errorReporter, splitViews, memberSets) || []; } - // This is the deprecated approach - const includes = cube.includes && this.membersFromIncludeExclude(cube.includes, cube.name, type) || []; - const excludes = cube.excludes && this.membersFromIncludeExclude(cube.excludes, cube.name, type) || []; - - // cube includes will take precedence in case of member clash - const finalIncludes = this.diffByMember( - this.diffByMember(includes, cubeIncludes).concat(cubeIncludes), - excludes - ); - if (type === 'hierarchies') { - for (const member of finalIncludes) { + for (const member of cubeIncludes) { const path = member.member.split('.'); const cubeName = path[path.length - 2]; const hierarchyName = path[path.length - 1]; @@ -350,10 +340,10 @@ export class CubeSymbols { } } - const includeMembers = this.generateIncludeMembers(finalIncludes, cube.name, type); + const includeMembers = this.generateIncludeMembers(cubeIncludes, cube.name, type); this.applyIncludeMembers(includeMembers, cube, type, errorReporter); - cube.includedMembers = [...(cube.includedMembers || []), ...Array.from(new Set(finalIncludes.map((it: any) => { + cube.includedMembers = [...(cube.includedMembers || []), ...Array.from(new Set(cubeIncludes.map((it: any) => { const split = it.member.split('.'); const memberPath = this.pathFromArray([split[split.length - 2], split[split.length - 1]]); return { @@ -465,22 +455,6 @@ export class CubeSymbols { return includes.filter(include => !excludesMap.has(include.member)); } - protected membersFromIncludeExclude(referencesFn: (...args: Array) => Array, cubeName: string, type: string) { - const references = this.evaluateReferences(cubeName, referencesFn); - return R.unnest(references.map((ref: string) => { - const path = ref.split('.'); - if (path.length === 1) { - const membersObj = this.symbols[path[0]]?.cubeObj()?.[type] || {}; - return Object.keys(membersObj).map(memberName => ({ member: `${ref}.${memberName}` })); - } else if (path.length === 2) { - const resolvedMember = this.getResolvedMember(type, path[0], path[1]); - return resolvedMember ? [{ member: ref }] : undefined; - } else { - throw new Error(`Unexpected path length ${path.length} for ${ref}`); - } - })).filter(Boolean); - } - protected getResolvedMember(type: string, cubeName: string, memberName: string) { return this.symbols[cubeName]?.cubeObj()?.[type]?.[memberName]; } diff --git a/packages/cubejs-schema-compiler/src/compiler/CubeValidator.ts b/packages/cubejs-schema-compiler/src/compiler/CubeValidator.ts index dbe755aa1bb42..69e4733d72923 100644 --- a/packages/cubejs-schema-compiler/src/compiler/CubeValidator.ts +++ b/packages/cubejs-schema-compiler/src/compiler/CubeValidator.ts @@ -779,8 +779,6 @@ const cubeSchema = inherit(baseSchema, { const viewSchema = inherit(baseSchema, { isView: Joi.boolean().strict(), - includes: Joi.func(), - excludes: Joi.func(), cubes: Joi.array().items( Joi.object().keys({ joinPath: Joi.func().required(), diff --git a/packages/cubejs-schema-compiler/test/unit/views.test.ts b/packages/cubejs-schema-compiler/test/unit/views.test.ts index 3b412ee8f4841..b5b0b95e09054 100644 --- a/packages/cubejs-schema-compiler/test/unit/views.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/views.test.ts @@ -391,42 +391,6 @@ describe('Views YAML', () => { }); }); - it('includes * (legacy)', async () => { - const { cubeEvaluator } = await schemaCompile([{ - name: 'simple_view', - includes: [ - 'CubeA.id', - // conflict - // 'CubeB.id', - 'CubeB.other_id', - ] - }]); - - expect(cubeEvaluator.getCubeDefinition('simple_view').dimensions).toEqual({ - id: dimensionFixtureForCube('CubeA.id'), - other_id: dimensionFixtureForCube('CubeB.other_id'), - }); - }); - - it('includes * (legacy) + exclude b.id', async () => { - const { cubeEvaluator } = await schemaCompile([{ - name: 'simple_view', - includes: [ - 'CubeA.id', - 'CubeB.id', - 'CubeB.other_id', - ], - excludes: [ - 'CubeB.id' - ] - }]); - - expect(cubeEvaluator.getCubeDefinition('simple_view').dimensions).toEqual({ - id: dimensionFixtureForCube('CubeA.id'), - other_id: dimensionFixtureForCube('CubeB.other_id'), - }); - }); - it('throws error for unresolved members', async () => { const { compiler } = prepareYamlCompiler(` cubes: From 291ba07f943308be4697d0c8106feab4ee8ed6b3 Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Fri, 28 Mar 2025 17:19:17 +0200 Subject: [PATCH 2/3] fix view tests --- .../integration/postgres/cube-views.test.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/cubejs-schema-compiler/test/integration/postgres/cube-views.test.ts b/packages/cubejs-schema-compiler/test/integration/postgres/cube-views.test.ts index 81a70b84baa94..9b19d0dbcfd76 100644 --- a/packages/cubejs-schema-compiler/test/integration/postgres/cube-views.test.ts +++ b/packages/cubejs-schema-compiler/test/integration/postgres/cube-views.test.ts @@ -200,8 +200,19 @@ cube(\`ProductCategories\`, { }); view(\`OrdersView\`, { - includes: [Orders], - excludes: [Orders.createdAt], + cubes: [{ + join_path: Orders, + includes: '*', + excludes: ['createdAt'] + }, { + join_path: Orders.Products, + includes: '*', + prefix: true + }, { + join_path: Orders.Products.ProductCategories, + includes: '*', + prefix: true + }], measures: { productCategoryCount: { @@ -233,10 +244,6 @@ view(\`OrdersView\`, { } }); -view(\`OrdersView2\`, { - includes: [Orders.count], -}); - view(\`OrdersView3\`, { cubes: [{ join_path: Orders, From 797b914b5e6a54f250205e42fed512b640b83f05 Mon Sep 17 00:00:00 2001 From: Igor Lukanin Date: Mon, 31 Mar 2025 13:21:33 +0200 Subject: [PATCH 3/3] Update DEPRECATION --- DEPRECATION.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DEPRECATION.md b/DEPRECATION.md index a66d5d6a1282f..558232ab1089e 100644 --- a/DEPRECATION.md +++ b/DEPRECATION.md @@ -58,7 +58,7 @@ features: | Removed | [Using Redis for in-memory cache and queue](#using-redis-for-in-memory-cache-and-queue) | v0.32.0 | v0.36.0 | | Deprecated | [`SECURITY_CONTEXT`](#security_context) | v0.33.0 | | | Deprecated | [`running_total` measure type](#running_total-measure-type) | v0.33.39 | | -| Deprecated | [Top-level `includes` parameter in views](#top-level-includes-parameter-in-views) | v0.34.34 | | +| Removed | [Top-level `includes` parameter in views](#top-level-includes-parameter-in-views) | v0.34.34 | v1.3.0 | | Removed | [Node.js 16](#nodejs-16) | v0.35.0 | v0.36.0 | | Removed | [MySQL-based SQL API](#mysql-based-sql-api) | v0.35.0 | v0.35.0 | | Removed | [`initApp` hook](#initapp-hook) | v0.35.0 | v0.35.0 | @@ -350,9 +350,9 @@ to calculate running totals instead. ### Top-level `includes` parameter in views -**Deprecated in Release: v0.34.34** +**Removed in Release: v1.3.0** -The top-level `includes` parameter is now deprecated. Please always use the +The top-level `includes` parameter is now removed. Please always use the `includes` parameter within [`cubes` and `join_path` parameters](https://cube.dev/docs/reference/data-model/view#cubes) so you can explicitly control the join path.