parsql_deadpool_postgres/
transaction_extensions.rs

1use std::fmt::Debug;
2use std::sync::OnceLock;
3use tokio_postgres::Error;
4use deadpool_postgres::Transaction;
5
6use crate::{SqlQuery, SqlParams, FromRow, UpdateParams};
7
8/// TransactionOps trait, Transaction için CRUD işlemlerini extension method olarak sağlar
9/// Bu şekilde, herhangi bir Transaction nesnesi üzerinde doğrudan CRUD işlemleri yapılabilir
10#[async_trait::async_trait]
11pub trait TransactionOps {
12    /// Insert method, yeni bir kayıt eklemek için kullanılır
13    ///
14    /// # Parameters
15    /// * `entity` - Eklenecek varlık, SqlQuery ve SqlParams trait'lerini implement etmeli
16    ///
17    /// # Örnek Kullanım
18    /// ```rust,no_run
19    /// use deadpool_postgres::{Config, Runtime};
20    /// use parsql_deadpool_postgres::TransactionOps;
21    /// use tokio_postgres::NoTls;
22    ///
23    /// // Entity tanımı
24    /// #[derive(SqlQuery, SqlParams)]
25    /// #[table("users")]
26    /// pub struct InsertUser {
27    ///     pub name: String,
28    ///     pub email: String,
29    /// }
30    ///
31    /// #[tokio::main]
32    /// async fn main() -> Result<(), tokio_postgres::Error> {
33    ///     let mut cfg = Config::new();
34    ///     cfg.dbname = Some("test".to_string());
35    ///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
36    ///     
37    ///     let client = pool.get().await?;
38    ///     let tx = client.transaction().await?;
39    ///     
40    ///     let user = InsertUser {
41    ///         name: "John".to_string(),
42    ///         email: "john@example.com".to_string(),
43    ///     };
44    ///     
45    ///     // Extension method kullanımı
46    ///     let rows_affected = tx.insert(user).await?;
47    ///     tx.commit().await?;
48    ///     
49    ///     println!("{} kayıt eklendi", rows_affected);
50    ///     Ok(())
51    /// }
52    /// ```
53    async fn insert<T>(&self, entity: T) -> Result<u64, Error>
54    where
55        T: SqlQuery + SqlParams + Debug + Send + 'static;
56
57    /// Update method, mevcut bir kaydı güncellemek için kullanılır
58    ///
59    /// # Parameters
60    /// * `entity` - Güncellenecek varlık, SqlQuery, UpdateParams ve SqlParams trait'lerini implement etmeli
61    async fn update<T>(&self, entity: T) -> Result<u64, Error>
62    where
63        T: SqlQuery + UpdateParams + SqlParams + Debug + Send + 'static;
64
65    /// Delete method, bir kaydı silmek için kullanılır
66    ///
67    /// # Parameters
68    /// * `entity` - Silinecek varlık, SqlQuery ve SqlParams trait'lerini implement etmeli
69    async fn delete<T>(&self, entity: T) -> Result<u64, Error>
70    where
71        T: SqlQuery + SqlParams + Debug + Send + 'static;
72
73    /// Get method, tek bir kayıt getirmek için kullanılır
74    ///
75    /// # Parameters
76    /// * `params` - Sorgu parametreleri, SqlQuery, FromRow ve SqlParams trait'lerini implement etmeli
77    async fn get<T>(&self, params: &T) -> Result<T, Error>
78    where
79        T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static;
80
81    /// Get All method, birden fazla kayıt getirmek için kullanılır
82    ///
83    /// # Parameters
84    /// * `params` - Sorgu parametreleri, SqlQuery, FromRow ve SqlParams trait'lerini implement etmeli
85    async fn get_all<T>(&self, params: &T) -> Result<Vec<T>, Error>
86    where
87        T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static;
88
89    /// Select method, özel dönüşüm fonksiyonu ile tek bir kayıt getirmek için kullanılır
90    ///
91    /// # Parameters
92    /// * `entity` - Sorgu parametreleri, SqlQuery ve SqlParams trait'lerini implement etmeli
93    /// * `to_model` - Satırı istenen türe dönüştüren fonksiyon
94    async fn select<T, R, F>(&self, entity: T, to_model: F) -> Result<R, Error>
95    where
96        T: SqlQuery + SqlParams + Debug + Send + 'static,
97        F: FnOnce(&tokio_postgres::Row) -> Result<R, Error> + Send + Sync + 'static,
98        R: Send + 'static;
99
100    /// Select All method, özel dönüşüm fonksiyonu ile birden fazla kayıt getirmek için kullanılır
101    ///
102    /// # Parameters
103    /// * `entity` - Sorgu parametreleri, SqlQuery ve SqlParams trait'lerini implement etmeli
104    /// * `to_model` - Her satırı istenen türe dönüştüren fonksiyon
105    async fn select_all<T, R, F>(&self, entity: T, to_model: F) -> Result<Vec<R>, Error>
106    where
107        T: SqlQuery + SqlParams + Debug + Send + 'static,
108        F: Fn(&tokio_postgres::Row) -> R + Send + Sync + 'static,
109        R: Send + 'static;
110}
111
112#[async_trait::async_trait]
113impl TransactionOps for Transaction<'_> {
114    async fn insert<T>(&self, entity: T) -> Result<u64, Error>
115    where
116        T: SqlQuery + SqlParams + Debug + Send + 'static,
117    {
118        let sql = T::query();
119        
120        if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
121            if trace == "1" {
122                println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
123            }
124        }
125
126        let params = SqlParams::params(&entity);
127        self.execute(&sql, &params[..]).await
128    }
129
130    async fn update<T>(&self, entity: T) -> Result<u64, Error>
131    where
132        T: SqlQuery + UpdateParams + SqlParams + Debug + Send + 'static,
133    {
134        let sql = T::query();
135        
136        if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
137            if trace == "1" {
138                println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
139            }
140        }
141
142        let params = SqlParams::params(&entity);
143        self.execute(&sql, &params[..]).await
144    }
145
146    async fn delete<T>(&self, entity: T) -> Result<u64, Error>
147    where
148        T: SqlQuery + SqlParams + Debug + Send + 'static,
149    {
150        let sql = T::query();
151        
152        if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
153            if trace == "1" {
154                println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
155            }
156        }
157
158        let params = SqlParams::params(&entity);
159        self.execute(&sql, &params[..]).await
160    }
161
162    async fn get<T>(&self, params: &T) -> Result<T, Error>
163    where
164        T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static,
165    {
166        let sql = T::query();
167        
168        static TRACE_ENABLED: OnceLock<bool> = OnceLock::new();
169        let is_trace_enabled = *TRACE_ENABLED.get_or_init(|| {
170            std::env::var_os("PARSQL_TRACE").map_or(false, |v| v == "1")
171        });
172        
173        if is_trace_enabled {
174            println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
175        }
176
177        let params_owned = params.clone();
178        let query_params = SqlParams::params(&params_owned);
179        let row = self.query_one(&sql, &query_params[..]).await?;
180        
181        T::from_row(&row)
182    }
183
184    async fn get_all<T>(&self, params: &T) -> Result<Vec<T>, Error>
185    where
186        T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static,
187    {
188        let sql = T::query();
189        
190        if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
191            if trace == "1" {
192                println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
193            }
194        }
195
196        let params_owned = params.clone();
197        let query_params = SqlParams::params(&params_owned);
198        let rows = self.query(&sql, &query_params[..]).await?;
199        
200        let mut results = Vec::with_capacity(rows.len());
201        for row in rows {
202            results.push(T::from_row(&row)?);
203        }
204        
205        Ok(results)
206    }
207
208    async fn select<T, R, F>(&self, entity: T, to_model: F) -> Result<R, Error>
209    where
210        T: SqlQuery + SqlParams + Debug + Send + 'static,
211        F: FnOnce(&tokio_postgres::Row) -> Result<R, Error> + Send + Sync + 'static,
212        R: Send + 'static,
213    {
214        let sql = T::query();
215        
216        if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
217            if trace == "1" {
218                println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
219            }
220        }
221
222        let params = SqlParams::params(&entity);
223        let row = self.query_one(&sql, &params[..]).await?;
224        to_model(&row)
225    }
226
227    async fn select_all<T, R, F>(&self, entity: T, to_model: F) -> Result<Vec<R>, Error>
228    where
229        T: SqlQuery + SqlParams + Debug + Send + 'static,
230        F: Fn(&tokio_postgres::Row) -> R + Send + Sync + 'static,
231        R: Send + 'static,
232    {
233        let sql = T::query();
234        
235        if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
236            if trace == "1" {
237                println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
238            }
239        }
240
241        let params = SqlParams::params(&entity);
242        let rows = self.query(&sql, &params[..]).await?;
243        
244        let mut results = Vec::with_capacity(rows.len());
245        for row in rows {
246            results.push(to_model(&row));
247        }
248        
249        Ok(results)
250    }
251}