u70b3 opened a new pull request, #23987:
URL: https://github.com/apache/datafusion/pull/23987

   ## Which issue does this PR close?
   
   - Closes #23894
   
   ## Rationale for this change
   
   `datafusion-spark`'s `mod` routes through the shared `try_rem` helper in
   `datafusion/spark/src/function/math/modulus.rs`, which has two gaps in its
   zero-divisor handling (both verified against Spark 3.5.8 – 4.2.0 in the 
issue):
   
   1. **ANSI mode, floating-point divisor.** `try_rem` delegates to Arrow's 
`rem`
      kernel in ANSI mode, but Arrow only reports division by zero for integer 
and
      decimal types. Floating-point divisors follow IEEE 754 and quietly produce
      `NaN`, while Spark raises `REMAINDER_BY_ZERO` for a zero divisor of any
      numeric type:
   
      ```sql
      set datafusion.execution.enable_ansi_mode = true;
      SELECT mod(10.5::float8, 0.0::float8);  -- NaN, Spark raises
      ```
   
   2. **`-0.0` divisor, both modes.** The legacy path nulls out zero divisors 
via
      `eq(right, 0)`, but Arrow's floating-point comparisons use a total order 
in
      which `-0.0` is distinct from `0.0`, so a `-0.0` divisor goes 
unrecognised.
      Spark's `isZero` is a numeric comparison and treats `-0.0` as zero:
   
      ```sql
      SELECT mod(10.5::float8, -0.0::float8);  -- NaN, Spark returns NULL 
(legacy)
      ```
   
   ## What changes are included in this PR?
   
   `try_rem` now detects zero divisors itself, mirroring the shape #23898
   established for `pmod`:
   
   - A new `is_zero` helper counts `-0.0` as zero for the floating-point types
     (via a `negative_zero` companion, same as #23898).
   - In ANSI mode, any row with a zero divisor raises `ArrowError::DivideByZero`
     — the same error Arrow's `rem` already produces for integers today, so the
     message stays uniform across types. The check is masked by the validity of
     the dividend because Spark's remainder expressions are null intolerant: a
     NULL dividend short-circuits to NULL before the divisor is validated, so
     `mod(NULL, 0)` must return NULL rather than raise.
   - Both modes substitute NULL for zero divisors before calling Arrow's `rem`,
     so the kernel never sees a zero divisor: legacy mode gets NULLs, and ANSI
     mode has already raised on the rows that required it.
   
   Note on overlap with #23898: that PR rewrites `pmod` to no longer use
   `try_rem` and adds identical `is_zero`/`negative_zero` helpers. This PR is
   independent of it — `mod` is fixed either way — but whichever lands second
   should dedupe the helpers in a rebase. Until #23898 lands, `pmod` also picks
   up the `-0.0` and ANSI floating-point zero-divisor fixes through the shared
   helper.
   
   Out of scope: #23897 (reproducing Spark's exact ANSI error text) is a
   repository-wide error-message policy question, as noted in that issue.
   
   ## Are these changes tested?
   
   Yes:
   
   - New unit tests in `modulus.rs`: ANSI floating-point zero divisor raises;
     `-0.0` divisor returns NULL in legacy mode and raises in ANSI mode; a NULL
     dividend with a zero divisor returns NULL in ANSI mode (integer and float).
   - New sqllogictest cases in `spark/math/mod.slt` covering the same behavior 
at
     SQL level.
   - Verified `cargo test -p datafusion-spark`, the `spark/math/mod.slt` and
     `spark/math/pmod.slt` sqllogictests, `./dev/rust_lint.sh`, and the extended
     workspace suite (ci profile with
     
`avro,json,backtrace,extended_tests,recursive_protection,parquet_encryption`)
     — all green.
   
   ## Are there any user-facing changes?
   
   Only the bug fixes, and only for the Spark `mod`/`pmod` functions: in ANSI
   mode a floating-point zero divisor now raises instead of returning NaN, and a
   `-0.0` divisor is treated as zero in both modes (NULL in legacy mode, an 
error
   in ANSI mode), matching Spark. No API changes.
   


-- 
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