1use snafu::{ensure, ResultExt};
16use sqlparser::dialect::keywords::Keyword;
17use sqlparser::tokenizer::Token;
18
19use crate::error::{self, InvalidFlowNameSnafu, InvalidTableNameSnafu, Result};
20use crate::parser::{ParserContext, FLOW};
21use crate::statements::drop::{DropDatabase, DropFlow, DropTable, DropView};
22use crate::statements::statement::Statement;
23
24impl ParserContext<'_> {
26 pub(crate) fn parse_drop(&mut self) -> Result<Statement> {
27 let _ = self.parser.next_token();
28 match self.parser.peek_token().token {
29 Token::Word(w) => match w.keyword {
30 Keyword::TABLE => self.parse_drop_table(),
31 Keyword::VIEW => self.parse_drop_view(),
32 Keyword::SCHEMA | Keyword::DATABASE => self.parse_drop_database(),
33 Keyword::NoKeyword => {
34 let uppercase = w.value.to_uppercase();
35 match uppercase.as_str() {
36 FLOW => self.parse_drop_flow(),
37 _ => self.unsupported(w.to_string()),
38 }
39 }
40 _ => self.unsupported(w.to_string()),
41 },
42 unexpected => self.unsupported(unexpected.to_string()),
43 }
44 }
45
46 fn parse_drop_view(&mut self) -> Result<Statement> {
47 let _ = self.parser.next_token();
48
49 let if_exists = self.parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
50 let raw_view_ident = self
51 .parse_object_name()
52 .with_context(|_| error::UnexpectedSnafu {
53 expected: "a view name",
54 actual: self.peek_token_as_string(),
55 })?;
56 let view_ident = Self::canonicalize_object_name(raw_view_ident);
57 ensure!(
58 !view_ident.0.is_empty(),
59 InvalidTableNameSnafu {
60 name: view_ident.to_string()
61 }
62 );
63
64 Ok(Statement::DropView(DropView {
65 view_name: view_ident,
66 drop_if_exists: if_exists,
67 }))
68 }
69
70 fn parse_drop_flow(&mut self) -> Result<Statement> {
71 let _ = self.parser.next_token();
72
73 let if_exists = self.parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
74 let raw_flow_ident = self
75 .parse_object_name()
76 .with_context(|_| error::UnexpectedSnafu {
77 expected: "a flow name",
78 actual: self.peek_token_as_string(),
79 })?;
80 let flow_ident = Self::canonicalize_object_name(raw_flow_ident);
81 ensure!(
82 !flow_ident.0.is_empty(),
83 InvalidFlowNameSnafu {
84 name: flow_ident.to_string()
85 }
86 );
87
88 Ok(Statement::DropFlow(DropFlow::new(flow_ident, if_exists)))
89 }
90
91 fn parse_drop_table(&mut self) -> Result<Statement> {
92 let _ = self.parser.next_token();
93
94 let if_exists = self.parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
95 let mut table_names = Vec::with_capacity(1);
96 loop {
97 let raw_table_ident =
98 self.parse_object_name()
99 .with_context(|_| error::UnexpectedSnafu {
100 expected: "a table name",
101 actual: self.peek_token_as_string(),
102 })?;
103 let table_ident = Self::canonicalize_object_name(raw_table_ident);
104 ensure!(
105 !table_ident.0.is_empty(),
106 InvalidTableNameSnafu {
107 name: table_ident.to_string()
108 }
109 );
110 table_names.push(table_ident);
111 if !self.parser.consume_token(&Token::Comma) {
112 break;
113 }
114 }
115
116 Ok(Statement::DropTable(DropTable::new(table_names, if_exists)))
117 }
118
119 fn parse_drop_database(&mut self) -> Result<Statement> {
120 let _ = self.parser.next_token();
121
122 let if_exists = self.parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
123 let database_name = self
124 .parse_object_name()
125 .with_context(|_| error::UnexpectedSnafu {
126 expected: "a database name",
127 actual: self.peek_token_as_string(),
128 })?;
129 let database_name = Self::canonicalize_object_name(database_name);
130
131 Ok(Statement::DropDatabase(DropDatabase::new(
132 database_name,
133 if_exists,
134 )))
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use sqlparser::ast::{Ident, ObjectName};
141
142 use super::*;
143 use crate::dialect::GreptimeDbDialect;
144 use crate::parser::ParseOptions;
145
146 #[test]
147 pub fn test_drop_table() {
148 let sql = "DROP TABLE foo";
149 let result =
150 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
151 let mut stmts = result.unwrap();
152 assert_eq!(
153 stmts.pop().unwrap(),
154 Statement::DropTable(DropTable::new(
155 vec![ObjectName(vec![Ident::new("foo")])],
156 false
157 ))
158 );
159
160 let sql = "DROP TABLE IF EXISTS foo";
161 let result =
162 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
163 let mut stmts = result.unwrap();
164 assert_eq!(
165 stmts.pop().unwrap(),
166 Statement::DropTable(DropTable::new(
167 vec![ObjectName(vec![Ident::new("foo")])],
168 true
169 ))
170 );
171
172 let sql = "DROP TABLE my_schema.foo";
173 let result =
174 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
175 let mut stmts = result.unwrap();
176 assert_eq!(
177 stmts.pop().unwrap(),
178 Statement::DropTable(DropTable::new(
179 vec![ObjectName(vec![Ident::new("my_schema"), Ident::new("foo")])],
180 false
181 ))
182 );
183
184 let sql = "DROP TABLE my_catalog.my_schema.foo";
185 let result =
186 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
187 let mut stmts = result.unwrap();
188 assert_eq!(
189 stmts.pop().unwrap(),
190 Statement::DropTable(DropTable::new(
191 vec![ObjectName(vec![
192 Ident::new("my_catalog"),
193 Ident::new("my_schema"),
194 Ident::new("foo")
195 ])],
196 false
197 ))
198 )
199 }
200
201 #[test]
202 pub fn test_drop_database() {
203 let sql = "DROP DATABASE public";
204 let result =
205 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
206 let mut stmts = result.unwrap();
207 assert_eq!(
208 stmts.pop().unwrap(),
209 Statement::DropDatabase(DropDatabase::new(
210 ObjectName(vec![Ident::new("public")]),
211 false
212 ))
213 );
214
215 let sql = "DROP DATABASE IF EXISTS public";
216 let result =
217 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
218 let mut stmts = result.unwrap();
219 assert_eq!(
220 stmts.pop().unwrap(),
221 Statement::DropDatabase(DropDatabase::new(
222 ObjectName(vec![Ident::new("public")]),
223 true
224 ))
225 );
226
227 let sql = "DROP DATABASE `fOo`";
228 let result =
229 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
230 let mut stmts = result.unwrap();
231 assert_eq!(
232 stmts.pop().unwrap(),
233 Statement::DropDatabase(DropDatabase::new(
234 ObjectName(vec![Ident::with_quote('`', "fOo"),]),
235 false
236 ))
237 );
238 }
239
240 #[test]
241 pub fn test_drop_flow() {
242 let sql = "DROP FLOW foo";
243 let result =
244 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
245 let mut stmts: Vec<Statement> = result.unwrap();
246 assert_eq!(
247 stmts.pop().unwrap(),
248 Statement::DropFlow(DropFlow::new(ObjectName(vec![Ident::new("foo")]), false))
249 );
250
251 let sql = "DROP FLOW IF EXISTS foo";
252 let result =
253 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
254 let mut stmts = result.unwrap();
255 assert_eq!(
256 stmts.pop().unwrap(),
257 Statement::DropFlow(DropFlow::new(ObjectName(vec![Ident::new("foo")]), true))
258 );
259
260 let sql = "DROP FLOW my_schema.foo";
261 let result =
262 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
263 let mut stmts = result.unwrap();
264 assert_eq!(
265 stmts.pop().unwrap(),
266 Statement::DropFlow(DropFlow::new(
267 ObjectName(vec![Ident::new("my_schema"), Ident::new("foo")]),
268 false
269 ))
270 );
271
272 let sql = "DROP FLOW my_catalog.my_schema.foo";
273 let result =
274 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
275 let mut stmts = result.unwrap();
276 assert_eq!(
277 stmts.pop().unwrap(),
278 Statement::DropFlow(DropFlow::new(
279 ObjectName(vec![
280 Ident::new("my_catalog"),
281 Ident::new("my_schema"),
282 Ident::new("foo")
283 ]),
284 false
285 ))
286 )
287 }
288
289 #[test]
290 pub fn test_drop_view() {
291 let sql = "DROP VIEW foo";
292 let result =
293 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
294 let mut stmts: Vec<Statement> = result.unwrap();
295 let stmt = stmts.pop().unwrap();
296 assert_eq!(
297 stmt,
298 Statement::DropView(DropView {
299 view_name: ObjectName(vec![Ident::new("foo")]),
300 drop_if_exists: false,
301 })
302 );
303 assert_eq!(sql, stmt.to_string());
304
305 let sql = "DROP VIEW greptime.public.foo";
306 let result =
307 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
308 let mut stmts: Vec<Statement> = result.unwrap();
309 let stmt = stmts.pop().unwrap();
310 assert_eq!(
311 stmt,
312 Statement::DropView(DropView {
313 view_name: ObjectName(vec![
314 Ident::new("greptime"),
315 Ident::new("public"),
316 Ident::new("foo")
317 ]),
318 drop_if_exists: false,
319 })
320 );
321 assert_eq!(sql, stmt.to_string());
322
323 let sql = "DROP VIEW IF EXISTS foo";
324 let result =
325 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
326 let mut stmts: Vec<Statement> = result.unwrap();
327 let stmt = stmts.pop().unwrap();
328 assert_eq!(
329 stmt,
330 Statement::DropView(DropView {
331 view_name: ObjectName(vec![Ident::new("foo")]),
332 drop_if_exists: true,
333 })
334 );
335 assert_eq!(sql, stmt.to_string());
336 }
337}