Skip to main content

doido_model/migration/
column.rs

1//! Column operations: `add_column`, `remove_column`, `rename_column`.
2
3use sea_orm::sea_query::{Alias, ColumnDef, Table as SqTable, TableAlterStatement};
4use sea_orm::{ConnectionTrait, DbErr};
5use sea_orm_migration::SchemaManager;
6
7fn add_column_statement(
8    table: &str,
9    name: &str,
10    f: impl FnOnce(&mut ColumnDef),
11) -> TableAlterStatement {
12    let mut col = ColumnDef::new(Alias::new(name));
13    f(&mut col);
14    let mut stmt = SqTable::alter();
15    stmt.table(Alias::new(table)).add_column(col);
16    stmt
17}
18
19fn remove_column_statement(table: &str, name: &str) -> TableAlterStatement {
20    let mut stmt = SqTable::alter();
21    stmt.table(Alias::new(table)).drop_column(Alias::new(name));
22    stmt
23}
24
25fn rename_column_statement(table: &str, from: &str, to: &str) -> TableAlterStatement {
26    let mut stmt = SqTable::alter();
27    stmt.table(Alias::new(table))
28        .rename_column(Alias::new(from), Alias::new(to));
29    stmt
30}
31
32/// `add_column :table, :name, :type` — `f` configures the column type/modifiers.
33pub async fn add_column(
34    manager: &SchemaManager<'_>,
35    table: &str,
36    name: &str,
37    f: impl FnOnce(&mut ColumnDef),
38) -> Result<(), DbErr> {
39    manager
40        .get_connection()
41        .execute(&add_column_statement(table, name, f))
42        .await
43        .map(|_| ())
44}
45
46/// `remove_column :table, :name`.
47pub async fn remove_column(
48    manager: &SchemaManager<'_>,
49    table: &str,
50    name: &str,
51) -> Result<(), DbErr> {
52    manager
53        .get_connection()
54        .execute(&remove_column_statement(table, name))
55        .await
56        .map(|_| ())
57}
58
59/// `rename_column :table, :from, :to`.
60pub async fn rename_column(
61    manager: &SchemaManager<'_>,
62    table: &str,
63    from: &str,
64    to: &str,
65) -> Result<(), DbErr> {
66    manager
67        .get_connection()
68        .execute(&rename_column_statement(table, from, to))
69        .await
70        .map(|_| ())
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use sea_orm::sea_query::PostgresQueryBuilder;
77
78    #[test]
79    fn add_column_alters_table() {
80        let sql = add_column_statement("users", "age", |c| {
81            c.integer();
82        })
83        .to_string(PostgresQueryBuilder);
84        assert!(sql.contains("ALTER TABLE \"users\""));
85        assert!(sql.contains("\"age\""));
86    }
87
88    #[test]
89    fn rename_column_renders_both_names() {
90        let sql = rename_column_statement("users", "sku", "code").to_string(PostgresQueryBuilder);
91        assert!(sql.contains("\"sku\""));
92        assert!(sql.contains("\"code\""));
93    }
94}