cronback_lib/database/
errors.rs1use sqlx::postgres::PgDatabaseError;
2use sqlx::sqlite::SqliteError;
3use thiserror::Error;
4
5const SQLITE_UNIQUE_CONSTRAINT_FAILED_CODE: &str = "2067";
6const POSTGRES_UNIQUE_CONSTRAINT_FAILED_CODE: &str = "23505";
7
8#[derive(Error, Debug)]
9pub enum DatabaseError {
10 #[error("serialization error: {0}")]
11 Parse(#[from] serde_json::Error),
12
13 #[error("constraint error: violated unique constraint")]
14 DuplicateRecord,
15
16 #[error("database error: {0}")]
17 DB(sea_orm::DbErr),
18}
19
20impl From<sea_orm::DbErr> for DatabaseError {
21 fn from(value: sea_orm::DbErr) -> Self {
22 match value {
23 | sea_orm::DbErr::Exec(sea_orm::RuntimeErr::SqlxError(
24 sqlx::Error::Database(db_err),
25 )) if is_duplicate_record_error(db_err.as_ref()) => {
26 DatabaseError::DuplicateRecord
27 }
28 | _ => DatabaseError::DB(value),
29 }
30 }
31}
32
33fn is_duplicate_record_error(db_err: &dyn sqlx::error::DatabaseError) -> bool {
34 if db_err.try_downcast_ref::<SqliteError>().is_some() {
35 return db_err.code().map(|a| a.to_string())
36 == Some(SQLITE_UNIQUE_CONSTRAINT_FAILED_CODE.to_string());
37 }
38 if db_err.try_downcast_ref::<PgDatabaseError>().is_some() {
39 return db_err.code().map(|a| a.to_string())
40 == Some(POSTGRES_UNIQUE_CONSTRAINT_FAILED_CODE.to_string());
41 }
42 false
43}