1#[cfg(feature = "sqlx-dep")]
2pub use sqlx::error::Error as SqlxError;
3
4#[cfg(feature = "sqlx-mysql")]
5pub use sqlx::mysql::MySqlDatabaseError as SqlxMySqlError;
6
7#[cfg(feature = "sqlx-postgres")]
8pub use sqlx::postgres::PgDatabaseError as SqlxPostgresError;
9
10#[cfg(feature = "sqlx-sqlite")]
11pub use sqlx::sqlite::SqliteError as SqlxSqliteError;
12
13use thiserror::Error;
14
15#[derive(Error, Debug)]
17pub enum DbErr {
18 #[error("Failed to acquire connection from pool: {0}")]
20 ConnectionAcquire(#[source] ConnAcquireErr),
21 #[error("Error converting `{from}` into `{into}`: {source}")]
23 TryIntoErr {
24 from: &'static str,
26 into: &'static str,
28 source: Box<dyn std::error::Error + Send + Sync>,
30 },
31 #[error("Connection Error: {0}")]
33 Conn(#[source] RuntimeErr),
34 #[error("Execution Error: {0}")]
36 Exec(#[source] RuntimeErr),
37 #[error("Query Error: {0}")]
39 Query(#[source] RuntimeErr),
40 #[error("Type '{0}' cannot be converted from u64")]
42 ConvertFromU64(&'static str),
43 #[error("Failed to unpack last_insert_id")]
45 UnpackInsertId,
46 #[error("Failed to get primary key from model")]
49 UpdateGetPrimaryKey,
50 #[error("RecordNotFound Error: {0}")]
52 RecordNotFound(String),
53 #[error("Attribute {0} is NotSet")]
55 AttrNotSet(String),
56 #[error("Custom Error: {0}")]
58 Custom(String),
59 #[error("Type Error: {0}")]
61 Type(String),
62 #[error("Json Error: {0}")]
64 Json(String),
65 #[error("Migration Error: {0}")]
67 Migration(String),
68 #[error("None of the records are inserted")]
71 RecordNotInserted,
72 #[error("None of the records are updated")]
75 RecordNotUpdated,
76}
77
78#[derive(Error, Debug, PartialEq, Eq)]
80pub enum ConnAcquireErr {
81 #[error("Connection pool timed out")]
83 Timeout,
84 #[error("Connection closed")]
86 ConnectionClosed,
87}
88
89#[derive(Error, Debug)]
91pub enum RuntimeErr {
92 #[cfg(feature = "sqlx-dep")]
94 #[error("{0}")]
95 SqlxError(#[source] sqlx::error::Error),
96 #[error("{0}")]
98 Internal(String),
99}
100
101impl PartialEq for DbErr {
102 fn eq(&self, other: &Self) -> bool {
103 self.to_string() == other.to_string()
104 }
105}
106
107impl Eq for DbErr {}
108
109#[derive(Error, Debug)]
111#[error("Failed to match \"{0}\" as Column")]
112pub struct ColumnFromStrErr(pub String);
113
114#[allow(dead_code)]
115pub(crate) fn conn_err<T>(s: T) -> DbErr
116where
117 T: ToString,
118{
119 DbErr::Conn(RuntimeErr::Internal(s.to_string()))
120}
121
122#[allow(dead_code)]
123pub(crate) fn exec_err<T>(s: T) -> DbErr
124where
125 T: ToString,
126{
127 DbErr::Exec(RuntimeErr::Internal(s.to_string()))
128}
129
130#[allow(dead_code)]
131pub(crate) fn query_err<T>(s: T) -> DbErr
132where
133 T: ToString,
134{
135 DbErr::Query(RuntimeErr::Internal(s.to_string()))
136}
137
138#[allow(dead_code)]
139pub(crate) fn type_err<T>(s: T) -> DbErr
140where
141 T: ToString,
142{
143 DbErr::Type(s.to_string())
144}
145
146#[allow(dead_code)]
147pub(crate) fn json_err<T>(s: T) -> DbErr
148where
149 T: ToString,
150{
151 DbErr::Json(s.to_string())
152}
153
154#[derive(Error, Debug, Clone, PartialEq, Eq)]
156#[non_exhaustive]
157pub enum SqlErr {
158 #[error("Unique Constraint Violated: {0}")]
160 UniqueConstraintViolation(String),
161 #[error("Foreign Key Constraint Violated: {0}")]
163 ForeignKeyConstraintViolation(String),
164}
165
166#[allow(dead_code)]
167impl DbErr {
168 pub fn sql_err(&self) -> Option<SqlErr> {
170 #[cfg(any(
171 feature = "sqlx-mysql",
172 feature = "sqlx-postgres",
173 feature = "sqlx-sqlite"
174 ))]
175 {
176 use std::ops::Deref;
177 if let DbErr::Exec(RuntimeErr::SqlxError(sqlx::Error::Database(e)))
178 | DbErr::Query(RuntimeErr::SqlxError(sqlx::Error::Database(e))) = self
179 {
180 let error_code = e.code().unwrap_or_default();
181 let _error_code_expanded = error_code.deref();
182 #[cfg(feature = "sqlx-mysql")]
183 if e.try_downcast_ref::<sqlx::mysql::MySqlDatabaseError>()
184 .is_some()
185 {
186 let error_number = e
187 .try_downcast_ref::<sqlx::mysql::MySqlDatabaseError>()?
188 .number();
189 match error_number {
190 1022 | 1062 | 1169 | 1586 => {
195 return Some(SqlErr::UniqueConstraintViolation(e.message().into()))
196 }
197 1216 | 1217 | 1451 | 1452 | 1557 | 1761 | 1762 => {
205 return Some(SqlErr::ForeignKeyConstraintViolation(e.message().into()))
206 }
207 _ => return None,
208 }
209 }
210 #[cfg(feature = "sqlx-postgres")]
211 if e.try_downcast_ref::<sqlx::postgres::PgDatabaseError>()
212 .is_some()
213 {
214 match _error_code_expanded {
215 "23505" => {
216 return Some(SqlErr::UniqueConstraintViolation(e.message().into()))
217 }
218 "23503" => {
219 return Some(SqlErr::ForeignKeyConstraintViolation(e.message().into()))
220 }
221 _ => return None,
222 }
223 }
224 #[cfg(feature = "sqlx-sqlite")]
225 if e.try_downcast_ref::<sqlx::sqlite::SqliteError>().is_some() {
226 match _error_code_expanded {
227 "1555" | "2067" => {
230 return Some(SqlErr::UniqueConstraintViolation(e.message().into()))
231 }
232 "787" => {
233 return Some(SqlErr::ForeignKeyConstraintViolation(e.message().into()))
234 }
235 _ => return None,
236 }
237 }
238 }
239 }
240 None
241 }
242}