1use crate::migration::{Migration, MigrationId};
3use crate::runner::{MigrationResult, Report};
4
5use std::error::Error as StdError;
6
7pub type TernResult<T> = Result<T, Error>;
9type BoxDynError = Box<dyn StdError + Send + Sync + 'static>;
10
11#[derive(Debug, thiserror::Error)]
14#[non_exhaustive]
15pub enum Error {
16 #[error("error applying migrations {0}")]
18 Execute(#[source] BoxDynError),
19 #[error("error applying migration: {{name: {1}, no_tx: {2}}}: {0}")]
21 ExecuteMigration(#[source] BoxDynError, MigrationId, bool),
22 #[error("runtime could not resolve query: {0}")]
26 ResolveQuery(String),
27 #[error("could not parse migration query: {0}")]
29 Sql(#[from] std::fmt::Error),
30 #[error("missing source: {local} migrations found but {history} have been applied: {msg}")]
32 MissingSource {
33 local: i64,
34 history: i64,
35 msg: String,
36 },
37 #[error("invalid parameter for the operation requested: {0}")]
39 Invalid(String),
40 #[error("migration could not complete: {source}, partial report: {report}")]
42 Partial { source: BoxDynError, report: Report },
43}
44
45impl Error {
46 pub fn to_resolve_query_error<E>(e: E) -> Self
47 where
48 E: std::fmt::Display,
49 {
50 Self::ResolveQuery(e.to_string())
51 }
52}
53
54pub trait DatabaseError<T, E> {
63 fn tern_result(self) -> TernResult<T>;
65
66 fn void_tern_result(self) -> TernResult<()>;
68
69 fn tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<T>;
72
73 fn void_tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<()>;
75
76 fn with_report(self, report: &[MigrationResult]) -> TernResult<T>;
79}
80
81impl<T, E> DatabaseError<T, E> for Result<T, E>
82where
83 E: StdError + Send + Sync + 'static,
84{
85 fn void_tern_result(self) -> TernResult<()> {
86 match self {
87 Err(e) => Err(Error::Execute(Box::new(e))),
88 _ => Ok(()),
89 }
90 }
91
92 fn void_tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<()> {
93 match self {
94 Err(e) => Err(Error::ExecuteMigration(
95 Box::new(e),
96 migration.migration_id(),
97 migration.no_tx(),
98 )),
99 _ => Ok(()),
100 }
101 }
102
103 fn tern_result(self) -> TernResult<T> {
104 match self {
105 Ok(v) => Ok(v),
106 Err(e) => Err(Error::Execute(Box::new(e))),
107 }
108 }
109
110 fn tern_migration_result<M: Migration + ?Sized>(self, migration: &M) -> TernResult<T> {
111 match self {
112 Ok(v) => Ok(v),
113 Err(e) => Err(Error::ExecuteMigration(
114 Box::new(e),
115 migration.migration_id(),
116 migration.no_tx(),
117 )),
118 }
119 }
120
121 fn with_report(self, migrations: &[MigrationResult]) -> TernResult<T> {
122 match self {
123 Ok(v) => Ok(v),
124 Err(e) => Err(Error::Partial {
125 source: Box::new(e),
126 report: Report::new(migrations.to_vec()),
127 }),
128 }
129 }
130}