1use std::any::type_name;
2use std::io;
3
4use deadpool_sync::InteractError;
5use thiserror::Error;
6
7#[derive(Debug, Error)]
12pub enum SchemaVerificationError {
13 #[error("failed to create in-memory reference database")]
14 InMemoryDbCreation(#[source] diesel::ConnectionError),
15 #[error("failed to apply migrations to reference database")]
16 MigrationApplication(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
17 #[error("failed to extract schema from database")]
18 SchemaExtraction(#[source] diesel::result::Error),
19 #[error(
20 "schema mismatch: expected {expected_count} objects, found {actual_count} \
21 ({missing_count} missing, {extra_count} unexpected)"
22 )]
23 Mismatch {
24 expected_count: usize,
25 actual_count: usize,
26 missing_count: usize,
27 extra_count: usize,
28 },
29}
30
31#[derive(Debug, Error)]
35pub enum DatabaseError {
36 #[error("SQLite pool interaction failed: {0}")]
37 InteractError(String),
38 #[error("setup deadpool connection pool failed")]
39 ConnectionPoolObtainError(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
40 #[error("conversion from SQL to rust type {to} failed")]
41 ConversionSqlToRust {
42 #[source]
43 inner: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
44 to: &'static str,
45 },
46 #[error(transparent)]
47 Diesel(#[from] diesel::result::Error),
48 #[error("schema verification failed")]
49 SchemaVerification(#[from] SchemaVerificationError),
50 #[error("I/O error")]
51 Io(#[from] io::Error),
52 #[error("pool build error")]
53 PoolBuild(#[from] deadpool::managed::BuildError),
54 #[error("Setup deadpool connection pool failed")]
55 Pool(#[from] deadpool::managed::PoolError<deadpool_diesel::Error>),
56}
57
58impl DatabaseError {
59 pub fn interact(msg: &(impl ToString + ?Sized), e: &InteractError) -> Self {
70 let msg = msg.to_string();
71 Self::InteractError(format!("{msg} failed: {e:?}"))
72 }
73
74 pub fn conversiont_from_sql<RT, E, MaybeE>(err: MaybeE) -> DatabaseError
76 where
77 MaybeE: Into<Option<E>>,
78 E: std::error::Error + Send + Sync + 'static,
79 {
80 DatabaseError::ConversionSqlToRust {
81 inner: err.into().map(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync>),
82 to: type_name::<RT>(),
83 }
84 }
85
86 pub fn deserialization(
90 context: &'static str,
91 source: impl std::error::Error + Send + Sync + 'static,
92 ) -> Self {
93 Self::ConversionSqlToRust {
94 inner: Some(Box::new(source)),
95 to: context,
96 }
97 }
98}