File size: 1,187 Bytes
28035e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"""Safe SQL execution against PostgreSQL.

Only SELECT queries are allowed. Results are returned as list[dict].
Database errors are captured and returned for the AI repair loop.
"""

from typing import Any

from sqlalchemy import text

from db.connection import get_engine
from ai.validator import validate_sql


def execute_sql(sql: str) -> dict[str, Any]:
    """Execute a SQL query and return results or error.

    Returns
    -------
    dict with keys:
        success : bool
        data    : list[dict]   (on success)
        columns : list[str]    (on success)
        error   : str          (on failure)
    """
    # Safety gate
    is_safe, reason = validate_sql(sql)
    if not is_safe:
        return {"success": False, "data": [], "columns": [], "error": reason}

    try:
        with get_engine().connect() as conn:
            result = conn.execute(text(sql))
            columns = list(result.keys())
            rows = [dict(zip(columns, row)) for row in result.fetchall()]
            return {"success": True, "data": rows, "columns": columns, "error": ""}
    except Exception as exc:
        return {"success": False, "data": [], "columns": [], "error": str(exc)}