1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

MDEV-17318 CAST(LEAST(zero_date,non_zero_date) AS numeric_data_type) returns a wrong result

Also fixes:
MDEV-17330 Wrong result for 0 + LEAST(TIME'-10:00:00',TIME'10:00:00')

Problems:

1. These methods did not take into account the current session date flags
and passed date_mode_t(0) to func->get_date():

Type_handler_temporal_result::Item_func_min_max_val_real
Type_handler_temporal_result::Item_func_min_max_val_int
Type_handler_temporal_result::Item_func_min_max_val_decimal

Fixing to pass sql_mode_for_dates(thd) instead of date_mode_t(0).
Note, sql_mode_for_dates(thd) is only needed for DATE/DATETIME
data types. It is not needed for TIME.
So splitting value methods Type_handler_temporal_result::Item_func_min_max_xxx
into individual implementations for
Type_handler_{time|date|datetime|timestamp}_common
and, instead of calling get_date(), reusing inside classes
Time(), Date(), Datetime() and their methods to_longlong().
sql_mode_for_dates(thd) is automatically passed to get_date()
inside Date() and Datetime() constructors.

The switch to classes also fixed the problem reported in MDEV-17330.
Type_handler_temporal_result::Item_func_min_max_val_int() used to
call TIME_to_ulonglong(), which was not correct for TIME.
Changing the code to use Time().to_longlong() solved this.

2. Type_handler_temporal_result::Item_func_min_max_get_date
also did not take into account the current session
date flags in case of conversion from DATE/DATETIME to time
and passed date_mode_t(0) to get_date_native().
Fixing to pass sql_mode_for_dates(thd) in case of conversion
from DATE/DATETIME to TIME.
This commit is contained in:
Alexander Barkov
2018-09-30 17:24:19 +04:00
parent 23740441d8
commit f79bab3ae6
4 changed files with 204 additions and 20 deletions

View File

@ -4639,13 +4639,30 @@ double Type_handler_string_result::
}
double Type_handler_temporal_result::
double Type_handler_time_common::
Item_func_min_max_val_real(Item_func_min_max *func) const
{
MYSQL_TIME ltime;
if (func->get_date(current_thd, &ltime, date_mode_t(0)))
return 0;
return TIME_to_double(&ltime);
return Time(current_thd, func).to_double();
}
double Type_handler_date_common::
Item_func_min_max_val_real(Item_func_min_max *func) const
{
return Date(current_thd, func).to_double();
}
double Type_handler_datetime_common::
Item_func_min_max_val_real(Item_func_min_max *func) const
{
return Datetime(current_thd, func).to_double();
}
double Type_handler_timestamp_common::
Item_func_min_max_val_real(Item_func_min_max *func) const
{
return Datetime(current_thd, func).to_double();
}
@ -4663,13 +4680,31 @@ longlong Type_handler_string_result::
}
longlong Type_handler_temporal_result::
longlong Type_handler_time_common::
Item_func_min_max_val_int(Item_func_min_max *func) const
{
MYSQL_TIME ltime;
if (func->get_date(current_thd, &ltime, date_mode_t(0)))
return 0;
return TIME_to_ulonglong(&ltime);
return Time(current_thd, func).to_longlong();
}
longlong Type_handler_date_common::
Item_func_min_max_val_int(Item_func_min_max *func) const
{
return Date(current_thd, func).to_longlong();
}
longlong Type_handler_datetime_common::
Item_func_min_max_val_int(Item_func_min_max *func) const
{
return Datetime(current_thd, func).to_longlong();
}
longlong Type_handler_timestamp_common::
Item_func_min_max_val_int(Item_func_min_max *func) const
{
return Datetime(current_thd, func).to_longlong();
}
@ -4696,14 +4731,35 @@ my_decimal *Type_handler_numeric::
}
my_decimal *Type_handler_temporal_result::
my_decimal *Type_handler_time_common::
Item_func_min_max_val_decimal(Item_func_min_max *func,
my_decimal *dec) const
{
MYSQL_TIME ltime;
if (func->get_date(current_thd, &ltime, date_mode_t(0)))
return 0;
return date2my_decimal(&ltime, dec);
return Time(current_thd, func).to_decimal(dec);
}
my_decimal *Type_handler_date_common::
Item_func_min_max_val_decimal(Item_func_min_max *func,
my_decimal *dec) const
{
return Date(current_thd, func).to_decimal(dec);
}
my_decimal *Type_handler_datetime_common::
Item_func_min_max_val_decimal(Item_func_min_max *func,
my_decimal *dec) const
{
return Datetime(current_thd, func).to_decimal(dec);
}
my_decimal *Type_handler_timestamp_common::
Item_func_min_max_val_decimal(Item_func_min_max *func,
my_decimal *dec) const
{
return Datetime(current_thd, func).to_decimal(dec);
}
@ -4733,7 +4789,19 @@ bool Type_handler_temporal_result::
Item_func_min_max_get_date(THD *thd, Item_func_min_max *func,
MYSQL_TIME *ltime, date_mode_t fuzzydate) const
{
return func->get_date_native(thd, ltime, fuzzydate);
/*
- If the caller specified TIME_TIME_ONLY, then it's going to convert
a DATETIME or DATE to TIME. So we pass the default flags for date. This is
exactly the same with what Item_func_min_max_val_{int|real|decimal|str} or
Item_send_datetime() do. We return the value in accordance with the
current session date flags and let the caller further convert it to TIME.
- If the caller did not specify TIME_TIME_ONLY, then return the value
according to the flags supplied by the caller.
*/
return func->get_date_native(thd, ltime,
fuzzydate & TIME_TIME_ONLY ?
sql_mode_for_dates(thd) :
fuzzydate);
}
bool Type_handler_time_common::