Skip to main content

wasi_pg_client/
lib.rs

1//! # wasi-pg-client
2//!
3//! A production-grade PostgreSQL client library for WASI Preview 2.
4//!
5//! ## Quick Start
6//!
7//! ```rust,no_run
8//! use wasi_pg_client::{Connection, Config};
9//!
10//! #[wstd::main]
11//! async fn main() -> Result<(), wasi_pg_client::PgError> {
12//!     let config = Config::from_uri("postgresql://user:pass@localhost/mydb")?;
13//!     let mut conn = Connection::connect(&config).await?;
14//!
15//!     let result = conn.query("SELECT id, name FROM users").await?;
16//!     for row in result.iter() {
17//!         let id: i32 = row.get(0)?;
18//!         let name: String = row.get(1)?;
19//!         println!("{}: {}", id, name);
20//!     }
21//!
22//!     conn.close().await?;
23//!     Ok(())
24//! }
25//! ```
26//!
27//! ## Key Features
28//!
29//! - **Full PostgreSQL wire protocol v3** — simple and extended query protocols
30//! - **Parameterized queries** — SQL injection prevention with `$1`, `$2` syntax
31//! - **Prepared statements** — with automatic LRU caching
32//! - **Streaming results** — O(1) memory for large queries via `RowStream`
33//! - **Parameterized streaming** — `query_params_stream()` for streaming with parameters
34//! - **Transactions** — RAII guards with automatic rollback on drop
35//! - **Savepoints** — nested transaction scopes
36//! - **COPY protocol** — bulk import/export with CSV and binary support
37//! - **LISTEN/NOTIFY** — asynchronous pub/sub with timeout support
38//! - **TLS** — via rustls (pure Rust, WASI-compatible)
39//! - **SCRAM-SHA-256** and MD5 authentication
40//! - **Connection pooling** — via `wasi_pg_client::pool` module with `Mutex`-based thread safety
41//! - **Automatic reconnection** — with exponential backoff and session state rebuild
42//! - **Retry policies** — for transient errors (serialization failures, deadlocks)
43//! - **Query cancellation** — out-of-band via `CancelToken` (with TLS support)
44//! - **Runtime parameter setting** — `set_param()` with automatic re-application on reconnect
45//! - **Structured logging** — via `tracing`
46//! - **Compiles to `wasm32-wasip2`** and native targets
47//!
48//! ## Feature Flags
49//!
50//! | Feature | Default | Description |
51//! |---------|---------|-------------|
52//! | `tls` | ✅ | TLS support via rustls |
53//! | `scram` | ✅ | SCRAM-SHA-256 authentication |
54//! | `md5-auth` | ❌ | MD5 authentication (legacy) |
55//! | `pool` | ❌ | Connection pooling |
56//! | `tracing` | ✅ | Structured logging via tracing |
57//! | `uuid` | ❌ | UUID type support via uuid crate |
58//! | `serde-json` | ❌ | JSON type support via serde_json |
59//! | `chrono` | ❌ | chrono integration for date/time |
60//! | `test-native` | ❌ | Native transport for testing |
61//! | `tokio-transport` | ❌ | Tokio async TCP transport for native builds |
62//!
63//! ## WASI P2 Requirements
64//!
65//! This library targets `wasm32-wasip2`. When running in wasmtime, use:
66//! ```bash
67//! wasmtime run --wasi inherit-network --wasi inherit-env component.wasm
68//! ```
69//!
70//! The `getrandom` crate must be configured with `features = ["wasi"]` for
71//! cryptographic randomness (required for SCRAM auth and TLS).
72//!
73//! ## Tracing
74//!
75//! When the `tracing` feature is enabled, the library emits structured events
76//! at the following levels:
77//!
78//! | Level | What gets logged |
79//! |-------|-----------------|
80//! | ERROR | Fatal errors: auth failed, TLS handshake failed, reconnection failed |
81//! | WARN  | Recoverable problems: connection broken, transaction rolled back, dirty connection discarded |
82//! | INFO  | Normal operations: connection established/closed, query completed |
83//! | DEBUG | Detailed info: TCP connect, auth method, pool acquire/release, connection state |
84//! | TRACE | Wire-level detail: every protocol message, full SQL |
85//!
86//! ⚠️ TRACE may expose sensitive data. Use only in development, never in production.
87
88// Internal modules.
89mod auth;
90mod cancel;
91mod config;
92mod connection;
93pub mod copy;
94pub mod error;
95mod notification;
96pub mod protocol;
97mod query;
98mod transaction;
99pub mod types;
100
101// Transport scaffolding — directory module for TCP, TLS, and test transports.
102pub mod transport;
103
104// Reconnection and retry support.
105pub mod reconnect;
106
107// Internal tracing helpers (target constants, redaction).
108#[cfg(feature = "tracing")]
109mod tracing_ext;
110
111// ── Public API re-exports ──
112
113// Core types
114pub use cancel::CancelToken;
115pub use config::{Config, ConfigError, TargetSessionAttrs};
116pub use connection::{Connection, ConnectionState};
117pub use copy::{BinaryCopyWriter, CopyFormat, CopyIn, CopyOut};
118pub use notification::Notification;
119pub use query::result::{CommandTag, ExecuteResult, QueryResult};
120pub use query::row::{FieldDescription, Row};
121pub use query::stream::RowStream;
122pub use query::{
123    Cursor, CursorStream, Pipeline, PipelineResult, PreparedStatement, StatementCache,
124};
125pub use query::{Notice, NoticeHandler};
126pub use transaction::{IsolationLevel, Savepoint, Transaction, TransactionOptions};
127
128// Error types
129pub use error::sqlstate;
130pub use error::{retry, Error, PgError, PgServerError, PoolErrorVariant, Result};
131
132// Type system
133#[cfg(feature = "serde-json")]
134pub use types::JsonB;
135pub use types::{FromSql, Oid, ToSql, Type};
136
137// Transport (for custom transports / testing)
138pub use transport::{AsyncTransport, TransportError};
139
140// TLS (behind feature flag)
141#[cfg(feature = "tls")]
142pub use transport::tls::{SslMode, TlsConfig, TlsInfo};
143
144// Reconnection
145pub use reconnect::{classify_error, ErrorClass, ReconnectConfig, RetryPolicy, StaleConfig};
146pub use reconnect::{ConnectionHealth, SessionState};
147
148// Connection pooling (behind the `pool` feature flag).
149#[cfg(feature = "pool")]
150pub mod pool;
151
152// Protocol types (for advanced use)
153pub use protocol::types::{FormatCode, TransactionStatus};
154pub use protocol::BackendMessage;
155pub use protocol::FrontendMessage;
156
157/// Builder type alias for [`Config`].
158///
159/// The `Config` type already uses the builder pattern via its `new()` method
160/// and chainable setters. This alias is provided for discoverability.
161pub type ConfigBuilder = Config;
162
163// Prelude for convenient imports.
164pub mod prelude {
165    //! Common imports for working with wasi-pg-client.
166    //!
167    //! ```rust,no_run
168    //! use wasi_pg_client::prelude::*;
169    //! ```
170
171    pub use super::error::PgServerError;
172    pub use super::{Config, Connection, Error, PgError, Result};
173    pub use crate::types::{FromSql, ToSql, Type};
174}
175
176/// Runtime sanity check that `getrandom` is properly configured for WASI P2.
177///
178/// Call this early (e.g. during `Connection::connect`) to get a clear panic
179/// message instead of a cryptic runtime failure deep inside crypto code.
180pub fn ensure_random_available() {
181    let mut buf = [0u8; 1];
182    if getrandom::fill(&mut buf).is_err() {
183        panic!(
184            "wasi-pg-client: getrandom failed. \
185             Ensure 'getrandom' is compiled with features=[\"custom\"] \
186             or a WASI-compatible backend when targeting wasm32-wasip2."
187        );
188    }
189}