parsql_deadpool_postgres/
transactional_ops.rs

1// use parsql_core::{Deleteable, Insertable, Queryable, Updateable};
2use deadpool_postgres::{Transaction, Client};
3use tokio_postgres::Error;
4// Makrolar sadece dokümantasyon için kullanılıyor, gerçek kodda SqlQuery kullanılmalı
5// use parsql_macros::{Insertable, Updateable};
6
7use crate::traits::{SqlQuery, SqlParams, FromRow};
8
9/// # begin
10/// 
11/// Starts a new database transaction from a pool client.
12/// 
13/// ## Parameters
14/// - `client`: Pool client to start the transaction from
15/// 
16/// ## Return Value
17/// - `Result<Transaction<'_>, Error>`: On success, returns the new transaction
18/// 
19/// ## Example Usage
20/// ```rust,no_run
21/// use tokio_postgres::{NoTls, Error};
22/// use deadpool_postgres::{Config, Runtime};
23/// use parsql::deadpool_postgres::transactional::begin;
24/// 
25/// #[tokio::main]
26/// async fn main() -> Result<(), Error> {
27///     let mut cfg = Config::new();
28///     cfg.host = Some("localhost".to_string());
29///     cfg.dbname = Some("test".to_string());
30///     
31///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls)?;
32///     let mut client = pool.get().await?;
33///     
34///     let tx = begin(&mut client).await?;
35///     // Now you can use the transaction
36///     
37///     // Commit the transaction
38///     tx.commit().await?;
39///     
40///     Ok(())
41/// }
42/// ```
43pub async fn begin(client: &mut Client) -> Result<Transaction<'_>, Error> {
44    let tx = client.transaction().await?;
45    
46    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
47        println!("[PARSQL-TOKIO-POSTGRES-TX] Begin Transaction");
48    }
49    
50    Ok(tx)
51}
52
53/// # begin_from_pool
54/// 
55/// Starts a new database transaction directly from a connection pool.
56/// 
57/// ## Parameters
58/// - `pool`: Connection pool to start the transaction from
59/// 
60/// ## Return Value
61/// - `Result<(Client, Transaction<'_>), Error>`: On success, returns the client and transaction
62/// 
63/// ## Example Usage
64/// ```rust,no_run
65/// use tokio_postgres::{NoTls, Error};
66/// use deadpool_postgres::{Config, Runtime};
67/// use parsql::deadpool_postgres::transactional::begin_from_pool;
68/// 
69/// #[tokio::main]
70/// async fn main() -> Result<(), Error> {
71///     let mut cfg = Config::new();
72///     cfg.host = Some("localhost".to_string());
73///     cfg.dbname = Some("test".to_string());
74///     
75///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls)?;
76///     
77///     // Instead of using begin_from_pool, we'll get a client and start a transaction
78///     let client = pool.get().await.unwrap();
79///     let tx = client.transaction().await?;
80///     
81///     // Now you can use the transaction
82///     
83///     // Commit the transaction
84///     tx.commit().await?;
85///     // Client will be dropped and returned to the pool automatically
86///     
87///     Ok(())
88/// }
89/// ```
90// Bu fonksiyon lifetime sorunları nedeniyle kaldırıldı
91// Bunun yerine client'ı manuel olarak alıp, üzerinde transaction başlatmak daha uygun
92
93/// # tx_update
94/// 
95/// Updates a record within a transaction.
96/// 
97/// ## Parameters
98/// - `transaction`: Active transaction object
99/// - `entity`: Data object containing the update information (must implement Updateable and SqlParams traits)
100/// 
101/// ## Return Value
102/// - `Result<(Transaction<'_>, u64), Error>`: On success, returns the transaction and number of updated records
103/// 
104/// ## Example Usage
105/// ```rust,no_run
106/// use tokio_postgres::{NoTls, Error};
107/// use deadpool_postgres::{Config, Runtime};
108/// use parsql::deadpool_postgres::transactional::tx_update;
109/// 
110/// #[derive(Updateable, UpdateParams)]
111/// #[table("users")]
112/// #[update("name, email")]
113/// #[where_clause("id = $")]
114/// pub struct UpdateUser {
115///     pub id: i32,
116///     pub name: String,
117///     pub email: String,
118/// }
119///
120/// #[tokio::main]
121/// async fn main() -> Result<(), Error> {
122///     let mut cfg = Config::new();
123///     cfg.host = Some("localhost".to_string());
124///     cfg.dbname = Some("test".to_string());
125///     
126///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls)?;
127///     let client = pool.get().await?;
128///     
129///     let mut tx = client.transaction().await?;
130///     
131///     let update_user = UpdateUser {
132///         id: 1,
133///         name: String::from("John"),
134///         email: String::from("john@example.com"),
135///     };
136///     
137///     let (tx, rows_affected) = tx_update(tx, update_user).await?;
138///     tx.commit().await?;
139///     
140///     println!("Updated {} rows", rows_affected);
141///     Ok(())
142/// }
143/// ```
144pub async fn tx_update<T: SqlQuery + SqlParams>(
145    transaction: Transaction<'_>,
146    entity: T,
147) -> Result<(Transaction<'_>, u64), Error> {
148    let sql = T::query();
149    
150    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
151        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
152    }
153
154    let params = entity.params();
155    let result = transaction.execute(&sql, &params).await?;
156    Ok((transaction, result))
157}
158
159/// # tx_insert
160/// 
161/// Inserts a record within a transaction.
162/// 
163/// ## Parameters
164/// - `transaction`: Active transaction object
165/// - `entity`: Data object to be inserted (must implement Insertable and SqlParams traits)
166/// 
167/// ## Return Value
168/// - `Result<(Transaction<'_>, u64), Error>`: On success, returns the transaction and number of inserted records
169/// 
170/// ## Example Usage
171/// ```rust,no_run
172/// use tokio_postgres::{NoTls, Error};
173/// use deadpool_postgres::{Config, Runtime};
174/// use parsql::deadpool_postgres::transactional::tx_insert;
175/// 
176/// #[derive(Insertable, SqlParams)]
177/// #[table("users")]
178/// pub struct InsertUser {
179///     pub name: String,
180///     pub email: String,
181///     pub state: i16,
182/// }
183///
184/// #[tokio::main]
185/// async fn main() -> Result<(), Error> {
186///     let mut cfg = Config::new();
187///     cfg.host = Some("localhost".to_string());
188///     cfg.dbname = Some("test".to_string());
189///     
190///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls)?;
191///     let client = pool.get().await?;
192///     
193///     let mut tx = client.transaction().await?;
194///     
195///     let insert_user = InsertUser {
196///         name: "John".to_string(),
197///         email: "john@example.com".to_string(),
198///         state: 1,
199///     };
200///     
201///     let (tx, rows_affected) = tx_insert(tx, insert_user).await?;
202///     tx.commit().await?;
203///     
204///     println!("Inserted {} rows", rows_affected);
205///     Ok(())
206/// }
207/// ```
208pub async fn tx_insert<T: SqlQuery + SqlParams>(
209    transaction: Transaction<'_>,
210    entity: T,
211) -> Result<(Transaction<'_>, u64), Error> {
212    let sql = T::query();
213    
214    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
215        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
216    }
217
218    let params = entity.params();
219    let result = transaction.execute(&sql, &params).await?;
220    Ok((transaction, result))
221}
222
223/// # tx_delete
224/// 
225/// Deletes a record within a transaction.
226/// 
227/// ## Parameters
228/// - `transaction`: Active transaction object
229/// - `entity`: Data object identifying the record to delete (must implement Deletable and SqlParams traits)
230/// 
231/// ## Return Value
232/// - `Result<(Transaction<'_>, u64), Error>`: On success, returns the transaction and number of deleted records
233pub async fn tx_delete<T: SqlQuery + SqlParams>(
234    transaction: Transaction<'_>,
235    entity: T,
236) -> Result<(Transaction<'_>, u64), Error> {
237    let sql = T::query();
238    
239    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
240        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
241    }
242
243    let params = entity.params();
244    let result = transaction.execute(&sql, &params).await?;
245    Ok((transaction, result))
246}
247
248/// # tx_get
249/// 
250/// Retrieves a single record within a transaction.
251/// 
252/// ## Parameters
253/// - `transaction`: Active transaction object
254/// - `params`: Query parameters (must implement SqlQuery, FromRow and SqlParams traits)
255/// 
256/// ## Return Value
257/// - `Result<(Transaction<'_>, T), Error>`: On success, returns the transaction and the retrieved record
258pub async fn tx_get<'a, T>(
259    transaction: Transaction<'a>,
260    params: &T,
261) -> Result<(Transaction<'a>, T), Error>
262where
263    T: SqlQuery + FromRow + SqlParams,
264{
265    let sql = T::query();
266    
267    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
268        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
269    }
270
271    let query_params = params.params();
272    let row = transaction.query_one(&sql, &query_params).await?;
273    let result = T::from_row(&row)?;
274    
275    Ok((transaction, result))
276}
277
278/// # tx_get_all
279/// 
280/// Retrieves multiple records within a transaction.
281/// 
282/// ## Parameters
283/// - `transaction`: Active transaction object
284/// - `params`: Query parameters (must implement SqlQuery, FromRow and SqlParams traits)
285/// 
286/// ## Return Value
287/// - `Result<(Transaction<'_>, Vec<T>), Error>`: On success, returns the transaction and the retrieved records
288pub async fn tx_get_all<'a, T>(
289    transaction: Transaction<'a>,
290    params: &T,
291) -> Result<(Transaction<'a>, Vec<T>), Error>
292where
293    T: SqlQuery + FromRow + SqlParams,
294{
295    let sql = T::query();
296    
297    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
298        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
299    }
300
301    let query_params = params.params();
302    let rows = transaction.query(&sql, &query_params).await?;
303    
304    let mut results = Vec::with_capacity(rows.len());
305    for row in rows {
306        results.push(T::from_row(&row)?);
307    }
308    
309    Ok((transaction, results))
310}
311
312/// # tx_select
313/// 
314/// Retrieves a single record using a custom transformation function within a transaction.
315/// 
316/// ## Parameters
317/// - `transaction`: Active transaction object
318/// - `entity`: Query parameters (must implement SqlQuery and SqlParams traits)
319/// - `to_model`: Function to transform the row into the desired type
320/// 
321/// ## Return Value
322/// - `Result<(Transaction<'_>, R), Error>`: On success, returns the transaction and the transformed record
323pub async fn tx_select<'a, T, R, F>(
324    transaction: Transaction<'a>,
325    entity: T,
326    to_model: F,
327) -> Result<(Transaction<'a>, R), Error>
328where
329    T: SqlQuery + SqlParams,
330    F: FnOnce(&tokio_postgres::Row) -> Result<R, Error>,
331{
332    let sql = T::query();
333    
334    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
335        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
336    }
337
338    let params = entity.params();
339    let row = transaction.query_one(&sql, &params).await?;
340    let result = to_model(&row)?;
341    
342    Ok((transaction, result))
343}
344
345/// # tx_select_all
346/// 
347/// Retrieves multiple records using a custom transformation function within a transaction.
348/// 
349/// ## Parameters
350/// - `transaction`: Active transaction object
351/// - `entity`: Query parameters (must implement SqlQuery and SqlParams traits)
352/// - `to_model`: Function to transform each row into the desired type
353/// 
354/// ## Return Value
355/// - `Result<(Transaction<'_>, Vec<R>), Error>`: On success, returns the transaction and the transformed records
356pub async fn tx_select_all<'a, T, R, F>(
357    transaction: Transaction<'a>,
358    entity: T,
359    to_model: F,
360) -> Result<(Transaction<'a>, Vec<R>), Error>
361where
362    T: SqlQuery + SqlParams,
363    F: Fn(&tokio_postgres::Row) -> R,
364{
365    let sql = T::query();
366    
367    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
368        println!("[PARSQL-TOKIO-POSTGRES-TX] Execute SQL: {}", sql);
369    }
370
371    let params = entity.params();
372    let rows = transaction.query(&sql, &params).await?;
373    
374    let mut results = Vec::with_capacity(rows.len());
375    for row in rows {
376        results.push(to_model(&row));
377    }
378    
379    Ok((transaction, results))
380}