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) } {
} ffi::SQLITE_ROW => {
match unsafe { ffi::sqlite3_step(self.stmt.stmt) } { let current_row = self.current_row.get() + 1;
ffi::SQLITE_ROW => { self.current_row.set(current_row);
let current_row = self.current_row.get() + 1; Some(Ok(Row {
self.current_row.set(current_row); stmt: stmt,
Some(Ok(Row { current_row: self.current_row.clone(),
stmt: self.stmt, row_idx: current_row,
current_row: self.current_row.clone(), }))
row_idx: current_row, }
})) ffi::SQLITE_DONE => {
self.reset();
None
}
code => {
self.reset();
Some(Err(stmt.conn.decode_result(code).unwrap_err()))
}
} }
ffi::SQLITE_DONE => { })
self.done = true;
None
}
code => {
self.done = true;
Some(Err(self.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);
}
} }
} }