mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +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