From 11d68abc8101795099b62bf33de45061b058c340 Mon Sep 17 00:00:00 2001 From: Alex Qyoun-ae <4062971+MazterQyou@users.noreply.github.com> Date: Tue, 9 Aug 2022 19:41:40 +0400 Subject: [PATCH] Support `SHOW TABLES` --- src/ast/mod.rs | 29 ++++++++++++++++ src/parser.rs | 45 +++++++++++++++++------- tests/sqlparser_mysql.rs | 75 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 12 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 86c0f2e92..eeead0de0 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1027,6 +1027,15 @@ pub enum Statement { table_name: ObjectName, filter: Option, }, + /// SHOW TABLES + /// + /// Note: this is a MySQL-specific statement. + ShowTables { + extended: bool, + full: bool, + db_name: Option, + filter: Option, + }, /// USE /// /// Note: This is a MySQL-specific statement. @@ -1859,6 +1868,26 @@ impl fmt::Display for Statement { } Ok(()) } + Statement::ShowTables { + extended, + full, + db_name, + filter, + } => { + write!( + f, + "SHOW {extended}{full}TABLES", + extended = if *extended { "EXTENDED " } else { "" }, + full = if *full { "FULL " } else { "" }, + )?; + if let Some(db_name) = db_name { + write!(f, " FROM {}", db_name)?; + } + if let Some(filter) = filter { + write!(f, " {}", filter)?; + } + Ok(()) + } Statement::Use { db_name } => { write!(f, "USE {}", db_name)?; Ok(()) diff --git a/src/parser.rs b/src/parser.rs index 5bea35e79..412d3eb0a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3727,17 +3727,19 @@ impl<'a> Parser<'a> { } pub fn parse_show(&mut self) -> Result { + let extended = self.parse_keyword(Keyword::EXTENDED); + let full = self.parse_keyword(Keyword::FULL); if self - .parse_one_of_keywords(&[ - Keyword::EXTENDED, - Keyword::FULL, - Keyword::COLUMNS, - Keyword::FIELDS, - ]) + .parse_one_of_keywords(&[Keyword::COLUMNS, Keyword::FIELDS]) .is_some() { - self.prev_token(); - Ok(self.parse_show_columns()?) + Ok(self.parse_show_columns(extended, full)?) + } else if self.parse_keyword(Keyword::TABLES) { + Ok(self.parse_show_tables(extended, full)?) + } else if extended || full { + Err(ParserError::ParserError( + "EXTENDED/FULL are not supported with this type of SHOW query".to_string(), + )) } else if self.parse_one_of_keywords(&[Keyword::CREATE]).is_some() { Ok(self.parse_show_create()?) } else if self.parse_keyword(Keyword::VARIABLES) @@ -3780,10 +3782,11 @@ impl<'a> Parser<'a> { Ok(Statement::ShowCreate { obj_type, obj_name }) } - pub fn parse_show_columns(&mut self) -> Result { - let extended = self.parse_keyword(Keyword::EXTENDED); - let full = self.parse_keyword(Keyword::FULL); - self.expect_one_of_keywords(&[Keyword::COLUMNS, Keyword::FIELDS])?; + pub fn parse_show_columns( + &mut self, + extended: bool, + full: bool, + ) -> Result { self.expect_one_of_keywords(&[Keyword::FROM, Keyword::IN])?; let object_name = self.parse_object_name()?; let table_name = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) { @@ -3804,6 +3807,24 @@ impl<'a> Parser<'a> { }) } + pub fn parse_show_tables( + &mut self, + extended: bool, + full: bool, + ) -> Result { + let db_name = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) { + Some(_) => Some(self.parse_identifier()?), + None => None, + }; + let filter = self.parse_show_statement_filter()?; + Ok(Statement::ShowTables { + extended, + full, + db_name, + filter, + }) + } + pub fn parse_show_statement_filter( &mut self, ) -> Result, ParserError> { diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index a514b1e8e..a72ffbb07 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -116,6 +116,81 @@ fn parse_show_columns() { ); } +#[test] +fn parse_show_tables() { + assert_eq!( + mysql_and_generic().verified_stmt("SHOW TABLES"), + Statement::ShowTables { + extended: false, + full: false, + db_name: None, + filter: None, + } + ); + assert_eq!( + mysql_and_generic().verified_stmt("SHOW TABLES FROM mydb"), + Statement::ShowTables { + extended: false, + full: false, + db_name: Some(Ident::new("mydb")), + filter: None, + } + ); + assert_eq!( + mysql_and_generic().verified_stmt("SHOW EXTENDED TABLES"), + Statement::ShowTables { + extended: true, + full: false, + db_name: None, + filter: None, + } + ); + assert_eq!( + mysql_and_generic().verified_stmt("SHOW FULL TABLES"), + Statement::ShowTables { + extended: false, + full: true, + db_name: None, + filter: None, + } + ); + assert_eq!( + mysql_and_generic().verified_stmt("SHOW TABLES LIKE 'pattern'"), + Statement::ShowTables { + extended: false, + full: false, + db_name: None, + filter: Some(ShowStatementFilter::Like("pattern".into())), + } + ); + assert_eq!( + mysql_and_generic().verified_stmt("SHOW TABLES WHERE 1 = 2"), + Statement::ShowTables { + extended: false, + full: false, + 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"); +} + +#[test] +fn parse_show_extended_full() { + assert!(mysql_and_generic() + .parse_sql_statements("SHOW EXTENDED FULL TABLES") + .is_ok()); + assert!(mysql_and_generic() + .parse_sql_statements("SHOW EXTENDED FULL COLUMNS FROM mytable") + .is_ok()); + // SHOW EXTENDED/FULL can only be used with COLUMNS and TABLES + assert!(mysql_and_generic() + .parse_sql_statements("SHOW EXTENDED FULL CREATE TABLE mytable") + .is_err()); +} + #[test] fn parse_show_create() { let obj_name = ObjectName(vec![Ident::new("myident")]);