pub struct TransactionScope { /* private fields */ }database and native only.Expand description
Transaction scope guard with automatic rollback on drop
This struct implements RAII (Resource Acquisition Is Initialization) pattern for database transactions. When the scope is dropped without explicit commit, it automatically rolls back the transaction.
§Connection Affinity
TransactionScope holds a dedicated database connection that is used for all
queries within the transaction. This ensures proper transaction isolation by
guaranteeing that all operations (BEGIN, queries, COMMIT/ROLLBACK) run on the
same physical connection.
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
// For doctest purposes, using mock connection (URL is ignored in current implementation)
let conn = DatabaseConnection::connect("postgres://localhost/test").await.unwrap();
// Transaction is automatically rolled back if not committed
{
let mut tx = TransactionScope::begin(&conn).await.unwrap();
// ... perform operations ...
// If we don't call tx.commit(), rollback happens automatically
}
// Explicit commit
{
let mut tx = TransactionScope::begin(&conn).await.unwrap();
// ... perform operations ...
tx.commit().await.unwrap(); // Explicit commit
}Implementations§
Source§impl TransactionScope
impl TransactionScope
Sourcepub async fn begin(conn: &DatabaseConnection) -> Result<TransactionScope, Error>
pub async fn begin(conn: &DatabaseConnection) -> Result<TransactionScope, Error>
Begin a new transaction scope
This acquires a dedicated database connection and begins a transaction on it. All queries executed through this scope are guaranteed to run on the same physical connection, ensuring proper transaction isolation.
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
// For doctest purposes, using mock connection (URL is ignored in current implementation)
let conn = DatabaseConnection::connect("postgres://localhost/test").await.unwrap();
let mut tx = TransactionScope::begin(&conn).await.unwrap();
// ... perform operations ...
tx.commit().await.unwrap();Sourcepub async fn begin_with_isolation(
conn: &DatabaseConnection,
level: IsolationLevel,
) -> Result<TransactionScope, Error>
pub async fn begin_with_isolation( conn: &DatabaseConnection, level: IsolationLevel, ) -> Result<TransactionScope, Error>
Begin a new transaction scope with specific isolation level
This acquires a dedicated database connection and begins a transaction with the specified isolation level. All queries executed through this scope are guaranteed to run on the same physical connection.
§Arguments
conn- The database connectionlevel- The desired isolation level for the transaction
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::{TransactionScope, IsolationLevel};
let conn = DatabaseConnection::connect("postgres://localhost/test").await.unwrap();
let mut tx = TransactionScope::begin_with_isolation(&conn, IsolationLevel::Serializable).await.unwrap();
// ... perform operations ...
tx.commit().await.unwrap();Sourcepub async fn execute(
&mut self,
sql: &str,
params: Vec<QueryValue>,
) -> Result<u64, Error>
pub async fn execute( &mut self, sql: &str, params: Vec<QueryValue>, ) -> Result<u64, Error>
Execute a SQL statement within the transaction
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
let conn = DatabaseConnection::connect("postgres://localhost/test").await.unwrap();
let mut tx = TransactionScope::begin(&conn).await.unwrap();
// Execute SQL within the transaction
tx.execute("INSERT INTO users (name) VALUES ($1)", vec!["Alice".into()]).await.unwrap();
tx.commit().await.unwrap();Sourcepub async fn query_one(
&mut self,
sql: &str,
params: Vec<QueryValue>,
) -> Result<QueryRow, Error>
pub async fn query_one( &mut self, sql: &str, params: Vec<QueryValue>, ) -> Result<QueryRow, Error>
Execute a SQL query and return a single row within the transaction
Sourcepub async fn query(
&mut self,
sql: &str,
params: Vec<QueryValue>,
) -> Result<Vec<QueryRow>, Error>
pub async fn query( &mut self, sql: &str, params: Vec<QueryValue>, ) -> Result<Vec<QueryRow>, Error>
Execute a SQL query and return all rows within the transaction
Sourcepub async fn query_optional(
&mut self,
sql: &str,
params: Vec<QueryValue>,
) -> Result<Option<QueryRow>, Error>
pub async fn query_optional( &mut self, sql: &str, params: Vec<QueryValue>, ) -> Result<Option<QueryRow>, Error>
Execute a SQL query and return an optional row within the transaction
Sourcepub async fn commit(self) -> Result<(), Error>
pub async fn commit(self) -> Result<(), Error>
Commit the transaction
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
// For doctest purposes, using mock connection (URL is ignored in current implementation)
let conn = DatabaseConnection::connect("postgres://localhost/test").await.unwrap();
let mut tx = TransactionScope::begin(&conn).await.unwrap();
// ... perform operations ...
tx.commit().await.unwrap();Sourcepub async fn rollback(self) -> Result<(), Error>
pub async fn rollback(self) -> Result<(), Error>
Explicit rollback
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
// For doctest purposes, using mock connection (URL is ignored in current implementation)
let conn = DatabaseConnection::connect("postgres://localhost/test").await.unwrap();
let mut tx = TransactionScope::begin(&conn).await.unwrap();
// ... error occurs ...
tx.rollback().await.unwrap();Sourcepub async fn savepoint(&mut self, name: &str) -> Result<(), Error>
pub async fn savepoint(&mut self, name: &str) -> Result<(), Error>
Create a savepoint within the transaction
Savepoints allow partial rollback of a transaction. You can create multiple savepoints and rollback to any of them without affecting work done before that savepoint.
§Arguments
name- The name of the savepoint
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
let conn = DatabaseConnection::connect("postgres://localhost/test").await?;
let mut tx = TransactionScope::begin(&conn).await?;
tx.execute("INSERT INTO users (name) VALUES ($1)", vec!["Alice".into()]).await?;
// Create a savepoint before risky operation
tx.savepoint("before_risky_op").await?;
// Perform risky operation
if let Err(_) = tx.execute("INSERT INTO users (name) VALUES ($1)", vec!["Invalid".into()]).await {
// Rollback to savepoint, keeping Alice's insert
tx.rollback_to_savepoint("before_risky_op").await?;
}
tx.commit().await?;Sourcepub async fn release_savepoint(&mut self, name: &str) -> Result<(), Error>
pub async fn release_savepoint(&mut self, name: &str) -> Result<(), Error>
Release a savepoint
Releasing a savepoint removes it from the transaction’s savepoint stack. This is typically done after the risky operation succeeded and the savepoint is no longer needed.
§Arguments
name- The name of the savepoint to release
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
let conn = DatabaseConnection::connect("postgres://localhost/test").await?;
let mut tx = TransactionScope::begin(&conn).await?;
tx.savepoint("sp1").await?;
// ... operations succeeded ...
tx.release_savepoint("sp1").await?;
tx.commit().await?;Sourcepub async fn rollback_to_savepoint(&mut self, name: &str) -> Result<(), Error>
pub async fn rollback_to_savepoint(&mut self, name: &str) -> Result<(), Error>
Rollback to a savepoint
This undoes all changes made after the savepoint was created, but keeps the transaction open for further operations.
§Arguments
name- The name of the savepoint to rollback to
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
let conn = DatabaseConnection::connect("postgres://localhost/test").await?;
let mut tx = TransactionScope::begin(&conn).await?;
tx.execute("INSERT INTO users (name) VALUES ($1)", vec!["Alice".into()]).await?;
tx.savepoint("sp1").await?;
// This will be rolled back
tx.execute("INSERT INTO users (name) VALUES ($1)", vec!["Bob".into()]).await?;
// Rollback to savepoint - Bob's insert is undone, Alice's remains
tx.rollback_to_savepoint("sp1").await?;
tx.commit().await?; // Only Alice is committedSourcepub async fn run<F, Fut, T>(self, f: F) -> Result<T, Error>
pub async fn run<F, Fut, T>(self, f: F) -> Result<T, Error>
Execute a closure and automatically commit on success or rollback on error
This method provides a closure-based API for executing operations within the transaction scope. The transaction is automatically committed if the closure returns Ok, or rolled back if it returns Err.
§Examples
use reinhardt_db::orm::connection::DatabaseConnection;
use reinhardt_db::orm::transaction::TransactionScope;
let conn = DatabaseConnection::connect("sqlite::memory:").await?;
let mut tx = TransactionScope::begin(&conn).await?;
let result = tx.run(|tx| async move {
// Perform operations via tx.execute(), tx.query(), etc.
Ok(42)
}).await?;
assert_eq!(result, 42);Trait Implementations§
Source§impl Drop for TransactionScope
impl Drop for TransactionScope
Source§fn drop(&mut self)
fn drop(&mut self)
Automatically rollback transaction if not committed
This ensures that transactions are always cleaned up, even if an error occurs or the scope is exited early.
§Note
When using TransactionScope directly (not through transaction() function),
it’s recommended to explicitly call commit() or rollback() to handle
errors properly. The automatic rollback in Drop cannot propagate errors.
The automatic rollback in Drop requires a multi-threaded tokio runtime. For single-threaded runtimes or when no runtime is available, only a warning message is printed.
Auto Trait Implementations§
impl Freeze for TransactionScope
impl !RefUnwindSafe for TransactionScope
impl Send for TransactionScope
impl Sync for TransactionScope
impl Unpin for TransactionScope
impl UnsafeUnpin for TransactionScope
impl !UnwindSafe for TransactionScope
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
type Err = Infallible
fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.