sqlx_migrator/
operation.rs

1//! Module for defining the [`Operation`] trait
2//!
3//! This module provides the [`Operation`] trait, allowing users to define
4//! database operations that can be executed as part of a migration process.
5//! These operations can be applied (`up`) or optionally reverted (`down`).
6#![cfg_attr(
7    feature = "sqlite",
8    doc = "
9To create own operation implement trait for type
10
11### Example
12```rust,no_run
13use sqlx_migrator::error::Error;
14use sqlx_migrator::operation::Operation;
15use sqlx::Sqlite;
16
17struct ExampleOperation;
18
19#[async_trait::async_trait]
20impl Operation<Sqlite> for ExampleOperation {
21    async fn up(
22        &self,
23        connection: &mut sqlx::SqliteConnection,
24    ) -> Result<(), Error> {
25        // Do some operations
26        Ok(())
27    }
28
29    // By default operation is irreversible and cannot be reversed if you want to support
30    // reverse of migration than add down function as well
31    async fn down(
32        &self,
33        connection: &mut sqlx::SqliteConnection,
34    ) -> Result<(), Error> {
35        // Do some operations
36        Ok(())
37    }
38}
39```
40"
41)]
42
43use sqlx::Database;
44
45use crate::error::Error;
46
47/// Trait for defining a database operation.
48///
49/// An Operation represents action that can be applied to or reverted from a
50/// database during a migration. Each operation can have an up method for
51/// applying the change and an optional down method for rolling it back.
52///
53/// Operations can also specify whether they are destructible meaning that they
54/// require user confirmation before being applied, due to potential data loss
55/// or irreversible changes
56#[async_trait::async_trait]
57pub trait Operation<DB>: Send + Sync
58where
59    DB: Database,
60{
61    /// The up method executes the operation when applying the migration.
62    ///
63    /// This method is called when the migration is being applied to the
64    /// database. Implement this method to define the changes you want to
65    /// apply.
66    async fn up(&self, connection: &mut <DB as Database>::Connection) -> Result<(), Error>;
67
68    /// The down method reverses the operation when rolling back the
69    /// migration.
70    ///
71    /// This method is called when the migration is being rolled back. Implement
72    /// this method if you want to make the operation reversible. If not
73    /// implemented, the operation is considered irreversible.
74    async fn down(&self, connection: &mut <DB as Database>::Connection) -> Result<(), Error> {
75        let _connection = connection;
76        return Err(Error::IrreversibleOperation);
77    }
78
79    /// Indicates whether the `up` operation is destructible.
80    ///
81    /// If the operation is destructible, the user will be prompted for
82    /// confirmation before running the migration via the CLI, due to the
83    /// potential for data loss or irreversible changes. By default, `up`
84    /// operations are considered non-destructible. Note that `down` operations
85    /// are always considered destructible and cannot be changed.
86    fn is_destructible(&self) -> bool {
87        false
88    }
89}
90
91#[async_trait::async_trait]
92impl<DB, U, D> Operation<DB> for (U, D)
93where
94    DB: Database,
95    U: AsRef<str> + Send + Sync,
96    D: AsRef<str> + Send + Sync,
97    for<'c> &'c mut <DB as Database>::Connection: sqlx::Executor<'c, Database = DB>,
98    for<'q> <DB as Database>::Arguments<'q>: sqlx::IntoArguments<'q, DB>,
99{
100    async fn up(&self, connection: &mut <DB as Database>::Connection) -> Result<(), Error> {
101        sqlx::query(self.0.as_ref())
102            .execute(connection)
103            .await
104            .map_err(Error::from)?;
105        Ok(())
106    }
107
108    async fn down(&self, connection: &mut <DB as Database>::Connection) -> Result<(), Error> {
109        sqlx::query(self.1.as_ref())
110            .execute(connection)
111            .await
112            .map_err(Error::from)?;
113        Ok(())
114    }
115}