Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
436 changes: 419 additions & 17 deletions docs/pages/guides/recipes/analytics/event-analytics.mdx

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions docs/pages/guides/recipes/data-modeling/snapshots.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ First, we need to generate a range with all dates of interest, from the earliest
to the latest. Second, we need to join the dates with the statuses and leave
only the most recent statuses to date.

<CodeTabs>

```javascript
cube(`status_snapshots`, {
extends: statuses,
Expand Down Expand Up @@ -111,6 +113,39 @@ cube(`status_snapshots`, {
});
```

```yaml
cubes:
- name: status_snapshots
extends: statuses
sql: >
-- Create a range from the earlist date to the latest date
WITH range AS (
SELECT date
FROM GENERATE_SERIES(
(SELECT MIN(changed_at) FROM {statuses.sql()} AS statuses),
(SELECT MAX(changed_at) FROM {statuses.sql()} AS statuses),
INTERVAL '1 DAY'
) AS date
)

-- Calculate snapshots for every date in the range
SELECT range.date, statuses.*
FROM range
LEFT JOIN {statuses.sql()} AS statuses
ON range.date >= statuses.changed_at
AND statuses.changed_at = (
SELECT MAX(changed_at)
FROM {statuses.sql()} AS sub_statuses
WHERE sub_statuses.order_id = statuses.order_id
)
dimensions:
date:
sql: date
type: time
```

</CodeTabs>

<InfoBox>

To generate a range of dates, here we use the
Expand Down
67 changes: 58 additions & 9 deletions docs/pages/product/data-modeling/concepts/data-blending.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ cube(`online_orders`, {

Given the above cubes, a data blending cube can be introduced as follows:

<CodeTabs>

```javascript
cube(`all_sales`, {
sql: `
Expand All @@ -136,14 +138,14 @@ cube(`all_sales`, {
user_id AS customer_id,
created_at,
'online' AS row_type
FROM (${online_orders.sql()}) AS online
FROM ${online_orders.sql()} AS online
UNION ALL
SELECT
amount,
customer_id,
created_at,
'retail' AS row_type
FROM (${retail_orders.sql()}) AS retail
FROM ${retail_orders.sql()} AS retail
`,

measures: {
Expand Down Expand Up @@ -193,16 +195,63 @@ cube(`all_sales`, {
});
```

<ReferenceBox>
```yaml
cubes:
- name: all_sales
sql: >
SELECT
amount,
user_id AS customer_id,
created_at,
'online' AS row_type
FROM {online_orders.sql()} AS online
UNION ALL
SELECT
amount,
customer_id,
created_at,
'retail' AS row_type
FROM {retail_orders.sql()} AS retail

measures:
- name: customer_count
sql: customer_id
type: count_distinct

- name: revenue
sql: amount
type: sum

- name: online_revenue
sql: amount
type: sum
filters:
- sql: "{CUBE}.row_type = 'online'"

Currently, [`{cube.sql()}` function][ref-cube-sql-func] is not supported in YAML data models.
Please [track this issue](https://github.com/cube-js/cube/issues/7484).
- name: offline_revenue
sql: amount
type: sum
filters:
- sql: "{CUBE}.row_type = 'retail'"

As a workaround, you can use JavaScript data models, put a SQL query in a
[Jinja](/product/data-modeling/dynamic/jinja#jinja) variable, or load it from
the [template context](/reference/python/cube#templatecontext-class).
- name: online_revenue_percentage
sql: >
{online_revenue} /
NULLIF({online_revenue} + {offline_revenue}, 0)
type: number
format: percent

</ReferenceBox>
dimensions:
- name: created_at
sql: created_at
type: time

- name: revenue_type
sql: row_type
type: string
```

</CodeTabs>

Another use case of the Data Blending approach would be when you want to chart
some measures (business related) together and see how they correlate.
Expand Down
28 changes: 19 additions & 9 deletions docs/pages/product/data-modeling/concepts/polymorphic-cubes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ cube(`users`, {

Then you can derive the `teachers` and `students` cubes from `users`:

<CodeTabs>

```javascript
cube(`teachers`, {
extends: users,
Expand All @@ -110,16 +112,24 @@ cube(`students`, {
});
```

<ReferenceBox>

Currently, [`{cube.sql()}` function][ref-cube-sql-func] is not supported in YAML data models.
Please [track this issue](https://github.com/cube-js/cube/issues/7484).

As a workaround, you can use JavaScript data models, put a SQL query in a
[Jinja](/product/data-modeling/dynamic/jinja#jinja) variable, or load it from
the [template context](/reference/python/cube#templatecontext-class).
```yaml
cubes:
- name: teachers
extends: users
sql: >
SELECT *
FROM {users.sql()}
WHERE type = 'teacher'

- name: students
extends: users
sql: >
SELECT *
FROM {users.sql()}
WHERE type = 'student'
```

</ReferenceBox>
</CodeTabs>

Once we have those cubes, we can define correct joins from the `lessons` cube:

Expand Down
44 changes: 29 additions & 15 deletions docs/pages/product/data-modeling/syntax.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ model
Cube supports two ways to define data model files: with [YAML][wiki-yaml] or
JavaScript syntax. YAML data model files should have the `.yml` extension,
whereas JavaScript data model files should end with `.js`. You can mix YAML and
JavaScript files within a single data model.
JavaScript files within a single data model.

<CodeTabs>

Expand Down Expand Up @@ -547,6 +547,8 @@ when defining [polymorphic cubes][ref-polymorphism] or using [data blending][ref

Consider the following data model:

<CodeTabs>

```javascript
cube(`organisms`, {
sql_table: `organisms`
Expand All @@ -564,7 +566,7 @@ cube(`dogs`, {
sql: `
SELECT *
FROM ${animals.sql()}
WHERE species = 'dogs'
WHERE species = 'dogs'
`,

measures: {
Expand All @@ -575,6 +577,30 @@ cube(`dogs`, {
})
```

```yaml
cubes:
- name: organisms
sql_table: organisms

- name: animals
sql: >
SELECT *
FROM {organisms.sql()}
WHERE kingdom = 'animals'

- name: dogs
sql: >
SELECT *
FROM {animals.sql()}
WHERE species = 'dogs'

measures:
- name: count
type: count
```

</CodeTabs>

If you query for `dogs.count`, Cube will generate the following SQL:

```sql
Expand All @@ -590,18 +616,6 @@ FROM (
) AS "dogs"
```

<ReferenceBox>

Currently, `{cube.sql()}` function is only supported in JavaScript data models.
It is not supported in YAML data models.
Please [track this issue](https://github.com/cube-js/cube/issues/7484).

As a workaround, you can use JavaScript data models, put a SQL query in a
[Jinja](/product/data-modeling/dynamic/jinja#jinja) variable, or load it from
the [template context](/reference/python/cube#templatecontext-class).

</ReferenceBox>

### Curly braces and escaping

As you can see in the examples above, within [SQL expressions][self-sql-expressions],
Expand Down Expand Up @@ -761,4 +775,4 @@ defining dynamic data models.
[ref-style-guide]: /guides/style-guide
[ref-polymorphism]: /product/data-modeling/concepts/polymorphic-cubes
[ref-data-blending]: /product/data-modeling/concepts/data-blending
[link-js-template-literals]: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/Strings#embedding_javascript
[link-js-template-literals]: https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/Strings#embedding_javascript
25 changes: 21 additions & 4 deletions docs/pages/reference/data-model/cube.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -269,18 +269,34 @@ cubes:

</CodeTabs>

With JavaScript models, you can also reference other cubes' SQL statements for
code reuse:
You can also reference other cubes' SQL statements for code reuse using the
[`{cube.sql()}`][ref-syntax-cube-sql] function:

<CodeTabs>

```javascript
cube(`companies`, {
sql: `
SELECT users.company_name, users.company_id
SELECT
users.company_name,
users.company_id
FROM ${users.sql()} AS users
`,
});
```

```yaml
cubes:
- name: companies
sql:
SELECT
users.company_name,
users.company_id
FROM {users.sql()} AS users
```

</CodeTabs>

It is recommended to prefer the [`sql_table`](#parameters-sql-table) parameter
over the `sql` parameter for all cubes that are supposed to use queries like
this: `SELECT * FROM table`.
Expand Down Expand Up @@ -626,4 +642,5 @@ The `access_policy` parameter is used to configure [data access policies][ref-re
[ref-ref-segments]: /reference/data-model/segments
[ref-ref-joins]: /reference/data-model/joins
[ref-ref-pre-aggs]: /reference/data-model/pre-aggregations
[ref-ref-dap]: /reference/data-model/data-access-policies
[ref-ref-dap]: /reference/data-model/data-access-policies
[ref-syntax-cube-sql]: /product/data-modeling/syntax#cubesql-function
4 changes: 3 additions & 1 deletion packages/cubejs-schema-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@
"coverageDirectory": "coverage/",
"collectCoverageFrom": [
"dist/src/**/*.js",
"dist/src/**/*.ts"
"dist/src/**/*.ts",
"!dist/src/parser/GenericSql*.js",
"!dist/src/parser/Python3*.js"
],
"coveragePathIgnorePatterns": [
".*\\.d\\.ts"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ testlist_comp: (test | star_expr) (
comp_for
| (COMMA (test | star_expr))* (COMMA)?
);
trailer: '(' (arglist)? ')' | '[' subscriptlist ']' | '.' NAME;
trailer: callArguments | '[' subscriptlist ']' | '.' NAME;
subscriptlist: subscript (COMMA subscript)* (COMMA)?;
subscript: test | (test)? ':' (test)? (sliceop)?;
sliceop: ':' (test)?;
Expand All @@ -251,6 +251,8 @@ dictorsetmaker: (

classdef: 'class' NAME ('(' (arglist)? ')')? ':' suite;

callArguments: '(' (arglist)? ')';

arglist: argument (COMMA argument)* (COMMA)?;

// The reason that keywords are test nodes instead of NAME is that using NAME results in an
Expand Down

Large diffs are not rendered by default.

Loading
Loading