nikolas-sapa opened a new pull request, #26742:
URL: https://github.com/apache/datafusion/pull/26742

   ## Which issue does this PR close?
   
   - Closes #26671
   
   ## Rationale for this change
   
   Comparing a `Duration` (e.g. `ts1 - ts2`) with an `INTERVAL` that has a days 
or months
   component silently returns wrong results. For example, both of these 
returned `true`
   for a 10-day duration:
   
   ```sql
   select (timestamp '2026-01-11' - timestamp '2026-01-01') <= interval '3 
days'; -- true (wrong)
   select interval '3 days' >= (timestamp '2026-01-11' - timestamp 
'2026-01-01'); -- true (wrong)
   ```
   
   so range filters built on such comparisons silently filter the wrong rows.
   
   Root cause: the mixed comparison coerced both sides to 
`Interval(MonthDayNano)`.
   arrow-cast represents the duration side as `IntervalMonthDayNano(0, 0, 
nanos)`, and
   `IntervalMonthDayNano`'s derived ordering compares months, then days, then 
nanoseconds —
   so any interval with non-zero days or months decides the comparison on a 
field the
   duration side can never influence.
   
   ## What changes are included in this PR?
   
   - Mixed `Duration`/`Interval` comparisons now compare exact elapsed time: 
both sides
     coerce to `Duration(Nanosecond)` via a new 
`duration_interval_comparison_coercion`,
     routed from `comparison_coercion_inner` so it covers comparison operators, 
`IN`
     lists, `CASE`/`WHEN` and `BETWEEN`.
   - Intervals whose months and days are zero (e.g. `INTERVAL '240 hours'`) 
compare
     exactly and correctly.
   - Intervals with non-zero months or days now fail loudly when converted — 
during
     constant folding or at execution — with Arrow's "Cannot convert interval 
containing
     non-zero months or days to duration", instead of silently returning wrong 
results.
     `Interval(YearMonth)` and `Interval(DayTime)` have no exact duration 
conversion and
     fail at planning ("cannot infer common argument type"), as before.
   - `Duration`-vs-`Duration` and `Interval`-vs-`Interval` comparison coercion 
is unchanged:
     both still compare via `Interval(MonthDayNano)`'s ordering, consistent 
with Postgres
     (so `interval '3 days' > interval '240 hours'` remains true). Only mixed 
pairs change.
   
   Design note for reviewers: an alternative semantics would treat a day as 
exactly
   86,400 seconds and only reject months-bearing intervals. This PR 
deliberately follows
   Arrow's cast semantics instead: a "day" added to a timezone-aware timestamp 
is not
   always 86,400 seconds (DST transitions), so treating days as fixed in 
*comparisons*
   would silently disagree with `ts + INTERVAL '1 day'` *arithmetic* — erroring 
keeps the
   two consistent, and mirrors Arrow's own refusal to convert. Happy to switch 
to
   `days == 0`-only-erroring if maintainers prefer.
   
   ## What is the testing strategy for this PR?
   
   - Unit tests: `test_duration_interval_comparison_coercion` in
     `datafusion/expr-common/src/type_coercion/binary/tests/comparison.rs` 
covers all six
     comparison operators plus `IS DISTINCT FROM` / `IS NOT DISTINCT FROM`, all 
four
     duration units, both operand orders, the `YearMonth`/`DayTime` rejection, 
and that
     Duration-vs-Duration / Interval-vs-Interval coercions are unchanged.
   - sqllogictest regressions in 
`datafusion/sqllogictest/test_files/datetime/interval.slt`:
     the constant-folded path (scalar duration vs scalar interval), the runtime 
path
     (column values, both operand orders), an `IN`-list with the mixed pair,
     pure-nanosecond intervals comparing exactly, and the exact error messages 
for
     months/days-bearing intervals and for 
`Interval(YearMonth)`/`Interval(DayTime)`.
   - Verified locally: `cargo test -p datafusion-expr-common --lib` (222 
passed),
     the `datetime/interval` sqllogictest files, `cargo fmt --all -- --check`,
     `cargo clippy --all-targets --workspace --all-features -- -D warnings`, 
and the full
     workspace suite via `RUST_BACKTRACE=1 cargo xtask ci step test workspace`
     (13,043 passed / 0 failed / 15 ignored on the pre-amend tree; the amend 
adds only
     test assertions, re-verified by the targeted runs above).
   
   ## Are there any user-facing changes?
   
   Yes — a behavior change from silently wrong results to explicit errors for
   Duration-vs-Interval comparisons where the interval has non-zero months or 
days;
   pure-time intervals now compare correctly. No public 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