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