--- name: metabase_validate_sql kind: function lang: py domain: infra version: "1.0.0" purity: impure signature: "def metabase_validate_sql(client: MetabaseClient, database_id: int, sql: str, max_rows: int = 0) -> dict" description: "Valida sintaxis y referencias de una query SQL ejecutandola contra Metabase via POST /api/dataset. Captura tanto errores HTTP como errores embebidos en el body (Metabase a veces devuelve 200 con status failed). Retorna ok, error y rows_returned." tags: [metabase, validation, sql, pre-flight, impure, query, syntax-check] uses_functions: [metabase_execute_query_py_infra, metabase_auth_py_infra] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [httpx] params: - name: client desc: "instancia autenticada de MetabaseClient con sesion activa" - name: database_id desc: "ID de la base de datos en Metabase contra la que ejecutar el SQL" - name: sql desc: "sentencia SQL a validar (SELECT, WITH, etc.) — se ejecuta realmente contra la BD" - name: max_rows desc: "limite de filas a retornar durante la validacion para minimizar carga (0 = default de Metabase, tipicamente 2000)" output: "dict con tres claves: ok (bool) indica si la query se ejecuto sin error; error (str|None) mensaje de error si ok=False; rows_returned (int) numero de filas devueltas si ok=True" tested: false tests: [] test_file_path: "" file_path: "python/functions/metabase/validation.py" --- ## Ejemplo ```python result = metabase_validate_sql(client, database_id=1, sql="SELECT id FROM orders LIMIT 1") if not result["ok"]: print(f"SQL invalido: {result['error']}") else: print(f"SQL valido, {result['rows_returned']} filas retornadas") ``` ## Notas No tiene tests automatizados porque requiere una instancia Metabase corriendo con una base de datos real. Para testear manualmente: ```python client = metabase_auth("http://localhost:3000", "admin@example.com", "pass") result = metabase_validate_sql(client, 1, "SELECT * FROM tabla_inexistente") # result["ok"] == False, result["error"] == "Table 'tabla_inexistente' not found" ``` Comportamiento ante errores: - `httpx.HTTPStatusError` (4xx/5xx): extrae el campo `error` o `message` del JSON del response de Metabase. - Body con `status: "failed"` (Metabase devuelve 200 en algunos errores de query): captura el campo `error` del body. - Cualquier otra excepcion: convierte a string y la incluye en el campo `error`. Usa `metabase_execute_query` internamente, que mapea a POST /api/dataset.