parsql_deadpool_postgres/
crud_ops.rs

1use deadpool_postgres::{Pool, PoolError};
2use postgres::types::FromSqlOwned;
3//use postgres::types::FromSql;
4use crate::traits::{CrudOps, FromRow, SqlCommand, SqlParams, SqlQuery, UpdateParams};
5use tokio_postgres::{types::FromSql, Error, Row};
6
7// Daha basit bir yaklaşım: PoolError'dan genel bir Error oluştur
8fn pool_err_to_io_err(e: PoolError) -> Error {
9    // Bu özel fonksiyon tokio_postgres'in sağladığı timeout hatasını döndürür
10    // Güzel bir çözüm değil, ama çalışır bir örnek için kullanılabilir
11    let err = Error::__private_api_timeout();
12
13    // Debug süreci için stderr'e hatayı yazdıralım
14    eprintln!("Pool bağlantı hatası: {}", e);
15
16    err
17}
18
19/// # insert
20///
21/// Deadpool bağlantı havuzunu kullanarak veritabanına yeni bir kayıt ekler.
22///
23/// ## Parametreler
24/// - `pool`: Deadpool bağlantı havuzu
25/// - `entity`: Eklenecek veri nesnesi (SqlQuery ve SqlParams trait'lerini uygulamalıdır)
26///
27/// ## Dönüş Değeri
28/// - `Result<i64, Error>`: Başarılı olursa, eklenen kayıt ID'sini döndürür; başarısız olursa, Error döndürür
29///
30/// ## Yapı Tanımı
31/// Bu fonksiyonla kullanılan yapılar aşağıdaki derive makrolarıyla işaretlenmelidir:
32///
33/// ```rust,no_run
34/// #[derive(Insertable, SqlParams)]  // Gerekli makrolar
35/// #[table("tablo_adi")]            // Ekleme yapılacak tablo adı
36/// pub struct VeriModeli {
37///     pub alan1: String,
38///     pub alan2: i32,
39///     // ...
40/// }
41/// ```
42///
43/// - `Insertable`: Otomatik olarak SQL INSERT ifadeleri oluşturur
44/// - `SqlParams`: Otomatik olarak SQL parametreleri oluşturur
45/// - `#[table("tablo_adi")]`: Ekleme yapılacak tablo adını belirtir
46///
47/// ## Kullanım Örneği
48/// ```rust,no_run
49/// use deadpool_postgres::{Config, Runtime, Pool};
50/// use tokio_postgres::{NoTls, Error};
51/// use parsql::tokio_postgres::pool_crud_ops::insert;
52///
53/// #[derive(Insertable, SqlParams)]
54/// #[table("users")]
55/// pub struct InsertUser {
56///     pub name: String,
57///     pub email: String,
58///     pub state: i16,
59/// }
60///
61/// #[tokio::main]
62/// async fn main() -> Result<(), Error> {
63///     let mut cfg = Config::new();
64///     cfg.host = Some("localhost".to_string());
65///     cfg.dbname = Some("test".to_string());
66///     
67///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
68///
69///     let insert_user = InsertUser {
70///         name: "John".to_string(),
71///         email: "john@example.com".to_string(),
72///         state: 1_i16,
73///     };
74///
75///     let insert_result = insert(&pool, insert_user).await?;
76///     println!("Insert result: {:?}", insert_result);
77///     Ok(())
78/// }
79/// ```
80// pub async fn insert<T: SqlQuery + SqlParams, P:for<'a> FromSql<'a> + Send + Sync>(
81//     pool: &Pool,
82//     entity: T,
83// ) -> Result<P, Error> {
84//     let client = pool.get().await.map_err(pool_err_to_io_err)?;
85//     let sql = T::query();
86
87//     if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
88//         println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
89//     }
90
91//     let params = entity.params();
92//     let row = client.query_one(&sql, &params).await?;
93//     row.try_get::<_, P>(0)
94// }
95
96pub async fn insert<T, P>(pool: &Pool, entity: T) -> Result<P, Error>
97where
98    T: SqlCommand + SqlParams,
99    P: FromSqlOwned + Send + Sync,
100{
101    let client = pool.get().await.map_err(pool_err_to_io_err)?;
102    let sql = T::query();
103
104    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
105        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
106    }
107
108    let params = entity.params();
109    let row = client.query_one(&sql, &params).await?;
110    row.try_get::<_, P>(0)
111}
112
113/// # update
114///
115/// Deadpool bağlantı havuzunu kullanarak veritabanındaki mevcut bir kaydı günceller.
116///
117/// ## Parametreler
118/// - `pool`: Deadpool bağlantı havuzu
119/// - `entity`: Güncelleme bilgilerini içeren veri nesnesi (SqlQuery ve UpdateParams trait'lerini uygulamalıdır)
120///
121/// ## Dönüş Değeri
122/// - `Result<bool, Error>`: Başarılı olursa, true döndürür; başarısız olursa, Error döndürür
123///
124/// ## Yapı Tanımı
125/// Bu fonksiyonla kullanılan yapılar aşağıdaki derive makrolarıyla işaretlenmelidir:
126///
127/// ```rust,no_run
128/// #[derive(Updateable, UpdateParams)]  // Gerekli makrolar
129/// #[table("tablo_adi")]               // Güncellenecek tablo adı
130/// #[update("alan1, alan2")]          // Güncellenecek alanlar (isteğe bağlı)
131/// #[where_clause("id = $")]            // Güncelleme koşulu
132/// pub struct VeriModeli {
133///     pub id: i32,                     // Koşulda kullanılan alanlar
134///     pub alan1: String,              // Güncellenecek alanlar
135///     pub alan2: i32,                 // Güncellenecek alanlar
136///     // ...
137/// }
138/// ```
139///
140/// - `Updateable`: Otomatik olarak SQL UPDATE ifadeleri oluşturur
141/// - `UpdateParams`: Otomatik olarak güncelleme parametreleri oluşturur
142/// - `#[table("tablo_adi")]`: Güncellenecek tablo adını belirtir
143/// - `#[update("alan1, alan2")]`: Hangi alanların güncelleneceğini belirtir (belirtilmezse, tüm alanlar güncellenir)
144/// - `#[where_clause("id = $")]`: Güncelleme koşulunu belirtir (`$` parametre değeri ile değiştirilir)
145///
146/// ## Kullanım Örneği
147/// ```rust,no_run
148/// use deadpool_postgres::{Config, Runtime, Pool};
149/// use tokio_postgres::{NoTls, Error};
150/// use parsql::tokio_postgres::pool_crud_ops::update;
151///
152/// #[derive(Updateable, UpdateParams)]
153/// #[table("users")]
154/// #[update("name, email")]
155/// #[where_clause("id = $")]
156/// pub struct UpdateUser {
157///     pub id: i32,
158///     pub name: String,
159///     pub email: String,
160///     pub state: i16,  // update özniteliğinde belirtilmediği için bu alan güncellenmez
161/// }
162///
163/// #[tokio::main]
164/// async fn main() -> Result<(), Error> {
165///     let mut cfg = Config::new();
166///     cfg.host = Some("localhost".to_string());
167///     cfg.dbname = Some("test".to_string());
168///     
169///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
170///
171///     let update_user = UpdateUser {
172///         id: 1,
173///         name: String::from("John"),
174///         email: String::from("john@example.com"),
175///         state: 2,
176///     };
177///
178///     let update_result = update(&pool, update_user).await?;
179///     println!("Update result: {:?}", update_result);
180///     Ok(())
181/// }
182/// ```
183pub async fn update<T: SqlCommand + UpdateParams>(pool: &Pool, entity: T) -> Result<bool, Error> {
184    let client = pool.get().await.map_err(pool_err_to_io_err)?;
185    let sql = T::query();
186
187    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
188        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
189    }
190
191    let params = entity.params();
192    match client.execute(&sql, &params).await {
193        Ok(_) => Ok(true),
194        Err(e) => Err(e),
195    }
196}
197
198/// # delete
199///
200/// Deadpool bağlantı havuzunu kullanarak veritabanından bir kaydı siler.
201///
202/// ## Parametreler
203/// - `pool`: Deadpool bağlantı havuzu
204/// - `entity`: Silme bilgilerini içeren veri nesnesi (SqlQuery ve SqlParams trait'lerini uygulamalıdır)
205///
206/// ## Dönüş Değeri
207/// - `Result<u64, Error>`: Başarılı olursa, silinen kayıt sayısını döndürür; başarısız olursa, Error döndürür
208///
209/// ## Yapı Tanımı
210/// Bu fonksiyonla kullanılan yapılar aşağıdaki derive makrolarıyla işaretlenmelidir:
211///
212/// ```rust,no_run
213/// #[derive(Deletable, SqlParams)]   // Gerekli makrolar
214/// #[table("tablo_adi")]             // Silinecek tablo adı
215/// #[where_clause("id = $")]          // Silme koşulu
216/// pub struct VeriModeli {
217///     pub id: i32,                   // Koşulda kullanılan alanlar
218///     // Diğer alanlar eklenebilir, ancak genellikle sadece koşul alanları gereklidir
219/// }
220/// ```
221///
222/// - `Deletable`: Otomatik olarak SQL DELETE ifadeleri oluşturur
223/// - `SqlParams`: Otomatik olarak SQL parametreleri oluşturur
224/// - `#[table("tablo_adi")]`: Silinecek tablo adını belirtir
225/// - `#[where_clause("id = $")]`: Silme koşulunu belirtir (`$` parametre değeri ile değiştirilir)
226///
227/// ## Kullanım Örneği
228/// ```rust,no_run
229/// use deadpool_postgres::{Config, Runtime, Pool};
230/// use tokio_postgres::{NoTls, Error};
231/// use parsql::tokio_postgres::pool_crud_ops::delete;
232///
233/// #[derive(Deletable, SqlParams)]
234/// #[table("users")]
235/// #[where_clause("id = $")]
236/// pub struct DeleteUser {
237///     pub id: i32,
238/// }
239///
240/// #[tokio::main]
241/// async fn main() -> Result<(), Error> {
242///     let mut cfg = Config::new();
243///     cfg.host = Some("localhost".to_string());
244///     cfg.dbname = Some("test".to_string());
245///     
246///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
247///
248///     let delete_user = DeleteUser { id: 6 };
249///     let delete_result = delete(&pool, delete_user).await?;
250///     
251///     println!("Delete result: {:?}", delete_result);
252///     Ok(())
253/// }
254/// ```
255pub async fn delete<T: SqlCommand + SqlParams>(pool: &Pool, entity: T) -> Result<u64, Error> {
256    let client = pool.get().await.map_err(pool_err_to_io_err)?;
257    let sql = T::query();
258
259    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
260        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
261    }
262
263    let params = entity.params();
264    client.execute(&sql, &params).await
265}
266
267/// # fetch
268///
269/// Deadpool bağlantı havuzunu kullanarak veritabanından bir kaydı alır.
270///
271/// ## Parametreler
272/// - `pool`: Deadpool bağlantı havuzu
273/// - `params`: Sorgu parametrelerini içeren veri nesnesi (SqlQuery, FromRow ve SqlParams trait'lerini uygulamalıdır)
274///
275/// ## Dönüş Değeri
276/// - `Result<T, Error>`: Başarılı olursa, alınan kaydı döndürür; başarısız olursa, Error döndürür
277///
278/// ## Yapı Tanımı
279/// Bu fonksiyonla kullanılan yapılar aşağıdaki derive makrolarıyla işaretlenmelidir:
280///
281/// ```rust,no_run
282/// #[derive(Queryable, SqlParams, FromRow)]   // Gerekli makrolar
283/// #[table("tablo_adi")]                     // Sorgulanacak tablo adı
284/// #[where_clause("id = $")]                  // Sorgu koşulu
285/// pub struct VeriModeli {
286///     pub id: i32,                          // Koşulda kullanılan alanlar
287///     pub alan1: String,                    // Getirilen veri alanları
288///     pub alan2: i32,                       // Getirilen veri alanları
289///     // ...
290/// }
291/// ```
292///
293/// - `Queryable`: Otomatik olarak SQL SELECT ifadeleri oluşturur
294/// - `SqlParams`: Otomatik olarak SQL parametreleri oluşturur
295/// - `FromRow`: Veritabanı satırını yapıya dönüştürür
296/// - `#[table("tablo_adi")]`: Sorgulanacak tablo adını belirtir
297/// - `#[where_clause("id = $")]`: Sorgu koşulunu belirtir (`$` parametre değeri ile değiştirilir)
298///
299/// ## Kullanım Örneği
300/// ```rust,no_run
301/// use deadpool_postgres::{Config, Runtime, Pool};
302/// use tokio_postgres::{NoTls, Error};
303/// use parsql::tokio_postgres::pool_crud_ops::fetch;
304///
305/// #[derive(Queryable, SqlParams, FromRow)]
306/// #[table("users")]
307/// #[where_clause("id = $")]
308/// pub struct GetUser {
309///     pub id: i32,
310///     pub name: String,
311///     pub email: String,
312///     pub state: i16,
313/// }
314///
315/// impl GetUser {
316///     pub fn new(id: i32) -> Self {
317///         Self {
318///             id,
319///             name: String::new(),
320///             email: String::new(),
321///             state: 0,
322///         }
323///     }
324/// }
325///
326/// #[tokio::main]
327/// async fn main() -> Result<(), Error> {
328///     let mut cfg = Config::new();
329///     cfg.host = Some("localhost".to_string());
330///     cfg.dbname = Some("test".to_string());
331///     
332///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
333///
334///     let user_params = GetUser::new(1);
335///     let user = fetch(&pool, &user_params).await?;
336///     
337///     println!("User: {:?}", user);
338///     Ok(())
339/// }
340/// ```
341pub async fn fetch<P, R>(pool: &Pool, params: &P) -> Result<R, Error>
342where
343    P: SqlQuery<R> + SqlParams,
344    R: FromRow,
345{
346    let client = pool.get().await.map_err(pool_err_to_io_err)?;
347    let sql = P::query();
348
349    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
350        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
351    }
352
353    let query_params = params.params();
354    let row = client.query_one(&sql, &query_params).await?;
355    R::from_row(&row)
356}
357
358/// # fetch_all
359///
360/// Deadpool bağlantı havuzunu kullanarak veritabanından birden fazla kaydı alır.
361///
362/// ## Parametreler
363/// - `pool`: Deadpool bağlantı havuzu
364/// - `params`: Sorgu parametrelerini içeren veri nesnesi (SqlQuery, FromRow ve SqlParams trait'lerini uygulamalıdır)
365///
366/// ## Dönüş Değeri
367/// - `Result<Vec<T>, Error>`: Başarılı olursa, alınan kayıtları içeren bir vektör döndürür; başarısız olursa, Error döndürür
368///
369/// ## Yapı Tanımı
370/// Bu fonksiyonla kullanılan yapılar aşağıdaki derive makrolarıyla işaretlenmelidir:
371///
372/// ```rust,no_run
373/// #[derive(Queryable, SqlParams, FromRow)]   // Gerekli makrolar
374/// #[table("tablo_adi")]                     // Sorgulanacak tablo adı
375/// #[where_clause("state = $")]              // Sorgu koşulu
376/// pub struct VeriModeli {
377///     pub id: i32,                          // Alınacak alanlar
378///     pub alan1: String,                    // Alınacak alanlar
379///     pub alan2: i32,                       // Alınacak alanlar
380///     pub state: i16,                       // Koşulda kullanılan alanlar
381///     // ...
382/// }
383/// ```
384///
385/// - `Queryable`: Otomatik olarak SQL SELECT ifadeleri oluşturur
386/// - `SqlParams`: Otomatik olarak SQL parametreleri oluşturur
387/// - `FromRow`: Veritabanı satırını yapıya dönüştürür
388/// - `#[table("tablo_adi")]`: Sorgulanacak tablo adını belirtir
389/// - `#[where_clause("state = $")]`: Sorgu koşulunu belirtir (`$` parametre değeri ile değiştirilir)
390///
391/// ## Kullanım Örneği
392/// ```rust,no_run
393/// use deadpool_postgres::{Config, Runtime, Pool};
394/// use tokio_postgres::{NoTls, Error};
395/// use parsql::tokio_postgres::pool_crud_ops::fetch_all;
396///
397/// #[derive(Queryable, SqlParams, FromRow)]
398/// #[table("users")]
399/// #[where_clause("state = $")]
400/// pub struct ListUsers {
401///     pub id: i32,
402///     pub name: String,
403///     pub email: String,
404///     pub state: i16,
405/// }
406///
407/// impl ListUsers {
408///     pub fn new(state: i16) -> Self {
409///         Self {
410///             id: 0,
411///             name: String::new(),
412///             email: String::new(),
413///             state,
414///         }
415///     }
416/// }
417///
418/// #[tokio::main]
419/// async fn main() -> Result<(), Error> {
420///     let mut cfg = Config::new();
421///     cfg.host = Some("localhost".to_string());
422///     cfg.dbname = Some("test".to_string());
423///     
424///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
425///
426///     let user_params = ListUsers::new(1);
427///     let users = fetch_all(&pool, &user_params).await?;
428///     
429///     println!("Users: {:?}", users);
430///     Ok(())
431/// }
432/// ```
433pub async fn fetch_all<P, R>(pool: &Pool, params: &P) -> Result<Vec<R>, Error>
434where
435    P: SqlQuery<R> + SqlParams,
436    R: FromRow,
437{
438    let client = pool.get().await.map_err(pool_err_to_io_err)?;
439    let sql = P::query();
440
441    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
442        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
443    }
444
445    let query_params = params.params();
446    let rows = client.query(&sql, &query_params).await?;
447
448    let mut results = Vec::with_capacity(rows.len());
449    for row in rows {
450        results.push(R::from_row(&row)?);
451    }
452
453    Ok(results)
454}
455
456/// # select
457///
458/// Deadpool bağlantı havuzunu kullanarak özel bir model dönüştürücü fonksiyon ile veritabanından bir kayıt seçer.
459///
460/// ## Parametreler
461/// - `pool`: Deadpool bağlantı havuzu
462/// - `entity`: Sorgu parametrelerini içeren veri nesnesi (SqlQuery ve SqlParams trait'lerini uygulamalıdır)
463/// - `to_model`: Satırı modele dönüştüren fonksiyon
464///
465/// ## Dönüş Değeri
466/// - `Result<R, Error>`: Başarılı olursa, dönüştürülen modeli döndürür; başarısız olursa, Error döndürür
467///
468/// ## Kullanım Örneği
469/// ```rust,no_run
470/// use deadpool_postgres::{Config, Runtime, Pool};
471/// use tokio_postgres::{NoTls, Error, Row};
472/// use parsql::tokio_postgres::pool_crud_ops::select;
473///
474/// #[derive(Queryable, SqlParams)]
475/// #[table("users")]
476/// #[where_clause("id = $")]
477/// pub struct UserQuery {
478///     pub id: i32,
479/// }
480///
481/// pub struct UserModel {
482///     pub id: i32,
483///     pub name: String,
484///     pub email: String,
485///     pub is_active: bool,
486/// }
487///
488/// impl UserQuery {
489///     pub fn new(id: i32) -> Self {
490///         Self { id }
491///     }
492/// }
493///
494/// fn row_to_user(row: &Row) -> Result<UserModel, Error> {
495///     Ok(UserModel {
496///         id: row.try_get("id")?,
497///         name: row.try_get("name")?,
498///         email: row.try_get("email")?,
499///         is_active: row.try_get::<_, i16>("state")? == 1,
500///     })
501/// }
502///
503/// #[tokio::main]
504/// async fn main() -> Result<(), Error> {
505///     let mut cfg = Config::new();
506///     cfg.host = Some("localhost".to_string());
507///     cfg.dbname = Some("test".to_string());
508///     
509///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
510///
511///     let query = UserQuery::new(1);
512///     let user = select(&pool, query, row_to_user).await?;
513///     
514///     println!("User: {:?}", user);
515///     Ok(())
516/// }
517/// ```
518pub async fn select<T: SqlQuery<T> + SqlParams, R, F>(
519    pool: &Pool,
520    entity: T,
521    to_model: F,
522) -> Result<R, Error>
523where
524    F: Fn(&Row) -> Result<R, Error>,
525{
526    let client = pool.get().await.map_err(pool_err_to_io_err)?;
527    let sql = T::query();
528
529    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
530        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
531    }
532
533    let params = entity.params();
534    let row = client.query_one(&sql, &params).await?;
535    to_model(&row)
536}
537
538/// # select_all
539///
540/// Deadpool bağlantı havuzunu kullanarak özel bir model dönüştürücü fonksiyon ile veritabanından birden fazla kayıt seçer.
541///
542/// ## Parametreler
543/// - `pool`: Deadpool bağlantı havuzu
544/// - `entity`: Sorgu parametrelerini içeren veri nesnesi (SqlQuery ve SqlParams trait'lerini uygulamalıdır)
545/// - `to_model`: Satırı modele dönüştüren fonksiyon
546///
547/// ## Dönüş Değeri
548/// - `Result<Vec<R>, Error>`: Başarılı olursa, dönüştürülen modelleri içeren bir vektör döndürür; başarısız olursa, Error döndürür
549///
550/// ## Kullanım Örneği
551/// ```rust,no_run
552/// use deadpool_postgres::{Config, Runtime, Pool};
553/// use tokio_postgres::{NoTls, Error, Row};
554/// use parsql::tokio_postgres::pool_crud_ops::select_all;
555///
556/// #[derive(Queryable, SqlParams)]
557/// #[table("users")]
558/// #[where_clause("state = $")]
559/// pub struct UsersQuery {
560///     pub state: i16,
561/// }
562///
563/// pub struct UserModel {
564///     pub id: i32,
565///     pub name: String,
566///     pub email: String,
567///     pub is_active: bool,
568/// }
569///
570/// impl UsersQuery {
571///     pub fn new(state: i16) -> Self {
572///         Self { state }
573///     }
574/// }
575///
576/// fn row_to_user(row: &Row) -> UserModel {
577///     UserModel {
578///         id: row.get("id"),
579///         name: row.get("name"),
580///         email: row.get("email"),
581///         is_active: row.get::<_, i16>("state") == 1,
582///     }
583/// }
584///
585/// #[tokio::main]
586/// async fn main() -> Result<(), Error> {
587///     let mut cfg = Config::new();
588///     cfg.host = Some("localhost".to_string());
589///     cfg.dbname = Some("test".to_string());
590///     
591///     let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
592///
593///     let query = UsersQuery::new(1);
594///     let users = select_all(&pool, query, row_to_user).await?;
595///     
596///     println!("Users: {:?}", users);
597///     Ok(())
598/// }
599/// ```
600pub async fn select_all<T: SqlQuery<T> + SqlParams, R, F>(
601    pool: &Pool,
602    entity: T,
603    to_model: F,
604) -> Result<Vec<R>, Error>
605where
606    F: Fn(&Row) -> R,
607{
608    let client = pool.get().await.map_err(pool_err_to_io_err)?;
609    let sql = T::query();
610
611    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
612        println!("[PARSQL-TOKIO-POSTGRES-POOL] Execute SQL: {}", sql);
613    }
614
615    let params = entity.params();
616    let rows = client.query(&sql, &params).await?;
617
618    let mut results = Vec::with_capacity(rows.len());
619    for row in rows {
620        results.push(to_model(&row));
621    }
622
623    Ok(results)
624}
625
626// Deprecated functions for backward compatibility
627#[deprecated(
628    since = "0.2.0",
629    note = "Renamed to `fetch`. Please use `fetch` function instead."
630)]
631pub async fn get<T: SqlQuery<T> + FromRow + SqlParams>(
632    pool: &Pool,
633    params: &T,
634) -> Result<T, Error> {
635    fetch(pool, params).await
636}
637
638#[deprecated(
639    since = "0.2.0",
640    note = "Renamed to `fetch_all`. Please use `fetch_all` function instead."
641)]
642pub async fn get_all<T: SqlQuery<T> + FromRow + SqlParams>(
643    pool: &Pool,
644    params: &T,
645) -> Result<Vec<T>, Error> {
646    fetch_all(pool, params).await
647}
648
649/// CrudOps trait implementation for deadpool_postgres::Client
650#[async_trait::async_trait]
651impl CrudOps for Pool {
652    async fn insert<T, P: for<'a> FromSql<'a> + Send + Sync>(&self, entity: T) -> Result<P, Error>
653    where
654        T: SqlCommand + SqlParams + Send + Sync,
655    {
656        let client = self.get().await.map_err(pool_err_to_io_err)?;
657        let sql = T::query();
658
659        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
660            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
661        }
662
663        let params = entity.params();
664        let row = client.query_one(&sql, &params).await?;
665        row.try_get::<_, P>(0)
666    }
667
668    async fn update<T>(&self, entity: T) -> Result<u64, Error>
669    where
670        T: SqlCommand + UpdateParams + Send + Sync,
671    {
672        let client = self.get().await.map_err(pool_err_to_io_err)?;
673        let sql = T::query();
674
675        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
676            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
677        }
678
679        let params = entity.params();
680        client.execute(&sql, &params).await
681    }
682
683    async fn delete<T>(&self, entity: T) -> Result<u64, Error>
684    where
685        T: SqlCommand + SqlParams + Send + Sync,
686    {
687        let client = self.get().await.map_err(pool_err_to_io_err)?;
688        let sql = T::query();
689
690        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
691            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
692        }
693
694        let params = entity.params();
695        client.execute(&sql, &params).await
696    }
697
698    async fn fetch<P, R>(&self, params: &P) -> Result<R, Error>
699    where
700        P: SqlQuery<R> + SqlParams + Send + Sync,
701        R: FromRow + Send + Sync,
702    {
703        let client = self.get().await.map_err(pool_err_to_io_err)?;
704        let sql = P::query();
705
706        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
707            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
708        }
709
710        let query_params = params.params();
711        let row = client.query_one(&sql, &query_params).await?;
712        R::from_row(&row)
713    }
714
715    async fn fetch_all<P, R>(&self, params: &P) -> Result<Vec<R>, Error>
716    where
717        P: SqlQuery<R> + SqlParams + Send + Sync,
718        R: FromRow + Send + Sync,
719    {
720        let client = self.get().await.map_err(pool_err_to_io_err)?;
721        let sql = P::query();
722
723        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
724            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
725        }
726
727        let query_params = params.params();
728        let rows = client.query(&sql, &query_params).await?;
729
730        let mut results = Vec::with_capacity(rows.len());
731        for row in rows {
732            results.push(R::from_row(&row)?);
733        }
734
735        Ok(results)
736    }
737
738    async fn select<T, R, F>(&self, entity: T, to_model: F) -> Result<R, Error>
739    where
740        T: SqlQuery<T> + SqlParams + Send + Sync,
741        F: FnOnce(&Row) -> Result<R, Error> + Send + Sync,
742    {
743        let client = self.get().await.map_err(pool_err_to_io_err)?;
744        let sql = T::query();
745
746        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
747            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
748        }
749
750        let params = entity.params();
751        let row = client.query_one(&sql, &params).await?;
752        to_model(&row)
753    }
754
755    async fn select_all<T, R, F>(&self, entity: T, to_model: F) -> Result<Vec<R>, Error>
756    where
757        T: SqlQuery<T> + SqlParams + Send + Sync,
758        F: Fn(&Row) -> R + Send + Sync,
759    {
760        let client = self.get().await.map_err(pool_err_to_io_err)?;
761        let sql = T::query();
762
763        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
764            println!("[PARSQL-DEADPOOL-POSTGRES] Execute SQL: {}", sql);
765        }
766
767        let params = entity.params();
768        let rows = client.query(&sql, &params).await?;
769
770        let mut results = Vec::with_capacity(rows.len());
771        for row in rows {
772            results.push(to_model(&row));
773        }
774
775        Ok(results)
776    }
777}