refactor composer to use sqlalchemy, avoid string concatenations and follow conventions
This commit is contained in:
42
api/composer/encodings.py
Normal file
42
api/composer/encodings.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""Storage-encoding library — how a column's raw storage maps to a value the
|
||||
composer can compare against.
|
||||
|
||||
Some warehouses store logical types in surprising physical encodings (BIRD
|
||||
ships YYMMDD-encoded *integer* "dates", for instance). The composer needs a way
|
||||
to coerce such a column to a comparable value without baking any one dataset's
|
||||
quirk into the generic SQL builder.
|
||||
|
||||
The model is **defaults with override**:
|
||||
|
||||
- `DEFAULT_ENCODINGS` ships the generic, reusable patterns here — keyed by the
|
||||
`Column.semantic_type` a dataset declares in `schema_docs.yaml`.
|
||||
- A dataset may add a novel encoding or override a default via the optional
|
||||
`encodings:` section of its `schema_docs.yaml` (carried onto
|
||||
`Recon.encodings`). The dataset always wins.
|
||||
|
||||
Each encoding is plain data: a map of role → SQL template with a `{col}`
|
||||
placeholder for the (already-qualified) column reference. Today the only role
|
||||
is `as_date` — the expression that yields a DATE for `date_range` filters; new
|
||||
roles are additive.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from api.recon.types import Recon
|
||||
|
||||
|
||||
DEFAULT_ENCODINGS: dict[str, dict[str, str]] = {
|
||||
# BIRD-style YYMMDD stored as a 6-digit integer → real DATE.
|
||||
"date_yymmdd": {"as_date": "TO_DATE(LPAD({col}::text, 6, '0'), 'YYMMDD')"},
|
||||
# Add further reusable patterns here (e.g. epoch_seconds, julian_day) as
|
||||
# they recur across datasets — never a single dataset's one-off quirk.
|
||||
}
|
||||
|
||||
|
||||
def effective_encodings(recon: "Recon") -> dict[str, dict[str, str]]:
|
||||
"""The encoding map the composer should use for `recon`: built-in defaults
|
||||
overlaid with the dataset's own `encodings` (dataset entries win)."""
|
||||
return {**DEFAULT_ENCODINGS, **(recon.encodings or {})}
|
||||
Reference in New Issue
Block a user