From 5226b10ed48198e2ad6d4c2621798dd94ce3ab46 Mon Sep 17 00:00:00 2001 From: lovasoa Date: Sun, 24 Nov 2024 22:00:05 +0100 Subject: [PATCH 1/4] `json_object('k' VALUE 'v')` in postgres Fixes https://github.com/apache/datafusion-sqlparser-rs/issues/1545 --- src/ast/mod.rs | 3 +++ src/parser/mod.rs | 1 + tests/sqlparser_postgres.rs | 13 +++++++++++++ 3 files changed, 17 insertions(+) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 9185c9df4..0e4505402 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -5462,6 +5462,8 @@ pub enum FunctionArgOperator { Assignment, /// function(arg1 : value1) Colon, + /// function(arg1 VALUE value1) + Value, } impl fmt::Display for FunctionArgOperator { @@ -5471,6 +5473,7 @@ impl fmt::Display for FunctionArgOperator { FunctionArgOperator::RightArrow => f.write_str("=>"), FunctionArgOperator::Assignment => f.write_str(":="), FunctionArgOperator::Colon => f.write_str(":"), + FunctionArgOperator::Value => f.write_str("VALUE"), } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1bf173169..dd8860762 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -11411,6 +11411,7 @@ impl<'a> Parser<'a> { Token::Colon if self.dialect.supports_named_fn_args_with_colon_operator() => { Ok(FunctionArgOperator::Colon) } + Token::Word(w) if w.value.to_uppercase() == "VALUE" => Ok(FunctionArgOperator::Value), _ => { self.prev_token(); self.expected("argument operator", tok) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 098a3464c..fa07d5530 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -2812,6 +2812,19 @@ fn test_json() { ); } +#[test] +fn test_json_object() { + match pg().verified_expr("JSON_OBJECT('name' VALUE 'value')") { + Expr::Function(Function { args: FunctionArguments::List(FunctionArgumentList { args, .. }), .. }) => { + assert!(matches!( + &args[..], + &[FunctionArg::ExprNamed { operator: FunctionArgOperator::Value, .. }] + )); + } + other => panic!("Expected: JSON_OBJECT('name' VALUE 'value') to be parsed as a function, but got {other:?}"), + } +} + #[test] fn parse_json_table_is_not_reserved() { // JSON_TABLE is not a reserved keyword in PostgreSQL, even though it is in SQL:2023 From 9279fb9d0a71d44d49e3d8bb9e455e8105779cfa Mon Sep 17 00:00:00 2001 From: lovasoa Date: Sun, 24 Nov 2024 22:07:48 +0100 Subject: [PATCH 2/4] efficient comparison --- src/parser/mod.rs | 4 +++- tests/sqlparser_postgres.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index dd8860762..f81dcfe15 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -11411,7 +11411,9 @@ impl<'a> Parser<'a> { Token::Colon if self.dialect.supports_named_fn_args_with_colon_operator() => { Ok(FunctionArgOperator::Colon) } - Token::Word(w) if w.value.to_uppercase() == "VALUE" => Ok(FunctionArgOperator::Value), + Token::Word(w) if w.value.eq_ignore_ascii_case("value") => { + Ok(FunctionArgOperator::Value) + } _ => { self.prev_token(); self.expected("argument operator", tok) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index fa07d5530..01211c35d 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -2819,7 +2819,7 @@ fn test_json_object() { assert!(matches!( &args[..], &[FunctionArg::ExprNamed { operator: FunctionArgOperator::Value, .. }] - )); + ), "Invalid function argument: {:?}", args); } other => panic!("Expected: JSON_OBJECT('name' VALUE 'value') to be parsed as a function, but got {other:?}"), } From 1cc5f82b47e88124ce5396793be83aa592668518 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Tue, 26 Nov 2024 17:32:57 +0100 Subject: [PATCH 3/4] Update tests/sqlparser_postgres.rs Co-authored-by: Ifeanyi Ubah --- tests/sqlparser_postgres.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 01211c35d..ec1877e58 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -2813,7 +2813,7 @@ fn test_json() { } #[test] -fn test_json_object() { +fn test_fn_arg_with_value_operator() { match pg().verified_expr("JSON_OBJECT('name' VALUE 'value')") { Expr::Function(Function { args: FunctionArguments::List(FunctionArgumentList { args, .. }), .. }) => { assert!(matches!( From 8a33f4b9e85989e8b7958b7bd0e8761134dbbf88 Mon Sep 17 00:00:00 2001 From: lovasoa Date: Wed, 27 Nov 2024 15:53:43 +0100 Subject: [PATCH 4/4] https://github.com/apache/datafusion-sqlparser-rs/pull/1547#discussion_r1860757158 --- src/parser/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5fdbb8377..90c9a4ff5 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -11478,6 +11478,9 @@ impl<'a> Parser<'a> { } fn parse_function_named_arg_operator(&mut self) -> Result { + if self.parse_keyword(Keyword::VALUE) { + return Ok(FunctionArgOperator::Value); + } let tok = self.next_token(); match tok.token { Token::RArrow if self.dialect.supports_named_fn_args_with_rarrow_operator() => { @@ -11496,9 +11499,6 @@ impl<'a> Parser<'a> { Token::Colon if self.dialect.supports_named_fn_args_with_colon_operator() => { Ok(FunctionArgOperator::Colon) } - Token::Word(w) if w.value.eq_ignore_ascii_case("value") => { - Ok(FunctionArgOperator::Value) - } _ => { self.prev_token(); self.expected("argument operator", tok)