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