use std::error::Error as StdError;
use std::fmt::{self, Debug, Display, Formatter};
pub(crate) use sqlx_core::error::*;
use std::borrow::Cow;
use std::ops::Range;
pub struct XuguDatabaseError {
code: String,
message: String,
}
impl Debug for XuguDatabaseError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("XuguDatabaseError")
.field("code", &self.code)
.field("message", &self.message)
.finish()
}
}
impl Display for XuguDatabaseError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(code) = &self.code() {
write!(f, "({}): {}", code, self.message())
} else {
write!(f, "{}", self.message())
}
}
}
impl XuguDatabaseError {
pub fn from_str(err: &str) -> Self {
let mut code_range: Range<usize> = 0..0;
let mut message_range = 0..err.len();
if err.starts_with("[E") {
if let Some(pos) = err.find(']') {
code_range = 1..pos;
message_range = pos + 1..err.len();
}
}
XuguDatabaseError {
code: err[code_range].into(),
message: err[message_range].trim().into(),
}
}
fn get_err_code(code: &str) -> i32 {
let cleaned = code.trim_matches(|c| c == '[' || c == ']');
if let Some(e_pos) = cleaned.find('E') {
let after_e = &cleaned[e_pos + 1..];
if let Some(l_pos) = after_e.find('L') {
let numeric_part = &after_e[..l_pos];
numeric_part.parse().unwrap_or(0)
} else {
after_e.parse().unwrap_or(0)
}
} else {
cleaned.parse().unwrap_or(0)
}
}
}
impl StdError for XuguDatabaseError {}
impl DatabaseError for XuguDatabaseError {
#[inline]
fn message(&self) -> &str {
self.message.as_str()
}
#[inline]
fn code(&self) -> Option<Cow<'_, str>> {
Some(Cow::from(&self.code))
}
#[doc(hidden)]
fn as_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
self
}
#[doc(hidden)]
fn as_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
self
}
#[doc(hidden)]
fn into_error(self: Box<Self>) -> Box<dyn StdError + Send + Sync + 'static> {
self
}
fn kind(&self) -> ErrorKind {
let err_code = Self::get_err_code(&self.code);
match err_code {
13001 => ErrorKind::UniqueViolation,
13005 => ErrorKind::ForeignKeyViolation,
13009 => ErrorKind::NotNullViolation,
13004 | 13008 => ErrorKind::CheckViolation,
_ => ErrorKind::Other,
}
}
}