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 #[track_caller]
261 pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
262 self.get(idx).unwrap()
263 }
264
265 #[track_caller]
282 pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
283 let idx = idx.idx(self.stmt)?;
284 let value = self.stmt.value_ref(idx);
285 FromSql::column_result(value).map_err(|err| match err {
286 FromSqlError::InvalidType => Error::InvalidColumnType(
287 idx,
288 self.stmt.column_name_unwrap(idx).into(),
289 value.data_type(),
290 ),
291 FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
292 FromSqlError::Other(err) => {
293 Error::FromSqlConversionFailure(idx, value.data_type(), err)
294 }
295 FromSqlError::InvalidBlobSize { .. } => {
296 Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err))
297 }
298 })
299 }
300
301 pub fn get_ref<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
317 let idx = idx.idx(self.stmt)?;
318 let val_ref = self.stmt.value_ref(idx);
322 Ok(val_ref)
323 }
324
325 #[track_caller]
341 pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
342 self.get_ref(idx).unwrap()
343 }
344}
345
346impl<'stmt> AsRef<Statement<'stmt>> for Row<'stmt> {
347 fn as_ref(&self) -> &Statement<'stmt> {
348 self.stmt
349 }
350}
351
352impl<'stmt> std::fmt::Debug for Row<'stmt> {
356 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
357 let mut dm = f.debug_map();
358 for c in 0..self.stmt.column_count() {
359 let name = self.stmt.column_name(c);
360 dm.key(&name);
361 let value = self.get_ref(c);
362 match value {
363 Ok(value) => {
364 let dt = value.data_type();
365 match value {
366 ValueRef::Null => {
367 dm.value(&(dt, ()));
368 }
369 ValueRef::Integer(i) => {
370 dm.value(&(dt, i));
371 }
372 ValueRef::Real(f) => {
373 dm.value(&(dt, f));
374 }
375 ValueRef::Text(s) => {
376 dm.value(&(dt, String::from_utf8_lossy(s)));
377 }
378 ValueRef::Blob(b) => {
379 dm.value(&(dt, b.len()));
380 }
381 }
382 }
383 Err(ref _err) => {
384 dm.value(&value);
385 }
386 }
387 }
388 dm.finish()
389 }
390}
391
392mod sealed {
393 pub trait Sealed {}
396 impl Sealed for usize {}
397 impl Sealed for &str {}
398}
399
400pub trait RowIndex: sealed::Sealed {
404 fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
407}
408
409impl RowIndex for usize {
410 #[inline]
411 fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
412 if *self >= stmt.column_count() {
413 Err(Error::InvalidColumnIndex(*self))
414 } else {
415 Ok(*self)
416 }
417 }
418}
419
420impl RowIndex for &'_ str {
421 #[inline]
422 fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
423 stmt.column_index(self)
424 }
425}
426
427macro_rules! tuple_try_from_row {
428 ($($field:ident),*) => {
429 impl<'a, $($field,)*> convert::TryFrom<&'a Row<'a>> for ($($field,)*) where $($field: FromSql,)* {
430 type Error = crate::Error;
431
432 #[allow(unused_assignments, unused_variables, unused_mut)]
435 fn try_from(row: &'a Row<'a>) -> Result<Self> {
436 let mut index = 0;
437 $(
438 #[allow(non_snake_case)]
439 let $field = row.get::<_, $field>(index)?;
440 index += 1;
441 )*
442 Ok(($($field,)*))
443 }
444 }
445 }
446}
447
448macro_rules! tuples_try_from_row {
449 () => {
450 tuple_try_from_row!();
452 };
453 ($first:ident $(, $remaining:ident)*) => {
454 tuple_try_from_row!($first $(, $remaining)*);
455 tuples_try_from_row!($($remaining),*);
456 };
457}
458
459tuples_try_from_row!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
460
461#[cfg(test)]
462mod tests {
463 #![allow(clippy::redundant_closure)] use crate::{Connection, Result};
465
466 #[test]
467 fn test_try_from_row_for_tuple_1() -> Result<()> {
468 use crate::ToSql;
469 use std::convert::TryFrom;
470
471 let conn = Connection::open_in_memory()?;
472 conn.execute(
473 "CREATE TABLE test (a INTEGER)",
474 crate::params_from_iter(std::iter::empty::<&dyn ToSql>()),
475 )?;
476 conn.execute("INSERT INTO test VALUES (42)", [])?;
477 let val = conn.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))?;
478 assert_eq!(val, (42,));
479 let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row));
480 fail.unwrap_err();
481 Ok(())
482 }
483
484 #[test]
485 fn test_try_from_row_for_tuple_2() -> Result<()> {
486 use std::convert::TryFrom;
487
488 let conn = Connection::open_in_memory()?;
489 conn.execute("CREATE TABLE test (a INTEGER, b INTEGER)", [])?;
490 conn.execute("INSERT INTO test VALUES (42, 47)", [])?;
491 let val = conn.query_row("SELECT a, b FROM test", [], |row| {
492 <(u32, u32)>::try_from(row)
493 })?;
494 assert_eq!(val, (42, 47));
495 let fail = conn.query_row("SELECT a, b FROM test", [], |row| {
496 <(u32, u32, u32)>::try_from(row)
497 });
498 fail.unwrap_err();
499 Ok(())
500 }
501
502 #[test]
503 fn test_try_from_row_for_tuple_16() -> Result<()> {
504 use std::convert::TryFrom;
505
506 let create_table = "CREATE TABLE test (
507 a INTEGER,
508 b INTEGER,
509 c INTEGER,
510 d INTEGER,
511 e INTEGER,
512 f INTEGER,
513 g INTEGER,
514 h INTEGER,
515 i INTEGER,
516 j INTEGER,
517 k INTEGER,
518 l INTEGER,
519 m INTEGER,
520 n INTEGER,
521 o INTEGER,
522 p INTEGER
523 )";
524
525 let insert_values = "INSERT INTO test VALUES (
526 0,
527 1,
528 2,
529 3,
530 4,
531 5,
532 6,
533 7,
534 8,
535 9,
536 10,
537 11,
538 12,
539 13,
540 14,
541 15
542 )";
543
544 type BigTuple = (
545 u32,
546 u32,
547 u32,
548 u32,
549 u32,
550 u32,
551 u32,
552 u32,
553 u32,
554 u32,
555 u32,
556 u32,
557 u32,
558 u32,
559 u32,
560 u32,
561 );
562
563 let conn = Connection::open_in_memory()?;
564 conn.execute(create_table, [])?;
565 conn.execute(insert_values, [])?;
566 let val = conn.query_row("SELECT * FROM test", [], |row| BigTuple::try_from(row))?;
567 assert_eq!(val.0, 0);
569 assert_eq!(val.1, 1);
570 assert_eq!(val.2, 2);
571 assert_eq!(val.3, 3);
572 assert_eq!(val.4, 4);
573 assert_eq!(val.5, 5);
574 assert_eq!(val.6, 6);
575 assert_eq!(val.7, 7);
576 assert_eq!(val.8, 8);
577 assert_eq!(val.9, 9);
578 assert_eq!(val.10, 10);
579 assert_eq!(val.11, 11);
580 assert_eq!(val.12, 12);
581 assert_eq!(val.13, 13);
582 assert_eq!(val.14, 14);
583 assert_eq!(val.15, 15);
584
585 Ok(())
587 }
588}