From 8f8c96f87ffe58945a0875c9c897f36c989b0095 Mon Sep 17 00:00:00 2001 From: Jax Liu Date: Sun, 4 Aug 2024 19:47:32 +0800 Subject: [PATCH] Support parsing empty map literal syntax for DuckDB and Genric (#1361) --- src/parser/mod.rs | 42 ++++++++++++++++----------------------- tests/sqlparser_common.rs | 2 ++ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index da9ca2672..fe8acb4f2 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1849,17 +1849,9 @@ impl<'a> Parser<'a> { /// Parses an array expression `[ex1, ex2, ..]` /// if `named` is `true`, came from an expression like `ARRAY[ex1, ex2]` pub fn parse_array_expr(&mut self, named: bool) -> Result { - if self.peek_token().token == Token::RBracket { - let _ = self.next_token(); // consume ] - Ok(Expr::Array(Array { - elem: vec![], - named, - })) - } else { - let exprs = self.parse_comma_separated(Parser::parse_expr)?; - self.expect_token(&Token::RBracket)?; - Ok(Expr::Array(Array { elem: exprs, named })) - } + let exprs = self.parse_comma_separated0(Parser::parse_expr, Token::RBracket)?; + self.expect_token(&Token::RBracket)?; + Ok(Expr::Array(Array { elem: exprs, named })) } pub fn parse_listagg_on_overflow(&mut self) -> Result, ParserError> { @@ -2352,11 +2344,8 @@ impl<'a> Parser<'a> { /// [map]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps fn parse_duckdb_map_literal(&mut self) -> Result { self.expect_token(&Token::LBrace)?; - - let fields = self.parse_comma_separated(Self::parse_duckdb_map_field)?; - + let fields = self.parse_comma_separated0(Self::parse_duckdb_map_field, Token::RBrace)?; self.expect_token(&Token::RBrace)?; - Ok(Expr::Map(Map { entries: fields })) } @@ -2937,7 +2926,7 @@ impl<'a> Parser<'a> { Expr::InList { expr: Box::new(expr), list: if self.dialect.supports_in_empty_list() { - self.parse_comma_separated0(Parser::parse_expr)? + self.parse_comma_separated0(Parser::parse_expr, Token::RParen)? } else { self.parse_comma_separated(Parser::parse_expr)? }, @@ -3479,18 +3468,20 @@ impl<'a> Parser<'a> { } /// Parse a comma-separated list of 0+ items accepted by `F` - pub fn parse_comma_separated0(&mut self, f: F) -> Result, ParserError> + /// * `end_token` - expected end token for the closure (e.g. [Token::RParen], [Token::RBrace] ...) + pub fn parse_comma_separated0( + &mut self, + f: F, + end_token: Token, + ) -> Result, ParserError> where F: FnMut(&mut Parser<'a>) -> Result, { - // () - if matches!(self.peek_token().token, Token::RParen) { + if self.peek_token().token == end_token { return Ok(vec![]); } - // (,) - if self.options.trailing_commas - && matches!(self.peek_tokens(), [Token::Comma, Token::RParen]) - { + + if self.options.trailing_commas && self.peek_tokens() == [Token::Comma, end_token] { let _ = self.consume_token(&Token::Comma); return Ok(vec![]); } @@ -4059,7 +4050,7 @@ impl<'a> Parser<'a> { }) }; self.expect_token(&Token::LParen)?; - let args = self.parse_comma_separated0(parse_function_param)?; + let args = self.parse_comma_separated0(parse_function_param, Token::RParen)?; self.expect_token(&Token::RParen)?; let return_type = if self.parse_keyword(Keyword::RETURNS) { @@ -10713,7 +10704,8 @@ impl<'a> Parser<'a> { } if self.consume_token(&Token::LParen) { - let interpolations = self.parse_comma_separated0(|p| p.parse_interpolation())?; + let interpolations = + self.parse_comma_separated0(|p| p.parse_interpolation(), Token::RParen)?; self.expect_token(&Token::RParen)?; // INTERPOLATE () and INTERPOLATE ( ... ) variants return Ok(Some(Interpolate { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 44e245254..7ec017269 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -10282,6 +10282,8 @@ fn test_map_syntax() { }), }, ); + + check("MAP {}", Expr::Map(Map { entries: vec![] })); } #[test]