quackapi
HTTP-Framework der FastAPI-Klasse in DuckDB — CREATE ROUTE macht aus SQL typisierte, validierte Endpunkte; ein Prozess ist DB + HTTP (+ PDF/Renderer über Begleiterweiterungen).
Maintainer: asubbarao
Installation und Laden
INSTALL quackapi FROM community;LOAD quackapi;Beispiel
LOAD quackapi;
-- JSON endpoint: the SELECT is the handlerCREATE ROUTE hello GET '/hello' AS SELECT 'world' AS msg;
-- Path params bind as $id; cast failure → FastAPI-shaped 422CREATE ROUTE item GET '/items/:id' AS SELECT $id::INTEGER AS id;
-- HTML when the single output column is named htmlCREATE ROUTE home GET '/' AS SELECT '<h1>quackapi</h1>' AS html;
-- Typed optional query param with constraintCREATE ROUTE search GET '/search' PARAM limit INTEGER DEFAULT 10 LE 100 ASSELECT $q::VARCHAR AS q, $limit::INTEGER AS limit;
-- POST mutation (JSON body fields bind as $name / $age)CREATE ROUTE create_user POST '/users' STATUS 201 ASSELECT $name::VARCHAR AS name, $age::INTEGER AS age;
-- Serve (background threads; shell stays usable)-- Optional: static_dir for unrouted GETs; cors_origins for browser CORSSELECT * FROM quackapi_serve(8000, static_dir := './static');
-- curl http://127.0.0.1:8000/hello → [{"msg":"world"}]-- curl http://127.0.0.1:8000/items/42 → [{"id":42}]-- curl http://127.0.0.1:8000/items/abc → 422 detail[loc=path,id]-- curl -X POST …/users -H 'Content-Type: application/json' -d '{"name":"a","age":3}'
SELECT * FROM quackapi_routes();SELECT * FROM quackapi_stop(8000);Über quackapi
quackapi
Ein HTTP-Framework der FastAPI-Klasse, das in DuckDB lebt. Routen sind DDL, Handler sind SQL, und die Anfragevalidierung ist das Typensystem der Datenbank.
These: das Backend IST die Datenbank
Ein konventioneller Stack serialisiert an jedem Hop (App-Server → Worker → DB → PDF-Microservice). quackapi verdichtet das zu einem DuckDB-Prozess:
browser → DuckDB [ quackapi(HTTP) · pdf · tera · fakeit · webbed · … ]Begleitende Community-Erweiterungen (pdf, tera, fakeit, crawler/webbed,
cronjob, curl_httpfs, …) werden in denselben Adressraum geladen. Ein Handler, der
ein PDF schwärzt, ist wörtlich SELECT pdf_redact(...) — kein RPC zwischen Schichten.
Showcase: die Closure-Redaction-Review-App (DB + HTML-UI + PDF-Wort-
boxen + POST-Entscheidungen + statische Assets) läuft als einzelner DuckDB-Prozess über
CREATE ROUTE + quackapi_serve.
CREATE ROUTE
CREATE [OR REPLACE] ROUTE <name> <METHOD> '<pattern>' [STATUS <n>] [REQUIRE <auth>] [GROUP <g>] [BODY SCHEMA '<json-schema>'] [PARAM <name> [<type>] [HEADER|COOKIE|QUERY …] [DEFAULT …] [GE|LE|…] …] AS <select>;- Methoden: GET, POST, PUT, DELETE, PATCH, HEAD.
- Pfadsegmente
:id/{id}und Query-/Body-Felder binden an$id. - Cast-/Constraint-Fehler liefern 422 im FastAPI-Format
{"detail":[{"loc":[...],"msg":...,"type":...}]}. - Die Standard-JSON-Antwort ist ein Array von Zeilenobjekten (SQL-Resultset-
Semantik). Eine einzelne Spalte namens
htmlodertextgibt rohes HTML/Text zurück;location/set_cookiesetzen Antwort-Header. quackapi_serve([port], host := …, static_dir := …, cors_origins := …, memory_limit := …)verwendet DuckDBs mitgeliefertes httplib (Hintergrund-Listener + Worker).- Eingebautes OpenAPI:
GET /openapi.json,GET /docs,GET /redoc.
Weitere DDL / Funktionen
- Auth:
CREATE AUTH … AS API_KEY | JWT (SECRET … [, ALGORITHM HS256]),REQUIREan Routen,quackapi_add_api_key,quackapi_auths, Claims als$claims_*. Die JWT-Prüfung ist in sich geschlossen (von DuckDB mitgeliefertes mbedtls +json_*-Claims) — hängt nicht von der Community-Erweiterungcryptoab (diese ist nur Hash/HMAC, kein JWT-Parse/exp/nbf/Claims). - Gruppen:
CREATE GROUP … WITH (prefix=…, auth=…, tags=…)— Pfadpräfix- Auth-Vererbung (
quackapi_groups()).
- Auth-Vererbung (
- Table API:
CREATE API FOR TABLE t [AT '/path'] [KEY 'id']→ nur GET-Liste- GET per Schlüssel.
- Queue:
CREATE QUEUE,quackapi_enqueue/dequeue/ack/nack, Tabellequackapi_jobs(ohne Broker; kombinieren Siecronjobfür Worker). - SSE:
CREATE STREAM … GET '/path' AS <select>(text/event-stream; WebSocket wird von httplib nicht unterstützt). - Policies:
CREATE ROW ACCESS POLICY/CREATE MASKING POLICY+ Bindung überALTER TABLE;quackapi_policies(). - Inspektion:
quackapi_routes(),quackapi_servers(),quackapi_http_util_name().
Plattformen und Build
Zielt nur auf DuckDB v1.5.5. C++17; hängt nur von DuckDBs mitgeliefertem httplib und mbedtls ab (kein vcpkg, kein libcurl). CI baut linux/macOS/windows_amd64; schließt wasm und Windows MinGW/rtools/arm64 aus.
Grenzen (offen)
- DuckDB Single-Writer / Dateikonkurrenz — kein High-Write-Multi-Tenant-OLTP.
- Der Serve-
memory_limit-Standard von 256 MB gilt nur, wenn nichts konfiguriert ist; verwenden Siememory_limit := '4GB'/SET quackapi_memory_limit(überschreibt nie ein Operator-SET memory_limit). - Request-Body maximal 8 MiB; JWT nur HS256 (kein RS256/OIDC); die Table API ist ein schreibgeschütztes Gerüst.
- Die Routenregistry ist instanzbezogen (DDL nach erneutem Öffnen erneut ausführen); Queue-Jobs
bleiben in
quackapi_jobserhalten.
Vollständige Referenz: https://github.com/asubbarao/quackapi
Entwurf der Community-Seite: https://github.com/asubbarao/quackapi/blob/main/docs/community-page.md
Hinzugefügte Funktionen
| function_name | function_type | description | comment | examples |
|---|---|---|---|---|
| quack_from_express | table | NULL | NULL | |
| quack_from_express_models | table | NULL | NULL | |
| quack_from_fastapi | table | NULL | NULL | |
| quack_from_fastapi_models | table | NULL | NULL | |
| quack_from_gin | table | NULL | NULL | |
| quack_from_gin_models | table | NULL | NULL | |
| quack_from_rails | table | NULL | NULL | |
| quack_from_rails_models | table | NULL | NULL | |
| quack_from_x_sql | scalar | NULL | NULL | |
| quack_from_x_sql_relpath | scalar | NULL | NULL | |
| quackapi_ack | scalar | NULL | NULL | |
| quackapi_add_api_key | table | NULL | NULL | |
| quackapi_authentication | scalar | NULL | NULL | |
| quackapi_authorization | scalar | NULL | NULL | |
| quackapi_auths | table | NULL | NULL | |
| quackapi_dequeue | table | NULL | NULL | |
| quackapi_enqueue | scalar | NULL | NULL | |
| quackapi_groups | table | NULL | NULL | |
| quackapi_http_util_name | scalar | NULL | NULL | |
| quackapi_nack | scalar | NULL | NULL | |
| quackapi_policies | table | NULL | NULL | |
| quackapi_queues | table | NULL | NULL | |
| quackapi_request | table | NULL | NULL | |
| quackapi_routes | table | NULL | NULL | |
| quackapi_serve | table | NULL | NULL | |
| quackapi_servers | table | NULL | NULL | |
| quackapi_stop | table | NULL | NULL | |
| quackapi_streams | table | NULL | NULL | |
| quackapi_verify_auth | scalar | NULL | NULL |
Überladene Funktionen
Diese Erweiterung fügt keine Funktionsüberladungen hinzu.
Hinzugefügte Typen
Diese Erweiterung fügt keine Typen hinzu.
Hinzugefügte Einstellungen
| name | description | input_type | scope | aliases |
|---|---|---|---|---|
| quackapi_compression | Enable Accept-Encoding response compression on quackapi_serve (zstd preferred, then gzip). Default true. Overridden by compression named parameter. | BOOLEAN | GLOBAL | [] |
| quackapi_compression_min_bytes | Minimum response body size (bytes) before compression. Default 256. Overridden by compression_min_bytes named parameter. | BIGINT | GLOBAL | [] |
| quackapi_cors_origins | CORS allowed origins for quackapi_serve (* or comma-separated list). Empty (default) disables CORS. Overridden by cors_origins named parameter. | VARCHAR | GLOBAL | [] |
| quackapi_http_client | Outbound HTTP client for httpfs/route fetches: auto|curl|httplib. Default auto prefers curl_httpfs (pool, HTTP/2, async) and falls back to httplib with http_client_reason on /healthz when unavailable. curl fails serve if curl_httpfs cannot INSTALL/LOAD. Overridden by http_client named parameter. Does not change the inbound HTTP server. | VARCHAR | GLOBAL | [] |
| quackapi_log_level | Log verbosity for quackapi_serve: silent|error|warn|info|debug. Default info. Overridden by log_level named parameter. | VARCHAR | GLOBAL | [] |
| quackapi_memory_limit | Memory limit applied by quackapi_serve (e.g. ‘4GB’, ‘512MB’). Empty (default): do not clobber a non-default DuckDB memory_limit; only apply the 256MB serve default when nothing was configured. Overridden by memory_limit named parameter. | VARCHAR | GLOBAL | [] |