1use std::fmt::{self, Display};
16
17use serde::Serialize;
18use sqlparser_derive::{Visit, VisitMut};
19
20use crate::ast::{Expr, Ident, ObjectName};
21
22#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
24pub enum ShowKind {
25 All,
26 Like(Ident),
27 Where(Expr),
28}
29
30impl Display for ShowKind {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 match self {
33 ShowKind::All => write!(f, ""),
35 ShowKind::Like(ident) => write!(f, "LIKE {ident}"),
36 ShowKind::Where(expr) => write!(f, "WHERE {expr}"),
37 }
38 }
39}
40
41macro_rules! format_kind {
42 ($self: expr, $f: expr) => {
43 if $self.kind != ShowKind::All {
44 write!($f, " {}", &$self.kind)?;
45 }
46 };
47}
48
49#[cfg(feature = "enterprise")]
50pub mod trigger;
51
52#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
54pub struct ShowDatabases {
55 pub kind: ShowKind,
56 pub full: bool,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
61pub struct ShowColumns {
62 pub kind: ShowKind,
63 pub table: String,
64 pub database: Option<String>,
65 pub full: bool,
66}
67
68impl Display for ShowColumns {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "SHOW ")?;
71 if self.full {
72 write!(f, "FULL ")?;
73 }
74 write!(f, "COLUMNS IN {}", &self.table)?;
75 if let Some(database) = &self.database {
76 write!(f, " IN {database}")?;
77 }
78 format_kind!(self, f);
79 Ok(())
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
85pub struct ShowIndex {
86 pub kind: ShowKind,
87 pub table: String,
88 pub database: Option<String>,
89}
90
91impl Display for ShowIndex {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 write!(f, "SHOW INDEX IN {}", &self.table)?;
94 if let Some(database) = &self.database {
95 write!(f, " IN {database}")?;
96 }
97 format_kind!(self, f);
98
99 Ok(())
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
105pub struct ShowRegion {
106 pub kind: ShowKind,
107 pub table: String,
108 pub database: Option<String>,
109}
110
111impl Display for ShowRegion {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 write!(f, "SHOW REGION IN {}", &self.table)?;
114 if let Some(database) = &self.database {
115 write!(f, " IN {database}")?;
116 }
117 format_kind!(self, f);
118 Ok(())
119 }
120}
121
122impl ShowDatabases {
123 pub fn new(kind: ShowKind, full: bool) -> Self {
125 ShowDatabases { kind, full }
126 }
127}
128
129impl Display for ShowDatabases {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 if self.full {
132 write!(f, "SHOW FULL DATABASES")?;
133 } else {
134 write!(f, "SHOW DATABASES")?;
135 }
136
137 format_kind!(self, f);
138
139 Ok(())
140 }
141}
142
143#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
145pub struct ShowTables {
146 pub kind: ShowKind,
147 pub database: Option<String>,
148 pub full: bool,
149}
150
151impl Display for ShowTables {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 write!(f, "SHOW ")?;
154 if self.full {
155 write!(f, "FULL ")?;
156 }
157 write!(f, "TABLES")?;
158 if let Some(database) = &self.database {
159 write!(f, " IN {database}")?;
160 }
161 format_kind!(self, f);
162
163 Ok(())
164 }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
169pub struct ShowTableStatus {
170 pub kind: ShowKind,
171 pub database: Option<String>,
172}
173
174impl Display for ShowTableStatus {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 write!(f, "SHOW TABLE STATUS")?;
177 if let Some(database) = &self.database {
178 write!(f, " IN {database}")?;
179 }
180
181 format_kind!(self, f);
182
183 Ok(())
184 }
185}
186
187#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
189pub struct ShowCreateDatabase {
190 pub database_name: ObjectName,
191}
192
193impl Display for ShowCreateDatabase {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 let database_name = &self.database_name;
196 write!(f, r#"SHOW CREATE DATABASE {database_name}"#)
197 }
198}
199
200#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
202pub struct ShowCreateTable {
203 pub table_name: ObjectName,
204 pub variant: ShowCreateTableVariant,
205}
206
207#[derive(Default, Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
209pub enum ShowCreateTableVariant {
210 #[default]
211 Original,
212 PostgresForeignTable,
213}
214
215impl Display for ShowCreateTable {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 let table_name = &self.table_name;
218 write!(f, r#"SHOW CREATE TABLE {table_name}"#)?;
219 if let ShowCreateTableVariant::PostgresForeignTable = self.variant {
220 write!(f, " FOR POSTGRES_FOREIGN_TABLE")?;
221 }
222
223 Ok(())
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
229pub struct ShowCreateFlow {
230 pub flow_name: ObjectName,
231}
232
233impl Display for ShowCreateFlow {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 let flow_name = &self.flow_name;
236 write!(f, "SHOW CREATE FLOW {flow_name}")
237 }
238}
239
240#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
242pub struct ShowFlows {
243 pub kind: ShowKind,
244 pub database: Option<String>,
245}
246
247impl Display for ShowFlows {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 write!(f, "SHOW FLOWS")?;
250 if let Some(database) = &self.database {
251 write!(f, " IN {database}")?;
252 }
253 format_kind!(self, f);
254
255 Ok(())
256 }
257}
258
259#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
261pub struct ShowFlowStatus {
262 pub kind: ShowKind,
263}
264
265impl Display for ShowFlowStatus {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 write!(f, "SHOW FLOW STATUS")?;
268 format_kind!(self, f);
269
270 Ok(())
271 }
272}
273
274#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
276pub struct ShowCreateView {
277 pub view_name: ObjectName,
278}
279
280impl Display for ShowCreateView {
281 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282 let view_name = &self.view_name;
283 write!(f, "SHOW CREATE VIEW {view_name}")
284 }
285}
286
287#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
289pub struct ShowViews {
290 pub kind: ShowKind,
291 pub database: Option<String>,
292}
293
294impl Display for ShowViews {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 write!(f, "SHOW VIEWS")?;
297 if let Some(database) = &self.database {
298 write!(f, " IN {database}")?;
299 }
300 format_kind!(self, f);
301
302 Ok(())
303 }
304}
305
306#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
308pub struct ShowVariables {
309 pub variable: ObjectName,
310}
311
312impl Display for ShowVariables {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 let variable = &self.variable;
315 write!(f, r#"SHOW VARIABLES {variable}"#)
316 }
317}
318
319#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
321pub struct ShowStatus {}
322
323impl Display for ShowStatus {
324 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325 write!(f, "SHOW STATUS")
326 }
327}
328
329#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
331pub struct ShowSearchPath {}
332
333impl Display for ShowSearchPath {
334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335 write!(f, "SHOW SEARCH_PATH")
336 }
337}
338
339#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
341pub struct ShowProcessList {
342 pub full: bool,
343}
344impl Display for ShowProcessList {
345 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346 if self.full {
347 write!(f, "SHOW FULL PROCESSLIST")?;
348 } else {
349 write!(f, "SHOW PROCESSLIST")?;
350 }
351
352 Ok(())
353 }
354}
355
356#[cfg(test)]
357mod tests {
358 use std::assert_matches;
359
360 use sqlparser::ast::UnaryOperator;
361
362 use super::*;
363 use crate::dialect::GreptimeDbDialect;
364 use crate::parser::{ParseOptions, ParserContext};
365 use crate::statements::statement::Statement;
366
367 #[test]
368 fn test_kind_display() {
369 assert_eq!("", format!("{}", ShowKind::All));
370 assert_eq!(
371 "LIKE test",
372 format!("{}", ShowKind::Like(Ident::new("test")),)
373 );
374 assert_eq!(
375 "WHERE NOT a",
376 format!(
377 "{}",
378 ShowKind::Where(Expr::UnaryOp {
379 op: UnaryOperator::Not,
380 expr: Box::new(Expr::Identifier(Ident::new("a"))),
381 })
382 )
383 );
384 }
385
386 #[test]
387 pub fn test_show_database() {
388 let sql = "SHOW DATABASES";
389 let stmts =
390 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
391 .unwrap();
392 assert_eq!(1, stmts.len());
393 assert_matches!(&stmts[0], Statement::ShowDatabases { .. });
394 match &stmts[0] {
395 Statement::ShowDatabases(show) => {
396 assert_eq!(ShowKind::All, show.kind);
397 }
398 _ => {
399 unreachable!();
400 }
401 }
402 }
403
404 #[test]
405 pub fn test_show_create_table() {
406 let sql = "SHOW CREATE TABLE test";
407 let stmts: Vec<Statement> =
408 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
409 .unwrap();
410 assert_eq!(1, stmts.len());
411 assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
412 match &stmts[0] {
413 Statement::ShowCreateTable(show) => {
414 let table_name = show.table_name.to_string();
415 assert_eq!(table_name, "test");
416 assert_eq!(show.variant, ShowCreateTableVariant::Original);
417 }
418 _ => {
419 unreachable!();
420 }
421 }
422
423 let sql = "SHOW CREATE TABLE test FOR POSTGRES_FOREIGN_TABLE";
424 let stmts: Vec<Statement> =
425 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
426 .unwrap();
427 assert_eq!(1, stmts.len());
428 assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
429 match &stmts[0] {
430 Statement::ShowCreateTable(show) => {
431 let table_name = show.table_name.to_string();
432 assert_eq!(table_name, "test");
433 assert_eq!(show.variant, ShowCreateTableVariant::PostgresForeignTable);
434 }
435 _ => {
436 unreachable!();
437 }
438 }
439 }
440
441 #[test]
442 pub fn test_show_create_missing_table_name() {
443 let sql = "SHOW CREATE TABLE";
444 assert!(
445 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
446 .is_err()
447 );
448 }
449
450 #[test]
451 pub fn test_show_create_unknown_for() {
452 let sql = "SHOW CREATE TABLE t FOR UNKNOWN";
453 assert!(
454 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
455 .is_err()
456 );
457 }
458
459 #[test]
460 pub fn test_show_create_flow() {
461 let sql = "SHOW CREATE FLOW test";
462 let stmts: Vec<Statement> =
463 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
464 .unwrap();
465 assert_eq!(1, stmts.len());
466 assert_matches!(&stmts[0], Statement::ShowCreateFlow { .. });
467 match &stmts[0] {
468 Statement::ShowCreateFlow(show) => {
469 let flow_name = show.flow_name.to_string();
470 assert_eq!(flow_name, "test");
471 }
472 _ => {
473 unreachable!();
474 }
475 }
476 }
477 #[test]
478 pub fn test_show_create_missing_flow() {
479 let sql = "SHOW CREATE FLOW";
480 assert!(
481 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
482 .is_err()
483 );
484 }
485
486 #[test]
487 fn test_display_show_variables() {
488 let sql = r"show variables v1;";
489 let stmts: Vec<Statement> =
490 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
491 .unwrap();
492 assert_eq!(1, stmts.len());
493 assert_matches!(&stmts[0], Statement::ShowVariables { .. });
494 match &stmts[0] {
495 Statement::ShowVariables(show) => {
496 let new_sql = format!("\n{}", show);
497 assert_eq!(
498 r#"
499SHOW VARIABLES v1"#,
500 &new_sql
501 );
502 }
503 _ => {
504 unreachable!();
505 }
506 }
507 }
508
509 #[test]
510 fn test_display_show_create_table() {
511 let sql = r"show create table monitor;";
512 let stmts: Vec<Statement> =
513 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
514 .unwrap();
515 assert_eq!(1, stmts.len());
516 assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
517 match &stmts[0] {
518 Statement::ShowCreateTable(show) => {
519 let new_sql = format!("\n{}", show);
520 assert_eq!(
521 r#"
522SHOW CREATE TABLE monitor"#,
523 &new_sql
524 );
525 }
526 _ => {
527 unreachable!();
528 }
529 }
530 }
531
532 #[test]
533 fn test_display_show_index() {
534 let sql = r"show index from t1 from d1;";
535 let stmts: Vec<Statement> =
536 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
537 .unwrap();
538 assert_eq!(1, stmts.len());
539 assert_matches!(&stmts[0], Statement::ShowIndex { .. });
540 match &stmts[0] {
541 Statement::ShowIndex(show) => {
542 let new_sql = format!("\n{}", show);
543 assert_eq!(
544 r#"
545SHOW INDEX IN t1 IN d1"#,
546 &new_sql
547 );
548 }
549 _ => {
550 unreachable!();
551 }
552 }
553 }
554
555 #[test]
556 fn test_display_show_columns() {
557 let sql = r"show full columns in t1 in d1;";
558 let stmts: Vec<Statement> =
559 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
560 .unwrap();
561 assert_eq!(1, stmts.len());
562 assert_matches!(&stmts[0], Statement::ShowColumns { .. });
563 match &stmts[0] {
564 Statement::ShowColumns(show) => {
565 let new_sql = format!("\n{}", show);
566 assert_eq!(
567 r#"
568SHOW FULL COLUMNS IN t1 IN d1"#,
569 &new_sql
570 );
571 }
572 _ => {
573 unreachable!();
574 }
575 }
576 }
577
578 #[test]
579 fn test_display_show_tables() {
580 let sql = r"show full tables in d1;";
581 let stmts: Vec<Statement> =
582 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
583 .unwrap();
584 assert_eq!(1, stmts.len());
585 assert_matches!(&stmts[0], Statement::ShowTables { .. });
586 match &stmts[0] {
587 Statement::ShowTables(show) => {
588 let new_sql = format!("\n{}", show);
589 assert_eq!(
590 r#"
591SHOW FULL TABLES IN d1"#,
592 &new_sql
593 );
594 }
595 _ => {
596 unreachable!();
597 }
598 }
599
600 let sql = r"show full tables;";
601 let stmts: Vec<Statement> =
602 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
603 .unwrap();
604 assert_eq!(1, stmts.len());
605 assert_matches!(&stmts[0], Statement::ShowTables { .. });
606 match &stmts[0] {
607 Statement::ShowTables(show) => {
608 let new_sql = format!("\n{}", show);
609 assert_eq!(
610 r#"
611SHOW FULL TABLES"#,
612 &new_sql
613 );
614 }
615 _ => {
616 unreachable!();
617 }
618 }
619 }
620
621 #[test]
622 fn test_display_show_views() {
623 let sql = r"show views in d1;";
624 let stmts: Vec<Statement> =
625 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
626 .unwrap();
627 assert_eq!(1, stmts.len());
628 assert_matches!(&stmts[0], Statement::ShowViews { .. });
629 match &stmts[0] {
630 Statement::ShowViews(show) => {
631 let new_sql = format!("\n{}", show);
632 assert_eq!(
633 r#"
634SHOW VIEWS IN d1"#,
635 &new_sql
636 );
637 }
638 _ => {
639 unreachable!();
640 }
641 }
642
643 let sql = r"show views;";
644 let stmts: Vec<Statement> =
645 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
646 .unwrap();
647 assert_eq!(1, stmts.len());
648 assert_matches!(&stmts[0], Statement::ShowViews { .. });
649 match &stmts[0] {
650 Statement::ShowViews(show) => {
651 let new_sql = format!("\n{}", show);
652 assert_eq!(
653 r#"
654SHOW VIEWS"#,
655 &new_sql
656 );
657 }
658 _ => {
659 unreachable!();
660 }
661 }
662 }
663
664 #[test]
665 fn test_display_show_flows() {
666 let sql = r"show flows in d1;";
667 let stmts: Vec<Statement> =
668 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
669 .unwrap();
670 assert_eq!(1, stmts.len());
671 assert_matches!(&stmts[0], Statement::ShowFlows { .. });
672 match &stmts[0] {
673 Statement::ShowFlows(show) => {
674 let new_sql = format!("\n{}", show);
675 assert_eq!(
676 r#"
677SHOW FLOWS IN d1"#,
678 &new_sql
679 );
680 }
681 _ => {
682 unreachable!();
683 }
684 }
685
686 let sql = r"show flows;";
687 let stmts: Vec<Statement> =
688 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
689 .unwrap();
690 assert_eq!(1, stmts.len());
691 assert_matches!(&stmts[0], Statement::ShowFlows { .. });
692 match &stmts[0] {
693 Statement::ShowFlows(show) => {
694 let new_sql = format!("\n{}", show);
695 assert_eq!(
696 r#"
697SHOW FLOWS"#,
698 &new_sql
699 );
700 }
701 _ => {
702 unreachable!("{:?}", &stmts[0]);
703 }
704 }
705 }
706
707 #[test]
708 fn test_display_show_databases() {
709 let sql = r"show databases;";
710 let stmts: Vec<Statement> =
711 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
712 .unwrap();
713 assert_eq!(1, stmts.len());
714 assert_matches!(&stmts[0], Statement::ShowDatabases { .. });
715 match &stmts[0] {
716 Statement::ShowDatabases(show) => {
717 let new_sql = format!("\n{}", show);
718 assert_eq!(
719 r#"
720SHOW DATABASES"#,
721 &new_sql
722 );
723 }
724 _ => {
725 unreachable!();
726 }
727 }
728 }
729}