diff --git a/sql/item_func.cc b/sql/item_func.cc
index 90bec7b..0b3c246 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2795,7 +2795,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
@@ -2808,21 +2808,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());
@@ -2862,63 +2852,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;
-  }
-  case ROW_RESULT:
-  case TIME_RESULT:
-    DBUG_ASSERT(0);                // This case should never be chosen
-    return 0;
+    if ((null_value= args[i]->null_value))
+      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(&ltime, 0))
-      return 0;
-
-    return TIME_to_double(&ltime);
-  }
   for (uint i=0; i < arg_count ; i++)
   {
     if (i == 0)
@@ -2936,18 +2898,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(&ltime, 0))
-      return 0;
-
-    return TIME_to_ulonglong(&ltime);
-  }
   for (uint i=0; i < arg_count ; i++)
   {
     if (i == 0)
@@ -2965,19 +2919,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(&ltime, 0))
-      return 0;
-
-    return date2my_decimal(&ltime, 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 2ec3297..ce716e0 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1235,11 +1235,42 @@ class Item_func_min_max :public Item_hybrid_func
   Item_func_min_max(THD *thd, List<Item> &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 1e6ed4d..74e8fbe 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -1231,3 +1231,143 @@ longlong Type_handler_decimal_result::
 }
 
 /***************************************************************************/
+
+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(&ltime, 0))
+    return 0;
+  return TIME_to_double(&ltime);
+}
+
+
+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(&ltime, 0))
+    return 0;
+  return TIME_to_ulonglong(&ltime);
+}
+
+
+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(&ltime, 0))
+    return 0;
+  return date2my_decimal(&ltime, 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 9086e60..1b2b2c5 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -28,6 +28,7 @@ class Item;
 class Item_cache;
 class Item_sum_hybrid;
 class Item_func_hex;
+class Item_func_min_max;
 class Item_func_hybrid_field_type;
 class Item_func_between;
 class Type_std_attributes;
@@ -314,7 +315,18 @@ class Type_handler
   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;
 };
@@ -413,6 +425,33 @@ class Type_handler_row: public Type_handler
     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;
 };
 
@@ -427,6 +466,12 @@ class Type_handler_numeric: public Type_handler
                                                   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() { }
 };
 
@@ -461,6 +506,7 @@ class Type_handler_real_result: public Type_handler_numeric
   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;
 };
 
@@ -494,6 +540,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
   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;
 };
 
@@ -527,6 +574,7 @@ class Type_handler_int_result: public Type_handler_numeric
   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;
 };
 
@@ -558,6 +606,13 @@ class Type_handler_temporal_result: public Type_handler
   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;
 };
 
@@ -593,6 +648,13 @@ class Type_handler_string_result: public Type_handler
   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;
 };
 
