"""BaseExecutor + QueryResult — uniform return shape across DB and tabular paths.""" from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import Any from ..ir.models import QueryIR @dataclass class QueryResult: source_id: str backend: str # "sql" | "tabular" columns: list[str] = field(default_factory=list) rows: list[dict[str, Any]] = field(default_factory=list) row_count: int = 0 truncated: bool = False elapsed_ms: int = 0 error: str | None = None table_id: str = "" table_name: str = "" source_name: str = "" # The executed query string (compiled SQL for db, rendered pandas chain for # tabular), surfaced to traceability. None on error/unset paths. KM-691. query: str | None = None class BaseExecutor(ABC): """Subclasses: DbExecutor, TabularExecutor.""" @abstractmethod async def run(self, ir: QueryIR) -> QueryResult: ...