parsql_sqlite/
transactional_ops.rs

1//! Transaction operations for SQLite
2//!
3//! This module provides functions for performing CRUD operations within a transaction.
4
5use rusqlite::{Connection, Transaction, Error, ToSql};
6use crate::crud_ops::CrudOps;
7use crate::{SqlParams, SqlQuery, UpdateParams, FromRow};
8
9/// Implementation of CrudOps for Transaction
10impl<'conn> CrudOps for Transaction<'conn> {
11    /// Inserts a record into the database and returns the number of rows affected.
12    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
13    ///
14    /// # Arguments
15    /// * `entity` - A struct that implements Insertable and SqlParams traits
16    ///
17    /// # Returns
18    /// * `Result<usize, Error>` - Number of affected rows or an error
19    ///
20    /// # Example
21    /// ```rust,no_run
22    /// use rusqlite::{Connection, Result};
23    /// use parsql::sqlite::CrudOps;
24    /// use parsql::sqlite::transactional;
25    /// use parsql::macros::{Insertable, SqlParams};
26    ///
27    /// #[derive(Insertable, SqlParams)]
28    /// #[table("users")]
29    /// struct InsertUser {
30    ///     name: String,
31    ///     email: String,
32    /// }
33    ///
34    /// fn main() -> Result<()> {
35    ///     let conn = Connection::open("test.db")?;
36    ///     let tx = transactional::begin(&conn)?;
37    ///     
38    ///     let user = InsertUser {
39    ///         name: "John".to_string(),
40    ///         email: "john@example.com".to_string(),
41    ///     };
42    ///     
43    ///     let rows_affected = tx.insert(user)?;
44    ///     
45    ///     tx.commit()?;
46    ///     Ok(())
47    /// }
48    /// ```
49    fn insert<T: SqlQuery + SqlParams>(&self, entity: T) -> Result<usize, Error> {
50        let sql = T::query();
51        
52        // Debug log the SQL query
53        #[cfg(debug_assertions)]
54        println!("[SQL] {}", sql);
55        
56        let params = entity.params();
57        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
58        
59        self.execute(&sql, param_refs.as_slice())
60    }
61
62    /// Updates a record in the database and returns the number of rows affected.
63    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
64    ///
65    /// # Arguments
66    /// * `entity` - A struct that implements Updateable and UpdateParams traits
67    ///
68    /// # Returns
69    /// * `Result<usize, Error>` - Number of affected rows or an error
70    ///
71    /// # Example
72    /// ```rust,no_run
73    /// use rusqlite::{Connection, Result};
74    /// use parsql::sqlite::CrudOps;
75    /// use parsql::sqlite::transactional;
76    /// use parsql::macros::{Updateable, UpdateParams};
77    ///
78    /// #[derive(Updateable, UpdateParams)]
79    /// #[table("users")]
80    /// #[update("name, email")]
81    /// #[where_clause("id = ?")]
82    /// struct UpdateUser {
83    ///     id: i64,
84    ///     name: String,
85    ///     email: String,
86    /// }
87    ///
88    /// fn main() -> Result<()> {
89    ///     let conn = Connection::open("test.db")?;
90    ///     let tx = transactional::begin(&conn)?;
91    ///     
92    ///     let user = UpdateUser {
93    ///         id: 1,
94    ///         name: "John Doe".to_string(),
95    ///         email: "john.doe@example.com".to_string(),
96    ///     };
97    ///     
98    ///     let rows_affected = tx.update(user)?;
99    ///     
100    ///     tx.commit()?;
101    ///     Ok(())
102    /// }
103    /// ```
104    fn update<T: SqlQuery + UpdateParams>(&self, entity: T) -> Result<usize, Error> {
105        let sql = T::query();
106        
107        // Debug log the SQL query
108        #[cfg(debug_assertions)]
109        println!("[SQL] {}", sql);
110        
111        let params = entity.params();
112        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
113        
114        self.execute(&sql, param_refs.as_slice())
115    }
116
117    /// Deletes a record from the database and returns the number of rows affected.
118    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
119    ///
120    /// # Arguments
121    /// * `entity` - A struct that implements Deletable and SqlParams traits
122    ///
123    /// # Returns
124    /// * `Result<usize, Error>` - Number of affected rows or an error
125    ///
126    /// # Example
127    /// ```rust,no_run
128    /// use rusqlite::{Connection, Result};
129    /// use parsql::sqlite::CrudOps;
130    /// use parsql::sqlite::transactional;
131    /// use parsql::macros::{Deletable, SqlParams};
132    ///
133    /// #[derive(Deletable, SqlParams)]
134    /// #[table("users")]
135    /// #[where_clause("id = ?")]
136    /// struct DeleteUser {
137    ///     id: i64,
138    /// }
139    ///
140    /// fn main() -> Result<()> {
141    ///     let conn = Connection::open("test.db")?;
142    ///     let tx = transactional::begin(&conn)?;
143    ///     
144    ///     let user = DeleteUser { id: 1 };
145    ///     
146    ///     let rows_affected = tx.delete(user)?;
147    ///     
148    ///     tx.commit()?;
149    ///     Ok(())
150    /// }
151    /// ```
152    fn delete<T: SqlQuery + SqlParams>(&self, entity: T) -> Result<usize, Error> {
153        let sql = T::query();
154        
155        // Debug log the SQL query
156        #[cfg(debug_assertions)]
157        println!("[SQL] {}", sql);
158        
159        let params = entity.params();
160        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
161        
162        self.execute(&sql, param_refs.as_slice())
163    }
164
165    /// Gets a single record from the database and converts it to a struct.
166    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
167    ///
168    /// # Arguments
169    /// * `entity` - A struct that implements Queryable, SqlParams, and FromRow traits
170    ///
171    /// # Returns
172    /// * `Result<T, Error>` - The retrieved record as a struct or an error
173    ///
174    /// # Example
175    /// ```rust,no_run
176    /// use rusqlite::{Connection, Result};
177    /// use parsql::sqlite::CrudOps;
178    /// use parsql::sqlite::transactional;
179    /// use parsql::macros::{Queryable, SqlParams, FromRow};
180    ///
181    /// #[derive(Queryable, SqlParams, FromRow)]
182    /// #[table("users")]
183    /// #[where_clause("id = ?")]
184    /// struct GetUser {
185    ///     id: i64,
186    ///     name: String,
187    ///     email: String,
188    /// }
189    ///
190    /// fn main() -> Result<()> {
191    ///     let conn = Connection::open("test.db")?;
192    ///     let tx = transactional::begin(&conn)?;
193    ///     
194    ///     let param = GetUser {
195    ///         id: 1,
196    ///         name: String::new(),
197    ///         email: String::new(),
198    ///     };
199    ///     
200    ///     let user = tx.get(&param)?;
201    ///     
202    ///     tx.commit()?;
203    ///     println!("Found user: {} - {}", user.name, user.email);
204    ///     Ok(())
205    /// }
206    /// ```
207    fn get<T: SqlQuery + FromRow + SqlParams>(&self, entity: &T) -> Result<T, Error> {
208        let sql = T::query();
209        
210        // Debug log the SQL query
211        #[cfg(debug_assertions)]
212        println!("[SQL] {}", sql);
213        
214        let params = entity.params();
215        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
216        
217        let mut stmt = self.prepare(&sql)?;
218        let row = stmt.query_row(param_refs.as_slice(), |row| T::from_row(row))?;
219        
220        Ok(row)
221    }
222
223    /// Gets multiple records from the database and converts them to a vector of structs.
224    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
225    ///
226    /// # Arguments
227    /// * `entity` - A struct that implements Queryable, SqlParams, and FromRow traits
228    ///
229    /// # Returns
230    /// * `Result<Vec<T>, Error>` - A vector of retrieved records as structs or an error
231    ///
232    /// # Example
233    /// ```rust,no_run
234    /// use rusqlite::{Connection, Result};
235    /// use parsql::sqlite::CrudOps;
236    /// use parsql::sqlite::transactional;
237    /// use parsql::macros::{Queryable, SqlParams, FromRow};
238    ///
239    /// #[derive(Queryable, SqlParams, FromRow)]
240    /// #[table("users")]
241    /// #[where_clause("email LIKE ?")]
242    /// struct GetUsers {
243    ///     id: i64,
244    ///     name: String,
245    ///     email: String,
246    /// }
247    ///
248    /// fn main() -> Result<()> {
249    ///     let conn = Connection::open("test.db")?;
250    ///     let tx = transactional::begin(&conn)?;
251    ///     
252    ///     let param = GetUsers {
253    ///         id: 0,
254    ///         name: String::new(),
255    ///         email: "%example.com".to_string(),
256    ///     };
257    ///     
258    ///     let users = tx.get_all(&param)?;
259    ///     
260    ///     tx.commit()?;
261    ///     for user in users {
262    ///         println!("Found user: {} - {}", user.name, user.email);
263    ///     }
264    ///     Ok(())
265    /// }
266    /// ```
267    fn get_all<T: SqlQuery + FromRow + SqlParams>(&self, entity: &T) -> Result<Vec<T>, Error> {
268        let sql = T::query();
269        
270        // Debug log the SQL query
271        #[cfg(debug_assertions)]
272        println!("[SQL] {}", sql);
273        
274        let params = entity.params();
275        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
276        
277        let mut stmt = self.prepare(&sql)?;
278        let rows = stmt.query_map(param_refs.as_slice(), |row| T::from_row(row))?;
279        
280        let mut results = Vec::new();
281        for row_result in rows {
282            results.push(row_result?);
283        }
284        
285        Ok(results)
286    }
287
288    /// Executes a custom SELECT query and transforms the result using a provided function.
289    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
290    ///
291    /// # Arguments
292    /// * `entity` - Data object containing query parameters
293    /// * `to_model` - Function to transform a row into a value
294    ///
295    /// # Returns
296    /// * `Result<R, Error>` - The transformed value or an error
297    ///
298    /// # Example
299    /// ```rust,no_run
300    /// use rusqlite::{Connection, Result};
301    /// use parsql::sqlite::CrudOps;
302    /// use parsql::sqlite::transactional;
303    /// use parsql::macros::{Queryable, SqlParams};
304    ///
305    /// #[derive(Queryable, SqlParams)]
306    /// #[table("users")]
307    /// #[where_clause("email LIKE ?")]
308    /// struct CountUsers {
309    ///     email: String,
310    /// }
311    ///
312    /// fn main() -> Result<()> {
313    ///     let conn = Connection::open("test.db")?;
314    ///     let tx = transactional::begin(&conn)?;
315    ///     
316    ///     let param = CountUsers {
317    ///         email: "%example.com".to_string(),
318    ///     };
319    ///     
320    ///     let count: i64 = tx.select(&param, |row| row.get(0))?;
321    ///     
322    ///     tx.commit()?;
323    ///     println!("Number of users: {}", count);
324    ///     Ok(())
325    /// }
326    /// ```
327    fn select<T: SqlQuery + SqlParams, F, R>(&self, entity: &T, to_model: F) -> Result<R, Error>
328    where
329        F: Fn(&rusqlite::Row) -> Result<R, Error>,
330    {
331        let sql = T::query();
332        
333        // Debug log the SQL query
334        #[cfg(debug_assertions)]
335        println!("[SQL] {}", sql);
336        
337        let params = entity.params();
338        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
339        
340        let mut stmt = self.prepare(&sql)?;
341        stmt.query_row(param_refs.as_slice(), to_model)
342    }
343
344    /// Executes a custom SELECT query and transforms all results using a provided function.
345    /// This function is an extension to the Transaction struct and is available when the CrudOps trait is in scope.
346    ///
347    /// # Arguments
348    /// * `entity` - Data object containing query parameters
349    /// * `to_model` - Function to transform rows into values
350    ///
351    /// # Returns
352    /// * `Result<Vec<R>, Error>` - A vector of transformed values or an error
353    ///
354    /// # Example
355    /// ```rust,no_run
356    /// use rusqlite::{Connection, Result};
357    /// use parsql::sqlite::CrudOps;
358    /// use parsql::sqlite::transactional;
359    /// use parsql::macros::{Queryable, SqlParams};
360    ///
361    /// #[derive(Queryable, SqlParams)]
362    /// #[table("users")]
363    /// #[where_clause("email LIKE ?")]
364    /// struct GetUserNames {
365    ///     email: String,
366    /// }
367    ///
368    /// fn main() -> Result<()> {
369    ///     let conn = Connection::open("test.db")?;
370    ///     let tx = transactional::begin(&conn)?;
371    ///     
372    ///     let param = GetUserNames {
373    ///         email: "%example.com".to_string(),
374    ///     };
375    ///     
376    ///     let names: Vec<String> = tx.select_all(&param, |row| row.get(0))?;
377    ///     
378    ///     tx.commit()?;
379    ///     for name in names {
380    ///         println!("User name: {}", name);
381    ///     }
382    ///     Ok(())
383    /// }
384    /// ```
385    fn select_all<T: SqlQuery + SqlParams, F, R>(&self, entity: &T, to_model: F) -> Result<Vec<R>, Error>
386    where
387        F: Fn(&rusqlite::Row) -> Result<R, Error>,
388    {
389        let sql = T::query();
390        
391        // Debug log the SQL query
392        #[cfg(debug_assertions)]
393        println!("[SQL] {}", sql);
394        
395        let params = entity.params();
396        let param_refs: Vec<&dyn ToSql> = params.iter().map(|p| *p as &dyn ToSql).collect();
397        
398        let mut stmt = self.prepare(&sql)?;
399        let rows = stmt.query_map(param_refs.as_slice(), to_model)?;
400        
401        let mut results = Vec::new();
402        for row_result in rows {
403            results.push(row_result?);
404        }
405        
406        Ok(results)
407    }
408}
409
410/// Begin a new transaction.
411///
412/// # Arguments
413/// * `conn` - A reference to a SQLite connection
414///
415/// # Returns
416/// * `Result<Transaction>` - A new transaction or an error
417///
418/// # Example
419/// ```rust,no_run
420/// use rusqlite::{Connection, Result};
421/// use parsql::sqlite::transactional;
422///
423/// fn main() -> Result<()> {
424///     let conn = Connection::open("test.db")?;
425///     let tx = transactional::begin(&conn)?;
426///     
427///     // ... perform operations ...
428///     
429///     tx.commit()?;
430///     Ok(())
431/// }
432/// ```
433pub fn begin(conn: &Connection) -> Result<Transaction, Error> {
434    conn.unchecked_transaction()
435}
436
437/// Insert a record within a transaction.
438///
439/// # Arguments
440/// * `tx` - A transaction
441/// * `entity` - A struct that implements Insertable and SqlParams traits
442///
443/// # Returns
444/// * `Result<(Transaction, usize)>` - The transaction and number of affected rows, or an error
445///
446/// # Example
447/// ```rust,no_run
448/// use rusqlite::{Connection, Result};
449/// use parsql::sqlite::transactional;
450/// use parsql::macros::{Insertable, SqlParams};
451///
452/// #[derive(Insertable, SqlParams)]
453/// #[table("users")]
454/// struct InsertUser {
455///     name: String,
456///     email: String,
457/// }
458///
459/// fn main() -> Result<()> {
460///     let conn = Connection::open("test.db")?;
461///     let tx = transactional::begin(&conn)?;
462///     
463///     let user = InsertUser {
464///         name: "John".to_string(),
465///         email: "john@example.com".to_string(),
466///     };
467///     
468///     let (tx, rows_affected) = transactional::tx_insert(tx, user)?;
469///     
470///     tx.commit()?;
471///     Ok(())
472/// }
473/// ```
474pub fn tx_insert<'a, T: SqlQuery + SqlParams>(
475    tx: Transaction<'a>, 
476    entity: T
477) -> Result<(Transaction<'a>, usize), Error> {
478    let rows_affected = tx.insert(entity)?;
479    Ok((tx, rows_affected))
480}
481
482/// Update a record within a transaction.
483///
484/// # Arguments
485/// * `tx` - A transaction
486/// * `entity` - A struct that implements Updateable and UpdateParams traits
487///
488/// # Returns
489/// * `Result<(Transaction, usize)>` - The transaction and number of affected rows, or an error
490///
491/// # Example
492/// ```rust,no_run
493/// use rusqlite::{Connection, Result};
494/// use parsql::sqlite::transactional;
495/// use parsql::macros::{Updateable, UpdateParams};
496///
497/// #[derive(Updateable, UpdateParams)]
498/// #[table("users")]
499/// #[update("name, email")]
500/// #[where_clause("id = ?")]
501/// struct UpdateUser {
502///     id: i64,
503///     name: String,
504///     email: String,
505/// }
506///
507/// fn main() -> Result<()> {
508///     let conn = Connection::open("test.db")?;
509///     let tx = transactional::begin(&conn)?;
510///     
511///     let user = UpdateUser {
512///         id: 1,
513///         name: "John Doe".to_string(),
514///         email: "john.doe@example.com".to_string(),
515///     };
516///     
517///     let (tx, rows_affected) = transactional::tx_update(tx, user)?;
518///     
519///     tx.commit()?;
520///     Ok(())
521/// }
522/// ```
523pub fn tx_update<'a, T: SqlQuery + UpdateParams>(
524    tx: Transaction<'a>, 
525    entity: T
526) -> Result<(Transaction<'a>, usize), Error> {
527    let rows_affected = tx.update(entity)?;
528    Ok((tx, rows_affected))
529}
530
531/// Delete a record within a transaction.
532///
533/// # Arguments
534/// * `tx` - A transaction
535/// * `entity` - A struct that implements Deletable and SqlParams traits
536///
537/// # Returns
538/// * `Result<(Transaction, usize)>` - The transaction and number of affected rows, or an error
539///
540/// # Example
541/// ```rust,no_run
542/// use rusqlite::{Connection, Result};
543/// use parsql::sqlite::transactional;
544/// use parsql::macros::{Deletable, SqlParams};
545///
546/// #[derive(Deletable, SqlParams)]
547/// #[table("users")]
548/// #[where_clause("id = ?")]
549/// struct DeleteUser {
550///     id: i64,
551/// }
552///
553/// fn main() -> Result<()> {
554///     let conn = Connection::open("test.db")?;
555///     let tx = transactional::begin(&conn)?;
556///     
557///     let user = DeleteUser { id: 1 };
558///     
559///     let (tx, rows_affected) = transactional::tx_delete(tx, user)?;
560///     
561///     tx.commit()?;
562///     Ok(())
563/// }
564/// ```
565pub fn tx_delete<'a, T: SqlQuery + SqlParams>(
566    tx: Transaction<'a>, 
567    entity: T
568) -> Result<(Transaction<'a>, usize), Error> {
569    let rows_affected = tx.delete(entity)?;
570    Ok((tx, rows_affected))
571}
572
573/// Get a single record within a transaction.
574///
575/// # Arguments
576/// * `tx` - A transaction
577/// * `entity` - A struct that implements Queryable, SqlParams, and FromRow traits
578///
579/// # Returns
580/// * `Result<(Transaction, T)>` - The transaction and retrieved record, or an error
581///
582/// # Example
583/// ```rust,no_run
584/// use rusqlite::{Connection, Result};
585/// use parsql::sqlite::transactional;
586/// use parsql::macros::{Queryable, SqlParams, FromRow};
587///
588/// #[derive(Queryable, SqlParams, FromRow)]
589/// #[table("users")]
590/// #[where_clause("id = ?")]
591/// struct GetUser {
592///     id: i64,
593///     name: String,
594///     email: String,
595/// }
596///
597/// fn main() -> Result<()> {
598///     let conn = Connection::open("test.db")?;
599///     let tx = transactional::begin(&conn)?;
600///     
601///     let param = GetUser {
602///         id: 1,
603///         name: String::new(),
604///         email: String::new(),
605///     };
606///     
607///     let (tx, user) = transactional::tx_get(tx, &param)?;
608///     
609///     println!("Found user: {} - {}", user.name, user.email);
610///     
611///     tx.commit()?;
612///     Ok(())
613/// }
614/// ```
615pub fn tx_get<'a, T: SqlQuery + FromRow + SqlParams>(
616    tx: Transaction<'a>, 
617    entity: &T
618) -> Result<(Transaction<'a>, T), Error> {
619    let result = tx.get(entity)?;
620    Ok((tx, result))
621}
622
623/// Get multiple records within a transaction.
624///
625/// # Arguments
626/// * `tx` - A transaction
627/// * `entity` - A struct that implements Queryable, SqlParams, and FromRow traits
628///
629/// # Returns
630/// * `Result<(Transaction, Vec<T>)>` - The transaction and retrieved records, or an error
631///
632/// # Example
633/// ```rust,no_run
634/// use rusqlite::{Connection, Result};
635/// use parsql::sqlite::transactional;
636/// use parsql::macros::{Queryable, SqlParams, FromRow};
637///
638/// #[derive(Queryable, SqlParams, FromRow)]
639/// #[table("users")]
640/// #[where_clause("email LIKE ?")]
641/// struct GetUsers {
642///     id: i64,
643///     name: String,
644///     email: String,
645/// }
646///
647/// fn main() -> Result<()> {
648///     let conn = Connection::open("test.db")?;
649///     let tx = transactional::begin(&conn)?;
650///     
651///     let param = GetUsers {
652///         id: 0,
653///         name: String::new(),
654///         email: "%example.com".to_string(),
655///     };
656///     
657///     let (tx, users) = transactional::tx_get_all(tx, &param)?;
658///     
659///     for user in users {
660///         println!("Found user: {} - {}", user.name, user.email);
661///     }
662///     
663///     tx.commit()?;
664///     Ok(())
665/// }
666/// ```
667pub fn tx_get_all<'a, T: SqlQuery + FromRow + SqlParams>(
668    tx: Transaction<'a>, 
669    entity: &T
670) -> Result<(Transaction<'a>, Vec<T>), Error> {
671    let results = tx.get_all(entity)?;
672    Ok((tx, results))
673}
674
675/// Execute a custom SELECT query within a transaction and transform the result.
676///
677/// # Arguments
678/// * `tx` - A transaction
679/// * `entity` - Data object containing query parameters
680/// * `to_model` - Function to transform a row into a value
681///
682/// # Returns
683/// * `Result<(Transaction, R)>` - The transaction and transformed value, or an error
684///
685/// # Example
686/// ```rust,no_run
687/// use rusqlite::{Connection, Result};
688/// use parsql::sqlite::transactional;
689/// use parsql::macros::{Queryable, SqlParams};
690///
691/// #[derive(Queryable, SqlParams)]
692/// #[table("users")]
693/// #[where_clause("email LIKE ?")]
694/// struct CountUsers {
695///     email: String,
696/// }
697///
698/// fn main() -> Result<()> {
699///     let conn = Connection::open("test.db")?;
700///     let tx = transactional::begin(&conn)?;
701///     
702///     let param = CountUsers {
703///         email: "%example.com".to_string(),
704///     };
705///     
706///     let (tx, count): (_, i64) = transactional::tx_select(
707///         tx,
708///         &param,
709///         |row| row.get(0)
710///     )?;
711///     
712///     println!("Number of users: {}", count);
713///     
714///     tx.commit()?;
715///     Ok(())
716/// }
717/// ```
718pub fn tx_select<'a, T, F, R>(
719    tx: Transaction<'a>,
720    entity: &T,
721    to_model: F,
722) -> Result<(Transaction<'a>, R), Error>
723where
724    T: SqlQuery + SqlParams,
725    F: Fn(&rusqlite::Row) -> Result<R, Error>,
726{
727    let result = tx.select(entity, to_model)?;
728    Ok((tx, result))
729}
730
731/// Execute a custom SELECT query within a transaction and transform all results.
732///
733/// # Arguments
734/// * `tx` - A transaction
735/// * `entity` - Data object containing query parameters
736/// * `to_model` - Function to transform rows into values
737///
738/// # Returns
739/// * `Result<(Transaction, Vec<R>)>` - The transaction and transformed values, or an error
740///
741/// # Example
742/// ```rust,no_run
743/// use rusqlite::{Connection, Result};
744/// use parsql::sqlite::transactional;
745/// use parsql::macros::{Queryable, SqlParams};
746///
747/// #[derive(Queryable, SqlParams)]
748/// #[table("users")]
749/// #[where_clause("email LIKE ?")]
750/// struct GetUserNames {
751///     email: String,
752/// }
753///
754/// fn main() -> Result<()> {
755///     let conn = Connection::open("test.db")?;
756///     let tx = transactional::begin(&conn)?;
757///     
758///     let param = GetUserNames {
759///         email: "%example.com".to_string(),
760///     };
761///     
762///     let (tx, names): (_, Vec<String>) = transactional::tx_select_all(
763///         tx,
764///         &param,
765///         |row| row.get(0)
766///     )?;
767///     
768///     for name in names {
769///         println!("User name: {}", name);
770///     }
771///     
772///     tx.commit()?;
773///     Ok(())
774/// }
775/// ```
776pub fn tx_select_all<'a, T, F, R>(
777    tx: Transaction<'a>,
778    entity: &T,
779    to_model: F,
780) -> Result<(Transaction<'a>, Vec<R>), Error>
781where
782    T: SqlQuery + SqlParams,
783    F: Fn(&rusqlite::Row) -> Result<R, Error>,
784{
785    let results = tx.select_all(entity, to_model)?;
786    Ok((tx, results))
787}