diff --git a/sqlx-core/src/error.rs b/sqlx-core/src/error.rs index 8e147c8b..91640d4c 100644 --- a/sqlx-core/src/error.rs +++ b/sqlx-core/src/error.rs @@ -2,6 +2,10 @@ use std::borrow::Cow; use std::error::Error as StdError; use std::fmt::{self, Display, Formatter}; +mod database; + +pub use database::DatabaseError; + pub type Result = std::result::Result; #[derive(Debug)] @@ -9,6 +13,8 @@ pub type Result = std::result::Result; pub enum Error { Configuration { message: Cow<'static, str>, source: Option> }, + Connect(Box), + Network(std::io::Error), } @@ -30,14 +36,16 @@ impl Error { impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Self::Network(source) => write!(f, "network: {}", source), + Self::Network(source) => write!(f, "{}", source), + + Self::Connect(source) => write!(f, "{}", source), Self::Configuration { message, source: None } => { - write!(f, "configuration: {}", message) + write!(f, "{}", message) } Self::Configuration { message, source: Some(source) } => { - write!(f, "configuration: {}: {}", message, source) + write!(f, "{}: {}", message, source) } } } @@ -57,12 +65,12 @@ impl StdError for Error { impl From for Error { fn from(error: std::io::Error) -> Self { - Error::Network(error) + Self::Network(error) } } impl From for Error { fn from(error: std::io::ErrorKind) -> Self { - Error::Network(error.into()) + Self::Network(error.into()) } } diff --git a/sqlx-core/src/error/database.rs b/sqlx-core/src/error/database.rs new file mode 100644 index 00000000..02db4c8e --- /dev/null +++ b/sqlx-core/src/error/database.rs @@ -0,0 +1,13 @@ +use std::error::Error as StdError; + +/// `DatabaseError` is a trait representing an error that was returned from +/// the database. +/// +/// Provides abstract access to information returned from the database about +/// the error. +/// +#[allow(clippy::module_name_repetitions)] +pub trait DatabaseError: 'static + StdError + Send + Sync { + /// Returns the primary, human-readable error message. + fn message(&self) -> &str; +} diff --git a/sqlx-core/src/lib.rs b/sqlx-core/src/lib.rs index 9cfc4701..dbf35892 100644 --- a/sqlx-core/src/lib.rs +++ b/sqlx-core/src/lib.rs @@ -41,7 +41,7 @@ pub mod blocking; pub use connection::Connection; pub use database::{Database, HasOutput}; -pub use error::{Error, Result}; +pub use error::{Error, Result, DatabaseError}; pub use options::ConnectOptions; #[cfg(feature = "actix")] pub use runtime::Actix; diff --git a/sqlx-mysql/src/error.rs b/sqlx-mysql/src/error.rs new file mode 100644 index 00000000..a8de4e14 --- /dev/null +++ b/sqlx-mysql/src/error.rs @@ -0,0 +1,28 @@ +use std::error::Error as StdError; +use std::fmt::{self, Display, Formatter}; + +use sqlx_core::DatabaseError; + +use crate::protocol::ErrPacket; + +/// An error returned from the MySQL database server. +#[allow(clippy::module_name_repetitions)] +#[derive(Debug)] +pub struct MySqlDatabaseError(pub(crate) ErrPacket); + +impl DatabaseError for MySqlDatabaseError { + fn message(&self) -> &str { + &self.0.error_message + } +} + +impl Display for MySqlDatabaseError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match &self.0.sql_state { + Some(state) => write!(f, "{} ({}): {}", self.0.error_code, state, self.message()), + None => write!(f, "{}: {}", self.0.error_code, self.message()), + } + } +} + +impl StdError for MySqlDatabaseError {}