A self-contained PostgreSQL driver for Tachyon — no libpq. It speaks the v3 wire
protocol over a plain TCP socket: the startup handshake, SCRAM-SHA-256
authentication (the modern Postgres default, with MD5 and cleartext fallbacks),
and the simple query protocol. Rows come back as Json objects keyed by column
name, exactly like the sqlite driver, so column access is the built-in Json.
Add the dependency to your Tachyon.toml:
deps = ["git+https://github.com/vahan-gev/tachyon-postgres#v0.1.0"]import postgres.db as pg;
function main(): void {
let db = pg.pgConnect("127.0.0.1", 5432, "app_user", "secret", "app_db") catch (e) {
eprintln(`cannot connect: ${pg.pgError()}`);
return;
};
pg.pgExec(db, "create table if not exists users (id serial primary key, name text)") catch 0L;
pg.pgExec(db, `insert into users (name) values ('${pg.pgEscape("Ada")}')`) catch 0L;
for (row in pg.pgQuery(db, "select id, name from users order by id") catch Vec()) {
println(`${row["id"].asInt()}: ${row["name"].asString()}`);
}
pg.pgClose(db);
}Numeric and boolean columns arrive as native JSON (so .asInt(), .asDouble(),
.asBool() work); everything else is a JSON string (.asString()). SQL NULL
is JSON null — test it with .isNull().
A concurrent server wants one connection per in-flight request, not one per
process and not a fresh TCP+auth per query. pgPool opens a fixed set of
connections and hands them out; it returns a Box<PgPool>, so passing it to
worker threads shares the one pool rather than copying it:
let pool = pg.pgPool("127.0.0.1", 5432, "app_user", "secret", "app_db", 8)?;
// in each worker thread:
let conn = pool.lease(); // waits if all are busy
let rows = pg.pgQuery(conn, "select now()") catch Vec();
pool.release(conn); // always return it
// on shutdown, when idle:
pool.closeAll();lease()/release() are safe to call from many threads at once — access to
each connection is serialised, so no two threads ever share a socket.
Implemented: startup + auth (SCRAM-SHA-256 / MD5 / cleartext), the simple query protocol (text results decoded to typed JSON), affected-row counts, error messages, and the pool.
Not implemented: the extended/prepared-statement protocol (so bound
parameters are a roadmap item — use pgEscape for now), binary result
formats, COPY, LISTEN/NOTIFY, and SSL. As with the HTTP server, run over a
trusted network or terminate TLS at a proxy.
tools/pgtest.sh stands up a throwaway cluster, runs the suite against it, and
tears it down. The tests also run (and skip cleanly) as part of tachyon test
when no PGTEST_* environment is set.