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 handler
CREATE ROUTE hello GET '/hello' AS SELECT 'world' AS msg;
-- Path params bind as $id; cast failure → FastAPI-shaped 422
CREATE ROUTE item GET '/items/:id' AS SELECT $id::INTEGER AS id;
-- HTML when the single output column is named html
CREATE ROUTE home GET '/' AS SELECT '<h1>quackapi</h1>' AS html;
-- Typed optional query param with constraint
CREATE ROUTE search GET '/search'
PARAM limit INTEGER DEFAULT 10 LE 100
AS
SELECT $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 AS
SELECT $name::VARCHAR AS name, $age::INTEGER AS age;
-- Serve (background threads; shell stays usable)
-- Optional: static_dir for unrouted GETs; cors_origins for browser CORS
SELECT * 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 html oder text gibt rohes HTML/Text zurück; location / set_cookie setzen 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]), REQUIRE an 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-Erweiterung crypto ab (diese ist nur Hash/HMAC, kein JWT-Parse/exp/nbf/Claims).
  • Gruppen: CREATE GROUP … WITH (prefix=…, auth=…, tags=…) — Pfadpräfix
    • Auth-Vererbung (quackapi_groups()).
  • 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, Tabelle quackapi_jobs (ohne Broker; kombinieren Sie cronjob fü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 über ALTER 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 Sie memory_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_jobs erhalten.

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 []