Files
fn_registry/python/functions/pipelines/query_project_pg.py
T
egutierrez 32c7336bf6 feat(infra): auto-commit con 56 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 14:22:55 +02:00

55 lines
2.3 KiB
Python

"""Pipeline one-shot: ejecuta un SELECT contra el Postgres de un proyecto conocido.
Compone dos funciones del registry sin reescribir su lógica:
1. resolve_pg_dsn(project) -> resuelve el DSN del proyecto (env / .env / pass).
2. pg_query(dsn, sql, max_rows=...) -> ejecuta el SELECT read-only y devuelve
las filas como list[dict].
Elimina el patrón inline que el agente repetía: resolver el DSN a mano y luego
lanzar psql/psycopg2 con él. El caller solo necesita el nombre del proyecto y
el SQL; el password sale de pass en runtime, nunca está hardcodeado.
Es un pipeline (kind: pipeline -> siempre impuro). Devuelve un dict sin lanzar:
lo que devuelve pg_query en éxito, o el error de resolución del DSN si falla
el primer paso.
"""
from infra.resolve_pg_dsn import resolve_pg_dsn
from infra.pg_query import pg_query
def query_project_pg(project: str, sql: str, max_rows: int = 10000) -> dict:
"""Resuelve el DSN de un proyecto y ejecuta un SELECT contra su Postgres.
Args:
project: nombre del proyecto conocido ('captacion' / 'captacion_clientes',
'seo' / 'seo_analytics'). Se pasa tal cual a resolve_pg_dsn.
sql: sentencia SQL a ejecutar (pensada para SELECT). Para parámetros, usa
el marcador %s; este pipeline no expone params posicionales, así que
interpola valores constantes y de confianza solo (para entradas no
confiables usa pg_query directamente con params).
max_rows: número máximo de filas a materializar (default 10000). Se pasa
tal cual a pg_query; si la query produce más, el resultado se trunca.
Returns:
dict. En éxito propaga el resultado de pg_query:
{status:'ok', columns, rows, row_count, truncated}. Si la resolución del
DSN falla, propaga {status:'error', error} de resolve_pg_dsn sin tocar
Postgres.
"""
resolved = resolve_pg_dsn(project)
if resolved.get("status") != "ok":
return resolved
return pg_query(resolved["dsn"], sql, max_rows=max_rows)
if __name__ == "__main__":
# Demo lanzable: cuenta de oportunidades de producto en captacion_clientes.
import json
out = query_project_pg(
"captacion",
"SELECT COUNT(*) AS n FROM product_opportunities",
)
print(json.dumps(out, ensure_ascii=False))