rusqlite/src/error.rs

191 lines
7.4 KiB
Rust
Raw Normal View History

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.
#[deprecated(since = "0.6.0", note = "Use Error instead")]
pub type SqliteError = Error;
2015-12-17 12:46:39 +08:00
/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
pub enum Error {
2015-12-17 12:46:39 +08:00
/// An error from an underlying SQLite call.
SqliteFailure(ffi::Error, Option<String>),
2015-12-17 12:46:39 +08:00
/// Error reported when attempting to open a connection when SQLite was configured to
/// allow single-threaded use only.
SqliteSingleThreadedMode,
2015-12-17 12:46:39 +08:00
/// An error case available for implementors of the `FromSql` trait.
FromSqlConversionFailure(Box<error::Error + Send + Sync>),
2015-12-17 12:46:39 +08:00
/// Error converting a string to UTF-8.
Utf8Error(str::Utf8Error),
2015-12-17 12:46:39 +08:00
/// Error converting a string to a C-compatible string because it contained an embedded nul.
NulError(::std::ffi::NulError),
2015-12-17 12:46:39 +08:00
/// Error when using SQL named parameters and passing a parameter name not present in the SQL.
InvalidParameterName(String),
2015-12-17 12:46:39 +08:00
/// Error converting a file path to a string.
InvalidPath(PathBuf),
2015-12-17 12:46:39 +08:00
2016-01-08 00:36:01 +08:00
/// Error returned when an `execute` call returns rows.
ExecuteReturnedResults,
2015-12-17 12:46:39 +08:00
/// Error when a query that was expected to return at least one row (e.g., for `query_row`)
/// did not return any.
QueryReturnedNoRows,
2015-12-17 12:46:39 +08:00
/// Error when the value of a particular column is requested, but the index is out of range
/// for the statement.
InvalidColumnIndex(c_int),
2015-12-17 12:46:39 +08:00
/// Error when the value of a named column is requested, but no column matches the name
/// for the statement.
InvalidColumnName(String),
2015-12-17 12:46:39 +08:00
/// Error when the value of a particular column is requested, but the type of the result in
/// that column cannot be converted to the requested Rust type.
InvalidColumnType,
/// Error when a query that was expected to insert one row did not insert any or insert many.
StatementChangedRows(c_int),
/// Error when a query that was expected to insert a row did not change the connection's
/// last_insert_rowid().
StatementFailedToInsertRow,
2015-12-17 12:46:39 +08:00
/// Error returned by `functions::Context::get` when the function argument cannot be converted
/// to the requested type.
#[cfg(feature = "functions")]
InvalidFunctionParameterType,
2015-12-17 12:46:39 +08:00
/// An error case available for implementors of custom user functions (e.g.,
/// `create_scalar_function`).
#[cfg(feature = "functions")]
#[allow(dead_code)]
UserFunctionError(Box<error::Error + Send + Sync>),
}
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 {
2016-02-14 23:11:59 +08:00
match *self {
Error::SqliteFailure(ref err, None) => err.fmt(f),
Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
Error::SqliteSingleThreadedMode => {
2016-02-03 02:12:00 +08:00
write!(f,
"SQLite was compiled or configured for single-threaded use only")
}
2016-02-14 23:11:59 +08:00
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 => {
2016-02-03 02:12:00 +08:00
write!(f, "Execute returned results - did you mean to call query?")
}
2016-02-14 23:11:59 +08:00
Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {}", name),
Error::InvalidColumnType => write!(f, "Invalid column type"),
Error::StatementChangedRows(i) => write!(f, "Query changed {} rows", i),
Error::StatementFailedToInsertRow => write!(f, "Statement failed to insert new row"),
#[cfg(feature = "functions")]
2016-02-14 23:11:59 +08:00
Error::InvalidFunctionParameterType => write!(f, "Invalid function parameter type"),
#[cfg(feature = "functions")]
2016-02-14 23:11:59 +08:00
Error::UserFunctionError(ref err) => err.fmt(f),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
2016-02-14 23:11:59 +08:00
match *self {
Error::SqliteFailure(ref err, None) => err.description(),
Error::SqliteFailure(_, Some(ref s)) => s,
Error::SqliteSingleThreadedMode => {
2016-02-03 02:12:00 +08:00
"SQLite was compiled or configured for single-threaded use only"
}
2016-02-14 23:11:59 +08:00
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 => {
2016-02-03 02:12:00 +08:00
"execute returned results - did you mean to call query?"
}
2016-02-14 23:11:59 +08:00
Error::QueryReturnedNoRows => "query returned no rows",
Error::InvalidColumnIndex(_) => "invalid column index",
Error::InvalidColumnName(_) => "invalid column name",
Error::InvalidColumnType => "invalid column type",
Error::StatementChangedRows(_) => "query inserted zero or more than one row",
Error::StatementFailedToInsertRow => "statement failed to insert new row",
#[cfg(feature = "functions")]
2016-02-14 23:11:59 +08:00
Error::InvalidFunctionParameterType => "invalid function parameter type",
#[cfg(feature = "functions")]
2016-02-14 23:11:59 +08:00
Error::UserFunctionError(ref err) => err.description(),
}
}
#[cfg_attr(feature="clippy", allow(match_same_arms))]
fn cause(&self) -> Option<&error::Error> {
2016-02-14 23:11:59 +08:00
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::SqliteSingleThreadedMode |
Error::InvalidParameterName(_) |
Error::ExecuteReturnedResults |
Error::QueryReturnedNoRows |
Error::InvalidColumnIndex(_) |
Error::InvalidColumnName(_) |
Error::InvalidColumnType |
2016-05-20 04:02:06 +08:00
Error::InvalidPath(_) |
Error::StatementChangedRows(_) |
Error::StatementFailedToInsertRow => None,
#[cfg(feature = "functions")]
2016-02-14 23:11:59 +08:00
Error::InvalidFunctionParameterType => None,
#[cfg(feature = "functions")]
2016-02-14 23:11:59 +08:00
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)
}