mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-24 07:54:06 +00:00
support json_object('k':'v')
in postgres (#1546)
This commit is contained in:
parent
fd21fae297
commit
525d1780e8
3 changed files with 191 additions and 160 deletions
|
@ -211,6 +211,26 @@ impl Dialect for PostgreSqlDialect {
|
||||||
fn supports_load_extension(&self) -> bool {
|
fn supports_load_extension(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See <https://www.postgresql.org/docs/current/functions-json.html>
|
||||||
|
///
|
||||||
|
/// Required to support the colon in:
|
||||||
|
/// ```sql
|
||||||
|
/// SELECT json_object('a': 'b')
|
||||||
|
/// ```
|
||||||
|
fn supports_named_fn_args_with_colon_operator(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See <https://www.postgresql.org/docs/current/functions-json.html>
|
||||||
|
///
|
||||||
|
/// Required to support the label in:
|
||||||
|
/// ```sql
|
||||||
|
/// SELECT json_object('label': 'value')
|
||||||
|
/// ```
|
||||||
|
fn supports_named_fn_args_with_expr_name(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||||
|
|
|
@ -1471,6 +1471,173 @@ fn parse_json_ops_without_colon() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_json_object() {
|
||||||
|
let dialects = TestedDialects::new(vec![
|
||||||
|
Box::new(MsSqlDialect {}),
|
||||||
|
Box::new(PostgreSqlDialect {}),
|
||||||
|
]);
|
||||||
|
let select = dialects.verified_only_select("SELECT JSON_OBJECT('name' : 'value', 'type' : 1)");
|
||||||
|
match expr_from_projection(&select.projection[0]) {
|
||||||
|
Expr::Function(Function {
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList { args, .. }),
|
||||||
|
..
|
||||||
|
}) => assert_eq!(
|
||||||
|
&[
|
||||||
|
FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||||
|
"value".into()
|
||||||
|
))),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
},
|
||||||
|
FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString("type".into())),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Value(number("1"))),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
}
|
||||||
|
],
|
||||||
|
&args[..]
|
||||||
|
),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
let select = dialects
|
||||||
|
.verified_only_select("SELECT JSON_OBJECT('name' : 'value', 'type' : NULL ABSENT ON NULL)");
|
||||||
|
match expr_from_projection(&select.projection[0]) {
|
||||||
|
Expr::Function(Function {
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
assert_eq!(
|
||||||
|
&[
|
||||||
|
FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||||
|
"value".into()
|
||||||
|
))),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
},
|
||||||
|
FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString("type".into())),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Value(Value::Null)),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
}
|
||||||
|
],
|
||||||
|
&args[..]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
&[FunctionArgumentClause::JsonNullClause(
|
||||||
|
JsonNullClause::AbsentOnNull
|
||||||
|
)],
|
||||||
|
&clauses[..]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
let select = dialects.verified_only_select("SELECT JSON_OBJECT(NULL ON NULL)");
|
||||||
|
match expr_from_projection(&select.projection[0]) {
|
||||||
|
Expr::Function(Function {
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
assert!(args.is_empty());
|
||||||
|
assert_eq!(
|
||||||
|
&[FunctionArgumentClause::JsonNullClause(
|
||||||
|
JsonNullClause::NullOnNull
|
||||||
|
)],
|
||||||
|
&clauses[..]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
let select = dialects.verified_only_select("SELECT JSON_OBJECT(ABSENT ON NULL)");
|
||||||
|
match expr_from_projection(&select.projection[0]) {
|
||||||
|
Expr::Function(Function {
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
assert!(args.is_empty());
|
||||||
|
assert_eq!(
|
||||||
|
&[FunctionArgumentClause::JsonNullClause(
|
||||||
|
JsonNullClause::AbsentOnNull
|
||||||
|
)],
|
||||||
|
&clauses[..]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
let select = dialects.verified_only_select(
|
||||||
|
"SELECT JSON_OBJECT('name' : 'value', 'type' : JSON_ARRAY(1, 2) ABSENT ON NULL)",
|
||||||
|
);
|
||||||
|
match expr_from_projection(&select.projection[0]) {
|
||||||
|
Expr::Function(Function {
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
assert_eq!(
|
||||||
|
&FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||||
|
"value".into()
|
||||||
|
))),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
},
|
||||||
|
&args[0]
|
||||||
|
);
|
||||||
|
assert!(matches!(
|
||||||
|
args[1],
|
||||||
|
FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString(_)),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Function(_)),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
}
|
||||||
|
));
|
||||||
|
assert_eq!(
|
||||||
|
&[FunctionArgumentClause::JsonNullClause(
|
||||||
|
JsonNullClause::AbsentOnNull
|
||||||
|
)],
|
||||||
|
&clauses[..]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
let select = dialects.verified_only_select(
|
||||||
|
"SELECT JSON_OBJECT('name' : 'value', 'type' : JSON_OBJECT('type_id' : 1, 'name' : 'a') NULL ON NULL)",
|
||||||
|
);
|
||||||
|
match expr_from_projection(&select.projection[0]) {
|
||||||
|
Expr::Function(Function {
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
assert_eq!(
|
||||||
|
&FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||||
|
"value".into()
|
||||||
|
))),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
},
|
||||||
|
&args[0]
|
||||||
|
);
|
||||||
|
assert!(matches!(
|
||||||
|
args[1],
|
||||||
|
FunctionArg::ExprNamed {
|
||||||
|
name: Expr::Value(Value::SingleQuotedString(_)),
|
||||||
|
arg: FunctionArgExpr::Expr(Expr::Function(_)),
|
||||||
|
operator: FunctionArgOperator::Colon
|
||||||
|
}
|
||||||
|
));
|
||||||
|
assert_eq!(
|
||||||
|
&[FunctionArgumentClause::JsonNullClause(
|
||||||
|
JsonNullClause::NullOnNull
|
||||||
|
)],
|
||||||
|
&clauses[..]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_mod_no_spaces() {
|
fn parse_mod_no_spaces() {
|
||||||
use self::Expr::*;
|
use self::Expr::*;
|
||||||
|
@ -4416,7 +4583,10 @@ fn parse_explain_query_plan() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_named_argument_function() {
|
fn parse_named_argument_function() {
|
||||||
let dialects = all_dialects_where(|d| d.supports_named_fn_args_with_rarrow_operator());
|
let dialects = all_dialects_where(|d| {
|
||||||
|
d.supports_named_fn_args_with_rarrow_operator()
|
||||||
|
&& !d.supports_named_fn_args_with_expr_name()
|
||||||
|
});
|
||||||
let sql = "SELECT FUN(a => '1', b => '2') FROM foo";
|
let sql = "SELECT FUN(a => '1', b => '2') FROM foo";
|
||||||
let select = dialects.verified_only_select(sql);
|
let select = dialects.verified_only_select(sql);
|
||||||
|
|
||||||
|
|
|
@ -793,165 +793,6 @@ fn parse_for_json_expect_ast() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_mssql_json_object() {
|
fn parse_mssql_json_object() {
|
||||||
let select = ms().verified_only_select("SELECT JSON_OBJECT('name' : 'value', 'type' : 1)");
|
|
||||||
match expr_from_projection(&select.projection[0]) {
|
|
||||||
Expr::Function(Function {
|
|
||||||
args: FunctionArguments::List(FunctionArgumentList { args, .. }),
|
|
||||||
..
|
|
||||||
}) => assert_eq!(
|
|
||||||
&[
|
|
||||||
FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
|
||||||
"value".into()
|
|
||||||
))),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
},
|
|
||||||
FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString("type".into())),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Value(number("1"))),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
}
|
|
||||||
],
|
|
||||||
&args[..]
|
|
||||||
),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
let select = ms()
|
|
||||||
.verified_only_select("SELECT JSON_OBJECT('name' : 'value', 'type' : NULL ABSENT ON NULL)");
|
|
||||||
match expr_from_projection(&select.projection[0]) {
|
|
||||||
Expr::Function(Function {
|
|
||||||
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
assert_eq!(
|
|
||||||
&[
|
|
||||||
FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
|
||||||
"value".into()
|
|
||||||
))),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
},
|
|
||||||
FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString("type".into())),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::Null)),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
}
|
|
||||||
],
|
|
||||||
&args[..]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
&[FunctionArgumentClause::JsonNullClause(
|
|
||||||
JsonNullClause::AbsentOnNull
|
|
||||||
)],
|
|
||||||
&clauses[..]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
let select = ms().verified_only_select("SELECT JSON_OBJECT(NULL ON NULL)");
|
|
||||||
match expr_from_projection(&select.projection[0]) {
|
|
||||||
Expr::Function(Function {
|
|
||||||
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
assert!(args.is_empty());
|
|
||||||
assert_eq!(
|
|
||||||
&[FunctionArgumentClause::JsonNullClause(
|
|
||||||
JsonNullClause::NullOnNull
|
|
||||||
)],
|
|
||||||
&clauses[..]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
let select = ms().verified_only_select("SELECT JSON_OBJECT(ABSENT ON NULL)");
|
|
||||||
match expr_from_projection(&select.projection[0]) {
|
|
||||||
Expr::Function(Function {
|
|
||||||
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
assert!(args.is_empty());
|
|
||||||
assert_eq!(
|
|
||||||
&[FunctionArgumentClause::JsonNullClause(
|
|
||||||
JsonNullClause::AbsentOnNull
|
|
||||||
)],
|
|
||||||
&clauses[..]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
let select = ms().verified_only_select(
|
|
||||||
"SELECT JSON_OBJECT('name' : 'value', 'type' : JSON_ARRAY(1, 2) ABSENT ON NULL)",
|
|
||||||
);
|
|
||||||
match expr_from_projection(&select.projection[0]) {
|
|
||||||
Expr::Function(Function {
|
|
||||||
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
assert_eq!(
|
|
||||||
&FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
|
||||||
"value".into()
|
|
||||||
))),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
},
|
|
||||||
&args[0]
|
|
||||||
);
|
|
||||||
assert!(matches!(
|
|
||||||
args[1],
|
|
||||||
FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString(_)),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Function(_)),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
}
|
|
||||||
));
|
|
||||||
assert_eq!(
|
|
||||||
&[FunctionArgumentClause::JsonNullClause(
|
|
||||||
JsonNullClause::AbsentOnNull
|
|
||||||
)],
|
|
||||||
&clauses[..]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
let select = ms().verified_only_select(
|
|
||||||
"SELECT JSON_OBJECT('name' : 'value', 'type' : JSON_OBJECT('type_id' : 1, 'name' : 'a') NULL ON NULL)",
|
|
||||||
);
|
|
||||||
match expr_from_projection(&select.projection[0]) {
|
|
||||||
Expr::Function(Function {
|
|
||||||
args: FunctionArguments::List(FunctionArgumentList { args, clauses, .. }),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
assert_eq!(
|
|
||||||
&FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString("name".into())),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
|
||||||
"value".into()
|
|
||||||
))),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
},
|
|
||||||
&args[0]
|
|
||||||
);
|
|
||||||
assert!(matches!(
|
|
||||||
args[1],
|
|
||||||
FunctionArg::ExprNamed {
|
|
||||||
name: Expr::Value(Value::SingleQuotedString(_)),
|
|
||||||
arg: FunctionArgExpr::Expr(Expr::Function(_)),
|
|
||||||
operator: FunctionArgOperator::Colon
|
|
||||||
}
|
|
||||||
));
|
|
||||||
assert_eq!(
|
|
||||||
&[FunctionArgumentClause::JsonNullClause(
|
|
||||||
JsonNullClause::NullOnNull
|
|
||||||
)],
|
|
||||||
&clauses[..]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
let select = ms().verified_only_select(
|
let select = ms().verified_only_select(
|
||||||
"SELECT JSON_OBJECT('user_name' : USER_NAME(), LOWER(@id_key) : @id_value, 'sid' : (SELECT @@SPID) ABSENT ON NULL)",
|
"SELECT JSON_OBJECT('user_name' : USER_NAME(), LOWER(@id_key) : @id_value, 'sid' : (SELECT @@SPID) ABSENT ON NULL)",
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue