ClickHouse + Bruin 101
1) Materialize code-managed reference data
assets/python/customer_regions.py is a Python asset. Bruin runs its materialize() function in the declared python:3.13 image, validates its returned rows against the asset schema, and writes a create+replace ClickHouse table.
The file starts with a Python docstring that Bruin reads as the asset definition:
"""@bruin
name: customer_regions
connection: clickhouse-default
materialization:
type: table
strategy: create+replace
image: python:3.13
parameters:
enforce_schema: true
columns:
- name: country
type: String
primary_key: true
checks:
- name: not_null
- name: unique
- name: sales_region
type: LowCardinality(String)
checks:
- name: not_null
- name: support_tier
type: LowCardinality(String)
checks:
- name: accepted_values
value: [strategic, standard]
@bruin"""
connection chooses the ClickHouse destination and image chooses the Python runtime. The declared schema is still the contract: enforce_schema: true validates what the Python function returns, country is unique, and support_tier is limited to the two known values.
The executable part is ordinary Python:
def materialize():
return [
{
"country": "United Kingdom",
"sales_region": "EMEA",
"support_tier": "strategic",
},
{
"country": "United States",
"sales_region": "North America",
"support_tier": "strategic",
},
{
"country": "Austria",
"sales_region": "EMEA",
"support_tier": "standard",
},
]
Bruin calls materialize() and writes the returned dictionaries into customer_regions. The dictionary keys must match the declared columns. create+replace then replaces the complete table, which suits this tiny code-managed lookup.
The function returns three country-to-region mappings. The asset also defines an accepted-values check for support_tier, a primary key on country, enforce_schema: true, and the same ownership and metadata fields seen in the SQL assets. country_revenue.sql then treats customer_regions as an ordinary upstream table.
This is the pattern to use when a small reference dataset is better expressed as reviewed code than as a CSV. See the Python asset reference and the Python Materialization tutorial for a fuller example.