mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-15340 Wrong result HOUR(case_expression_with_time_and_datetime)
The problem was that Item_func_hybrid_field_type::get_date() did not convert the result to the correct data type, so MYSQL_TIME::time_type of the get_date() result could be not in sync with field_type(). Changes: 1. Adding two new classes Datetime and Date to store MYSQL_TIMESTAMP_DATETIME and MYSQL_TIMESTAMP_DATE values respectively (in addition to earlier added class Time, for MYSQL_TIMESTAMP_TIME values). 2. Adding Item_func_hybrid_field_type::time_op(). It performs the operation using TIME representation, and always returns a MYSQL_TIME value with time_type=MYSQL_TIMESTAMP_TIME. Implementing time_op() for all affected children classes. 3. Fixing all implementations of date_op() to perform the operation using strictly DATETIME representation. Now they always return a MYSQL_TIME value with time_type=MYSQL_TIMESTAMP_{DATE|DATETIME}, according to the result data type. 4. Removing assignment of ltime.time_type to mysql_timestamp_type() from all val_xxx_from_date_op(), because now date_op() makes sure to return a proper MYSQL_TIME value with a good time_type (and other member) 5. Adding Item_func_hybrid_field_type::val_xxx_from_time_op(). 6. Overriding Type_handler_time_common::Item_func_hybrid_field_type_val_xxx() to call val_xxx_from_time_op() instead of val_xxx_from_date_op(). 7. Modified Item_func::get_arg0_date() to return strictly a TIME value if TIME_TIME_ONLY is passed, or return strictly a DATETIME value otherwise. If args[0] returned a value of a different temporal type, (for example a TIME value when TIME_TIME_ONLY was not passed, or a DATETIME value when TIME_TIME_ONLY was passed), the conversion is automatically applied. Earlier, get_arg0_date() did not guarantee a result in accordance to TIME_TIME_ONLY flag.
This commit is contained in:
@@ -2368,9 +2368,25 @@ Item_func_ifnull::str_op(String *str)
|
||||
bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (!args[0]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
|
||||
return (null_value= false);
|
||||
return (null_value= args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES));
|
||||
for (uint i= 0; i < 2; i++)
|
||||
{
|
||||
Datetime dt(current_thd, args[i], fuzzydate & ~TIME_FUZZY_DATES);
|
||||
if (!(dt.copy_to_mysql_time(ltime, mysql_timestamp_type())))
|
||||
return (null_value= false);
|
||||
}
|
||||
return (null_value= true);
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_ifnull::time_op(MYSQL_TIME *ltime)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
for (uint i= 0; i < 2; i++)
|
||||
{
|
||||
if (!Time(args[i]).copy_to_mysql_time(ltime))
|
||||
return (null_value= false);
|
||||
}
|
||||
return (null_value= true);
|
||||
}
|
||||
|
||||
|
||||
@@ -2850,7 +2866,19 @@ Item_func_nullif::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (!compare())
|
||||
return (null_value= true);
|
||||
return (null_value= args[2]->get_date(ltime, fuzzydate));
|
||||
Datetime dt(current_thd, args[2], fuzzydate);
|
||||
return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_func_nullif::time_op(MYSQL_TIME *ltime)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (!compare())
|
||||
return (null_value= true);
|
||||
return (null_value= Time(args[2]).copy_to_mysql_time(ltime));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2991,7 +3019,18 @@ bool Item_func_case::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
|
||||
Item *item= find_item();
|
||||
if (!item)
|
||||
return (null_value= true);
|
||||
return (null_value= item->get_date_with_conversion(ltime, fuzzydate));
|
||||
Datetime dt(current_thd, item, fuzzydate);
|
||||
return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_case::time_op(MYSQL_TIME *ltime)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Item *item= find_item();
|
||||
if (!item)
|
||||
return (null_value= true);
|
||||
return (null_value= Time(item).copy_to_mysql_time(ltime));
|
||||
}
|
||||
|
||||
|
||||
@@ -3401,7 +3440,20 @@ bool Item_func_coalesce::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
{
|
||||
if (!args[i]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
|
||||
Datetime dt(current_thd, args[i], fuzzydate & ~TIME_FUZZY_DATES);
|
||||
if (!dt.copy_to_mysql_time(ltime, mysql_timestamp_type()))
|
||||
return (null_value= false);
|
||||
}
|
||||
return (null_value= true);
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_coalesce::time_op(MYSQL_TIME *ltime)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
{
|
||||
if (!Time(args[i]).copy_to_mysql_time(ltime))
|
||||
return (null_value= false);
|
||||
}
|
||||
return (null_value= true);
|
||||
|
Reference in New Issue
Block a user