Move Error into its own module (internal organization only - public API remains).

This commit is contained in:
John Gallagher 2015-12-13 01:04:09 -05:00
parent aac4d59fcc
commit 047861b928
4 changed files with 146 additions and 136 deletions

View File

@ -36,7 +36,8 @@ use std::time::Duration;
use ffi; use ffi;
use {DatabaseName, Connection, Error, Result}; use {DatabaseName, Connection, Result};
use error::{error_from_sqlite_code, error_from_handle};
impl Connection { impl Connection {
/// Back up the `name` database to the given destination path. /// Back up the `name` database to the given destination path.
@ -70,8 +71,8 @@ impl Connection {
match r { match r {
Done => Ok(()), Done => Ok(()),
Busy => Err(Error::from_handle(ptr::null_mut(), ffi::SQLITE_BUSY)), Busy => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_BUSY)),
Locked => Err(Error::from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED)), Locked => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED)),
More => unreachable!(), More => unreachable!(),
} }
} }
@ -115,8 +116,8 @@ impl Connection {
match r { match r {
Done => Ok(()), Done => Ok(()),
Busy => Err(Error::from_handle(ptr::null_mut(), ffi::SQLITE_BUSY)), Busy => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_BUSY)),
Locked => Err(Error::from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED)), Locked => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED)),
More => unreachable!(), More => unreachable!(),
} }
} }
@ -201,7 +202,7 @@ impl<'a, 'b> Backup<'a, 'b> {
from.db.borrow_mut().db, from.db.borrow_mut().db,
from_name.as_ptr()); from_name.as_ptr());
if b.is_null() { if b.is_null() {
return Err(Error::from_handle(to_db, ffi::sqlite3_errcode(to_db))); return Err(error_from_handle(to_db, ffi::sqlite3_errcode(to_db)));
} }
b b
}; };
@ -244,7 +245,7 @@ impl<'a, 'b> Backup<'a, 'b> {
ffi::SQLITE_OK => Ok(More), ffi::SQLITE_OK => Ok(More),
ffi::SQLITE_BUSY => Ok(Busy), ffi::SQLITE_BUSY => Ok(Busy),
ffi::SQLITE_LOCKED => Ok(Locked), ffi::SQLITE_LOCKED => Ok(Locked),
_ => Err(Error::from_sqlite_code(rc, None)), _ => Err(error_from_sqlite_code(rc, None)),
} }
} }

126
src/error.rs Normal file
View File

@ -0,0 +1,126 @@
use std::error;
use std::fmt;
use std::path::PathBuf;
use std::str;
use libc::c_int;
use {ffi, errmsg_to_string};
/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;
#[derive(Debug)]
pub enum Error {
SqliteFailure(ffi::Error, Option<String>),
FromSqlConversionFailure(Box<error::Error>),
Utf8Error(str::Utf8Error),
NulError(::std::ffi::NulError),
InvalidParameterName(String),
InvalidPath(PathBuf),
ExecuteReturnedResults,
QueryReturnedNoRows,
GetFromStaleRow,
InvalidColumnIndex(c_int),
InvalidColumnType,
#[cfg(feature = "functions")]
InvalidFunctionParameterType,
#[cfg(feature = "functions")]
#[allow(dead_code)]
UserFunctionError(Box<error::Error>),
}
impl From<str::Utf8Error> for Error {
fn from(err: str::Utf8Error) -> Error {
Error::Utf8Error(err)
}
}
impl From<::std::ffi::NulError> 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 {
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 {
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),
}
}
}
// These are public but not re-exported by lib.rs, so only visible within crate.
pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
Error::SqliteFailure(ffi::Error::new(code), message)
}
pub fn error_from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error {
let message = if db.is_null() {
None
} else {
Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
};
error_from_sqlite_code(code, message)
}

View File

@ -64,7 +64,6 @@ use std::mem;
use std::ptr; use std::ptr;
use std::fmt; use std::fmt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::error;
use std::rc::Rc; use std::rc::Rc;
use std::cell::{RefCell, Cell}; use std::cell::{RefCell, Cell};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
@ -73,8 +72,10 @@ use std::str;
use libc::{c_int, c_char}; use libc::{c_int, c_char};
use types::{ToSql, FromSql}; use types::{ToSql, FromSql};
use error::{error_from_sqlite_code, error_from_handle};
pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior}; pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior};
pub use error::{SqliteError, Error};
#[cfg(feature = "load_extension")] #[cfg(feature = "load_extension")]
pub use load_extension_guard::{SqliteLoadExtensionGuard, LoadExtensionGuard}; pub use load_extension_guard::{SqliteLoadExtensionGuard, LoadExtensionGuard};
@ -82,6 +83,7 @@ pub use load_extension_guard::{SqliteLoadExtensionGuard, LoadExtensionGuard};
pub mod types; pub mod types;
mod transaction; mod transaction;
mod named_params; mod named_params;
mod error;
#[cfg(feature = "load_extension")]mod load_extension_guard; #[cfg(feature = "load_extension")]mod load_extension_guard;
#[cfg(feature = "trace")]pub mod trace; #[cfg(feature = "trace")]pub mod trace;
#[cfg(feature = "backup")]pub mod backup; #[cfg(feature = "backup")]pub mod backup;
@ -100,126 +102,6 @@ unsafe fn errmsg_to_string(errmsg: *const c_char) -> String {
utf8_str.unwrap_or("Invalid string encoding").to_string() utf8_str.unwrap_or("Invalid string encoding").to_string()
} }
/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;
#[derive(Debug)]
pub enum Error {
SqliteFailure(ffi::Error, Option<String>),
FromSqlConversionFailure(Box<error::Error>),
Utf8Error(str::Utf8Error),
NulError(std::ffi::NulError),
InvalidParameterName(String),
InvalidPath(PathBuf),
ExecuteReturnedResults,
QueryReturnedNoRows,
GetFromStaleRow,
InvalidColumnIndex(c_int),
InvalidColumnType,
#[cfg(feature = "functions")]
InvalidFunctionParameterType,
#[cfg(feature = "functions")]
#[allow(dead_code)]
UserFunctionError(Box<std::error::Error>),
}
impl From<str::Utf8Error> for Error {
fn from(err: str::Utf8Error) -> Error {
Error::Utf8Error(err)
}
}
impl From<std::ffi::NulError> 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 {
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 {
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<String>) -> 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() {
None
} else {
Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
};
Error::from_sqlite_code(code, message)
}
}
fn str_to_cstring(s: &str) -> Result<CString> { fn str_to_cstring(s: &str) -> Result<CString> {
Ok(try!(CString::new(s))) Ok(try!(CString::new(s)))
} }
@ -668,9 +550,9 @@ impl InnerConnection {
let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), ptr::null()); let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), ptr::null());
if r != ffi::SQLITE_OK { if r != ffi::SQLITE_OK {
let e = if db.is_null() { let e = if db.is_null() {
Error::from_sqlite_code(r, None) error_from_sqlite_code(r, None)
} else { } else {
let e = Error::from_handle(db, r); let e = error_from_handle(db, r);
ffi::sqlite3_close(db); ffi::sqlite3_close(db);
e e
}; };
@ -679,7 +561,7 @@ impl InnerConnection {
} }
let r = ffi::sqlite3_busy_timeout(db, 5000); let r = ffi::sqlite3_busy_timeout(db, 5000);
if r != ffi::SQLITE_OK { if r != ffi::SQLITE_OK {
let e = Error::from_handle(db, r); let e = error_from_handle(db, r);
ffi::sqlite3_close(db); ffi::sqlite3_close(db);
return Err(e); return Err(e);
} }
@ -699,7 +581,7 @@ impl InnerConnection {
if code == ffi::SQLITE_OK { if code == ffi::SQLITE_OK {
Ok(()) Ok(())
} else { } else {
Err(Error::from_handle(self.db(), code)) Err(error_from_handle(self.db(), code))
} }
} }
@ -748,7 +630,7 @@ impl InnerConnection {
} else { } else {
let message = errmsg_to_string(&*errmsg); let message = errmsg_to_string(&*errmsg);
ffi::sqlite3_free(errmsg as *mut libc::c_void); ffi::sqlite3_free(errmsg as *mut libc::c_void);
Err(Error::from_sqlite_code(r, Some(message))) Err(error_from_sqlite_code(r, Some(message)))
} }
} }
} }
@ -762,7 +644,7 @@ impl InnerConnection {
sql: &str) sql: &str)
-> Result<Statement<'a>> { -> Result<Statement<'a>> {
if sql.len() >= ::std::i32::MAX as usize { if sql.len() >= ::std::i32::MAX as usize {
return Err(Error::from_sqlite_code(ffi::SQLITE_TOOBIG, None)); return Err(error_from_sqlite_code(ffi::SQLITE_TOOBIG, None));
} }
let mut c_stmt: *mut ffi::sqlite3_stmt = unsafe { mem::uninitialized() }; let mut c_stmt: *mut ffi::sqlite3_stmt = unsafe { mem::uninitialized() };
let c_sql = try!(str_to_cstring(sql)); let c_sql = try!(str_to_cstring(sql));

View File

@ -8,7 +8,8 @@ use std::str;
use std::time::Duration; use std::time::Duration;
use super::ffi; use super::ffi;
use {Error, Result, Connection}; use {Result, Connection};
use error::error_from_sqlite_code;
/// Set up the process-wide SQLite error logging callback. /// Set up the process-wide SQLite error logging callback.
/// This function is marked unsafe for two reasons: /// This function is marked unsafe for two reasons:
@ -45,7 +46,7 @@ pub unsafe fn config_log(callback: Option<fn(c_int, &str)>) -> Result<()> {
if rc == ffi::SQLITE_OK { if rc == ffi::SQLITE_OK {
Ok(()) Ok(())
} else { } else {
Err(Error::from_sqlite_code(rc, None)) Err(error_from_sqlite_code(rc, None))
} }
} }