Source code for codegen_database.ext.ledger.queries

"""Query builders for ledger factories.

Provides pure-Python helpers that return SQLAlchemy selects
without registering anything on metadata.  Callers are responsible
for passing the results to
:class:`~codegen_database.views.view.CodegenDatabasePlainView`.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from sqlalchemy import func, select

if TYPE_CHECKING:
    from sqlalchemy import Select

    from codegen_database.factory.context import ContextSource

from codegen_database.errors import CodegenDatabaseValidationError


[docs] def construct_ledger_balance_query( source: ContextSource, dimensions: list[str], ) -> Select: """Build a balance aggregation query for a ledger. Generates:: SELECT dim_col1, ..., SUM(value) AS balance FROM <primary_table> GROUP BY dim_col1, ... Args: source: A :class:`~codegen_database.factory.ledger.CodegenDatabaseLedger` instance or a :class:`~codegen_database.declarative.CodegenDatabaseBase` subclass using ``CodegenDatabaseLedger`` as its factory. dimensions: Column names to group by. Must be a non-empty list. Returns: A SQLAlchemy :class:`~sqlalchemy.Select`. Raises: CodegenDatabaseValidationError: If *dimensions* is empty. """ if not dimensions: msg = "dimensions must be a non-empty list" raise CodegenDatabaseValidationError(msg) table = source.ctx["primary"] dim_cols = [table.c[d] for d in dimensions] return ( select( *[c.label(c.key) for c in dim_cols], func.sum(table.c["value"]).label("balance"), ) .select_from(table) .group_by(*dim_cols) )
[docs] def construct_ledger_latest_query( source: ContextSource, dimensions: list[str], ) -> Select: """Build a latest-row query for a ledger using DISTINCT ON. Generates:: SELECT * FROM <primary_table> DISTINCT ON (dim_col1, ...) ORDER BY dim_col1, ..., created_at DESC Args: source: A :class:`~codegen_database.factory.ledger.CodegenDatabaseLedger` instance or a :class:`~codegen_database.declarative.CodegenDatabaseBase` subclass using ``CodegenDatabaseLedger`` as its factory. dimensions: Column names to partition by. Must be a non-empty list. Returns: A SQLAlchemy :class:`~sqlalchemy.Select`. Raises: CodegenDatabaseValidationError: If *dimensions* is empty. """ if not dimensions: msg = "dimensions must be a non-empty list" raise CodegenDatabaseValidationError(msg) table = source.ctx["primary"] created_at_col = source.ctx["created_at_column"] dim_cols = [table.c[d] for d in dimensions] return ( select(table) .distinct(*dim_cols) .order_by( *dim_cols, table.c[created_at_col].desc(), ) )