Skip to content

fix: reject date_bin strides that are not positive - #26070

Open
viirya wants to merge 2 commits into
apache:mainfrom
viirya:date-bin-reject-nonpositive-stride
Open

viirya wants to merge 2 commits into
apache:mainfrom
viirya:date-bin-reject-nonpositive-stride

Conversation

@viirya

@viirya viirya commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Which issue does this PR close?

Rationale for this change

date_bin accepted negative strides, but they had no defined semantics:

  • A negative fixed stride rounds toward the origin, so a timestamp before the origin can land in a bin after it.
  • A negative month stride is not monotonic. date_bin(INTERVAL '-1 month', ts, TIMESTAMP '2023-01-31') bins 2023-01-01 to 2023-02-28 and 2023-01-31 to itself.

#25815 worked around the second one by not propagating ordering for negative month strides. As discussed in #25856, date_bin now rejects strides that are not positive. This matches PostgreSQL for fixed strides (PostgreSQL does not support month strides at all), and DataFusion applies the same rule to month strides. A positive stride already bins timestamps before the origin, so a negative stride adds nothing, and an error is better than silently taking the absolute value of an accidental negative.

What changes are included in this PR?

  • date_bin returns DATE_BIN stride must be greater than zero for a stride that is not positive. This covers negative months, negative days or nanoseconds, intervals whose parts add up to a negative stride, and TIME inputs. The zero-stride error is folded into this message.
  • output_ordering no longer special-cases negative month strides: any constant stride preserves the order of the source.
  • With only positive strides, compute_distance and compute_distance_wide round down with rem_euclid. For a positive stride this is the same as the old truncate-then-step-back logic, and the two functions still match. Overflow near i64::MIN still returns an error, which becomes NULL.
  • The date_bin docs say the interval must be greater than zero, and the 56.0.0 upgrade guide describes the change.

What is the testing strategy for this PR?

  • date_bin_errors.slt: error cases for negative month, year, minute, day and nanosecond strides, an interval whose parts add up to a negative stride, scalar and column inputs at second and nanosecond precision, and TIME inputs. The -1 nanosecond case replaces the unit test for the i64::MIN % -1 overflow from panic: date_bin compute_distance subtracts past i64::MIN #22215, which can no longer be reached.
  • timestamps.slt: the negative-month ordering cases from fix: bin coarse date_bin timestamps in i128 and restore ordering #25815 are replaced by the error tests above. The positive-month control stays, and the zero-stride cases expect the new message.
  • Unit tests: test_date_bin covers negative IntervalDayTime strides, which SQL interval literals cannot produce. output_ordering_requires_constant_stride replaces output_ordering_requires_monotonic_stride.

Are there any user-facing changes?

Yes, this is a breaking change: a negative date_bin stride is now an error. Previously it returned the same bins as the positive stride when the source was at or after the origin (for month strides, only when the source's day of month was not earlier than the origin's), and a bin later than the source otherwise. The zero-stride error message also changes. Both are documented in the 56.0.0 upgrade guide.

viirya added 2 commits October 5, 2026 22:11
Negative strides had no defined semantics: a negative fixed stride rounds
toward the origin, and a negative month stride is not monotonic. Like
PostgreSQL, `date_bin` now returns an error for a stride that is not
greater than zero, which also covers the zero stride.

With only positive strides, `output_ordering` no longer special-cases
negative month strides (added in apache#25815), and `compute_distance` /
`compute_distance_wide` round down with `rem_euclid`.

Closes apache#25856.
@viirya viirya added the api change Changes the API exposed to users of the crate label Oct 6, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation sqllogictest SQL Logic Tests (.slt) functions Changes to functions implementation labels Oct 6, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.69%. Comparing base (c0e872f) to head (7ed727a).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #26070      +/-   ##
==========================================
- Coverage   82.69%   82.69%   -0.01%     
==========================================
  Files        1147     1147              
  Lines      447348   447330      -18     
  Branches   447348   447330      -18     
==========================================
- Hits       369936   369919      -17     
+ Misses      54999    54998       -1     
  Partials    22413    22413              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

api change Changes the API exposed to users of the crate documentation Improvements or additions to documentation functions Changes to functions implementation sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

date_bin: define the semantics of negative strides

2 participants