diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 484d2ba..f3e96f6 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -3778,5 +3778,64 @@ SELECT STDDEV(COALESCE(a)) FROM t1;
 ERROR HY000: Illegal parameter data type geometry for operation 'std('
 DROP TABLE t1;
 #
+# MDEV-12303 Add Type_handler::Item_xxx_fix_length_and_dec() for CAST classes
+#
+CREATE TABLE t1 (a GEOMETRY);
+SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
+SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
+SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
+SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'decimal_typecast'
+SELECT CAST(POINT(1,1) AS CHAR) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_char'
+SELECT CAST(POINT(1,1) AS TIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_time'
+SELECT CAST(POINT(1,1) AS DATE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_date'
+SELECT CAST(POINT(1,1) AS DATETIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_datetime'
+SELECT CAST(a AS SIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
+SELECT CAST(a AS UNSIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
+SELECT CAST(a AS DOUBLE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
+SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'decimal_typecast'
+SELECT CAST(a AS CHAR) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_char'
+SELECT CAST(a AS TIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_time'
+SELECT CAST(a AS DATE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_date'
+SELECT CAST(a AS DATETIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_datetime'
+SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
+SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
+SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
+SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'decimal_typecast'
+SELECT CAST(COALESCE(a) AS CHAR) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_char'
+SELECT CAST(COALESCE(a) AS TIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_time'
+SELECT CAST(COALESCE(a) AS DATE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_date'
+SELECT CAST(COALESCE(a) AS DATETIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_datetime'
+SELECT LENGTH(CAST(POINT(1,1) AS BINARY)) FROM t1;
+LENGTH(CAST(POINT(1,1) AS BINARY))
+SELECT LENGTH(CAST(a AS BINARY)) FROM t1;
+LENGTH(CAST(a AS BINARY))
+SELECT LENGTH(CAST(COALESCE(a) AS BINARY)) FROM t1;
+LENGTH(CAST(COALESCE(a) AS BINARY))
+DROP TABLE t1;
+#
 # End of 10.3 tests
 #
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 1d86a64..5d45fec 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -1952,6 +1952,69 @@ SELECT STDDEV(COALESCE(a)) FROM t1;
 
 DROP TABLE t1;
 
+--echo #
+--echo # MDEV-12303 Add Type_handler::Item_xxx_fix_length_and_dec() for CAST classes
+--echo #
+
+CREATE TABLE t1 (a GEOMETRY);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS CHAR) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS TIME) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DATE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DATETIME) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS SIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS UNSIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DOUBLE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS CHAR) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS TIME) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DATE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DATETIME) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS CHAR) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS TIME) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DATE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DATETIME) FROM t1;
+
+# CAST from GEOMETRY to BINARY is OK
+SELECT LENGTH(CAST(POINT(1,1) AS BINARY)) FROM t1;
+SELECT LENGTH(CAST(a AS BINARY)) FROM t1;
+SELECT LENGTH(CAST(COALESCE(a) AS BINARY)) FROM t1;
+
+DROP TABLE t1;
 
 --echo #
 --echo # End of 10.3 tests
diff --git a/sql/item_func.h b/sql/item_func.h
index f372ced..26c2a48 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -758,7 +758,7 @@ class Item_func_signed :public Item_int_func
     null_value= args[0]->null_value;
     return value;
   }
-  void fix_length_and_dec()
+  void fix_length_and_dec_generic()
   {
     uint32 char_length= MY_MIN(args[0]->max_char_length(),
                                MY_INT64_NUM_DECIMAL_DIGITS);
@@ -770,6 +770,10 @@ class Item_func_signed :public Item_int_func
     set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
     fix_char_length(char_length);
   }
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
+  }
   virtual void print(String *str, enum_query_type query_type);
   uint decimal_precision() const { return args[0]->decimal_precision(); }
   bool need_parentheses_in_default() { return true; }
@@ -792,6 +796,10 @@ class Item_func_unsigned :public Item_func_signed
     null_value= args[0]->null_value;
     return value;
   }
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
+  }
   virtual void print(String *str, enum_query_type query_type);
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_func_unsigned>(thd, mem_root, this); }
@@ -815,7 +823,11 @@ class Item_decimal_typecast :public Item_func
   my_decimal *val_decimal(my_decimal*);
   enum Item_result result_type () const { return DECIMAL_RESULT; }
   enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
-  void fix_length_and_dec() {}
+  void fix_length_and_dec_generic() {}
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this);
+  }
   const char *func_name() const { return "decimal_typecast"; }
   virtual void print(String *str, enum_query_type query_type);
   bool need_parentheses_in_default() { return true; }
@@ -835,7 +847,11 @@ class Item_double_typecast :public Item_real_func
   }
   double val_real();
   enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
-  void fix_length_and_dec() { maybe_null= 1; }
+  void fix_length_and_dec_generic() { maybe_null= 1; }
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
+  }
   const char *func_name() const { return "double_typecast"; }
   virtual void print(String *str, enum_query_type query_type);
   bool need_parentheses_in_default() { return true; }
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 0a56478..174f8ff 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2502,7 +2502,23 @@ String *Item_char_typecast::val_str(String *str)
 }
 
 
-void Item_char_typecast::fix_length_and_dec()
+void Item_char_typecast::fix_length_and_dec_numeric()
+{
+  fix_length_and_dec_internal(from_cs= cast_cs->mbminlen == 1 ?
+                                       cast_cs :
+                                       &my_charset_latin1);
+}
+
+
+void Item_char_typecast::fix_length_and_dec_str()
+{
+  fix_length_and_dec_internal(from_cs= args[0]->dynamic_result() ?
+                                       0 :
+                                       args[0]->collation.collation);
+}
+
+
+void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs)
 {
   uint32 char_length;
   /* 
@@ -2532,12 +2548,6 @@ void Item_char_typecast::fix_length_and_dec()
 
        Note (TODO): we could use repertoire technique here.
   */
-  from_cs= ((args[0]->result_type() == INT_RESULT || 
-             args[0]->result_type() == DECIMAL_RESULT ||
-             args[0]->result_type() == REAL_RESULT) ?
-            (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
-            args[0]->dynamic_result() ? 0 :
-            args[0]->collation.collation);
   charset_conversion= !from_cs || (cast_cs->mbmaxlen > 1) ||
                       (!my_charset_same(from_cs, cast_cs) &&
                        from_cs != &my_charset_bin &&
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 1014326..6ee5652 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -1037,14 +1037,21 @@ class Item_char_typecast :public Item_str_func
   String *copy(String *src, CHARSET_INFO *cs);
   uint adjusted_length_with_warn(uint length);
   void check_truncation_with_warn(String *src, uint dstlen);
+  void fix_length_and_dec_internal(CHARSET_INFO *fromcs);
 public:
   Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg):
     Item_str_func(thd, a), cast_length(length_arg), cast_cs(cs_arg) {}
   enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
   bool eq(const Item *item, bool binary_cmp) const;
   const char *func_name() const { return "cast_as_char"; }
+  CHARSET_INFO *cast_charset() const { return cast_cs; }
   String *val_str(String *a);
-  void fix_length_and_dec();
+  void fix_length_and_dec_numeric();
+  void fix_length_and_dec_str();
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
+  }
   void print(String *str, enum_query_type query_type);
   bool need_parentheses_in_default() { return true; }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1058,7 +1065,7 @@ class Item_temporal_typecast: public Item_temporal_func
   Item_temporal_typecast(THD *thd, Item *a): Item_temporal_func(thd, a) {}
   virtual const char *cast_type() const = 0;
   void print(String *str, enum_query_type query_type);
-  void fix_length_and_dec()
+  void fix_length_and_dec_generic()
   {
     if (decimals == NOT_FIXED_DEC)
       decimals= args[0]->temporal_precision(field_type());
@@ -1074,6 +1081,10 @@ class Item_date_typecast :public Item_temporal_typecast
   bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
   const char *cast_type() const { return "date"; }
   enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
+  }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_date_typecast>(thd, mem_root, this); }
 };
@@ -1088,6 +1099,10 @@ class Item_time_typecast :public Item_temporal_typecast
   bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
   const char *cast_type() const { return "time"; }
   enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_time_typecast_fix_length_and_dec(this);
+  }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_time_typecast>(thd, mem_root, this); }
 };
@@ -1102,6 +1117,10 @@ class Item_datetime_typecast :public Item_temporal_typecast
   const char *cast_type() const { return "datetime"; }
   enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
   bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
+  void fix_length_and_dec()
+  {
+    args[0]->type_handler()->Item_datetime_typecast_fix_length_and_dec(this);
+  }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_datetime_typecast>(thd, mem_root, this); }
 };
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 7044f7e..76d07f8 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -164,6 +164,22 @@ CHARSET_INFO *Type_handler::charset_for_protocol(const Item *item) const
 }
 
 
+bool
+Type_handler::Item_func_or_sum_illegal_param(const char *funcname) const
+{
+  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+           name().ptr(), funcname);
+  return true;
+}
+
+
+bool
+Type_handler::Item_func_or_sum_illegal_param(const Item_func_or_sum *it) const
+{
+  return Item_func_or_sum_illegal_param(it->func_name());
+}
+
+
 CHARSET_INFO *
 Type_handler_string_result::charset_for_protocol(const Item *item) const
 {
@@ -1445,9 +1461,7 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), "sum");
-  return false;
+  return Item_func_or_sum_illegal_param("sum");
 }
 #endif
 
@@ -1498,9 +1512,7 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), "avg");
-  return false;
+  return Item_func_or_sum_illegal_param("avg");
 }
 #endif
 
@@ -1551,9 +1563,7 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), item->func_name());
-  return false;
+  return Item_func_or_sum_illegal_param(item);
 }
 #endif
 
@@ -2369,9 +2379,7 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_func_round_fix_length_and_dec(Item_func_round *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), item->func_name());
-  return false;
+  return Item_func_or_sum_illegal_param(item);
 }
 #endif
 
@@ -2429,9 +2437,7 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), item->func_name());
-  return true;
+  return Item_func_or_sum_illegal_param(item);
 }
 #endif
 
@@ -2489,9 +2495,7 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), item->func_name());
-  return true;
+  return Item_func_or_sum_illegal_param(item);
 }
 #endif
 
@@ -2549,10 +2553,150 @@ bool Type_handler_string_result::
 bool Type_handler_geometry::
        Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
 {
-  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
-           type_handler_geometry.name().ptr(), item->func_name());
-  return true;
+  return Item_func_or_sum_illegal_param(item);
 }
 #endif
 
+
+/***************************************************************************/
+
+bool Type_handler::
+       Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
+{
+  item->fix_length_and_dec_str();
+  return false;
+}
+
+
+bool Type_handler_numeric::
+       Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
+{
+  item->fix_length_and_dec_numeric();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+}
+
+
+bool Type_handler::
+       Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item)
+                                                 const
+{
+  item->fix_length_and_dec_generic();
+  return false;
+
+}
+
+
+#ifdef HAVE_SPATIAL
+
+bool Type_handler_geometry::
+       Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+  return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+       Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+  return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+       Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const
+{
+  return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+       Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
+{
+  return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+       Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
+{
+  if (item->cast_charset() != &my_charset_bin)
+    return Item_func_or_sum_illegal_param(item); // CAST(geom AS CHAR)
+  item->fix_length_and_dec_str();
+  return false; // CAST(geom AS BINARY)
+}
+
+
+bool Type_handler_geometry::
+       Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
+{
+  return Item_func_or_sum_illegal_param(item);
+}
+
+
+
+bool Type_handler_geometry::
+       Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const
+{
+  return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+       Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item)
+                                                 const
+{
+  return Item_func_or_sum_illegal_param(item);
+
+}
+
+#endif /* HAVE_SPATIAL */
+
 /***************************************************************************/
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 3ac9324..52b634c 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -27,6 +27,7 @@
 class Field;
 class Item;
 class Item_cache;
+class Item_func_or_sum;
 class Item_sum_hybrid;
 class Item_sum_sum;
 class Item_sum_avg;
@@ -42,6 +43,14 @@ class Item_func_round;
 class Item_func_int_val;
 class Item_func_abs;
 class Item_func_neg;
+class Item_func_signed;
+class Item_func_unsigned;
+class Item_double_typecast;
+class Item_decimal_typecast;
+class Item_char_typecast;
+class Item_time_typecast;
+class Item_date_typecast;
+class Item_datetime_typecast;
 class cmp_item;
 class in_vector;
 class Type_std_attributes;
@@ -273,6 +282,10 @@ class Type_handler
                               bool maybe_null, bool null_value,
                               bool unsigned_flag,
                               longlong value) const;
+  bool
+  Item_func_or_sum_illegal_param(const char *name) const;
+  bool
+  Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
 public:
   static const Type_handler *string_type_handler(uint max_octet_length);
   static const Type_handler *get_handler_by_field_type(enum_field_types type);
@@ -467,6 +480,23 @@ class Type_handler
 
   virtual bool
   Item_func_neg_fix_length_and_dec(Item_func_neg *func) const= 0;
+
+  virtual bool
+  Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
+  virtual bool
+  Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
+  virtual bool
+  Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const;
+  virtual bool
+  Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const;
+  virtual bool
+  Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const;
+  virtual bool
+  Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const;
+  virtual bool
+  Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const;
+  virtual bool
+  Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const;
 };
 
 
@@ -637,6 +667,47 @@ class Type_handler_row: public Type_handler
   bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
   bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
   bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+
+  bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
+  bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
+  bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
+  bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
+  bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
+  bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  } 
+  bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
+  bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const
+  {
+    DBUG_ASSERT(0);
+    return true;
+  }
 };
 
 
@@ -662,6 +733,7 @@ class Type_handler_numeric: public Type_handler
                                    Item *target_expr, Item *target_value,
                                    Item_bool_func2 *source,
                                    Item *source_expr, Item *source_const) const;
+  bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const;
 };
 
 
@@ -1348,6 +1420,15 @@ class Type_handler_geometry: public Type_handler_string_result
   bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
   bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
   bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+
+  bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const;
+  bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const;
+  bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const;
+  bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const;
+  bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const;
+  bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const;
+  bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const;
+  bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const;
 };
 
 extern Type_handler_geometry type_handler_geometry;
