Files
nvi/api/composer/order.py

39 lines
1.2 KiB
Python

"""ORDER BY rendering.
A Pick orders by either the metric or a named dimension; both reference the
SELECT-list *output alias* (the metric's name, or the dimension's output alias),
not the underlying qualified column. Returns an `exp.Ordered` node.
"""
from __future__ import annotations
from sqlglot import exp
from api.composer.types import OrderBy, PickValidationError
def _ordered(alias: str, direction: str) -> exp.Ordered:
return exp.Ordered(this=exp.column(alias, quoted=True), desc=(direction == "desc"))
def render_order_by(
ob: OrderBy,
metric_name: str,
dim_select: dict[str, str],
) -> exp.Ordered:
"""`metric_name` is the metric SELECT alias; `dim_select` maps a dimension
ref → its output alias."""
if ob.by == "metric":
return _ordered(metric_name, ob.direction)
if ob.dimension not in dim_select:
raise PickValidationError(
f"order_by.dimension={ob.dimension!r} is not in group_by ({list(dim_select)})"
)
return _ordered(dim_select[ob.dimension], ob.direction)
def default_order_by(metric_name: str) -> exp.Ordered:
"""Sensible default when a grouped query gives no explicit order: largest
metric value first."""
return _ordered(metric_name, "desc")