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 CREATE VIEW`.
260#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
261pub struct ShowCreateView {
262    pub view_name: ObjectName,
263}
264
265impl Display for ShowCreateView {
266    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267        let view_name = &self.view_name;
268        write!(f, "SHOW CREATE VIEW {view_name}")
269    }
270}
271
272/// SQL structure for `SHOW VIEWS`.
273#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
274pub struct ShowViews {
275    pub kind: ShowKind,
276    pub database: Option<String>,
277}
278
279impl Display for ShowViews {
280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281        write!(f, "SHOW VIEWS")?;
282        if let Some(database) = &self.database {
283            write!(f, " IN {database}")?;
284        }
285        format_kind!(self, f);
286
287        Ok(())
288    }
289}
290
291/// SQL structure for `SHOW VARIABLES xxx`.
292#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
293pub struct ShowVariables {
294    pub variable: ObjectName,
295}
296
297impl Display for ShowVariables {
298    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299        let variable = &self.variable;
300        write!(f, r#"SHOW VARIABLES {variable}"#)
301    }
302}
303
304/// SQL structure for "SHOW STATUS"
305#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
306pub struct ShowStatus {}
307
308impl Display for ShowStatus {
309    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310        write!(f, "SHOW STATUS")
311    }
312}
313
314/// SQL structure for "SHOW SEARCH_PATH" postgres only
315#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
316pub struct ShowSearchPath {}
317
318impl Display for ShowSearchPath {
319    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320        write!(f, "SHOW SEARCH_PATH")
321    }
322}
323
324/// SQL structure for `SHOW PROCESSLIST`.
325#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
326pub struct ShowProcessList {
327    pub full: bool,
328}
329impl Display for ShowProcessList {
330    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331        if self.full {
332            write!(f, "SHOW FULL PROCESSLIST")?;
333        } else {
334            write!(f, "SHOW PROCESSLIST")?;
335        }
336
337        Ok(())
338    }
339}
340
341#[cfg(test)]
342mod tests {
343    use std::assert_matches::assert_matches;
344
345    use sqlparser::ast::UnaryOperator;
346
347    use super::*;
348    use crate::dialect::GreptimeDbDialect;
349    use crate::parser::{ParseOptions, ParserContext};
350    use crate::statements::statement::Statement;
351
352    #[test]
353    fn test_kind_display() {
354        assert_eq!("", format!("{}", ShowKind::All));
355        assert_eq!(
356            "LIKE test",
357            format!("{}", ShowKind::Like(Ident::new("test")),)
358        );
359        assert_eq!(
360            "WHERE NOT a",
361            format!(
362                "{}",
363                ShowKind::Where(Expr::UnaryOp {
364                    op: UnaryOperator::Not,
365                    expr: Box::new(Expr::Identifier(Ident::new("a"))),
366                })
367            )
368        );
369    }
370
371    #[test]
372    pub fn test_show_database() {
373        let sql = "SHOW DATABASES";
374        let stmts =
375            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
376                .unwrap();
377        assert_eq!(1, stmts.len());
378        assert_matches!(&stmts[0], Statement::ShowDatabases { .. });
379        match &stmts[0] {
380            Statement::ShowDatabases(show) => {
381                assert_eq!(ShowKind::All, show.kind);
382            }
383            _ => {
384                unreachable!();
385            }
386        }
387    }
388
389    #[test]
390    pub fn test_show_create_table() {
391        let sql = "SHOW CREATE TABLE test";
392        let stmts: Vec<Statement> =
393            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
394                .unwrap();
395        assert_eq!(1, stmts.len());
396        assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
397        match &stmts[0] {
398            Statement::ShowCreateTable(show) => {
399                let table_name = show.table_name.to_string();
400                assert_eq!(table_name, "test");
401                assert_eq!(show.variant, ShowCreateTableVariant::Original);
402            }
403            _ => {
404                unreachable!();
405            }
406        }
407
408        let sql = "SHOW CREATE TABLE test FOR POSTGRES_FOREIGN_TABLE";
409        let stmts: Vec<Statement> =
410            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
411                .unwrap();
412        assert_eq!(1, stmts.len());
413        assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
414        match &stmts[0] {
415            Statement::ShowCreateTable(show) => {
416                let table_name = show.table_name.to_string();
417                assert_eq!(table_name, "test");
418                assert_eq!(show.variant, ShowCreateTableVariant::PostgresForeignTable);
419            }
420            _ => {
421                unreachable!();
422            }
423        }
424    }
425
426    #[test]
427    pub fn test_show_create_missing_table_name() {
428        let sql = "SHOW CREATE TABLE";
429        assert!(
430            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
431                .is_err()
432        );
433    }
434
435    #[test]
436    pub fn test_show_create_unknown_for() {
437        let sql = "SHOW CREATE TABLE t FOR UNKNOWN";
438        assert!(
439            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
440                .is_err()
441        );
442    }
443
444    #[test]
445    pub fn test_show_create_flow() {
446        let sql = "SHOW CREATE FLOW test";
447        let stmts: Vec<Statement> =
448            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
449                .unwrap();
450        assert_eq!(1, stmts.len());
451        assert_matches!(&stmts[0], Statement::ShowCreateFlow { .. });
452        match &stmts[0] {
453            Statement::ShowCreateFlow(show) => {
454                let flow_name = show.flow_name.to_string();
455                assert_eq!(flow_name, "test");
456            }
457            _ => {
458                unreachable!();
459            }
460        }
461    }
462    #[test]
463    pub fn test_show_create_missing_flow() {
464        let sql = "SHOW CREATE FLOW";
465        assert!(
466            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
467                .is_err()
468        );
469    }
470
471    #[test]
472    fn test_display_show_variables() {
473        let sql = r"show variables v1;";
474        let stmts: Vec<Statement> =
475            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
476                .unwrap();
477        assert_eq!(1, stmts.len());
478        assert_matches!(&stmts[0], Statement::ShowVariables { .. });
479        match &stmts[0] {
480            Statement::ShowVariables(show) => {
481                let new_sql = format!("\n{}", show);
482                assert_eq!(
483                    r#"
484SHOW VARIABLES v1"#,
485                    &new_sql
486                );
487            }
488            _ => {
489                unreachable!();
490            }
491        }
492    }
493
494    #[test]
495    fn test_display_show_create_table() {
496        let sql = r"show create table monitor;";
497        let stmts: Vec<Statement> =
498            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
499                .unwrap();
500        assert_eq!(1, stmts.len());
501        assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
502        match &stmts[0] {
503            Statement::ShowCreateTable(show) => {
504                let new_sql = format!("\n{}", show);
505                assert_eq!(
506                    r#"
507SHOW CREATE TABLE monitor"#,
508                    &new_sql
509                );
510            }
511            _ => {
512                unreachable!();
513            }
514        }
515    }
516
517    #[test]
518    fn test_display_show_index() {
519        let sql = r"show index from t1 from d1;";
520        let stmts: Vec<Statement> =
521            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
522                .unwrap();
523        assert_eq!(1, stmts.len());
524        assert_matches!(&stmts[0], Statement::ShowIndex { .. });
525        match &stmts[0] {
526            Statement::ShowIndex(show) => {
527                let new_sql = format!("\n{}", show);
528                assert_eq!(
529                    r#"
530SHOW INDEX IN t1 IN d1"#,
531                    &new_sql
532                );
533            }
534            _ => {
535                unreachable!();
536            }
537        }
538    }
539
540    #[test]
541    fn test_display_show_columns() {
542        let sql = r"show full columns in t1 in d1;";
543        let stmts: Vec<Statement> =
544            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
545                .unwrap();
546        assert_eq!(1, stmts.len());
547        assert_matches!(&stmts[0], Statement::ShowColumns { .. });
548        match &stmts[0] {
549            Statement::ShowColumns(show) => {
550                let new_sql = format!("\n{}", show);
551                assert_eq!(
552                    r#"
553SHOW FULL COLUMNS IN t1 IN d1"#,
554                    &new_sql
555                );
556            }
557            _ => {
558                unreachable!();
559            }
560        }
561    }
562
563    #[test]
564    fn test_display_show_tables() {
565        let sql = r"show full tables in d1;";
566        let stmts: Vec<Statement> =
567            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
568                .unwrap();
569        assert_eq!(1, stmts.len());
570        assert_matches!(&stmts[0], Statement::ShowTables { .. });
571        match &stmts[0] {
572            Statement::ShowTables(show) => {
573                let new_sql = format!("\n{}", show);
574                assert_eq!(
575                    r#"
576SHOW FULL TABLES IN d1"#,
577                    &new_sql
578                );
579            }
580            _ => {
581                unreachable!();
582            }
583        }
584
585        let sql = r"show full tables;";
586        let stmts: Vec<Statement> =
587            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
588                .unwrap();
589        assert_eq!(1, stmts.len());
590        assert_matches!(&stmts[0], Statement::ShowTables { .. });
591        match &stmts[0] {
592            Statement::ShowTables(show) => {
593                let new_sql = format!("\n{}", show);
594                assert_eq!(
595                    r#"
596SHOW FULL TABLES"#,
597                    &new_sql
598                );
599            }
600            _ => {
601                unreachable!();
602            }
603        }
604    }
605
606    #[test]
607    fn test_display_show_views() {
608        let sql = r"show views in d1;";
609        let stmts: Vec<Statement> =
610            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
611                .unwrap();
612        assert_eq!(1, stmts.len());
613        assert_matches!(&stmts[0], Statement::ShowViews { .. });
614        match &stmts[0] {
615            Statement::ShowViews(show) => {
616                let new_sql = format!("\n{}", show);
617                assert_eq!(
618                    r#"
619SHOW VIEWS IN d1"#,
620                    &new_sql
621                );
622            }
623            _ => {
624                unreachable!();
625            }
626        }
627
628        let sql = r"show views;";
629        let stmts: Vec<Statement> =
630            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
631                .unwrap();
632        assert_eq!(1, stmts.len());
633        assert_matches!(&stmts[0], Statement::ShowViews { .. });
634        match &stmts[0] {
635            Statement::ShowViews(show) => {
636                let new_sql = format!("\n{}", show);
637                assert_eq!(
638                    r#"
639SHOW VIEWS"#,
640                    &new_sql
641                );
642            }
643            _ => {
644                unreachable!();
645            }
646        }
647    }
648
649    #[test]
650    fn test_display_show_flows() {
651        let sql = r"show flows in d1;";
652        let stmts: Vec<Statement> =
653            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
654                .unwrap();
655        assert_eq!(1, stmts.len());
656        assert_matches!(&stmts[0], Statement::ShowFlows { .. });
657        match &stmts[0] {
658            Statement::ShowFlows(show) => {
659                let new_sql = format!("\n{}", show);
660                assert_eq!(
661                    r#"
662SHOW FLOWS IN d1"#,
663                    &new_sql
664                );
665            }
666            _ => {
667                unreachable!();
668            }
669        }
670
671        let sql = r"show flows;";
672        let stmts: Vec<Statement> =
673            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
674                .unwrap();
675        assert_eq!(1, stmts.len());
676        assert_matches!(&stmts[0], Statement::ShowFlows { .. });
677        match &stmts[0] {
678            Statement::ShowFlows(show) => {
679                let new_sql = format!("\n{}", show);
680                assert_eq!(
681                    r#"
682SHOW FLOWS"#,
683                    &new_sql
684                );
685            }
686            _ => {
687                unreachable!("{:?}", &stmts[0]);
688            }
689        }
690    }
691
692    #[test]
693    fn test_display_show_databases() {
694        let sql = r"show databases;";
695        let stmts: Vec<Statement> =
696            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
697                .unwrap();
698        assert_eq!(1, stmts.len());
699        assert_matches!(&stmts[0], Statement::ShowDatabases { .. });
700        match &stmts[0] {
701            Statement::ShowDatabases(show) => {
702                let new_sql = format!("\n{}", show);
703                assert_eq!(
704                    r#"
705SHOW DATABASES"#,
706                    &new_sql
707                );
708            }
709            _ => {
710                unreachable!();
711            }
712        }
713    }
714}