nikolas-sapa commented on issue #26671:
URL: https://github.com/apache/datafusion/issues/26671#issuecomment-6424993031

   Hi — I dug into this and opened PR #26742 with a fix. Thanks for the clear 
repro!
   
   **Root cause.** Comparison coercion unifies any `Duration` with any 
`Interval` as `Interval(MonthDayNano)`, and arrow's duration→interval cast puts 
the *entire* duration into the nanoseconds field (`IntervalMonthDayNano::new(0, 
0, v)` in arrow-cast 60.0.0 `cast/mod.rs:516-568`). But 
`IntervalMonthDayNano`'s derived `Ord` is lexicographic **months → days → 
nanoseconds** (arrow-buffer `interval.rs:46-77` — its docs warn the ordering is 
"potentially surprising"). So for `(ts1 - ts2) <= INTERVAL '3 days'`, the 
duration becomes `{months: 0, days: 0, nanos: 10d}` and the interval `{months: 
0, days: 3, nanos: 0}` — the days field decides `0 < 3` before nanoseconds are 
ever compared, and the predicate folds to `true`. Any interval with a non-zero 
months or days field mis-decides the same way; pure-nanosecond intervals 
(`INTERVAL '1 hour'`) happened to compare correctly because the comparison 
degenerated to a pure nanoseconds compare. Both the constant-folded and the 
runtime path
  are affected.
   
   **Proposed semantics** (in the PR): mixed Duration-vs-Interval comparisons 
coerce both sides to `Duration(Nanosecond)` and compare exact elapsed time, 
following arrow's own convertibility rules:
   
   - arrow-cast only supports `Duration <-> Interval(MonthDayNano)` casts at 
all (`cast/mod.rs:336-337`), so `Interval(YearMonth)`/`Interval(DayTime)` mixed 
comparisons are rejected at planning (`Cannot infer common argument type for 
comparison operation`).
   - `cast_month_day_nano_to_duration` succeeds exactly when `months == 0 && 
days == 0` and otherwise fails loudly (`Cannot convert interval containing 
non-zero months or days to duration`). With DataFusion's default `safe: false` 
cast options, pure-nanosecond intervals keep comparing correctly via exact 
nanoseconds, while days/months intervals error — at plan time for literals, at 
execution time for columns — instead of silently returning wrong results.
   - Duration-vs-Duration, Interval-vs-Interval, and UNION/CASE type 
unification are unchanged.
   
   **One judgment call I'd appreciate maintainer feedback on:** for intervals 
with a **days** component, an alternative would be to normalize days as exact 
24h (`days * 86_400e9 + nanos`) and reject only months (arrow-arith does add 
interval days as exact 24h, `arrow-array` `types.rs:1095-1105`). I went with 
erroring instead, because arrow-cast deliberately refuses interval→duration for 
non-zero days, and hand-rolling the conversion would make `d <= i` disagree 
with `CAST(i AS Duration(...))` / `arrow_cast(i, 'Duration(Second)')`. If you'd 
rather keep `d <= INTERVAL '3 days'` working via exact-24h normalization, 
that's a small change to the coercion and I'm happy to do it.
   
   (Prepared with AI assistance; analysis and fix verified locally — unit tests 
plus sqllogictests for both the constant-folded and runtime paths, all green.)
   


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