From d981b0996a96dbb80205b468235ed09f94d8c89d Mon Sep 17 00:00:00 2001 From: universalmind303 Date: Thu, 8 Feb 2024 19:24:42 -0600 Subject: [PATCH] feat: support = operator in function args (#1128) Co-authored-by: Andrew Lamb --- src/ast/mod.rs | 32 ++++++++++++++++++++++++++++++-- src/parser/mod.rs | 17 ++++++++++++++++- tests/sqlparser_common.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 371fe3d5..346247e2 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -4287,18 +4287,46 @@ impl fmt::Display for FunctionArgExpr { } } +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Operator used to separate function arguments +pub enum FunctionArgOperator { + /// function(arg1 = value1) + Equals, + /// function(arg1 => value1) + RightArrow, +} + +impl fmt::Display for FunctionArgOperator { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + FunctionArgOperator::Equals => f.write_str("="), + FunctionArgOperator::RightArrow => f.write_str("=>"), + } + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FunctionArg { - Named { name: Ident, arg: FunctionArgExpr }, + Named { + name: Ident, + arg: FunctionArgExpr, + operator: FunctionArgOperator, + }, Unnamed(FunctionArgExpr), } impl fmt::Display for FunctionArg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - FunctionArg::Named { name, arg } => write!(f, "{name} => {arg}"), + FunctionArg::Named { + name, + arg, + operator, + } => write!(f, "{name} {operator} {arg}"), FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"), } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 9d79a32e..ff7939c9 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -8106,7 +8106,22 @@ impl<'a> Parser<'a> { self.expect_token(&Token::RArrow)?; let arg = self.parse_wildcard_expr()?.into(); - Ok(FunctionArg::Named { name, arg }) + Ok(FunctionArg::Named { + name, + arg, + operator: FunctionArgOperator::RightArrow, + }) + } else if self.peek_nth_token(1) == Token::Eq { + let name = self.parse_identifier(false)?; + + self.expect_token(&Token::Eq)?; + let arg = self.parse_wildcard_expr()?.into(); + + Ok(FunctionArg::Named { + name, + arg, + operator: FunctionArgOperator::Equals, + }) } else { Ok(FunctionArg::Unnamed(self.parse_wildcard_expr()?.into())) } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 691ffb92..21cbcc99 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -3971,12 +3971,48 @@ fn parse_named_argument_function() { arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "1".to_owned() ))), + operator: FunctionArgOperator::RightArrow }, FunctionArg::Named { name: Ident::new("b"), arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( "2".to_owned() ))), + operator: FunctionArgOperator::RightArrow + }, + ], + null_treatment: None, + filter: None, + over: None, + distinct: false, + special: false, + order_by: vec![], + }), + expr_from_projection(only(&select.projection)) + ); +} + +#[test] +fn parse_named_argument_function_with_eq_operator() { + let sql = "SELECT FUN(a = '1', b = '2') FROM foo"; + let select = verified_only_select(sql); + assert_eq!( + &Expr::Function(Function { + name: ObjectName(vec![Ident::new("FUN")]), + args: vec![ + FunctionArg::Named { + name: Ident::new("a"), + arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( + "1".to_owned() + ))), + operator: FunctionArgOperator::Equals + }, + FunctionArg::Named { + name: Ident::new("b"), + arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString( + "2".to_owned() + ))), + operator: FunctionArgOperator::Equals }, ], null_treatment: None,