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