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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
use std::{convert, result};
use std::marker::PhantomData;

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

/// 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`.
    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: stmt,
                    phantom: PhantomData,
                }))
            }
            Ok(false) => {
                self.reset();
                None
            }
            Err(err) => {
                self.reset();
                Some(Err(err))
            }
        })
    }
}

// TODO: This trait lets us have "pub(crate)" visibility on some methods. Remove this
// once pub(crate) is stable.
pub trait RowsCrateImpl<'stmt> {
    fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt>;
    fn get_expected_row<'a>(&'a mut self) -> Result<Row<'a, 'stmt>>;
}

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

    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,
}

// TODO: This trait lets us have "pub(crate)" visibility on some methods. Remove this
// once pub(crate) is stable.
pub trait MappedRowsCrateImpl<'stmt, T, F> {
    fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F>;
}

impl<'stmt, T, F> MappedRowsCrateImpl<'stmt, T, F> for MappedRows<'stmt, F>
    where F: FnMut(&Row) -> T
{
    fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F> {
        MappedRows {
            rows: 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,
}

// TODO: This trait lets us have "pub(crate)" visibility on some methods. Remove this
// once pub(crate) is stable.
pub trait AndThenRowsCrateImpl<'stmt, T, E, F> {
    fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F>;
}

impl<'stmt, T, E, F> AndThenRowsCrateImpl<'stmt, T, E, F> for AndThenRows<'stmt, F>
    where F: FnMut(&Row) -> result::Result<T, E>
{
    fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F> {
        AndThenRows {
            rows: 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) -> i32 {
        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<i32>;
}

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

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