1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use TransactionContext;
use MySqlPool;
use Future;
use Pin;
/// Executes a function within a database transaction, using anyhow::Error for error handling.
///
/// This is a convenience wrapper around the main `with_transaction` function that accepts
/// closures returning `anyhow::Result<T>` instead of `crate::Result<T>`.
///
/// # Type Parameters
///
/// * `F` - A function that takes a mutable `TransactionContext` and returns a pinned future
/// * `T` - The return type of the function (must be `Send`)
///
/// # Arguments
///
/// * `pool` - The MySQL connection pool
/// * `f` - The function to execute within the transaction
///
/// # Returns
///
/// Returns the result of the function execution as `anyhow::Result<T>`.
///
/// # Examples
///
/// ```rust,no_run
/// use sqlx::MySqlPool;
/// use sqlx_transaction_manager::with_transaction_anyhow;
/// use sqlx_named_bind::PreparedQuery;
///
/// # async fn example() -> anyhow::Result<()> {
/// # let pool = MySqlPool::connect("mysql://localhost/test").await?;
/// with_transaction_anyhow(&pool, |tx| {
/// Box::pin(async move {
/// let mut query = PreparedQuery::new(
/// "INSERT INTO users (name) VALUES (:name)",
/// |q, key| match key {
/// ":name" => q.bind("Alice"),
/// _ => q,
/// }
/// )?;
/// query.execute(tx.as_executor()).await?;
/// Ok(())
/// })
/// }).await?;
/// # Ok(())
/// # }
/// ```
pub async
/// Executes a nested transaction using savepoints, with anyhow::Error for error handling.
///
/// This is a convenience wrapper for nested transactions that accepts closures
/// returning `anyhow::Result<T>`.
///
/// # Examples
///
/// ```rust,no_run
/// use sqlx::MySqlPool;
/// use sqlx_transaction_manager::{with_transaction_anyhow, with_nested_transaction_anyhow};
///
/// # async fn example() -> anyhow::Result<()> {
/// # let pool = MySqlPool::connect("mysql://localhost/test").await?;
/// with_transaction_anyhow(&pool, |tx| {
/// Box::pin(async move {
/// sqlx::query("INSERT INTO users (name) VALUES (?)")
/// .bind("Alice")
/// .execute(tx.as_executor())
/// .await?;
///
/// with_nested_transaction_anyhow(tx, |nested_tx| {
/// Box::pin(async move {
/// sqlx::query("INSERT INTO audit_log (action) VALUES (?)")
/// .bind("User created")
/// .execute(nested_tx.as_executor())
/// .await?;
/// Ok(())
/// })
/// }).await?;
///
/// Ok(())
/// })
/// }).await?;
/// # Ok(())
/// # }
/// ```
pub async