Remove 'static requirement on output of closure given to query_map and query_and_then.

The 'static bound was there to prevent callers from being able to save
off the `SqliteRow` handles passed into the closure. This PR changes the
closure to take `&SqliteRow`s instead, which provides the same feature
without restricting the output of the closure.
This commit is contained in:
John Gallagher 2015-12-01 10:55:01 -05:00
parent 86165725de
commit 635616842c
3 changed files with 15 additions and 13 deletions

View File

@ -1,3 +1,9 @@
# Version UPCOMDING (TBD)
* Slight change to the closure types passed to `query_map` and `query_and_then`:
* Remove the `'static` requirement on the closure's output type.
* Give the closure a `&SqliteRow` instead of a `SqliteRow`.
# Version 0.4.0 (2015-11-03) # Version 0.4.0 (2015-11-03)
* Adds `Sized` bound to `FromSql` trait as required by RFC 1214. * Adds `Sized` bound to `FromSql` trait as required by RFC 1214.

View File

@ -91,7 +91,7 @@ There are other, less obvious things that may result in a panic as well, such as
`collect()` on a `SqliteRows` and then trying to use the collected rows. `collect()` on a `SqliteRows` and then trying to use the collected rows.
Strongly consider using the method `query_map()` instead, if you can. Strongly consider using the method `query_map()` instead, if you can.
`query_map()` returns an iterator over rows-mapped-to-some-`'static`-type. This `query_map()` returns an iterator over rows-mapped-to-some-type. This
iterator does not have any of the above issues with panics due to attempting to iterator does not have any of the above issues with panics due to attempting to
access stale rows. access stale rows.

View File

@ -712,8 +712,7 @@ impl<'conn> SqliteStatement<'conn> {
/// for accessing stale rows. /// for accessing stale rows.
pub fn query_map<'a, T, F>(&'a mut self, params: &[&ToSql], f: F) pub fn query_map<'a, T, F>(&'a mut self, params: &[&ToSql], f: F)
-> SqliteResult<MappedRows<'a, F>> -> SqliteResult<MappedRows<'a, F>>
where T: 'static, where F: FnMut(&SqliteRow) -> T {
F: FnMut(SqliteRow) -> T {
let row_iter = try!(self.query(params)); let row_iter = try!(self.query(params));
Ok(MappedRows{ Ok(MappedRows{
@ -730,9 +729,8 @@ impl<'conn> SqliteStatement<'conn> {
/// for accessing stale rows. /// for accessing stale rows.
pub fn query_and_then<'a, T, E, F>(&'a mut self, params: &[&ToSql], f: F) pub fn query_and_then<'a, T, E, F>(&'a mut self, params: &[&ToSql], f: F)
-> SqliteResult<AndThenRows<'a, F>> -> SqliteResult<AndThenRows<'a, F>>
where T: 'static, where E: convert::From<SqliteError>,
E: convert::From<SqliteError>, F: FnMut(&SqliteRow) -> Result<T, E> {
F: FnMut(SqliteRow) -> Result<T, E> {
let row_iter = try!(self.query(params)); let row_iter = try!(self.query(params));
Ok(AndThenRows{ Ok(AndThenRows{
@ -804,12 +802,11 @@ pub struct MappedRows<'stmt, F> {
} }
impl<'stmt, T, F> Iterator for MappedRows<'stmt, F> impl<'stmt, T, F> Iterator for MappedRows<'stmt, F>
where T: 'static, where F: FnMut(&SqliteRow) -> T {
F: FnMut(SqliteRow) -> T {
type Item = SqliteResult<T>; type Item = SqliteResult<T>;
fn next(&mut self) -> Option<SqliteResult<T>> { fn next(&mut self) -> Option<SqliteResult<T>> {
self.rows.next().map(|row_result| row_result.map(|row| (self.map)(row))) self.rows.next().map(|row_result| row_result.map(|row| (self.map)(&row)))
} }
} }
@ -821,15 +818,14 @@ pub struct AndThenRows<'stmt, F> {
} }
impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F> impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F>
where T: 'static, where E: convert::From<SqliteError>,
E: convert::From<SqliteError>, F: FnMut(&SqliteRow) -> Result<T, E> {
F: FnMut(SqliteRow) -> Result<T, E> {
type Item = Result<T, E>; type Item = Result<T, E>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.rows.next().map(|row_result| row_result self.rows.next().map(|row_result| row_result
.map_err(E::from) .map_err(E::from)
.and_then(|row| (self.map)(row))) .and_then(|row| (self.map)(&row)))
} }
} }