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
//! Operation module
#![cfg_attr(
    feature = "sqlite",
    doc = r##"
To create own operation implement trait for type

### Example
```rust,no_run
use sqlx_migrator::error::Error;
use sqlx_migrator::operation::Operation;
use sqlx_migrator::sqlx::Sqlite;

struct ExampleOperation;

#[async_trait::async_trait]
impl Operation<Sqlite> for ExampleOperation {
    async fn up(
        &self,
        connection: &mut sqlx::SqliteConnection,
        state: &(),
    ) -> Result<(), Error> {
        // Do some operations
        Ok(())
    }

    // By default operation is irreversible and cannot be reversed if you want to support
    // reverse of migration than add down function as well
    async fn down(
        &self,
        connection: &mut sqlx::SqliteConnection,
        state: &(),
    ) -> Result<(), Error> {
        // Do some operations
        Ok(())
    }
}
```
"##
)]

use crate::error::Error;

/// Trait for operation
#[allow(clippy::module_name_repetitions)]
#[async_trait::async_trait]
pub trait Operation<DB, State = ()>: Send + Sync
where
    DB: sqlx::Database,
    State: Send + Sync,
{
    /// Up command to be executed during migration apply
    async fn up(
        &self,
        connection: &mut <DB as sqlx::Database>::Connection,
        state: &State,
    ) -> Result<(), Error>;

    /// Down command to be executed during migration rollback. If it is not
    /// implemented than operation is irreversible operation.
    async fn down(
        &self,
        connection: &mut <DB as sqlx::Database>::Connection,
        state: &State,
    ) -> Result<(), Error> {
        let _connection = connection;
        let _state = state;
        return Err(Error::IrreversibleOperation);
    }

    /// Whether up operation is destructible or not. If operation is
    /// destructible than user should answer before running migration through
    /// cli. By default up operation are false. Down operation are always
    /// destructible and cannot be changed
    fn is_destructible(&self) -> bool {
        false
    }
}

#[cfg(all(
    any(feature = "postgres", feature = "mysql", feature = "sqlite"),
    feature = "any"
))]
#[async_trait::async_trait]
impl<U, D> Operation<sqlx::Any> for (U, D)
where
    U: AsRef<str> + Send + Sync,
    D: AsRef<str> + Send + Sync,
{
    async fn up(&self, connection: &mut sqlx::AnyConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.0.as_ref()).execute(connection).await?;
        Ok(())
    }

    async fn down(&self, connection: &mut sqlx::AnyConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.1.as_ref()).execute(connection).await?;
        Ok(())
    }
}

#[cfg(feature = "mysql")]
#[async_trait::async_trait]
impl<U, D> Operation<sqlx::MySql> for (U, D)
where
    U: AsRef<str> + Send + Sync,
    D: AsRef<str> + Send + Sync,
{
    async fn up(&self, connection: &mut sqlx::MySqlConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.0.as_ref()).execute(connection).await?;
        Ok(())
    }

    async fn down(&self, connection: &mut sqlx::MySqlConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.1.as_ref()).execute(connection).await?;
        Ok(())
    }
}

#[cfg(feature = "postgres")]
#[async_trait::async_trait]
impl<U, D> Operation<sqlx::Postgres> for (U, D)
where
    U: AsRef<str> + Send + Sync,
    D: AsRef<str> + Send + Sync,
{
    async fn up(&self, connection: &mut sqlx::PgConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.0.as_ref()).execute(connection).await?;
        Ok(())
    }

    async fn down(&self, connection: &mut sqlx::PgConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.1.as_ref()).execute(connection).await?;
        Ok(())
    }
}

#[cfg(feature = "sqlite")]
#[async_trait::async_trait]
impl<U, D> Operation<sqlx::Sqlite> for (U, D)
where
    U: AsRef<str> + Send + Sync,
    D: AsRef<str> + Send + Sync,
{
    async fn up(&self, connection: &mut sqlx::SqliteConnection, _state: &()) -> Result<(), Error> {
        sqlx::query(self.0.as_ref()).execute(connection).await?;
        Ok(())
    }

    async fn down(
        &self,
        connection: &mut sqlx::SqliteConnection,
        _state: &(),
    ) -> Result<(), Error> {
        sqlx::query(self.1.as_ref()).execute(connection).await?;
        Ok(())
    }
}