diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ae6c38a874e9daf1ed46c9d0cc63842a6ce53643..3135fe050dcdc79ffe2f93f154d72878b067849a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -6963,13 +6963,16 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
 {
   List<Item> field_list;
   Item *item;
+  List<Item> item_list;
   THD *thd=join->thd;
+  MYSQL_LOCK *save_lock;
   SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
+  select_result *result=join->result;
   DBUG_ENTER("select_describe");
 
   /* Don't log this into the slow query log */
   select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
-  if (join->thd->lex.select == select_lex)
+  if (thd->lex.select == select_lex)
   {
     field_list.push_back(new Item_empty_string("table",NAME_LEN));
     field_list.push_back(new Item_empty_string("type",10));
@@ -6985,24 +6988,22 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
     item->maybe_null=1;
     field_list.push_back(new Item_real("rows",0.0,0,10));
     field_list.push_back(new Item_empty_string("Extra",255));
-    if (send_fields(thd,field_list,1))
+    if (result->send_fields(field_list,1))
       return;
   }
-  char buff[512],*buff_ptr;
-  String tmp(buff,sizeof(buff)),*packet= &thd->packet;
+
   if (message)
   {
-    packet->length(0);
-    net_store_null(packet);
-    net_store_null(packet);
-    net_store_null(packet);
-    net_store_null(packet);
-    net_store_null(packet);
-    net_store_null(packet);
-    net_store_null(packet);
-    net_store_data(packet,message,strlen(message));
-    if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
-      DBUG_VOID_RETURN;
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_empty_string("",0));
+    item_list.push_back(new Item_string(message,strlen(message)));
+    if (result->send_data(item_list))
+      result->send_error(0,NullS);
   }
   else
   {
@@ -7011,69 +7012,70 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
     {
       JOIN_TAB *tab=join->join_tab+i;
       TABLE *table=tab->table;
-      
+      char buff[512],*buff_ptr=buff;
+      char buff1[512], buff2[512], bufff[512];
+      String tmp1(buff1,sizeof(buff1));
+      String tmp2(buff2,sizeof(buff2));
+      item_list.empty();
       if (tab->type == JT_ALL && tab->select && tab->select->quick)
 	tab->type= JT_RANGE;
-      packet->length(0);
-      net_store_data(packet,table->table_name);
-      net_store_data(packet,join_type_str[tab->type]);
-      tmp.length(0);
+      item_list.push_back(new Item_string(table->table_name,strlen(table->table_name)));
+      item_list.push_back(new Item_string(join_type_str[tab->type],strlen(join_type_str[tab->type])));
+      tmp1.length(0); tmp2.length(0);
       key_map bits;
       uint j;
       for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
       {
 	if (bits & 1)
 	{
-	  if (tmp.length())
-	    tmp.append(',');
-	  tmp.append(table->key_info[j].name);
+	  if (tmp1.length())
+	    tmp1.append(',');
+	  tmp1.append(table->key_info[j].name);
 	}
       }
-      if (tmp.length())
-	net_store_data(packet,tmp.ptr(),tmp.length());
+      if (tmp1.length())
+	item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length()));
       else
-	net_store_null(packet);
+	item_list.push_back(new Item_null());
       if (tab->ref.key_parts)
       {
-	net_store_data(packet,table->key_info[tab->ref.key].name);
-	net_store_data(packet,(uint32) tab->ref.key_length);
-	tmp.length(0);
+	item_list.push_back(new Item_string(table->key_info[tab->ref.key].name,strlen(table->key_info[tab->ref.key].name)));
+	item_list.push_back(new Item_int((int) tab->ref.key_length));
 	for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
 	{
-	  if (tmp.length())
-	    tmp.append(',');
-	  tmp.append((*ref)->name());
+	  if (tmp2.length())
+	    tmp2.append(',');
+	  tmp2.append((*ref)->name());
 	}
-	net_store_data(packet,tmp.ptr(),tmp.length());
+	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length()));
       }
       else if (tab->type == JT_NEXT)
       {
-	net_store_data(packet,table->key_info[tab->index].name);
-	net_store_data(packet,(uint32) table->key_info[tab->index].key_length);
-	net_store_null(packet);
+	item_list.push_back(new Item_string(table->key_info[tab->index].name,strlen(table->key_info[tab->index].name)));
+	item_list.push_back(new Item_int((int) table->key_info[tab->index].key_length));
+	item_list.push_back(new Item_null());
       }
       else if (tab->select && tab->select->quick)
       {
-	net_store_data(packet,table->key_info[tab->select->quick->index].name);;
-	net_store_data(packet,(uint32) tab->select->quick->max_used_key_length);
-	net_store_null(packet);
+	item_list.push_back(new Item_string(table->key_info[tab->select->quick->index].name,strlen(table->key_info[tab->select->quick->index].name)));
+	item_list.push_back(new Item_int((int) tab->select->quick->max_used_key_length));
+	item_list.push_back(new Item_null());
       }
       else
       {
-	net_store_null(packet);
-	net_store_null(packet);
-	net_store_null(packet);
+	item_list.push_back(new Item_null());
+	item_list.push_back(new Item_null());
+	item_list.push_back(new Item_null());
       }
-      sprintf(buff,"%.0f",join->best_positions[i].records_read);
-      net_store_data(packet,buff);
+      sprintf(bufff,"%.0f",join->best_positions[i].records_read);
+      item_list.push_back(new Item_string(bufff,strlen(bufff)));
       my_bool key_read=table->key_read;
       if (tab->type == JT_NEXT &&
 	  ((table->used_keys & ((key_map) 1 << tab->index))))
 	key_read=1;
       
-      buff_ptr=buff;
       if (tab->info)
-	net_store_data(packet,tab->info);
+	item_list.push_back(new Item_string(tab->info,strlen(tab->info)));
       else if (tab->select)
       {
 	if (tab->use_quick == 2)
@@ -7127,16 +7129,20 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
 	}
 	buff_ptr=strmov(buff_ptr,"Distinct");
       }
-      net_store_data(packet,buff,(uint) (buff_ptr - buff));
-      if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
-	DBUG_VOID_RETURN;				/* Purecov: Inspected */
-
+      item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff)));
       // For next iteration
       used_tables|=table->map;
+      if (result->send_data(item_list))
+	result->send_error(0,NullS);
     }
   }
   if (!join->thd->lex.select->next)
-    send_eof(&thd->net);
+  {
+    save_lock=thd->lock;
+    thd->lock=(MYSQL_LOCK *)0;
+    result->send_eof();
+    thd->lock=save_lock;
+  }
   DBUG_VOID_RETURN;
 }
 
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 51ad24250227a8380cb5b20c21062f818a1d4a98..60155e0ce8dd44c3d21df1f5ef0f51fff6c7a68c 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -31,10 +31,11 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
   ORDER *order;
   List<Item> item_list;
   TABLE *table;
+  int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0;
+  int res;
   TABLE_LIST result_table_list;
   TMP_TABLE_PARAM tmp_table_param;
   select_union *union_result;
-  int res;
   DBUG_ENTER("mysql_union");
 
   /* Fix tables 'to-be-unioned-from' list to point at opened tables */
@@ -70,33 +71,26 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
     lex_sl=0;
     order=0;
   }
-
-  if (lex->select_lex.options & SELECT_DESCRIBE)
+  
+  if (describe)
   {
-    for (sl= &lex->select_lex; sl; sl=sl->next)
-    {
-      lex->select=sl;
-      thd->offset_limit=sl->offset_limit;
-      thd->select_limit=sl->select_limit+sl->offset_limit;
-      if (thd->select_limit < sl->select_limit)
-	thd->select_limit= HA_POS_ERROR;		// no limit
-      if (thd->select_limit == HA_POS_ERROR)
-	sl->options&= ~OPTION_FOUND_ROWS;
-      res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first,
-		       sl->item_list,
-		       sl->where,
-		       ((sl->braces) ?
-			(ORDER *) sl->order_list.first : (ORDER *) 0),
-		       (ORDER*) sl->group_list.first,
-		       sl->having,
-		       (ORDER*) NULL,
-		       (sl->options | thd->options | SELECT_NO_UNLOCK |
-			SELECT_DESCRIBE),
-		       result);
-    }
-    DBUG_RETURN(0);
+    Item *item;
+    item_list.push_back(new Item_empty_string("table",NAME_LEN));
+    item_list.push_back(new Item_empty_string("type",10));
+    item_list.push_back(item=new Item_empty_string("possible_keys",
+						  NAME_LEN*MAX_KEY));
+    item->maybe_null=1;
+    item_list.push_back(item=new Item_empty_string("key",NAME_LEN));
+    item->maybe_null=1;
+    item_list.push_back(item=new Item_int("key_len",0,3));
+    item->maybe_null=1;
+    item_list.push_back(item=new Item_empty_string("ref",
+						    NAME_LEN*MAX_REF_PARTS));
+    item->maybe_null=1;
+    item_list.push_back(new Item_real("rows",0.0,0,10));
+    item_list.push_back(new Item_empty_string("Extra",255));
   }
-
+  else
   {
     Item *item;
     List_iterator<Item> it(lex->select_lex.item_list);
@@ -113,7 +107,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
   bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
   tmp_table_param.field_count=item_list.elements;
   if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
-			       (ORDER*) 0, !lex->union_option,
+			       (ORDER*) 0, !describe & !lex->union_option,
 			       1, 0,
 			       (lex->select_lex.options | thd->options |
 				TMP_TABLE_ALL_COLUMNS))))
@@ -130,7 +124,9 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
     res= -1;
     goto exit;
   }
-  for (sl= &lex->select_lex; sl; sl=sl->next)
+  union_result->save_time_stamp=!describe;
+
+  for (sl=&lex->select_lex;sl;sl=sl->next)
   {
     thd->offset_limit=sl->offset_limit;
     thd->select_limit=sl->select_limit+sl->offset_limit;
@@ -146,7 +142,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
 		     (ORDER*) sl->group_list.first,
 		     sl->having,
 		     (ORDER*) NULL,
-		     sl->options | thd->options | SELECT_NO_UNLOCK,
+		     sl->options | thd->options | SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0),
 		     union_result);
     if (res)
       goto exit;
@@ -187,6 +183,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
 	if (thd->select_limit == HA_POS_ERROR)
 	  thd->options&= ~OPTION_FOUND_ROWS;
       }
+      if (describe)
+	thd->select_limit= HA_POS_ERROR;		// no limit
       res=mysql_select(thd,&result_table_list,
 		       item_list, NULL, /*ftfunc_list,*/ order,
 		       (ORDER*) NULL, NULL, (ORDER*) NULL,
@@ -222,7 +220,7 @@ select_union::~select_union()
 
 int select_union::prepare(List<Item> &list)
 {
-  if (list.elements != table->fields)
+  if (save_time_stamp && list.elements != table->fields)
   {
     my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
 	       ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));