Skip to content

Commit f7bac3f

Browse files
tests: cover PostgreSQL SQL/JSON clauses and keep JSON_TABLE AST expectations aligned
1 parent e7c162b commit f7bac3f

2 files changed

Lines changed: 158 additions & 0 deletions

File tree

tests/sqlparser_mysql.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3890,6 +3890,7 @@ fn parse_json_table() {
38903890
on_error: Some(JsonTableColumnErrorHandling::Null),
38913891
}),
38923892
],
3893+
on_error: None,
38933894
alias: table_alias(true, "t"),
38943895
}
38953896
);

tests/sqlparser_postgres.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3813,6 +3813,163 @@ fn parse_json_table_is_not_reserved() {
38133813
}
38143814
}
38153815

3816+
fn parse_pg_select(sql: &str) -> Select {
3817+
let stmts = pg().parse_sql_statements(sql).unwrap();
3818+
let stmt = stmts.into_iter().next().unwrap();
3819+
let Statement::Query(query) = stmt else {
3820+
panic!("Expected query statement");
3821+
};
3822+
let SetExpr::Select(select) = *query.body else {
3823+
panic!("Expected select query body");
3824+
};
3825+
*select
3826+
}
3827+
3828+
fn parse_pg_projection_expr(sql: &str) -> Expr {
3829+
let select = parse_pg_select(sql);
3830+
expr_from_projection(&select.projection[0]).clone()
3831+
}
3832+
3833+
#[test]
3834+
fn parse_postgres_sql_json_query_functions() {
3835+
let expr = parse_pg_projection_expr("SELECT JSON_EXISTS(jsonb '1', '$.a' FALSE ON ERROR)");
3836+
let Expr::Function(Function {
3837+
args: FunctionArguments::List(FunctionArgumentList { clauses, .. }),
3838+
..
3839+
}) = expr
3840+
else {
3841+
panic!("Expected JSON_EXISTS to parse as a function call");
3842+
};
3843+
assert_eq!(
3844+
clauses,
3845+
vec![FunctionArgumentClause::JsonExistsOnErrorClause(
3846+
JsonExistsOnErrorBehavior::False
3847+
)]
3848+
);
3849+
3850+
let expr = parse_pg_projection_expr(
3851+
"SELECT JSON_VALUE(jsonb '{\"a\": 1}', '$.a ? (@ > $x)' PASSING 0 AS x RETURNING int DEFAULT 1 ON EMPTY ERROR ON ERROR)",
3852+
);
3853+
let Expr::Function(Function {
3854+
args: FunctionArguments::List(FunctionArgumentList { clauses, .. }),
3855+
..
3856+
}) = expr
3857+
else {
3858+
panic!("Expected JSON_VALUE to parse as a function call");
3859+
};
3860+
assert!(matches!(
3861+
&clauses[0],
3862+
FunctionArgumentClause::JsonPassingClause(JsonPassingClause { args })
3863+
if args.len() == 1 && args[0].name.value == "x"
3864+
));
3865+
assert!(matches!(
3866+
&clauses[1],
3867+
FunctionArgumentClause::JsonReturningClause(JsonReturningClause {
3868+
data_type: DataType::Int(None)
3869+
})
3870+
));
3871+
assert!(matches!(
3872+
&clauses[2],
3873+
FunctionArgumentClause::JsonValueBehaviorClause(JsonValueBehaviorClause {
3874+
behavior: JsonValueBehavior::Default(_),
3875+
target: JsonBehaviorTarget::Empty,
3876+
})
3877+
));
3878+
assert!(matches!(
3879+
&clauses[3],
3880+
FunctionArgumentClause::JsonValueBehaviorClause(JsonValueBehaviorClause {
3881+
behavior: JsonValueBehavior::Error,
3882+
target: JsonBehaviorTarget::Error,
3883+
})
3884+
));
3885+
3886+
let expr = parse_pg_projection_expr(
3887+
"SELECT JSON_QUERY(jsonb '[\"1\"]', '$[*]' RETURNING bytea FORMAT JSON WITH UNCONDITIONAL ARRAY WRAPPER KEEP QUOTES ON SCALAR STRING EMPTY ARRAY ON EMPTY EMPTY OBJECT ON ERROR)",
3888+
);
3889+
let Expr::Function(Function {
3890+
args: FunctionArguments::List(FunctionArgumentList { clauses, .. }),
3891+
..
3892+
}) = expr
3893+
else {
3894+
panic!("Expected JSON_QUERY to parse as a function call");
3895+
};
3896+
assert!(matches!(
3897+
&clauses[0],
3898+
FunctionArgumentClause::JsonReturningClause(JsonReturningClause {
3899+
data_type: DataType::Bytea
3900+
})
3901+
));
3902+
assert!(matches!(
3903+
&clauses[1],
3904+
FunctionArgumentClause::JsonFormatClause(JsonFormatClause {
3905+
format: JsonFormatType::Json,
3906+
encoding: None,
3907+
})
3908+
));
3909+
assert!(matches!(
3910+
&clauses[2],
3911+
FunctionArgumentClause::JsonQueryWrapperClause(
3912+
JsonQueryWrapperClause::WithUnconditionalArrayWrapper
3913+
)
3914+
));
3915+
assert!(matches!(
3916+
&clauses[3],
3917+
FunctionArgumentClause::JsonQueryQuotesClause(JsonQueryQuotesClause {
3918+
mode: JsonQueryQuotesMode::Keep,
3919+
on_scalar_string: true,
3920+
})
3921+
));
3922+
assert!(matches!(
3923+
&clauses[4],
3924+
FunctionArgumentClause::JsonQueryBehaviorClause(JsonQueryBehaviorClause {
3925+
behavior: JsonQueryBehavior::EmptyArray,
3926+
target: JsonBehaviorTarget::Empty,
3927+
})
3928+
));
3929+
assert!(matches!(
3930+
&clauses[5],
3931+
FunctionArgumentClause::JsonQueryBehaviorClause(JsonQueryBehaviorClause {
3932+
behavior: JsonQueryBehavior::EmptyObject,
3933+
target: JsonBehaviorTarget::Error,
3934+
})
3935+
));
3936+
}
3937+
3938+
#[test]
3939+
fn parse_postgres_json_table_on_error() {
3940+
let select = parse_pg_select(
3941+
"SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH '$.a' ERROR ON ERROR) ERROR ON ERROR) jt",
3942+
);
3943+
let relation = &select.from[0].relation;
3944+
assert!(matches!(
3945+
relation,
3946+
TableFactor::JsonTable {
3947+
on_error: Some(JsonTableOnErrorHandling::Error),
3948+
..
3949+
}
3950+
));
3951+
3952+
let select = parse_pg_select(
3953+
"SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH '$.a') EMPTY ARRAY ON ERROR) jt",
3954+
);
3955+
let relation = &select.from[0].relation;
3956+
assert!(matches!(
3957+
relation,
3958+
TableFactor::JsonTable {
3959+
on_error: Some(JsonTableOnErrorHandling::EmptyArray),
3960+
..
3961+
}
3962+
));
3963+
}
3964+
3965+
#[test]
3966+
fn parse_postgres_sql_json_duplicate_behavior_clauses() {
3967+
let sql = "SELECT JSON_VALUE(jsonb '1', '$.a' NULL ON EMPTY ERROR ON EMPTY)";
3968+
assert!(pg().parse_sql_statements(sql).is_err());
3969+
let sql = "SELECT JSON_QUERY(jsonb '[]', '$[*]' NULL ON ERROR EMPTY ARRAY ON ERROR)";
3970+
assert!(pg().parse_sql_statements(sql).is_err());
3971+
}
3972+
38163973
#[test]
38173974
fn test_composite_value() {
38183975
let sql = "SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9";

0 commit comments

Comments
 (0)