mirror of
https://github.com/duckdb/duckdb.git
synced 2026-10-29 01:06:47 +08:00
Reject timestamps below the minimum in time_bucket, epoch_ms and to_timestamp
This commit is contained in:
1 parent
0d55d51113
commit
65cdf0fa07
4 files changed
+57
-1
No files matched your search
@@ -12,7 +12,9 @@ struct EpochSecOperator {
|
||||
template <class INPUT_TYPE, class RESULT_TYPE>
|
||||
static RESULT_TYPE Operation(INPUT_TYPE sec) {
|
||||
int64_t result;
|
||||
if (!TryCast::Operation(sec * Interval::MICROS_PER_SEC, result)) {
|
||||
// the first midnight of Timestamp::MIN_YEAR - smaller values are not valid timestamps
|
||||
constexpr int64_t min_timestamp_micros = -9223372022400000000LL;
|
||||
if (!TryCast::Operation(sec * Interval::MICROS_PER_SEC, result) || result < min_timestamp_micros) {
|
||||
throw ConversionException("Epoch seconds out of range for TIMESTAMP WITH TIME ZONE");
|
||||
}
|
||||
return timestamp_t(result);
|
||||
|
||||
@@ -97,6 +97,9 @@ struct TimeBucket {
|
||||
return (Date::ExtractYear(ts_date) - 1970) * 12 + Date::ExtractMonth(ts_date) - 1;
|
||||
}
|
||||
|
||||
//! The first midnight of Timestamp::MIN_YEAR - smaller values are not valid timestamps
|
||||
static constexpr int64_t MIN_TIMESTAMP_MICROS = -9223372022400000000LL;
|
||||
|
||||
static inline timestamp_t WidthConvertibleToMicrosCommon(int64_t bucket_width_micros, int64_t ts_micros,
|
||||
int64_t origin_micros) {
|
||||
origin_micros %= bucket_width_micros;
|
||||
@@ -108,6 +111,9 @@ struct TimeBucket {
|
||||
SubtractOperatorOverflowCheck::Operation<int64_t, int64_t, int64_t>(result_micros, bucket_width_micros);
|
||||
}
|
||||
result_micros = AddOperatorOverflowCheck::Operation<int64_t, int64_t, int64_t>(result_micros, origin_micros);
|
||||
if (result_micros < MIN_TIMESTAMP_MICROS) {
|
||||
throw OutOfRangeException("Overflow in TIME_BUCKET: the result is below the minimum TIMESTAMP");
|
||||
}
|
||||
|
||||
return Timestamp::FromEpochMicroSeconds(result_micros);
|
||||
}
|
||||
|
||||
@@ -450,6 +450,10 @@ timestamp_t Timestamp::FromEpochMsPossiblyInfinite(int64_t ms) {
|
||||
if (!TryMultiplyOperator::Operation(ms, Interval::MICROS_PER_MSEC, result)) {
|
||||
throw ConversionException("Could not convert Timestamp(MS) to Timestamp(US)");
|
||||
}
|
||||
// the first midnight of Timestamp::MIN_YEAR - smaller values are not valid timestamps
|
||||
if (result < -9223372022400000000LL) {
|
||||
throw ConversionException("Could not convert Timestamp(MS) to Timestamp(US)");
|
||||
}
|
||||
return timestamp_t(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# name: test/sql/function/timestamp/test_timestamp_lower_bound.test
|
||||
# description: Timestamp constructors reject values below the minimum timestamp
|
||||
# group: [timestamp]
|
||||
|
||||
statement error
|
||||
SELECT time_bucket(INTERVAL '1 hour', TIMESTAMP '290309-12-22 (BC) 00:00:00', TIMESTAMP '2000-01-01 00:00:01')
|
||||
----
|
||||
Overflow in TIME_BUCKET
|
||||
|
||||
statement error
|
||||
SELECT epoch_ms(-9223372022400001)
|
||||
----
|
||||
<REGEX>:.*(Out of Range|Conversion) Error.*
|
||||
|
||||
statement error
|
||||
SELECT make_timestamp_ms(-9223372022400001)
|
||||
----
|
||||
<REGEX>:.*(Out of Range|Conversion) Error.*
|
||||
|
||||
statement error
|
||||
SELECT to_timestamp(-9223372022401)
|
||||
----
|
||||
<REGEX>:.*(Out of Range|Conversion) Error.*
|
||||
|
||||
statement error
|
||||
SELECT to_timestamp(-9223372036854.775808)
|
||||
----
|
||||
<REGEX>:.*(Out of Range|Conversion) Error.*
|
||||
|
||||
# the minimum timestamp is still accepted
|
||||
query I
|
||||
SELECT epoch_ms(-9223372022400000)::VARCHAR
|
||||
----
|
||||
290309-12-22 (BC) 00:00:00
|
||||
|
||||
query I
|
||||
SELECT to_timestamp(-9223372022400)::VARCHAR
|
||||
----
|
||||
290309-12-22 (BC) 00:00:00+00
|
||||
|
||||
query I
|
||||
SELECT time_bucket(INTERVAL '1 hour', TIMESTAMP '2020-01-01 10:30:00', TIMESTAMP '2000-01-01 00:00:01')::VARCHAR
|
||||
----
|
||||
2020-01-01 10:00:01
|
||||
Reference in new issue
Block a user