[bug](function) fix milliseconds_diff function return wrong result (#32897)

* [bug](function) fix milliseconds_diff function return wrong result
This commit is contained in:
zhangstar333
2024-03-29 16:51:49 +08:00
committed by yiguolei
parent 3b7d75fb4b
commit 59aa923bce
5 changed files with 36 additions and 15 deletions

View File

@ -289,15 +289,25 @@ struct TimeDiffImpl {
static constexpr auto name = "timediff";
static constexpr auto is_nullable = false;
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() {

View File

@ -1119,13 +1119,13 @@ public:
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;
}

View File

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

View File

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

View File

@ -1795,12 +1795,6 @@ public class SessionVariable implements Serializable, Writable {
default:
break;
}
randomInt = random.nextInt(2);
if (randomInt % 2 == 0) {
this.enableFoldConstantByBe = false;
} else {
this.enableFoldConstantByBe = true;
}
switch (Config.pull_request_id % 3) {
case 0:
@ -1838,8 +1832,10 @@ public class SessionVariable implements Serializable, Writable {
if (Config.pull_request_id > 0) {
if (Config.pull_request_id % 2 == 1) {
this.batchSize = 4064;
this.enableFoldConstantByBe = true;
} else {
this.batchSize = 50;
this.enableFoldConstantByBe = false;
}
}
}