pub struct Transaction { /* private fields */ }Expand description
An open transaction. Owned, lifetime-free, and an Executor — any
function written as fn f(db: &dyn Executor) accepts it, which is what
lets model hooks run inside the caller’s transaction without knowing one
exists.
commit and rollback consume self: using a finished transaction is a
compile error, not a runtime one. Dropping without either abandons the
connection — it is closed rather than returned to the pool, and the
server rolls the transaction back. The lazy path is therefore always
safe and merely expensive; commit is the only way to keep work. Prefer
BeginExt::within, where neither a drop nor a forgotten commit can
happen at all.
This crate itself issues the transaction vocabulary — BEGIN, COMMIT,
ROLLBACK, SAVEPOINT n / RELEASE SAVEPOINT n / ROLLBACK TO SAVEPOINT n — which is identical across PostgreSQL, MySQL and SQLite, so no
backend re-implements (or drifts on) transaction semantics. Where the
engines stop agreeing — isolation levels, access modes — the vocabulary
is still written here, once, but per family and with the disagreements
spelled out: see TxOptions and BeginWith.
Implementations§
Source§impl Transaction
impl Transaction
Sourcepub async fn begin_on(conn: Box<dyn RawConnection>) -> Result<Self, ExecError>
pub async fn begin_on(conn: Box<dyn RawConnection>) -> Result<Self, ExecError>
Open a transaction on an exclusively-owned connection. Backend-facing:
a backend’s Begin impl checks a connection out and hands it here.
Sourcepub async fn begin_on_with(
conn: Box<dyn RawConnection>,
opts: TxOptions,
) -> Result<Self, ExecError>
pub async fn begin_on_with( conn: Box<dyn RawConnection>, opts: TxOptions, ) -> Result<Self, ExecError>
Open a transaction with explicit TxOptions. Backend-facing, the
counterpart of BeginWith::begin_with.
The options are turned into statements by TxOptions::plan before
anything is sent, so an option this engine cannot honour is refused
with the connection untouched — it goes back to its pool clean rather
than being abandoned. Every statement of the plan runs on this one
connection, ahead of any statement the caller issues; if one of them
fails the connection is abandoned rather than returned, because a
half-applied plan (MySQL’s SET TRANSACTION having landed without its
START TRANSACTION) would otherwise leak into whatever transaction
this pooled connection served next.
Sourcepub fn options(&self) -> TxOptions
pub fn options(&self) -> TxOptions
The options this transaction was opened with — TxOptions::new’s
defaults for one begun by Begin::begin.
Sourcepub async fn commit(self) -> Result<(), ExecError>
pub async fn commit(self) -> Result<(), ExecError>
Commit. Consumes the transaction; on success the connection goes back to wherever it came from.
Sourcepub async fn rollback(self) -> Result<(), ExecError>
pub async fn rollback(self) -> Result<(), ExecError>
Roll back explicitly. Consumes the transaction; cheaper than dropping, because the connection is returned cleanly instead of closed.
Sourcepub async fn savepoint<T, E, F>(&self, f: F) -> Result<T, E>
pub async fn savepoint<T, E, F>(&self, f: F) -> Result<T, E>
A nested transaction, via SAVEPOINT.
The savepoint has no handle to leak: Ok(_) releases it, Err(_)
rolls back to it, and the outer transaction lives on either way. The
closure receives this same transaction, so every &dyn Executor-taking
helper works unchanged inside. Nesting is unbounded; depth-numbered
names never collide.
Trait Implementations§
Source§impl Atomic for Transaction
Inside a transaction: atomic is Transaction::savepoint.
impl Atomic for Transaction
Inside a transaction: atomic is Transaction::savepoint.
Not an overlapping impl, and not by luck: Transaction does not
implement Begin, which is the design decision above holding the two
impls apart.
Source§impl Atomic for &Transaction
A reference to a transaction — what makes the bare impl Atomic
parameter form work, since that is the type a scope closure hands you.
impl Atomic for &Transaction
A reference to a transaction — what makes the bare impl Atomic
parameter form work, since that is the type a scope closure hands you.
Executor is implemented for &E and Arc<E> for the same reason: a
caller should not have to know whether what it holds is the value or a
handle to it. Coherent with the blanket impl for the same reason
Transaction’s own impl is — &Transaction is not Begin either.