Skip to main content

gluesql_core/query_builder/
alter_table.rs

1use {
2    super::Build,
3    crate::{
4        ast::{AlterTableOperation, Statement},
5        plan::StatementPlan,
6        query_builder::ColumnDefNode,
7        result::Result,
8    },
9};
10
11#[derive(Clone, Debug)]
12pub struct AlterTableNode {
13    table_name: String,
14}
15
16impl AlterTableNode {
17    pub fn new(table_name: String) -> Self {
18        Self { table_name }
19    }
20
21    pub fn add_column<T: Into<ColumnDefNode>>(self, column: T) -> AddColumnNode {
22        AddColumnNode {
23            table_node: self,
24            column_def: column.into(),
25        }
26    }
27
28    pub fn drop_column(self, column_name: &str) -> DropColumnNode {
29        DropColumnNode {
30            table_node: self,
31            column_name: column_name.to_owned(),
32            if_exists: false,
33        }
34    }
35
36    pub fn drop_column_if_exists(self, column_name: &str) -> DropColumnNode {
37        DropColumnNode {
38            table_node: self,
39            column_name: column_name.to_owned(),
40            if_exists: true,
41        }
42    }
43
44    pub fn rename_column(self, old_name: &str, new_name: &str) -> RenameColumnNode {
45        RenameColumnNode {
46            table_node: self,
47            old_column_name: old_name.to_owned(),
48            new_column_name: new_name.to_owned(),
49        }
50    }
51
52    pub fn rename_table(self, new_table_name: &str) -> RenameTableNode {
53        RenameTableNode {
54            table_node: self,
55            new_table_name: new_table_name.to_owned(),
56        }
57    }
58}
59
60pub struct AddColumnNode {
61    table_node: AlterTableNode,
62    column_def: ColumnDefNode,
63}
64
65impl Build for AddColumnNode {
66    fn build(self) -> Result<StatementPlan> {
67        let table_name = self.table_node.table_name;
68        let operation = AlterTableOperation::AddColumn {
69            column_def: self.column_def.try_into()?,
70        };
71        Ok(Statement::AlterTable {
72            name: table_name,
73            operation,
74        }
75        .into())
76    }
77}
78
79pub struct DropColumnNode {
80    table_node: AlterTableNode,
81    column_name: String,
82    if_exists: bool,
83}
84
85impl Build for DropColumnNode {
86    fn build(self) -> Result<StatementPlan> {
87        let table_name = self.table_node.table_name;
88        let operation = AlterTableOperation::DropColumn {
89            column_name: self.column_name,
90            if_exists: self.if_exists,
91        };
92        Ok(Statement::AlterTable {
93            name: table_name,
94            operation,
95        }
96        .into())
97    }
98}
99
100pub struct RenameColumnNode {
101    table_node: AlterTableNode,
102    old_column_name: String,
103    new_column_name: String,
104}
105
106impl Build for RenameColumnNode {
107    fn build(self) -> Result<StatementPlan> {
108        let table_name = self.table_node.table_name;
109        let operation = AlterTableOperation::RenameColumn {
110            old_column_name: self.old_column_name,
111            new_column_name: self.new_column_name,
112        };
113        Ok(Statement::AlterTable {
114            name: table_name,
115            operation,
116        }
117        .into())
118    }
119}
120
121pub struct RenameTableNode {
122    table_node: AlterTableNode,
123    new_table_name: String,
124}
125
126impl Build for RenameTableNode {
127    fn build(self) -> Result<StatementPlan> {
128        let old_table_name = self.table_node.table_name;
129        let operation = AlterTableOperation::RenameTable {
130            table_name: self.new_table_name,
131        };
132        Ok(Statement::AlterTable {
133            name: old_table_name,
134            operation,
135        }
136        .into())
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use crate::query_builder::{Build, table, test};
143
144    #[test]
145    fn alter_table() {
146        let actual = table("Foo")
147            .alter_table()
148            .add_column("opt BOOLEAN NULL")
149            .build();
150        let expected = "ALTER TABLE Foo ADD COLUMN opt BOOLEAN NULL";
151        test(&actual, expected);
152
153        let actual = table("Foo").alter_table().drop_column("col_name").build();
154        let expected = "ALTER TABLE Foo DROP COLUMN col_name";
155        test(&actual, expected);
156
157        let actual = table("Foo")
158            .alter_table()
159            .drop_column_if_exists("col_name")
160            .build();
161        let expected = "ALTER TABLE Foo DROP COLUMN IF EXISTS col_name";
162        test(&actual, expected);
163
164        let actual = table("Foo")
165            .alter_table()
166            .rename_column("old", "new")
167            .build();
168        let expected = "ALTER TABLE Foo RENAME COLUMN old TO new";
169        test(&actual, expected);
170
171        let actual = table("Foo")
172            .alter_table()
173            .rename_table("new_table_name")
174            .build();
175        let expected = "ALTER TABLE Foo RENAME TO new_table_name";
176        test(&actual, expected);
177    }
178}