diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index acd3d74..f02b66c 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3621,51 +3621,13 @@ String *Item_func_weight_string::val_str(String *str)
 }
 
 
-String *Item_func_hex::val_str_ascii(String *str)
+String *Item_func_hex::val_str_ascii_from_int(String *str, ulonglong num)
 {
-  String *res;
-  DBUG_ASSERT(fixed == 1);
-  if (args[0]->result_type() != STRING_RESULT)
-  {
-    ulonglong dec;
-    char ans[65],*ptr;
-    /* Return hex of unsigned longlong value */
-    if (args[0]->result_type() == REAL_RESULT ||
-        args[0]->result_type() == DECIMAL_RESULT)
-    {
-      double val= args[0]->val_real();
-      if ((val <= (double) LONGLONG_MIN) || 
-          (val >= (double) (ulonglong) ULONGLONG_MAX))
-        dec=  ~(longlong) 0;
-      else
-        dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
-    }
-    else
-      dec= (ulonglong) args[0]->val_int();
-
-    if ((null_value= args[0]->null_value))
-      return 0;
-    
-    if (!(ptr= longlong2str(dec, ans, 16)) ||
-        str->copy(ans,(uint32) (ptr - ans),
-        &my_charset_numeric))
-      return make_empty_result();		// End of memory
-    return str;
-  }
-
-  /* Convert given string to a hex string, character by character */
-  res= args[0]->val_str(str);
-  if (!res || tmp_value.alloc(res->length()*2+1))
-  {
-    null_value=1;
-    return 0;
-  }
-  null_value=0;
-  tmp_value.length(res->length()*2);
-  tmp_value.set_charset(&my_charset_latin1);
-
-  octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length());
-  return &tmp_value;
+  char ans[65], *ptr;
+  if (!(ptr= longlong2str(num, ans, 16)) ||
+      str->copy(ans, (uint32) (ptr - ans), &my_charset_numeric))
+    return make_empty_result();        // End of memory
+  return str;
 }
 
   /** Convert given hex string to a binary string. */
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 25b63eb..9719879 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -913,17 +913,24 @@ class Item_func_conv :public Item_str_func
 
 class Item_func_hex :public Item_str_ascii_func
 {
+protected:
   String tmp_value;
+  String *val_str_ascii_from_int(String *, ulonglong);
+  const Type_handler *m_handler;
 public:
   Item_func_hex(THD *thd, Item *a):
-    Item_str_ascii_func(thd, a) {}
+    Item_str_ascii_func(thd, a), m_handler(NULL) {}
   const char *func_name() const { return "hex"; }
-  String *val_str_ascii(String *);
+  String *val_str_ascii(String *str)
+  {
+    return m_handler->Item_func_hex_val_str_ascii(this, str);
+  }
   void fix_length_and_dec()
   {
     collation.set(default_charset());
     decimals=0;
     fix_char_length(args[0]->max_length * 2);
+    m_handler= args[0]->type_handler();
   }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_func_hex>(thd, mem_root, this); }
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index a80417f..0f85a84 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -640,3 +640,99 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table,
                    metadata & 0x00ff/*pack_length()*/,
                    ((const Field_enum*) target)->typelib, target->charset());
 }
+
+
+/***********************************************************************/
+
+class Item_func_hex_int: public Item_func_hex
+{
+public:
+  String *val_str_ascii(String *str)
+  {
+    ulonglong dec= (ulonglong) args[0]->val_int();
+    if ((null_value= args[0]->null_value))
+      return 0;
+    return val_str_ascii_from_int(str, dec);
+  }
+};
+
+
+class Item_func_hex_real: public Item_func_hex
+{
+public:
+  String *val_str_ascii(String *str)
+  {
+    ulonglong dec;
+    double val= args[0]->val_real();
+    if ((null_value= args[0]->null_value))
+      return 0;
+    if ((val <= (double) LONGLONG_MIN) ||
+        (val >= (double) (ulonglong) ULONGLONG_MAX))
+      dec= ~(longlong) 0;
+    else
+      dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
+    return val_str_ascii_from_int(str, dec);
+  }
+};
+
+
+class Item_func_hex_str: public Item_func_hex
+{
+public:
+  String *val_str_ascii(String *str)
+  {
+    /* Convert given string to a hex string, character by character */
+    String *res= args[0]->val_str(str);
+    if ((null_value= (!res || tmp_value.alloc(res->length() * 2 + 1))))
+      return 0;
+    tmp_value.length(res->length() * 2);
+    tmp_value.set_charset(&my_charset_latin1);
+    octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length());
+    return &tmp_value;
+  }
+};
+
+
+String *
+Type_handler_real_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                                      String *str) const
+{
+  return static_cast<Item_func_hex_real*>(item)->
+    Item_func_hex_real::val_str_ascii(str);
+}
+
+
+String *
+Type_handler_decimal_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                                         String *str) const
+{
+  return static_cast<Item_func_hex_real*>(item)->
+    Item_func_hex_real::val_str_ascii(str);
+}
+
+
+String *
+Type_handler_int_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                                     String *str) const
+{
+  return static_cast<Item_func_hex_int*>(item)->
+    Item_func_hex_int::val_str_ascii(str);
+}
+
+
+String *
+Type_handler_temporal_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                                          String *str) const
+{
+  return static_cast<Item_func_hex_str*>(item)->
+    Item_func_hex_str::val_str_ascii(str);
+}
+
+
+String *
+Type_handler_string_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                                        String *str) const
+{
+  return static_cast<Item_func_hex_str*>(item)->
+    Item_func_hex_str::val_str_ascii(str);
+}
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 4b05a46..511a0fe 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -25,6 +25,7 @@
 
 class Field;
 class Item;
+class Item_func_hex;
 class Type_std_attributes;
 class Sort_param;
 struct TABLE;
@@ -92,6 +93,9 @@ class Type_handler
   virtual void sortlength(THD *thd,
                           const Type_std_attributes *item,
                           SORT_FIELD_ATTR *attr) const= 0;
+
+  virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                              String *str) const= 0;
 };
 
 
@@ -108,6 +112,8 @@ class Type_handler_real_result: public Type_handler
   void sortlength(THD *thd,
                   const Type_std_attributes *item,
                   SORT_FIELD_ATTR *attr) const;
+  String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                      String *str) const;
 };
 
 
@@ -123,6 +129,8 @@ class Type_handler_decimal_result: public Type_handler
   void sortlength(THD *thd,
                   const Type_std_attributes *item,
                   SORT_FIELD_ATTR *attr) const;
+  String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                      String *str) const;
 };
 
 
@@ -138,6 +146,8 @@ class Type_handler_int_result: public Type_handler
   void sortlength(THD *thd,
                   const Type_std_attributes *item,
                   SORT_FIELD_ATTR *attr) const;
+  String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                      String *str) const;
 };
 
 
@@ -152,6 +162,8 @@ class Type_handler_temporal_result: public Type_handler
   void sortlength(THD *thd,
                   const Type_std_attributes *item,
                   SORT_FIELD_ATTR *attr) const;
+  String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                      String *str) const;
 };
 
 
@@ -169,6 +181,8 @@ class Type_handler_string_result: public Type_handler
   void sortlength(THD *thd,
                   const Type_std_attributes *item,
                   SORT_FIELD_ATTR *attr) const;
+  String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+                                      String *str) const;
 };
 
 
