oxisql-postgres 0.1.0

Pure-Rust PostgreSQL backend for OxiSQL via tokio-postgres + OxiTLS (no libpq, no OpenSSL)
Documentation

oxisql-postgres — Pure-Rust PostgreSQL backend for OxiSQL

Crates.io License

oxisql-postgres provides PgConnection, which implements oxisql_core::Connection over tokio-postgres. There are no C bindings — no libpq, no openssl-sys. TLS uses rustls + rustls-rustcrypto.

Installation

[dependencies]
oxisql-postgres = "0.1.0"

Quick Start

use oxisql_postgres::{PgConnection, TlsMode};
use oxisql_core::Connection;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // No TLS
    let conn = PgConnection::connect(
        "host=localhost port=5432 user=postgres password=secret dbname=mydb",
        TlsMode::Disabled,
    ).await?;

    conn.execute("CREATE TABLE IF NOT EXISTS t (id BIGINT, val TEXT)", &[]).await?;
    conn.execute("INSERT INTO t VALUES ($1, $2)", &[&1i64, &"hello"]).await?;

    let rows = conn.query("SELECT id, val FROM t WHERE id = $1", &[&1i64]).await?;
    let id: i64 = rows[0].try_get("id")?;
    println!("id={id}");
    Ok(())
}

Quick Start (TLS via OxiTLS)

use oxisql_postgres::{PgConnection, TlsMode};

let root_store = oxitls::webpki_root_certs();
let client_cfg = oxitls::client_config(root_store)
    .map_err(|e| format!("TLS cfg: {e}"))?;

let conn = PgConnection::connect(
    "host=db.example.com port=5432 user=postgres sslmode=require",
    TlsMode::Rustls(client_cfg),
).await?;

API Overview

PgConnection

Method / Function Description
PgConnection::connect(conn_str, tls) Connect using a libpq-style connection string
PgConnection::connect_url(url, tls) Connect using a postgres:// URL
PgConnection::from_client(client, handle) Wrap an existing tokio_postgres::Client
parse_pg_conn_str(s) Parse a connection string into PgConnParts

The connection string format follows the libpq key=value syntax: host=, port=, user=, password=, dbname=, sslmode=.

TlsMode

Variant Description
TlsMode::Disabled No TLS (plain TCP)
TlsMode::Rustls(ClientConfig) TLS via rustls + rustls-rustcrypto

PgConnectionBuilder

Fluent builder for fine-grained connection configuration:

use oxisql_postgres::PgConnectionBuilder;

let conn = PgConnectionBuilder::new()
    .host("localhost")
    .port(5432)
    .user("postgres")
    .password("secret")
    .dbname("mydb")
    .connect_timeout(std::time::Duration::from_secs(5))
    .tls(TlsMode::Disabled)
    .connect()
    .await?;

PgTransaction

Obtained via conn.transaction(). Implements oxisql_core::Transaction.

Supports savepoint(), release_savepoint(), and rollback_to_savepoint().

Dropping a PgTransaction without explicit commit schedules a ROLLBACK on the active Tokio runtime.

Extended type mapping

PostgreSQL type OxiSQL Value variant
BOOLEAN Value::Bool
INT2 / INT4 / INT8 Value::I64
FLOAT4 / FLOAT8 Value::F64
TEXT / VARCHAR / CHAR Value::Text
BYTEA Value::Blob
TIMESTAMP / TIMESTAMPTZ Value::Timestamp (µs since epoch)
DATE Value::Date (days since epoch)
TIME / TIMETZ Value::Time (µs since midnight)
UUID Value::Uuid (u128)
JSON / JSONB Value::Json
NUMERIC / DECIMAL Value::Decimal (string)
INTEGER[] / TEXT[] etc. Value::Array

Advanced features

Prepared statements

let stmt = conn.prepare("SELECT * FROM users WHERE id = $1").await?;
let rows = stmt.query(&[&42i64]).await?;

Column description (without executing)

let desc: Vec<ColumnDescription> = conn.describe("SELECT id, name FROM users").await?;
// desc[0].name == "id", desc[0].type_name == "int8"

Pipeline (batch multiple queries in one network round-trip)

use oxisql_postgres::PgPipeline;
let mut pipeline = conn.pipeline();
pipeline.add_execute("INSERT INTO t VALUES ($1)", &[&1i64]);
pipeline.add_query("SELECT * FROM t");
let results: Vec<PipelineResult> = pipeline.run().await?;

LISTEN / NOTIFY

conn.listen("my_channel").await?;
let mut stream: NotificationStream = conn.notifications();
// stream yields PgNotification { channel, payload }

COPY (bulk load/unload)

The copy module exposes copy_in and copy_out for PostgreSQL's COPY protocol.

Wire Protocol

Uses Frontend/Backend Protocol version 3 via tokio-postgres:

API path Wire mode
execute / query Extended-query protocol
execute_batch Simple-query protocol
prepare / describe Extended-query Parse + Describe
pipeline Multiple extended-query cycles, single send buffer

Schema introspection

tables(), columns(table), indexes(table), foreign_keys(table) are all supported and query the PostgreSQL information schema / system catalogs.

Known Limitations

  • Logical replication (Streaming Replication Protocol) is not exposed.
  • LISTEN notifications are only available on connections created via PgConnection::connect (not from_client).
  • PostgreSQL protocol v2 (pre-7.4 servers) is not supported.

Test Status

As of 2026-05-30: 49 tests passing, 36 skipped (live-Postgres tests are #[ignore]d and skipped when no server is available).

License

Apache-2.0 — COOLJAPAN OU (Team Kitasan)