diff --git a/mysql-test/main/func_hybrid_type.result b/mysql-test/main/func_hybrid_type.result index 2c1d03859f7..043f2fab3d2 100644 --- a/mysql-test/main/func_hybrid_type.result +++ b/mysql-test/main/func_hybrid_type.result @@ -3873,5 +3873,75 @@ t1 CREATE TABLE `t1` ( DROP TABLE t1; SET sql_mode=DEFAULT; # +# MDEV-17318 CAST(LEAST(zero_date,non_zero_date) AS numeric_data_type) returns a wrong result +# +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +SELECT +LEAST('0000-00-00',DATE'2001-01-01') AS c0, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +c0 string date datetime time dc dbl sint uint +NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +CREATE TABLE t1 AS SELECT +LEAST('0000-00-00',DATE'2001-01-01') AS c0, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +SELECT * FROM t1; +c0 string date datetime time dc dbl sint uint +NULL NULL NULL NULL NULL NULL NULL NULL NULL +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c0` date DEFAULT NULL, + `string` varchar(10) DEFAULT NULL, + `date` date DEFAULT NULL, + `datetime` datetime DEFAULT NULL, + `time` time DEFAULT NULL, + `dc` decimal(10,0) DEFAULT NULL, + `dbl` double DEFAULT NULL, + `sint` bigint(10) DEFAULT NULL, + `uint` bigint(20) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-17330 Wrong result for 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') +# +SELECT 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') AS c; +c +-100000 +# # End of 10.4 tests # diff --git a/mysql-test/main/func_hybrid_type.test b/mysql-test/main/func_hybrid_type.test index a85ffcecf92..6b32f331d34 100644 --- a/mysql-test/main/func_hybrid_type.test +++ b/mysql-test/main/func_hybrid_type.test @@ -682,6 +682,40 @@ SHOW CREATE TABLE t1; DROP TABLE t1; SET sql_mode=DEFAULT; +--echo # +--echo # MDEV-17318 CAST(LEAST(zero_date,non_zero_date) AS numeric_data_type) returns a wrong result +--echo # +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +SELECT + LEAST('0000-00-00',DATE'2001-01-01') AS c0, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +CREATE TABLE t1 AS SELECT + LEAST('0000-00-00',DATE'2001-01-01') AS c0, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET sql_mode=DEFAULT; + +--echo # +--echo # MDEV-17330 Wrong result for 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') +--echo # +SELECT 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') AS c; + --echo # --echo # End of 10.4 tests diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 04882f557e9..e051b9efc4c 100644 --- a/sql/sql_type.cc +++ b/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:: diff --git a/sql/sql_type.h b/sql/sql_type.h index 0e8a433ac74..e0d3aa5a1f3 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3308,10 +3308,6 @@ public: Item_func_hybrid_field_type *, MYSQL_TIME *, date_mode_t fuzzydate) const; - double Item_func_min_max_val_real(Item_func_min_max *) const; - longlong Item_func_min_max_val_int(Item_func_min_max *) const; - my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, - my_decimal *) const; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const; bool Item_func_between_fix_length_and_dec(Item_func_between *func) const; @@ -3939,6 +3935,10 @@ public: MYSQL_TIME *, date_mode_t fuzzydate) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, MYSQL_TIME *, date_mode_t fuzzydate) const; longlong Item_func_between_val_int(Item_func_between *func) const; @@ -4056,6 +4056,10 @@ public: String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -4152,6 +4156,10 @@ public: String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -4252,6 +4260,10 @@ public: String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *,