vahan-gev/tachyon-postgres

From-scratch PostgreSQL driver for Tachyon (SCRAM-SHA-256, connection pool), no libpq

★ 1Forks 0CGitHub ↗Compare

README

postgres

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.

Using it

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().

Connection pool

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.

Scope and limits

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.

Testing

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.

Contributors

vahan-gev

Issues