aboutsummaryrefslogtreecommitdiff
path: root/src/db/migration/change.rs
blob: 758e23abb2f1a9fc2af5ea6936914f37fa61d716 (plain)
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
use diesel::Connection as _;

use crate::db::backend::{Connection, SqlGenerator};
use crate::db::models::Field;

pub enum DatabaseChange {
    CreateModel {
        name: &'static str,
        fields: &'static [Field],
        options: &'static [CreateModelOption],
    },
}

impl DatabaseChange {
    pub fn apply(&self, app_name: &str, connection: &Connection) {
        use barrel::{types, Migration, Table};

        match self {
            DatabaseChange::CreateModel {
                name,
                fields,
                options,
            } => {
                let mut m = Migration::new();

                let columns: Vec<(&'static str, _)> = fields
                    .iter()
                    .map(|field| match field {
                        Field::CharField { name, max_length } => {
                            let name = *name;
                            let _type = match max_length {
                                None => types::text(),
                                Some(max_length) => types::varchar(*max_length),
                            };
                            (name, _type)
                        }
                        Field::DateTimeField { name } => {
                            (*name, types::text()) // TODO do smart things on non-sqlite
                        }
                        Field::IntField { name: "id" } => ("id", types::primary()),
                        Field::IntField { name } => (*name, types::integer()),
                    })
                    .collect();

                let callback = move |t: &mut Table| {
                    for (name, _type) in &columns {
                        t.add_column(*name, _type.clone());
                    }
                };

                let table_name = format!("{}-{}", app_name, name);

                if options.contains(&CreateModelOption::IfNotExist) {
                    m.create_table_if_not_exists(table_name, callback);
                } else {
                    m.create_table(table_name, callback);
                }

                connection.execute(&m.make::<SqlGenerator>()).unwrap();
            }
        }
    }
}

#[derive(PartialEq)]
pub enum CreateModelOption {
    IfNotExist,
}