Source code for loom.core.sql.abc.contracts

"""Backend-agnostic SQL execution contracts.

These types form the port between :class:`~loom.core.sql.service.SqlQueryService`
and concrete SQL backends. They carry no infrastructure imports: each executor
translates :class:`SqlExecutionOptions` to its native mechanism and returns the
standard :class:`SqlQueryResult` envelope.
"""

from __future__ import annotations

from collections.abc import Mapping
from typing import Any, Protocol

from loom.core.model import LoomFrozenStruct


[docs] class SqlExecutionOptions(LoomFrozenStruct, frozen=True, kw_only=True): """Backend-agnostic execution options resolved by the service policy. Each executor translates these values to its native per-query mechanism (for ClickHouse: per-query ``settings``). The policy applies them last, so connection-level settings can never override them. Attributes: roles: Effective roles for this single query, already validated against the connection allowlist. Several roles apply the union of their privileges; empty means no role at all (internal probes only). readonly: Whether the query must run in read-only mode. limit: Maximum number of rows to return. The executor requests ``limit + 1`` rows to compute ``has_more``. offset: Number of rows to skip before returning results. max_execution_time: Per-query execution timeout in seconds. """ roles: tuple[str, ...] = () readonly: bool = True limit: int | None = None offset: int = 0 max_execution_time: int = 30
[docs] class SqlColumn(LoomFrozenStruct, frozen=True, kw_only=True): """Column descriptor of a SQL result set. Attributes: name: Column name as reported by the backend. type: Native backend type (e.g. ``"DateTime64(3)"``). """ name: str type: str
[docs] class SqlQueryResult(LoomFrozenStruct, frozen=True, kw_only=True): """Standard tabular envelope returned for any SQL statement. Attributes: columns: Ordered column descriptors of the result set. rows: Result rows, already trimmed to ``limit``. row_count: Number of rows in ``rows``. limit: Effective limit applied to this page. offset: Effective offset applied to this page. has_more: Whether more rows exist beyond this page. elapsed_ms: Server-side execution telemetry in milliseconds. """ columns: tuple[SqlColumn, ...] rows: tuple[tuple[Any, ...], ...] row_count: int limit: int offset: int has_more: bool elapsed_ms: float
[docs] class SqlExecutor(Protocol): """Port implemented by concrete SQL backends. Exists for dependency inversion (the service never imports driver code) and for testing with fakes. Documented as a contract in evolution until a second backend implementation lands. """
[docs] async def execute( self, sql: str, *, parameters: Mapping[str, Any] | None = None, options: SqlExecutionOptions, ) -> SqlQueryResult: """Execute *sql* with server-side bound *parameters* under *options*. Args: sql: SQL statement with native parameter placeholders. parameters: Values bound server-side; never interpolated locally. options: Policy-resolved execution options for this single query. Returns: The standard tabular result envelope. Raises: SqlExecutionError: When the backend rejects the statement. """ ...