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 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!(
880 "Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: EOF",
881 error.to_string()
882 );
883
884 let sql = "SHOW COLUMNS from test";
885 let result =
886 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
887 let stmts = result.unwrap();
888 assert_eq!(1, stmts.len());
889 assert!(matches!(&stmts[0],
890 Statement::ShowColumns(ShowColumns {
891 table,
892 database,
893 full,
894 ..
895
896 }) if table == "test" && database.is_none() && !full));
897
898 let sql = "SHOW FULL COLUMNS from test from public";
899 let result =
900 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
901 let stmts = result.unwrap();
902 assert_eq!(1, stmts.len());
903 assert!(matches!(&stmts[0],
904 Statement::ShowColumns(ShowColumns {
905 table,
906 database: Some(database),
907 full,
908 ..
909 }) if table == "test" && database == "public" && *full));
910
911 let sql = "SHOW COLUMNS from test like 'disk%'";
912 let result =
913 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
914 let stmts = result.unwrap();
915 assert_eq!(1, stmts.len());
916 assert!(matches!(&stmts[0],
917 Statement::ShowColumns(ShowColumns {
918 table,
919 kind: ShowKind::Like(ident),
920 ..
921 }) if table == "test" && ident.to_string() == "'disk%'"));
922
923 let sql = "SHOW COLUMNS from test where Field = 'disk'";
924 let result =
925 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
926 let stmts = result.unwrap();
927 assert_eq!(1, stmts.len());
928 assert!(matches!(&stmts[0],
929 Statement::ShowColumns(ShowColumns {
930 table,
931 kind: ShowKind::Where(expr),
932 ..
933 }) if table == "test" && expr.to_string() == "Field = 'disk'"));
934 }
935
936 #[test]
937 pub fn test_show_index() {
938 let sql = "SHOW INDEX";
939 let result =
940 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
941 let error = result.unwrap_err();
942 assert_eq!(
943 "Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: EOF",
944 error.to_string()
945 );
946
947 let sql = "SHOW INDEX from test";
948 let result =
949 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
950 let stmts = result.unwrap();
951 assert_eq!(1, stmts.len());
952 assert!(matches!(&stmts[0],
953 Statement::ShowIndex(ShowIndex {
954 table,
955 database,
956 ..
957
958 }) if table == "test" && database.is_none()));
959
960 let sql = "SHOW INDEX from test from public";
961 let result =
962 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
963 let stmts = result.unwrap();
964 assert_eq!(1, stmts.len());
965 assert!(matches!(&stmts[0],
966 Statement::ShowIndex(ShowIndex {
967 table,
968 database: Some(database),
969 ..
970 }) if table == "test" && database == "public"));
971
972 let sql = "SHOW INDEX from test like 'disk%'";
974 let result =
975 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
976 let error = result.unwrap_err();
977 assert_eq!(
978 "SQL statement is not supported, keyword: like",
979 error.to_string()
980 );
981
982 let sql = "SHOW INDEX from test where Field = 'disk'";
983 let result =
984 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
985 let stmts = result.unwrap();
986 assert_eq!(1, stmts.len());
987 assert!(matches!(&stmts[0],
988 Statement::ShowIndex(ShowIndex {
989 table,
990 kind: ShowKind::Where(expr),
991 ..
992 }) if table == "test" && expr.to_string() == "Field = 'disk'"));
993 }
994
995 #[test]
996 fn test_show_region() {
997 let sql = "SHOW REGION";
998 let result =
999 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1000 let error = result.unwrap_err();
1001 assert_eq!(
1002 "Unexpected token while parsing SQL statement, expected: '{FROM | IN} table', found: EOF",
1003 error.to_string()
1004 );
1005
1006 let sql = "SHOW REGION from test";
1007 let result =
1008 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1009 let stmts = result.unwrap();
1010 assert_eq!(1, stmts.len());
1011 assert!(matches!(&stmts[0],
1012 Statement::ShowRegion(ShowRegion {
1013 table,
1014 database,
1015 ..
1016
1017 }) if table == "test" && database.is_none()));
1018
1019 let sql = "SHOW REGION from test from public";
1020 let result =
1021 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1022 let stmts = result.unwrap();
1023 assert_eq!(1, stmts.len());
1024 assert!(matches!(&stmts[0],
1025 Statement::ShowRegion(ShowRegion {
1026 table,
1027 database: Some(database),
1028 ..
1029 }) if table == "test" && database == "public"));
1030
1031 let sql = "SHOW REGION from test like 'disk%'";
1033 let result =
1034 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1035 let error = result.unwrap_err();
1036 assert_eq!(
1037 "SQL statement is not supported, keyword: like",
1038 error.to_string()
1039 );
1040
1041 let sql = "SHOW REGION from test where Field = 'disk'";
1042 let result =
1043 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1044 let stmts = result.unwrap();
1045 assert_eq!(1, stmts.len());
1046 assert!(matches!(&stmts[0],
1047 Statement::ShowRegion(ShowRegion {
1048 table,
1049 kind: ShowKind::Where(expr),
1050 ..
1051 }) if table == "test" && expr.to_string() == "Field = 'disk'"));
1052 }
1053
1054 #[test]
1055 fn parse_show_collation() {
1056 let sql = "SHOW COLLATION";
1057 let result =
1058 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1059 assert!(matches!(
1060 result.unwrap()[0],
1061 Statement::ShowCollation(ShowKind::All)
1062 ));
1063
1064 let sql = "SHOW COLLATION WHERE Charset = 'latin1'";
1065 let result =
1066 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1067 assert!(matches!(
1068 result.unwrap()[0],
1069 Statement::ShowCollation(ShowKind::Where(_))
1070 ));
1071
1072 let sql = "SHOW COLLATION LIKE 'latin1'";
1073 let result =
1074 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1075 assert!(matches!(
1076 result.unwrap()[0],
1077 Statement::ShowCollation(ShowKind::Like(_))
1078 ));
1079 }
1080
1081 #[test]
1082 fn parse_show_charset() {
1083 let sql = "SHOW CHARSET";
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 CHARACTER SET";
1092 let result =
1093 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1094 assert!(matches!(
1095 result.unwrap()[0],
1096 Statement::ShowCharset(ShowKind::All)
1097 ));
1098
1099 let sql = "SHOW CHARSET WHERE Charset = 'latin1'";
1100 let result =
1101 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1102 assert!(matches!(
1103 result.unwrap()[0],
1104 Statement::ShowCharset(ShowKind::Where(_))
1105 ));
1106
1107 let sql = "SHOW CHARACTER SET LIKE 'latin1'";
1108 let result =
1109 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1110 assert!(matches!(
1111 result.unwrap()[0],
1112 Statement::ShowCharset(ShowKind::Like(_))
1113 ));
1114 }
1115
1116 fn parse_show_table_status(sql: &str) -> ShowTableStatus {
1117 let result =
1118 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1119 let mut stmts = result.unwrap();
1120 assert_eq!(1, stmts.len());
1121
1122 match stmts.remove(0) {
1123 Statement::ShowTableStatus(stmt) => stmt,
1124 _ => panic!("Failed to parse show table status"),
1125 }
1126 }
1127
1128 #[test]
1129 pub fn test_show_table_status() {
1130 let sql = "SHOW TABLE STATUS";
1131 let stmt = parse_show_table_status(sql);
1132 assert!(stmt.database.is_none());
1133 assert_eq!(sql, stmt.to_string());
1134
1135 let sql = "SHOW TABLE STATUS IN test";
1136 let stmt = parse_show_table_status(sql);
1137 assert_eq!("test", stmt.database.as_ref().unwrap());
1138 assert_eq!(sql, stmt.to_string());
1139
1140 let sql = "SHOW TABLE STATUS LIKE '%monitor'";
1141 let stmt = parse_show_table_status(sql);
1142 assert!(stmt.database.is_none());
1143 assert!(matches!(stmt.kind, ShowKind::Like(_)));
1144 assert_eq!(sql, stmt.to_string());
1145
1146 let sql = "SHOW TABLE STATUS IN test WHERE Name = 'monitor'";
1147 let stmt = parse_show_table_status(sql);
1148 assert_eq!("test", stmt.database.as_ref().unwrap());
1149 assert!(matches!(stmt.kind, ShowKind::Where(_)));
1150 assert_eq!(sql, stmt.to_string());
1151 }
1152
1153 #[test]
1154 pub fn test_show_create_view() {
1155 let sql = "SHOW CREATE VIEW test";
1156 let result =
1157 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1158 let stmts = result.unwrap();
1159 assert_eq!(1, stmts.len());
1160 assert_eq!(
1161 stmts[0],
1162 Statement::ShowCreateView(ShowCreateView {
1163 view_name: ObjectName::from(vec![Ident::new("test")]),
1164 })
1165 );
1166 assert_eq!(sql, stmts[0].to_string());
1167 }
1168
1169 #[test]
1170 pub fn test_show_views() {
1171 let sql = "SHOW VIEWS";
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::ShowViews(ShowViews {
1179 kind: ShowKind::All,
1180 database: None,
1181 })
1182 );
1183 assert_eq!(sql, stmts[0].to_string());
1184 }
1185
1186 #[test]
1187 pub fn test_show_views_in_db() {
1188 let sql = "SHOW VIEWS IN d1";
1189 let result =
1190 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1191 let stmts = result.unwrap();
1192 assert_eq!(1, stmts.len());
1193 assert_eq!(
1194 stmts[0],
1195 Statement::ShowViews(ShowViews {
1196 kind: ShowKind::All,
1197 database: Some("d1".to_string()),
1198 })
1199 );
1200 assert_eq!(sql, stmts[0].to_string());
1201 }
1202
1203 #[test]
1204 pub fn test_show_flows() {
1205 let sql = "SHOW FLOWS";
1206 let result =
1207 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1208 let stmts = result.unwrap();
1209 assert_eq!(1, stmts.len());
1210 assert_eq!(
1211 stmts[0],
1212 Statement::ShowFlows(ShowFlows {
1213 kind: ShowKind::All,
1214 database: None,
1215 })
1216 );
1217 assert_eq!(sql, stmts[0].to_string());
1218 }
1219
1220 #[test]
1221 pub fn test_show_flows_in_db() {
1222 let sql = "SHOW FLOWS IN d1";
1223 let result =
1224 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1225 let stmts = result.unwrap();
1226 assert_eq!(1, stmts.len());
1227 assert_eq!(
1228 stmts[0],
1229 Statement::ShowFlows(ShowFlows {
1230 kind: ShowKind::All,
1231 database: Some("d1".to_string()),
1232 })
1233 );
1234 assert_eq!(sql, stmts[0].to_string());
1235 }
1236
1237 #[test]
1238 pub fn test_show_processlist() {
1239 let sql = "SHOW PROCESSLIST";
1240 let result =
1241 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1242 let stmts = result.unwrap();
1243 assert_eq!(1, stmts.len());
1244 assert_eq!(
1245 stmts[0],
1246 Statement::ShowProcesslist(ShowProcessList { full: false })
1247 );
1248 assert_eq!(sql, stmts[0].to_string());
1249
1250 let sql = "SHOW FULL PROCESSLIST";
1251 let result =
1252 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
1253 let stmts = result.unwrap();
1254 assert_eq!(1, stmts.len());
1255 assert_eq!(
1256 stmts[0],
1257 Statement::ShowProcesslist(ShowProcessList { full: true })
1258 );
1259 assert_eq!(sql, stmts[0].to_string());
1260 }
1261}