diff options
author | Alexander Barkov <bar@mariadb.org> | 2018-02-19 23:41:01 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2018-02-19 23:41:01 +0400 |
commit | aef530bb6955d8c13a1ff9c5624c74fefa68943c (patch) | |
tree | 091fc40e90d082e79f61d580c58be61a4f4abe47 /sql/item_cmpfunc.cc | |
parent | 5c3d0c6badfa76e3b71bf60d3bcdd06bcd1b96c1 (diff) | |
download | mariadb-git-aef530bb6955d8c13a1ff9c5624c74fefa68943c.tar.gz |
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.
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5846ef094d9..9f30b238660 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -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); |