"""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" rows: list[dict[str, Any]] = field(default_factory=list) row_count: int = 0 truncated: bool = False elapsed_ms: int = 0 error: str | None = None class BaseExecutor(ABC): """Subclasses: DbExecutor, TabularExecutor.""" @abstractmethod async def run(self, ir: QueryIR) -> QueryResult: ...