tern_core/
error.rs

1use std::error::Error as StdError;
2
3use crate::migration::{Migration, MigrationId};
4
5/// Alias for a result whose error type is [`Error`].
6pub type TernResult<T> = Result<T, Error>;
7type BoxDynError = Box<dyn StdError + Send + Sync + 'static>;
8
9/// All the ways the lifecycle of applying migrations
10/// can end in failure.
11#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum Error {
14    /// An error that came from applying migrations.
15    #[error("error applying migrations {0}")]
16    Execute(#[source] BoxDynError),
17    /// Error from one migration.
18    #[error("error applying migration {{name: {1}, no_tx: {2}}}: {0}")]
19    ExecuteMigration(#[source] BoxDynError, MigrationId, bool),
20    /// An error resolving the query before applying.
21    /// Can be used as a fallthrough to map arbitrary error types to when
22    /// implementing `QueryBuilder`.
23    #[error("runtime could not resolve query {0}")]
24    ResolveQuery(String),
25    /// Error processing a migration source.
26    #[error("could not parse migration query {0}")]
27    Sql(#[from] std::fmt::Error),
28    /// Local migration source has fewer migrations than the history table.
29    #[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
42/// Converting a result with a generic `std::error::Error` to one with this
43/// crate's error type.
44pub 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}