"""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 = "" class BaseExecutor(ABC): """Subclasses: DbExecutor, TabularExecutor.""" @abstractmethod async def run(self, ir: QueryIR) -> QueryResult: ...