Skip to content

Commit e68530a

Browse files
feat(schema-compiler): Support view extends (#9507)
* restructure validation schemas (for hierarchies and folders) * remove unneeded * feat(schema-compiler): Support folders via views extends * tests fix/improve * make extend of all the things in the view * update tests * upd tests * Add docs * update snapshot --------- Co-authored-by: Igor Lukanin <[email protected]>
1 parent 4098c28 commit e68530a

File tree

13 files changed

+664
-324
lines changed

13 files changed

+664
-324
lines changed

docs/pages/product/data-modeling/concepts/_meta.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
"calculated-members": "Calculated members",
3-
"code-reusability-extending-cubes": "Extending cubes",
3+
"code-reusability-extending-cubes": "Extension",
44
"polymorphic-cubes": "Polymorphic cubes",
55
"data-blending": "Data blending",
66
"working-with-joins": "Working with joins"
Lines changed: 76 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,21 @@
1-
---
2-
redirect_from:
3-
- /extending-cubes
4-
- /recipes/extending-cubes
5-
- /schema/advanced/extending-cubes
6-
---
1+
# Extension
72

8-
# Extending cubes
3+
The `extends` parameter, supported for [cubes][ref-cube-extends] and
4+
[views][ref-view-extends], allows you to create a _child_ cube (or a view) that reuses
5+
all declared members of a _parent_ cube (or a view). This helps build reusable data models.
96

10-
Cube supports the [`extends` feature][ref-schema-ref-cube-extends], which allows
11-
you to create a cube that reuses all declared members of another cube. This is a
12-
foundation for building reusable data models.
7+
Cubes declare members such as measures, dimensions, and segments. When a child cube extends
8+
the parent cube, lists of measures, dimensions, and segments are merged.
9+
For example, if the parent cube defines the `a` measure and the child cube defines the `b`
10+
measure, the resulting cube will have both measures `a` and `b`.
1311

14-
[Cubes][ref-schema-concepts-cubes] are represented as [JavaScript
15-
objects][mdn-js-objects] with such properties as measures, dimensions, and
16-
segments. Extending in Cube works similarly to JavaScript’s prototype
17-
inheritance. Measures, dimensions, and segments are merged as separate objects.
18-
So if the base cube defines measure `a` and the extending cube defines measure
19-
`b`, the resulting cube will have both measures `a` and `b`.
20-
21-
The usual pattern is to **extract common measures, dimensions, and joins into
22-
the base cube** and then **extend from the base cube**. This helps to prevent
23-
code duplication and makes code easier to maintain and refactor.
24-
25-
<ReferenceBox>
26-
27-
Currently, the `extends` parameter does not pass the joins.
28-
Please [track this issue](https://github.com/cube-js/cube/issues/7137).
29-
30-
</ReferenceBox>
12+
The usual pattern is to extract common measures, dimensions, and joins into
13+
the parent cube and then extend from it. This helps prevent code duplication
14+
and makes code easier to maintain and refactor.
3115

3216
In the example below, the `base_events` cube defines the common events measures,
3317
dimensions, and a join to the `users` cube:
3418

35-
<InfoBox>
36-
37-
It’s important to use the `CUBE` reference when referencing properties on the
38-
cube. Not specifying the cube name or using `${base_events}` does not work when
39-
the cube is extended.
40-
41-
</InfoBox>
42-
4319
<CodeTabs>
4420

4521
```yaml
@@ -90,6 +66,14 @@ cube(`base_events`, {
9066

9167
</CodeTabs>
9268

69+
<InfoBox>
70+
71+
It’s important to use the [`CUBE` variable][ref-cube-variable] when referencing members
72+
and columns of the cube. Not specifying the cube name or using `${base_events}` does not
73+
work when the cube is extended.
74+
75+
</InfoBox>
76+
9377
The `product_purchases` and `page_views` cubes are extended from `base_events`
9478
and define only the specific dimensions: `product_name` for product purchases
9579
and `page_path` for page views.
@@ -145,79 +129,80 @@ cube(`page_views`, {
145129

146130
</CodeTabs>
147131

148-
## Usage with FILTER_PARAMS
149-
150-
If the base cube is using [`FILTER_PARAMS`][ref-schema-ref-cube-filter-params]
151-
in any `sql` property, then extending cubes can do one of two things:
132+
## Usage with `FILTER_PARAMS`
152133

153-
- Override the `sql` property in each target cube.
134+
If the parent cube is using [`FILTER_PARAMS`][ref-schema-ref-cube-filter-params]
135+
in any `sql` parameter, then child cubes can accomodate to that in two ways.
154136

155-
<CodeTabs>
137+
First, the `sql` parameter can be overridden in each child cube:
156138

157-
```yaml
158-
cubes:
159-
- name: product_purchases
160-
sql: >
161-
SELECT *
162-
FROM events
163-
WHERE {FILTER_PARAMS.product_purchases.timestamp.filter('time')}
164-
165-
# ...
166-
```
139+
<CodeTabs>
167140

168-
```javascript
169-
cube(`product_purchases`, {
170-
sql: `
141+
```yaml
142+
cubes:
143+
- name: product_purchases
144+
sql: >
171145
SELECT *
172146
FROM events
173-
WHERE ${FILTER_PARAMS.product_purchases.timestamp.filter("time")}
174-
`,
147+
WHERE {FILTER_PARAMS.product_purchases.timestamp.filter('time')}
175148
176-
// ...
177-
});
178-
```
149+
# ...
150+
```
179151

180-
</CodeTabs>
152+
```javascript
153+
cube(`product_purchases`, {
154+
sql: `
155+
SELECT *
156+
FROM events
157+
WHERE ${FILTER_PARAMS.product_purchases.timestamp.filter("time")}
158+
`,
181159

182-
- Put all filters inside the base cube and reference all specific cubes filters
183-
using `AND`. The unused filters will be rendered to `1 = 1` in the SQL query.
160+
// ...
161+
});
162+
```
184163

185-
<CodeTabs>
164+
</CodeTabs>
186165

187-
```yaml
188-
cubes:
189-
- name: base_events
190-
sql: >
191-
SELECT *
192-
FROM events
193-
WHERE
194-
{FILTER_PARAMS.base_events.timestamp.filter('time')} AND
195-
{FILTER_PARAMS.product_purchases.timestamp.filter('time')} AND
196-
{FILTER_PARAMS.page_views.timestamp.filter('time')}
166+
Alternatively, all filters can be put inside the parent cube and referenced
167+
in the child cubes using `AND`. The unused filters will be rendered to `1 = 1`
168+
in the SQL query:
197169

198-
# ...
199-
```
170+
<CodeTabs>
200171

201-
```javascript
202-
cube(`base_events`, {
203-
sql: `
172+
```yaml
173+
cubes:
174+
- name: base_events
175+
sql: >
204176
SELECT *
205177
FROM events
206178
WHERE
207-
{$FILTER_PARAMS.base_events.timestamp.filter('time')} AND
208-
{$FILTER_PARAMS.product_purchases.timestamp.filter('time')} AND
209-
{$FILTER_PARAMS.page_views.timestamp.filter('time')}
210-
`,
179+
{FILTER_PARAMS.base_events.timestamp.filter('time')} AND
180+
{FILTER_PARAMS.product_purchases.timestamp.filter('time')} AND
181+
{FILTER_PARAMS.page_views.timestamp.filter('time')}
182+
183+
# ...
184+
```
211185

212-
// ...
213-
});
214-
```
186+
```javascript
187+
cube(`base_events`, {
188+
sql: `
189+
SELECT *
190+
FROM events
191+
WHERE
192+
{$FILTER_PARAMS.base_events.timestamp.filter('time')} AND
193+
{$FILTER_PARAMS.product_purchases.timestamp.filter('time')} AND
194+
{$FILTER_PARAMS.page_views.timestamp.filter('time')}
195+
`,
196+
197+
// ...
198+
});
199+
```
200+
201+
</CodeTabs>
215202

216-
</CodeTabs>
217203

218-
[mdn-js-objects]:
219-
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
220204
[ref-schema-concepts-cubes]: /product/data-modeling/concepts#cubes
221-
[ref-schema-ref-cube-extends]: /reference/data-model/cube#extends
222-
[ref-schema-ref-cube-filter-params]:
223-
/reference/data-model/cube#filter-params
205+
[ref-cube-extends]: /reference/data-model/cube#extends
206+
[ref-view-extends]: /reference/data-model/view#extends
207+
[ref-schema-ref-cube-filter-params]: /reference/data-model/cube#filter-params
208+
[ref-cube-variable]: /product/data-modeling/syntax#cube-variable

docs/pages/reference/data-model/cube.mdx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,10 @@ all member names including pre-aggregation table names.
138138

139139
### `extends`
140140

141-
You can extend cubes in order to reuse all declared members of a cube. In the
142-
example below, `extended_order_facts` will reuse the `sql` and `count` measures
141+
You can use the `extends` parameter to [extend cubes][ref-extension] in order to reuse
142+
all declared members of a cube.
143+
144+
In the example below, `extended_order_facts` will reuse the `sql` and `count` measures
143145
from `order_facts`:
144146

145147
<CodeTabs>
@@ -326,12 +328,14 @@ cubes:
326328
327329
### `title`
328330

329-
Use `title` to change the display name of the cube. By default, Cube will
330-
humanize the cube's name, so for instance, `users_orders` would become
331-
`Users Orders`. If default humanizing doesn't work in your case, please use the
332-
title parameter. It is highly recommended to give human readable names to your
333-
cubes. It will help everyone on a team better understand the data structure and
334-
will help maintain a consistent set of definitions across an organization.
331+
Use the `title` parameter to change the display name of the cube.
332+
333+
By default, Cube will humanize the cube's name, so for instance, `users_orders`
334+
would become `Users Orders`. If default humanizing doesn't work in your case,
335+
please use the `title` parameter. It is highly recommended to give human readable
336+
names to your cubes. It will help everyone on a team better understand the data
337+
structure and will help maintain a consistent set of definitions across an
338+
organization.
335339

336340
<CodeTabs>
337341

@@ -645,3 +649,4 @@ The `access_policy` parameter is used to configure [data access policies][ref-re
645649
[ref-ref-pre-aggs]: /reference/data-model/pre-aggregations
646650
[ref-ref-dap]: /reference/data-model/data-access-policies
647651
[ref-syntax-cube-sql]: /product/data-modeling/syntax#cubesql-function
652+
[ref-extension]: /product/data-modeling/concepts/code-reusability-extending-cubes

0 commit comments

Comments
 (0)