xgbtxy opened a new issue, #27365:
URL: https://github.com/apache/datafusion/issues/27365

   ### Describe the bug
   
   In `datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs` 
(verified on DataFusion `55.0.0` and `main` `HEAD` `e1c625fdf5`, lines 
1151–1166), literal comparison conjunction simplification rewrites:
   - `f = 0.0 AND f != -0.0` $\rightarrow$ `f = 0.0`
   - `f = 0.0 AND f = -0.0` $\rightarrow$ `false`
   - `f IN (0.0) AND f NOT IN (-0.0)` $\rightarrow$ `f = 0.0`
   
   because distinctness between two literal `ScalarValue`s (`l1 != l2`) is 
checked using Rust's `ScalarValue::PartialEq` (which uses totalOrder / 
bit-aware comparison where `Float64(0.0) != Float64(-0.0)` is `true`), whereas 
DataFusion/Arrow's SQL `=` and `!=` operators follow IEEE-754 numeric equality 
where `0.0 = -0.0` is `true` and `0.0 != -0.0` is `false`.
   
   As a result, disabling the logical optimizer 
(`datafusion.optimizer.max_passes = 0`) vs. running with default optimizations 
produces opposite query results.
   
   ### To Reproduce
   
   ```python
   import datafusion
   import pyarrow as pa
   
   tbl = pa.table({
       "id": pa.array([1, 2, 3], type=pa.int64()),
       "f": pa.array([0.0, -0.0, 1.5], type=pa.float64()),
   })
   
   ctx_unopt = datafusion.SessionContext(
       datafusion.SessionConfig().set("datafusion.optimizer.max_passes", "0")
   )
   ctx_opt = datafusion.SessionContext()
   ctx_unopt.from_arrow(tbl, name="t")
   ctx_opt.from_arrow(tbl, name="t")
   
   for q in [
       "SELECT id FROM t WHERE f = 0.0 AND f != -0.0 ORDER BY id",
       "SELECT id FROM t WHERE f = 0.0 AND f = -0.0 ORDER BY id",
   ]:
       r_unopt = [r["id"] for b in ctx_unopt.sql(q).collect() for r in 
b.to_pylist()]
       r_opt = [r["id"] for b in ctx_opt.sql(q).collect() for r in 
b.to_pylist()]
       print(q)
       print("  max_passes=0:", r_unopt)
       print("  default opt :", r_opt)
   ```
   
   Output on DataFusion `55.0.0`:
   ```text
   SELECT id FROM t WHERE f = 0.0 AND f != -0.0 ORDER BY id
     max_passes=0: []
     default opt : [1, 2]
   SELECT id FROM t WHERE f = 0.0 AND f = -0.0 ORDER BY id
     max_passes=0: [1, 2]
     default opt : []
   ```
   
   ### Expected behavior
   
   Under IEEE-754 floating-point equality (`0.0 = -0.0` is `true`):
   - `SELECT id FROM t WHERE f = 0.0 AND f != -0.0` should return `[]` 
(matching `max_passes=0`, PostgreSQL, DuckDB, and SQLite).
   - `SELECT id FROM t WHERE f = 0.0 AND f = -0.0` should return `[1, 2]`.
   
   ### Additional context
   
   In `expr_simplifier.rs` (around lines 1151–1166, introduced in #19731, and 
similarly in `A = L1 AND A = L2 -> false`), comparing floating-point 
`ScalarValue`s (`Float16`, `Float32`, `Float64`) for SQL `=` / `!=` 
simplification needs numeric zero-sign-insensitive equality (`+0.0 == -0.0` and 
`NaN` handling matching DataFusion's `eq` kernel) rather than 
`ScalarValue::PartialEq`.
   
   ### Willingness to contribute
   
   I would like to contribute a fix for this bug, but request guidance from the 
DataFusion community
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to