Dictionaries¶
Declaration¶
Dictionaries are declared with flat ch_dict_* attributes on class Meta, not with builder functions. Set ch_dictionary = True to mark the model as a dictionary:
from sqlalchemy.orm import Mapped, mapped_column
from dbwarden.databases.clickhouse import CHTableMeta
class CountryLookup(Base):
__tablename__ = "country_lookup"
code: Mapped[str] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column()
class Meta(CHTableMeta):
ch_dictionary = True
ch_dict_primary_key = "code"
ch_dict_layout = "flat"
ch_dict_source = {
"clickhouse": {"query": "SELECT code, name FROM source_countries"},
}
ch_dict_lifetime = 300
The five recognised attributes are ch_dictionary, ch_dict_primary_key, ch_dict_layout, ch_dict_source, and ch_dict_lifetime. Because CHTableMeta is validated at import time, a misspelled attribute raises DBWardenConfigError when the module loads.
There is also a dictionary() helper that builds a DictSpec directly, for code that constructs specs programmatically rather than declaring them on a model:
from dbwarden.databases.clickhouse import dictionary
spec = dictionary(
layout="hashed",
source={"clickhouse": {"table": "dim_users"}},
lifetime=300,
primary_key="id",
)
Additional model examples¶
MySQL-sourced dictionary¶
class MySQLCountry(Base):
__tablename__ = "mysql_country"
code: Mapped[str] = mapped_column()
name: Mapped[str] = mapped_column()
class Meta(CHTableMeta):
ch_dictionary = True
ch_dict_primary_key = "code"
ch_dict_layout = "hashed"
ch_dict_source = {
"mysql": {
"named_collection": "mysql_dict",
"query": "SELECT iso_code, full_name FROM ref.countries",
},
}
ch_dict_lifetime = "MIN 60 MAX 300"
HTTP-sourced dictionary with complex key¶
class CurrencyRate(Base):
__tablename__ = "currency_rate"
currency: Mapped[str] = mapped_column()
rate: Mapped[float] = mapped_column()
class Meta(CHTableMeta):
ch_dictionary = True
ch_dict_primary_key = "currency"
ch_dict_layout = "cache"
ch_dict_source = {
"http": {
"url": "https://api.example.com/rates",
"format": "JSONEachRow",
},
}
ch_dict_lifetime = 3600
Range-hashed dictionary for time-based lookup¶
class TaxRate(Base):
__tablename__ = "tax_rate"
region: Mapped[str] = mapped_column()
rate: Mapped[float] = mapped_column()
class Meta(CHTableMeta):
ch_dictionary = True
ch_dict_primary_key = ["region", "valid_from"]
ch_dict_layout = "range_hashed"
ch_dict_source = {
"clickhouse": {
"query": "SELECT region, valid_from, valid_to, rate FROM ref.tax_rates",
},
}
ch_dict_lifetime = 86400
Usage in queries:
Source types¶
ch_dict_source is a dict keyed by source type, whose value carries that source's settings:
| Source type | ch_dict_source |
|---|---|
| ClickHouse | {"clickhouse": {"query": "..."}} |
| MySQL | {"mysql": {...}} |
| PostgreSQL | {"postgresql": {...}} |
| MongoDB | {"mongodb": {...}} |
| HTTP(S) | {"http": {...}} |
| Local file | {"file": {...}} |
| Executable | {"executable": {...}} |
For connection secrets, reference a named collection rather than inlining credentials:
Layout types¶
ch_dict_layout is the layout name as a string:
ch_dict_layout = "flat" # One key, single value
ch_dict_layout = "hashed" # Hash table, all in memory
ch_dict_layout = "sparse_hashed" # Like hashed but sparse
ch_dict_layout = "cache" # LRU cache
ch_dict_layout = "complex_key_hashed" # Composite keys
ch_dict_layout = "ip_trie" # IP prefix matching
ch_dict_layout = "direct" # No caching
ch_dict_layout = "range_hashed" # Time ranges
Lifetime¶
ch_dict_lifetime accepts an integer for a fixed interval, or a string for ClickHouse's ranged form:
What changes are allowed¶
| Change | Safety |
|---|---|
| Lifetime adjustment | INFO |
| Layout change | CRITICAL: requires recreate |
| Source connection change | INFO (named collection swap) |
| Query/SELECT change | WARN |
| Primary key change | CRITICAL: requires recreate |
Rollback behavior¶
Dictionary changes that require a recreate follow the full pipeline. See Safety.