1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
//! Module defining migration trait
#![cfg_attr(
feature = "sqlite",
doc = r##"
To create own implement migration trait for type
### Example
```rust,no_run
use sqlx_migrator::error::Error;
use sqlx_migrator::migration::Migration;
use sqlx_migrator::operation::Operation;
use sqlx_migrator::sqlx::Sqlite;
struct ExampleMigration;
impl Migration<Sqlite> for ExampleMigration {
fn app(&self) -> &str {
"example"
}
fn name(&self) -> &str {
"first_migration"
}
fn parents(&self) -> Vec<Box<dyn Migration<Sqlite>>> {
vec![]
}
fn operations(&self) -> Vec<Box<dyn Operation<Sqlite>>> {
vec![]
}
fn replaces(&self) -> Vec<Box<dyn Migration<Sqlite>>> {
vec![]
}
fn run_before(&self) -> Vec<Box<dyn Migration<Sqlite>>> {
vec![]
}
fn is_atomic(&self) -> bool {
true
}
}
```
"##
)]
use std::hash::Hash;
use crate::operation::Operation;
/// Trait for migration
#[allow(clippy::module_name_repetitions)]
pub trait Migration<DB, State = ()>: Send + Sync {
/// Migration app name. Can be name of folder or library where migration is
/// located
fn app(&self) -> &str;
/// Migration name. Can be file name without extension
fn name(&self) -> &str;
/// Parents of migration (migrations that should be applied before this
/// migration)
fn parents(&self) -> Vec<Box<dyn Migration<DB, State>>>;
/// Operation performed for migration (create, drop, etc.). Migration can
/// contains multiple operation within each other which are interrelated
fn operations(&self) -> Vec<Box<dyn Operation<DB, State>>>;
/// Replace certain migrations. If any one of listed migration is applied
/// than migration will not be applied else migration will apply/revert
/// instead of applying/reverting those migration.
fn replaces(&self) -> Vec<Box<dyn Migration<DB, State>>> {
vec![]
}
/// Run before(for applying)/after(for reverting) certain migration. This
/// can be helpful in condition where other library migration need to be
/// applied after this migration or reverted before this migration
fn run_before(&self) -> Vec<Box<dyn Migration<DB, State>>> {
vec![]
}
/// Whether migration is atomic or not. By default it is atomic so this
/// function returns `true`. If you make migration non atomic all its
/// operation will be non atomic if any operation needs to be atomic it is
/// recommended to split migration so one migration will have atomic
/// operation where as another have non atomic operation
fn is_atomic(&self) -> bool {
true
}
/// Whether migration is virtual or not. By default migration are not
/// virtual. If migration is virtual than it expects another migration with
/// same app and name present inside migration list which is not virtual.
/// For virtual migration all other methods gets ignored since it is
/// reference to actual migration instead of actual migration
fn is_virtual(&self) -> bool {
false
}
}
impl<DB, State> PartialEq for dyn Migration<DB, State> {
fn eq(&self, other: &Self) -> bool {
self.app() == other.app() && self.name() == other.name()
}
}
impl<DB, State> Eq for dyn Migration<DB, State> {}
impl<DB, State> Hash for dyn Migration<DB, State> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.app().hash(state);
self.name().hash(state);
}
}
impl<DB, A, N> Migration<DB> for (A, N)
where
A: AsRef<str> + Send + Sync,
N: AsRef<str> + Send + Sync,
{
fn app(&self) -> &str {
self.0.as_ref()
}
fn name(&self) -> &str {
self.1.as_ref()
}
fn parents(&self) -> Vec<Box<dyn Migration<DB, ()>>> {
vec![]
}
fn operations(&self) -> Vec<Box<dyn Operation<DB, ()>>> {
vec![]
}
fn is_virtual(&self) -> bool {
true
}
}
/// Migration struct created from sql table. Struct contains 4 fields which maps
/// to `id`, `app`, `name`, `applied_time` sql fields. It is used to list
/// applied migrations
#[derive(sqlx::FromRow, Clone)]
pub struct AppliedMigrationSqlRow {
id: i32,
app: String,
name: String,
applied_time: String,
}
impl AppliedMigrationSqlRow {
#[cfg(test)]
pub(crate) fn new(id: i32, app: &str, name: &str) -> Self {
Self {
id,
app: app.to_string(),
name: name.to_string(),
applied_time: String::new(),
}
}
}
impl AppliedMigrationSqlRow {
/// Return id value present on database
#[must_use]
pub fn id(&self) -> i32 {
self.id
}
/// Return migration applied time
#[must_use]
pub fn applied_time(&self) -> &str {
&self.applied_time
}
}
impl<DB, State> PartialEq<Box<dyn Migration<DB, State>>> for AppliedMigrationSqlRow {
fn eq(&self, other: &Box<dyn Migration<DB, State>>) -> bool {
self.app == other.app() && self.name == other.name()
}
}