Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6c3fcde
feat: add links, html, and synthetic dimension parameters documentation
cursoragent May 10, 2026
e97d76a
fix: remove html section, implement only links per request
cursoragent May 10, 2026
b403976
feat: implement links feature in schema compiler and API gateway
cursoragent May 10, 2026
779d1e8
refactor: treat link url as standard SQL expression, not a template
cursoragent May 10, 2026
ac4dafa
feat: add Tesseract (native SQL planner) support for links
cursoragent May 10, 2026
ec31cae
refactor: implement links as synthetic dimensions instead of flag-bas…
cursoragent May 13, 2026
6330769
feat: add name property to links, use it in synthetic dimension naming
cursoragent May 14, 2026
0b09261
feat: auto-include synthetic link dimensions when member is included …
cursoragent May 14, 2026
8405f07
refactor: generate synthetic link dims after include/exclude logic
cursoragent May 17, 2026
dd73d3b
feat: implement links feature for dimensions in the data model
cursoragent May 19, 2026
8df11cf
fix: handle link.name as function (YAML compiler wraps strings as tem…
cursoragent May 20, 2026
f834198
fix: mutate dimensions object in place instead of reassigning
cursoragent May 20, 2026
093b684
fix: use SQL || concatenation in test instead of CONCAT()
cursoragent May 20, 2026
f153226
fix: simplify test URL expressions to avoid Python parser issues
cursoragent May 20, 2026
cefc527
fix: correct test assertion - link name is send_email not email
cursoragent May 20, 2026
4377e5f
fix: correct test assertions for link names and simplify validation test
cursoragent May 20, 2026
5d15a9a
fix: replace SQL generation test with dimension existence check
cursoragent May 20, 2026
9c97103
feat: make link dimensions public, validate name as identifier, add a…
cursoragent May 21, 2026
fa6fc33
fix: add non-null assertions for strict TS checks in test
cursoragent May 22, 2026
d7bbe3d
feat: add dashboard parameter to links
cursoragent May 24, 2026
3d917c3
feat: params as SQL expressions with urlEncode in generated URL
cursoragent May 25, 2026
606156f
test: add params integration test for link URL generation with urlEncode
cursoragent May 25, 2026
28c5e17
fix: change params from object map to array of {key, value} for prope…
cursoragent May 25, 2026
4059709
feat: add native urlEncode for Databricks and Athena/Presto
cursoragent May 27, 2026
1eac7b8
test: add smoke test for links consumed through views
cursoragent May 27, 2026
b265308
ci: add smoke:links to CI integration-smoke test suite
cursoragent May 28, 2026
4ff38e1
fix: skip 'view defines own member' error for synthetic link dimensions
cursoragent May 28, 2026
cf7b838
fix: generate synthetic link dims on source cube before view includes
cursoragent May 28, 2026
2d666ea
fix: wrap dashboard path in SQL string quotes
cursoragent May 28, 2026
38cc574
fix: use inline SQL in smoke test fixture and simplify query test
cursoragent May 28, 2026
ac82984
fix: correct meta API URL in smoke test (apiUrl already includes /cub…
cursoragent May 28, 2026
6a0c95e
fix: propagate links and synthetic metadata to view dimensions, simpl…
cursoragent May 28, 2026
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
4 changes: 4 additions & 0 deletions .github/actions/smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,7 @@ echo "::endgroup::"
echo "::group::RBAC GraphQL"
yarn lerna run --concurrency 1 --stream --no-prefix smoke:rbac-graphql
echo "::endgroup::"

echo "::group::Links"
yarn lerna run --concurrency 1 --stream --no-prefix smoke:links
echo "::endgroup::"
5 changes: 3 additions & 2 deletions docs-mintlify/reference/data-modeling/context-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ values from the Cube query during SQL generation.

This is useful for hinting your database optimizer to use a specific index
or filter out partitions or shards in your cloud data warehouse so you won't
be billed for scanning those.
be billed for scanning those. It can also be useful for constructing [links][ref-links].

<Warning>

Expand Down Expand Up @@ -816,4 +816,5 @@ cube(`orders`, {
[ref-dynamic-data-models]: /docs/data-modeling/dynamic/jinja
[ref-query-filter]: /reference/rest-api/query-format#query-properties
[ref-dynamic-jinja]: /docs/data-modeling/dynamic/jinja
[ref-filter-boolean]: /reference/rest-api/query-format#boolean-logical-operators
[ref-filter-boolean]: /reference/rest-api/query-format#boolean-logical-operators
[ref-links]: /reference/data-modeling/dimensions#links
116 changes: 114 additions & 2 deletions docs-mintlify/reference/data-modeling/dimensions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -426,9 +426,107 @@ Using it with other dimension types will result in a validation error.

</Info>

### `links`

The `links` parameter allows you to define links associated with a dimension.
They can be rendered as HTML links by supporting tools, e.g., [Workbooks][ref-workbooks].

Links are useful to let users navigate to related external resources (e.g., Google
search), internal tools (e.g., Salesforce), or other pages in a BI tool.

Each link must have a `name` and a `label`. The `name` is used as an identifier
in the [synthetic dimension](#synthetic) name.

A link must specify either a `url` or a `dashboard`:
- `url` is a SQL expression that constructs the link URL. It can [reference][ref-references]
column and dimension values, just like the [`sql` parameter](#sql) or [`mask` parameter](#mask).
- `dashboard` is a dashboard identifier. When set, the link URL is generated as
`/dashboard/<dashboard_id>`. The `params` object is still appended as a query string.

Optionally, a link might use the `icon` parameter to reference an icon from a [supported
icon set][link-tabler] to be displayed alongside the link label.

Optionally, a link might use the `target` parameter to specify [where to open it][link-target]:
`blank` (default) to open in a new tab/window or `self` to open in the same tab/window.

```yaml
cubes:
- name: users

dimensions:
# Definitions of dimensions such as `email`, etc.

- name: full_name
sql: full_name
type: string
links:
- name: google_search
label: Search on Google
url: "CONCAT('https://www.google.com/search?q=', {CUBE}.full_name)"
icon: brand-google
target: blank

- name: salesforce_search
label: Search in Salesforce
url: "CONCAT('https://your-company.salesforce.com/search/results/?q=', {email})"
target: blank

- name: send_email
label: Write an email
url: "CONCAT('mailto:', {email})"
icon: send
```

#### `params`

The optional `params` parameter can be used to add additional query parameters to the
URL. It accepts a map of key-value pairs, where keys are parameter names and values are
SQL expressions (just like `url`).

Values in `params` can [reference][ref-references] columns and dimension values.
All parameter values will be [URL-encoded][link-encode-uri-component] in the generated SQL
using a database-specific encoding function.

```yaml
cubes:
- name: users

dimensions:
# Definitions of dimensions such as `id`, `country`, etc.

- name: full_name
sql: full_name
type: string
links:
- name: performance
label: Check performance dashboard
dashboard: KSqDYdUz6Ble
params:
- key: filter_user_id
value: "{id}"
- key: filter_country
value: "{country}"
```

#### Dimensions
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Ambiguous heading. The #### Dimensions heading is used as a sub-section under both links and html to describe the synthetic dimensions generated in the result set. Since this appears inside a page titled "Dimensions," the heading reads like a circular reference. Consider a more descriptive title like #### Generated dimensions or #### Synthetic dimensions in the result set to make it immediately clear what this sub-section covers.


Each link will be rendered as an additional [synthetic](#synthetic) dimension in the
result set, with the following naming convention:

- `<dimension_name>___link_<link_name>_url`

<Info>

All references in link URLs and parameters must resolve to a single value for a given
value of the dimension on which the link is defined. Otherwise, it will result in
duplicate rows in the result set.

</Info>

### `meta`

Custom metadata. Can be used to pass any information to the frontend.
The `meta` parameter allows you to attach arbitrary information to a dimension.
It can be consumed and interpreted by supporting tools.

You can also use the `ai_context` key to provide context to the
[AI agent][ref-ai-context] without exposing it in the user interface.
Expand Down Expand Up @@ -902,6 +1000,13 @@ cube(`orders`, {

</CodeGroup>

### `synthetic`

The `synthetic` parameter can't be set by a user directly. It is used to mark dimensions
that are automatically created by Cube, e.g., for [links](#links).

You can check if a dimension is synthetic via the [`/v1/meta` API endpoint][ref-meta-api].

### `granularities`

By default, the following granularities are available for time dimensions:
Expand Down Expand Up @@ -1222,4 +1327,11 @@ cube(`fiscal_calendar`, {
[link-tesseract]: https://cube.dev/blog/introducing-next-generation-data-modeling-engine
[ref-case-measures]: /reference/data-modeling/measures#case
[ref-meta-api]: /reference/rest-api/reference#base_pathv1meta
[ref-string-time-dims]: /recipes/data-modeling/string-time-dimensions
[ref-string-time-dims]: /recipes/data-modeling/string-time-dimensions
[ref-workbooks]: /docs/explore-analyze/workbooks
[link-target]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#target
[link-tabler]: https://tabler.io/icons
[ref-references]: /docs/data-modeling/syntax#references
[ref-filter-params]: /reference/data-modeling/context-variables#filter_params
[link-encode-uri-component]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
[ref-rest-filters]: /reference/rest-api/query-format#query-properties
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ values from the Cube query during SQL generation.

This is useful for hinting your database optimizer to use a specific index
or filter out partitions or shards in your cloud data warehouse so you won't
be billed for scanning those.
be billed for scanning those. It can also be useful for constructing [links][ref-links].

<WarningBox>

Expand Down Expand Up @@ -816,4 +816,5 @@ cube(`orders`, {
[ref-dynamic-data-models]: /product/data-modeling/dynamic/jinja
[ref-query-filter]: /product/apis-integrations/rest-api/query-format#query-properties
[ref-dynamic-jinja]: /product/data-modeling/dynamic/jinja
[ref-filter-boolean]: /product/apis-integrations/rest-api/query-format#boolean-logical-operators
[ref-filter-boolean]: /product/apis-integrations/rest-api/query-format#boolean-logical-operators
[ref-links]: /product/data-modeling/reference/dimensions#links
115 changes: 114 additions & 1 deletion docs/content/product/data-modeling/reference/dimensions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,107 @@ cubes:

</CodeTabs>

### `links`

The `links` parameter allows you to define links associated with a dimension.
They can be rendered as HTML links by supporting tools, e.g., [Workbooks][ref-workbooks].

Links are useful to let users navigate to related external resources (e.g., Google
search), internal tools (e.g., Salesforce), or other pages in a BI tool.

Each link must have a `name` and a `label`. The `name` is used as an identifier
in the [synthetic dimension](#synthetic) name.

A link must specify either a `url` or a `dashboard`:
- `url` is a SQL expression that constructs the link URL. It can [reference][ref-references]
column and dimension values, just like the [`sql` parameter](#sql) or [`mask` parameter](#mask).
- `dashboard` is a dashboard identifier. When set, the link URL is generated as
`/dashboard/<dashboard_id>`. The `params` object is still appended as a query string.

Optionally, a link might use the `icon` parameter to reference an icon from a [supported
icon set][link-tabler] to be displayed alongside the link label.

Optionally, a link might use the `target` parameter to specify [where to open it][link-target]:
`blank` (default) to open in a new tab/window or `self` to open in the same tab/window.

```yaml
cubes:
- name: users

dimensions:
# Definitions of dimensions such as `email`, etc.

- name: full_name
sql: full_name
type: string
links:
- name: google_search
label: Search on Google
url: "CONCAT('https://www.google.com/search?q=', {CUBE}.full_name)"
icon: brand-google
target: blank

- name: salesforce_search
label: Search in Salesforce
url: "CONCAT('https://your-company.salesforce.com/search/results/?q=', {email})"
target: blank

- name: send_email
label: Write an email
url: "CONCAT('mailto:', {email})"
icon: send
```

#### `params`

The optional `params` parameter can be used to add additional query parameters to the
URL. It accepts a map of key-value pairs, where keys are parameter names and values are
SQL expressions (just like `url`).

Values in `params` can [reference][ref-references] columns and dimension values.
All parameter values will be [URL-encoded][link-encode-uri-component] in the generated SQL
using a database-specific encoding function.

```yaml
cubes:
- name: users

dimensions:
# Definitions of dimensions such as `id`, `country`, etc.

- name: full_name
sql: full_name
type: string
links:
- name: performance
label: Check performance dashboard
dashboard: KSqDYdUz6Ble
params:
- key: filter_user_id
value: "{id}"
- key: filter_country
value: "{country}"
```

#### Dimensions

Each link will be rendered as an additional [synthetic](#synthetic) dimension in the
result set, with the following naming convention:

- `<dimension_name>___link_<link_name>_url`

<InfoBox>

All references in link URLs and parameters must resolve to a single value for a given
value of the dimension on which the link is defined. Otherwise, it will result in
duplicate rows in the result set.

</InfoBox>

### `meta`

Custom metadata. Can be used to pass any information to the frontend.
The `meta` parameter allows you to attach arbitrary information to a dimension.
It can be consumed and interpreted by supporting tools.

<CodeTabs>

Expand Down Expand Up @@ -701,6 +799,13 @@ cubes:

</CodeTabs>

### `synthetic`

The `synthetic` parameter can't be set by a user directly. It is used to mark dimensions
that are automatically created by Cube, e.g., for [links](#links).

You can check if a dimension is synthetic via the [`/v1/meta` API endpoint][ref-meta].

### `granularities`

By default, the following granularities are available for time dimensions:
Expand Down Expand Up @@ -1015,3 +1120,11 @@ cube(`fiscal_calendar`, {
[ref-cube-calendar]: /product/data-modeling/reference/cube#calendar
[ref-measure-time-shift]: /product/data-modeling/reference/measures#time_shift
[ref-data-masking]: /product/auth/data-access-policies#data-masking
[ref-workbooks]: /product/exploration/workbooks
[link-target]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#target
[link-tabler]: https://tabler.io/icons
[ref-references]: /product/data-modeling/syntax#references
[ref-filter-params]: /product/data-modeling/reference/context-variables#filter_params
[link-encode-uri-component]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
[ref-rest-filters]: /product/apis-integrations/rest-api/query-format#query-properties
[ref-meta]: /product/apis-integrations/rest-api/reference#base_pathv1meta
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,8 @@ export class DatabricksQuery extends BaseQuery {
delete templates.types.interval;
return templates;
}

public urlEncode(sql: string): string {
return `url_encode(CAST(${sql} as STRING))`;
}
}
18 changes: 16 additions & 2 deletions packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -3989,6 +3989,17 @@ export class BaseQuery {
throw new Error('Not implemented');
}

/**
* URL-encode a SQL expression. Override in dialect-specific query classes
* for native URL encoding support. Default implementation uses REPLACE
* chains for the most common characters.
* @param {string} sql
* @return {string}
*/
urlEncode(sql) {
return `REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CAST(${sql} as TEXT), '%', '%25'), '&', '%26'), '=', '%3D'), '+', '%2B'), ' ', '%20')`;
}

/**
* @param {string} granularity
* @param {string} dimension
Expand Down Expand Up @@ -5007,7 +5018,8 @@ export class BaseQuery {
filterParams: this.filtersProxy(),
filterGroup: this.filterGroupFunction(),
sqlUtils: {
convertTz: this.convertTz.bind(this)
convertTz: this.convertTz.bind(this),
urlEncode: this.urlEncode.bind(this)
}
}, R.map(
(symbols) => this.contextSymbolsProxy(symbols),
Expand All @@ -5023,6 +5035,7 @@ export class BaseQuery {
filterGroup: () => '1 = 1',
sqlUtils: {
convertTz: (field) => field,
urlEncode: (sql) => sql,
},
securityContext: CubeSymbols.contextSymbolsProxyFrom({}, allocateParam),
};
Expand All @@ -5034,7 +5047,8 @@ export class BaseQuery {

sqlUtilsForRust() {
return {
convertTz: this.convertTz.bind(this)
convertTz: this.convertTz.bind(this),
urlEncode: this.urlEncode.bind(this)
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,8 @@ export class PrestodbQuery extends BaseQuery {
public castToString(sql: any): string {
return `CAST(${sql} as VARCHAR)`;
}

public urlEncode(sql: string): string {
return `url_encode(CAST(${sql} as VARCHAR))`;
}
}
Loading
Loading