1use std::error::Error as StdError;
2
3use crate::migration::{Migration, MigrationId};
4
5pub type TernResult<T> = Result<T, Error>;
7type BoxDynError = Box<dyn StdError + Send + Sync + 'static>;
8
9#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum Error {
14 #[error("error applying migrations {0}")]
16 Execute(#[source] BoxDynError),
17 #[error("error applying migration {{name: {1}, no_tx: {2}}}: {0}")]
19 ExecuteMigration(#[source] BoxDynError, MigrationId, bool),
20 #[error("runtime could not resolve query {0}")]
24 ResolveQuery(String),
25 #[error("could not parse migration query {0}")]
27 Sql(#[from] std::fmt::Error),
28 #[error("migration source has {0} migrations but {1} have been applied")]
30 MissingSource(i64, i64),
31}
32
33impl Error {
34 pub fn to_resolve_query_error<E>(e: E) -> Self
35 where
36 E: std::fmt::Display,
37 {
38 Self::ResolveQuery(e.to_string())
39 }
40}
41
42pub trait DatabaseError<T, E> {
45 fn tern_result(self) -> TernResult<T>;
46 fn void_tern_result(self) -> TernResult<()>;
47 fn tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<T>;
48 fn void_tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<()>;
49}
50
51impl<T, E> DatabaseError<T, E> for Result<T, E>
52where
53 E: StdError + Send + Sync + 'static,
54{
55 fn void_tern_result(self) -> TernResult<()> {
56 match self {
57 Err(e) => Err(Error::Execute(Box::new(e))),
58 _ => Ok(()),
59 }
60 }
61
62 fn void_tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<()> {
63 match self {
64 Err(e) => Err(Error::ExecuteMigration(
65 Box::new(e),
66 migration.migration_id(),
67 migration.no_tx(),
68 )),
69 _ => Ok(()),
70 }
71 }
72
73 fn tern_result(self) -> TernResult<T> {
74 match self {
75 Ok(v) => Ok(v),
76 Err(e) => Err(Error::Execute(Box::new(e))),
77 }
78 }
79
80 fn tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<T> {
81 match self {
82 Ok(v) => Ok(v),
83 Err(e) => Err(Error::ExecuteMigration(
84 Box::new(e),
85 migration.migration_id(),
86 migration.no_tx(),
87 )),
88 }
89 }
90}