Files
egutierrez fd5787c55f chore: auto-commit (43 archivos)
- .mcp.json
- bash/functions/infra/write_mcp_jupyter_config.md
- bash/functions/infra/write_mcp_jupyter_config.sh
- cpp/CMakeLists.txt
- cpp/apps/chart_demo
- cpp/apps/shaders_lab
- cpp/functions/gfx/gl_framebuffer.cpp
- cpp/functions/gfx/gl_framebuffer.h
- cpp/functions/gfx/gl_framebuffer.md
- cpp/functions/gfx/mesh_gpu.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 17:28:47 +02:00

3.7 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path params output
clickhouse_query function py infra 1.0.0 impure def clickhouse_query(base_url: str, sql: str, *, user: str = 'default', password: str = '', database: str = 'analytics', timeout: float = 30.0) -> list[dict] Ejecuta un SQL contra ClickHouse via HTTP (puerto 8123) y retorna los resultados como lista de dicts. Para SELECT usa JSONEachRow automaticamente; para DDL/DML retorna [].
clickhouse
analytics
http
query
select
read
false error_go_core
json
urllib.request
urllib.parse
urllib.error
false
python/functions/infra/clickhouse_query.py
name desc
base_url URL base del servidor ClickHouse sin trailing slash. Ej: 'http://127.0.0.1:18123'. Para tunel SSH, apunta al puerto local reenviado.
name desc
sql SQL completo a ejecutar. El caller escribe el SQL entero; esta funcion no anade nada. Para SELECT retorna filas; para CREATE/INSERT/etc. retorna [].
name desc
user Usuario ClickHouse para autenticacion via header X-ClickHouse-User (default: 'default').
name desc
password Contrasena ClickHouse para autenticacion via header X-ClickHouse-Key (default: cadena vacia).
name desc
database Base de datos ClickHouse enviada como parametro de query (default: 'analytics').
name desc
timeout Timeout de socket en segundos (default: 30.0).
Lista de dicts, uno por fila del resultado. Lista vacia para sentencias sin resultado (DDL, INSERT). Los numeros Int64 de ClickHouse llegan como strings JSON — castear con int() si se necesita aritmetica.

Ejemplo

from infra import clickhouse_query

# Contar filas
rows = clickhouse_query(
    "http://127.0.0.1:18123",
    "SELECT count() AS c FROM analytics.gnula_movies",
    user="analytics",
    password="secret",
    database="analytics",
)
print(int(rows[0]["c"]))  # Int64 llega como string → castear

# Leer ultimas inserciones
recent = clickhouse_query(
    "http://127.0.0.1:18123",
    "SELECT snapshot_ts, title, status FROM analytics.gnula_movies ORDER BY snapshot_ts DESC LIMIT 5",
    user="analytics",
    password="secret",
)
for r in recent:
    print(r["snapshot_ts"], r["title"], r["status"])

Cuando usarla

Leer agregados, validar ingest o inspeccionar datos en ClickHouse via HTTP sin dependencias externas. Util en ETLs de validacion, notebooks, scripts de monitoreo y pipelines que ya usan clickhouse_insert_rows_py_infra para escribir y necesitan verificar el resultado. Tambien sirve para ejecutar DDL (CREATE TABLE, etc.) cuando la respuesta vacia es esperada.

Gotchas

  • base_url sin trailing slash: "http://127.0.0.1:18123", no "http://127.0.0.1:18123/".
  • El caller escribe el SQL completo. Esta funcion no anade FORMAT, LIMIT ni nada — lo que se pasa es lo que se ejecuta.
  • Int64 y UInt64 de ClickHouse llegan como strings JSON en JSONEachRow. Castear explicitamente: int(row["c"]). Float64 llega como numero JSON nativo.
  • Para SELECT sin FORMAT explicito, default_format=JSONEachRow se aplica automaticamente via query param. No hace falta escribir FORMAT JSONEachRow en el SQL.
  • DDL y DML (CREATE, INSERT, ALTER) retornan cuerpo vacio → la funcion retorna []. No es un error.
  • Para tunel SSH: ssh -L 18123:localhost:8123 user@host y usar base_url="http://127.0.0.1:18123".
  • En caso de error HTTP, ValueError incluye el codigo y los primeros 500 caracteres del cuerpo — util para depurar errores de SQL o permisos.
  • Queries con resultado muy grande se leen enteras en memoria. Para resultados masivos, usar LIMIT o streaming manual con urllib.request.urlopen directamente.