mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 01:04:19 +01:00
MDEV-29149 Assertion `!is_valid_datetime() || fraction_remainder(((item->decimals) < (6) ? (item->decimals) : (6))) == 0' failed in Datetime_truncation_not_needed::Datetime_truncation_not_needed
TIME-alike string and numeric arguments to TIMEDIFF() can get additional fractional seconds during the supported TIME range adjustment in get_time(). For example, during TIMEDIFF('839:00:00','00:00:00') evaluation in Item_func_timediff::get_date(), the call for args[0]->get_time() returns MYSQL_TIME '838:59:59.999999'. Item_func_timediff::get_date() did not handle these extra digits and returned a MYSQL_TIME result with fractional digits outside of Item_func_timediff::decimals. This mismatch could further be caught by a DBUG_ASSERT() in various other pieces of the code, leading to a crash. Fix: In case if get_time() returned MYSQL_TIMESTAMP_TIME, let's truncate all extra digits using my_time_trunc(&l_time,decimals). This guarantees that the rest of the code returns a MYSQL_TIME with second_part not conflicting with Item_func_timediff::decimals.
This commit is contained in:
parent
0304dbc327
commit
b697dce8ca
3 changed files with 111 additions and 0 deletions
|
@ -6373,3 +6373,57 @@ NULL
|
||||||
SELECT FROM_UNIXTIME(LEAST(3696610869, NULL));
|
SELECT FROM_UNIXTIME(LEAST(3696610869, NULL));
|
||||||
FROM_UNIXTIME(LEAST(3696610869, NULL))
|
FROM_UNIXTIME(LEAST(3696610869, NULL))
|
||||||
NULL
|
NULL
|
||||||
|
#
|
||||||
|
# Start of 10.5 tests
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# MDEV-29149 Assertion `!is_valid_datetime() || fraction_remainder(((item->decimals) < (6) ? (item->decimals) : (6))) == 0' failed in Datetime_truncation_not_needed::Datetime_truncation_not_needed
|
||||||
|
#
|
||||||
|
SET @@timestamp= UNIX_TIMESTAMP('2022-07-21 23:00:00');
|
||||||
|
SELECT DATE_SUB('2022-07-21 00:00:00', INTERVAL 800 HOUR) AS expected_result;
|
||||||
|
expected_result
|
||||||
|
2022-06-17 16:00:00
|
||||||
|
SELECT
|
||||||
|
IF(1,TIMEDIFF('38:59:59','839:00:00'),CAST('2022-12-12' AS DATE)) AS c1,
|
||||||
|
IF(1,TIMEDIFF('-839:00:00','-38:59:59'),CAST('2022-12-12' AS DATE)) AS c2;
|
||||||
|
c1 c2
|
||||||
|
2022-06-17 16:00:00 2022-06-17 16:00:00
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Truncated incorrect time value: '839:00:00'
|
||||||
|
Warning 1292 Truncated incorrect time value: '-839:00:00'
|
||||||
|
SELECT
|
||||||
|
IF(1,TIMEDIFF(385959,8390000),CAST('2022-12-12' AS DATE)) AS c1,
|
||||||
|
IF(1,TIMEDIFF(-8390000,-385959),CAST('2022-12-12' AS DATE)) AS c2;
|
||||||
|
c1 c2
|
||||||
|
2022-06-17 16:00:00 2022-06-17 16:00:00
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Truncated incorrect time value: '8390000'
|
||||||
|
Warning 1292 Truncated incorrect time value: '-8390000'
|
||||||
|
SELECT
|
||||||
|
TIMEDIFF('38:59:59','839:00:00') AS c1,
|
||||||
|
CAST(TIMEDIFF('38:59:59','839:00:00') AS TIME(6)) AS c2,
|
||||||
|
TIMEDIFF('839:00:00','38:59:59') AS c3,
|
||||||
|
CAST(TIMEDIFF('839:00:00','38:59:59') AS TIME(6)) AS c4;
|
||||||
|
c1 c2 c3 c4
|
||||||
|
-800:00:00 -800:00:00.000000 800:00:00 800:00:00.000000
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Truncated incorrect time value: '839:00:00'
|
||||||
|
Warning 1292 Truncated incorrect time value: '839:00:00'
|
||||||
|
Warning 1292 Truncated incorrect time value: '839:00:00'
|
||||||
|
Warning 1292 Truncated incorrect time value: '839:00:00'
|
||||||
|
SELECT
|
||||||
|
TIMEDIFF(385959,8390000) AS c1,
|
||||||
|
CAST(TIMEDIFF(385959,8390000) AS TIME(6)) AS c2,
|
||||||
|
TIMEDIFF(8390000,385959) AS c3,
|
||||||
|
CAST(TIMEDIFF(8390000,385959) AS TIME(6)) AS c4;
|
||||||
|
c1 c2 c3 c4
|
||||||
|
-800:00:00 -800:00:00.000000 800:00:00 800:00:00.000000
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Truncated incorrect time value: '8390000'
|
||||||
|
Warning 1292 Truncated incorrect time value: '8390000'
|
||||||
|
Warning 1292 Truncated incorrect time value: '8390000'
|
||||||
|
Warning 1292 Truncated incorrect time value: '8390000'
|
||||||
|
SET @@timestamp= DEFAULT;
|
||||||
|
#
|
||||||
|
# End of 10.5 tests
|
||||||
|
#
|
||||||
|
|
|
@ -3213,3 +3213,42 @@ SELECT CONCAT(MAKETIME('01', '01', LEAST( -100, NULL )));
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
SELECT FROM_UNIXTIME(LEAST(3696610869, NULL));
|
SELECT FROM_UNIXTIME(LEAST(3696610869, NULL));
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Start of 10.5 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-29149 Assertion `!is_valid_datetime() || fraction_remainder(((item->decimals) < (6) ? (item->decimals) : (6))) == 0' failed in Datetime_truncation_not_needed::Datetime_truncation_not_needed
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET @@timestamp= UNIX_TIMESTAMP('2022-07-21 23:00:00');
|
||||||
|
|
||||||
|
SELECT DATE_SUB('2022-07-21 00:00:00', INTERVAL 800 HOUR) AS expected_result;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
IF(1,TIMEDIFF('38:59:59','839:00:00'),CAST('2022-12-12' AS DATE)) AS c1,
|
||||||
|
IF(1,TIMEDIFF('-839:00:00','-38:59:59'),CAST('2022-12-12' AS DATE)) AS c2;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
IF(1,TIMEDIFF(385959,8390000),CAST('2022-12-12' AS DATE)) AS c1,
|
||||||
|
IF(1,TIMEDIFF(-8390000,-385959),CAST('2022-12-12' AS DATE)) AS c2;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
TIMEDIFF('38:59:59','839:00:00') AS c1,
|
||||||
|
CAST(TIMEDIFF('38:59:59','839:00:00') AS TIME(6)) AS c2,
|
||||||
|
TIMEDIFF('839:00:00','38:59:59') AS c3,
|
||||||
|
CAST(TIMEDIFF('839:00:00','38:59:59') AS TIME(6)) AS c4;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
TIMEDIFF(385959,8390000) AS c1,
|
||||||
|
CAST(TIMEDIFF(385959,8390000) AS TIME(6)) AS c2,
|
||||||
|
TIMEDIFF(8390000,385959) AS c3,
|
||||||
|
CAST(TIMEDIFF(8390000,385959) AS TIME(6)) AS c4;
|
||||||
|
|
||||||
|
SET @@timestamp= DEFAULT;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.5 tests
|
||||||
|
--echo #
|
||||||
|
|
|
@ -2706,6 +2706,24 @@ bool Item_func_timediff::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy
|
||||||
if (l_time1.neg != l_time2.neg)
|
if (l_time1.neg != l_time2.neg)
|
||||||
l_sign= -l_sign;
|
l_sign= -l_sign;
|
||||||
|
|
||||||
|
if (l_time1.time_type == MYSQL_TIMESTAMP_TIME)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
In case of TIME-alike arguments:
|
||||||
|
TIMEDIFF('38:59:59', '839:00:00')
|
||||||
|
let's truncate extra fractional seconds that might appear if the argument
|
||||||
|
values were out of the supported TIME range. For example, args[n]->get_time()
|
||||||
|
for the string literal '839:00:00' returns TIME'838:59:59.999999'.
|
||||||
|
The fractional part must be truncated according to this->decimals,
|
||||||
|
to avoid returning more fractional seconds than it was detected
|
||||||
|
during this->fix_length_and_dec().
|
||||||
|
Note, the thd rounding mode should not be important here, as we're removing
|
||||||
|
redundant digits from the maximum possible value: '838:59:59.999999'.
|
||||||
|
*/
|
||||||
|
my_time_trunc(&l_time1, decimals);
|
||||||
|
my_time_trunc(&l_time2, decimals);
|
||||||
|
}
|
||||||
|
|
||||||
if (calc_time_diff(&l_time1, &l_time2, l_sign, &l_time3, fuzzydate))
|
if (calc_time_diff(&l_time1, &l_time2, l_sign, &l_time3, fuzzydate))
|
||||||
return (null_value= 1);
|
return (null_value= 1);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue