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#[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}