Check sqlite3_reset result

https://sqlite.org/c3ref/reset.html
> Therefore, it is important that applications check the return code from sqlite3_reset(S) even if no prior call to sqlite3_step(S) indicated a problem.
This commit is contained in:
gwenn 2023-11-25 10:13:55 +01:00
parent 7f8c42116e
commit 87d81cd46b
2 changed files with 19 additions and 10 deletions

View File

@ -14,9 +14,11 @@ pub struct Rows<'stmt> {
impl<'stmt> Rows<'stmt> { impl<'stmt> Rows<'stmt> {
#[inline] #[inline]
fn reset(&mut self) { fn reset(&mut self) -> Result<()> {
if let Some(stmt) = self.stmt.take() { if let Some(stmt) = self.stmt.take() {
stmt.reset(); stmt.reset()
} else {
Ok(())
} }
} }
@ -105,6 +107,7 @@ impl<'stmt> Rows<'stmt> {
} }
impl Drop for Rows<'_> { impl Drop for Rows<'_> {
#[allow(unused_must_use)]
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
self.reset(); self.reset();
@ -217,12 +220,12 @@ impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
Ok(()) Ok(())
} }
Ok(false) => { Ok(false) => {
self.reset(); let r = self.reset();
self.row = None; self.row = None;
Ok(()) r
} }
Err(e) => { Err(e) => {
self.reset(); let _ = self.reset(); // prevents infinite loop on error
self.row = None; self.row = None;
Err(e) Err(e)
} }

View File

@ -650,9 +650,12 @@ impl Statement<'_> {
fn execute_with_bound_parameters(&mut self) -> Result<usize> { fn execute_with_bound_parameters(&mut self) -> Result<usize> {
self.check_update()?; self.check_update()?;
let r = self.stmt.step(); let r = self.stmt.step();
self.stmt.reset(); let rr = self.stmt.reset();
match r { match r {
ffi::SQLITE_DONE => Ok(self.conn.changes() as usize), ffi::SQLITE_DONE => match rr {
ffi::SQLITE_OK => Ok(self.conn.changes() as usize),
_ => Err(self.conn.decode_result(rr).unwrap_err()),
},
ffi::SQLITE_ROW => Err(Error::ExecuteReturnedResults), ffi::SQLITE_ROW => Err(Error::ExecuteReturnedResults),
_ => Err(self.conn.decode_result(r).unwrap_err()), _ => Err(self.conn.decode_result(r).unwrap_err()),
} }
@ -847,8 +850,11 @@ impl Statement<'_> {
} }
#[inline] #[inline]
pub(super) fn reset(&self) -> c_int { pub(super) fn reset(&self) -> Result<()> {
self.stmt.reset() match self.stmt.reset() {
ffi::SQLITE_OK => Ok(()),
code => Err(self.conn.decode_result(code).unwrap_err()),
}
} }
} }
@ -1274,7 +1280,7 @@ mod test {
assert_eq!(0, stmt.column_count()); assert_eq!(0, stmt.column_count());
stmt.parameter_index("test").unwrap(); stmt.parameter_index("test").unwrap();
stmt.step().unwrap_err(); stmt.step().unwrap_err();
stmt.reset(); stmt.reset().unwrap(); // SQLITE_OMIT_AUTORESET = false
stmt.execute([]).unwrap_err(); stmt.execute([]).unwrap_err();
Ok(()) Ok(())
} }