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