rusqlite/
row.rs

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/// An handle for the resulting rows of a query.
9#[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) -> Result<()> {
18        if let Some(stmt) = self.stmt.take() {
19            stmt.reset()
20        } else {
21            Ok(())
22        }
23    }
24
25    /// Attempt to get the next row from the query. Returns `Ok(Some(Row))` if
26    /// there is another row, `Err(...)` if there was an error
27    /// getting the next row, and `Ok(None)` if all rows have been retrieved.
28    ///
29    /// ## Note
30    ///
31    /// This interface is not compatible with Rust's `Iterator` trait, because
32    /// the lifetime of the returned row is tied to the lifetime of `self`.
33    /// This is a fallible "streaming iterator". For a more natural interface,
34    /// consider using [`query_map`](Statement::query_map) or
35    /// [`query_and_then`](Statement::query_and_then) instead, which
36    /// return types that implement `Iterator`.
37    #[allow(clippy::should_implement_trait)] // cannot implement Iterator
38    #[inline]
39    pub fn next(&mut self) -> Result<Option<&Row<'stmt>>> {
40        self.advance()?;
41        Ok((*self).get())
42    }
43
44    /// Map over this `Rows`, converting it to a [`Map`], which
45    /// implements `FallibleIterator`.
46    /// ```rust,no_run
47    /// use fallible_iterator::FallibleIterator;
48    /// # use rusqlite::{Result, Statement};
49    /// fn query(stmt: &mut Statement) -> Result<Vec<i64>> {
50    ///     let rows = stmt.query([])?;
51    ///     rows.map(|r| r.get(0)).collect()
52    /// }
53    /// ```
54    // FIXME Hide FallibleStreamingIterator::map
55    #[inline]
56    pub fn map<F, B>(self, f: F) -> Map<'stmt, F>
57    where
58        F: FnMut(&Row<'_>) -> Result<B>,
59    {
60        Map { rows: self, f }
61    }
62
63    /// Map over this `Rows`, converting it to a [`MappedRows`], which
64    /// implements `Iterator`.
65    #[inline]
66    pub fn mapped<F, B>(self, f: F) -> MappedRows<'stmt, F>
67    where
68        F: FnMut(&Row<'_>) -> Result<B>,
69    {
70        MappedRows { rows: self, map: f }
71    }
72
73    /// Map over this `Rows` with a fallible function, converting it to a
74    /// [`AndThenRows`], which implements `Iterator` (instead of
75    /// `FallibleStreamingIterator`).
76    #[inline]
77    pub fn and_then<F, T, E>(self, f: F) -> AndThenRows<'stmt, F>
78    where
79        F: FnMut(&Row<'_>) -> Result<T, E>,
80    {
81        AndThenRows { rows: self, map: f }
82    }
83
84    /// Give access to the underlying statement
85    #[must_use]
86    pub fn as_ref(&self) -> Option<&Statement<'stmt>> {
87        self.stmt
88    }
89}
90
91impl<'stmt> Rows<'stmt> {
92    #[inline]
93    pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
94        Rows {
95            stmt: Some(stmt),
96            row: None,
97        }
98    }
99
100    #[inline]
101    pub(crate) fn get_expected_row(&mut self) -> Result<&Row<'stmt>> {
102        match self.next()? {
103            Some(row) => Ok(row),
104            None => Err(Error::QueryReturnedNoRows),
105        }
106    }
107}
108
109impl Drop for Rows<'_> {
110    #[allow(unused_must_use)]
111    #[inline]
112    fn drop(&mut self) {
113        self.reset();
114    }
115}
116
117/// `F` is used to transform the _streaming_ iterator into a _fallible_
118/// iterator.
119#[must_use = "iterators are lazy and do nothing unless consumed"]
120pub struct Map<'stmt, F> {
121    rows: Rows<'stmt>,
122    f: F,
123}
124
125impl<F, B> FallibleIterator for Map<'_, F>
126where
127    F: FnMut(&Row<'_>) -> Result<B>,
128{
129    type Error = Error;
130    type Item = B;
131
132    #[inline]
133    fn next(&mut self) -> Result<Option<B>> {
134        match self.rows.next()? {
135            Some(v) => Ok(Some((self.f)(v)?)),
136            None => Ok(None),
137        }
138    }
139}
140
141/// An iterator over the mapped resulting rows of a query.
142///
143/// `F` is used to transform the _streaming_ iterator into a _standard_
144/// iterator.
145#[must_use = "iterators are lazy and do nothing unless consumed"]
146pub struct MappedRows<'stmt, F> {
147    rows: Rows<'stmt>,
148    map: F,
149}
150
151impl<T, F> Iterator for MappedRows<'_, F>
152where
153    F: FnMut(&Row<'_>) -> Result<T>,
154{
155    type Item = Result<T>;
156
157    #[inline]
158    fn next(&mut self) -> Option<Result<T>> {
159        let map = &mut self.map;
160        self.rows
161            .next()
162            .transpose()
163            .map(|row_result| row_result.and_then(map))
164    }
165}
166
167/// An iterator over the mapped resulting rows of a query, with an Error type
168/// unifying with Error.
169#[must_use = "iterators are lazy and do nothing unless consumed"]
170pub struct AndThenRows<'stmt, F> {
171    rows: Rows<'stmt>,
172    map: F,
173}
174
175impl<T, E, F> Iterator for AndThenRows<'_, F>
176where
177    E: From<Error>,
178    F: FnMut(&Row<'_>) -> Result<T, E>,
179{
180    type Item = Result<T, E>;
181
182    #[inline]
183    fn next(&mut self) -> Option<Self::Item> {
184        let map = &mut self.map;
185        self.rows
186            .next()
187            .transpose()
188            .map(|row_result| row_result.map_err(E::from).and_then(map))
189    }
190}
191
192/// `FallibleStreamingIterator` differs from the standard library's `Iterator`
193/// in two ways:
194/// * each call to `next` (`sqlite3_step`) can fail.
195/// * returned `Row` is valid until `next` is called again or `Statement` is
196///   reset or finalized.
197///
198/// While these iterators cannot be used with Rust `for` loops, `while let`
199/// loops offer a similar level of ergonomics:
200/// ```rust,no_run
201/// # use rusqlite::{Result, Statement};
202/// fn query(stmt: &mut Statement) -> Result<()> {
203///     let mut rows = stmt.query([])?;
204///     while let Some(row) = rows.next()? {
205///         // scan columns value
206///     }
207///     Ok(())
208/// }
209/// ```
210impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
211    type Error = Error;
212    type Item = Row<'stmt>;
213
214    #[inline]
215    fn advance(&mut self) -> Result<()> {
216        if let Some(stmt) = self.stmt {
217            match stmt.step() {
218                Ok(true) => {
219                    self.row = Some(Row { stmt });
220                    Ok(())
221                }
222                Ok(false) => {
223                    let r = self.reset();
224                    self.row = None;
225                    r
226                }
227                Err(e) => {
228                    let _ = self.reset(); // prevents infinite loop on error
229                    self.row = None;
230                    Err(e)
231                }
232            }
233        } else {
234            self.row = None;
235            Ok(())
236        }
237    }
238
239    #[inline]
240    fn get(&self) -> Option<&Row<'stmt>> {
241        self.row.as_ref()
242    }
243}
244
245/// A single result row of a query.
246pub struct Row<'stmt> {
247    pub(crate) stmt: &'stmt Statement<'stmt>,
248}
249
250impl<'stmt> Row<'stmt> {
251    /// Get the value of a particular column of the result row.
252    ///
253    /// # Panics
254    ///
255    /// Panics if calling [`row.get(idx)`](Row::get) would return an error,
256    /// including:
257    ///
258    /// * If the underlying SQLite column type is not a valid type as a source
259    ///   for `T`
260    /// * If the underlying SQLite integral value is outside the range
261    ///   representable by `T`
262    /// * If `idx` is outside the range of columns in the returned query
263    #[track_caller]
264    pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
265        self.get(idx).unwrap()
266    }
267
268    /// Get the value of a particular column of the result row.
269    ///
270    /// ## Failure
271    ///
272    /// Returns an `Error::InvalidColumnType` if the underlying SQLite column
273    /// type is not a valid type as a source for `T`.
274    ///
275    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
276    /// column range for this row.
277    ///
278    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
279    /// name for this row.
280    ///
281    /// If the result type is i128 (which requires the `i128_blob` feature to be
282    /// enabled), and the underlying SQLite column is a blob whose size is not
283    /// 16 bytes, `Error::InvalidColumnType` will also be returned.
284    #[track_caller]
285    pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
286        let idx = idx.idx(self.stmt)?;
287        let value = self.stmt.value_ref(idx);
288        FromSql::column_result(value).map_err(|err| match err {
289            FromSqlError::InvalidType => Error::InvalidColumnType(
290                idx,
291                self.stmt.column_name_unwrap(idx).into(),
292                value.data_type(),
293            ),
294            FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
295            FromSqlError::Other(err) => {
296                Error::FromSqlConversionFailure(idx, value.data_type(), err)
297            }
298            FromSqlError::InvalidBlobSize { .. } => {
299                Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err))
300            }
301        })
302    }
303
304    /// Get the value of a particular column of the result row as a `ValueRef`,
305    /// allowing data to be read out of a row without copying.
306    ///
307    /// This `ValueRef` is valid only as long as this Row, which is enforced by
308    /// it's lifetime. This means that while this method is completely safe,
309    /// it can be somewhat difficult to use, and most callers will be better
310    /// served by [`get`](Row::get) or [`get_unwrap`](Row::get_unwrap).
311    ///
312    /// ## Failure
313    ///
314    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
315    /// column range for this row.
316    ///
317    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
318    /// name for this row.
319    pub fn get_ref<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
320        let idx = idx.idx(self.stmt)?;
321        // Narrowing from `ValueRef<'stmt>` (which `self.stmt.value_ref(idx)`
322        // returns) to `ValueRef<'a>` is needed because it's only valid until
323        // the next call to sqlite3_step.
324        let val_ref = self.stmt.value_ref(idx);
325        Ok(val_ref)
326    }
327
328    /// Get the value of a particular column of the result row as a `ValueRef`,
329    /// allowing data to be read out of a row without copying.
330    ///
331    /// This `ValueRef` is valid only as long as this Row, which is enforced by
332    /// it's lifetime. This means that while this method is completely safe,
333    /// it can be difficult to use, and most callers will be better served by
334    /// [`get`](Row::get) or [`get_unwrap`](Row::get_unwrap).
335    ///
336    /// # Panics
337    ///
338    /// Panics if calling [`row.get_ref(idx)`](Row::get_ref) would return an
339    /// error, including:
340    ///
341    /// * If `idx` is outside the range of columns in the returned query.
342    /// * If `idx` is not a valid column name for this row.
343    #[track_caller]
344    pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
345        self.get_ref(idx).unwrap()
346    }
347}
348
349impl<'stmt> AsRef<Statement<'stmt>> for Row<'stmt> {
350    fn as_ref(&self) -> &Statement<'stmt> {
351        self.stmt
352    }
353}
354
355/// Debug `Row` like an ordered `Map<Result<&str>, Result<(Type, ValueRef)>>`
356/// with column name as key except that for `Type::Blob` only its size is
357/// printed (not its content).
358impl<'stmt> std::fmt::Debug for Row<'stmt> {
359    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360        let mut dm = f.debug_map();
361        for c in 0..self.stmt.column_count() {
362            let name = self.stmt.column_name(c);
363            dm.key(&name);
364            let value = self.get_ref(c);
365            match value {
366                Ok(value) => {
367                    let dt = value.data_type();
368                    match value {
369                        ValueRef::Null => {
370                            dm.value(&(dt, ()));
371                        }
372                        ValueRef::Integer(i) => {
373                            dm.value(&(dt, i));
374                        }
375                        ValueRef::Real(f) => {
376                            dm.value(&(dt, f));
377                        }
378                        ValueRef::Text(s) => {
379                            dm.value(&(dt, String::from_utf8_lossy(s)));
380                        }
381                        ValueRef::Blob(b) => {
382                            dm.value(&(dt, b.len()));
383                        }
384                    }
385                }
386                Err(ref _err) => {
387                    dm.value(&value);
388                }
389            }
390        }
391        dm.finish()
392    }
393}
394
395mod sealed {
396    /// This trait exists just to ensure that the only impls of `trait Params`
397    /// that are allowed are ones in this crate.
398    pub trait Sealed {}
399    impl Sealed for usize {}
400    impl Sealed for &str {}
401}
402
403/// A trait implemented by types that can index into columns of a row.
404///
405/// It is only implemented for `usize` and `&str`.
406pub trait RowIndex: sealed::Sealed {
407    /// Returns the index of the appropriate column, or `None` if no such
408    /// column exists.
409    fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
410}
411
412impl RowIndex for usize {
413    #[inline]
414    fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
415        if *self >= stmt.column_count() {
416            Err(Error::InvalidColumnIndex(*self))
417        } else {
418            Ok(*self)
419        }
420    }
421}
422
423impl RowIndex for &'_ str {
424    #[inline]
425    fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
426        stmt.column_index(self)
427    }
428}
429
430macro_rules! tuple_try_from_row {
431    ($($field:ident),*) => {
432        impl<'a, $($field,)*> convert::TryFrom<&'a Row<'a>> for ($($field,)*) where $($field: FromSql,)* {
433            type Error = crate::Error;
434
435            // we end with index += 1, which rustc warns about
436            // unused_variables and unused_mut are allowed for ()
437            #[allow(unused_assignments, unused_variables, unused_mut)]
438            fn try_from(row: &'a Row<'a>) -> Result<Self> {
439                let mut index = 0;
440                $(
441                    #[allow(non_snake_case)]
442                    let $field = row.get::<_, $field>(index)?;
443                    index += 1;
444                )*
445                Ok(($($field,)*))
446            }
447        }
448    }
449}
450
451macro_rules! tuples_try_from_row {
452    () => {
453        // not very useful, but maybe some other macro users will find this helpful
454        tuple_try_from_row!();
455    };
456    ($first:ident $(, $remaining:ident)*) => {
457        tuple_try_from_row!($first $(, $remaining)*);
458        tuples_try_from_row!($($remaining),*);
459    };
460}
461
462tuples_try_from_row!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
463
464#[cfg(test)]
465mod tests {
466    #![allow(clippy::redundant_closure)] // false positives due to lifetime issues; clippy issue #5594
467    use crate::{Connection, Result};
468
469    #[test]
470    fn test_try_from_row_for_tuple_1() -> Result<()> {
471        use crate::ToSql;
472        use std::convert::TryFrom;
473
474        let conn = Connection::open_in_memory()?;
475        conn.execute(
476            "CREATE TABLE test (a INTEGER)",
477            crate::params_from_iter(std::iter::empty::<&dyn ToSql>()),
478        )?;
479        conn.execute("INSERT INTO test VALUES (42)", [])?;
480        let val = conn.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))?;
481        assert_eq!(val, (42,));
482        let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row));
483        fail.unwrap_err();
484        Ok(())
485    }
486
487    #[test]
488    fn test_try_from_row_for_tuple_2() -> Result<()> {
489        use std::convert::TryFrom;
490
491        let conn = Connection::open_in_memory()?;
492        conn.execute("CREATE TABLE test (a INTEGER, b INTEGER)", [])?;
493        conn.execute("INSERT INTO test VALUES (42, 47)", [])?;
494        let val = conn.query_row("SELECT a, b FROM test", [], |row| {
495            <(u32, u32)>::try_from(row)
496        })?;
497        assert_eq!(val, (42, 47));
498        let fail = conn.query_row("SELECT a, b FROM test", [], |row| {
499            <(u32, u32, u32)>::try_from(row)
500        });
501        fail.unwrap_err();
502        Ok(())
503    }
504
505    #[test]
506    fn test_try_from_row_for_tuple_16() -> Result<()> {
507        use std::convert::TryFrom;
508
509        let create_table = "CREATE TABLE test (
510            a INTEGER,
511            b INTEGER,
512            c INTEGER,
513            d INTEGER,
514            e INTEGER,
515            f INTEGER,
516            g INTEGER,
517            h INTEGER,
518            i INTEGER,
519            j INTEGER,
520            k INTEGER,
521            l INTEGER,
522            m INTEGER,
523            n INTEGER,
524            o INTEGER,
525            p INTEGER
526        )";
527
528        let insert_values = "INSERT INTO test VALUES (
529            0,
530            1,
531            2,
532            3,
533            4,
534            5,
535            6,
536            7,
537            8,
538            9,
539            10,
540            11,
541            12,
542            13,
543            14,
544            15
545        )";
546
547        type BigTuple = (
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            u32,
562            u32,
563            u32,
564        );
565
566        let conn = Connection::open_in_memory()?;
567        conn.execute(create_table, [])?;
568        conn.execute(insert_values, [])?;
569        let val = conn.query_row("SELECT * FROM test", [], |row| BigTuple::try_from(row))?;
570        // Debug is not implemented for tuples of 16
571        assert_eq!(val.0, 0);
572        assert_eq!(val.1, 1);
573        assert_eq!(val.2, 2);
574        assert_eq!(val.3, 3);
575        assert_eq!(val.4, 4);
576        assert_eq!(val.5, 5);
577        assert_eq!(val.6, 6);
578        assert_eq!(val.7, 7);
579        assert_eq!(val.8, 8);
580        assert_eq!(val.9, 9);
581        assert_eq!(val.10, 10);
582        assert_eq!(val.11, 11);
583        assert_eq!(val.12, 12);
584        assert_eq!(val.13, 13);
585        assert_eq!(val.14, 14);
586        assert_eq!(val.15, 15);
587
588        // We don't test one bigger because it's unimplemented
589        Ok(())
590    }
591
592    #[test]
593    #[cfg(feature = "bundled")]
594    fn pathological_case() -> Result<()> {
595        let conn = Connection::open_in_memory()?;
596        conn.execute_batch(
597            "CREATE TABLE foo(x);
598        CREATE TRIGGER oops BEFORE INSERT ON foo BEGIN SELECT RAISE(FAIL, 'Boom'); END;",
599        )?;
600        let mut stmt = conn.prepare("INSERT INTO foo VALUES (0) RETURNING rowid;")?;
601        {
602            let iterator_count = stmt.query_map([], |_| Ok(()))?.count();
603            assert_eq!(1, iterator_count); // should be 0
604            use fallible_streaming_iterator::FallibleStreamingIterator;
605            let fallible_iterator_count = stmt.query([])?.count().unwrap_or(0);
606            assert_eq!(0, fallible_iterator_count);
607        }
608        {
609            let iterator_last = stmt.query_map([], |_| Ok(()))?.last();
610            assert!(iterator_last.is_some()); // should be none
611            use fallible_iterator::FallibleIterator;
612            let fallible_iterator_last = stmt.query([])?.map(|_| Ok(())).last();
613            assert!(fallible_iterator_last.is_err());
614        }
615        Ok(())
616    }
617}