Skip to content

fix: add parentheses in binary expr human_display to reflect precedence#21787

Open
Jah-yee wants to merge 2 commits intoapache:mainfrom
Jah-yee:main
Open

fix: add parentheses in binary expr human_display to reflect precedence#21787
Jah-yee wants to merge 2 commits intoapache:mainfrom
Jah-yee:main

Conversation

@Jah-yee
Copy link
Copy Markdown

@Jah-yee Jah-yee commented Apr 22, 2026

Good day,

This PR fixes #16054 - "Expr formatting missing parentheses".

Problem

The human_display() method for BinaryExpr was not adding parentheses to correctly reflect operator precedence. For example, (1+2)*3 was displayed as 1 + 2 * 3 instead of (1 + 2) * 3.

Solution

Added a write_child helper function that checks operator precedence and wraps child BinaryExprs in parentheses when the child has lower precedence than the parent. This matches the behavior in the BinaryExpr Display impl.

Changes

  • Modified SqlDisplay::write for Expr::BinaryExpr to use precedence-aware child formatting
  • Added test_human_display_binary_expr_parens test to verify the fix

Test results

cargo test -p datafusion-expr test_human_display_binary_expr_parens passes ✅

Verification

  • Commit author: Jah-yee jydu_seven@outlook.com
  • All existing tests pass (ran full test suite for datafusion-expr)

Thank you for your attention. If there are any issues or suggestions, please leave a comment and I will address them promptly.

Warmly, Jah-yee

Fixes apache#16054 - Expr formatting missing parentheses

The human_display() method for BinaryExpr was not adding parentheses
to correctly reflect operator precedence. For example, (1+2)*3 was
displayed as 1 + 2 * 3 instead of (1 + 2) * 3.

This change adds a write_child helper that checks operator precedence
and wraps child BinaryExprs in parentheses when the child has lower
precedence than the parent.

Added test_human_display_binary_expr_parens to verify the fix.
@github-actions github-actions Bot added the logical-expr Logical plan and expressions label Apr 22, 2026
@Jefffrey
Copy link
Copy Markdown
Contributor

I think we'd also need to fix SchemaDisplay as well in order to close the issue, reference:

Copy link
Copy Markdown
Contributor

@kosiew kosiew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jah-yee
Thanks for working on this. I think there is one semantics issue to address before this lands, plus one follow-up cleanup that would help keep the display logic consistent.

match expr {
Expr::BinaryExpr(child) => {
let p = child.op.precedence();
if p == 0 || p < precedence {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this still needs to account for equal-precedence expressions on the right-hand side.

For example, lit(1) - (lit(2) - lit(3)) would currently render as 1 - 2 - 3, which is normally read as (1 - 2) - 3. Similarly, a / (b * c) would render as a / b * c.

I would expect human_display() to preserve the expression tree semantics whenever it omits parentheses. Could we distinguish left and right children here, and parenthesize right-hand children with equal precedence when the parent and child operator combination is not safely associative?

Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
write!(f, "{} {op} {}", SqlDisplay(left), SqlDisplay(right),)
// Add parentheses around child binary expressions to correctly reflect
// precedence. Same logic as BinaryExpr Display impl.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it duplicates the existing BinaryExpr Display precedence logic.

Once the associativity and equal-precedence case is fixed, could we extract a small shared helper, perhaps parameterized by the child display function, so Display and human_display() do not drift again?

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

Labels

logical-expr Logical plan and expressions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expr formatting missing parentheses

4 participants