1#[cfg(feature = "enterprise")]
16pub mod trigger;
17
18use snafu::{ResultExt, ensure};
19use sqlparser::keywords::Keyword;
20use sqlparser::tokenizer::Token;
21
22use crate::ast::ObjectNamePartExt;
23use crate::error::{
24 self, InvalidDatabaseNameSnafu, InvalidFlowNameSnafu, InvalidTableNameSnafu, Result,
25};
26use crate::parser::ParserContext;
27use crate::statements::show::{
28 ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateTableVariant,
29 ShowCreateView, ShowDatabases, ShowFlowStatus, ShowFlows, ShowIndex, ShowKind, ShowProcessList,
30 ShowRegion, ShowSearchPath, ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
31};
32use crate::statements::statement::Statement;
33
34impl ParserContext<'_> {
36 pub(crate) fn parse_show(&mut self) -> Result<Statement> {
39 #[cfg(feature = "enterprise")]
40 if self.consume_token("TRIGGERS") {
41 return self.parse_show_triggers();
42 }
43 if self.consume_token("DATABASES") || self.consume_token("SCHEMAS") {
44 self.parse_show_databases(false)
45 } else if self.matches_keyword(Keyword::TABLES) {
46 self.parser.next_token();
47 self.parse_show_tables(false)
48 } else if self.matches_keyword(Keyword::TABLE) {
49 self.parser.next_token();
50 if self.matches_keyword(Keyword::STATUS) {
51 self.parser.next_token();
52 self.parse_show_table_status()
53 } else {
54 self.unsupported(self.peek_token_as_string())
55 }
56 } else if self.consume_token("VIEWS") {
57 self.parse_show_views()
58 } else if self.consume_token("FLOWS") {
59 self.parse_show_flows()
60 } else if self.consume_token("FLOW") {
61 if self.consume_token("STATUS") {
62 self.parse_show_flow_status()
63 } else {
64 self.unsupported(self.peek_token_as_string())
65 }
66 } else if self.matches_keyword(Keyword::CHARSET) {
67 self.parser.next_token();
68 Ok(Statement::ShowCharset(self.parse_show_kind()?))
69 } else if self.matches_keyword(Keyword::CHARACTER) {
70 self.parser.next_token();
71
72 if self.matches_keyword(Keyword::SET) {
73 self.parser.next_token();
74 Ok(Statement::ShowCharset(self.parse_show_kind()?))
75 } else {
76 self.unsupported(self.peek_token_as_string())
77 }
78 } else if self.matches_keyword(Keyword::COLLATION) {
79 self.parser.next_token();
80 Ok(Statement::ShowCollation(self.parse_show_kind()?))
81 } else if self.matches_keyword(Keyword::COLUMNS) || self.matches_keyword(Keyword::FIELDS) {
82 self.parser.next_token();
84 self.parse_show_columns(false)
85 } else if self.consume_token("INDEX")
86 || self.consume_token("INDEXES")
87 || self.consume_token("KEYS")
88 {
89 self.parse_show_index()
91 } else if self.consume_token("REGIONS") || self.consume_token("REGION") {
92 self.parse_show_regions()
94 } else if self.consume_token("CREATE") {
95 #[cfg(feature = "enterprise")]
96 if self.consume_token("TRIGGER") {
97 return self.parse_show_create_trigger();
98 }
99
100 if self.consume_token("DATABASE") || self.consume_token("SCHEMA") {
101 self.parse_show_create_database()
102 } else if self.consume_token("TABLE") {
103 self.parse_show_create_table()
104 } else if self.consume_token("FLOW") {
105 self.parse_show_create_flow()
106 } else if self.consume_token("VIEW") {
107 self.parse_show_create_view()
108 } else {
109 self.unsupported(self.peek_token_as_string())
110 }
111 } else if self.consume_token("FULL") {
112 if self.consume_token("TABLES") {
113 self.parse_show_tables(true)
114 } else if self.consume_token("COLUMNS") || self.consume_token("FIELDS") {
115 self.parse_show_columns(true)
117 } else if self.consume_token("DATABASES") || self.consume_token("SCHEMAS") {
118 self.parse_show_databases(true)
119 } else if self.consume_token("PROCESSLIST") {
120 self.parse_show_processlist(true)
121 } else {
122 self.unsupported(self.peek_token_as_string())
123 }
124 } else if self.consume_token("VARIABLES") {
125 let variable = self
126 .parse_object_name()
127 .with_context(|_| error::UnexpectedSnafu {
128 expected: "a variable name",
129 actual: self.peek_token_as_string(),
130 })?;
131 Ok(Statement::ShowVariables(ShowVariables { variable }))
132 } else if self.consume_token("STATUS") {
133 Ok(Statement::ShowStatus(ShowStatus {}))
134 } else if self.consume_token("SEARCH_PATH") {
135 Ok(Statement::ShowSearchPath(ShowSearchPath {}))
136 } else if self.consume_token("PROCESSLIST") {
137 self.parse_show_processlist(false)
138 } else {
139 let variable = self
141 .parse_object_name()
142 .with_context(|_| error::UnexpectedSnafu {
143 expected: "a variable name",
144 actual: self.peek_token_as_string(),
145 })?;
146 Ok(Statement::ShowVariables(ShowVariables { variable }))
147 }
148 }
149
150 fn parse_show_create_database(&mut self) -> Result<Statement> {
151 let raw_database_name =
152 self.parse_object_name()
153 .with_context(|_| error::UnexpectedSnafu {
154 expected: "a database name",
155 actual: self.peek_token_as_string(),
156 })?;
157 let database_name = Self::canonicalize_object_name(raw_database_name)?;
158 ensure!(
159 !database_name.0.is_empty(),
160 InvalidDatabaseNameSnafu {
161 name: database_name.to_string(),
162 }
163 );
164 Ok(Statement::ShowCreateDatabase(ShowCreateDatabase {
165 database_name,
166 }))
167 }
168
169 fn parse_show_create_table(&mut self) -> Result<Statement> {
171 let raw_table_name = self
172 .parse_object_name()
173 .with_context(|_| error::UnexpectedSnafu {
174 expected: "a table name",
175 actual: self.peek_token_as_string(),
176 })?;
177 let table_name = Self::canonicalize_object_name(raw_table_name)?;
178 ensure!(
179 !table_name.0.is_empty(),
180 InvalidTableNameSnafu {
181 name: table_name.to_string(),
182 }
183 );
184 let mut variant = ShowCreateTableVariant::Original;
185 if self.consume_token("FOR") {
186 if self.consume_token("POSTGRES_FOREIGN_TABLE") {
187 variant = ShowCreateTableVariant::PostgresForeignTable;
188 } else {
189 self.unsupported(self.peek_token_as_string())?;
190 }
191 }
192
193 Ok(Statement::ShowCreateTable(ShowCreateTable {
194 table_name,
195 variant,
196 }))
197 }
198
199 fn parse_show_create_flow(&mut self) -> Result<Statement> {
200 let raw_flow_name = self
201 .parse_object_name()
202 .with_context(|_| error::UnexpectedSnafu {
203 expected: "a flow name",
204 actual: self.peek_token_as_string(),
205 })?;
206 let flow_name = Self::canonicalize_object_name(raw_flow_name)?;
207 ensure!(
208 !flow_name.0.is_empty(),
209 InvalidFlowNameSnafu {
210 name: flow_name.to_string(),
211 }
212 );
213 Ok(Statement::ShowCreateFlow(ShowCreateFlow { flow_name }))
214 }
215
216 fn parse_show_create_view(&mut self) -> Result<Statement> {
217 let raw_view_name = self
218 .parse_object_name()
219 .with_context(|_| error::UnexpectedSnafu {
220 expected: "a view name",
221 actual: self.peek_token_as_string(),
222 })?;
223 let view_name = Self::canonicalize_object_name(raw_view_name)?;
224 ensure!(
225 !view_name.0.is_empty(),
226 InvalidTableNameSnafu {
227 name: view_name.to_string(),
228 }
229 );
230 Ok(Statement::ShowCreateView(ShowCreateView { view_name }))
231 }
232
233 fn parse_show_table_name(&mut self) -> Result<String> {
234 self.parser.next_token();
235 let table_name = self
236 .parse_object_name()
237 .with_context(|_| error::UnexpectedSnafu {
238 expected: "a table name",
239 actual: self.peek_token_as_string(),
240 })?;
241
242 ensure!(
243 table_name.0.len() == 1,
244 InvalidDatabaseNameSnafu {
245 name: table_name.to_string(),
246 }
247 );
248
249 Ok(Self::canonicalize_object_name(table_name)?.0[0].to_string_unquoted())
251 }
252
253 fn parse_db_name(&mut self) -> Result<Option<String>> {
254 self.parser.next_token();
255 let db_name = self
256 .parse_object_name()
257 .with_context(|_| error::UnexpectedSnafu {
258 expected: "a database name",
259 actual: self.peek_token_as_string(),
260 })?;
261
262 ensure!(
263 db_name.0.len() == 1,
264 InvalidDatabaseNameSnafu {
265 name: db_name.to_string(),
266 }
267 );
268
269 Ok(Some(
271 Self::canonicalize_object_name(db_name)?.0[0].to_string_unquoted(),
272 ))
273 }
274
275 fn parse_show_columns(&mut self, full: bool) -> Result<Statement> {
276 let table = match self.parser.peek_token().token {
277 Token::Word(w) if matches!(w.keyword, Keyword::IN | Keyword::FROM) => {
279 self.parse_show_table_name()?
280 }
281 _ => {
282 return error::UnexpectedTokenSnafu {
283 expected: "{FROM | IN} table",
284 actual: self.peek_token_as_string(),
285 }
286 .fail();
287 }
288 };
289
290 let database = match self.parser.peek_token().token {
291 Token::EOF | Token::SemiColon => {
292 return Ok(Statement::ShowColumns(ShowColumns {
293 kind: ShowKind::All,
294 table,
295 database: None,
296 full,
297 }));
298 }
299
300 Token::Word(w) => match w.keyword {
302 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
303
304 _ => None,
305 },
306 _ => None,
307 };
308
309 let kind = self.parse_show_kind()?;
310
311 Ok(Statement::ShowColumns(ShowColumns {
312 kind,
313 database,
314 table,
315 full,
316 }))
317 }
318
319 fn parse_show_kind(&mut self) -> Result<ShowKind> {
320 match self.parser.peek_token().token {
321 Token::EOF | Token::SemiColon => Ok(ShowKind::All),
322 Token::Word(w) => match w.keyword {
323 Keyword::LIKE => {
324 self.parser.next_token();
325 Ok(ShowKind::Like(
326 self.parser.parse_identifier().with_context(|_| {
327 error::UnexpectedSnafu {
328 expected: "LIKE",
329 actual: self.peek_token_as_string(),
330 }
331 })?,
332 ))
333 }
334 Keyword::WHERE => {
335 self.parser.next_token();
336 Ok(ShowKind::Where(self.parser.parse_expr().with_context(
337 |_| error::UnexpectedSnafu {
338 expected: "some valid expression",
339 actual: self.peek_token_as_string(),
340 },
341 )?))
342 }
343 _ => self.unsupported(self.peek_token_as_string()),
344 },
345 _ => self.unsupported(self.peek_token_as_string()),
346 }
347 }
348
349 fn parse_show_index(&mut self) -> Result<Statement> {
350 let table = match self.parser.peek_token().token {
351 Token::Word(w) if matches!(w.keyword, Keyword::IN | Keyword::FROM) => {
353 self.parse_show_table_name()?
354 }
355 _ => {
356 return error::UnexpectedTokenSnafu {
357 expected: "{FROM | IN} table",
358 actual: self.peek_token_as_string(),
359 }
360 .fail();
361 }
362 };
363
364 let database = match self.parser.peek_token().token {
365 Token::EOF | Token::SemiColon => {
366 return Ok(Statement::ShowIndex(ShowIndex {
367 kind: ShowKind::All,
368 table,
369 database: None,
370 }));
371 }
372
373 Token::Word(w) => match w.keyword {
375 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
376
377 _ => None,
378 },
379 _ => None,
380 };
381
382 let kind = match self.parser.peek_token().token {
383 Token::EOF | Token::SemiColon => ShowKind::All,
384 Token::Word(w) => match w.keyword {
386 Keyword::WHERE => {
387 self.parser.next_token();
388 ShowKind::Where(self.parser.parse_expr().with_context(|_| {
389 error::UnexpectedSnafu {
390 expected: "some valid expression",
391 actual: self.peek_token_as_string(),
392 }
393 })?)
394 }
395 _ => return self.unsupported(self.peek_token_as_string()),
396 },
397 _ => return self.unsupported(self.peek_token_as_string()),
398 };
399
400 Ok(Statement::ShowIndex(ShowIndex {
401 kind,
402 database,
403 table,
404 }))
405 }
406
407 fn parse_show_regions(&mut self) -> Result<Statement> {
408 let table = match self.parser.peek_token().token {
409 Token::Word(w) if matches!(w.keyword, Keyword::IN | Keyword::FROM) => {
411 self.parse_show_table_name()?
412 }
413 _ => {
414 return error::UnexpectedTokenSnafu {
415 expected: "{FROM | IN} table",
416 actual: self.peek_token_as_string(),
417 }
418 .fail();
419 }
420 };
421
422 let database = match self.parser.peek_token().token {
423 Token::EOF | Token::SemiColon => {
424 return Ok(Statement::ShowRegion(ShowRegion {
425 kind: ShowKind::All,
426 table,
427 database: None,
428 }));
429 }
430
431 Token::Word(w) => match w.keyword {
433 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
434
435 _ => None,
436 },
437 _ => None,
438 };
439
440 let kind = match self.parser.peek_token().token {
441 Token::EOF | Token::SemiColon => ShowKind::All,
442 Token::Word(w) => match w.keyword {
444 Keyword::WHERE => {
445 self.parser.next_token();
446 ShowKind::Where(self.parser.parse_expr().with_context(|_| {
447 error::UnexpectedSnafu {
448 expected: "some valid expression",
449 actual: self.peek_token_as_string(),
450 }
451 })?)
452 }
453 _ => return self.unsupported(self.peek_token_as_string()),
454 },
455 _ => return self.unsupported(self.peek_token_as_string()),
456 };
457
458 Ok(Statement::ShowRegion(ShowRegion {
459 kind,
460 database,
461 table,
462 }))
463 }
464
465 fn parse_show_tables(&mut self, full: bool) -> Result<Statement> {
466 let database = match self.parser.peek_token().token {
467 Token::EOF | Token::SemiColon => {
468 return Ok(Statement::ShowTables(ShowTables {
469 kind: ShowKind::All,
470 database: None,
471 full,
472 }));
473 }
474
475 Token::Word(w) => match w.keyword {
477 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
478
479 _ => None,
480 },
481 _ => None,
482 };
483
484 let kind = self.parse_show_kind()?;
485
486 Ok(Statement::ShowTables(ShowTables {
487 kind,
488 database,
489 full,
490 }))
491 }
492
493 fn parse_show_table_status(&mut self) -> Result<Statement> {
494 let database = match self.parser.peek_token().token {
495 Token::EOF | Token::SemiColon => {
496 return Ok(Statement::ShowTableStatus(ShowTableStatus {
497 kind: ShowKind::All,
498 database: None,
499 }));
500 }
501
502 Token::Word(w) => match w.keyword {
504 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
505
506 _ => None,
507 },
508 _ => None,
509 };
510
511 let kind = self.parse_show_kind()?;
512
513 Ok(Statement::ShowTableStatus(ShowTableStatus {
514 kind,
515 database,
516 }))
517 }
518
519 pub fn parse_show_databases(&mut self, full: bool) -> Result<Statement> {
521 let tok = self.parser.next_token().token;
522 match &tok {
523 Token::EOF | Token::SemiColon => Ok(Statement::ShowDatabases(ShowDatabases::new(
524 ShowKind::All,
525 full,
526 ))),
527 Token::Word(w) => match w.keyword {
528 Keyword::LIKE => Ok(Statement::ShowDatabases(ShowDatabases::new(
529 ShowKind::Like(self.parser.parse_identifier().with_context(|_| {
530 error::UnexpectedSnafu {
531 expected: "LIKE",
532 actual: tok.to_string(),
533 }
534 })?),
535 full,
536 ))),
537 Keyword::WHERE => Ok(Statement::ShowDatabases(ShowDatabases::new(
538 ShowKind::Where(self.parser.parse_expr().with_context(|_| {
539 error::UnexpectedSnafu {
540 expected: "some valid expression",
541 actual: self.peek_token_as_string(),
542 }
543 })?),
544 full,
545 ))),
546 _ => self.unsupported(self.peek_token_as_string()),
547 },
548 _ => self.unsupported(self.peek_token_as_string()),
549 }
550 }
551
552 fn parse_show_views(&mut self) -> Result<Statement> {
553 let database = match self.parser.peek_token().token {
554 Token::EOF | Token::SemiColon => {
555 return Ok(Statement::ShowViews(ShowViews {
556 kind: ShowKind::All,
557 database: None,
558 }));
559 }
560
561 Token::Word(w) => match w.keyword {
563 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
564 _ => None,
565 },
566 _ => None,
567 };
568
569 let kind = self.parse_show_kind()?;
570
571 Ok(Statement::ShowViews(ShowViews { kind, database }))
572 }
573
574 fn parse_show_flows(&mut self) -> Result<Statement> {
575 let database = match self.parser.peek_token().token {
576 Token::EOF | Token::SemiColon => {
577 return Ok(Statement::ShowFlows(ShowFlows {
578 kind: ShowKind::All,
579 database: None,
580 }));
581 }
582
583 Token::Word(w) => match w.keyword {
585 Keyword::IN | Keyword::FROM => self.parse_db_name()?,
586 _ => None,
587 },
588 _ => None,
589 };
590
591 let kind = self.parse_show_kind()?;
592
593 Ok(Statement::ShowFlows(ShowFlows { kind, database }))
594 }
595
596 fn parse_show_flow_status(&mut self) -> Result<Statement> {
597 let kind = self.parse_show_kind()?;
598
599 Ok(Statement::ShowFlowStatus(ShowFlowStatus { kind }))
600 }
601
602 fn parse_show_processlist(&mut self, full: bool) -> Result<Statement> {
603 match self.parser.next_token().token {
604 Token::EOF | Token::SemiColon => {
605 Ok(Statement::ShowProcesslist(ShowProcessList { full }))
606 }
607 _ => self.unsupported(self.peek_token_as_string()),
608 }
609 }
610}
611
612#[cfg(test)]
613mod tests {
614 use std::assert_matches;
615
616 use sqlparser::ast::{Ident, ObjectName};
617
618 use super::*;
619 use crate::dialect::GreptimeDbDialect;
620 use crate::parser::ParseOptions;
621 use crate::statements::show::ShowDatabases;
622 #[cfg(feature = "enterprise")]
623 use crate::statements::show::trigger::ShowCreateTrigger;
624 #[cfg(feature = "enterprise")]
625 use crate::statements::show::trigger::ShowTriggers;
626
627 #[test]
628 pub fn test_show_database_all() {
629 let sql = "SHOW DATABASES";
630 let result =
631 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
632 let stmts = result.unwrap();
633 assert_eq!(1, stmts.len());
634
635 assert_matches!(
636 &stmts[0],
637 Statement::ShowDatabases(ShowDatabases {
638 kind: ShowKind::All,
639 full: false,
640 })
641 );
642 }
643
644 #[test]
645 pub fn test_show_full_databases() {
646 let sql = "SHOW FULL DATABASES";
647 let result =
648 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
649 let stmts = result.unwrap();
650 assert_eq!(1, stmts.len());
651
652 assert_matches!(
653 &stmts[0],
654 Statement::ShowDatabases(ShowDatabases {
655 kind: ShowKind::All,
656 full: true,
657 })
658 );
659
660 let sql = "SHOW FULL DATABASES LIKE 'test%'";
661 let result =
662 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
663 let stmts = result.unwrap();
664 assert_eq!(1, stmts.len());
665
666 assert_matches!(
667 &stmts[0],
668 Statement::ShowDatabases(ShowDatabases {
669 kind: ShowKind::Like(_),
670 full: true,
671 })
672 );
673 }
674
675 #[test]
676 pub fn test_show_database_like() {
677 let sql = "SHOW DATABASES LIKE test_database";
678 let result =
679 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
680 let stmts = result.unwrap();
681 assert_eq!(1, stmts.len());
682
683 assert_matches!(
684 &stmts[0],
685 Statement::ShowDatabases(ShowDatabases {
686 kind: ShowKind::Like(sqlparser::ast::Ident {
687 value: _,
688 quote_style: None,
689 span: _,
690 }),
691 ..
692 })
693 );
694 }
695
696 #[test]
697 pub fn test_show_database_where() {
698 let sql = "SHOW DATABASES WHERE Database LIKE '%whatever1%' OR Database LIKE '%whatever2%'";
699 let result =
700 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
701 let stmts = result.unwrap();
702 assert_eq!(1, stmts.len());
703
704 assert_matches!(
705 &stmts[0],
706 Statement::ShowDatabases(ShowDatabases {
707 kind: ShowKind::Where(sqlparser::ast::Expr::BinaryOp {
708 left: _,
709 right: _,
710 op: sqlparser::ast::BinaryOperator::Or,
711 }),
712 ..
713 })
714 );
715 }
716
717 #[test]
718 pub fn test_show_tables_all() {
719 let sql = "SHOW TABLES";
720 let result =
721 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
722 let stmts = result.unwrap();
723 assert_eq!(1, stmts.len());
724
725 assert_matches!(
726 &stmts[0],
727 Statement::ShowTables(ShowTables {
728 kind: ShowKind::All,
729 database: None,
730 full: false
731 })
732 );
733 }
734
735 #[test]
736 pub fn test_show_tables_like() {
737 let sql = "SHOW TABLES LIKE test_table";
738 let result =
739 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
740 let stmts = result.unwrap();
741 assert_eq!(1, stmts.len());
742
743 assert_matches!(
744 &stmts[0],
745 Statement::ShowTables(ShowTables {
746 kind: ShowKind::Like(sqlparser::ast::Ident {
747 value: _,
748 quote_style: None,
749 span: _,
750 }),
751 database: None,
752 full: false
753 })
754 );
755
756 let sql = "SHOW TABLES in test_db LIKE test_table";
757 let result =
758 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
759 let stmts = result.unwrap();
760 assert_eq!(1, stmts.len());
761
762 assert_matches!(
763 &stmts[0],
764 Statement::ShowTables(ShowTables {
765 kind: ShowKind::Like(sqlparser::ast::Ident {
766 value: _,
767 quote_style: None,
768 span: _,
769 }),
770 database: Some(_),
771 full: false
772 })
773 );
774 }
775
776 #[test]
777 pub fn test_show_tables_where() {
778 let sql = "SHOW TABLES where name like test_table";
779 let result =
780 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
781 let stmts = result.unwrap();
782 assert_eq!(1, stmts.len());
783
784 assert_matches!(
785 &stmts[0],
786 Statement::ShowTables(ShowTables {
787 kind: ShowKind::Where(sqlparser::ast::Expr::Like { .. }),
788 database: None,
789 full: false
790 })
791 );
792
793 let sql = "SHOW TABLES in test_db where name LIKE test_table";
794 let result =
795 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
796 let stmts = result.unwrap();
797 assert_eq!(1, stmts.len());
798
799 assert_matches!(
800 &stmts[0],
801 Statement::ShowTables(ShowTables {
802 kind: ShowKind::Where(sqlparser::ast::Expr::Like { .. }),
803 database: Some(_),
804 full: false
805 })
806 );
807 }
808
809 #[test]
810 pub fn test_show_full_tables() {
811 let sql = "SHOW FULL TABLES";
812 let stmts =
813 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
814 .unwrap();
815 assert_eq!(1, stmts.len());
816 assert_matches!(&stmts[0], Statement::ShowTables { .. });
817 match &stmts[0] {
818 Statement::ShowTables(show) => {
819 assert!(show.full);
820 }
821 _ => {
822 unreachable!();
823 }
824 }
825 }
826
827 #[test]
828 pub fn test_show_full_tables_where() {
829 let sql = "SHOW FULL TABLES IN test_db WHERE Tables LIKE test_table";
830 let stmts =
831 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
832 .unwrap();
833 assert_eq!(1, stmts.len());
834
835 assert_matches!(
836 &stmts[0],
837 Statement::ShowTables(ShowTables {
838 kind: ShowKind::Where(sqlparser::ast::Expr::Like { .. }),
839 database: Some(_),
840 full: true
841 })
842 );
843 }
844
845 #[test]
846 pub fn test_show_full_tables_like() {
847 let sql = "SHOW FULL TABLES LIKE test_table";
848 let result =
849 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
850 let stmts = result.unwrap();
851 assert_eq!(1, stmts.len());
852
853 assert_matches!(
854 &stmts[0],
855 Statement::ShowTables(ShowTables {
856 kind: ShowKind::Like(sqlparser::ast::Ident {
857 value: _,
858 quote_style: None,
859 span: _,
860 }),
861 database: None,
862 full: true
863 })
864 );
865
866 let sql = "SHOW FULL TABLES in test_db LIKE test_table";
867 let result =
868 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
869 let stmts = result.unwrap();
870 assert_eq!(1, stmts.len());
871
872 assert_matches!(
873 &stmts[0],
874 Statement::ShowTables(ShowTables {
875 kind: ShowKind::Like(sqlparser::ast::Ident {
876 value: _,
877 quote_style: None,
878 span: _,
879 }),
880 database: Some(_),
881 full: true
882 })
883 );
884 }
885
886 #[test]
887 pub fn test_show_variables() {
888 let sql = "SHOW VARIABLES system_time_zone";
889 let result =
890 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
891 let stmts = result.unwrap();
892 assert_eq!(1, stmts.len());
893 assert_eq!(
894 stmts[0],
895 Statement::ShowVariables(ShowVariables {
896 variable: ObjectName::from(vec![Ident::new("system_time_zone")]),
897 })
898 );
899 }
900
901 #[test]
902 pub fn test_show_columns() {
903 let sql = "SHOW COLUMNS";
904 let result =
905 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
906 let error = result.unwrap_err();
907 assert_eq!(
908 "Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: EOF",
909 error.to_string()
910 );
911
912 let sql = "SHOW COLUMNS from test";
913 let result =
914 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
915 let stmts = result.unwrap();
916 assert_eq!(1, stmts.len());
917 assert!(matches!(&stmts[0],
918 Statement::ShowColumns(ShowColumns {
919 table,
920 database,
921 full,
922 ..
923
924 }) if table == "test" && database.is_none() && !full));
925
926 let sql = "SHOW FULL COLUMNS from test from public";
927 let result =
928 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
929 let stmts = result.unwrap();
930 assert_eq!(1, stmts.len());
931 assert!(matches!(&stmts[0],
932 Statement::ShowColumns(ShowColumns {
933 table,
934 database: Some(database),
935 full,
936 ..
937 }) if table == "test" && database == "public" && *full));
938
939 let sql = "SHOW COLUMNS from test like 'disk%'";
940 let result =
941 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
942 let stmts = result.unwrap();
943 assert_eq!(1, stmts.len());
944 assert!(matches!(&stmts[0],
945 Statement::ShowColumns(ShowColumns {
946 table,
947 kind: ShowKind::Like(ident),
948 ..
949 }) if table == "test" && ident.to_string() == "'disk%'"));
950
951 let sql = "SHOW COLUMNS from test where Field = 'disk'";
952 let result =
953 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
954 let stmts = result.unwrap();
955 assert_eq!(1, stmts.len());
956 assert!(matches!(&stmts[0],
957 Statement::ShowColumns(ShowColumns {
958 table,
959 kind: ShowKind::Where(expr),
960 ..
961 }) if table == "test" && expr.to_string() == "Field = 'disk'"));
962 }
963
964 #[test]
965 pub fn test_show_index() {
966 let sql = "SHOW INDEX";
967 let result =
968 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
969 let error = result.unwrap_err();
970 assert_eq!(
971 "Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: EOF",
972 error.to_string()
973 );
974
975 let sql = "SHOW INDEX from test";
976 let result =
977 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
978 let stmts = result.unwrap();
979 assert_eq!(1, stmts.len());
980 assert!(matches!(&stmts[0],
981 Statement::ShowIndex(ShowIndex {
982 table,
983 database,
984 ..
985
986 }) if table == "test" && database.is_none()));
987
988 let sql = "SHOW INDEX from test from public";
989 let result =
990 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
991 let stmts = result.unwrap();
992 assert_eq!(1, stmts.len());
993 assert!(matches!(&stmts[0],
994 Statement::ShowIndex(ShowIndex {
995 table,
996 database: Some(database),
997 ..
998 }) if table == "test" && database == "public"));
999
1000 let sql = "SHOW INDEX from test like 'disk%'";
1002 let result =
1003 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1004 let error = result.unwrap_err();
1005 assert_eq!(
1006 "SQL statement is not supported, keyword: like",
1007 error.to_string()
1008 );
1009
1010 let sql = "SHOW INDEX from test where Field = 'disk'";
1011 let result =
1012 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1013 let stmts = result.unwrap();
1014 assert_eq!(1, stmts.len());
1015 assert!(matches!(&stmts[0],
1016 Statement::ShowIndex(ShowIndex {
1017 table,
1018 kind: ShowKind::Where(expr),
1019 ..
1020 }) if table == "test" && expr.to_string() == "Field = 'disk'"));
1021 }
1022
1023 #[test]
1024 fn test_show_region() {
1025 let sql = "SHOW REGION";
1026 let result =
1027 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1028 let error = result.unwrap_err();
1029 assert_eq!(
1030 "Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: EOF",
1031 error.to_string()
1032 );
1033
1034 let sql = "SHOW REGION from test";
1035 let result =
1036 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1037 let stmts = result.unwrap();
1038 assert_eq!(1, stmts.len());
1039 assert!(matches!(&stmts[0],
1040 Statement::ShowRegion(ShowRegion {
1041 table,
1042 database,
1043 ..
1044
1045 }) if table == "test" && database.is_none()));
1046
1047 let sql = "SHOW REGION from test from public";
1048 let result =
1049 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1050 let stmts = result.unwrap();
1051 assert_eq!(1, stmts.len());
1052 assert!(matches!(&stmts[0],
1053 Statement::ShowRegion(ShowRegion {
1054 table,
1055 database: Some(database),
1056 ..
1057 }) if table == "test" && database == "public"));
1058
1059 let sql = "SHOW REGION from test like 'disk%'";
1061 let result =
1062 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1063 let error = result.unwrap_err();
1064 assert_eq!(
1065 "SQL statement is not supported, keyword: like",
1066 error.to_string()
1067 );
1068
1069 let sql = "SHOW REGION from test where Field = 'disk'";
1070 let result =
1071 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1072 let stmts = result.unwrap();
1073 assert_eq!(1, stmts.len());
1074 assert!(matches!(&stmts[0],
1075 Statement::ShowRegion(ShowRegion {
1076 table,
1077 kind: ShowKind::Where(expr),
1078 ..
1079 }) if table == "test" && expr.to_string() == "Field = 'disk'"));
1080 }
1081
1082 #[test]
1083 fn parse_show_collation() {
1084 let sql = "SHOW COLLATION";
1085 let result =
1086 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1087 assert!(matches!(
1088 result.unwrap()[0],
1089 Statement::ShowCollation(ShowKind::All)
1090 ));
1091
1092 let sql = "SHOW COLLATION WHERE Charset = 'latin1'";
1093 let result =
1094 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1095 assert!(matches!(
1096 result.unwrap()[0],
1097 Statement::ShowCollation(ShowKind::Where(_))
1098 ));
1099
1100 let sql = "SHOW COLLATION LIKE 'latin1'";
1101 let result =
1102 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1103 assert!(matches!(
1104 result.unwrap()[0],
1105 Statement::ShowCollation(ShowKind::Like(_))
1106 ));
1107 }
1108
1109 #[test]
1110 fn parse_show_charset() {
1111 let sql = "SHOW CHARSET";
1112 let result =
1113 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1114 assert!(matches!(
1115 result.unwrap()[0],
1116 Statement::ShowCharset(ShowKind::All)
1117 ));
1118
1119 let sql = "SHOW CHARACTER SET";
1120 let result =
1121 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1122 assert!(matches!(
1123 result.unwrap()[0],
1124 Statement::ShowCharset(ShowKind::All)
1125 ));
1126
1127 let sql = "SHOW CHARSET WHERE Charset = 'latin1'";
1128 let result =
1129 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1130 assert!(matches!(
1131 result.unwrap()[0],
1132 Statement::ShowCharset(ShowKind::Where(_))
1133 ));
1134
1135 let sql = "SHOW CHARACTER SET LIKE 'latin1'";
1136 let result =
1137 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1138 assert!(matches!(
1139 result.unwrap()[0],
1140 Statement::ShowCharset(ShowKind::Like(_))
1141 ));
1142 }
1143
1144 fn parse_show_table_status(sql: &str) -> ShowTableStatus {
1145 let result =
1146 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1147 let mut stmts = result.unwrap();
1148 assert_eq!(1, stmts.len());
1149
1150 match stmts.remove(0) {
1151 Statement::ShowTableStatus(stmt) => stmt,
1152 _ => panic!("Failed to parse show table status"),
1153 }
1154 }
1155
1156 #[test]
1157 pub fn test_show_table_status() {
1158 let sql = "SHOW TABLE STATUS";
1159 let stmt = parse_show_table_status(sql);
1160 assert!(stmt.database.is_none());
1161 assert_eq!(sql, stmt.to_string());
1162
1163 let sql = "SHOW TABLE STATUS IN test";
1164 let stmt = parse_show_table_status(sql);
1165 assert_eq!("test", stmt.database.as_ref().unwrap());
1166 assert_eq!(sql, stmt.to_string());
1167
1168 let sql = "SHOW TABLE STATUS LIKE '%monitor'";
1169 let stmt = parse_show_table_status(sql);
1170 assert!(stmt.database.is_none());
1171 assert!(matches!(stmt.kind, ShowKind::Like(_)));
1172 assert_eq!(sql, stmt.to_string());
1173
1174 let sql = "SHOW TABLE STATUS IN test WHERE Name = 'monitor'";
1175 let stmt = parse_show_table_status(sql);
1176 assert_eq!("test", stmt.database.as_ref().unwrap());
1177 assert!(matches!(stmt.kind, ShowKind::Where(_)));
1178 assert_eq!(sql, stmt.to_string());
1179 }
1180
1181 #[test]
1182 pub fn test_show_create_view() {
1183 let sql = "SHOW CREATE VIEW test";
1184 let result =
1185 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1186 let stmts = result.unwrap();
1187 assert_eq!(1, stmts.len());
1188 assert_eq!(
1189 stmts[0],
1190 Statement::ShowCreateView(ShowCreateView {
1191 view_name: ObjectName::from(vec![Ident::new("test")]),
1192 })
1193 );
1194 assert_eq!(sql, stmts[0].to_string());
1195 }
1196
1197 #[test]
1198 pub fn test_show_views() {
1199 let sql = "SHOW VIEWS";
1200 let result =
1201 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1202 let stmts = result.unwrap();
1203 assert_eq!(1, stmts.len());
1204 assert_eq!(
1205 stmts[0],
1206 Statement::ShowViews(ShowViews {
1207 kind: ShowKind::All,
1208 database: None,
1209 })
1210 );
1211 assert_eq!(sql, stmts[0].to_string());
1212 }
1213
1214 #[test]
1215 pub fn test_show_views_in_db() {
1216 let sql = "SHOW VIEWS IN d1";
1217 let result =
1218 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1219 let stmts = result.unwrap();
1220 assert_eq!(1, stmts.len());
1221 assert_eq!(
1222 stmts[0],
1223 Statement::ShowViews(ShowViews {
1224 kind: ShowKind::All,
1225 database: Some("d1".to_string()),
1226 })
1227 );
1228 assert_eq!(sql, stmts[0].to_string());
1229 }
1230
1231 #[test]
1232 pub fn test_show_flows() {
1233 let sql = "SHOW FLOWS";
1234 let result =
1235 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1236 let stmts = result.unwrap();
1237 assert_eq!(1, stmts.len());
1238 assert_eq!(
1239 stmts[0],
1240 Statement::ShowFlows(ShowFlows {
1241 kind: ShowKind::All,
1242 database: None,
1243 })
1244 );
1245 assert_eq!(sql, stmts[0].to_string());
1246 }
1247
1248 #[test]
1249 pub fn test_show_flows_in_db() {
1250 let sql = "SHOW FLOWS IN d1";
1251 let result =
1252 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1253 let stmts = result.unwrap();
1254 assert_eq!(1, stmts.len());
1255 assert_eq!(
1256 stmts[0],
1257 Statement::ShowFlows(ShowFlows {
1258 kind: ShowKind::All,
1259 database: Some("d1".to_string()),
1260 })
1261 );
1262 assert_eq!(sql, stmts[0].to_string());
1263 }
1264
1265 #[test]
1266 pub fn test_show_flow_status() {
1267 let sql = "SHOW FLOW STATUS";
1268 let result =
1269 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1270 let stmts = result.unwrap();
1271 assert_eq!(1, stmts.len());
1272 assert_eq!(
1273 stmts[0],
1274 Statement::ShowFlowStatus(ShowFlowStatus {
1275 kind: ShowKind::All,
1276 })
1277 );
1278 assert_eq!(sql, stmts[0].to_string());
1279 }
1280
1281 #[test]
1282 pub fn test_show_processlist() {
1283 let sql = "SHOW PROCESSLIST";
1284 let result =
1285 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1286 let stmts = result.unwrap();
1287 assert_eq!(1, stmts.len());
1288 assert_eq!(
1289 stmts[0],
1290 Statement::ShowProcesslist(ShowProcessList { full: false })
1291 );
1292 assert_eq!(sql, stmts[0].to_string());
1293
1294 let sql = "SHOW FULL PROCESSLIST";
1295 let result =
1296 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1297 let stmts = result.unwrap();
1298 assert_eq!(1, stmts.len());
1299 assert_eq!(
1300 stmts[0],
1301 Statement::ShowProcesslist(ShowProcessList { full: true })
1302 );
1303 assert_eq!(sql, stmts[0].to_string());
1304 }
1305
1306 #[cfg(feature = "enterprise")]
1307 #[test]
1308 pub fn test_parse_show_create_trigger() {
1309 let sql = "SHOW CREATE TRIGGER test_trigger";
1310 let result =
1311 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1312 let stmts = result.unwrap();
1313 assert_eq!(1, stmts.len());
1314 assert_eq!(
1315 stmts[0],
1316 Statement::ShowCreateTrigger(ShowCreateTrigger {
1317 trigger_name: ObjectName::from(vec![Ident::new("test_trigger")]),
1318 })
1319 );
1320 assert_eq!(sql, stmts[0].to_string());
1321 }
1322
1323 #[cfg(feature = "enterprise")]
1324 #[test]
1325 pub fn test_parse_show_triggers() {
1326 let sql = "SHOW TRIGGERS";
1327 let result =
1328 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1329 let stmts = result.unwrap();
1330 assert_eq!(1, stmts.len());
1331 assert_eq!(
1332 stmts[0],
1333 Statement::ShowTriggers(ShowTriggers {
1334 kind: ShowKind::All,
1335 })
1336 );
1337 assert_eq!(sql, stmts[0].to_string());
1338 }
1339
1340 #[cfg(feature = "enterprise")]
1341 #[test]
1342 pub fn test_parse_show_triggers_like() {
1343 let sql = "SHOW TRIGGERS LIKE 'test_trigger'";
1344 let result =
1345 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1346 let stmts = result.unwrap();
1347 assert_eq!(1, stmts.len());
1348 assert_eq!(
1349 stmts[0],
1350 Statement::ShowTriggers(ShowTriggers {
1351 kind: ShowKind::Like(Ident::with_quote('\'', "test_trigger")),
1352 })
1353 );
1354 assert_eq!(sql, stmts[0].to_string());
1355 }
1356
1357 #[cfg(feature = "enterprise")]
1358 #[test]
1359 pub fn test_parse_show_triggers_where() {
1360 let sql = "SHOW TRIGGERS WHERE name = 'test_trigger'";
1361 let result =
1362 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1363 let stmts = result.unwrap();
1364 assert_eq!(1, stmts.len());
1365 assert!(matches!(
1366 &stmts[0],
1367 Statement::ShowTriggers(ShowTriggers {
1368 kind: ShowKind::Where(_)
1369 })
1370 ));
1371 assert_eq!(sql, stmts[0].to_string());
1372 }
1373}