Skip to content

Commit

Permalink
[bug](function) fix milliseconds_diff function return wrong result (a…
Browse files Browse the repository at this point in the history
…pache#32897)

* [bug](function) fix milliseconds_diff function return wrong result
  • Loading branch information
zhangstar333 committed Apr 1, 2024
1 parent 808c9cd commit 5c877e6
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 11 deletions.
18 changes: 14 additions & 4 deletions be/src/vec/functions/function_date_or_datetime_computation.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,25 @@ struct TimeDiffImpl {

static constexpr auto name = "timediff";
static constexpr auto is_nullable = false;
static inline ReturnType ::FieldType execute(const ArgType1& t0, const ArgType2& t1,
bool& is_null) {
static constexpr int64_t limit_value = 3020399000000; // 838:59:59 convert to microsecond
static inline ReturnType::FieldType execute(const ArgType1& t0, const ArgType2& t1,
bool& is_null) {
const auto& ts0 = reinterpret_cast<const DateValueType1&>(t0);
const auto& ts1 = reinterpret_cast<const DateValueType2&>(t1);
is_null = !ts0.is_valid_date() || !ts1.is_valid_date();
if constexpr (UsingTimev2) {
return ts0.microsecond_diff(ts1);
// refer to https://dev.mysql.com/doc/refman/5.7/en/time.html
// the time type value between '-838:59:59' and '838:59:59', so the return value should limited
int64_t diff_m = ts0.microsecond_diff(ts1);
if (diff_m > limit_value) {
return (double)limit_value;
} else if (diff_m < -1 * limit_value) {
return (double)(-1 * limit_value);
} else {
return (double)diff_m;
}
} else {
return (1000 * 1000) * ts0.second_diff(ts1);
return (double)((1000 * 1000) * ts0.second_diff(ts1));
}
}
static DataTypes get_variadic_argument_types() {
Expand Down
8 changes: 4 additions & 4 deletions be/src/vec/runtime/vdatetime_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -1111,13 +1111,13 @@ class DateV2Value {
return (daynr() - rhs.daynr()) * SECOND_PER_HOUR * HOUR_PER_DAY + time_part_diff(rhs);
}

// used by INT microseconds_diff(DATETIME enddate, DATETIME startdate)
// return it's int type, so shouldn't have any limit.
// when used by TIME TIMEDIFF(DATETIME expr1, DATETIME expr2), it's return time type, should have limited.
template <typename RHS>
double microsecond_diff(const RHS& rhs) const {
int64_t microsecond_diff(const RHS& rhs) const {
int64_t diff_m = (daynr() - rhs.daynr()) * SECOND_PER_HOUR * HOUR_PER_DAY * 1000 * 1000 +
time_part_diff_microsecond(rhs);
if (diff_m > (int64_t)3020399 * 1000 * 1000) {
diff_m = (int64_t)3020399 * 1000 * 1000;
}
return diff_m;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ under the License.
TIMEDIFF returns the difference between two DATETIMEs

The TIMEDIFF function returns the result of expr1 - expr2 expressed as a time value, with a return value of TIME type

The results are limited to TIME values ranging from - 838:59:59 to 838:59:59.
Due to the valid range of TIME type being '-838:59:59' to '838:59:59',
So when the return value of the calculation result is less than the left boundary or greater than the right boundary, the corresponding boundary value will be taken.

#### example

Expand All @@ -60,6 +60,13 @@ mysql> SELECT TIMEDIFF('2019-01-01 00:00:00', NULL);
+---------------------------------------+
| NULL |
+---------------------------------------+
mysql >SELECT timediff('2020-02-02 15:30:00', '1951-02-16 15:27:00') as res;
+-----------+
| res |
+-----------+
| 838:59:59 |
+-----------+
```
### keywords
TIMEDIFF
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ under the License.

TIMEDIFF返回两个DATETIME之间的差值

TIMEDIFF函数返回表示为时间值的expr1 - expr2的结果,返回值为TIME类型
TIMEDIFF函数返回表示为时间值的expr1 - expr2的结果,返回值为TIME类型, 由于TIME类型的合法有效范围为'-838:59:59' to '838:59:59',
所以当计算结果的返回值小于左边界或大于右边界时,会取对应的边界值.

### example

Expand All @@ -58,6 +59,13 @@ mysql> SELECT TIMEDIFF('2019-01-01 00:00:00', NULL);
+---------------------------------------+
| NULL |
+---------------------------------------+
mysql >SELECT timediff('2020-02-02 15:30:00', '1951-02-16 15:27:00') as res;
+-----------+
| res |
+-----------+
| 838:59:59 |
+-----------+
```

### keywords
Expand Down

0 comments on commit 5c877e6

Please sign in to comment.