1use crate::backend::Backend;
4use crate::connection::{BoxableConnection, Connection};
5use crate::deserialize::{FromSql, FromSqlRow};
6use crate::expression::AsExpression;
7use crate::result::QueryResult;
8use crate::serialize::ToSql;
9use crate::sql_types::Text;
10use std::borrow::Cow;
11use std::error::Error;
12use std::fmt::Display;
13
14pub type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
17
18#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, FromSqlRow, AsExpression)]
24#[diesel(sql_type = Text)]
25pub struct MigrationVersion<'a>(Cow<'a, str>);
26
27impl MigrationVersion<'_> {
28 pub fn as_owned(&self) -> MigrationVersion<'static> {
31 MigrationVersion(Cow::Owned(self.0.as_ref().to_owned()))
32 }
33}
34
35impl<DB> FromSql<Text, DB> for MigrationVersion<'_>
36where
37 String: FromSql<Text, DB>,
38 DB: Backend,
39{
40 fn from_sql(bytes: DB::RawValue<'_>) -> crate::deserialize::Result<Self> {
41 let s = String::from_sql(bytes)?;
42 Ok(Self(Cow::Owned(s)))
43 }
44}
45
46impl<'a, DB> ToSql<Text, DB> for MigrationVersion<'a>
47where
48 Cow<'a, str>: ToSql<Text, DB>,
49 DB: Backend,
50{
51 fn to_sql<'b>(
52 &'b self,
53 out: &mut crate::serialize::Output<'b, '_, DB>,
54 ) -> crate::serialize::Result {
55 self.0.to_sql(out)
56 }
57}
58
59impl From<String> for MigrationVersion<'_> {
60 fn from(s: String) -> Self {
61 MigrationVersion(Cow::Owned(s))
62 }
63}
64
65impl<'a> From<&'a str> for MigrationVersion<'a> {
66 fn from(s: &'a str) -> Self {
67 MigrationVersion(Cow::Borrowed(s))
68 }
69}
70
71impl<'a> From<&'a String> for MigrationVersion<'a> {
72 fn from(s: &'a String) -> Self {
73 MigrationVersion(Cow::Borrowed(s))
74 }
75}
76
77impl Display for MigrationVersion<'_> {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 f.write_str(self.0.as_ref())
80 }
81}
82
83pub trait MigrationName: Display {
90 fn version(&self) -> MigrationVersion<'_>;
92}
93
94pub trait Migration<DB: Backend> {
96 fn run(&self, conn: &mut dyn BoxableConnection<DB>) -> Result<()>;
98
99 fn revert(&self, conn: &mut dyn BoxableConnection<DB>) -> Result<()>;
101
102 fn metadata(&self) -> &dyn MigrationMetadata;
104
105 fn name(&self) -> &dyn MigrationName;
112}
113
114pub trait MigrationMetadata {
123 fn run_in_transaction(&self) -> bool {
131 true
132 }
133}
134
135pub trait MigrationSource<DB: Backend> {
138 fn migrations(&self) -> Result<Vec<Box<dyn Migration<DB>>>>;
141}
142
143impl<DB: Backend> Migration<DB> for Box<dyn Migration<DB> + '_> {
144 fn run(&self, conn: &mut dyn BoxableConnection<DB>) -> Result<()> {
145 (**self).run(conn)
146 }
147
148 fn revert(&self, conn: &mut dyn BoxableConnection<DB>) -> Result<()> {
149 (**self).revert(conn)
150 }
151
152 fn metadata(&self) -> &dyn MigrationMetadata {
153 (**self).metadata()
154 }
155
156 fn name(&self) -> &dyn MigrationName {
157 (**self).name()
158 }
159}
160
161impl<DB: Backend> Migration<DB> for &dyn Migration<DB> {
162 fn run(&self, conn: &mut dyn BoxableConnection<DB>) -> Result<()> {
163 (**self).run(conn)
164 }
165
166 fn revert(&self, conn: &mut dyn BoxableConnection<DB>) -> Result<()> {
167 (**self).revert(conn)
168 }
169
170 fn metadata(&self) -> &dyn MigrationMetadata {
171 (**self).metadata()
172 }
173
174 fn name(&self) -> &dyn MigrationName {
175 (**self).name()
176 }
177}
178
179pub const CREATE_MIGRATIONS_TABLE: &str = include_str!("setup_migration_table.sql");
182
183pub trait MigrationConnection: Connection {
187 fn setup(&mut self) -> QueryResult<usize>;
199}
200
201#[cfg(feature = "postgres")]
202impl MigrationConnection for crate::pg::PgConnection {
203 fn setup(&mut self) -> QueryResult<usize> {
204 use crate::RunQueryDsl;
205 crate::sql_query(CREATE_MIGRATIONS_TABLE).execute(self)
206 }
207}
208
209#[cfg(feature = "mysql")]
210impl MigrationConnection for crate::mysql::MysqlConnection {
211 fn setup(&mut self) -> QueryResult<usize> {
212 use crate::RunQueryDsl;
213 crate::sql_query(CREATE_MIGRATIONS_TABLE).execute(self)
214 }
215}
216
217#[cfg(feature = "sqlite")]
218impl MigrationConnection for crate::sqlite::SqliteConnection {
219 fn setup(&mut self) -> QueryResult<usize> {
220 use crate::RunQueryDsl;
221 crate::sql_query(CREATE_MIGRATIONS_TABLE).execute(self)
222 }
223}