1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
use std::marker::PhantomData;
use std::{convert, result};

use super::{Error, Result, Statement};
use types::{FromSql, FromSqlError};

/// An handle for the resulting rows of a query.
pub struct Rows<'stmt> {
    stmt: Option<&'stmt Statement<'stmt>>,
}

impl<'stmt> Rows<'stmt> {
    fn reset(&mut self) {
        if let Some(stmt) = self.stmt.take() {
            stmt.reset();
        }
    }

    /// Attempt to get the next row from the query. Returns `Some(Ok(Row))` if
    /// there is another row, `Some(Err(...))` if there was an error
    /// getting the next row, and `None` if all rows have been retrieved.
    ///
    /// ## Note
    ///
    /// This interface is not compatible with Rust's `Iterator` trait, because
    /// the lifetime of the returned row is tied to the lifetime of `self`.
    /// This is a "streaming iterator". For a more natural interface,
    /// consider using `query_map` or `query_and_then` instead, which
    /// return types that implement `Iterator`.
    #[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))] // cannot implement Iterator
    pub fn next<'a>(&'a mut self) -> Option<Result<Row<'a, 'stmt>>> {
        self.stmt.and_then(|stmt| match stmt.step() {
            Ok(true) => Some(Ok(Row {
                stmt,
                phantom: PhantomData,
            })),
            Ok(false) => {
                self.reset();
                None
            }
            Err(err) => {
                self.reset();
                Some(Err(err))
            }
        })
    }
}

impl<'stmt> Rows<'stmt> {
    pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
        Rows { stmt: Some(stmt) }
    }

    pub(crate) fn get_expected_row<'a>(&'a mut self) -> Result<Row<'a, 'stmt>> {
        match self.next() {
            Some(row) => row,
            None => Err(Error::QueryReturnedNoRows),
        }
    }
}

impl<'stmt> Drop for Rows<'stmt> {
    fn drop(&mut self) {
        self.reset();
    }
}

/// An iterator over the mapped resulting rows of a query.
pub struct MappedRows<'stmt, F> {
    rows: Rows<'stmt>,
    map: F,
}

impl<'stmt, T, F> MappedRows<'stmt, F>
where
    F: FnMut(&Row) -> T,
{
    pub(crate) fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F> {
        MappedRows { rows, map: f }
    }
}

impl<'conn, T, F> Iterator for MappedRows<'conn, F>
where
    F: FnMut(&Row) -> T,
{
    type Item = Result<T>;

    fn next(&mut self) -> Option<Result<T>> {
        let map = &mut self.map;
        self.rows
            .next()
            .map(|row_result| row_result.map(|row| (map)(&row)))
    }
}

/// An iterator over the mapped resulting rows of a query, with an Error type
/// unifying with Error.
pub struct AndThenRows<'stmt, F> {
    rows: Rows<'stmt>,
    map: F,
}

impl<'stmt, T, E, F> AndThenRows<'stmt, F>
where
    F: FnMut(&Row) -> result::Result<T, E>,
{
    pub(crate) fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F> {
        AndThenRows { rows, map: f }
    }
}

impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F>
where
    E: convert::From<Error>,
    F: FnMut(&Row) -> result::Result<T, E>,
{
    type Item = result::Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        let map = &mut self.map;
        self.rows
            .next()
            .map(|row_result| row_result.map_err(E::from).and_then(|row| (map)(&row)))
    }
}

/// A single result row of a query.
pub struct Row<'a, 'stmt> {
    stmt: &'stmt Statement<'stmt>,
    phantom: PhantomData<&'a ()>,
}

impl<'a, 'stmt> Row<'a, 'stmt> {
    /// Get the value of a particular column of the result row.
    ///
    /// ## Failure
    ///
    /// Panics if calling `row.get_checked(idx)` would return an error,
    /// including:
    ///
    ///    * If the underlying SQLite column type is not a valid type as a
    ///      source for `T`
    ///    * If the underlying SQLite integral value is
    ///      outside the range representable by `T`
    ///    * If `idx` is outside the range of columns in the
    ///      returned query
    pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
        self.get_checked(idx).unwrap()
    }

    /// Get the value of a particular column of the result row.
    ///
    /// ## Failure
    ///
    /// Returns an `Error::InvalidColumnType` if the underlying SQLite column
    /// type is not a valid type as a source for `T`.
    ///
    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
    /// column range for this row.
    ///
    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
    /// name for this row.
    pub fn get_checked<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
        let idx = try!(idx.idx(self.stmt));
        let value = self.stmt.value_ref(idx);
        FromSql::column_result(value).map_err(|err| match err {
            FromSqlError::InvalidType => Error::InvalidColumnType(idx, value.data_type()),
            FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
            FromSqlError::Other(err) => {
                Error::FromSqlConversionFailure(idx as usize, value.data_type(), err)
            }
        })
    }

    /// Return the number of columns in the current row.
    pub fn column_count(&self) -> usize {
        self.stmt.column_count()
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement) -> Result<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Result<usize> {
        if *self >= stmt.column_count() {
            Err(Error::InvalidColumnIndex(*self))
        } else {
            Ok(*self)
        }
    }
}

impl<'a> RowIndex for &'a str {
    #[inline]
    fn idx(&self, stmt: &Statement) -> Result<usize> {
        stmt.column_index(*self)
    }
}