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