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, ¶ms)?;
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, ¶ms)?;
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, ¶ms)?;
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, ¶ms)
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, ¶ms)
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, ¶ms)?;
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, ¶ms)?;
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}