diesel_migrations/
embedded_migrations.rs
1use std::fmt::Display;
2
3use crate::errors::RunMigrationsError;
4use crate::file_based_migrations::{DieselMigrationName, TomlMetadataWrapper};
5use crate::MigrationError;
6use diesel::backend::Backend;
7use diesel::migration::{Migration, MigrationName, MigrationSource, MigrationVersion, Result};
8
9#[allow(missing_copy_implementations)]
14pub struct EmbeddedMigrations {
15 migrations: &'static [EmbeddedMigration],
16}
17
18impl EmbeddedMigrations {
19 #[doc(hidden)]
20 pub const fn new(migrations: &'static [EmbeddedMigration]) -> Self {
21 Self { migrations }
22 }
23}
24
25impl<DB: Backend> MigrationSource<DB> for EmbeddedMigrations {
26 fn migrations(&self) -> Result<Vec<Box<dyn Migration<DB>>>> {
27 Ok(self
28 .migrations
29 .iter()
30 .map(|m| Box::new(m) as Box<dyn Migration<DB>>)
31 .collect())
32 }
33}
34
35#[doc(hidden)]
36pub struct EmbeddedMigration {
37 up: &'static str,
38 down: Option<&'static str>,
39 name: EmbeddedName,
40 metadata: TomlMetadataWrapper,
41}
42
43impl EmbeddedMigration {
44 #[doc(hidden)]
45 pub const fn new(
46 up: &'static str,
47 down: Option<&'static str>,
48 name: EmbeddedName,
49 metadata: TomlMetadataWrapper,
50 ) -> Self {
51 Self {
52 up,
53 down,
54 name,
55 metadata,
56 }
57 }
58}
59
60#[derive(Clone, Copy)]
61#[doc(hidden)]
62pub struct EmbeddedName {
63 name: &'static str,
64}
65
66impl EmbeddedName {
67 #[doc(hidden)]
68 pub const fn new(name: &'static str) -> Self {
69 Self { name }
70 }
71}
72
73impl MigrationName for EmbeddedName {
74 fn version(&self) -> MigrationVersion {
75 migrations_internals::version_from_string(self.name)
76 .expect(
77 "This name contains a valid version. We checked this at compile time by our macro",
78 )
79 .into()
80 }
81}
82
83impl Display for EmbeddedName {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 write!(f, "{}", self.name)
86 }
87}
88
89impl<DB: Backend> Migration<DB> for &EmbeddedMigration {
90 fn run(&self, conn: &mut dyn diesel::connection::BoxableConnection<DB>) -> Result<()> {
91 Ok(conn.batch_execute(self.up).map_err(|e| {
92 let name = DieselMigrationName::from_name(self.name.name)
93 .expect("We have a valid name here, we checked this in `embed_migration!`");
94 RunMigrationsError::QueryError(name, e)
95 })?)
96 }
97
98 fn revert(&self, conn: &mut dyn diesel::connection::BoxableConnection<DB>) -> Result<()> {
99 match self.down {
100 Some(down) => Ok(conn.batch_execute(down).map_err(|e| {
101 let name = DieselMigrationName::from_name(self.name.name)
102 .expect("We have a valid name here, we checked this in `embed_migration!`");
103 RunMigrationsError::QueryError(name, e)
104 })?),
105 None => Err(MigrationError::NoMigrationRevertFile.into()),
106 }
107 }
108
109 fn metadata(&self) -> &dyn diesel::migration::MigrationMetadata {
110 &self.metadata as &dyn diesel::migration::MigrationMetadata
111 }
112
113 fn name(&self) -> &dyn MigrationName {
114 &self.name
115 }
116}