You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by al...@apache.org on 2024/11/03 13:07:11 UTC

(datafusion-sqlparser-rs) branch main updated: Add support for SHOW DATABASES/SCHEMAS/TABLES/VIEWS in Hive (#1487)

This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new e2197eec Add support for SHOW DATABASES/SCHEMAS/TABLES/VIEWS in Hive (#1487)
e2197eec is described below

commit e2197eeca9ef2d51a26f29ac23c15515aa668a0f
Author: Yoav Cohen <59...@users.noreply.github.com>
AuthorDate: Sun Nov 3 14:07:06 2024 +0100

    Add support for SHOW DATABASES/SCHEMAS/TABLES/VIEWS in Hive (#1487)
---
 src/ast/mod.rs            | 81 +++++++++++++++++++++++++++++++++++++++++++++--
 src/keywords.rs           |  3 ++
 src/parser/mod.rs         | 50 ++++++++++++++++++++++++++---
 tests/sqlparser_common.rs | 21 ++++++++++++
 tests/sqlparser_mysql.rs  |  9 +++++-
 5 files changed, 157 insertions(+), 7 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 0573240a..b2672552 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -2782,12 +2782,29 @@ pub enum Statement {
         filter: Option<ShowStatementFilter>,
     },
     /// ```sql
+    /// SHOW DATABASES [LIKE 'pattern']
+    /// ```
+    ShowDatabases { filter: Option<ShowStatementFilter> },
+    /// ```sql
+    /// SHOW SCHEMAS [LIKE 'pattern']
+    /// ```
+    ShowSchemas { filter: Option<ShowStatementFilter> },
+    /// ```sql
     /// SHOW TABLES
     /// ```
-    /// Note: this is a MySQL-specific statement.
     ShowTables {
         extended: bool,
         full: bool,
+        clause: Option<ShowClause>,
+        db_name: Option<Ident>,
+        filter: Option<ShowStatementFilter>,
+    },
+    /// ```sql
+    /// SHOW VIEWS
+    /// ```
+    ShowViews {
+        materialized: bool,
+        clause: Option<ShowClause>,
         db_name: Option<Ident>,
         filter: Option<ShowStatementFilter>,
     },
@@ -4363,9 +4380,24 @@ impl fmt::Display for Statement {
                 }
                 Ok(())
             }
+            Statement::ShowDatabases { filter } => {
+                write!(f, "SHOW DATABASES")?;
+                if let Some(filter) = filter {
+                    write!(f, " {filter}")?;
+                }
+                Ok(())
+            }
+            Statement::ShowSchemas { filter } => {
+                write!(f, "SHOW SCHEMAS")?;
+                if let Some(filter) = filter {
+                    write!(f, " {filter}")?;
+                }
+                Ok(())
+            }
             Statement::ShowTables {
                 extended,
                 full,
+                clause: show_clause,
                 db_name,
                 filter,
             } => {
@@ -4375,8 +4407,33 @@ impl fmt::Display for Statement {
                     extended = if *extended { "EXTENDED " } else { "" },
                     full = if *full { "FULL " } else { "" },
                 )?;
+                if let Some(show_clause) = show_clause {
+                    write!(f, " {show_clause}")?;
+                }
+                if let Some(db_name) = db_name {
+                    write!(f, " {db_name}")?;
+                }
+                if let Some(filter) = filter {
+                    write!(f, " {filter}")?;
+                }
+                Ok(())
+            }
+            Statement::ShowViews {
+                materialized,
+                clause: show_clause,
+                db_name,
+                filter,
+            } => {
+                write!(
+                    f,
+                    "SHOW {}VIEWS",
+                    if *materialized { "MATERIALIZED " } else { "" }
+                )?;
+                if let Some(show_clause) = show_clause {
+                    write!(f, " {show_clause}")?;
+                }
                 if let Some(db_name) = db_name {
-                    write!(f, " FROM {db_name}")?;
+                    write!(f, " {db_name}")?;
                 }
                 if let Some(filter) = filter {
                     write!(f, " {filter}")?;
@@ -6057,6 +6114,7 @@ pub enum ShowStatementFilter {
     Like(String),
     ILike(String),
     Where(Expr),
+    NoKeyword(String),
 }
 
 impl fmt::Display for ShowStatementFilter {
@@ -6066,6 +6124,25 @@ impl fmt::Display for ShowStatementFilter {
             Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
             ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
             Where(expr) => write!(f, "WHERE {expr}"),
+            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum ShowClause {
+    IN,
+    FROM,
+}
+
+impl fmt::Display for ShowClause {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use ShowClause::*;
+        match self {
+            FROM => write!(f, "FROM"),
+            IN => write!(f, "IN"),
         }
     }
 }
diff --git a/src/keywords.rs b/src/keywords.rs
index 6182ae17..e9830968 100644
--- a/src/keywords.rs
+++ b/src/keywords.rs
@@ -217,6 +217,7 @@ define_keywords!(
     CYCLE,
     DATA,
     DATABASE,
+    DATABASES,
     DATA_RETENTION_TIME_IN_DAYS,
     DATE,
     DATE32,
@@ -662,6 +663,7 @@ define_keywords!(
     SAFE_CAST,
     SAVEPOINT,
     SCHEMA,
+    SCHEMAS,
     SCOPE,
     SCROLL,
     SEARCH,
@@ -822,6 +824,7 @@ define_keywords!(
     VERSION,
     VERSIONING,
     VIEW,
+    VIEWS,
     VIRTUAL,
     VOLATILE,
     WAREHOUSE,
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index a9a5b1df..c4b92ba4 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -9579,6 +9579,10 @@ impl<'a> Parser<'a> {
             Ok(self.parse_show_columns(extended, full)?)
         } else if self.parse_keyword(Keyword::TABLES) {
             Ok(self.parse_show_tables(extended, full)?)
+        } else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEWS]) {
+            Ok(self.parse_show_views(true)?)
+        } else if self.parse_keyword(Keyword::VIEWS) {
+            Ok(self.parse_show_views(false)?)
         } else if self.parse_keyword(Keyword::FUNCTIONS) {
             Ok(self.parse_show_functions()?)
         } else if extended || full {
@@ -9605,6 +9609,10 @@ impl<'a> Parser<'a> {
                 session,
                 global,
             })
+        } else if self.parse_keyword(Keyword::DATABASES) {
+            self.parse_show_databases()
+        } else if self.parse_keyword(Keyword::SCHEMAS) {
+            self.parse_show_schemas()
         } else {
             Ok(Statement::ShowVariable {
                 variable: self.parse_identifiers()?,
@@ -9612,6 +9620,18 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn parse_show_databases(&mut self) -> Result<Statement, ParserError> {
+        Ok(Statement::ShowDatabases {
+            filter: self.parse_show_statement_filter()?,
+        })
+    }
+
+    fn parse_show_schemas(&mut self) -> Result<Statement, ParserError> {
+        Ok(Statement::ShowSchemas {
+            filter: self.parse_show_statement_filter()?,
+        })
+    }
+
     pub fn parse_show_create(&mut self) -> Result<Statement, ParserError> {
         let obj_type = match self.expect_one_of_keywords(&[
             Keyword::TABLE,
@@ -9667,14 +9687,31 @@ impl<'a> Parser<'a> {
         extended: bool,
         full: bool,
     ) -> Result<Statement, ParserError> {
-        let db_name = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) {
-            Some(_) => Some(self.parse_identifier(false)?),
-            None => None,
+        let (clause, db_name) = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) {
+            Some(Keyword::FROM) => (Some(ShowClause::FROM), Some(self.parse_identifier(false)?)),
+            Some(Keyword::IN) => (Some(ShowClause::IN), Some(self.parse_identifier(false)?)),
+            _ => (None, None),
         };
         let filter = self.parse_show_statement_filter()?;
         Ok(Statement::ShowTables {
             extended,
             full,
+            clause,
+            db_name,
+            filter,
+        })
+    }
+
+    fn parse_show_views(&mut self, materialized: bool) -> Result<Statement, ParserError> {
+        let (clause, db_name) = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) {
+            Some(Keyword::FROM) => (Some(ShowClause::FROM), Some(self.parse_identifier(false)?)),
+            Some(Keyword::IN) => (Some(ShowClause::IN), Some(self.parse_identifier(false)?)),
+            _ => (None, None),
+        };
+        let filter = self.parse_show_statement_filter()?;
+        Ok(Statement::ShowViews {
+            materialized,
+            clause,
             db_name,
             filter,
         })
@@ -9704,7 +9741,12 @@ impl<'a> Parser<'a> {
         } else if self.parse_keyword(Keyword::WHERE) {
             Ok(Some(ShowStatementFilter::Where(self.parse_expr()?)))
         } else {
-            Ok(None)
+            self.maybe_parse(|parser| -> Result<String, ParserError> {
+                parser.parse_literal_string()
+            })?
+            .map_or(Ok(None), |filter| {
+                Ok(Some(ShowStatementFilter::NoKeyword(filter)))
+            })
         }
     }
 
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index a2eb5070..4016e5a6 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -11378,3 +11378,24 @@ fn test_try_convert() {
         all_dialects_where(|d| d.supports_try_convert() && !d.convert_type_before_value());
     dialects.verified_expr("TRY_CONVERT('foo', VARCHAR(MAX))");
 }
+
+#[test]
+fn test_show_dbs_schemas_tables_views() {
+    verified_stmt("SHOW DATABASES");
+    verified_stmt("SHOW DATABASES LIKE '%abc'");
+    verified_stmt("SHOW SCHEMAS");
+    verified_stmt("SHOW SCHEMAS LIKE '%abc'");
+    verified_stmt("SHOW TABLES");
+    verified_stmt("SHOW TABLES IN db1");
+    verified_stmt("SHOW TABLES IN db1 'abc'");
+    verified_stmt("SHOW VIEWS");
+    verified_stmt("SHOW VIEWS IN db1");
+    verified_stmt("SHOW VIEWS IN db1 'abc'");
+    verified_stmt("SHOW VIEWS FROM db1");
+    verified_stmt("SHOW VIEWS FROM db1 'abc'");
+    verified_stmt("SHOW MATERIALIZED VIEWS");
+    verified_stmt("SHOW MATERIALIZED VIEWS IN db1");
+    verified_stmt("SHOW MATERIALIZED VIEWS IN db1 'abc'");
+    verified_stmt("SHOW MATERIALIZED VIEWS FROM db1");
+    verified_stmt("SHOW MATERIALIZED VIEWS FROM db1 'abc'");
+}
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index db5b9ec8..4b9354e8 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -329,6 +329,7 @@ fn parse_show_tables() {
         Statement::ShowTables {
             extended: false,
             full: false,
+            clause: None,
             db_name: None,
             filter: None,
         }
@@ -338,6 +339,7 @@ fn parse_show_tables() {
         Statement::ShowTables {
             extended: false,
             full: false,
+            clause: Some(ShowClause::FROM),
             db_name: Some(Ident::new("mydb")),
             filter: None,
         }
@@ -347,6 +349,7 @@ fn parse_show_tables() {
         Statement::ShowTables {
             extended: true,
             full: false,
+            clause: None,
             db_name: None,
             filter: None,
         }
@@ -356,6 +359,7 @@ fn parse_show_tables() {
         Statement::ShowTables {
             extended: false,
             full: true,
+            clause: None,
             db_name: None,
             filter: None,
         }
@@ -365,6 +369,7 @@ fn parse_show_tables() {
         Statement::ShowTables {
             extended: false,
             full: false,
+            clause: None,
             db_name: None,
             filter: Some(ShowStatementFilter::Like("pattern".into())),
         }
@@ -374,13 +379,15 @@ fn parse_show_tables() {
         Statement::ShowTables {
             extended: false,
             full: false,
+            clause: None,
             db_name: None,
             filter: Some(ShowStatementFilter::Where(
                 mysql_and_generic().verified_expr("1 = 2")
             )),
         }
     );
-    mysql_and_generic().one_statement_parses_to("SHOW TABLES IN mydb", "SHOW TABLES FROM mydb");
+    mysql_and_generic().verified_stmt("SHOW TABLES IN mydb");
+    mysql_and_generic().verified_stmt("SHOW TABLES FROM mydb");
 }
 
 #[test]


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org