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(¶m)?;
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(¶m)?;
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(¶m, |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(¶m, |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, ¶m)?;
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, ¶m)?;
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/// ¶m,
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/// ¶m,
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}