Skip to content

PostgreSQL: bind unary plus and minus tighter than ^ - #2830

Closed
compiler-segfault wants to merge 1 commit into
apache:mainfrom
compiler-segfault:pg-unary-operand-precedence
Closed

compiler-segfault wants to merge 1 commit into
apache:mainfrom
compiler-segfault:pg-unary-operand-precedence

Conversation

@compiler-segfault

Copy link
Copy Markdown

SELECT -1 ^ 0 is parsed as -(1 ^ 0) by PostgreSqlDialect, so it yields -1 where PostgreSQL yields 1; SELECT +2 ^ 2 yields -4 instead of 4.

PostgreSQL 17:  SELECT -1 ^ 0;  ->  1
sqlparser:      UnaryOp { op: Minus, expr: BinaryOp { .., op: PGExp, .. } }

In gram.y UMINUS is declared above COLLATE, AT and ^, so the operand of a unary +/- may only take ., :: and []. The operand precedence is now a Dialect method that defaults to the previous MulDivModOp value, and PostgreSqlDialect returns the COLLATE level. That also makes -a AT TIME ZONE 'tz' parse as (-a) AT TIME ZONE 'tz', which is the same reading gram.y gives.

PostgreSQL precedence table

parse_unary_operand_binds_tighter_than_exponentiation is added to tests/sqlparser_postgres.rs; without the change it fails with the AST quoted above.

cargo test --all-features, cargo fmt --all and cargo clippy --all-targets --all-features -- -D warnings all pass.

Prepared with AI assistance; I reviewed the diff and ran the checks above.

Fixes #2819.

@compiler-segfault
compiler-segfault force-pushed the pg-unary-operand-precedence branch from d100d9a to 447c7c9 Compare November 7, 2026 08:39
@LucaCappelletti94

Copy link
Copy Markdown
Contributor

Closing as a duplicate of #2829

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PostgreSQL: unary minus binds more loosely than ^, so -1 ^ 0 parses as -(1 ^ 0)

2 participants