From 492c6a417f3a07d2f97127dc30b7aa5c78851d65 Mon Sep 17 00:00:00 2001 From: francis-du Date: Mon, 11 Jan 2021 13:53:25 +0800 Subject: [PATCH 1/2] feat: support parsing multiple show variables. --- src/ast/mod.rs | 10 ++++++++-- src/parser.rs | 15 ++++++++++++++- tests/sqlparser_common.rs | 28 ++++++++++------------------ tests/sqlparser_postgres.rs | 8 ++++---- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index d0e321185..9a96e34bc 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -637,7 +637,7 @@ pub enum Statement { /// SHOW /// /// Note: this is a PostgreSQL-specific statement. - ShowVariable { variable: Ident }, + ShowVariable { variable: Vec }, /// SHOW COLUMNS /// /// Note: this is a MySQL-specific statement. @@ -1136,7 +1136,13 @@ impl fmt::Display for Statement { value = display_comma_separated(value) ) } - Statement::ShowVariable { variable } => write!(f, "SHOW {}", variable), + Statement::ShowVariable { variable } => { + write!(f, "SHOW")?; + if !variable.is_empty() { + write!(f, " {}", display_separated(variable, " "))?; + } + Ok(()) + } Statement::ShowColumns { extended, full, diff --git a/src/parser.rs b/src/parser.rs index bee671f04..621209fd7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2043,6 +2043,19 @@ impl<'a> Parser<'a> { Ok(ObjectName(idents)) } + /// Parse identifiers + pub fn parse_identifiers(&mut self) -> Result, ParserError> { + let mut idents = vec![]; + loop { + match self.next_token() { + Token::Word(w) => idents.push(w.to_ident()), + Token::EOF => break, + _ => {} + } + } + Ok(idents) + } + /// Parse a simple one-word identifier (possibly quoted, possibly a keyword) pub fn parse_identifier(&mut self) -> Result { match self.next_token() { @@ -2439,7 +2452,7 @@ impl<'a> Parser<'a> { self.parse_show_columns() } else { Ok(Statement::ShowVariable { - variable: self.parse_identifier()?, + variable: self.parse_identifiers()?, }) } } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index f302245ee..22b92c025 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -543,23 +543,17 @@ fn parse_is_not_null() { fn parse_not_precedence() { // NOT has higher precedence than OR/AND, so the following must parse as (NOT true) OR true let sql = "NOT true OR true"; - assert_matches!( - verified_expr(sql), - Expr::BinaryOp { - op: BinaryOperator::Or, - .. - } - ); + assert_matches!(verified_expr(sql), Expr::BinaryOp { + op: BinaryOperator::Or, + .. + }); // But NOT has lower precedence than comparison operators, so the following parses as NOT (a IS NULL) let sql = "NOT a IS NULL"; - assert_matches!( - verified_expr(sql), - Expr::UnaryOp { - op: UnaryOperator::Not, - .. - } - ); + assert_matches!(verified_expr(sql), Expr::UnaryOp { + op: UnaryOperator::Not, + .. + }); // NOT has lower precedence than BETWEEN, so the following parses as NOT (1 NOT BETWEEN 1 AND 2) let sql = "NOT 1 NOT BETWEEN 1 AND 2"; @@ -1469,7 +1463,7 @@ fn parse_create_external_table_lowercase() { lng DOUBLE) \ STORED AS PARQUET LOCATION '/tmp/example.csv'", ); - assert_matches!(ast, Statement::CreateTable { .. }); + assert_matches!(ast, Statement::CreateTable{..}); } #[test] @@ -2588,9 +2582,7 @@ fn parse_multiple_statements() { #[test] fn parse_scalar_subqueries() { let sql = "(SELECT 1) + (SELECT 2)"; - assert_matches!( - verified_expr(sql), - Expr::BinaryOp { + assert_matches!(verified_expr(sql), Expr::BinaryOp { op: BinaryOperator::Plus, .. //left: box Subquery { .. }, //right: box Subquery { .. }, diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 2abd8ae9b..bcfce30fc 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -443,19 +443,19 @@ fn parse_set() { #[test] fn parse_show() { - let stmt = pg_and_generic().verified_stmt("SHOW a"); + let stmt = pg_and_generic().verified_stmt("SHOW a a"); assert_eq!( stmt, Statement::ShowVariable { - variable: "a".into() + variable: vec!["a".into(), "a".into()] } ); - let stmt = pg_and_generic().verified_stmt("SHOW ALL"); + let stmt = pg_and_generic().verified_stmt("SHOW ALL ALL"); assert_eq!( stmt, Statement::ShowVariable { - variable: "ALL".into() + variable: vec!["ALL".into(), "ALL".into()] } ) } From 7c1d215d53423e71ff6122200b180e5cfc8c2913 Mon Sep 17 00:00:00 2001 From: francis-du Date: Tue, 9 Feb 2021 08:26:58 +0800 Subject: [PATCH 2/2] fix: fix fmt error --- tests/sqlparser_common.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 22b92c025..f302245ee 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -543,17 +543,23 @@ fn parse_is_not_null() { fn parse_not_precedence() { // NOT has higher precedence than OR/AND, so the following must parse as (NOT true) OR true let sql = "NOT true OR true"; - assert_matches!(verified_expr(sql), Expr::BinaryOp { - op: BinaryOperator::Or, - .. - }); + assert_matches!( + verified_expr(sql), + Expr::BinaryOp { + op: BinaryOperator::Or, + .. + } + ); // But NOT has lower precedence than comparison operators, so the following parses as NOT (a IS NULL) let sql = "NOT a IS NULL"; - assert_matches!(verified_expr(sql), Expr::UnaryOp { - op: UnaryOperator::Not, - .. - }); + assert_matches!( + verified_expr(sql), + Expr::UnaryOp { + op: UnaryOperator::Not, + .. + } + ); // NOT has lower precedence than BETWEEN, so the following parses as NOT (1 NOT BETWEEN 1 AND 2) let sql = "NOT 1 NOT BETWEEN 1 AND 2"; @@ -1463,7 +1469,7 @@ fn parse_create_external_table_lowercase() { lng DOUBLE) \ STORED AS PARQUET LOCATION '/tmp/example.csv'", ); - assert_matches!(ast, Statement::CreateTable{..}); + assert_matches!(ast, Statement::CreateTable { .. }); } #[test] @@ -2582,7 +2588,9 @@ fn parse_multiple_statements() { #[test] fn parse_scalar_subqueries() { let sql = "(SELECT 1) + (SELECT 2)"; - assert_matches!(verified_expr(sql), Expr::BinaryOp { + assert_matches!( + verified_expr(sql), + Expr::BinaryOp { op: BinaryOperator::Plus, .. //left: box Subquery { .. }, //right: box Subquery { .. },