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#[cfg(test)]
325mod tests {
326    use std::assert_matches::assert_matches;
327
328    use sqlparser::ast::UnaryOperator;
329
330    use super::*;
331    use crate::dialect::GreptimeDbDialect;
332    use crate::parser::{ParseOptions, ParserContext};
333    use crate::statements::statement::Statement;
334
335    #[test]
336    fn test_kind_display() {
337        assert_eq!("", format!("{}", ShowKind::All));
338        assert_eq!(
339            "LIKE test",
340            format!("{}", ShowKind::Like(Ident::new("test")),)
341        );
342        assert_eq!(
343            "WHERE NOT a",
344            format!(
345                "{}",
346                ShowKind::Where(Expr::UnaryOp {
347                    op: UnaryOperator::Not,
348                    expr: Box::new(Expr::Identifier(Ident::new("a"))),
349                })
350            )
351        );
352    }
353
354    #[test]
355    pub fn test_show_database() {
356        let sql = "SHOW DATABASES";
357        let stmts =
358            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
359                .unwrap();
360        assert_eq!(1, stmts.len());
361        assert_matches!(&stmts[0], Statement::ShowDatabases { .. });
362        match &stmts[0] {
363            Statement::ShowDatabases(show) => {
364                assert_eq!(ShowKind::All, show.kind);
365            }
366            _ => {
367                unreachable!();
368            }
369        }
370    }
371
372    #[test]
373    pub fn test_show_create_table() {
374        let sql = "SHOW CREATE TABLE test";
375        let stmts: Vec<Statement> =
376            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
377                .unwrap();
378        assert_eq!(1, stmts.len());
379        assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
380        match &stmts[0] {
381            Statement::ShowCreateTable(show) => {
382                let table_name = show.table_name.to_string();
383                assert_eq!(table_name, "test");
384                assert_eq!(show.variant, ShowCreateTableVariant::Original);
385            }
386            _ => {
387                unreachable!();
388            }
389        }
390
391        let sql = "SHOW CREATE TABLE test FOR POSTGRES_FOREIGN_TABLE";
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::PostgresForeignTable);
402            }
403            _ => {
404                unreachable!();
405            }
406        }
407    }
408
409    #[test]
410    pub fn test_show_create_missing_table_name() {
411        let sql = "SHOW CREATE TABLE";
412        assert!(ParserContext::create_with_dialect(
413            sql,
414            &GreptimeDbDialect {},
415            ParseOptions::default()
416        )
417        .is_err());
418    }
419
420    #[test]
421    pub fn test_show_create_unknown_for() {
422        let sql = "SHOW CREATE TABLE t FOR UNKNOWN";
423        assert!(ParserContext::create_with_dialect(
424            sql,
425            &GreptimeDbDialect {},
426            ParseOptions::default()
427        )
428        .is_err());
429    }
430
431    #[test]
432    pub fn test_show_create_flow() {
433        let sql = "SHOW CREATE FLOW test";
434        let stmts: Vec<Statement> =
435            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
436                .unwrap();
437        assert_eq!(1, stmts.len());
438        assert_matches!(&stmts[0], Statement::ShowCreateFlow { .. });
439        match &stmts[0] {
440            Statement::ShowCreateFlow(show) => {
441                let flow_name = show.flow_name.to_string();
442                assert_eq!(flow_name, "test");
443            }
444            _ => {
445                unreachable!();
446            }
447        }
448    }
449    #[test]
450    pub fn test_show_create_missing_flow() {
451        let sql = "SHOW CREATE FLOW";
452        assert!(ParserContext::create_with_dialect(
453            sql,
454            &GreptimeDbDialect {},
455            ParseOptions::default()
456        )
457        .is_err());
458    }
459
460    #[test]
461    fn test_display_show_variables() {
462        let sql = r"show variables v1;";
463        let stmts: Vec<Statement> =
464            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
465                .unwrap();
466        assert_eq!(1, stmts.len());
467        assert_matches!(&stmts[0], Statement::ShowVariables { .. });
468        match &stmts[0] {
469            Statement::ShowVariables(show) => {
470                let new_sql = format!("\n{}", show);
471                assert_eq!(
472                    r#"
473SHOW VARIABLES v1"#,
474                    &new_sql
475                );
476            }
477            _ => {
478                unreachable!();
479            }
480        }
481    }
482
483    #[test]
484    fn test_display_show_create_table() {
485        let sql = r"show create table monitor;";
486        let stmts: Vec<Statement> =
487            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
488                .unwrap();
489        assert_eq!(1, stmts.len());
490        assert_matches!(&stmts[0], Statement::ShowCreateTable { .. });
491        match &stmts[0] {
492            Statement::ShowCreateTable(show) => {
493                let new_sql = format!("\n{}", show);
494                assert_eq!(
495                    r#"
496SHOW CREATE TABLE monitor"#,
497                    &new_sql
498                );
499            }
500            _ => {
501                unreachable!();
502            }
503        }
504    }
505
506    #[test]
507    fn test_display_show_index() {
508        let sql = r"show index from t1 from d1;";
509        let stmts: Vec<Statement> =
510            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
511                .unwrap();
512        assert_eq!(1, stmts.len());
513        assert_matches!(&stmts[0], Statement::ShowIndex { .. });
514        match &stmts[0] {
515            Statement::ShowIndex(show) => {
516                let new_sql = format!("\n{}", show);
517                assert_eq!(
518                    r#"
519SHOW INDEX IN t1 IN d1"#,
520                    &new_sql
521                );
522            }
523            _ => {
524                unreachable!();
525            }
526        }
527    }
528
529    #[test]
530    fn test_display_show_columns() {
531        let sql = r"show full columns in t1 in d1;";
532        let stmts: Vec<Statement> =
533            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
534                .unwrap();
535        assert_eq!(1, stmts.len());
536        assert_matches!(&stmts[0], Statement::ShowColumns { .. });
537        match &stmts[0] {
538            Statement::ShowColumns(show) => {
539                let new_sql = format!("\n{}", show);
540                assert_eq!(
541                    r#"
542SHOW FULL COLUMNS IN t1 IN d1"#,
543                    &new_sql
544                );
545            }
546            _ => {
547                unreachable!();
548            }
549        }
550    }
551
552    #[test]
553    fn test_display_show_tables() {
554        let sql = r"show full tables in d1;";
555        let stmts: Vec<Statement> =
556            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
557                .unwrap();
558        assert_eq!(1, stmts.len());
559        assert_matches!(&stmts[0], Statement::ShowTables { .. });
560        match &stmts[0] {
561            Statement::ShowTables(show) => {
562                let new_sql = format!("\n{}", show);
563                assert_eq!(
564                    r#"
565SHOW FULL TABLES IN d1"#,
566                    &new_sql
567                );
568            }
569            _ => {
570                unreachable!();
571            }
572        }
573
574        let sql = r"show full tables;";
575        let stmts: Vec<Statement> =
576            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
577                .unwrap();
578        assert_eq!(1, stmts.len());
579        assert_matches!(&stmts[0], Statement::ShowTables { .. });
580        match &stmts[0] {
581            Statement::ShowTables(show) => {
582                let new_sql = format!("\n{}", show);
583                assert_eq!(
584                    r#"
585SHOW FULL TABLES"#,
586                    &new_sql
587                );
588            }
589            _ => {
590                unreachable!();
591            }
592        }
593    }
594
595    #[test]
596    fn test_display_show_views() {
597        let sql = r"show views in d1;";
598        let stmts: Vec<Statement> =
599            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
600                .unwrap();
601        assert_eq!(1, stmts.len());
602        assert_matches!(&stmts[0], Statement::ShowViews { .. });
603        match &stmts[0] {
604            Statement::ShowViews(show) => {
605                let new_sql = format!("\n{}", show);
606                assert_eq!(
607                    r#"
608SHOW VIEWS IN d1"#,
609                    &new_sql
610                );
611            }
612            _ => {
613                unreachable!();
614            }
615        }
616
617        let sql = r"show views;";
618        let stmts: Vec<Statement> =
619            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
620                .unwrap();
621        assert_eq!(1, stmts.len());
622        assert_matches!(&stmts[0], Statement::ShowViews { .. });
623        match &stmts[0] {
624            Statement::ShowViews(show) => {
625                let new_sql = format!("\n{}", show);
626                assert_eq!(
627                    r#"
628SHOW VIEWS"#,
629                    &new_sql
630                );
631            }
632            _ => {
633                unreachable!();
634            }
635        }
636    }
637
638    #[test]
639    fn test_display_show_flows() {
640        let sql = r"show flows in d1;";
641        let stmts: Vec<Statement> =
642            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
643                .unwrap();
644        assert_eq!(1, stmts.len());
645        assert_matches!(&stmts[0], Statement::ShowFlows { .. });
646        match &stmts[0] {
647            Statement::ShowFlows(show) => {
648                let new_sql = format!("\n{}", show);
649                assert_eq!(
650                    r#"
651SHOW FLOWS IN d1"#,
652                    &new_sql
653                );
654            }
655            _ => {
656                unreachable!();
657            }
658        }
659
660        let sql = r"show flows;";
661        let stmts: Vec<Statement> =
662            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
663                .unwrap();
664        assert_eq!(1, stmts.len());
665        assert_matches!(&stmts[0], Statement::ShowFlows { .. });
666        match &stmts[0] {
667            Statement::ShowFlows(show) => {
668                let new_sql = format!("\n{}", show);
669                assert_eq!(
670                    r#"
671SHOW FLOWS"#,
672                    &new_sql
673                );
674            }
675            _ => {
676                unreachable!("{:?}", &stmts[0]);
677            }
678        }
679    }
680
681    #[test]
682    fn test_display_show_databases() {
683        let sql = r"show databases;";
684        let stmts: Vec<Statement> =
685            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
686                .unwrap();
687        assert_eq!(1, stmts.len());
688        assert_matches!(&stmts[0], Statement::ShowDatabases { .. });
689        match &stmts[0] {
690            Statement::ShowDatabases(show) => {
691                let new_sql = format!("\n{}", show);
692                assert_eq!(
693                    r#"
694SHOW DATABASES"#,
695                    &new_sql
696                );
697            }
698            _ => {
699                unreachable!();
700            }
701        }
702    }
703}