Skip to content

Commit 4d93386

Browse files
authored
Fix for Postgres regex and like binary operators (#1928)
1 parent 6506814 commit 4d93386

File tree

2 files changed

+55
-15
lines changed

2 files changed

+55
-15
lines changed

src/parser/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3486,10 +3486,18 @@ impl<'a> Parser<'a> {
34863486
| BinaryOperator::LtEq
34873487
| BinaryOperator::Eq
34883488
| BinaryOperator::NotEq
3489+
| BinaryOperator::PGRegexMatch
3490+
| BinaryOperator::PGRegexIMatch
3491+
| BinaryOperator::PGRegexNotMatch
3492+
| BinaryOperator::PGRegexNotIMatch
3493+
| BinaryOperator::PGLikeMatch
3494+
| BinaryOperator::PGILikeMatch
3495+
| BinaryOperator::PGNotLikeMatch
3496+
| BinaryOperator::PGNotILikeMatch
34893497
) {
34903498
return parser_err!(
34913499
format!(
3492-
"Expected one of [=, >, <, =>, =<, !=] as comparison operator, found: {op}"
3500+
"Expected one of [=, >, <, =>, =<, !=, ~, ~*, !~, !~*, ~~, ~~*, !~~, !~~*] as comparison operator, found: {op}"
34933501
),
34943502
span.start
34953503
);

tests/sqlparser_postgres.rs

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,21 +2187,39 @@ fn parse_pg_regex_match_ops() {
21872187
("!~*", BinaryOperator::PGRegexNotIMatch),
21882188
];
21892189

2190+
// Match against a single value
21902191
for (str_op, op) in pg_regex_match_ops {
2191-
let select = pg().verified_only_select(&format!("SELECT 'abc' {} '^a'", &str_op));
2192+
let select = pg().verified_only_select(&format!("SELECT 'abc' {str_op} '^a'"));
21922193
assert_eq!(
21932194
SelectItem::UnnamedExpr(Expr::BinaryOp {
2194-
left: Box::new(Expr::Value(
2195-
(Value::SingleQuotedString("abc".into())).with_empty_span()
2196-
)),
2195+
left: Box::new(Expr::Value(single_quoted_string("abc").with_empty_span(),)),
21972196
op: op.clone(),
2198-
right: Box::new(Expr::Value(
2199-
(Value::SingleQuotedString("^a".into())).with_empty_span()
2200-
)),
2197+
right: Box::new(Expr::Value(single_quoted_string("^a").with_empty_span(),)),
22012198
}),
22022199
select.projection[0]
22032200
);
22042201
}
2202+
2203+
// Match against any value from an array
2204+
for (str_op, op) in pg_regex_match_ops {
2205+
let select =
2206+
pg().verified_only_select(&format!("SELECT 'abc' {str_op} ANY(ARRAY['^a', 'x'])"));
2207+
assert_eq!(
2208+
SelectItem::UnnamedExpr(Expr::AnyOp {
2209+
left: Box::new(Expr::Value(single_quoted_string("abc").with_empty_span(),)),
2210+
compare_op: op.clone(),
2211+
right: Box::new(Expr::Array(Array {
2212+
elem: vec![
2213+
Expr::Value(single_quoted_string("^a").with_empty_span()),
2214+
Expr::Value(single_quoted_string("x").with_empty_span()),
2215+
],
2216+
named: true,
2217+
})),
2218+
is_some: false,
2219+
}),
2220+
select.projection[0]
2221+
)
2222+
}
22052223
}
22062224

22072225
#[test]
@@ -2213,21 +2231,35 @@ fn parse_pg_like_match_ops() {
22132231
("!~~*", BinaryOperator::PGNotILikeMatch),
22142232
];
22152233

2234+
// Match against a single value
22162235
for (str_op, op) in pg_like_match_ops {
2217-
let select = pg().verified_only_select(&format!("SELECT 'abc' {} 'a_c%'", &str_op));
2236+
let select = pg().verified_only_select(&format!("SELECT 'abc' {str_op} 'a_c%'"));
22182237
assert_eq!(
22192238
SelectItem::UnnamedExpr(Expr::BinaryOp {
2220-
left: Box::new(Expr::Value(
2221-
(Value::SingleQuotedString("abc".into())).with_empty_span()
2222-
)),
2239+
left: Box::new(Expr::Value(single_quoted_string("abc").with_empty_span(),)),
22232240
op: op.clone(),
2224-
right: Box::new(Expr::Value(
2225-
(Value::SingleQuotedString("a_c%".into())).with_empty_span()
2226-
)),
2241+
right: Box::new(Expr::Value(single_quoted_string("a_c%").with_empty_span(),)),
22272242
}),
22282243
select.projection[0]
22292244
);
22302245
}
2246+
2247+
// Match against all values from an array
2248+
for (str_op, op) in pg_like_match_ops {
2249+
let select =
2250+
pg().verified_only_select(&format!("SELECT 'abc' {str_op} ALL(ARRAY['a_c%'])"));
2251+
assert_eq!(
2252+
SelectItem::UnnamedExpr(Expr::AllOp {
2253+
left: Box::new(Expr::Value(single_quoted_string("abc").with_empty_span(),)),
2254+
compare_op: op.clone(),
2255+
right: Box::new(Expr::Array(Array {
2256+
elem: vec![Expr::Value(single_quoted_string("a_c%").with_empty_span())],
2257+
named: true,
2258+
})),
2259+
}),
2260+
select.projection[0]
2261+
)
2262+
}
22312263
}
22322264

22332265
#[test]

0 commit comments

Comments
 (0)