NURLNURL registrynurl-lang.org →

← psql

psql 0.2.3 API

pg.nu

packages/psql/src/pg.nu — PostgreSQL frontend/backend protocol v3 in pure NURL. No libpq: the wire protocol, the authentication (trust / cleartext / MD5 / SCRAM-SHA-256) and the optional TLS upgrade (PostgreSQL's SSLRequest, then the pure-NURL TLS client) are all implemented here, so a secure connection works on a host with nothing installed.

( pg_connect host port user password database sslmode ) → !*PgConn PgErr ( pg_query conn sql ) → !PgResult PgErr ( pg_close conn ) → v

sslmode: 0 disable · 1 prefer (TLS if offered, no verify) · 2 require (TLS mandatory, no cert check) · 3 verify-full (TLS + chain/hostname).

PgResult is a flat row-major cell table (see the accessors at the bottom): nested Vecs are avoided for robustness; NULLs are tracked in a parallel flag array.

API

: | PgErr

: | PgErr {
    PgConnFail  // could not open the TCP socket
    PgTls  // TLS upgrade failed (refused, or handshake/cert error)
    PgProtocol  // malformed/unexpected backend message
    PgAuth  // authentication failed or unsupported method
    PgServerError  // backend ErrorResponse — see . conn lasterr
    PgQuery  // query-time failure — see . conn lasterr
    PgNeedPassword  // server asked for a password but none was supplied
}

SSLRequest magic (1234 << 16 | 5679) and the protocol-3.0 version word.

@ pg_err_name PgErr e → s

: PgConn

: PgConn {
    i tls  // 0 plaintext, 1 TLS
    i raw  // raw socket handle (plaintext reads; fd the TLS layer took over)
    TcpConn tcp  // plaintext transport (writes via tcp_write_all)
    * TlsConn tc  // TLS transport (when tls = 1)
    ( Vec u ) rxbuf  // backend bytes not yet split into messages
    String lasterr  // last ErrorResponse / failure text
    i be_pid
    i be_key
    String srv_ver  // server_version from ParameterStatus (for the banner)
    String db_name  // connection identity, for the banner and \conninfo
    String user_name
    String host_name
}

: PgMsg

: PgMsg {
    i mtype
    ( Vec u ) payload
}

: PgResult

: PgResult {
    i ncols
    i nrows
    ( Vec String ) colnames
    ( Vec String ) cells  // NULL rendered as empty String; see nulls
    ( Vec u ) nulls  // 1 = SQL NULL
    String tag  // CommandComplete tag (e.g. "SELECT 3")
}

Row-major result table. cell(r,c) lives at index r*ncols+c.

@ pg_connect s host i port s user s password s database i sslmode → !*PgConn PgErr

@ pg_query * PgConn c s sql → !PgResult PgErr

── simple query ──────────────────────────────────────────────────

@ pg_result_col PgResult r i idx → String

── result accessors ──────────────────────────────────────────────

@ pg_result_is_null PgResult r i row i col → b

@ pg_result_cell PgResult r i row i col → String

@ pg_result_free PgResult r → v

@ pg_close * PgConn c → v

── teardown ──────────────────────────────────────────────────────


scram.nu

packages/psql/src/scram.nu — SCRAM-SHA-256 client (RFC 5802 / RFC 7677), the SASL mechanism PostgreSQL uses for password authentication.

Pure NURL on top of the stdlib crypto (SHA-256 / HMAC / PBKDF2 / base64). Channel binding is not used ("n,," / "c=biws"), matching libpq's default SCRAM-SHA-256 (not the -PLUS variant).

( scram_client_first_bare nonce ) → String "n=,r=<nonce>" ( scram_compute password cfb server_first ) → ScramResult

password is the raw password bytes (SASLprep is the identity map for the ASCII passwords overwhelmingly used in practice). cfb is the client-first-bare returned above; server_first is the server's SASLContinue payload. The result carries the client-final message to send and the base64 server signature to check against the SASLFinal.

API

: ScramResult

: ScramResult {
    b ok
    String client_final
    String server_sig
}

@ scram_client_first_bare s nonce → String

client-first-bare: PostgreSQL ignores the SCRAM username (it uses the startup username), so we send an empty n=.

@ scram_compute ( Vec u ) password String cfb String server_first → ScramResult


main.nu

packages/psql/src/main.nu — the psql command: a pure-NURL PostgreSQL client. Connects over the v3 wire protocol with optional TLS (pure-NURL, no libpq / no OpenSSL needed on the target), authenticates with trust / cleartext / MD5 / SCRAM-SHA-256, and behaves like psql for everyday use: aligned result tables, backslash meta-commands, a multi-line REPL terminated by ';', and one-shot -c.

psql [flags] ["postgres://user:pass@host:port/db?sslmode=..."] -h HOST host (default $PGHOST or localhost) -p PORT port (default $PGPORT or 5432) -U USER user (default $PGUSER or postgres) -d DB database (default $PGDATABASE or the user) -c SQL run one command and exit; otherwise read from stdin --sslmode M disable | prefer | require | verify-full (default prefer) Password is taken from $PGPASSWORD.

Meta-commands (when no statement is pending): \dt list tables \l list databases \d TABLE describe a table \du list roles \dn list schemas \conninfo connection info \? this help \q quit

API

& c @ isatty i32 fd → i32

& c @ nurl_read_password s prompt → s

: ConnInfo

: ConnInfo {
    String host
    i port
    String user
    String password
    String database
    i sslmode
    b has_url
}

postgres://[user[:pass]@]host[:port][/db][?sslmode=M]

@ main → i