1use fallible_iterator::FallibleIterator;
2use fallible_streaming_iterator::FallibleStreamingIterator;
3use std::convert;
4
5use super::{Error, Result, Statement};
6use crate::types::{FromSql, FromSqlError, ValueRef};
7
8#[must_use = "Rows is lazy and will do nothing unless consumed"]
10pub struct Rows<'stmt> {
11 pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
12 row: Option<Row<'stmt>>,
13}
14
15impl<'stmt> Rows<'stmt> {
16 #[inline]
17 fn reset(&mut self) {
18 if let Some(stmt) = self.stmt.take() {
19 stmt.reset();
20 }
21 }
22
23 #[allow(clippy::should_implement_trait)] #[inline]
37 pub fn next(&mut self) -> Result<Option<&Row<'stmt>>> {
38 self.advance()?;
39 Ok((*self).get())
40 }
41
42 #[inline]
54 pub fn map<F, B>(self, f: F) -> Map<'stmt, F>
55 where
56 F: FnMut(&Row<'_>) -> Result<B>,
57 {
58 Map { rows: self, f }
59 }
60
61 #[inline]
64 pub fn mapped<F, B>(self, f: F) -> MappedRows<'stmt, F>
65 where
66 F: FnMut(&Row<'_>) -> Result<B>,
67 {
68 MappedRows { rows: self, map: f }
69 }
70
71 #[inline]
75 pub fn and_then<F, T, E>(self, f: F) -> AndThenRows<'stmt, F>
76 where
77 F: FnMut(&Row<'_>) -> Result<T, E>,
78 {
79 AndThenRows { rows: self, map: f }
80 }
81
82 #[must_use]
84 pub fn as_ref(&self) -> Option<&Statement<'stmt>> {
85 self.stmt
86 }
87}
88
89impl<'stmt> Rows<'stmt> {
90 #[inline]
91 pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
92 Rows {
93 stmt: Some(stmt),
94 row: None,
95 }
96 }
97
98 #[inline]
99 pub(crate) fn get_expected_row(&mut self) -> Result<&Row<'stmt>> {
100 match self.next()? {
101 Some(row) => Ok(row),
102 None => Err(Error::QueryReturnedNoRows),
103 }
104 }
105}
106
107impl Drop for Rows<'_> {
108 #[inline]
109 fn drop(&mut self) {
110 self.reset();
111 }
112}
113
114#[must_use = "iterators are lazy and do nothing unless consumed"]
117pub struct Map<'stmt, F> {
118 rows: Rows<'stmt>,
119 f: F,
120}
121
122impl<F, B> FallibleIterator for Map<'_, F>
123where
124 F: FnMut(&Row<'_>) -> Result<B>,
125{
126 type Error = Error;
127 type Item = B;
128
129 #[inline]
130 fn next(&mut self) -> Result<Option<B>> {
131 match self.rows.next()? {
132 Some(v) => Ok(Some((self.f)(v)?)),
133 None => Ok(None),
134 }
135 }
136}
137
138#[must_use = "iterators are lazy and do nothing unless consumed"]
143pub struct MappedRows<'stmt, F> {
144 rows: Rows<'stmt>,
145 map: F,
146}
147
148impl<T, F> Iterator for MappedRows<'_, F>
149where
150 F: FnMut(&Row<'_>) -> Result<T>,
151{
152 type Item = Result<T>;
153
154 #[inline]
155 fn next(&mut self) -> Option<Result<T>> {
156 let map = &mut self.map;
157 self.rows
158 .next()
159 .transpose()
160 .map(|row_result| row_result.and_then(map))
161 }
162}
163
164#[must_use = "iterators are lazy and do nothing unless consumed"]
167pub struct AndThenRows<'stmt, F> {
168 rows: Rows<'stmt>,
169 map: F,
170}
171
172impl<T, E, F> Iterator for AndThenRows<'_, F>
173where
174 E: From<Error>,
175 F: FnMut(&Row<'_>) -> Result<T, E>,
176{
177 type Item = Result<T, E>;
178
179 #[inline]
180 fn next(&mut self) -> Option<Self::Item> {
181 let map = &mut self.map;
182 self.rows
183 .next()
184 .transpose()
185 .map(|row_result| row_result.map_err(E::from).and_then(map))
186 }
187}
188
189impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
208 type Error = Error;
209 type Item = Row<'stmt>;
210
211 #[inline]
212 fn advance(&mut self) -> Result<()> {
213 if let Some(stmt) = self.stmt {
214 match stmt.step() {
215 Ok(true) => {
216 self.row = Some(Row { stmt });
217 Ok(())
218 }
219 Ok(false) => {
220 self.reset();
221 self.row = None;
222 Ok(())
223 }
224 Err(e) => {
225 self.reset();
226 self.row = None;
227 Err(e)
228 }
229 }
230 } else {
231 self.row = None;
232 Ok(())
233 }
234 }
235
236 #[inline]
237 fn get(&self) -> Option<&Row<'stmt>> {
238 self.row.as_ref()
239 }
240}
241
242pub struct Row<'stmt> {
244 pub(crate) stmt: &'stmt Statement<'stmt>,
245}
246
247impl<'stmt> Row<'stmt> {
248 pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
261 self.get(idx).unwrap()
262 }
263
264 pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
281 let idx = idx.idx(self.stmt)?;
282 let value = self.stmt.value_ref(idx);
283 FromSql::column_result(value).map_err(|err| match err {
284 FromSqlError::InvalidType => Error::InvalidColumnType(
285 idx,
286 self.stmt.column_name_unwrap(idx).into(),
287 value.data_type(),
288 ),
289 FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
290 FromSqlError::Other(err) => {
291 Error::FromSqlConversionFailure(idx, value.data_type(), err)
292 }
293 FromSqlError::InvalidBlobSize { .. } => {
294 Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err))
295 }
296 })
297 }
298
299 pub fn get_ref<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
315 let idx = idx.idx(self.stmt)?;
316 let val_ref = self.stmt.value_ref(idx);
320 Ok(val_ref)
321 }
322
323 pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
339 self.get_ref(idx).unwrap()
340 }
341
342 #[deprecated = "Use [`get_ref`](Row::get_ref) instead."]
344 #[inline]
345 pub fn get_raw_checked<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
346 self.get_ref(idx)
347 }
348
349 #[deprecated = "Use [`get_ref_unwrap`](Row::get_ref_unwrap) instead."]
351 #[inline]
352 pub fn get_raw<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
353 self.get_ref_unwrap(idx)
354 }
355}
356
357impl<'stmt> AsRef<Statement<'stmt>> for Row<'stmt> {
358 fn as_ref(&self) -> &Statement<'stmt> {
359 self.stmt
360 }
361}
362
363mod sealed {
364 pub trait Sealed {}
367 impl Sealed for usize {}
368 impl Sealed for &str {}
369}
370
371pub trait RowIndex: sealed::Sealed {
375 fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
378}
379
380impl RowIndex for usize {
381 #[inline]
382 fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
383 if *self >= stmt.column_count() {
384 Err(Error::InvalidColumnIndex(*self))
385 } else {
386 Ok(*self)
387 }
388 }
389}
390
391impl RowIndex for &'_ str {
392 #[inline]
393 fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
394 stmt.column_index(*self)
395 }
396}
397
398macro_rules! tuple_try_from_row {
399 ($($field:ident),*) => {
400 impl<'a, $($field,)*> convert::TryFrom<&'a Row<'a>> for ($($field,)*) where $($field: FromSql,)* {
401 type Error = crate::Error;
402
403 #[allow(unused_assignments, unused_variables, unused_mut)]
406 fn try_from(row: &'a Row<'a>) -> Result<Self> {
407 let mut index = 0;
408 $(
409 #[allow(non_snake_case)]
410 let $field = row.get::<_, $field>(index)?;
411 index += 1;
412 )*
413 Ok(($($field,)*))
414 }
415 }
416 }
417}
418
419macro_rules! tuples_try_from_row {
420 () => {
421 tuple_try_from_row!();
423 };
424 ($first:ident $(, $remaining:ident)*) => {
425 tuple_try_from_row!($first $(, $remaining)*);
426 tuples_try_from_row!($($remaining),*);
427 };
428}
429
430tuples_try_from_row!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
431
432#[cfg(test)]
433mod tests {
434 #![allow(clippy::redundant_closure)] use crate::{Connection, Result};
436
437 #[test]
438 fn test_try_from_row_for_tuple_1() -> Result<()> {
439 use crate::ToSql;
440 use std::convert::TryFrom;
441
442 let conn = Connection::open_in_memory()?;
443 conn.execute(
444 "CREATE TABLE test (a INTEGER)",
445 crate::params_from_iter(std::iter::empty::<&dyn ToSql>()),
446 )?;
447 conn.execute("INSERT INTO test VALUES (42)", [])?;
448 let val = conn.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))?;
449 assert_eq!(val, (42,));
450 let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row));
451 assert!(fail.is_err());
452 Ok(())
453 }
454
455 #[test]
456 fn test_try_from_row_for_tuple_2() -> Result<()> {
457 use std::convert::TryFrom;
458
459 let conn = Connection::open_in_memory()?;
460 conn.execute("CREATE TABLE test (a INTEGER, b INTEGER)", [])?;
461 conn.execute("INSERT INTO test VALUES (42, 47)", [])?;
462 let val = conn.query_row("SELECT a, b FROM test", [], |row| {
463 <(u32, u32)>::try_from(row)
464 })?;
465 assert_eq!(val, (42, 47));
466 let fail = conn.query_row("SELECT a, b FROM test", [], |row| {
467 <(u32, u32, u32)>::try_from(row)
468 });
469 assert!(fail.is_err());
470 Ok(())
471 }
472
473 #[test]
474 fn test_try_from_row_for_tuple_16() -> Result<()> {
475 use std::convert::TryFrom;
476
477 let create_table = "CREATE TABLE test (
478 a INTEGER,
479 b INTEGER,
480 c INTEGER,
481 d INTEGER,
482 e INTEGER,
483 f INTEGER,
484 g INTEGER,
485 h INTEGER,
486 i INTEGER,
487 j INTEGER,
488 k INTEGER,
489 l INTEGER,
490 m INTEGER,
491 n INTEGER,
492 o INTEGER,
493 p INTEGER
494 )";
495
496 let insert_values = "INSERT INTO test VALUES (
497 0,
498 1,
499 2,
500 3,
501 4,
502 5,
503 6,
504 7,
505 8,
506 9,
507 10,
508 11,
509 12,
510 13,
511 14,
512 15
513 )";
514
515 type BigTuple = (
516 u32,
517 u32,
518 u32,
519 u32,
520 u32,
521 u32,
522 u32,
523 u32,
524 u32,
525 u32,
526 u32,
527 u32,
528 u32,
529 u32,
530 u32,
531 u32,
532 );
533
534 let conn = Connection::open_in_memory()?;
535 conn.execute(create_table, [])?;
536 conn.execute(insert_values, [])?;
537 let val = conn.query_row("SELECT * FROM test", [], |row| BigTuple::try_from(row))?;
538 assert_eq!(val.0, 0);
540 assert_eq!(val.1, 1);
541 assert_eq!(val.2, 2);
542 assert_eq!(val.3, 3);
543 assert_eq!(val.4, 4);
544 assert_eq!(val.5, 5);
545 assert_eq!(val.6, 6);
546 assert_eq!(val.7, 7);
547 assert_eq!(val.8, 8);
548 assert_eq!(val.9, 9);
549 assert_eq!(val.10, 10);
550 assert_eq!(val.11, 11);
551 assert_eq!(val.12, 12);
552 assert_eq!(val.13, 13);
553 assert_eq!(val.14, 14);
554 assert_eq!(val.15, 15);
555
556 Ok(())
558 }
559}