Skip to content

Commit b4fcb2e

Browse files
committed
fix: stop timestamp series at range boundary
1 parent 49bd63d commit b4fcb2e

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

datafusion/functions-table/src/generate_series.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,27 @@ impl SeriesValue for TimestampValue {
197197
Ok(())
198198
}
199199

200+
fn advance_with_end(&mut self, end: &mut Self, step: &Self::StepType) -> Result<()> {
201+
let tz = self
202+
.parsed_tz
203+
.unwrap_or_else(|| Tz::from_str("+00:00").unwrap());
204+
if let Some(next_ts) =
205+
TimestampNanosecondType::add_month_day_nano(self.value, *step, tz)
206+
{
207+
self.value = next_ts;
208+
} else {
209+
// Advancing would exceed the timestamp range. Clamp `end` so the
210+
// series terminates after the current (last reachable) value.
211+
let step_negative = step.months < 0 || step.days < 0 || step.nanoseconds < 0;
212+
end.value = if step_negative {
213+
self.value.saturating_add(1)
214+
} else {
215+
self.value.saturating_sub(1)
216+
};
217+
}
218+
Ok(())
219+
}
220+
200221
fn create_array(&self, values: Vec<Self::ValueType>) -> Result<ArrayRef> {
201222
let array = TimestampNanosecondArray::from(values);
202223

datafusion/sqllogictest/test_files/table_functions.slt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,19 @@ SELECT * FROM generate_series(TIMESTAMP '2262-04-11T23:47:16.854775807', TIMESTA
246246
----
247247
2262-04-11T23:47:16.854775807
248248

249+
# A timestamp step that exceeds the nanosecond range must terminate after the
250+
# last reachable value instead of returning an overflow error.
251+
query P
252+
SELECT * FROM generate_series(TIMESTAMP '2262-04-11T23:47:16.854775806', TIMESTAMP '2262-04-11T23:47:16.854775807', INTERVAL '2' NANOSECOND)
253+
----
254+
2262-04-11T23:47:16.854775806
255+
256+
# Same behavior for date series, which use the timestamp implementation.
257+
query P
258+
SELECT * FROM generate_series(DATE '2262-04-10', DATE '2262-04-11', INTERVAL '2' DAY)
259+
----
260+
2262-04-10T00:00:00
261+
249262
# UDF and UDTF `generate_series` can be used simultaneously
250263
query ? rowsort
251264
SELECT generate_series(1, t1.end) FROM generate_series(3, 5) as t1(end)

0 commit comments

Comments
 (0)