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()
    }
}