Skip to main content

oxisql_postgres/
lib.rs

1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3//! `oxisql-postgres` — Pure-Rust PostgreSQL backend for OxiSQL.
4//!
5//! Provides [`PgConnection`], which implements [`oxisql_core::Connection`]
6//! over `tokio-postgres` (no `libpq`, no C bindings) with TLS support via
7//! `rustls` + the pure-Rust RustCrypto provider from `oxitls`
8//! (no `ring`, no `openssl-sys`).
9//!
10//! # Wire protocol compliance
11//!
12//! This crate uses the PostgreSQL **Frontend/Backend Protocol version 3**
13//! (introduced in PostgreSQL 7.4) as implemented by `tokio-postgres`.  All
14//! client–server communication is framed according to that specification:
15//!
16//! | API path                          | Wire mode                             |
17//! |-----------------------------------|---------------------------------------|
18//! | `execute` / `query`               | Extended-query protocol (`Parse` → `Bind` → `Execute` → `Sync`) |
19//! | `execute_batch` / `begin_txn`     | Simple-query protocol (`Query` message) |
20//! | `query_binary`                    | Extended-query with explicit type OIDs; results decoded in **binary format** (format code 1) |
21//! | `prepare` / `describe`            | Extended-query `Parse` + `Describe` only (no `Execute`) |
22//! | `pipeline`                        | Multiple extended-query cycles flushed as a single send buffer |
23//!
24//! ## Limitations
25//!
26//! * **Logical replication** via the `pgoutput` plugin is available behind the
27//!   `replication` feature (see [`PgReplicationConnection`]); this is an MVP:
28//!   no in-progress-transaction streaming, no two-phase commit, and no
29//!   physical replication. (Binary-format tuple values and array-typed
30//!   columns *are* decoded, in both text and binary format, even though this
31//!   MVP never actually negotiates `binary 'true'` with the server.)
32//! * **Cancellation** via the `CancelRequest` flow is available through
33//!   [`PgConnection::cancel_token`] → [`PostgresCancelToken::cancel_query`].
34//!   It is not exposed at the `Connection` trait level; individual queries can
35//!   also be cancelled by dropping the `Future`.
36//! * Notification delivery via `LISTEN` is only available on connections
37//!   created through [`PgConnection::connect`] (not `from_client`), because
38//!   the background `Connection` driver that routes `NotificationResponse`
39//!   messages is only spawned in that code path.
40//! * PostgreSQL protocol v2 (pre-7.4) servers are not supported.
41//!
42//! # Quick start (no TLS)
43//!
44//! ```rust,no_run
45//! # #[tokio::main]
46//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
47//! use oxisql_postgres::{PgConnection, TlsMode};
48//! use oxisql_core::Connection;
49//!
50//! let conn = PgConnection::connect(
51//!     "host=localhost port=5432 user=postgres password=secret",
52//!     TlsMode::Disabled,
53//! ).await?;
54//!
55//! conn.execute("CREATE TABLE IF NOT EXISTS t (id BIGINT)", &[]).await?;
56//! # Ok(())
57//! # }
58//! ```
59//!
60//! # Quick start (TLS via OxiTLS)
61//!
62//! ```rust,no_run
63//! # #[tokio::main]
64//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
65//! use oxisql_postgres::{PgConnection, TlsMode};
66//!
67//! // Build a ClientConfig trusting the Mozilla CA bundle.
68//! // Requires the "pure" + "webpki-roots" features of oxitls (the defaults).
69//! let root_store = oxitls::webpki_root_certs();
70//! let client_cfg = oxitls::client_config(root_store)
71//!     .map_err(|e| format!("TLS cfg: {e}"))?;
72//!
73//! let conn = PgConnection::connect(
74//!     "host=db.example.com port=5432 user=postgres sslmode=require",
75//!     TlsMode::Rustls(client_cfg),
76//! ).await?;
77//! # Ok(())
78//! # }
79//! ```
80
81mod builder;
82mod connection;
83mod copy;
84mod error;
85mod notify;
86mod pipeline;
87mod prepared;
88#[cfg(feature = "replication")]
89mod replication;
90mod tls;
91pub mod types;
92
93pub use builder::{PgConnectionBuilder, TlsMode};
94pub use connection::{
95    parse_pg_conn_str, ColumnDescription, PgConnParts, PgConnection, PgTransaction,
96    PostgresCancelToken,
97};
98pub use error::PgError;
99pub use notify::{NotificationStream, PgNotification};
100pub use pipeline::{PgPipeline, PipelineResult};
101pub use prepared::PgPrepared;
102#[cfg(feature = "replication")]
103pub use replication::{
104    pg_micros_to_unix_micros, tuple_to_values, unix_micros_to_pg_micros, CellValue, ColumnSpec,
105    CreatedSlot, IdentifySystem, LogicalReplicationMessage, Lsn, PgReplicationConnection,
106    RelationBody, ReplicaIdentity, ReplicationEvent, ReplicationStream, TupleColumn, TupleData,
107};
108pub use types::{pg_row_to_row, value_to_param, OwnedParam};