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