1
0
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:
Alexander Barkov
2018-02-19 23:41:01 +04:00
parent 5c3d0c6bad
commit aef530bb69
14 changed files with 527 additions and 119 deletions

View File

@@ -1005,6 +1005,7 @@ public:
String *str_op(String *);
my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool time_op(MYSQL_TIME *ltime);
void fix_length_and_dec()
{
if (!aggregate_for_result(func_name(), args, arg_count, true))
@@ -1077,6 +1078,7 @@ public:
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool time_op(MYSQL_TIME *ltime);
void fix_length_and_dec()
{
Item_func_case_abbreviation2::fix_length_and_dec2(args);
@@ -1110,7 +1112,12 @@ public:
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date_with_conversion_from_item(find_item(), ltime, fuzzydate);
Datetime dt(current_thd, find_item(), fuzzydate);
return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
}
bool time_op(MYSQL_TIME *ltime)
{
return (null_value= Time(find_item()).copy_to_mysql_time(ltime));
}
longlong int_op()
{
@@ -1222,6 +1229,7 @@ public:
arg_count= 2; // See the comment to the constructor
}
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool time_op(MYSQL_TIME *ltime);
double real_op();
longlong int_op();
String *str_op(String *str);
@@ -2111,6 +2119,7 @@ public:
String *str_op(String *);
my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool time_op(MYSQL_TIME *ltime);
bool fix_fields(THD *thd, Item **ref);
table_map not_null_tables() const { return 0; }
const char *func_name() const { return "case"; }