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("error splitting statement {1}: {0}")]
32 Split(std::io::Error, usize),
33 #[error(
35 "missing source: {local} migrations found but {history} have been applied: {msg}"
36 )]
37 MissingSource { local: i64, history: i64, msg: String },
38 #[error("inconsistent source: {msg}: {at_issue:?}")]
41 OutOfSync { at_issue: Vec<MigrationId>, msg: String },
42 #[error("invalid parameter for the operation requested: {0}")]
44 Invalid(String),
45 #[error("migration could not complete: {source}, partial report: {report}")]
47 Partial { source: BoxDynError, report: Report },
48}
49
50impl Error {
51 pub fn to_resolve_query_error<E>(e: E) -> Self
52 where
53 E: std::fmt::Display,
54 {
55 Self::ResolveQuery(e.to_string())
56 }
57
58 pub(crate) fn split_err(idx: usize) -> impl FnMut(std::io::Error) -> Self {
59 move |e| Self::Split(e, idx)
60 }
61}
62
63pub trait DatabaseError<T, E> {
72 fn tern_result(self) -> TernResult<T>;
74
75 fn void_tern_result(self) -> TernResult<()>;
77
78 fn tern_migration_result<M: Migration + ?Sized>(
81 self,
82 migration: &M,
83 ) -> TernResult<T>;
84
85 fn void_tern_migration_result<M: Migration + ?Sized>(
87 self,
88 migration: &M,
89 ) -> TernResult<()>;
90
91 fn with_report(self, report: &[MigrationResult]) -> TernResult<T>;
94}
95
96impl<T, E> DatabaseError<T, E> for Result<T, E>
97where
98 E: StdError + Send + Sync + 'static,
99{
100 fn void_tern_result(self) -> TernResult<()> {
101 match self {
102 Err(e) => Err(Error::Execute(Box::new(e))),
103 _ => Ok(()),
104 }
105 }
106
107 fn void_tern_migration_result<M: Migration + ?Sized>(
108 self,
109 migration: &M,
110 ) -> TernResult<()> {
111 match self {
112 Err(e) => Err(Error::ExecuteMigration(
113 Box::new(e),
114 migration.migration_id(),
115 migration.no_tx(),
116 )),
117 _ => Ok(()),
118 }
119 }
120
121 fn tern_result(self) -> TernResult<T> {
122 match self {
123 Ok(v) => Ok(v),
124 Err(e) => Err(Error::Execute(Box::new(e))),
125 }
126 }
127
128 fn tern_migration_result<M: Migration + ?Sized>(
129 self,
130 migration: &M,
131 ) -> TernResult<T> {
132 match self {
133 Ok(v) => Ok(v),
134 Err(e) => Err(Error::ExecuteMigration(
135 Box::new(e),
136 migration.migration_id(),
137 migration.no_tx(),
138 )),
139 }
140 }
141
142 fn with_report(self, migrations: &[MigrationResult]) -> TernResult<T> {
143 match self {
144 Ok(v) => Ok(v),
145 Err(e) => Err(Error::Partial {
146 source: Box::new(e),
147 report: Report::new(migrations.to_vec()),
148 }),
149 }
150 }
151}