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