These libraries are experimental. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.
Pg
@korulang/pg@0.0.1Native PostgreSQL wire-protocol driver for Koru — no libpq, event-loop-native, zero-copy rows
pg/index.kz · 10 tors
@korulang/pg — native pgwire driver. No libpq, no C object model:
the connection owns its recv buffer, rows are zero-copy views into
it, and the fd is the caller's to drive (block on it, or register it
on an event loop — the codec doesn't care which).
Design doc: ./DESIGN.md — spike-proven numbers inline there.
conn = pg:connect(host, port, user, database): c
pg:query(conn, "SELECT ...") — simple protocol, blocks
pg:row.next(conn) -> bool — advance to next DataRow
pg:col.bytes(conn, i) -> string — view into rx buffer
pg:disconnect(conn)
Phantom lifecycles
Derived from the phantom labels in the declarations below — state! issues an
obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.
Conn 2 states connected!// --- surface ------------------------------------------------------------
~pub tor connect { host: string, port: i64, user: string, database: string }
| ok *Conn<connected!>
| err string~pub tor socket { conn: *Conn<*> } -> i32~pub tor set-nonblocking { conn: *Conn<*> }~pub tor disconnect { conn: *Conn<!connected> }// Simple-protocol query: sends 'Q'. Result frames are consumed by
// row.next / col.bytes until ready-for-query state.
~pub tor query { conn: *Conn<connected>, sql: string }
| ok i64
| err string// Advance the conn to the next DataRow. Returns true while a row is in
// the rx buffer ready for col.bytes; false at CommandComplete/Z/err.
// Blocking: reads the socket until the next row or stream end.
~pub tor row.next { conn: *Conn<connected> } -> bool// --- extended protocol: prepare once, pipeline binds ---------------------
//
// Parse 'sql' into a named statement on the server. One-shot setup —
// drains the ParseComplete + ReadyForQuery inside the call.
~pub tor prepare { conn: *Conn<connected>, name: string, sql: string }
| ok i64
| err string// Append a Bind+Execute for a prepared statement — does NOT send.
// One text param per call for now (the world-row queries take one int).
~pub tor bind.exec { conn: *Conn<connected>, stmt: string, param: string }// Append 'S' and flush conn.tx to the socket — one roundtrip for every
// bind.exec queued since the last send.
~pub tor send.pending { conn: *Conn<connected> }
| ok i64
| err string// View of column `i` in the current row — a slice into the rx buffer,
// valid until row.next advances. Zero-copy by construction.
~pub tor col.bytes { conn: *Conn<connected>, i: i64 } -> string