parsql_postgres/
transaction_ops.rs

1use crate::traits::{CrudOps, FromRow, SqlCommand, SqlParams, SqlQuery, UpdateParams};
2use postgres::{types::FromSql, Error, Row, Transaction};
3
4/// CrudOps trait implementasyonu Transaction<'_> için.
5/// Bu sayede transaction içinde tüm CRUD işlemleri extension metotları olarak kullanılabilir.
6impl<'a> CrudOps for Transaction<'a> {
7    fn insert<T: SqlCommand + SqlParams, P: for<'b> FromSql<'b> + Send + Sync>(
8        &mut self,
9        entity: T,
10    ) -> Result<P, Error> {
11        tx_insert(self, entity)
12    }
13
14    fn update<T: SqlCommand + UpdateParams>(&mut self, entity: T) -> Result<u64, Error> {
15        tx_update(self, entity)
16    }
17
18    fn delete<T: SqlCommand + SqlParams>(&mut self, entity: T) -> Result<u64, Error> {
19        tx_delete(self, entity)
20    }
21
22    fn fetch<P, R>(&mut self, params: &P) -> Result<R, Error>
23    where
24        P: SqlQuery<R> + SqlParams,
25        R: FromRow,
26    {
27        tx_fetch(self, params)
28    }
29
30    fn fetch_all<P, R>(&mut self, params: &P) -> Result<Vec<R>, Error>
31    where
32        P: SqlQuery<R> + SqlParams,
33        R: FromRow,
34    {
35        tx_fetch_all(self, params)
36    }
37
38    fn select<T, F, R>(&mut self, entity: &T, to_model: F) -> Result<R, Error>
39    where
40        T: SqlQuery<T> + SqlParams,
41        F: FnOnce(&Row) -> Result<R, Error>,
42    {
43        let sql = T::query();
44
45        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
46            println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
47        }
48
49        let params = entity.params();
50        let row = self.query_one(&sql, &params)?;
51        to_model(&row)
52    }
53
54    fn select_all<T, F, R>(&mut self, entity: &T, to_model: F) -> Result<Vec<R>, Error>
55    where
56        T: SqlQuery<T> + SqlParams,
57        F: FnMut(&Row) -> Result<R, Error>,
58    {
59        let sql = T::query();
60
61        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
62            println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
63        }
64
65        let params = entity.params();
66        let rows = self.query(&sql, &params)?;
67
68        rows.iter().map(to_model).collect()
69    }
70}
71
72/// # begin
73///
74/// Yeni bir transaction başlatır.
75///
76/// ## Parametreler
77/// - `client`: Veritabanı bağlantı istemcisi
78///
79/// ## Dönüş Değeri
80/// - `Result<Transaction<'_>, Error>`: Başarılı olursa, transaction nesnesini döner; hata durumunda Error döner
81///
82/// ## Örnek Kullanım
83/// ```rust,no_run
84/// use postgres::{Client, NoTls, Error};
85/// use parsql::postgres::transactional::begin;
86///
87/// fn main() -> Result<(), Error> {
88///     let mut client = Client::connect(
89///         "host=localhost user=postgres dbname=test",
90///         NoTls,
91///     )?;
92///     
93///     let tx = begin(&mut client)?;
94///     
95///     // İşlemler...
96///     
97///     // Transaction'ı tamamla
98///     tx.commit()?;
99///     Ok(())
100/// }
101/// ```
102pub fn begin<'a>(client: &'a mut postgres::Client) -> Result<Transaction<'a>, Error> {
103    client.transaction()
104}
105
106/// # tx_insert
107///
108/// Transaction içinde bir kaydı veritabanına ekler.
109///
110/// ## Parametreler
111/// - `tx`: Transaction nesnesi
112/// - `entity`: Eklenecek veri nesnesi (SqlQuery ve SqlParams trait'lerini implement etmeli)
113///
114/// ## Dönüş Değeri
115/// - `Result<(Transaction<'_>, P), Error>`: Başarılı olursa, transaction ve etkilenen kayıt sayısını döner; hata durumunda Error döner
116///
117/// ## Örnek Kullanım
118/// ```rust,no_run
119/// use postgres::{Client, NoTls, Error};
120/// use parsql::postgres::transactional::{begin, tx_insert};
121///
122/// #[derive(Insertable, SqlParams)]
123/// #[table("users")]
124/// pub struct InsertUser {
125///     pub name: String,
126///     pub email: String,
127/// }
128///
129/// fn main() -> Result<(), Error> {
130///     let mut client = Client::connect(
131///         "host=localhost user=postgres dbname=test",
132///         NoTls,
133///     )?;
134///     
135///     let mut tx = begin(&mut client)?;
136///     
137///     let insert_user = InsertUser {
138///         name: "John".to_string(),
139///         email: "john@example.com".to_string(),
140///     };
141///     
142///     let (tx, rows_affected) = tx_insert(tx, insert_user)?;
143///     
144///     // İşlemler devam edebilir...
145///     
146///     // Transaction'ı tamamla
147///     tx.commit()?;
148///     Ok(())
149/// }
150/// ```
151pub fn tx_insert<'a, T, P: for<'b> FromSql<'b> + Send + Sync>(
152    tx: &mut Transaction<'a>,
153    entity: T,
154) -> Result<P, Error>
155where
156    T: SqlCommand + SqlParams,
157{
158    let sql = T::query();
159
160    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
161        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
162    }
163
164    let params = entity.params();
165    let row = tx.query_one(&sql, &params)?;
166    row.try_get::<_, P>(0)
167}
168
169/// # tx_update
170///
171/// Transaction içinde bir kaydı günceller.
172///
173/// ## Parametreler
174/// - `tx`: Transaction nesnesi
175/// - `entity`: Güncellenecek veri nesnesi (SqlQuery ve UpdateParams trait'lerini implement etmeli)
176///
177/// ## Dönüş Değeri
178/// - `Result<(Transaction<'_>, u64), Error>`: Başarılı olursa, transaction ve etkilenen kayıt sayısını döner; hata durumunda Error döner
179///
180/// ## Örnek Kullanım
181/// ```rust,no_run
182/// use postgres::{Client, NoTls, Error};
183/// use parsql::postgres::transactional::{begin, tx_update};
184///
185/// #[derive(Updateable, UpdateParams)]
186/// #[table("users")]
187/// #[update("name, email")]
188/// #[where_clause("id = $")]
189/// pub struct UpdateUser {
190///     pub id: i32,
191///     pub name: String,
192///     pub email: String,
193/// }
194///
195/// fn main() -> Result<(), Error> {
196///     let mut client = Client::connect(
197///         "host=localhost user=postgres dbname=test",
198///         NoTls,
199///     )?;
200///     
201///     let mut tx = begin(&mut client)?;
202///     
203///     let update_user = UpdateUser {
204///         id: 1,
205///         name: "John Updated".to_string(),
206///         email: "john.updated@example.com".to_string(),
207///     };
208///     
209///     let (tx, rows_affected) = tx_update(tx, update_user)?;
210///     
211///     // İşlemler devam edebilir...
212///     
213///     // Transaction'ı tamamla
214///     tx.commit()?;
215///     Ok(())
216/// }
217/// ```
218pub fn tx_update<'a, T>(tx: &mut Transaction<'a>, entity: T) -> Result<u64, Error>
219where
220    T: SqlCommand + UpdateParams,
221{
222    let sql = T::query();
223
224    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
225        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
226    }
227
228    let params = entity.params();
229    tx.execute(&sql, &params)
230}
231
232/// # tx_delete
233///
234/// Transaction içinde bir kaydı siler.
235///
236/// ## Parametreler
237/// - `tx`: Transaction nesnesi
238/// - `entity`: Silinecek veri nesnesi (SqlQuery ve SqlParams trait'lerini implement etmeli)
239///
240/// ## Dönüş Değeri
241/// - `Result<(Transaction<'_>, u64), Error>`: Başarılı olursa, transaction ve etkilenen kayıt sayısını döner; hata durumunda Error döner
242///
243/// ## Örnek Kullanım
244/// ```rust,no_run
245/// use postgres::{Client, NoTls, Error};
246/// use parsql::postgres::transactional::{begin, tx_delete};
247///
248/// #[derive(Deletable, SqlParams)]
249/// #[table("users")]
250/// #[where_clause("id = $")]
251/// pub struct DeleteUser {
252///     pub id: i32,
253/// }
254///
255/// fn main() -> Result<(), Error> {
256///     let mut client = Client::connect(
257///         "host=localhost user=postgres dbname=test",
258///         NoTls,
259///     )?;
260///     
261///     let mut tx = begin(&mut client)?;
262///     
263///     let delete_user = DeleteUser { id: 1 };
264///     
265///     let (tx, rows_affected) = tx_delete(tx, delete_user)?;
266///     
267///     // İşlemler devam edebilir...
268///     
269///     // Transaction'ı tamamla
270///     tx.commit()?;
271///     Ok(())
272/// }
273/// ```
274pub fn tx_delete<'a, T>(tx: &mut Transaction<'a>, entity: T) -> Result<u64, Error>
275where
276    T: SqlCommand + SqlParams,
277{
278    let sql = T::query();
279
280    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
281        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
282    }
283
284    let params = entity.params();
285    tx.execute(&sql, &params)
286}
287
288/// # tx_fetch
289///
290/// Transaction içinde tek bir kaydı getirir.
291///
292/// ## Parametreler
293/// - `tx`: Transaction nesnesi
294/// - `entity`: Sorgu parametresi nesnesi (SqlQuery, FromRow ve SqlParams trait'lerini implement etmeli)
295///
296/// ## Dönüş Değeri
297/// - `Result<(Transaction<'_>, T), Error>`: Başarılı olursa, transaction ve bulunan kaydı döner; hata durumunda Error döner
298///
299/// ## Örnek Kullanım
300/// ```rust,no_run
301/// use postgres::{Client, NoTls, Error};
302/// use parsql::postgres::transactional::{begin, tx_fetch};
303///
304/// #[derive(Queryable, FromRow, SqlParams)]
305/// #[table("users")]
306/// #[where_clause("id = $")]
307/// pub struct GetUser {
308///     pub id: i32,
309///     pub name: String,
310///     pub email: String,
311/// }
312///
313/// fn main() -> Result<(), Error> {
314///     let mut client = Client::connect(
315///         "host=localhost user=postgres dbname=test",
316///         NoTls,
317///     )?;
318///     
319///     let mut tx = begin(&mut client)?;
320///     
321///     let get_user = GetUser {
322///         id: 1,
323///         name: String::new(),
324///         email: String::new(),
325///     };
326///     
327///     let (tx, user) = tx_fetch(tx, &get_user)?;
328///     
329///     // İşlemler devam edebilir...
330///     
331///     // Transaction'ı tamamla
332///     tx.commit()?;
333///     Ok(())
334/// }
335/// ```
336pub fn tx_fetch<'a, P, R>(tx: &mut Transaction<'a>, params: &P) -> Result<R, Error>
337where
338    P: SqlQuery<R> + SqlParams,
339    R: FromRow,
340{
341    let sql = P::query();
342
343    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
344        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
345    }
346
347    let query_params = params.params();
348    let row = tx.query_one(&sql, &query_params)?;
349    R::from_row(&row)
350}
351
352/// # tx_fetch_all
353///
354/// Transaction içinde birden fazla kaydı getirir.
355///
356/// ## Parametreler
357/// - `tx`: Transaction nesnesi
358/// - `entity`: Sorgu parametresi nesnesi (SqlQuery, FromRow ve SqlParams trait'lerini implement etmeli)
359///
360/// ## Dönüş Değeri
361/// - `Result<(Transaction<'_>, Vec<T>), Error>`: Başarılı olursa, transaction ve bulunan kayıtların listesini döner; hata durumunda Error döner
362///
363/// ## Örnek Kullanım
364/// ```rust,no_run
365/// use postgres::{Client, NoTls, Error};
366/// use parsql::postgres::transactional::{begin, tx_fetch_all};
367///
368/// #[derive(Queryable, FromRow, SqlParams)]
369/// #[table("users")]
370/// #[where_clause("active = $")]
371/// pub struct GetUsers {
372///     pub active: bool,
373///     pub id: i32,
374///     pub name: String,
375///     pub email: String,
376/// }
377///
378/// fn main() -> Result<(), Error> {
379///     let mut client = Client::connect(
380///         "host=localhost user=postgres dbname=test",
381///         NoTls,
382///     )?;
383///     
384///     let mut tx = begin(&mut client)?;
385///     
386///     let get_users = GetUsers {
387///         active: true,
388///         id: 0,
389///         name: String::new(),
390///         email: String::new(),
391///     };
392///     
393///     let (tx, users) = tx_fetch_all(tx, &get_users)?;
394///     
395///     // İşlemler devam edebilir...
396///     
397///     // Transaction'ı tamamla
398///     tx.commit()?;
399///     Ok(())
400/// }
401/// ```
402pub fn tx_fetch_all<'a, P, R>(tx: &mut Transaction<'a>, params: &P) -> Result<Vec<R>, Error>
403where
404    P: SqlQuery<R> + SqlParams,
405    R: FromRow,
406{
407    let sql = P::query();
408
409    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
410        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
411    }
412
413    let query_params = params.params();
414    let rows = tx.query(&sql, &query_params)?;
415
416    let mut results = Vec::with_capacity(rows.len());
417    for row in rows {
418        results.push(R::from_row(&row)?);
419    }
420
421    Ok(results)
422}
423
424/// # tx_select
425///
426/// Transaction içinde özel bir sorgu çalıştırır ve sonucu dönüştürür.
427///
428/// ## Parametreler
429/// - `tx`: Transaction nesnesi
430/// - `entity`: Sorgu parametresi nesnesi (SqlQuery ve SqlParams trait'lerini implement etmeli)
431/// - `to_model`: Row nesnesini hedef nesne tipine dönüştüren fonksiyon
432///
433/// ## Dönüş Değeri
434/// - `Result<(Transaction<'_>, R), Error>`: Başarılı olursa, transaction ve dönüştürülmüş nesneyi döner; hata durumunda Error döner
435pub fn tx_select<'a, T, F, R>(tx: &mut Transaction<'a>, entity: &T, to_model: F) -> Result<R, Error>
436where
437    T: SqlQuery<T> + SqlParams,
438    F: Fn(&Row) -> Result<R, Error>,
439{
440    let sql = T::query();
441
442    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
443        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
444    }
445
446    let params = entity.params();
447    let row = tx.query_one(&sql, &params)?;
448    to_model(&row)
449}
450
451/// # tx_select_all
452///
453/// Transaction içinde özel bir sorgu çalıştırır ve tüm sonuçları dönüştürür.
454///
455/// ## Parametreler
456/// - `tx`: Transaction nesnesi
457/// - `entity`: Sorgu parametresi nesnesi (SqlQuery ve SqlParams trait'lerini implement etmeli)
458/// - `to_model`: Row nesnesini hedef nesne tipine dönüştüren fonksiyon
459///
460/// ## Dönüş Değeri
461/// - `Result<(Transaction<'_>, Vec<R>), Error>`: Başarılı olursa, transaction ve dönüştürülmüş nesnelerin listesini döner; hata durumunda Error döner
462pub fn tx_select_all<'a, T, F, R>(
463    tx: &mut Transaction<'a>,
464    entity: &T,
465    to_model: F,
466) -> Result<Vec<R>, Error>
467where
468    T: SqlQuery<T> + SqlParams,
469    F: Fn(&Row) -> Result<R, Error>,
470{
471    let sql = T::query();
472
473    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
474        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
475    }
476
477    let params = entity.params();
478    let rows = tx.query(&sql, &params)?;
479
480    let mut results = Vec::with_capacity(rows.len());
481    for row in rows {
482        results.push(to_model(&row)?);
483    }
484
485    Ok(results)
486}
487
488// Geriye dönük uyumluluk için eski tx_get fonksiyonunu koruyalım
489#[deprecated(
490    since = "0.2.0",
491    note = "Renamed to `tx_fetch`. Please use `tx_fetch` function instead."
492)]
493/// # tx_get
494///
495/// Transaction içinde tek bir kaydı getirir.
496///
497/// This function is deprecated. Please use `tx_fetch` instead.
498pub fn tx_get<'a, T>(tx: &mut Transaction<'a>, params: &T) -> Result<T, Error>
499where
500    T: SqlQuery<T> + FromRow + SqlParams,
501{
502    tx_fetch(tx, params)
503}
504
505// Geriye dönük uyumluluk için eski tx_get_all fonksiyonunu koruyalım
506#[deprecated(
507    since = "0.2.0",
508    note = "Renamed to `tx_fetch_all`. Please use `tx_fetch_all` function instead."
509)]
510/// # tx_get_all
511///
512/// Transaction içinde birden fazla kaydı getirir.
513///
514/// This function is deprecated. Please use `tx_fetch_all` instead.
515pub fn tx_get_all<'a, T>(tx: &mut Transaction<'a>, params: &T) -> Result<Vec<T>, Error>
516where
517    T: SqlQuery<T> + FromRow + SqlParams,
518{
519    tx_fetch_all(tx, params)
520}