Semantic Layer YAML Specification
Coming Soon
The Semantic Catalog is currently in development. This reference documents the planned YAML format. We'll update these docs when the feature launches.
Reference for the semantic layer YAML format.
Overview
Semantic layers are defined in YAML with three main sections:
models:
- name: model_name
table: schema.table_name
dimensions: [...]
measures: [...]
relationships:
- name: relationship_name
from: model_a
to: model_b
type: left
sql: "model_a.id = model_b.model_a_id"
Models
A model maps to a database table or view.
models:
- name: accounts
table: public.accounts
description: "Customer accounts"
dimensions:
- name: segment
type: string
sql: segment
description: "Account segment: Enterprise, Mid-Market, SMB"
- name: created_date
type: date
sql: created_at::date
description: "Account creation date"
measures:
- name: total_arr
type: sum
sql: arr
description: "Total annual recurring revenue"
Dimensions
Dimensions are attributes used to group or filter data.
| Property | Required | Description |
|---|---|---|
name | Yes | Unique identifier |
type | Yes | string, number, date, datetime, boolean |
sql | Yes | SQL expression |
description | No | Human-readable description |
primary_key | No | Set true for primary key |
Dimension Types
dimensions:
# String dimension
- name: status
type: string
sql: status
# Date dimension
- name: signup_date
type: date
sql: created_at::date
# Boolean dimension
- name: is_active
type: boolean
sql: "status = 'active'"
Measures
Measures are aggregated values.
| Property | Required | Description |
|---|---|---|
name | Yes | Unique identifier |
type | Yes | count, count_distinct, sum, avg, min, max, number |
sql | Yes | SQL expression (column or formula) |
description | No | Human-readable description |
filters | No | Array of filter conditions |
Measure Types
measures:
# Count all rows
- name: total_accounts
type: count
sql: id
# Count distinct values
- name: unique_users
type: count_distinct
sql: user_id
# Sum a column
- name: total_revenue
type: sum
sql: amount
# Average
- name: avg_deal_size
type: average
sql: amount
# Custom formula
- name: conversion_rate
type: number
sql: "COUNT(CASE WHEN converted THEN 1 END)::float / NULLIF(COUNT(*), 0)"
Filtered Measures
Apply filters to restrict which rows are aggregated:
measures:
- name: active_arr
type: sum
sql: arr
filters:
- sql: "status = 'active'"
- name: enterprise_count
type: count
sql: id
filters:
- sql: "segment = 'Enterprise'"
Relationships
Define how models join together.
| Property | Required | Description |
|---|---|---|
name | Yes | Unique identifier |
from | Yes | Source model name |
to | Yes | Target model name |
type | Yes | inner, left, right, full |
sql | Yes | Join condition |
relationships:
- name: account_users
from: accounts
to: users
type: left
sql: "accounts.id = users.account_id"
- name: user_events
from: users
to: events
type: left
sql: "users.id = events.user_id"
Complete Example
models:
- name: accounts
table: public.accounts
description: "Customer accounts"
dimensions:
- name: id
type: string
sql: id
primary_key: true
- name: segment
type: string
sql: segment
- name: status
type: string
sql: status
- name: created_date
type: date
sql: created_at::date
measures:
- name: count
type: count
sql: id
- name: total_arr
type: sum
sql: arr
- name: avg_arr
type: average
sql: arr
- name: users
table: public.users
description: "User accounts"
dimensions:
- name: id
type: string
sql: id
primary_key: true
- name: account_id
type: string
sql: account_id
- name: role
type: string
sql: role
measures:
- name: count
type: count
sql: id
- name: unique_accounts
type: count_distinct
sql: account_id
relationships:
- name: account_users
from: accounts
to: users
type: left
sql: "accounts.id = users.account_id"
Validation
The semantic layer validates:
- Table and column existence
- Type compatibility
- Circular relationship detection
- Unique names within a model
Validation errors appear when saving a draft or publishing a version.