sqlparser_mysql/dds/
rename_table.rs

1use core::fmt;
2use std::fmt::Formatter;
3use std::str;
4
5use nom::bytes::complete::tag_no_case;
6use nom::character::complete::multispace0;
7use nom::combinator::opt;
8use nom::multi::many0;
9use nom::sequence::{terminated, tuple};
10use nom::IResult;
11
12use base::error::ParseSQLError;
13use base::table::Table;
14use base::CommonParser;
15
16/// parse `RENAME TABLE
17///     tbl_name TO new_tbl_name
18///     [, tbl_name2 TO new_tbl_name2] ...`
19#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
20pub struct RenameTableStatement {
21    pub tables: Vec<(Table, Table)>,
22}
23
24impl RenameTableStatement {
25    pub fn parse(i: &str) -> IResult<&str, RenameTableStatement, ParseSQLError<&str>> {
26        let mut parser = tuple((
27            tag_no_case("RENAME "),
28            multispace0,
29            tag_no_case("TABLE "),
30            multispace0,
31            many0(terminated(
32                Table::schema_table_reference_to_schema_table_reference,
33                opt(CommonParser::ws_sep_comma),
34            )),
35            CommonParser::statement_terminator,
36        ));
37        let (remaining_input, (_, _, _, _, table_pairs, _)) = parser(i)?;
38
39        Ok((
40            remaining_input,
41            RenameTableStatement {
42                tables: table_pairs,
43            },
44        ))
45    }
46}
47
48impl fmt::Display for RenameTableStatement {
49    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50        write!(f, "RENAME TABLE ")?;
51        let table_name = self
52            .tables
53            .iter()
54            .map(|(x, y)| {
55                let old = match &x.schema {
56                    Some(schema) => format!("{}.{}", schema, x.name),
57                    None => x.name.clone(),
58                };
59                let new = match &y.schema {
60                    Some(schema) => format!("{}.{}", schema, y.name),
61                    None => y.name.clone(),
62                };
63                format!("{} TO {}", old, new)
64            })
65            .collect::<Vec<String>>()
66            .join(", ");
67        write!(f, "{}", table_name)?;
68        Ok(())
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use base::table::Table;
75    use dds::rename_table::RenameTableStatement;
76
77    #[test]
78    fn parse_drop_table() {
79        let sqls = [
80            "RENAME TABLE tbl_name1 TO tbl_name2;",
81            "RENAME TABLE db1.tbl_name1 TO db2.tbl_name2;",
82            "RENAME TABLE tbl_name1 TO tbl_name2, tbl_name3 TO tbl_name4;",
83            "RENAME TABLE db1.tbl_name1 TO db2.tbl_name2, tbl_name3 TO tbl_name4;",
84            "RENAME TABLE tbl_name1 TO tbl_name2, db3.tbl_name3 TO db4.tbl_name4;",
85            "RENAME TABLE db1.tbl_name1 TO db2.tbl_name2, db3.tbl_name3 TO db4.tbl_name4;",
86        ];
87
88        let one_table = vec![(
89            Table {
90                name: String::from("tbl_name1"),
91                alias: None,
92                schema: None,
93            },
94            Table {
95                name: String::from("tbl_name2"),
96                alias: None,
97                schema: None,
98            },
99        )];
100
101        let one_table_with_schema = vec![(
102            Table {
103                name: String::from("tbl_name1"),
104                alias: None,
105                schema: Some(String::from("db1")),
106            },
107            Table {
108                name: String::from("tbl_name2"),
109                alias: None,
110                schema: Some(String::from("db2")),
111            },
112        )];
113
114        let two_tables = vec![
115            (
116                Table {
117                    name: String::from("tbl_name1"),
118                    alias: None,
119                    schema: None,
120                },
121                Table {
122                    name: String::from("tbl_name2"),
123                    alias: None,
124                    schema: None,
125                },
126            ),
127            (
128                Table {
129                    name: String::from("tbl_name3"),
130                    alias: None,
131                    schema: None,
132                },
133                Table {
134                    name: String::from("tbl_name4"),
135                    alias: None,
136                    schema: None,
137                },
138            ),
139        ];
140
141        let two_tables_with_schema = vec![
142            (
143                Table {
144                    name: String::from("tbl_name1"),
145                    alias: None,
146                    schema: Some(String::from("db1")),
147                },
148                Table {
149                    name: String::from("tbl_name2"),
150                    alias: None,
151                    schema: Some(String::from("db2")),
152                },
153            ),
154            (
155                Table {
156                    name: String::from("tbl_name3"),
157                    alias: None,
158                    schema: Some(String::from("db3")),
159                },
160                Table {
161                    name: String::from("tbl_name4"),
162                    alias: None,
163                    schema: Some(String::from("db4")),
164                },
165            ),
166        ];
167
168        let good_statements = [
169            RenameTableStatement {
170                tables: one_table.clone(),
171            },
172            RenameTableStatement {
173                tables: one_table_with_schema.clone(),
174            },
175            RenameTableStatement {
176                tables: two_tables.clone(),
177            },
178            RenameTableStatement {
179                tables: vec![
180                    (
181                        Table {
182                            name: String::from("tbl_name1"),
183                            alias: None,
184                            schema: Some(String::from("db1")),
185                        },
186                        Table {
187                            name: String::from("tbl_name2"),
188                            alias: None,
189                            schema: Some(String::from("db2")),
190                        },
191                    ),
192                    (
193                        Table {
194                            name: String::from("tbl_name3"),
195                            alias: None,
196                            schema: None,
197                        },
198                        Table {
199                            name: String::from("tbl_name4"),
200                            alias: None,
201                            schema: None,
202                        },
203                    ),
204                ],
205            },
206            RenameTableStatement {
207                tables: vec![
208                    (
209                        Table {
210                            name: String::from("tbl_name1"),
211                            alias: None,
212                            schema: None,
213                        },
214                        Table {
215                            name: String::from("tbl_name2"),
216                            alias: None,
217                            schema: None,
218                        },
219                    ),
220                    (
221                        Table {
222                            name: String::from("tbl_name3"),
223                            alias: None,
224                            schema: Some(String::from("db3")),
225                        },
226                        Table {
227                            name: String::from("tbl_name4"),
228                            alias: None,
229                            schema: Some(String::from("db4")),
230                        },
231                    ),
232                ],
233            },
234            RenameTableStatement {
235                tables: two_tables_with_schema.clone(),
236            },
237        ];
238
239        for i in 0..sqls.len() {
240            let res = RenameTableStatement::parse(sqls[i]);
241            assert!(res.is_ok());
242            assert_eq!(res.unwrap().1, good_statements[i]);
243        }
244    }
245}