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