parsql_postgres/
crud_ops.rs

1use postgres::{types::ToSql, Client, Error, Row};
2use crate::{SqlQuery, SqlParams, UpdateParams, FromRow};
3
4/// CrudOps trait defines the CRUD (Create, Read, Update, Delete) operations
5/// that can be performed on a PostgreSQL database.
6///
7/// This trait is implemented for the `postgres::Client` struct, allowing
8/// CRUD operations to be called as extension methods on a client.
9///
10/// # Example
11///
12/// ```rust,no_run
13/// use postgres::{Client, NoTls, Error};
14/// use parsql::postgres::CrudOps;
15/// use parsql::macros::{Insertable, SqlParams, Queryable, FromRow};
16///
17/// #[derive(Insertable, SqlParams)]
18/// #[table("users")]
19/// struct InsertUser {
20///     name: String,
21///     email: String,
22/// }
23///
24/// #[derive(Queryable, FromRow, SqlParams)]
25/// #[table("users")]
26/// #[where_clause("id = $1")]
27/// struct GetUser {
28///     id: i32,
29///     name: String,
30///     email: String,
31/// }
32///
33/// fn main() -> Result<(), Error> {
34///     let mut client = Client::connect("host=localhost user=postgres", NoTls)?;
35///     
36///     // Extension method for insert
37///     let insert_user = InsertUser {
38///         name: "John".to_string(),
39///         email: "john@example.com".to_string(),
40///     };
41///     let rows_affected = client.insert(insert_user)?;
42///     
43///     // Extension method for fetch
44///     let get_user = GetUser {
45///         id: 1,
46///         name: String::new(),
47///         email: String::new(),
48///     };
49///     let user = client.fetch(&get_user)?;
50///     
51///     println!("User: {:?}", user);
52///     Ok(())
53/// }
54/// ```
55pub trait CrudOps {
56    /// Inserts a new record into the PostgreSQL database.
57    /// 
58    /// # Arguments
59    /// * `entity` - Data object to be inserted (must implement SqlQuery and SqlParams traits)
60    /// 
61    /// # Returns
62    /// * `Result<u64, Error>` - On success, returns the number of inserted records; on failure, returns Error
63    fn insert<T: SqlQuery + SqlParams>(&mut self, entity: T) -> Result<u64, Error>;
64
65    /// Updates records in the PostgreSQL database.
66    /// 
67    /// # Arguments
68    /// * `entity` - Data object containing the update information (must implement SqlQuery and UpdateParams traits)
69    /// 
70    /// # Returns
71    /// * `Result<u64, Error>` - On success, returns the number of updated records; on failure, returns Error
72    fn update<T: SqlQuery + UpdateParams>(&mut self, entity: T) -> Result<u64, Error>;
73
74    /// Deletes records from the PostgreSQL database.
75    /// 
76    /// # Arguments
77    /// * `entity` - Data object containing delete conditions (must implement SqlQuery and SqlParams traits)
78    /// 
79    /// # Returns
80    /// * `Result<u64, Error>` - On success, returns the number of deleted records; on failure, returns Error
81    fn delete<T: SqlQuery + SqlParams>(&mut self, entity: T) -> Result<u64, Error>;
82
83    /// Retrieves a single record from the PostgreSQL database.
84    /// 
85    /// # Arguments
86    /// * `entity` - Data object containing query parameters (must implement SqlQuery, FromRow, and SqlParams traits)
87    /// 
88    /// # Returns
89    /// * `Result<T, Error>` - On success, returns the retrieved record; on failure, returns Error
90    fn fetch<T: SqlQuery + FromRow + SqlParams>(&mut self, entity: &T) -> Result<T, Error>;
91
92    /// Retrieves multiple records from the PostgreSQL database.
93    /// 
94    /// # Arguments
95    /// * `entity` - Data object containing query parameters (must implement SqlQuery, FromRow, and SqlParams traits)
96    /// 
97    /// # Returns
98    /// * `Result<Vec<T>, Error>` - On success, returns a vector of records; on failure, returns Error
99    fn fetch_all<T: SqlQuery + FromRow + SqlParams>(&mut self, entity: &T) -> Result<Vec<T>, Error>;
100
101    /// Executes a custom query and transforms the result using the provided function.
102    /// 
103    /// # Arguments
104    /// * `entity` - Data object containing query parameters (must implement SqlQuery and SqlParams traits)
105    /// * `to_model` - Function to transform the database row into the desired type
106    /// 
107    /// # Returns
108    /// * `Result<R, Error>` - On success, returns the transformed result; on failure, returns Error
109    fn select<T, F, R>(&mut self, entity: &T, to_model: F) -> Result<R, Error>
110    where
111        T: SqlQuery + SqlParams,
112        F: FnOnce(&Row) -> Result<R, Error>;
113
114    /// Executes a custom query and transforms all results using the provided function.
115    /// 
116    /// # Arguments
117    /// * `entity` - Data object containing query parameters (must implement SqlQuery and SqlParams traits)
118    /// * `to_model` - Function to transform database rows into the desired type
119    /// 
120    /// # Returns
121    /// * `Result<Vec<R>, Error>` - On success, returns a vector of transformed results; on failure, returns Error
122    fn select_all<T, F, R>(&mut self, entity: &T, to_model: F) -> Result<Vec<R>, Error>
123    where
124        T: SqlQuery + SqlParams,
125        F: FnMut(&Row) -> Result<R, Error>;
126}
127
128// CrudOps trait implementasyonu postgres::Client için
129impl CrudOps for Client {
130    fn insert<T: SqlQuery + SqlParams>(&mut self, entity: T) -> Result<u64, Error> {
131        insert(self, entity)
132    }
133
134    fn update<T: SqlQuery + UpdateParams>(&mut self, entity: T) -> Result<u64, Error> {
135        update(self, entity)
136    }
137
138    fn delete<T: SqlQuery + SqlParams>(&mut self, entity: T) -> Result<u64, Error> {
139        delete(self, entity)
140    }
141
142    fn fetch<T: SqlQuery + FromRow + SqlParams>(&mut self, entity: &T) -> Result<T, Error> {
143        fetch(self, entity)
144    }
145
146    fn fetch_all<T: SqlQuery + FromRow + SqlParams>(&mut self, entity: &T) -> Result<Vec<T>, Error> {
147        fetch_all(self, entity)
148    }
149
150    fn select<T, F, R>(&mut self, entity: &T, to_model: F) -> Result<R, Error>
151    where
152        T: SqlQuery + SqlParams,
153        F: FnOnce(&Row) -> Result<R, Error>,
154    {
155        let sql = T::query();
156        
157        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
158            println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
159        }
160
161        let params = entity.params();
162        let row = self.query_one(&sql, &params)?;
163        to_model(&row)
164    }
165
166    fn select_all<T, F, R>(&mut self, entity: &T, to_model: F) -> Result<Vec<R>, Error>
167    where
168        T: SqlQuery + SqlParams,
169        F: FnMut(&Row) -> Result<R, Error>,
170    {
171        let sql = T::query();
172        
173        if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
174            println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
175        }
176
177        let params = entity.params();
178        let rows = self.query(&sql, &params)?;
179        
180        rows.iter().map(to_model).collect()
181    }
182}
183
184/// # insert
185/// 
186/// Inserts a new record into the database.
187/// 
188/// ## Parameters
189/// - `client`: Database connection client
190/// - `entity`: Data object to be inserted (must implement SqlQuery and SqlParams traits)
191/// 
192/// ## Return Value
193/// - `Result<u64, Error>`: On success, returns the number of inserted records; on failure, returns Error
194/// 
195/// ## Struct Definition
196/// Structs used with this function should be annotated with the following derive macros:
197/// 
198/// ```rust,no_run
199/// #[derive(Insertable, SqlParams)]  // Required macros
200/// #[table("table_name")]            // Table name to insert into
201/// pub struct MyEntity {
202///     pub field1: String,
203///     pub field2: i32,
204///     // ...
205/// }
206/// ```
207/// 
208/// - `Insertable`: Automatically generates SQL INSERT statements
209/// - `SqlParams`: Automatically generates SQL parameters
210/// - `#[table("table_name")]`: Specifies the table name for the insertion
211/// 
212/// ## Example Usage
213/// ```rust,no_run
214/// use postgres::{Client, NoTls, Error};
215/// use parsql::postgres::insert;
216/// 
217/// #[derive(Insertable, SqlParams)]
218/// #[table("users")]
219/// pub struct InsertUser {
220///     pub name: String,
221///     pub email: String,
222///     pub state: i16,
223/// }
224///
225/// fn main() -> Result<(), Error> {
226///     let mut client = Client::connect(
227///         "host=localhost user=postgres dbname=test",
228///         NoTls,
229///     )?;
230///
231///     let insert_user = InsertUser {
232///         name: "John".to_string(),
233///         email: "john@example.com".to_string(),
234///         state: 1_i16,
235///     };
236///
237///     let insert_result = insert(&mut client, insert_user)?;
238///     println!("Insert result: {:?}", insert_result);
239///     Ok(())
240/// }
241/// ```
242pub fn insert<T: SqlQuery + SqlParams>(client: &mut Client, entity: T) -> Result<u64, Error> {
243    let sql = T::query();
244    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
245        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
246    }
247
248    let params = entity.params();
249    client.execute(&sql, &params)
250}
251
252/// # update
253/// 
254/// Updates an existing record in the database.
255/// 
256/// ## Parameters
257/// - `client`: Database connection client
258/// - `entity`: Data object containing the update information (must implement SqlQuery and UpdateParams traits)
259/// 
260/// ## Return Value
261/// - `Result<u64, Error>`: On success, returns the number of updated records; on failure, returns Error
262/// 
263/// ## Struct Definition
264/// Structs used with this function should be annotated with the following derive macros:
265/// 
266/// ```rust,no_run
267/// #[derive(Updateable, UpdateParams)]  // Required macros
268/// #[table("table_name")]               // Table name to update
269/// #[update("field1, field2")]          // Fields to update (optional)
270/// #[where_clause("id = $")]            // Update condition
271/// pub struct MyEntity {
272///     pub id: i32,                     // Fields used in the condition
273///     pub field1: String,              // Fields to be updated
274///     pub field2: i32,                 // Fields to be updated
275///     // ...
276/// }
277/// ```
278/// 
279/// - `Updateable`: Automatically generates SQL UPDATE statements
280/// - `UpdateParams`: Automatically generates update parameters
281/// - `#[table("table_name")]`: Specifies the table name for the update
282/// - `#[update("field1, field2")]`: Specifies which fields should be updated (if omitted, all fields will be updated)
283/// - `#[where_clause("id = $")]`: Specifies the update condition (`$` will be replaced with parameter value)
284/// 
285/// ## Example Usage
286/// ```rust,no_run
287/// use postgres::{Client, NoTls, Error};
288/// use parsql::postgres::update;
289/// 
290/// #[derive(Updateable, UpdateParams)]
291/// #[table("users")]
292/// #[update("name, email")]
293/// #[where_clause("id = $")]
294/// pub struct UpdateUser {
295///     pub id: i32,
296///     pub name: String,
297///     pub email: String,
298///     pub state: i16,  // This field won't be updated as it's not specified in the update attribute
299/// }
300///
301/// fn main() -> Result<(), Error> {
302///     let mut client = Client::connect(
303///         "host=localhost user=postgres dbname=test",
304///         NoTls,
305///     )?;
306///
307///     let update_user = UpdateUser {
308///         id: 1,
309///         name: String::from("John"),
310///         email: String::from("john@example.com"),
311///         state: 2,
312///     };
313///
314///     let update_result = update(&mut client, update_user)?;
315///     println!("Update result: {:?}", update_result);
316///     Ok(())
317/// }
318/// ```
319pub fn update<T: SqlQuery + UpdateParams>(
320    client: &mut postgres::Client,
321    entity: T,
322) -> Result<u64, Error> {
323    let sql = T::query();
324    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
325        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
326    }
327
328    let params = entity.params();
329    match client.execute(&sql, &params) {
330        Ok(rows_affected) => Ok(rows_affected),
331        Err(e) => Err(e),
332    }
333}
334
335/// # delete
336/// 
337/// Deletes a record from the database.
338/// 
339/// ## Parameters
340/// - `client`: Database connection client
341/// - `entity`: Data object containing the deletion information (must implement SqlQuery and SqlParams traits)
342/// 
343/// ## Return Value
344/// - `Result<u64, Error>`: On success, returns the number of deleted records; on failure, returns Error
345/// 
346/// ## Struct Definition
347/// Structs used with this function should be annotated with the following derive macros:
348/// 
349/// ```rust,no_run
350/// #[derive(Deletable, SqlParams)]   // Required macros
351/// #[table("table_name")]             // Table name to delete from
352/// #[where_clause("id = $")]          // Delete condition
353/// pub struct MyEntity {
354///     pub id: i32,                   // Fields used in the condition
355///     // Other fields can be added, but typically only condition fields are necessary
356/// }
357/// ```
358/// 
359/// - `Deletable`: Automatically generates SQL DELETE statements
360/// - `SqlParams`: Automatically generates SQL parameters
361/// - `#[table("table_name")]`: Specifies the table name for the deletion
362/// - `#[where_clause("id = $")]`: Specifies the delete condition (`$` will be replaced with parameter value)
363/// 
364/// ## Example Usage
365/// ```rust,no_run
366/// use postgres::{Client, NoTls, Error};
367/// use parsql::postgres::delete;
368/// 
369/// #[derive(Deletable, SqlParams)]
370/// #[table("users")]
371/// #[where_clause("id = $")]
372/// pub struct DeleteUser {
373///     pub id: i32,
374/// }
375/// 
376/// fn main() -> Result<(), Error> {
377///     let mut client = Client::connect(
378///         "host=localhost user=postgres dbname=test",
379///         NoTls,
380///     )?;
381///
382///     let delete_user = DeleteUser { id: 6 };
383///     let delete_result = delete(&mut client, delete_user)?;
384///     
385///     println!("Delete result: {:?}", delete_result);
386///     Ok(())
387/// }
388/// ```
389pub fn delete<T: SqlQuery + SqlParams>(
390    client: &mut postgres::Client,
391    entity: T,
392) -> Result<u64, Error> {
393    let sql = T::query();
394    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
395        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
396    }
397
398    let params = entity.params();
399    match client.execute(&sql, &params) {
400        Ok(rows_affected) => Ok(rows_affected),
401        Err(e) => Err(e),
402    }
403}
404
405/// # fetch
406/// 
407/// Retrieves a single record from the database.
408/// 
409/// ## Parameters
410/// - `client`: Database connection client
411/// - `params`: Query parameters (must implement SqlQuery, FromRow, and SqlParams traits)
412/// 
413/// ## Return Value
414/// - `Result<T, Error>`: On success, returns the retrieved record; on failure, returns Error
415/// 
416/// ## Struct Definition
417/// Structs used with this function should be annotated with the following derive macros:
418/// 
419/// ```rust,no_run
420/// #[derive(Queryable, FromRow, SqlParams)]  // Required macros
421/// #[table("table_name")]                    // Table name to query
422/// #[where_clause("id = $1")]                // WHERE clause with parameter placeholders
423/// struct GetUser {
424///     id: i32,                              // Parameter for the WHERE clause
425///     name: String,                         // Field to retrieve
426///     email: String,                        // Field to retrieve
427/// }
428/// ```
429pub fn fetch<T: SqlQuery + FromRow + SqlParams>(
430    client: &mut Client,
431    params: &T,
432) -> Result<T, Error> {
433    let sql = T::query();
434    
435    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
436        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
437    }
438
439    let query_params = params.params();
440    let row = client.query_one(&sql, &query_params)?;
441    T::from_row(&row)
442}
443
444/// # fetch_all
445/// 
446/// Retrieves multiple records from the database.
447/// 
448/// ## Parameters
449/// - `client`: Database connection client
450/// - `params`: Query parameters (must implement SqlQuery, FromRow, and SqlParams traits)
451/// 
452/// ## Return Value
453/// - `Result<Vec<T>, Error>`: On success, returns a vector of records; on failure, returns Error
454/// 
455/// ## Struct Definition
456/// Structs used with this function should be annotated with the following derive macros:
457/// 
458/// ```rust,no_run
459/// #[derive(Queryable, FromRow, SqlParams)]  // Required macros
460/// #[table("users")]                         // Table name to query
461/// #[where_clause("active = $1")]            // WHERE clause with parameter placeholders
462/// struct GetUsers {
463///     active: bool,                         // Parameter for the WHERE clause
464///     id: i32,                              // Field to retrieve
465///     name: String,                         // Field to retrieve
466///     email: String,                        // Field to retrieve
467/// }
468/// ```
469pub fn fetch_all<T: SqlQuery + FromRow + SqlParams>(
470    client: &mut Client,
471    params: &T,
472) -> Result<Vec<T>, Error> {
473    let sql = T::query();
474    
475    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
476        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
477    }
478
479    let query_params = params.params();
480    let rows = client.query(&sql, &query_params)?;
481    
482    let mut results = Vec::with_capacity(rows.len());
483    for row in &rows {
484        results.push(T::from_row(row)?);
485    }
486    
487    Ok(results)
488}
489
490/// # get_by_query
491/// 
492/// Retrieves multiple records from the database using a custom SQL query.
493/// 
494/// ## Parameters
495/// - `client`: Database connection client
496/// - `query`: Custom SQL query string
497/// - `params`: Array of query parameters
498/// 
499/// ## Return Value
500/// - `Result<Vec<T>, Error>`: On success, returns the list of found records; on failure, returns Error
501/// 
502/// ## Example Usage
503/// ```rust,no_run
504/// use postgres::{Client, NoTls, Error};
505/// use parsql::postgres::get_by_query;
506/// 
507/// #[derive(FromRow, Debug)]
508/// pub struct UserStats {
509///     pub state: i16,
510///     pub user_count: i64,
511/// }
512///
513/// fn main() -> Result<(), Error> {
514///     let mut client = Client::connect(
515///         "host=localhost user=postgres dbname=test",
516///         NoTls,
517///     )?;
518///
519///     let query = "SELECT state, COUNT(*) as user_count FROM users GROUP BY state HAVING COUNT(*) > $1";
520///     let min_count = 5;
521///     
522///     let stats = get_by_query::<UserStats>(&mut client, query, &[&min_count])?;
523///     println!("User stats: {:?}", stats);
524///     Ok(())
525/// }
526/// ```
527pub fn get_by_query<T: FromRow>(
528    client: &mut Client,
529    query: &str,
530    params: &[&(dyn ToSql + Sync)],
531) -> Result<Vec<T>, Error> {
532    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
533        println!("[PARSQL-POSTGRES] Execute SQL: {}", query);
534    }
535
536    let rows = client.query(query, params)?;
537    rows.iter()
538        .map(|row| T::from_row(row))
539        .collect::<Result<Vec<_>, _>>()
540}
541
542/// # select
543/// 
544/// Retrieves a single record from the database using a custom transformation function.
545/// This is useful when you want to use a custom transformation function instead of the FromRow trait.
546/// 
547/// ## Parameters
548/// - `client`: Database connection client
549/// - `entity`: Query parameter object (must implement SqlQuery and SqlParams traits)
550/// - `to_model`: Function to convert a Row object to the target object type
551/// 
552/// ## Return Value
553/// - `Result<T, Error>`: On success, returns the transformed object; on failure, returns Error
554/// 
555/// ## Struct Definition
556/// Structs used with this function should be annotated with the following derive macros:
557/// 
558/// ```rust,no_run
559/// #[derive(Queryable, SqlParams)]          // Required macros (FromRow is not needed)
560/// #[table("table_name")]                   // Table name to query
561/// #[where_clause("id = $")]                // Query condition
562/// pub struct MyQueryEntity {
563///     pub id: i32,                         // Field used in the query condition
564///     // Other fields can be added if necessary for the query condition
565/// }
566/// 
567/// // A separate struct can be used for the return value
568/// pub struct MyResultEntity {
569///     pub id: i32,
570///     pub name: String,
571///     pub count: i64,
572/// }
573/// ```
574/// 
575/// - `Queryable`: Automatically generates SQL SELECT statements
576/// - `SqlParams`: Automatically generates SQL parameters
577/// - `#[table("table_name")]`: Specifies the table name for the query
578/// - `#[where_clause("id = $")]`: Specifies the query condition (`$` will be replaced with parameter value)
579/// 
580/// ## Example Usage
581/// ```rust,no_run
582/// use postgres::{Client, NoTls, Error};
583/// use parsql::postgres::select;
584/// 
585/// #[derive(Queryable, SqlParams)]
586/// #[table("users")]
587/// #[where_clause("id = $")]
588/// pub struct UserQuery {
589///     pub id: i32,
590/// }
591/// 
592/// impl UserQuery {
593///     pub fn new(id: i32) -> Self {
594///         Self { id }
595///     }
596/// }
597/// 
598/// // Different return structure
599/// pub struct User {
600///     pub id: i32,
601///     pub name: String,
602/// }
603///
604/// fn main() -> Result<(), Error> {
605///     let mut client = Client::connect(
606///         "host=localhost user=postgres dbname=test",
607///         NoTls,
608///     )?;
609///
610///     // A custom model transformation function is required
611///     let user_query = UserQuery::new(1);
612///     let user = select(&mut client, user_query, |row| {
613///         let id: i32 = row.get("id");
614///         let name: String = row.get("name");
615///         Ok(User { id, name })
616///     })?;
617///     
618///     println!("User: {:?}", user);
619///     Ok(())
620/// }
621/// ```
622pub fn select<T: SqlQuery + SqlParams, F>(
623    client: &mut postgres::Client,
624    entity: T,
625    to_model: F,
626) -> Result<T, Error>
627where
628    F: Fn(&Row) -> Result<T, Error>,
629{
630    let sql = T::query();
631    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
632        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
633    }
634
635    let params = entity.params();
636
637    match client.query_one(&sql, &params) {
638        Ok(_row) => to_model(&_row),
639        Err(e) => Err(e),
640    }
641}
642
643/// # select_all
644/// 
645/// Retrieves multiple records from the database using a custom transformation function.
646/// This is useful when you want to use a custom transformation function instead of the FromRow trait.
647/// 
648/// ## Parameters
649/// - `client`: Database connection client
650/// - `entity`: Query parameter object (must implement SqlQuery and SqlParams traits)
651/// - `to_model`: Function to convert a Row object to the target object type
652/// 
653/// ## Return Value
654/// - `Result<Vec<T>, Error>`: On success, returns the list of transformed objects; on failure, returns Error
655/// 
656/// ## Struct Definition
657/// Structs used with this function should be annotated with the following derive macros:
658/// 
659/// ```rust,no_run
660/// #[derive(Queryable, SqlParams)]          // Required macros (FromRow is not needed)
661/// #[table("table_name")]                   // Table name to query
662/// #[select("id, name, COUNT(*) as count")] // Custom SELECT statement (optional)
663/// #[where_clause("active = $")]            // Query condition
664/// pub struct MyQueryEntity {
665///     pub active: bool,                    // Field used in the query condition
666///     // Other fields can be added if necessary for the query condition
667/// }
668/// 
669/// // A separate struct can be used for the return value
670/// pub struct MyResultEntity {
671///     pub id: i32,
672///     pub name: String,
673///     pub count: i64,
674/// }
675/// ```
676/// 
677/// - `Queryable`: Automatically generates SQL SELECT statements
678/// - `SqlParams`: Automatically generates SQL parameters
679/// - `#[table("table_name")]`: Specifies the table name for the query
680/// - `#[select("...")]`: Creates a custom SELECT statement (if omitted, all fields will be selected)
681/// - `#[where_clause("active = $")]`: Specifies the query condition (`$` will be replaced with parameter value)
682/// 
683/// ## Example Usage
684/// ```rust,no_run
685/// use postgres::{Client, NoTls, Error};
686/// use parsql::postgres::select_all;
687/// 
688/// #[derive(Queryable, SqlParams)]
689/// #[table("users")]
690/// #[select("id, name, email")]
691/// pub struct UsersQuery {
692///     // Can be empty for a parameterless query
693/// }
694/// 
695/// impl UsersQuery {
696///     pub fn new() -> Self {
697///         Self {}
698///     }
699/// }
700/// 
701/// // Different return structure
702/// pub struct User {
703///     pub id: i32,
704///     pub name: String,
705/// }
706///
707/// fn main() -> Result<(), Error> {
708///     let mut client = Client::connect(
709///         "host=localhost user=postgres dbname=test",
710///         NoTls,
711///     )?;
712///
713///     // A custom model transformation function is required
714///     let users_query = UsersQuery::new();
715///     let users = select_all(&mut client, users_query, |row| {
716///         let id: i32 = row.get("id");
717///         let name: String = row.get("name");
718///         User { id, name }
719///     })?;
720///     
721///     println!("Users: {:?}", users);
722///     Ok(())
723/// }
724/// ```
725pub fn select_all<T: SqlQuery + SqlParams, F>(
726    client: &mut postgres::Client,
727    entity: T,
728    to_model: F,
729) -> Result<Vec<T>, Error>
730where
731    F: Fn(&Row) -> Result<T, Error>,
732{
733    let sql = T::query();
734    if std::env::var("PARSQL_TRACE").unwrap_or_default() == "1" {
735        println!("[PARSQL-POSTGRES] Execute SQL: {}", sql);
736    }
737
738    let params = entity.params();
739
740    let rows = client.query(&sql, &params)?;
741
742    rows.iter()
743        .map(|row| to_model(row))
744        .collect::<Result<Vec<_>, _>>()
745}
746
747// Geriye dönük uyumluluk için eski get fonksiyonunu koruyalım
748#[deprecated(
749    since = "0.2.0",
750    note = "Renamed to `fetch`. Please use `fetch` function instead."
751)]
752/// # get
753/// 
754/// Retrieves a single record from the database.
755/// 
756/// This function is deprecated. Please use `fetch` instead.
757pub fn get<T: SqlQuery + FromRow + SqlParams>(
758    client: &mut Client,
759    params: &T,
760) -> Result<T, Error> {
761    fetch(client, params)
762}
763
764// Geriye dönük uyumluluk için eski get_all fonksiyonunu koruyalım
765#[deprecated(
766    since = "0.2.0",
767    note = "Renamed to `fetch_all`. Please use `fetch_all` function instead."
768)]
769/// # get_all
770/// 
771/// Retrieves multiple records from the database.
772/// 
773/// This function is deprecated. Please use `fetch_all` instead.
774pub fn get_all<T: SqlQuery + FromRow + SqlParams>(
775    client: &mut Client,
776    params: &T,
777) -> Result<Vec<T>, Error> {
778    fetch_all(client, params)
779}