From aac4d59fcc4af0cc30dbc6ceeadf052a3002045b Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Sun, 13 Dec 2015 00:54:08 -0500 Subject: [PATCH] Change `Error` from a struct to an enum (BREAKING CHANGE). This allows us to separate out the underlying SQLite error codes from errors that occur on the Rust side. --- libsqlite3-sys/src/error.rs | 7 + src/backup.rs | 7 +- src/functions.rs | 58 ++++---- src/lib.rs | 278 +++++++++++++++++++++--------------- src/named_params.rs | 5 +- src/trace.rs | 11 +- src/types.rs | 116 ++++++--------- 7 files changed, 241 insertions(+), 241 deletions(-) diff --git a/libsqlite3-sys/src/error.rs b/libsqlite3-sys/src/error.rs index 5c4bace..cf6f1b0 100644 --- a/libsqlite3-sys/src/error.rs +++ b/libsqlite3-sys/src/error.rs @@ -1,4 +1,5 @@ use libc::c_int; +use std::error; use std::fmt; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -77,6 +78,12 @@ impl fmt::Display for Error { } } +impl error::Error for Error { + fn description(&self) -> &str { + code_to_str(self.extended_code) + } +} + // Result codes. pub const SQLITE_OK : c_int = 0; diff --git a/src/backup.rs b/src/backup.rs index 8eb5625..0f724cb 100644 --- a/src/backup.rs +++ b/src/backup.rs @@ -244,12 +244,7 @@ impl<'a, 'b> Backup<'a, 'b> { ffi::SQLITE_OK => Ok(More), ffi::SQLITE_BUSY => Ok(Busy), ffi::SQLITE_LOCKED => Ok(Locked), - rc => { - Err(Error { - code: rc, - message: ffi::code_to_str(rc).into(), - }) - } + _ => Err(Error::from_sqlite_code(rc, None)), } } diff --git a/src/functions.rs b/src/functions.rs index 196e639..1def91c 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -26,11 +26,10 @@ //! match entry { //! Occupied(occ) => occ.into_mut(), //! Vacant(vac) => { -//! let r = try!(Regex::new(®ex_s).map_err(|e| Error { -//! code: libsqlite3_sys::SQLITE_ERROR, -//! message: format!("Invalid regular expression: {}", e), -//! })); -//! vac.insert(r) +//! match Regex::new(®ex_s) { +//! Ok(r) => vac.insert(r), +//! Err(err) => return Err(Error::UserFunctionError(Box::new(err))), +//! } //! } //! } //! }; @@ -50,6 +49,7 @@ //! assert!(is_match); //! } //! ``` +use std::error::Error as StdError; use std::ffi::CStr; use std::mem; use std::ptr; @@ -225,14 +225,8 @@ impl FromValue for String { Ok("".to_string()) } else { let c_slice = CStr::from_ptr(c_text as *const c_char).to_bytes(); - let utf8_str = str::from_utf8(c_slice); - utf8_str.map(|s| s.to_string()) - .map_err(|e| { - Error { - code: 0, - message: e.to_string(), - } - }) + let utf8_str = try!(str::from_utf8(c_slice)); + Ok(utf8_str.into()) } } @@ -302,10 +296,7 @@ impl<'a> Context<'a> { if T::parameter_has_valid_sqlite_type(arg) { T::parameter_value(arg) } else { - Err(Error { - code: ffi::SQLITE_MISMATCH, - message: "Invalid value type".to_string(), - }) + Err(Error::InvalidFunctionParameterType) } } } @@ -421,9 +412,15 @@ impl InnerConnection { assert!(!boxed_f.is_null(), "Internal error - null function pointer"); match (*boxed_f)(&ctx) { Ok(r) => r.set_result(ctx.ctx), - Err(e) => { - ffi::sqlite3_result_error_code(ctx.ctx, e.code); - if let Ok(cstr) = str_to_cstring(&e.message) { + Err(Error::SqliteFailure(err, s)) => { + ffi::sqlite3_result_error_code(ctx.ctx, err.extended_code); + if let Some(Ok(cstr)) = s.map(|s| str_to_cstring(&s)) { + ffi::sqlite3_result_error(ctx.ctx, cstr.as_ptr(), -1); + } + }, + Err(err) => { + ffi::sqlite3_result_error_code(ctx.ctx, ffi::SQLITE_CONSTRAINT_FUNCTION); + if let Ok(cstr) = str_to_cstring(err.description()) { ffi::sqlite3_result_error(ctx.ctx, cstr.as_ptr(), -1); } } @@ -476,7 +473,6 @@ mod test { use self::regex::Regex; use {Connection, Error, Result}; - use ffi; use functions::Context; fn half(ctx: &Context) -> Result { @@ -516,13 +512,10 @@ mod test { let new_re = match saved_re { None => { let s = try!(ctx.get::(0)); - let r = try!(Regex::new(&s).map_err(|e| { - Error { - code: ffi::SQLITE_ERROR, - message: format!("Invalid regular expression: {}", e), - } - })); - Some(r) + match Regex::new(&s) { + Ok(r) => Some(r), + Err(err) => return Err(Error::UserFunctionError(Box::new(err))), + } } Some(_) => None, }; @@ -591,11 +584,10 @@ mod test { match entry { Occupied(occ) => occ.into_mut(), Vacant(vac) => { - let r = try!(Regex::new(®ex_s).map_err(|e| Error { - code: ffi::SQLITE_ERROR, - message: format!("Invalid regular expression: {}", e), - })); - vac.insert(r) + match Regex::new(®ex_s) { + Ok(r) => vac.insert(r), + Err(err) => return Err(Error::UserFunctionError(Box::new(err))), + } } } }; diff --git a/src/lib.rs b/src/lib.rs index 875cfb1..c4dcfa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,59 +103,129 @@ unsafe fn errmsg_to_string(errmsg: *const c_char) -> String { /// Old name for `Error`. `SqliteError` is deprecated. pub type SqliteError = Error; -/// Encompasses an error result from a call to the SQLite C API. -#[derive(Debug, PartialEq)] -pub struct Error { - /// The error code returned by a SQLite C API call. See [SQLite Result - /// Codes](http://www.sqlite.org/rescode.html) for details. - pub code: c_int, +#[derive(Debug)] +pub enum Error { + SqliteFailure(ffi::Error, Option), + FromSqlConversionFailure(Box), + Utf8Error(str::Utf8Error), + NulError(std::ffi::NulError), + InvalidParameterName(String), + InvalidPath(PathBuf), + ExecuteReturnedResults, + QueryReturnedNoRows, + GetFromStaleRow, + InvalidColumnIndex(c_int), + InvalidColumnType, - /// The error message provided by [sqlite3_errmsg](http://www.sqlite.org/c3ref/errcode.html), - /// if possible, or a generic error message based on `code` otherwise. - pub message: String, + #[cfg(feature = "functions")] + InvalidFunctionParameterType, + #[cfg(feature = "functions")] + #[allow(dead_code)] + UserFunctionError(Box), +} + +impl From for Error { + fn from(err: str::Utf8Error) -> Error { + Error::Utf8Error(err) + } +} + +impl From for Error { + fn from(err: std::ffi::NulError) -> Error { + Error::NulError(err) + } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} (SQLite error {})", self.message, self.code) + match self { + &Error::SqliteFailure(ref err, None) => err.fmt(f), + &Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s), + &Error::FromSqlConversionFailure(ref err) => err.fmt(f), + &Error::Utf8Error(ref err) => err.fmt(f), + &Error::NulError(ref err) => err.fmt(f), + &Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name), + &Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()), + &Error::ExecuteReturnedResults => write!(f, "Execute returned results - did you mean to call query?"), + &Error::QueryReturnedNoRows => write!(f, "Query returned no rows"), + &Error::GetFromStaleRow => write!(f, "Attempted to get a value from a stale row"), + &Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i), + &Error::InvalidColumnType => write!(f, "Invalid column type"), + + #[cfg(feature = "functions")] + &Error::InvalidFunctionParameterType => write!(f, "Invalid function parameter type"), + #[cfg(feature = "functions")] + &Error::UserFunctionError(ref err) => err.fmt(f), + } } } impl error::Error for Error { fn description(&self) -> &str { - &self.message + match self { + &Error::SqliteFailure(ref err, None) => err.description(), + &Error::SqliteFailure(_, Some(ref s)) => s, + &Error::FromSqlConversionFailure(ref err) => err.description(), + &Error::Utf8Error(ref err) => err.description(), + &Error::InvalidParameterName(_) => "invalid parameter name", + &Error::NulError(ref err) => err.description(), + &Error::InvalidPath(_) => "invalid path", + &Error::ExecuteReturnedResults => "execute returned results - did you mean to call query?", + &Error::QueryReturnedNoRows => "query returned no rows", + &Error::GetFromStaleRow => "attempted to get a value from a stale row", + &Error::InvalidColumnIndex(_) => "invalid column index", + &Error::InvalidColumnType => "invalid column type", + + #[cfg(feature = "functions")] + &Error::InvalidFunctionParameterType => "invalid function parameter type", + #[cfg(feature = "functions")] + &Error::UserFunctionError(ref err) => err.description(), + } + } + + fn cause(&self) -> Option<&error::Error> { + match self { + &Error::SqliteFailure(ref err, _) => Some(err), + &Error::FromSqlConversionFailure(ref err) => Some(&**err), + &Error::Utf8Error(ref err) => Some(err), + &Error::NulError(ref err) => Some(err), + &Error::InvalidParameterName(_) => None, + &Error::InvalidPath(_) => None, + &Error::ExecuteReturnedResults => None, + &Error::QueryReturnedNoRows => None, + &Error::GetFromStaleRow => None, + &Error::InvalidColumnIndex(_) => None, + &Error::InvalidColumnType => None, + + #[cfg(feature = "functions")] + &Error::InvalidFunctionParameterType => None, + #[cfg(feature = "functions")] + &Error::UserFunctionError(ref err) => Some(&**err), + } } } impl Error { + fn from_sqlite_code(code: c_int, message: Option) -> Error { + Error::SqliteFailure(ffi::Error::new(code), message) + } + fn from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error { let message = if db.is_null() { - ffi::code_to_str(code).to_string() + None } else { - unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) } + Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) }) }; - Error { - code: code, - message: message, - } + Error::from_sqlite_code(code, message) } } fn str_to_cstring(s: &str) -> Result { - CString::new(s).map_err(|_| { - Error { - code: ffi::SQLITE_MISUSE, - message: format!("Could not convert string {} to C-combatible string", s), - } - }) + Ok(try!(CString::new(s))) } fn path_to_cstring(p: &Path) -> Result { - let s = try!(p.to_str().ok_or(Error { - code: ffi::SQLITE_MISUSE, - message: format!("Could not convert path {} to UTF-8 string", - p.to_string_lossy()), - })); + let s = try!(p.to_str().ok_or(Error::InvalidPath(p.to_owned()))); str_to_cstring(s) } @@ -598,10 +668,7 @@ impl InnerConnection { let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), ptr::null()); if r != ffi::SQLITE_OK { let e = if db.is_null() { - Error { - code: r, - message: ffi::code_to_str(r).to_string(), - } + Error::from_sqlite_code(r, None) } else { let e = Error::from_handle(db, r); ffi::sqlite3_close(db); @@ -681,10 +748,7 @@ impl InnerConnection { } else { let message = errmsg_to_string(&*errmsg); ffi::sqlite3_free(errmsg as *mut libc::c_void); - Err(Error { - code: r, - message: message, - }) + Err(Error::from_sqlite_code(r, Some(message))) } } } @@ -698,10 +762,7 @@ impl InnerConnection { sql: &str) -> Result> { if sql.len() >= ::std::i32::MAX as usize { - return Err(Error { - code: ffi::SQLITE_TOOBIG, - message: "statement too long".to_string(), - }); + return Err(Error::from_sqlite_code(ffi::SQLITE_TOOBIG, None)); } let mut c_stmt: *mut ffi::sqlite3_stmt = unsafe { mem::uninitialized() }; let c_sql = try!(str_to_cstring(sql)); @@ -797,21 +858,12 @@ impl<'conn> Statement<'conn> { match r { ffi::SQLITE_DONE => { if self.column_count != 0 { - Err(Error { - code: ffi::SQLITE_MISUSE, - message: "Unexpected column count - did you mean to call query?" - .to_string(), - }) + Err(Error::ExecuteReturnedResults) } else { Ok(self.conn.changes()) } - } - ffi::SQLITE_ROW => { - Err(Error { - code: r, - message: "Unexpected row result - did you mean to call query?".to_string(), - }) - } + }, + ffi::SQLITE_ROW => Err(Error::ExecuteReturnedResults), _ => Err(self.conn.decode_result(r).unwrap_err()), } } @@ -1052,12 +1104,7 @@ impl<'stmt> Rows<'stmt> { fn get_expected_row(&mut self) -> Result> { match self.next() { Some(row) => row, - None => { - Err(Error { - code: ffi::SQLITE_NOTICE, - message: "Query did not return a row".to_string(), - }) - } + None => Err(Error::QueryReturnedNoRows), } } } @@ -1142,26 +1189,17 @@ impl<'stmt> Row<'stmt> { /// for this row or if this row is stale. pub fn get_checked(&self, idx: c_int) -> Result { if self.row_idx != self.current_row.get() { - return Err(Error { - code: ffi::SQLITE_MISUSE, - message: "Cannot get values from a row after advancing to next row".to_string(), - }); + return Err(Error::GetFromStaleRow); } unsafe { if idx < 0 || idx >= self.stmt.column_count { - return Err(Error { - code: ffi::SQLITE_MISUSE, - message: "Invalid column index".to_string(), - }); + return Err(Error::InvalidColumnIndex(idx)); } if T::column_has_valid_sqlite_type(self.stmt.stmt, idx) { FromSql::column_result(self.stmt.stmt, idx) } else { - Err(Error { - code: ffi::SQLITE_MISMATCH, - message: "Invalid column type".to_string(), - }) + Err(Error::InvalidColumnType) } } } @@ -1264,8 +1302,10 @@ mod test { fn test_execute_select() { let db = checked_memory_handle(); let err = db.execute("SELECT 1 WHERE 1 < ?", &[&1i32]).unwrap_err(); - assert!(err.code == ffi::SQLITE_MISUSE); - assert!(err.message == "Unexpected column count - did you mean to call query?"); + match err { + Error::ExecuteReturnedResults => (), + _ => panic!("Unexpected error: {}", err), + } } #[test] @@ -1364,10 +1404,10 @@ mod test { .unwrap()); let result = db.query_row("SELECT x FROM foo WHERE x > 5", &[], |r| r.get::(0)); - let error = result.unwrap_err(); - - assert!(error.code == ffi::SQLITE_NOTICE); - assert!(error.message == "Query did not return a row"); + match result.unwrap_err() { + Error::QueryReturnedNoRows => (), + err => panic!("Unexpected error {}", err), + } let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", &[], |_| ()); @@ -1380,7 +1420,7 @@ mod test { db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap(); let err = db.prepare("SELECT * FROM does_not_exist").unwrap_err(); - assert!(err.message.contains("does_not_exist")); + assert!(format!("{}", err).contains("does_not_exist")); } #[test] @@ -1397,8 +1437,10 @@ mod test { assert_eq!(2i32, second.get(0)); - let result = first.get_checked::(0); - assert!(result.unwrap_err().message.contains("advancing to next row")); + match first.get_checked::(0).unwrap_err() { + Error::GetFromStaleRow => (), + err => panic!("Unexpected error {}", err), + } } #[test] @@ -1433,15 +1475,17 @@ mod test { let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", &[]); assert!(result.is_err()); - let err = result.err().unwrap(); - assert_eq!(err.code, ffi::SQLITE_CONSTRAINT_NOTNULL); + match result.unwrap_err() { + Error::SqliteFailure(err, _) => assert_eq!(err.extended_code, ffi::SQLITE_CONSTRAINT_NOTNULL), + err => panic!("Unexpected error {}", err), + } } mod query_and_then_tests { extern crate libsqlite3_sys as ffi; use super::*; - #[derive(Debug, PartialEq)] + #[derive(Debug)] enum CustomError { SomeError, Sqlite(Error), @@ -1512,27 +1556,23 @@ mod test { db.execute_batch(sql).unwrap(); let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap(); - let bad_type: Result> = query.query_and_then(&[], - |row| row.get_checked(1)) + let bad_type: Result> = query.query_and_then(&[], |row| row.get_checked(1)) .unwrap() .collect(); - assert_eq!(bad_type, - Err(Error { - code: ffi::SQLITE_MISMATCH, - message: "Invalid column type".to_owned(), - })); + match bad_type.unwrap_err() { + Error::InvalidColumnType => (), + err => panic!("Unexpected error {}", err), + } - let bad_idx: Result> = query.query_and_then(&[], - |row| row.get_checked(3)) + let bad_idx: Result> = query.query_and_then(&[], |row| row.get_checked(3)) .unwrap() .collect(); - assert_eq!(bad_idx, - Err(Error { - code: ffi::SQLITE_MISUSE, - message: "Invalid column index".to_owned(), - })); + match bad_idx.unwrap_err() { + Error::InvalidColumnIndex(_) => (), + err => panic!("Unexpected error {}", err), + } } #[test] @@ -1580,11 +1620,10 @@ mod test { .unwrap() .collect(); - assert_eq!(bad_type, - Err(CustomError::Sqlite(Error { - code: ffi::SQLITE_MISMATCH, - message: "Invalid column type".to_owned(), - }))); + match bad_type.unwrap_err() { + CustomError::Sqlite(Error::InvalidColumnType) => (), + err => panic!("Unexpected error {}", err), + } let bad_idx: CustomResult> = query.query_and_then(&[], |row| { row.get_checked(3) @@ -1593,11 +1632,10 @@ mod test { .unwrap() .collect(); - assert_eq!(bad_idx, - Err(CustomError::Sqlite(Error { - code: ffi::SQLITE_MISUSE, - message: "Invalid column index".to_owned(), - }))); + match bad_idx.unwrap_err() { + CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (), + err => panic!("Unexpected error {}", err), + } let non_sqlite_err: CustomResult> = query.query_and_then(&[], |_| { Err(CustomError::SomeError) @@ -1605,7 +1643,10 @@ mod test { .unwrap() .collect(); - assert_eq!(non_sqlite_err, Err(CustomError::SomeError)); + match non_sqlite_err.unwrap_err() { + CustomError::SomeError => (), + err => panic!("Unexpected error {}", err), + } } #[test] @@ -1641,27 +1682,28 @@ mod test { row.get_checked(1).map_err(CustomError::Sqlite) }); - assert_eq!(bad_type, - Err(CustomError::Sqlite(Error { - code: ffi::SQLITE_MISMATCH, - message: "Invalid column type".to_owned(), - }))); + match bad_type.unwrap_err() { + CustomError::Sqlite(Error::InvalidColumnType) => (), + err => panic!("Unexpected error {}", err), + } let bad_idx: CustomResult = db.query_row_and_then(query, &[], |row| { row.get_checked(3).map_err(CustomError::Sqlite) }); - assert_eq!(bad_idx, - Err(CustomError::Sqlite(Error { - code: ffi::SQLITE_MISUSE, - message: "Invalid column index".to_owned(), - }))); + match bad_idx.unwrap_err() { + CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (), + err => panic!("Unexpected error {}", err), + } let non_sqlite_err: CustomResult = db.query_row_and_then(query, &[], |_| { Err(CustomError::SomeError) }); - assert_eq!(non_sqlite_err, Err(CustomError::SomeError)); + match non_sqlite_err.unwrap_err() { + CustomError::SomeError => (), + err => panic!("Unexpected error {}", err), + } } } diff --git a/src/named_params.rs b/src/named_params.rs index d1dcdc9..dc880ca 100644 --- a/src/named_params.rs +++ b/src/named_params.rs @@ -133,10 +133,7 @@ impl<'conn> Statement<'conn> { if let Some(i) = try!(self.parameter_index(name)) { try!(self.conn.decode_result(unsafe { value.bind_parameter(self.stmt, i) })); } else { - return Err(Error { - code: ffi::SQLITE_MISUSE, - message: format!("Invalid parameter name: {}", name), - }); + return Err(Error::InvalidParameterName(name.into())); } } Ok(()) diff --git a/src/trace.rs b/src/trace.rs index 0c49ce5..c11534c 100644 --- a/src/trace.rs +++ b/src/trace.rs @@ -42,14 +42,11 @@ pub unsafe fn config_log(callback: Option) -> Result<()> { } }; - if rc != ffi::SQLITE_OK { - return Err(Error { - code: rc, - message: "sqlite3_config(SQLITE_CONFIG_LOG, ...)".to_string(), - }); + if rc == ffi::SQLITE_OK { + Ok(()) + } else { + Err(Error::from_sqlite_code(rc, None)) } - - Ok(()) } /// Write a message into the error log established by `config_log`. diff --git a/src/types.rs b/src/types.rs index f0852ab..c33afa8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -232,14 +232,8 @@ impl FromSql for String { Ok("".to_string()) } else { let c_slice = CStr::from_ptr(c_text as *const c_char).to_bytes(); - let utf8_str = str::from_utf8(c_slice); - utf8_str.map(|s| s.to_string()) - .map_err(|e| { - Error { - code: 0, - message: e.to_string(), - } - }) + let utf8_str = try!(str::from_utf8(c_slice)); + Ok(utf8_str.into()) } } @@ -272,14 +266,10 @@ impl FromSql for time::Timespec { unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result { let col_str = FromSql::column_result(stmt, col); col_str.and_then(|txt: String| { - time::strptime(&txt, SQLITE_DATETIME_FMT) - .map(|tm| tm.to_timespec()) - .map_err(|parse_error| { - Error { - code: ffi::SQLITE_MISMATCH, - message: format!("{}", parse_error), - } - }) + match time::strptime(&txt, SQLITE_DATETIME_FMT) { + Ok(tm) => Ok(tm.to_timespec()), + Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))), + } }) } @@ -306,8 +296,8 @@ impl FromSql for Option { #[cfg(test)] mod test { use Connection; - use ffi; use super::time; + use Error; use libc::{c_int, c_double}; fn checked_memory_handle() -> Connection { @@ -380,6 +370,13 @@ mod test { #[test] fn test_mismatched_types() { + fn is_invalid_column_type(err: Error) -> bool { + match err { + Error::InvalidColumnType => true, + _ => false, + } + } + let db = checked_memory_handle(); db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)", @@ -403,69 +400,42 @@ mod test { // check some invalid types // 0 is actually a blob (Vec) - assert_eq!(row.get_checked::(0).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(0).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(0).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(0).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(0).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(0).err().unwrap().code, - ffi::SQLITE_MISMATCH); + assert!(is_invalid_column_type(row.get_checked::(0).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(0).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(0).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(0).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(0).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(0).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(0).err().unwrap())); // 1 is actually a text (String) - assert_eq!(row.get_checked::(1).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(1).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(1).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(1).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(1).err().unwrap().code, - ffi::SQLITE_MISMATCH); + assert!(is_invalid_column_type(row.get_checked::(1).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(1).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(1).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(1).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(1).err().unwrap())); // 2 is actually an integer - assert_eq!(row.get_checked::(2).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(2).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(2).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(2).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(2).err().unwrap().code, - ffi::SQLITE_MISMATCH); + assert!(is_invalid_column_type(row.get_checked::(2).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(2).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(2).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(2).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(2).err().unwrap())); // 3 is actually a float (c_double) - assert_eq!(row.get_checked::(3).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(3).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(3).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(3).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(3).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(3).err().unwrap().code, - ffi::SQLITE_MISMATCH); + assert!(is_invalid_column_type(row.get_checked::(3).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(3).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(3).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(3).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(3).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(3).err().unwrap())); // 4 is actually NULL - assert_eq!(row.get_checked::(4).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(4).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(4).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(4).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::>(4).err().unwrap().code, - ffi::SQLITE_MISMATCH); - assert_eq!(row.get_checked::(4).err().unwrap().code, - ffi::SQLITE_MISMATCH); + assert!(is_invalid_column_type(row.get_checked::(4).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(4).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(4).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(4).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::>(4).err().unwrap())); + assert!(is_invalid_column_type(row.get_checked::(4).err().unwrap())); } }