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) {
18        if let Some(stmt) = self.stmt.take() {
19            stmt.reset();
20        }
21    }
22
23    /// Attempt to get the next row from the query. Returns `Ok(Some(Row))` if
24    /// there is another row, `Err(...)` if there was an error
25    /// getting the next row, and `Ok(None)` if all rows have been retrieved.
26    ///
27    /// ## Note
28    ///
29    /// This interface is not compatible with Rust's `Iterator` trait, because
30    /// the lifetime of the returned row is tied to the lifetime of `self`.
31    /// This is a fallible "streaming iterator". For a more natural interface,
32    /// consider using [`query_map`](crate::Statement::query_map) or
33    /// [`query_and_then`](crate::Statement::query_and_then) instead, which
34    /// return types that implement `Iterator`.
35    #[allow(clippy::should_implement_trait)] // cannot implement Iterator
36    #[inline]
37    pub fn next(&mut self) -> Result<Option<&Row<'stmt>>> {
38        self.advance()?;
39        Ok((*self).get())
40    }
41
42    /// Map over this `Rows`, converting it to a [`Map`], which
43    /// implements `FallibleIterator`.
44    /// ```rust,no_run
45    /// use fallible_iterator::FallibleIterator;
46    /// # use rusqlite::{Result, Statement};
47    /// fn query(stmt: &mut Statement) -> Result<Vec<i64>> {
48    ///     let rows = stmt.query([])?;
49    ///     rows.map(|r| r.get(0)).collect()
50    /// }
51    /// ```
52    // FIXME Hide FallibleStreamingIterator::map
53    #[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    /// Map over this `Rows`, converting it to a [`MappedRows`], which
62    /// implements `Iterator`.
63    #[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    /// Map over this `Rows` with a fallible function, converting it to a
72    /// [`AndThenRows`], which implements `Iterator` (instead of
73    /// `FallibleStreamingIterator`).
74    #[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    /// Give access to the underlying statement
83    #[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/// `F` is used to transform the _streaming_ iterator into a _fallible_
115/// iterator.
116#[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/// An iterator over the mapped resulting rows of a query.
139///
140/// `F` is used to transform the _streaming_ iterator into a _standard_
141/// iterator.
142#[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/// An iterator over the mapped resulting rows of a query, with an Error type
165/// unifying with Error.
166#[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
189/// `FallibleStreamingIterator` differs from the standard library's `Iterator`
190/// in two ways:
191/// * each call to `next` (`sqlite3_step`) can fail.
192/// * returned `Row` is valid until `next` is called again or `Statement` is
193///   reset or finalized.
194///
195/// While these iterators cannot be used with Rust `for` loops, `while let`
196/// loops offer a similar level of ergonomics:
197/// ```rust,no_run
198/// # use rusqlite::{Result, Statement};
199/// fn query(stmt: &mut Statement) -> Result<()> {
200///     let mut rows = stmt.query([])?;
201///     while let Some(row) = rows.next()? {
202///         // scan columns value
203///     }
204///     Ok(())
205/// }
206/// ```
207impl<'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
242/// A single result row of a query.
243pub struct Row<'stmt> {
244    pub(crate) stmt: &'stmt Statement<'stmt>,
245}
246
247impl<'stmt> Row<'stmt> {
248    /// Get the value of a particular column of the result row.
249    ///
250    /// ## Failure
251    ///
252    /// Panics if calling [`row.get(idx)`](Row::get) would return an error,
253    /// including:
254    ///
255    /// * If the underlying SQLite column type is not a valid type as a source
256    ///   for `T`
257    /// * If the underlying SQLite integral value is outside the range
258    ///   representable by `T`
259    /// * If `idx` is outside the range of columns in the returned query
260    pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
261        self.get(idx).unwrap()
262    }
263
264    /// Get the value of a particular column of the result row.
265    ///
266    /// ## Failure
267    ///
268    /// Returns an `Error::InvalidColumnType` if the underlying SQLite column
269    /// type is not a valid type as a source for `T`.
270    ///
271    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
272    /// column range for this row.
273    ///
274    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
275    /// name for this row.
276    ///
277    /// If the result type is i128 (which requires the `i128_blob` feature to be
278    /// enabled), and the underlying SQLite column is a blob whose size is not
279    /// 16 bytes, `Error::InvalidColumnType` will also be returned.
280    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    /// Get the value of a particular column of the result row as a `ValueRef`,
300    /// allowing data to be read out of a row without copying.
301    ///
302    /// This `ValueRef` is valid only as long as this Row, which is enforced by
303    /// it's lifetime. This means that while this method is completely safe,
304    /// it can be somewhat difficult to use, and most callers will be better
305    /// served by [`get`](Row::get) or [`get_unwrap`](Row::get_unwrap).
306    ///
307    /// ## Failure
308    ///
309    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
310    /// column range for this row.
311    ///
312    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
313    /// name for this row.
314    pub fn get_ref<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
315        let idx = idx.idx(self.stmt)?;
316        // Narrowing from `ValueRef<'stmt>` (which `self.stmt.value_ref(idx)`
317        // returns) to `ValueRef<'a>` is needed because it's only valid until
318        // the next call to sqlite3_step.
319        let val_ref = self.stmt.value_ref(idx);
320        Ok(val_ref)
321    }
322
323    /// Get the value of a particular column of the result row as a `ValueRef`,
324    /// allowing data to be read out of a row without copying.
325    ///
326    /// This `ValueRef` is valid only as long as this Row, which is enforced by
327    /// it's lifetime. This means that while this method is completely safe,
328    /// it can be difficult to use, and most callers will be better served by
329    /// [`get`](Row::get) or [`get_unwrap`](Row::get_unwrap).
330    ///
331    /// ## Failure
332    ///
333    /// Panics if calling [`row.get_ref(idx)`](Row::get_ref) would return an
334    /// error, including:
335    ///
336    /// * If `idx` is outside the range of columns in the returned query.
337    /// * If `idx` is not a valid column name for this row.
338    pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
339        self.get_ref(idx).unwrap()
340    }
341
342    /// Renamed to [`get_ref`](Row::get_ref).
343    #[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    /// Renamed to [`get_ref_unwrap`](Row::get_ref_unwrap).
350    #[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    /// This trait exists just to ensure that the only impls of `trait Params`
365    /// that are allowed are ones in this crate.
366    pub trait Sealed {}
367    impl Sealed for usize {}
368    impl Sealed for &str {}
369}
370
371/// A trait implemented by types that can index into columns of a row.
372///
373/// It is only implemented for `usize` and `&str`.
374pub trait RowIndex: sealed::Sealed {
375    /// Returns the index of the appropriate column, or `None` if no such
376    /// column exists.
377    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            // we end with index += 1, which rustc warns about
404            // unused_variables and unused_mut are allowed for ()
405            #[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        // not very useful, but maybe some other macro users will find this helpful
422        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)] // false positives due to lifetime issues; clippy issue #5594
435    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        // Debug is not implemented for tuples of 16
539        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        // We don't test one bigger because it's unimplemented
557        Ok(())
558    }
559}