refactor composer to use sqlalchemy, avoid string concatenations and follow conventions

This commit is contained in:
2026-06-03 12:10:30 -03:00
parent cbc7df8c60
commit be09fcde2c
16 changed files with 546 additions and 273 deletions

View File

@@ -137,6 +137,11 @@ def merge_into_recon(dataset: str, extracted: dict[str, Any]) -> Recon:
relationships = [Relationship.parse(r) for r in (aug.get("relationships", []) or [])]
# Storage-encoding overrides (optional). Keyed by Column.semantic_type; each
# value maps a role (e.g. "as_date") to a SQL template with a `{col}`
# placeholder. The composer merges these over its built-in defaults.
encodings: dict[str, dict[str, str]] = aug.get("encodings", {}) or {}
column_to_tables: dict[str, list[str]] = {}
for t in tables.values():
for c in t.columns:
@@ -150,6 +155,7 @@ def merge_into_recon(dataset: str, extracted: dict[str, Any]) -> Recon:
metrics=metrics,
column_to_tables=column_to_tables,
relationships=relationships,
encodings=encodings,
)

View File

@@ -151,6 +151,12 @@ class Recon:
metrics: dict[str, Metric]
column_to_tables: dict[str, list[str]] = field(default_factory=dict)
relationships: list[Relationship] = field(default_factory=list)
# Storage-encoding overrides keyed by Column.semantic_type. Each value is a
# map of role → SQL template with a `{col}` placeholder (e.g.
# {"date_yymmdd": {"as_date": "TO_DATE(LPAD({col}::text, 6, '0'), 'YYMMDD')"}}).
# The composer merges these over its DEFAULT_ENCODINGS — the dataset wins.
# Empty for datasets whose columns are stored in native types.
encodings: dict[str, dict[str, str]] = field(default_factory=dict)
# ── Read-side helpers used by Analyses + the composer ──
@@ -299,6 +305,7 @@ class Recon:
"metrics": {n: m.to_dict() for n, m in self.metrics.items()},
"column_to_tables": self.column_to_tables,
"relationships": [r.to_dict() for r in self.relationships],
"encodings": self.encodings,
}
@classmethod
@@ -309,4 +316,5 @@ class Recon:
metrics={n: Metric.from_dict(m) for n, m in d.get("metrics", {}).items()},
column_to_tables=d.get("column_to_tables", {}),
relationships=[Relationship(**r) for r in d.get("relationships", [])],
encodings=d.get("encodings", {}) or {},
)