Call sqlite3_reset on a statement ASAP inside Rows's Iterator impl.

This commit is contained in:
John Gallagher 2016-05-16 14:39:14 -05:00
parent 8e1ce5cf9c
commit 1262d3bb17

View File

@ -1002,17 +1002,15 @@ pub type SqliteRows<'stmt> = Rows<'stmt>;
/// `min`/`max` (which could return a stale row unless the last row happened to be the min or max, /// `min`/`max` (which could return a stale row unless the last row happened to be the min or max,
/// respectively). /// respectively).
pub struct Rows<'stmt> { pub struct Rows<'stmt> {
stmt: &'stmt Statement<'stmt>, stmt: Option<&'stmt Statement<'stmt>>,
current_row: Rc<Cell<c_int>>, current_row: Rc<Cell<c_int>>,
done: bool,
} }
impl<'stmt> Rows<'stmt> { impl<'stmt> Rows<'stmt> {
fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> { fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
Rows { Rows {
stmt: stmt, stmt: Some(stmt),
current_row: Rc::new(Cell::new(0)), current_row: Rc::new(Cell::new(0)),
done: false,
} }
} }
@ -1022,42 +1020,47 @@ impl<'stmt> Rows<'stmt> {
None => Err(Error::QueryReturnedNoRows), None => Err(Error::QueryReturnedNoRows),
} }
} }
fn reset(&mut self) {
if let Some(stmt) = self.stmt.take() {
unsafe {
ffi::sqlite3_reset(stmt.stmt);
}
}
}
} }
impl<'stmt> Iterator for Rows<'stmt> { impl<'stmt> Iterator for Rows<'stmt> {
type Item = Result<Row<'stmt>>; type Item = Result<Row<'stmt>>;
fn next(&mut self) -> Option<Result<Row<'stmt>>> { fn next(&mut self) -> Option<Result<Row<'stmt>>> {
if self.done { self.stmt.and_then(|stmt| {
return None; match unsafe { ffi::sqlite3_step(stmt.stmt) } {
}
match unsafe { ffi::sqlite3_step(self.stmt.stmt) } {
ffi::SQLITE_ROW => { ffi::SQLITE_ROW => {
let current_row = self.current_row.get() + 1; let current_row = self.current_row.get() + 1;
self.current_row.set(current_row); self.current_row.set(current_row);
Some(Ok(Row { Some(Ok(Row {
stmt: self.stmt, stmt: stmt,
current_row: self.current_row.clone(), current_row: self.current_row.clone(),
row_idx: current_row, row_idx: current_row,
})) }))
} }
ffi::SQLITE_DONE => { ffi::SQLITE_DONE => {
self.done = true; self.reset();
None None
} }
code => { code => {
self.done = true; self.reset();
Some(Err(self.stmt.conn.decode_result(code).unwrap_err())) Some(Err(stmt.conn.decode_result(code).unwrap_err()))
} }
} }
})
} }
} }
impl<'stmt> Drop for Rows<'stmt> { impl<'stmt> Drop for Rows<'stmt> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { self.reset();
ffi::sqlite3_reset(self.stmt.stmt);
}
} }
} }