sql/statements/
drop.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::Display;
16
17use serde::Serialize;
18use sqlparser::ast::ObjectName;
19use sqlparser_derive::{Visit, VisitMut};
20
21/// DROP TABLE statement.
22#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
23pub struct DropTable {
24    table_names: Vec<ObjectName>,
25
26    /// drop table if exists
27    drop_if_exists: bool,
28}
29
30impl DropTable {
31    /// Creates a statement for `DROP TABLE`
32    pub fn new(table_names: Vec<ObjectName>, if_exists: bool) -> Self {
33        Self {
34            table_names,
35            drop_if_exists: if_exists,
36        }
37    }
38
39    pub fn table_names(&self) -> &[ObjectName] {
40        &self.table_names
41    }
42
43    pub fn drop_if_exists(&self) -> bool {
44        self.drop_if_exists
45    }
46}
47
48impl Display for DropTable {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.write_str("DROP TABLE")?;
51        if self.drop_if_exists() {
52            f.write_str(" IF EXISTS")?;
53        }
54        let table_names = self.table_names();
55        for (i, table_name) in table_names.iter().enumerate() {
56            if i > 0 {
57                f.write_str(",")?;
58            }
59            write!(f, " {}", table_name)?;
60        }
61        Ok(())
62    }
63}
64
65/// DROP DATABASE statement.
66#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
67pub struct DropDatabase {
68    name: ObjectName,
69    /// drop table if exists
70    drop_if_exists: bool,
71}
72
73impl DropDatabase {
74    /// Creates a statement for `DROP DATABASE`
75    pub fn new(name: ObjectName, if_exists: bool) -> Self {
76        Self {
77            name,
78            drop_if_exists: if_exists,
79        }
80    }
81
82    pub fn name(&self) -> &ObjectName {
83        &self.name
84    }
85
86    pub fn drop_if_exists(&self) -> bool {
87        self.drop_if_exists
88    }
89}
90
91impl Display for DropDatabase {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        f.write_str("DROP DATABASE")?;
94        if self.drop_if_exists() {
95            f.write_str(" IF EXISTS")?;
96        }
97        let name = self.name();
98        write!(f, r#" {name}"#)
99    }
100}
101
102/// DROP FLOW statement.
103#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
104pub struct DropFlow {
105    flow_name: ObjectName,
106    /// drop flow if exists
107    drop_if_exists: bool,
108}
109
110impl DropFlow {
111    /// Creates a statement for `DROP DATABASE`
112    pub fn new(flow_name: ObjectName, if_exists: bool) -> Self {
113        Self {
114            flow_name,
115            drop_if_exists: if_exists,
116        }
117    }
118
119    /// Returns the flow name.
120    pub fn flow_name(&self) -> &ObjectName {
121        &self.flow_name
122    }
123
124    /// Return the `drop_if_exists`.
125    pub fn drop_if_exists(&self) -> bool {
126        self.drop_if_exists
127    }
128}
129
130impl Display for DropFlow {
131    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132        f.write_str("DROP FLOW")?;
133        if self.drop_if_exists() {
134            f.write_str(" IF EXISTS")?;
135        }
136        let flow_name = self.flow_name();
137        write!(f, r#" {flow_name}"#)
138    }
139}
140
141/// `DROP VIEW` statement.
142#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
143pub struct DropView {
144    // The view name
145    pub view_name: ObjectName,
146    // drop view if exists
147    pub drop_if_exists: bool,
148}
149
150impl Display for DropView {
151    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152        write!(
153            f,
154            "DROP VIEW{} {}",
155            if self.drop_if_exists {
156                " IF EXISTS"
157            } else {
158                ""
159            },
160            self.view_name
161        )
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use std::assert_matches::assert_matches;
168
169    use crate::dialect::GreptimeDbDialect;
170    use crate::parser::{ParseOptions, ParserContext};
171    use crate::statements::statement::Statement;
172
173    #[test]
174    fn test_display_drop_database() {
175        let sql = r"drop database test;";
176        let stmts =
177            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
178                .unwrap();
179        assert_eq!(1, stmts.len());
180        assert_matches!(&stmts[0], Statement::DropDatabase { .. });
181
182        match &stmts[0] {
183            Statement::DropDatabase(set) => {
184                let new_sql = format!("\n{}", set);
185                assert_eq!(
186                    r#"
187DROP DATABASE test"#,
188                    &new_sql
189                );
190            }
191            _ => {
192                unreachable!();
193            }
194        }
195
196        let sql = r"drop database if exists test;";
197        let stmts =
198            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
199                .unwrap();
200        assert_eq!(1, stmts.len());
201        assert_matches!(&stmts[0], Statement::DropDatabase { .. });
202
203        match &stmts[0] {
204            Statement::DropDatabase(set) => {
205                let new_sql = format!("\n{}", set);
206                assert_eq!(
207                    r#"
208DROP DATABASE IF EXISTS test"#,
209                    &new_sql
210                );
211            }
212            _ => {
213                unreachable!();
214            }
215        }
216    }
217
218    #[test]
219    fn test_display_drop_table() {
220        let sql = r"drop table test;";
221        let stmts =
222            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
223                .unwrap();
224        assert_eq!(1, stmts.len());
225        assert_matches!(&stmts[0], Statement::DropTable { .. });
226
227        match &stmts[0] {
228            Statement::DropTable(set) => {
229                let new_sql = format!("\n{}", set);
230                assert_eq!(
231                    r#"
232DROP TABLE test"#,
233                    &new_sql
234                );
235            }
236            _ => {
237                unreachable!();
238            }
239        }
240
241        let sql = r"drop table test1, test2;";
242        let stmts =
243            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
244                .unwrap();
245        assert_eq!(1, stmts.len());
246        assert_matches!(&stmts[0], Statement::DropTable { .. });
247
248        match &stmts[0] {
249            Statement::DropTable(set) => {
250                let new_sql = format!("\n{}", set);
251                assert_eq!(
252                    r#"
253DROP TABLE test1, test2"#,
254                    &new_sql
255                );
256            }
257            _ => {
258                unreachable!();
259            }
260        }
261
262        let sql = r"drop table if exists test;";
263        let stmts =
264            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
265                .unwrap();
266        assert_eq!(1, stmts.len());
267        assert_matches!(&stmts[0], Statement::DropTable { .. });
268
269        match &stmts[0] {
270            Statement::DropTable(set) => {
271                let new_sql = format!("\n{}", set);
272                assert_eq!(
273                    r#"
274DROP TABLE IF EXISTS test"#,
275                    &new_sql
276                );
277            }
278            _ => {
279                unreachable!();
280            }
281        }
282    }
283
284    #[test]
285    fn test_display_drop_flow() {
286        let sql = r"drop flow test;";
287        let stmts =
288            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
289                .unwrap();
290        assert_eq!(1, stmts.len());
291        assert_matches!(&stmts[0], Statement::DropFlow { .. });
292
293        match &stmts[0] {
294            Statement::DropFlow(set) => {
295                let new_sql = format!("\n{}", set);
296                assert_eq!(
297                    r#"
298DROP FLOW test"#,
299                    &new_sql
300                );
301            }
302            _ => {
303                unreachable!();
304            }
305        }
306
307        let sql = r"drop flow if exists test;";
308        let stmts =
309            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
310                .unwrap();
311        assert_eq!(1, stmts.len());
312        assert_matches!(&stmts[0], Statement::DropFlow { .. });
313
314        match &stmts[0] {
315            Statement::DropFlow(set) => {
316                let new_sql = format!("\n{}", set);
317                assert_eq!(
318                    r#"
319DROP FLOW IF EXISTS test"#,
320                    &new_sql
321                );
322            }
323            _ => {
324                unreachable!();
325            }
326        }
327    }
328}