How the compiler turns a request into SQL
Walk the algorithm that takes a structured metric request and produces correct, joined, grouped SQL.
The compiler (semantic_layer.py) is small but does the real work. Given a request — metrics, dimensions, filters, time grain — it produces and runs SQL. Understanding its steps demystifies the whole layer.
The algorithm for one measure
- 1Start at the base table.
revenue's base isorder_items. - 2Collect needed tables. Scan the metric's SQL and filters, plus the chosen dimensions' columns, for table names. Revenue-by-region needs
order_items,orders(for the status filter), andcustomers(for region). - 3Resolve joins. Walk the join graph from the base to each needed table, collecting exactly the join clauses along the path — no extra joins.
- 4Build SELECT. Emit each dimension column (wrapped in a time-grain function if requested) plus the metric's aggregate SQL,
GROUP BYthe dimensions. - 5Add WHERE. Combine the metric's built-in filters (refunds excluded) with any user filters, using parameter binding for safety.
- 6Run it against SQLite and return rows keyed by their dimension values.
Here's the shape of what it generates for "revenue by region":
SELECT customers.region AS dim_0,
SUM(order_items.quantity * order_items.unit_price - order_items.discount) AS value
FROM order_items
JOIN orders ON order_items.order_id = orders.order_id
JOIN customers ON orders.customer_id = customers.customer_id
WHERE orders.status = 'completed'
GROUP BY 1;It does a breadth-first search from the base table to each dimension table over the join graph, then emits joins in parent-before-child order. That's how one generic function correctly assembles the joins for any metric×dimension combination you throw at it.
If a dimension's table can't be reached from a metric's base (marketing spend by product category), the resolver raises a clear error instead of inventing a bogus number. Refusing an impossible question is a feature, not a bug.