Skip to main content

Connection

Struct Connection 

Source
pub struct Connection { /* private fields */ }
Expand description

A PostgreSQL connection over TCP, TLS, or Unix domain socket.

All I/O is synchronous using sync_io::Stream which wraps TcpStream, UnixStream, or rustls::StreamOwned. No async runtime is required.

§Thread safety

Connection is Send but not Sync — it must be used by one thread at a time. This matches the PostgreSQL wire protocol which is inherently sequential.

§Example

use bsql_driver_postgres::{Connection, Config};

let config = Config::from_url("postgres://user:pass@localhost/db")?;
let mut conn = Connection::connect(&config)?;

let hash = bsql_driver_postgres::hash_sql("SELECT 1 AS n");
let result = conn.query("SELECT 1 AS n", hash, &[])?;
assert_eq!(result.len(), 1);

Implementations§

Source§

impl Connection

Source

pub fn connect(config: &Config) -> Result<Self, DriverError>

Connect to PostgreSQL and complete the startup/auth handshake. Fully synchronous — no tokio runtime needed.

Transport is selected automatically based on config:

  • host starting with / -> Unix domain socket
  • Otherwise -> TCP (with optional TLS upgrade based on ssl mode)
§Errors

Returns an error if the connection fails, TLS upgrade fails (when required), or authentication fails.

Source

pub fn connect_arc(config: Arc<Config>) -> Result<Self, DriverError>

Connect using a shared config. Avoids cloning the Config strings.

Preferred by the connection pool, which holds Arc<Config> and opens new connections without 5 String clones per open.

Source

pub fn prepare_only( &mut self, sql: &str, sql_hash: u64, ) -> Result<(), DriverError>

Prepare a statement without executing it (Parse+Describe+Sync only).

If the statement is already cached, this is a no-op.

Source

pub fn query( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], ) -> Result<QueryResult, DriverError>

Execute a prepared query and return rows.

Optimized path: after send_pipeline flushes, we parse BindComplete + DataRow* + CommandComplete + ReadyForQuery directly from stream_buf, avoiding per-message read_message_buffered overhead. DataRow payloads are parsed in-place from stream_buf into a response buffer.

Note: arena is not used — row data is stored in an inline resp_buf owned by QueryResult. The parameter is kept for API compatibility with the streaming path, but callers may pass any &mut Arena.

Source

pub fn execute_monolithic( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], ) -> Result<u64, DriverError>

Monolithic execute — everything in one function, no intermediate calls.

Inlines the entire send_pipeline + response parsing path for INSERT/UPDATE/DELETE. On cache hit: template copy + param patch + write_all + inline message parsing. No send_pipeline(), no flush_write(), no refill_stream_buf(). The compiler sees the entire path and can optimize globally.

On cache miss (first execution of a statement), falls through to the cold execute_with_prepare path.

Source

pub fn execute( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], ) -> Result<u64, DriverError>

Execute a query without result rows (INSERT/UPDATE/DELETE).

Delegates to execute_monolithic which inlines the entire send + receive path. Kept for API compatibility.

Source

pub fn execute_pipeline( &mut self, sql: &str, sql_hash: u64, param_sets: &[&[&(dyn Encode + Sync)]], ) -> Result<Vec<u64>, DriverError>

Execute the same prepared statement N times with different parameters in a single pipeline round-trip.

Sends all N Bind+Execute messages followed by one Sync. PostgreSQL processes them in order and returns N BindComplete+CommandComplete responses followed by one ReadyForQuery.

This is a real optimization for bulk operations: N inserts in a transaction become 1 round-trip instead of N round-trips.

Returns the number of affected rows for each parameter set.

Source

pub fn for_each<F>( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], f: F, ) -> Result<(), DriverError>
where F: FnMut(PgDataRow<'_>) -> Result<(), DriverError>,

Process each row via a closure with zero-copy PgDataRow.

Source

pub fn for_each_raw_monolithic<F>( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], f: F, ) -> Result<(), DriverError>
where F: FnMut(&[u8]) -> Result<(), DriverError>,

Monolithic for_each_raw — everything in one function, no intermediate calls.

Inlines the entire send_pipeline + response parsing path for SELECT queries processed via a raw byte closure. On cache hit: template copy + param patch + write_all + inline DataRow streaming + inline ReadyForQuery. No send_pipeline(), no flush_write(), no refill_stream_buf().

On cache miss (first execution of a statement), falls through to the cold for_each_raw_with_prepare path.

Source

pub fn for_each_raw<F>( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], f: F, ) -> Result<(), DriverError>
where F: FnMut(&[u8]) -> Result<(), DriverError>,

Process each DataRow as raw bytes — fastest path.

Delegates to for_each_raw_monolithic which inlines the entire send + receive path. Kept for API compatibility.

Source

pub fn simple_query(&mut self, sql: &str) -> Result<(), DriverError>

Simple query protocol — for non-prepared SQL (BEGIN, COMMIT, SET, etc.).

Source

pub fn simple_query_rows( &mut self, sql: &str, ) -> Result<Vec<SimpleRow>, DriverError>

Execute a simple (text protocol) query and return all result rows.

Source

pub fn prepare_describe( &mut self, sql: &str, ) -> Result<PrepareResult, DriverError>

Prepare a statement without executing it (Parse+Describe+Sync only).

Returns column and parameter metadata. Uses the unnamed statement "" so there is no cache pollution.

Source

pub fn wait_for_notification(&mut self) -> Result<(String, String), DriverError>

Block until a NotificationResponse arrives on this connection.

Reads raw messages from the stream and skips everything except NotificationResponse. Returns the (channel, payload) pair. Used by the listener to receive LISTEN/NOTIFY events.

This method never returns Ok for non-notification messages – it loops internally, discarding ParameterStatus, NoticeResponse, etc.

Source

pub fn cancel(&self) -> Result<(), DriverError>

Cancel the currently running query on this connection.

Opens a NEW TCP connection to the same host:port and sends a CancelRequest message (16 bytes: length=16, code=80877102, pid, secret). The cancel connection is closed immediately after sending.

Source

pub fn set_read_timeout( &self, timeout: Option<Duration>, ) -> Result<(), DriverError>

Set the read timeout on the underlying socket.

Used by listeners to poll for notifications with a timeout. None means block indefinitely.

Source

pub fn query_streaming_start( &mut self, sql: &str, sql_hash: u64, params: &[&(dyn Encode + Sync)], chunk_size: i32, ) -> Result<(Arc<[ColumnDesc]>, bool), DriverError>

Begin a streaming query using the PG extended query protocol with Execute(max_rows=chunk_size).

Returns column metadata and puts the connection into streaming mode. The caller must repeatedly call streaming_next_chunk() until it returns Ok(false) (all rows consumed) before issuing any other query on this connection.

Uses the unnamed portal "" which stays open between Execute calls as long as Sync is NOT sent. We use Flush (not Sync) to force PG to send buffered output without destroying the portal.

Source

pub fn streaming_next_chunk( &mut self, arena: &mut Arena, all_col_offsets: &mut Vec<(usize, i32)>, ) -> Result<bool, DriverError>

Read the next chunk of rows from an in-progress streaming query.

Returns Ok(true) if more rows are available (PortalSuspended), Ok(false) when all rows have been consumed (CommandComplete).

After CommandComplete, this method sends Sync and reads ReadyForQuery, returning the connection to a clean protocol state.

Source

pub fn streaming_send_execute( &mut self, chunk_size: i32, ) -> Result<(), DriverError>

Send Execute+Flush for the next chunk of a streaming query.

Must be called before streaming_next_chunk() on the 2nd and subsequent chunks (the first chunk’s Execute is sent by query_streaming_start).

Uses Flush (not Sync) to keep the unnamed portal alive.

Source

pub fn is_streaming(&self) -> bool

Whether a streaming query is in progress.

Source

pub fn close(self) -> Result<(), DriverError>

Send Terminate and close the connection.

Source

pub fn is_idle(&self) -> bool

Whether the connection is in an idle transaction state.

Source

pub fn is_in_transaction(&self) -> bool

Whether the connection is in a transaction.

Source

pub fn is_in_failed_transaction(&self) -> bool

Whether the connection is in a failed transaction.

Source

pub fn touch(&mut self)

Record that the connection was just used.

Source

pub fn idle_duration(&self) -> Duration

How long since this connection last completed a query.

Source

pub fn query_counter(&self) -> u64

Monotonic query counter — incremented on every query/execute.

Source

pub fn parameter(&self, name: &str) -> Option<&str>

Get a server parameter value.

Source

pub fn server_params(&self) -> &[(Box<str>, Box<str>)]

All server parameters received during startup.

Source

pub fn pid(&self) -> i32

Backend process ID.

Source

pub fn secret_key(&self) -> i32

Backend secret key.

Source

pub fn drain_notifications(&mut self) -> Vec<Notification>

Drain all buffered notifications.

Source

pub fn pending_notification_count(&self) -> usize

Number of pending notifications.

Source

pub fn set_max_stmt_cache_size(&mut self, size: usize)

Set the maximum number of cached prepared statements.

Source

pub fn stmt_cache_len(&self) -> usize

Number of currently cached prepared statements.

Source

pub fn created_at(&self) -> Instant

When this connection was created.

Trait Implementations§

Source§

impl Debug for Connection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.