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>
This commit is contained in:
2026-05-30 17:28:47 +02:00
parent a2efdcf003
commit fd5787c55f
44 changed files with 3924 additions and 64 deletions
@@ -0,0 +1,81 @@
"""Query ClickHouse via the HTTP interface (port 8123) and return rows as dicts."""
import json
import urllib.error
import urllib.parse
import urllib.request
def clickhouse_query(
base_url: str,
sql: str,
*,
user: str = "default",
password: str = "",
database: str = "analytics",
timeout: float = 30.0,
) -> list[dict]:
"""Execute a SQL statement against ClickHouse via HTTP and return results.
Args:
base_url: ClickHouse HTTP base URL without trailing slash,
e.g. "http://127.0.0.1:18123".
sql: Full SQL statement. For SELECT queries the server returns
JSONEachRow automatically via the default_format param.
For DDL/DML with no result set (CREATE, INSERT, etc.)
the response body is empty and [] is returned.
user: ClickHouse username (default "default").
password: ClickHouse password (default empty string).
database: Target database sent as query param (default "analytics").
timeout: Socket timeout in seconds (default 30.0).
Returns:
List of dicts, one per result row. Empty list for statements that
produce no result set. Numbers may come back as strings for some
ClickHouse types (e.g. Int64 is returned as a JSON string in
JSONEachRow — cast explicitly if needed: int(row["c"])).
Raises:
ValueError: On non-200 HTTP response, with status code and first
500 chars of the response body.
urllib.error.URLError: On network-level errors (connection refused,
DNS failure, timeout).
"""
params = urllib.parse.urlencode(
{"database": database, "default_format": "JSONEachRow"}
)
url = f"{base_url}/?{params}"
body_bytes = sql.encode("utf-8")
req = urllib.request.Request(
url,
data=body_bytes,
method="POST",
headers={
"Content-Type": "text/plain",
"X-ClickHouse-User": user,
"X-ClickHouse-Key": password,
},
)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
if resp.status != 200:
body_preview = resp.read(500).decode("utf-8", errors="replace")
raise ValueError(
f"ClickHouse query failed: HTTP {resp.status}{body_preview}"
)
raw = resp.read().decode("utf-8", errors="replace")
except urllib.error.HTTPError as exc:
body_preview = exc.read(500).decode("utf-8", errors="replace")
raise ValueError(
f"ClickHouse query failed: HTTP {exc.code}{body_preview}"
) from exc
rows = []
for line in raw.splitlines():
line = line.strip()
if line:
rows.append(json.loads(line))
return rows