Skip to main content

sql/statements/
show.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::{self, Display};
16
17use serde::Serialize;
18use sqlparser_derive::{Visit, VisitMut};
19
20use crate::ast::{Expr, Ident, ObjectName};
21
22/// Show kind for SQL expressions like `SHOW DATABASE` or `SHOW TABLE`
23#[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            // The `All` is the default kind placeholder, not a valid statement.
34            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/// SQL structure for `SHOW DATABASES`.
53#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
54pub struct ShowDatabases {
55    pub kind: ShowKind,
56    pub full: bool,
57}
58
59/// The SQL `SHOW COLUMNS` statement
60#[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/// The SQL `SHOW INDEX` statement
84#[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/// The SQL `SHOW REGION` statement
104#[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    /// Creates a statement for `SHOW DATABASES`
124    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/// SQL structure for `SHOW TABLES`.
144#[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/// SQL structure for `SHOW TABLE STATUS`.
168#[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/// SQL structure for `SHOW CREATE DATABASE`.
188#[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/// SQL structure for `SHOW CREATE TABLE`.
201#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
202pub struct ShowCreateTable {
203    pub table_name: ObjectName,
204    pub variant: ShowCreateTableVariant,
205}
206
207/// Variant of a show create table
208#[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/// SQL structure for `SHOW CREATE FLOW`.
228#[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/// SQL structure for `SHOW FLOWS`.
241#[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/// SQL structure for `SHOW FLOW STATUS`.
260#[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/// SQL structure for `SHOW CREATE VIEW`.
275#[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/// SQL structure for `SHOW VIEWS`.
288#[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/// SQL structure for `SHOW VARIABLES xxx`.
307#[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/// SQL structure for "SHOW STATUS"
320#[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/// SQL structure for "SHOW SEARCH_PATH" postgres only
330#[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/// SQL structure for `SHOW PROCESSLIST`.
340#[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}