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:
100
sql/sql_type.cc
100
sql/sql_type.cc
@ -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, <ime, date_mode_t(0)))
|
||||
return 0;
|
||||
return TIME_to_double(<ime);
|
||||
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, <ime, date_mode_t(0)))
|
||||
return 0;
|
||||
return TIME_to_ulonglong(<ime);
|
||||
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, <ime, date_mode_t(0)))
|
||||
return 0;
|
||||
return date2my_decimal(<ime, 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::
|
||||
|
Reference in New Issue
Block a user