diff --git a/sql/item_func.cc b/sql/item_func.cc
index 17cf8642ce52f1242dccb6069fb3484cf8a55aee..879c0b36bdd48345a07dc6d183143c98a37547e5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2873,10 +2873,10 @@ void Item_func_match::init_search(bool no_order)
   if (key == NO_SUCH_KEY)
   {
     List<Item> fields;
+    fields.push_back(new Item_string(" ",1, cmp_collation.collation));
     for (uint i=1; i < arg_count; i++)
       fields.push_back(args[i]);
-    concat=new Item_func_concat_ws(new Item_string(" ",1,
-                                   cmp_collation.collation), fields);
+    concat=new Item_func_concat_ws(fields);
     /*
       Above function used only to get value and do not need fix_fields for it:
       Item_string - basic constant
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index d78a3ac88a434894d350bee9606740eb70db0339..c51894afde42d08a359d9a9d82b8a03ace469a4a 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -532,7 +532,7 @@ String *Item_func_concat_ws::val_str(String *str)
   uint i;
 
   null_value=0;
-  if (!(sep_str= separator->val_str(&tmp_sep_str)))
+  if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
     goto null;
 
   use_as_buff= &tmp_value;
@@ -541,7 +541,7 @@ String *Item_func_concat_ws::val_str(String *str)
 
   // Skip until non-null argument is found.
   // If not, return the empty string
-  for (i=0; i < arg_count; i++)
+  for (i=1; i < arg_count; i++)
     if ((res= args[i]->val_str(str)))
       break;
   if (i ==  arg_count)
@@ -635,67 +635,25 @@ String *Item_func_concat_ws::val_str(String *str)
   return 0;
 }
 
-void Item_func_concat_ws::split_sum_func(THD *thd, Item **ref_pointer_array,
-					 List<Item> &fields)
-{
-  if (separator->with_sum_func && separator->type() != SUM_FUNC_ITEM)
-    separator->split_sum_func(thd, ref_pointer_array, fields);
-  else if (separator->used_tables() || separator->type() == SUM_FUNC_ITEM)
-  {
-    uint el= fields.elements;
-    Item *new_item= new Item_ref(ref_pointer_array + el, 0, separator->name);
-    fields.push_front(separator);
-    ref_pointer_array[el]= separator;
-    thd->change_item_tree(&separator, new_item);
-  }
-  Item_str_func::split_sum_func(thd, ref_pointer_array, fields);
-}
 
 void Item_func_concat_ws::fix_length_and_dec()
 {
-  collation.set(separator->collation);
-  max_length=separator->max_length*(arg_count-1);
-  for (uint i=0 ; i < arg_count ; i++)
-  {
-    DTCollation tmp(collation.collation, collation.derivation);
+  max_length=0;
+
+  if (agg_arg_collations(collation, args, arg_count))
+    return;
+
+  max_length= arg_count > 1 ? args[0]->max_length * (arg_count - 2) : 0;
+  for (uint i=1 ; i < arg_count ; i++)
     max_length+=args[i]->max_length;
-    if (collation.aggregate(args[i]->collation))
-    {
-      collation.set(tmp); // Restore the previous value
-      my_coll_agg_error(collation, args[i]->collation, func_name());
-      break;
-    }
-  }
+
   if (max_length > MAX_BLOB_WIDTH)
   {
     max_length=MAX_BLOB_WIDTH;
     maybe_null=1;
   }
-  used_tables_cache|=     separator->used_tables();
-  not_null_tables_cache&= separator->not_null_tables();
-  const_item_cache&=	  separator->const_item();
-  with_sum_func=	  with_sum_func || separator->with_sum_func;
-}
-
-void Item_func_concat_ws::update_used_tables()
-{
-  Item_func::update_used_tables();
-  separator->update_used_tables();
-  used_tables_cache|=separator->used_tables();
-  const_item_cache&=separator->const_item();
 }
 
-void Item_func_concat_ws::print(String *str)
-{
-  str->append("concat_ws(", 10);
-  separator->print(str);
-  if (arg_count)
-  {
-    str->append(',');
-    print_args(str, 0);
-  }
-  str->append(')');
-}
 
 String *Item_func_reverse::val_str(String *str)
 {
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 77c1caec9fc6e85dc54207faa48b6428173e8ccd..afe03c31345b3dfca1cb874c7289b5fb39b28bea 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -89,30 +89,12 @@ class Item_func_concat :public Item_str_func
 
 class Item_func_concat_ws :public Item_str_func
 {
-  Item *separator;
   String tmp_value;
-
 public:
-  Item_func_concat_ws(Item *a,List<Item> &list) 
-    :Item_str_func(list),separator(a) {}
+  Item_func_concat_ws(List<Item> &list) :Item_str_func(list) {}
   String *val_str(String *);
   void fix_length_and_dec();
-  void update_used_tables();
-  bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
-  {
-    DBUG_ASSERT(fixed == 0);
-    return (separator->fix_fields(thd, tlist, &separator) ||
-	    separator->check_cols(1) ||
-	    Item_func::fix_fields(thd, tlist, ref));
-  }
-  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
   const char *func_name() const { return "concat_ws"; }
-  bool walk(Item_processor processor, byte *arg)
-  {
-    return separator->walk(processor, arg) ||
-      Item_str_func::walk(processor, arg);
-  }
-  void print(String *str);
 };
 
 class Item_func_reverse :public Item_str_func
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 142f52b87abeee6e4ad740fae0f8604e073682f5..4538cb6e6ac7d60114a2a67933749b2d67d29e86 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2889,7 +2889,7 @@ simple_expr:
 	| CONCAT '(' expr_list ')'
 	  { $$= new Item_func_concat(* $3); }
 	| CONCAT_WS '(' expr ',' expr_list ')'
-	  { $$= new Item_func_concat_ws($3, *$5); }
+	  { $5->push_front($3); $$= new Item_func_concat_ws(*$5); }
 	| CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')'
 	  {
 	    Lex->time_zone_tables_used= &fake_time_zone_tables_list;