|
1 | | ---- |
2 | | -redirect_from: |
3 | | - - /extending-cubes |
4 | | - - /recipes/extending-cubes |
5 | | - - /schema/advanced/extending-cubes |
6 | | ---- |
| 1 | +# Extension |
7 | 2 |
|
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. |
9 | 6 |
|
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`. |
13 | 11 |
|
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. |
31 | 15 |
|
32 | 16 | In the example below, the `base_events` cube defines the common events measures, |
33 | 17 | dimensions, and a join to the `users` cube: |
34 | 18 |
|
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 | | - |
43 | 19 | <CodeTabs> |
44 | 20 |
|
45 | 21 | ```yaml |
@@ -90,6 +66,14 @@ cube(`base_events`, { |
90 | 66 |
|
91 | 67 | </CodeTabs> |
92 | 68 |
|
| 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 | + |
93 | 77 | The `product_purchases` and `page_views` cubes are extended from `base_events` |
94 | 78 | and define only the specific dimensions: `product_name` for product purchases |
95 | 79 | and `page_path` for page views. |
@@ -145,79 +129,80 @@ cube(`page_views`, { |
145 | 129 |
|
146 | 130 | </CodeTabs> |
147 | 131 |
|
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` |
152 | 133 |
|
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. |
154 | 136 |
|
155 | | - <CodeTabs> |
| 137 | +First, the `sql` parameter can be overridden in each child cube: |
156 | 138 |
|
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> |
167 | 140 |
|
168 | | - ```javascript |
169 | | - cube(`product_purchases`, { |
170 | | - sql: ` |
| 141 | +```yaml |
| 142 | +cubes: |
| 143 | + - name: product_purchases |
| 144 | + sql: > |
171 | 145 | SELECT * |
172 | 146 | FROM events |
173 | | - WHERE ${FILTER_PARAMS.product_purchases.timestamp.filter("time")} |
174 | | - `, |
| 147 | + WHERE {FILTER_PARAMS.product_purchases.timestamp.filter('time')} |
175 | 148 |
|
176 | | - // ... |
177 | | - }); |
178 | | - ``` |
| 149 | + # ... |
| 150 | +``` |
179 | 151 |
|
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 | + `, |
181 | 159 |
|
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 | +``` |
184 | 163 |
|
185 | | - <CodeTabs> |
| 164 | +</CodeTabs> |
186 | 165 |
|
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: |
197 | 169 |
|
198 | | - # ... |
199 | | - ``` |
| 170 | +<CodeTabs> |
200 | 171 |
|
201 | | - ```javascript |
202 | | - cube(`base_events`, { |
203 | | - sql: ` |
| 172 | +```yaml |
| 173 | +cubes: |
| 174 | + - name: base_events |
| 175 | + sql: > |
204 | 176 | SELECT * |
205 | 177 | FROM events |
206 | 178 | 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 | +``` |
211 | 185 |
|
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> |
215 | 202 |
|
216 | | - </CodeTabs> |
217 | 203 |
|
218 | | -[mdn-js-objects]: |
219 | | - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object |
220 | 204 | [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 |
0 commit comments