rorm_cli/migrate/
sql_builder.rs

1use rorm_db::executor::{Executor, Nothing};
2use rorm_db::sql::alter_table::{AlterTable, AlterTableOperation};
3use rorm_db::sql::create_table::CreateTable;
4use rorm_db::sql::drop_table::DropTable;
5use rorm_db::sql::value::Value;
6use rorm_db::sql::DBImpl;
7use rorm_db::transaction::Transaction;
8use rorm_declaration::migration::{Migration, Operation};
9
10/// Helper method to convert a migration to a transaction string
11///
12/// - `db_impl`: [`DBImpl`]: The database implementation to use.
13/// - `migration`: [`&Migration`](Migration): Reference to the migration that should be converted.
14pub async fn migration_to_sql<'a>(
15    tx: &'a mut Transaction,
16    db_impl: DBImpl,
17    migration: &'a Migration,
18    do_log: bool,
19) -> anyhow::Result<()> {
20    for operation in &migration.operations {
21        match &operation {
22            Operation::CreateModel { name, fields } => {
23                let mut create_table = db_impl.create_table(name.as_str());
24
25                for field in fields {
26                    create_table = create_table.add_column(db_impl.create_column(
27                        name.as_str(),
28                        field.name.as_str(),
29                        field.db_type,
30                        &field.annotations,
31                    ));
32                }
33
34                let statements = create_table.build()?;
35
36                for (query_string, query_bind_params) in statements {
37                    execute_statement(tx, query_string, query_bind_params, do_log).await?;
38                }
39            }
40            Operation::RenameModel { old, new } => {
41                let statements = db_impl
42                    .alter_table(
43                        old.as_str(),
44                        AlterTableOperation::RenameTo {
45                            name: new.to_string(),
46                        },
47                    )
48                    .build()?;
49
50                for (query_string, query_bind_params) in statements {
51                    execute_statement(tx, query_string, query_bind_params, do_log).await?;
52                }
53            }
54            Operation::DeleteModel { name } => {
55                let query_string = db_impl.drop_table(name.as_str()).build();
56
57                if do_log {
58                    println!("{}", query_string.as_str());
59                }
60
61                tx.execute::<Nothing>(query_string, Vec::new()).await?;
62            }
63            Operation::CreateField { model, field } => {
64                let statements = db_impl
65                    .alter_table(
66                        model.as_str(),
67                        AlterTableOperation::AddColumn {
68                            operation: db_impl.create_column(
69                                model.as_str(),
70                                field.name.as_str(),
71                                field.db_type,
72                                &field.annotations,
73                            ),
74                        },
75                    )
76                    .build()?;
77
78                for (query_string, query_bind_params) in statements {
79                    execute_statement(tx, query_string, query_bind_params, do_log).await?;
80                }
81            }
82            Operation::RenameField {
83                table_name,
84                old,
85                new,
86            } => {
87                let statements = db_impl
88                    .alter_table(
89                        table_name.as_str(),
90                        AlterTableOperation::RenameColumnTo {
91                            column_name: old.to_string(),
92                            new_column_name: new.to_string(),
93                        },
94                    )
95                    .build()?;
96
97                for (query_string, query_bind_params) in statements {
98                    execute_statement(tx, query_string, query_bind_params, do_log).await?;
99                }
100            }
101            Operation::DeleteField { model, name } => {
102                let statements = db_impl
103                    .alter_table(
104                        model.as_str(),
105                        AlterTableOperation::DropColumn { name: name.clone() },
106                    )
107                    .build()?;
108
109                for (query_string, query_bind_params) in statements {
110                    execute_statement(tx, query_string, query_bind_params, do_log).await?;
111                }
112            }
113            #[allow(unused_variables)]
114            Operation::RawSQL {
115                mysql,
116                postgres,
117                sqlite,
118                ..
119            } => match db_impl {
120                #[cfg(feature = "sqlite")]
121                DBImpl::SQLite => {
122                    execute_statement(tx, sqlite.clone(), Vec::new(), do_log).await?;
123                }
124                #[cfg(feature = "postgres")]
125                DBImpl::Postgres => {
126                    execute_statement(tx, postgres.clone(), Vec::new(), do_log).await?;
127                }
128                #[cfg(feature = "mysql")]
129                DBImpl::MySQL => {
130                    execute_statement(tx, mysql.clone(), Vec::new(), do_log).await?;
131                }
132            },
133        }
134    }
135
136    Ok(())
137}
138
139async fn execute_statement(
140    tx: &mut Transaction,
141    query_string: String,
142    query_bind_params: Vec<Value<'_>>,
143    do_log: bool,
144) -> Result<(), rorm_db::Error> {
145    if do_log {
146        println!("{}", query_string.as_str());
147    }
148    tx.execute::<Nothing>(query_string, query_bind_params).await
149}