diff --git a/src/error.rs b/src/error.rs index bb46e2d..f5b4e28 100644 --- a/src/error.rs +++ b/src/error.rs @@ -130,7 +130,7 @@ pub enum Error { /// error code error: ffi::Error, /// error message - msg: String, + msg: Option, /// SQL input sql: String, /// byte offset of the start of invalid token @@ -324,7 +324,7 @@ impl fmt::Display for Error { offset, ref sql, .. - } => write!(f, "{msg} in {sql} at offset {offset}"), + } => write!(f, "{msg:?} in {sql} at offset {offset}"), #[cfg(feature = "loadable_extension")] Self::InitError(ref err) => err.fmt(f), #[cfg(feature = "modern_sqlite")] @@ -414,12 +414,20 @@ pub fn error_from_sqlite_code(code: c_int, message: Option) -> Error { #[cold] pub unsafe fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error { - let message = if db.is_null() { - None + error_from_sqlite_code(code, error_msg(db, code)) +} + +unsafe fn error_msg(db: *mut ffi::sqlite3, code: c_int) -> Option { + if db.is_null() || ffi::sqlite3_errcode(db) != code { + let err_str = ffi::sqlite3_errstr(code); + if err_str.is_null() { + None + } else { + Some(errmsg_to_string(err_str)) + } } else { Some(errmsg_to_string(ffi::sqlite3_errmsg(db))) - }; - error_from_sqlite_code(code, message) + } } pub unsafe fn decode_result_raw(db: *mut ffi::sqlite3, code: c_int) -> Result<()> { @@ -443,7 +451,7 @@ pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, sql: &str) - error_from_sqlite_code(code, None) } else { let error = ffi::Error::new(code); - let msg = errmsg_to_string(ffi::sqlite3_errmsg(db)); + let msg = error_msg(db, code); if ffi::ErrorCode::Unknown == error.code { let offset = ffi::sqlite3_error_offset(db); if offset >= 0 { @@ -455,7 +463,7 @@ pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, sql: &str) - }; } } - Error::SqliteFailure(error, Some(msg)) + Error::SqliteFailure(error, msg) } } diff --git a/src/statement.rs b/src/statement.rs index b11c31b..02cf72e 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -1286,7 +1286,12 @@ mod test { let mut stmt = conn.prepare("")?; assert_eq!(0, stmt.column_count()); stmt.parameter_index("test")?; - stmt.step().unwrap_err(); + let err = stmt.step().unwrap_err(); + assert_eq!(err.sqlite_error_code(), Some(crate::ErrorCode::ApiMisuse)); + assert_eq!( + err.to_string(), + "bad parameter or other API misuse".to_owned() + ); stmt.reset()?; // SQLITE_OMIT_AUTORESET = false stmt.execute([]).unwrap_err(); Ok(())