CML reference
Complete reference for every CML field โ node, dimension, measure, domain, data_keys, data_gates, and locale blocks.
CML (Celiq Modelling Language) is the YAML-based language for defining your semantic layer. Every node, domain, join, security rule, and locale setting is written in CML and version-controlled in Forge.
This page is a complete reference. For a conceptual introduction, see Key concepts.
node fields
The top-level block for a single table mapping.
node: <identifier>
label: <string>
description: <string>
sql_table: <schema.table>
connection: <connection_name>
tags: [<tag>, ...]
primary_key: <dimension_identifier>| Field | Type | Required | Description |
|---|---|---|---|
node | identifier | Yes | Unique identifier for this node. Snake case. Used in domain join references. |
label | string | Yes | Human-readable name shown in Discover. |
description | string | No | Shown in Discover field picker and search. Markdown supported. |
sql_table | string | Yes | The fully-qualified table name. Use schema.table format. Required unless sql_derived_table is set. |
sql_derived_table | string | No | A SQL subquery that defines the table. Use instead of sql_table for derived tables. |
connection | string | No | The name of the data connection to use. Defaults to workspace default if omitted. |
tags | string[] | No | Arbitrary tags for organising nodes in Forge. Not visible in Discover. |
primary_key | identifier | No | The dimension that uniquely identifies a row. Used for deduplication in certain join types. |
dimension fields
Dimensions are categorical or temporal fields used for grouping and filtering.
dimension: <identifier>
type: string | number | date | datetime | boolean | location
label: <string>
description: <string>
sql: <sql_expression>
primary_key: true | false
hidden: true | false
tags: [<tag>, ...]
data_gate: true | false
gate_behavior: restrict | hide
group_label: <string>
format: <format_string>
case_sensitive: true | false| Field | Type | Required | Description |
|---|---|---|---|
dimension | identifier | Yes | Unique identifier within the node. |
type | enum | Yes | Data type. string, number, date, datetime, boolean, location. |
label | string | Yes | Human-readable name in Discover. |
description | string | No | Shown in field picker tooltip. |
sql | string | Yes | SQL expression for the field. Use ${TABLE}.column_name for direct column references. |
primary_key | boolean | No | Marks this as the node's primary key. Defaults to false. |
hidden | boolean | No | Hides the field from Discover. Still usable in measures and joins. Defaults to false. |
data_gate | boolean | No | Enables field-level security. Access managed in Admin Console. Defaults to false. |
gate_behavior | enum | No | restrict (show badge, block query) or hide (field invisible). Defaults to restrict. |
group_label | string | No | Groups related dimensions under a collapsible heading in Discover. |
format | string | No | Display format for number and date types. E.g. "$#,##0.00", "YYYY-MM-DD". |
Dimension type: date
Date dimensions support automatic granularity groups (year, quarter, month, week, day). Celiq generates these sub-fields automatically when type: date or type: datetime is set.
dimension: created_at
type: date
label: Created At
sql: ${TABLE}.created_at
granularities: [day, week, month, quarter, year] # Default: all fivemeasure fields
Measures are aggregated calculations exposed in Discover as metrics.
measure: <identifier>
type: count | count_distinct | sum | average | min | max | percent_of_total | custom
label: <string>
description: <string>
sql: <sql_expression>
filters:
- dimension: <identifier>
value: <value>
format: number | currency | percent | <custom_format>
hidden: true | false
data_gate: true | false
gate_behavior: restrict | hide
tags: [<tag>, ...]| Field | Type | Required | Description |
|---|---|---|---|
measure | identifier | Yes | Unique identifier within the node. |
type | enum | Yes | Aggregation type. |
label | string | Yes | Human-readable name. |
sql | string | Yes | SQL expression for the field. Not required for count. |
filters | list | No | Optional WHERE conditions applied only to this measure. |
format | string | No | Display format. currency, percent, number, or a custom format string. |
Measure types
| Type | SQL equivalent | sql field required |
|---|---|---|
count | COUNT(*) | No |
count_distinct | COUNT(DISTINCT ${sql}) | Yes |
sum | SUM(${sql}) | Yes |
average | AVG(${sql}) | Yes |
min | MIN(${sql}) | Yes |
max | MAX(${sql}) | Yes |
percent_of_total | SUM / SUM OVER () | Yes |
custom | Raw SQL expression | Yes |
domain fields
Domains join multiple nodes together and define query entry points.
domain: <identifier>
label: <string>
description: <string>
base_node: <node_identifier>
joins:
- node: <node_identifier>
type: left_outer | full_outer | inner | cross
sql_on: <join_condition>
relationship: one_to_one | one_to_many | many_to_one | many_to_many| Field | Type | Required | Description |
|---|---|---|---|
domain | identifier | Yes | Unique identifier. |
label | string | Yes | Shown in the Discover node picker. |
base_node | identifier | Yes | The primary node that defines the cardinality of the query. |
joins | list | No | Additional nodes to join. |
Join fields
| Field | Type | Required | Description |
|---|---|---|---|
node | identifier | Yes | The node to join. |
type | enum | Yes | Join type: left_outer, full_outer, inner, cross. |
sql_on | string | Yes | The join condition. Use ${node.dimension} syntax. |
relationship | enum | Yes | Cardinality. Affects fan-out detection and measure correctness. |
data_keys block
Row-level security. See the full guide at Data Keys.
data_keys:
- key: <key_name>
dimension: <dimension_identifier>
null_behavior: deny | allow_all | deny_with_message
message: <string>| Field | Type | Required | Description |
|---|---|---|---|
key | string | Yes | The attribute name used for assignments in Admin Console. |
dimension | identifier | Yes | The dimension to filter on. Must be defined in this node. |
null_behavior | enum | No | What to do when a user has no assignment. Default: deny. |
message | string | No | Custom message shown when null_behavior: deny_with_message. |
locale block
Controls how a dimension's values are displayed in different languages.
dimension: status
type: string
label: Status
sql: ${TABLE}.status
locale:
en: { "active": "Active", "inactive": "Inactive" }
fr: { "active": "Actif", "inactive": "Inactif" }
de: { "active": "Aktiv", "inactive": "Inaktiv" }Locale mappings translate raw database values into display labels based on the user's language setting.