Add support for SHOW DATABASES/SCHEMAS/TABLES/VIEWS in Hive (#1487)

This commit is contained in:
Yoav Cohen 2024-11-03 14:07:06 +01:00 committed by GitHub
parent 8de3cb0074
commit e2197eeca9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 157 additions and 7 deletions

View file

@ -2782,12 +2782,29 @@ pub enum Statement {
filter: Option<ShowStatementFilter>, filter: Option<ShowStatementFilter>,
}, },
/// ```sql /// ```sql
/// SHOW DATABASES [LIKE 'pattern']
/// ```
ShowDatabases { filter: Option<ShowStatementFilter> },
/// ```sql
/// SHOW SCHEMAS [LIKE 'pattern']
/// ```
ShowSchemas { filter: Option<ShowStatementFilter> },
/// ```sql
/// SHOW TABLES /// SHOW TABLES
/// ``` /// ```
/// Note: this is a MySQL-specific statement.
ShowTables { ShowTables {
extended: bool, extended: bool,
full: 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>, db_name: Option<Ident>,
filter: Option<ShowStatementFilter>, filter: Option<ShowStatementFilter>,
}, },
@ -4363,9 +4380,24 @@ impl fmt::Display for Statement {
} }
Ok(()) 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 { Statement::ShowTables {
extended, extended,
full, full,
clause: show_clause,
db_name, db_name,
filter, filter,
} => { } => {
@ -4375,8 +4407,33 @@ impl fmt::Display for Statement {
extended = if *extended { "EXTENDED " } else { "" }, extended = if *extended { "EXTENDED " } else { "" },
full = if *full { "FULL " } else { "" }, full = if *full { "FULL " } else { "" },
)?; )?;
if let Some(show_clause) = show_clause {
write!(f, " {show_clause}")?;
}
if let Some(db_name) = db_name { if let Some(db_name) = db_name {
write!(f, " FROM {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, " {db_name}")?;
} }
if let Some(filter) = filter { if let Some(filter) = filter {
write!(f, " {filter}")?; write!(f, " {filter}")?;
@ -6057,6 +6114,7 @@ pub enum ShowStatementFilter {
Like(String), Like(String),
ILike(String), ILike(String),
Where(Expr), Where(Expr),
NoKeyword(String),
} }
impl fmt::Display for ShowStatementFilter { 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)), Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)), ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
Where(expr) => write!(f, "WHERE {expr}"), 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"),
} }
} }
} }

View file

@ -217,6 +217,7 @@ define_keywords!(
CYCLE, CYCLE,
DATA, DATA,
DATABASE, DATABASE,
DATABASES,
DATA_RETENTION_TIME_IN_DAYS, DATA_RETENTION_TIME_IN_DAYS,
DATE, DATE,
DATE32, DATE32,
@ -662,6 +663,7 @@ define_keywords!(
SAFE_CAST, SAFE_CAST,
SAVEPOINT, SAVEPOINT,
SCHEMA, SCHEMA,
SCHEMAS,
SCOPE, SCOPE,
SCROLL, SCROLL,
SEARCH, SEARCH,
@ -822,6 +824,7 @@ define_keywords!(
VERSION, VERSION,
VERSIONING, VERSIONING,
VIEW, VIEW,
VIEWS,
VIRTUAL, VIRTUAL,
VOLATILE, VOLATILE,
WAREHOUSE, WAREHOUSE,

View file

@ -9579,6 +9579,10 @@ impl<'a> Parser<'a> {
Ok(self.parse_show_columns(extended, full)?) Ok(self.parse_show_columns(extended, full)?)
} else if self.parse_keyword(Keyword::TABLES) { } else if self.parse_keyword(Keyword::TABLES) {
Ok(self.parse_show_tables(extended, full)?) 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) { } else if self.parse_keyword(Keyword::FUNCTIONS) {
Ok(self.parse_show_functions()?) Ok(self.parse_show_functions()?)
} else if extended || full { } else if extended || full {
@ -9605,6 +9609,10 @@ impl<'a> Parser<'a> {
session, session,
global, global,
}) })
} else if self.parse_keyword(Keyword::DATABASES) {
self.parse_show_databases()
} else if self.parse_keyword(Keyword::SCHEMAS) {
self.parse_show_schemas()
} else { } else {
Ok(Statement::ShowVariable { Ok(Statement::ShowVariable {
variable: self.parse_identifiers()?, 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> { pub fn parse_show_create(&mut self) -> Result<Statement, ParserError> {
let obj_type = match self.expect_one_of_keywords(&[ let obj_type = match self.expect_one_of_keywords(&[
Keyword::TABLE, Keyword::TABLE,
@ -9667,14 +9687,31 @@ impl<'a> Parser<'a> {
extended: bool, extended: bool,
full: bool, full: bool,
) -> Result<Statement, ParserError> { ) -> Result<Statement, ParserError> {
let db_name = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) { let (clause, db_name) = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) {
Some(_) => Some(self.parse_identifier(false)?), Some(Keyword::FROM) => (Some(ShowClause::FROM), Some(self.parse_identifier(false)?)),
None => None, Some(Keyword::IN) => (Some(ShowClause::IN), Some(self.parse_identifier(false)?)),
_ => (None, None),
}; };
let filter = self.parse_show_statement_filter()?; let filter = self.parse_show_statement_filter()?;
Ok(Statement::ShowTables { Ok(Statement::ShowTables {
extended, extended,
full, 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, db_name,
filter, filter,
}) })
@ -9704,7 +9741,12 @@ impl<'a> Parser<'a> {
} else if self.parse_keyword(Keyword::WHERE) { } else if self.parse_keyword(Keyword::WHERE) {
Ok(Some(ShowStatementFilter::Where(self.parse_expr()?))) Ok(Some(ShowStatementFilter::Where(self.parse_expr()?)))
} else { } else {
Ok(None) self.maybe_parse(|parser| -> Result<String, ParserError> {
parser.parse_literal_string()
})?
.map_or(Ok(None), |filter| {
Ok(Some(ShowStatementFilter::NoKeyword(filter)))
})
} }
} }

View file

@ -11378,3 +11378,24 @@ fn test_try_convert() {
all_dialects_where(|d| d.supports_try_convert() && !d.convert_type_before_value()); all_dialects_where(|d| d.supports_try_convert() && !d.convert_type_before_value());
dialects.verified_expr("TRY_CONVERT('foo', VARCHAR(MAX))"); 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'");
}

View file

@ -329,6 +329,7 @@ fn parse_show_tables() {
Statement::ShowTables { Statement::ShowTables {
extended: false, extended: false,
full: false, full: false,
clause: None,
db_name: None, db_name: None,
filter: None, filter: None,
} }
@ -338,6 +339,7 @@ fn parse_show_tables() {
Statement::ShowTables { Statement::ShowTables {
extended: false, extended: false,
full: false, full: false,
clause: Some(ShowClause::FROM),
db_name: Some(Ident::new("mydb")), db_name: Some(Ident::new("mydb")),
filter: None, filter: None,
} }
@ -347,6 +349,7 @@ fn parse_show_tables() {
Statement::ShowTables { Statement::ShowTables {
extended: true, extended: true,
full: false, full: false,
clause: None,
db_name: None, db_name: None,
filter: None, filter: None,
} }
@ -356,6 +359,7 @@ fn parse_show_tables() {
Statement::ShowTables { Statement::ShowTables {
extended: false, extended: false,
full: true, full: true,
clause: None,
db_name: None, db_name: None,
filter: None, filter: None,
} }
@ -365,6 +369,7 @@ fn parse_show_tables() {
Statement::ShowTables { Statement::ShowTables {
extended: false, extended: false,
full: false, full: false,
clause: None,
db_name: None, db_name: None,
filter: Some(ShowStatementFilter::Like("pattern".into())), filter: Some(ShowStatementFilter::Like("pattern".into())),
} }
@ -374,13 +379,15 @@ fn parse_show_tables() {
Statement::ShowTables { Statement::ShowTables {
extended: false, extended: false,
full: false, full: false,
clause: None,
db_name: None, db_name: None,
filter: Some(ShowStatementFilter::Where( filter: Some(ShowStatementFilter::Where(
mysql_and_generic().verified_expr("1 = 2") 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] #[test]