diff --git a/sql/item_func.cc b/sql/item_func.cc index 23477b1a147..9cd95029509 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2766,7 +2766,7 @@ void Item_func_min_max::fix_length_and_dec() /* - Compare item arguments in the DATETIME context. + Compare item arguments using DATETIME/DATE/TIME representation. DESCRIPTION Compare item arguments as DATETIME values and return the index of the @@ -2779,21 +2779,11 @@ void Item_func_min_max::fix_length_and_dec() 0 Otherwise */ -bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date) { longlong UNINIT_VAR(min_max); DBUG_ASSERT(fixed == 1); - /* - just like ::val_int() method of a string item can be called, - for example, SELECT CONCAT("10", "12") + 1, - ::get_date() can be called for non-temporal values, - for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09")) - - */ - if (Item_func_min_max::cmp_type() != TIME_RESULT) - return Item_func::get_date(ltime, fuzzy_date); - for (uint i=0; i < arg_count ; i++) { longlong res= args[i]->val_temporal_packed(Item_func_min_max::field_type()); @@ -2833,63 +2823,35 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } -String *Item_func_min_max::val_str(String *str) +String *Item_func_min_max::val_str_native(String *str) { - DBUG_ASSERT(fixed == 1); - if (Item_func_min_max::cmp_type() == TIME_RESULT) - return val_string_from_date(str); - switch (Item_func_min_max::result_type()) { - case INT_RESULT: - return val_string_from_int(str); - case DECIMAL_RESULT: - return val_string_from_decimal(str); - case REAL_RESULT: - return val_string_from_real(str); - case STRING_RESULT: + String *UNINIT_VAR(res); + for (uint i=0; i < arg_count ; i++) { - String *UNINIT_VAR(res); - for (uint i=0; i < arg_count ; i++) + if (i == 0) + res=args[i]->val_str(str); + else { - if (i == 0) - res=args[i]->val_str(str); - else + String *res2; + res2= args[i]->val_str(res == str ? &tmp_value : str); + if (res2) { - String *res2; - res2= args[i]->val_str(res == str ? &tmp_value : str); - if (res2) - { - int cmp= sortcmp(res,res2,collation.collation); - if ((cmp_sign < 0 ? cmp : -cmp) < 0) - res=res2; - } + int cmp= sortcmp(res,res2,collation.collation); + if ((cmp_sign < 0 ? cmp : -cmp) < 0) + res=res2; } - if ((null_value= args[i]->null_value)) - return 0; } - res->set_charset(collation.collation); - return res; + if ((null_value= args[i]->null_value)) + return 0; } - case ROW_RESULT: - case TIME_RESULT: - DBUG_ASSERT(0); // This case should never be chosen - return 0; - } - return 0; // Keep compiler happy + res->set_charset(collation.collation); + return res; } -double Item_func_min_max::val_real() +double Item_func_min_max::val_real_native() { - DBUG_ASSERT(fixed == 1); double value=0.0; - if (Item_func_min_max::cmp_type() == TIME_RESULT) - { - MYSQL_TIME ltime; - if (get_date(<ime, 0)) - return 0; - - return TIME_to_double(<ime); - } for (uint i=0; i < arg_count ; i++) { if (i == 0) @@ -2907,18 +2869,10 @@ double Item_func_min_max::val_real() } -longlong Item_func_min_max::val_int() +longlong Item_func_min_max::val_int_native() { DBUG_ASSERT(fixed == 1); longlong value=0; - if (Item_func_min_max::cmp_type() == TIME_RESULT) - { - MYSQL_TIME ltime; - if (get_date(<ime, 0)) - return 0; - - return TIME_to_ulonglong(<ime); - } for (uint i=0; i < arg_count ; i++) { if (i == 0) @@ -2936,19 +2890,11 @@ longlong Item_func_min_max::val_int() } -my_decimal *Item_func_min_max::val_decimal(my_decimal *dec) +my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec) { DBUG_ASSERT(fixed == 1); my_decimal tmp_buf, *tmp, *UNINIT_VAR(res); - if (Item_func_min_max::cmp_type() == TIME_RESULT) - { - MYSQL_TIME ltime; - if (get_date(<ime, 0)) - return 0; - - return date2my_decimal(<ime, dec); - } for (uint i=0; i < arg_count ; i++) { if (i == 0) diff --git a/sql/item_func.h b/sql/item_func.h index fcb03e914ac..368054222aa 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1284,11 +1284,42 @@ public: Item_func_min_max(THD *thd, List &list, int cmp_sign_arg): Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg) {} - double val_real(); - longlong val_int(); - String *val_str(String *); - my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + String *val_str_native(String *str); + double val_real_native(); + longlong val_int_native(); + my_decimal *val_decimal_native(my_decimal *); + bool get_date_native(MYSQL_TIME *res, ulonglong fuzzydate); + + double val_real() + { + DBUG_ASSERT(fixed); + return Item_func_min_max::type_handler()-> + Item_func_min_max_val_real(this); + } + longlong val_int() + { + DBUG_ASSERT(fixed); + return Item_func_min_max::type_handler()-> + Item_func_min_max_val_int(this); + } + String *val_str(String *str) + { + DBUG_ASSERT(fixed); + return Item_func_min_max::type_handler()-> + Item_func_min_max_val_str(this, str); + } + my_decimal *val_decimal(my_decimal *dec) + { + DBUG_ASSERT(fixed); + return Item_func_min_max::type_handler()-> + Item_func_min_max_val_decimal(this, dec); + } + bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) + { + DBUG_ASSERT(fixed); + return Item_func_min_max::type_handler()-> + Item_func_min_max_get_date(this, res, fuzzy_date); + } void fix_length_and_dec(); }; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index afc2a96c97f..6f20a6c17b6 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1780,3 +1780,143 @@ bool Type_handler_row::Item_func_in_fix_comparator_compatible_types(THD *thd, } /***************************************************************************/ + +String *Type_handler_string_result:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return func->val_str_native(str); +} + + +String *Type_handler_temporal_result:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return func->val_string_from_date(str); +} + + +String *Type_handler_int_result:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return func->val_string_from_int(str); +} + + +String *Type_handler_decimal_result:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return func->val_string_from_decimal(str); +} + + +String *Type_handler_real_result:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return func->val_string_from_real(str); +} + + +double Type_handler_string_result:: + Item_func_min_max_val_real(Item_func_min_max *func) const +{ + return func->val_real_native(); +} + + +double Type_handler_temporal_result:: + Item_func_min_max_val_real(Item_func_min_max *func) const +{ + MYSQL_TIME ltime; + if (func->get_date(<ime, 0)) + return 0; + return TIME_to_double(<ime); +} + + +double Type_handler_numeric:: + Item_func_min_max_val_real(Item_func_min_max *func) const +{ + return func->val_real_native(); +} + + +longlong Type_handler_string_result:: + Item_func_min_max_val_int(Item_func_min_max *func) const +{ + return func->val_int_native(); +} + + +longlong Type_handler_temporal_result:: + Item_func_min_max_val_int(Item_func_min_max *func) const +{ + MYSQL_TIME ltime; + if (func->get_date(<ime, 0)) + return 0; + return TIME_to_ulonglong(<ime); +} + + +longlong Type_handler_numeric:: + Item_func_min_max_val_int(Item_func_min_max *func) const +{ + return func->val_int_native(); +} + + +my_decimal *Type_handler_string_result:: + Item_func_min_max_val_decimal(Item_func_min_max *func, + my_decimal *dec) const +{ + return func->val_decimal_native(dec); +} + + +my_decimal *Type_handler_numeric:: + Item_func_min_max_val_decimal(Item_func_min_max *func, + my_decimal *dec) const +{ + return func->val_decimal_native(dec); +} + + +my_decimal *Type_handler_temporal_result:: + Item_func_min_max_val_decimal(Item_func_min_max *func, + my_decimal *dec) const +{ + MYSQL_TIME ltime; + if (func->get_date(<ime, 0)) + return 0; + return date2my_decimal(<ime, dec); +} + + +bool Type_handler_string_result:: + Item_func_min_max_get_date(Item_func_min_max *func, + MYSQL_TIME *ltime, ulonglong fuzzydate) const +{ + /* + just like ::val_int() method of a string item can be called, + for example, SELECT CONCAT("10", "12") + 1, + ::get_date() can be called for non-temporal values, + for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09")) + */ + return func->Item::get_date(ltime, fuzzydate); +} + + +bool Type_handler_numeric:: + Item_func_min_max_get_date(Item_func_min_max *func, + MYSQL_TIME *ltime, ulonglong fuzzydate) const +{ + return func->Item::get_date(ltime, fuzzydate); +} + + +bool Type_handler_temporal_result:: + Item_func_min_max_get_date(Item_func_min_max *func, + MYSQL_TIME *ltime, ulonglong fuzzydate) const +{ + return func->get_date_native(ltime, fuzzydate); +} + diff --git a/sql/sql_type.h b/sql/sql_type.h index c778c0feba2..b9c2dd096dd 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -30,6 +30,7 @@ class Item_cache; class Item_sum_hybrid; class Item_func_hex; class Item_hybrid_func; +class Item_func_min_max; class Item_func_hybrid_field_type; class Item_func_between; class Item_func_in; @@ -371,7 +372,18 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong fuzzydate) const= 0; - + virtual + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const= 0; + virtual + double Item_func_min_max_val_real(Item_func_min_max *) const= 0; + virtual + longlong Item_func_min_max_val_int(Item_func_min_max *) const= 0; + virtual + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const= 0; + virtual + bool Item_func_min_max_get_date(Item_func_min_max*, + MYSQL_TIME *, ulonglong fuzzydate) const= 0; virtual longlong Item_func_between_val_int(Item_func_between *func) const= 0; @@ -494,6 +506,33 @@ public: return true; } + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const + { + DBUG_ASSERT(0); + return NULL; + } + double Item_func_min_max_val_real(Item_func_min_max *) const + { + DBUG_ASSERT(0); + return 0; + } + longlong Item_func_min_max_val_int(Item_func_min_max *) const + { + DBUG_ASSERT(0); + return 0; + } + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const + { + DBUG_ASSERT(0); + return NULL; + } + bool Item_func_min_max_get_date(Item_func_min_max*, + MYSQL_TIME *, ulonglong fuzzydate) const + { + DBUG_ASSERT(0); + return true; + } longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const; @@ -512,6 +551,12 @@ protected: const Type_handler *handler) const; public: + 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(Item_func_min_max*, + MYSQL_TIME *, ulonglong fuzzydate) const; virtual ~Type_handler_numeric() { } }; @@ -549,6 +594,7 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong fuzzydate) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; @@ -591,6 +637,7 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong fuzzydate) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; @@ -631,6 +678,7 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong fuzzydate) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; @@ -667,6 +715,13 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong 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(Item_func_min_max*, + MYSQL_TIME *, ulonglong fuzzydate) const; longlong Item_func_between_val_int(Item_func_between *func) const; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const; @@ -709,6 +764,13 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong 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(Item_func_min_max*, + MYSQL_TIME *, ulonglong fuzzydate) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;