Files
fn_registry/python/functions/infra/pg_query.md
T
egutierrez 927437a8d8 feat(infra): grupo claude-fleet — FleetView TUI + orquestacion de Claudes
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una
sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI:

- list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals +
  runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId.
- list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables.
- wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console
  (preserva ancho del sidebar), tmux_map_claude_panes.
- launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r,
  mouse on, remain-on-exit off; fija el ancho del sidebar con hooks.
- docs/capabilities/claude-fleet.md + entrada en el INDEX.

Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes
varios de docs e infra de otra sesion, agrupados aqui para no perderlos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:04:41 +02:00

4.7 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
pg_query function py infra 1.0.0 impure def pg_query(dsn: str, sql: str, params: list = None, max_rows: int = 10000) -> dict Ejecuta un SELECT contra PostgreSQL via psycopg2 y devuelve las filas como list[dict] sin lanzar. Abre la conexion con el DSN, marca la transaccion read-only (SET TRANSACTION READ ONLY) y usa RealDictCursor para que cada fila sea un dict columna->valor. Devuelve {status:'ok', columns, rows, row_count, truncated} en exito y {status:'error', error} en fallo (estilo duckdb_query_readonly). Usa parametros posicionales con el marcador %s. Trunca a max_rows para proteger memoria. Normaliza valores no JSON-serializables: date/datetime/time a isoformat(), Decimal a float, bytes/memoryview a base64, UUID a str. Cierra la conexion siempre en try/finally. Espejo de duckdb_query_readonly para Postgres. Depende de psycopg2 (2.9.x en python/.venv).
postgres
postgresql
sql
query
readonly
infra
false error_py_core
base64
datetime
decimal
uuid
psycopg2
name desc
dsn Cadena de conexion PostgreSQL en formato postgresql://user:pass@host:port/dbname. Un DSN invalido o servidor inalcanzable devuelve {status:'error'} sin lanzar.
name desc
sql Sentencia SQL a ejecutar (pensada para SELECT). Usa el marcador %s para parametros posicionales (estilo psycopg2).
name desc
params Lista de parametros posicionales para el SQL en orden. None (default) significa sin parametros. Pasar los valores aqui en vez de interpolarlos en el SQL evita inyeccion.
name desc
max_rows Numero maximo de filas a materializar en memoria (default 10000). Si la query produce mas, el resultado se trunca y truncated queda en True.
dict. En exito: {status:'ok', columns:[str,...], rows:[{col:val,...},...], row_count:int, truncated:bool}; las filas son dicts (RealDictCursor). En error (sin lanzar): {status:'error', error:str}. Los valores estan normalizados a tipos JSON-serializables. true
test_skip_sin_pg_test_dsn
test_normaliza_tipos_no_serializables
test_select_con_parametros_posicionales
test_trunca_a_max_rows
test_dsn_invalido_devuelve_status_error
python/functions/infra/pg_query_test.py python/functions/infra/pg_query.py

Ejemplo

import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from infra.pg_query import pg_query

dsn = "postgresql://user:pass@localhost:5433/trends"

# SELECT con parametro posicional (nunca interpolar el valor en el SQL).
res = pg_query(
    dsn,
    "SELECT product, price FROM prices WHERE source = %s ORDER BY price DESC",
    params=["amazon"],
    max_rows=100,
)
print(res["status"])      # ok
print(res["columns"])     # ['product', 'price']
print(res["rows"][0])     # {'product': 'Widget X', 'price': 19.99}
print(res["truncated"])   # False

Cuando usarla

Usala cuando necesites leer datos de Postgres y pasarlos a otro paso de una composicion como dict serializable: inspeccionar una tabla, validar el resultado de un pipeline de ingesta, alimentar un dashboard o report, o consultar tablas materializadas. Es el espejo de duckdb_query_readonly para Postgres. Para escribir usa pg_insert_rows, pg_upsert o pg_apply_sql.

Gotchas

  • Lectura real contra un servidor (impura). La transaccion se marca read-only con set_session(readonly=True) y nunca se hace commit (rollback al final): cualquier INSERT/UPDATE/DELETE en el SQL falla a nivel de servidor y vuelve como {status:'error', ...}. NO es un sandbox de filesystem — read-only protege la base, no impide leer datos sensibles si el SQL viene de un cliente no confiable.
  • Inyeccion SQL: los valores van siempre por params con el marcador %s, nunca interpolados en el string del SQL. Esta funcion NO valida ni parametriza identificadores (nombres de tabla/columna): si necesitas un nombre de tabla dinamico, validalo tu antes con ^[A-Za-z_][A-Za-z0-9_]*$.
  • max_rows protege la memoria: una query que devuelve millones de filas se trunca a max_rows y marca truncated=True. Para todas las filas, pagina con LIMIT/OFFSET o sube max_rows conscientemente.
  • Valores no JSON-serializables se normalizan en la salida: date/datetime/time a isoformat(), Decimal a float (posible perdida de precision frente al decimal exacto), bytes/memoryview a base64 y UUID a str.
  • Conexion nueva por llamada (sin pool). Para muchas consultas pequenas en bucle, reusa una conexion fuera de esta funcion o agrupa el trabajo en una sola query.
  • Nunca lanza: DSN invalido, servidor caido, SQL malformado o falta de psycopg2 vuelven como {status:'error', error:str}.