Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/launchbadge/sqlx/llms.txt

Use this file to discover all available pages before exploring further.

SQLx decouples query construction from query execution through two core traits: Executor and Execute. This lets you write functions that accept a pool, a single connection, or a transaction without knowing which one they receive — a pattern that makes code more testable and reusable.
These traits are re-exported in sqlx::prelude. Add use sqlx::prelude::*; to bring them into scope alongside the other commonly used SQLx traits.

Executor trait

pub trait Executor<'c>: Send + Debug + Sized {
    type Database: Database;

    fn execute<'e, 'q: 'e, E>(self, query: E)
        -> BoxFuture<'e, Result<DB::QueryResult, Error>>
    where E: Execute<'q, Self::Database>;

    fn fetch<'e, 'q: 'e, E>(self, query: E)
        -> BoxStream<'e, Result<DB::Row, Error>>
    where E: Execute<'q, Self::Database>;

    fn fetch_many<'e, 'q: 'e, E>(self, query: E)
        -> BoxStream<'e, Result<Either<DB::QueryResult, DB::Row>, Error>>
    where E: Execute<'q, Self::Database>;

    fn fetch_all<'e, 'q: 'e, E>(self, query: E)
        -> BoxFuture<'e, Result<Vec<DB::Row>, Error>>
    where E: Execute<'q, Self::Database>;

    fn fetch_one<'e, 'q: 'e, E>(self, query: E)
        -> BoxFuture<'e, Result<DB::Row, Error>>
    where E: Execute<'q, Self::Database>;

    fn fetch_optional<'e, 'q: 'e, E>(self, query: E)
        -> BoxFuture<'e, Result<Option<DB::Row>, Error>>
    where E: Execute<'q, Self::Database>;

    fn prepare<'e>(self, query: SqlStr)
        -> BoxFuture<'e, Result<DB::Statement, Error>>;
}
Executor is the trait that knows how to run a query. Its methods correspond directly to the finalizer methods on query types; when you call .fetch_one(&pool), the pool is the executor.

Implementations

TypeGuarantees same physical connection?
&Pool<DB>No — each call may use a different connection from the pool.
&mut DB::ConnectionYes — all calls use the same connection.
&mut PoolConnection<DB>Yes — dereference to &mut *conn first.
&mut Transaction<'_, DB>Yes — dereference to &mut *tx first.
Transaction and PoolConnection no longer implement Executor directly. Dereference them before passing to an executor-accepting function: use &mut *tx or &mut *conn.

Writing generic functions

Accept impl Executor<'_, Database = DB> to write a function that works with any of the above handle types.
use sqlx::{Executor, Postgres};

async fn fetch_user(
    db: impl Executor<'_, Database = Postgres>,
    id: i64,
) -> sqlx::Result<Option<User>> {
    sqlx::query_as("SELECT id, name, email FROM users WHERE id = $1")
        .bind(id)
        .fetch_optional(db)
        .await
}

// Works with a pool reference...
let user = fetch_user(&pool, 42).await?;

// ...or a mutable connection reference...
let mut conn = pool.acquire().await?;
let user = fetch_user(&mut *conn, 42).await?;

// ...or inside a transaction.
let mut tx = pool.begin().await?;
let user = fetch_user(&mut *tx, 42).await?;
tx.commit().await?;

Execute trait

pub trait Execute<'q, DB: Database>: Send + Sized {
    fn sql(self) -> SqlStr;
    fn statement(&self) -> Option<&DB::Statement>;
    fn take_arguments(&mut self) -> Result<Option<DB::Arguments>, BoxDynError>;
    fn persistent(&self) -> bool;
}
Execute is implemented by the types that are a query — the other side of the pairing. You rarely implement or name this trait directly; it is the bound that executor methods use to accept any query-like value.

Implementations

Query / QueryAs / QueryScalar

Returned by sqlx::query(), sqlx::query_as(), and sqlx::query_scalar(). Carries a SQL string and a set of bound arguments; executes as a prepared statement.

RawSql

Returned by sqlx::raw_sql(). Carries a SQL string with no arguments; executes as an unprepared statement. Use for DDL and multi-statement batches.

&str / String

String types that implement SqlSafeStr also implement Execute. Passing a bare &str to an executor executes it as a simple (unprepared) query with no parameters.

Map

Returned by Query::try_map() and the query! macros. Wraps a Query with a row-mapping closure; shares the same execution methods.

Acquire trait

pub trait Acquire<'c> {
    type Database: Database;
    type Connection: Connection<Database = Self::Database> + Send;

    fn acquire(self) -> BoxFuture<'c, Result<Self::Connection, Error>>;
    fn begin(self) -> BoxFuture<'c, Result<Transaction<'c, Self::Database>, Error>>;
}
Acquire abstracts over types that can produce a connection — either by borrowing one from a pool or by wrapping a connection that already exists. Use it when you want a function to accept either a pool or a connection, and you need to call methods that require an owned or mutable connection (such as starting a transaction).
use sqlx::{Acquire, Postgres, Transaction};

async fn do_work<'c, A>(connector: A) -> sqlx::Result<()>
where
    A: Acquire<'c, Database = Postgres>,
{
    let mut conn = connector.acquire().await?;

    sqlx::query("INSERT INTO events(name) VALUES ($1)")
        .bind("started")
        .execute(&mut *conn)
        .await?;

    Ok(())
}

// Accepts a pool...
do_work(&pool).await?;

// ...or a plain connection.
let conn = pool.acquire().await?;
do_work(conn).await?;
Prefer impl Executor<'_, Database = DB> for simple read queries. Reach for impl Acquire<'_, Database = DB> when you need to start a transaction or hold a connection for multiple steps.

Implementations

TypeBehavior
&Pool<DB>Calls Pool::acquire() to borrow a connection from the pool.
PoolConnection<DB>Returns itself.
&mut PoolConnection<DB>Reborrowed; connection is returned to the pool when the outer guard drops.
&mut DB::ConnectionReborrowed; does not close the connection when done.

Build docs developers (and LLMs) love