fix: allow arbitrary operators with ANY and ALL on Postgres

In sqlparser PR #963 a check was introduced which limits which operators can be used with `ANY` and `ALL` expressions.

Postgres can parse more (possibly _all_ binary operators, investigation pending) in this location. Postgres only seems to care that the operator yields a boolean - which is a semantic error, not a syntax (parse) error.

Example (semantic error, not a parse error):

```
select 123 % ANY(array[246]);
ERROR:  op ANY/ALL (array) requires operator to yield boolean
LINE 1: select 123 % ANY(array[246]);
                   ^
```

The following code in `src/parser/mod.rs:2893-2908` is where the allowlist of operators is enforced:

```rust
if !matches!(
    op,
    BinaryOperator::Gt
        | BinaryOperator::Lt
        | BinaryOperator::GtEq
        | BinaryOperator::LtEq
        | BinaryOperator::Eq
        | BinaryOperator::NotEq
) {
    return parser_err!(
        format!(
        "Expected one of [=, >, <, =>, =<, !=] as comparison operator, found: {op}"
    ),
        tok.span.start
    );
};
```
This commit is contained in:
James Sadler 2025-05-07 17:18:49 +10:00
parent ac1c339666
commit 365cfb1bdf
No known key found for this signature in database
2 changed files with 31 additions and 1 deletions

View file

@ -3471,7 +3471,7 @@ impl<'a> Parser<'a> {
right
};
if !matches!(
if !dialect_of!(self is PostgreSqlDialect) && !matches!(
op,
BinaryOperator::Gt
| BinaryOperator::Lt

View file

@ -5936,6 +5936,36 @@ fn parse_bitstring_literal() {
);
}
#[test]
fn parse_arbitrary_operator_with_any_and_all() {
// The following statement is semantically non-sensical on vanilla postgres but it should *parse* in order to
// support situations where PG operators have been overloaded.
let select = pg().verified_only_select("SELECT 123 % ANY(ARRAY[1, 2, 3])");
assert!(
matches!(
select.projection[0],
SelectItem::UnnamedExpr(Expr::AnyOp {
left: _,
compare_op: BinaryOperator::Modulo,
right: _,
is_some: false
})
)
);
let select = pg().verified_only_select("SELECT 123 % ALL(ARRAY[1, 2, 3])");
assert!(
matches!(
select.projection[0],
SelectItem::UnnamedExpr(Expr::AllOp {
left: _,
compare_op: BinaryOperator::Modulo,
right: _,
})
)
);
}
#[test]
fn parse_varbit_datatype() {
match pg_and_generic().verified_stmt("CREATE TABLE foo (x VARBIT, y VARBIT(42))") {