List:Commits« Previous MessageNext Message »
From:holyfoot Date:January 4 2006 10:20am
Subject:bk commit into 5.1 tree (holyfoot:1.1988)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of hf. When hf does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1988 06/01/04 14:20:28 holyfoot@deer.(none) +46 -0
  Big patch to make embedded-server working in 5.x
  Now it supports queries returning several results
  (particularly important with the SP)

  mysql-test/t/subselect_notembedded.test
    1.1 06/01/04 14:18:56 holyfoot@stripped +8 -0

  mysql-test/t/subselect_notembedded.test
    1.0 06/01/04 14:18:56 holyfoot@stripped +0 -0
    BitKeeper file /home/hf/work/5.1.emb/mysql-test/t/subselect_notembedded.test

  mysql-test/t/sp_notembedded.test
    1.1 06/01/04 14:18:55 holyfoot@stripped +261 -0

  mysql-test/t/innodb_notembedded.test
    1.1 06/01/04 14:18:55 holyfoot@stripped +36 -0

  mysql-test/t/ctype_cp932_notembedded.test
    1.1 06/01/04 14:18:55 holyfoot@stripped +32 -0

  mysql-test/t/sp_notembedded.test
    1.0 06/01/04 14:18:55 holyfoot@stripped +0 -0
    BitKeeper file /home/hf/work/5.1.emb/mysql-test/t/sp_notembedded.test

  mysql-test/t/innodb_notembedded.test
    1.0 06/01/04 14:18:55 holyfoot@stripped +0 -0
    BitKeeper file /home/hf/work/5.1.emb/mysql-test/t/innodb_notembedded.test

  mysql-test/t/ctype_cp932_notembedded.test
    1.0 06/01/04 14:18:55 holyfoot@stripped +0 -0
    BitKeeper file /home/hf/work/5.1.emb/mysql-test/t/ctype_cp932_notembedded.test

  sql/sql_prepare.cc
    1.158 06/01/04 14:18:54 holyfoot@stripped +9 -2
    embedded-server related fix

  sql/sql_parse.cc
    1.501 06/01/04 14:18:54 holyfoot@stripped +0 -31
    embedded-server related fix

  sql/sql_cursor.cc
    1.5 06/01/04 14:18:54 holyfoot@stripped +1 -0
    embedded-server related fix

  sql/sql_class.h
    1.281 06/01/04 14:18:54 holyfoot@stripped +10 -2
    embedded-server related fix

  sql/sql_class.cc
    1.228 06/01/04 14:18:54 holyfoot@stripped +3 -3
    embedded-server related fix

  sql/protocol.h
    1.32 06/01/04 14:18:54 holyfoot@stripped +9 -0
    embedded-server related fix

  sql/protocol.cc
    1.112 06/01/04 14:18:54 holyfoot@stripped +43 -39
    embedded-server related fix

  sql/mysqld.cc
    1.507 06/01/04 14:18:54 holyfoot@stripped +0 -2
    embedded-server related fix

  sql-common/client.c
    1.82 06/01/04 14:18:54 holyfoot@stripped +5 -4
    small fixes

  mysql-test/t/wait_timeout.test
    1.2 06/01/04 14:18:54 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/view.test
    1.130 06/01/04 14:18:54 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/sp.test
    1.169 06/01/04 14:18:54 holyfoot@stripped +6 -95
    test fixed

  mysql-test/t/sp-threads.test
    1.8 06/01/04 14:18:54 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/sp-error.test
    1.101 06/01/04 14:18:54 holyfoot@stripped +0 -22
    test fixed

  mysql-test/t/sp-destruct.test
    1.4 06/01/04 14:18:54 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/skip_grants.test
    1.7 06/01/04 14:18:54 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/read_only.test
    1.2 06/01/04 14:18:54 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/query_cache_notembedded.test
    1.3 06/01/04 14:18:54 holyfoot@stripped +84 -0
    test fixed

  mysql-test/t/query_cache.test
    1.54 06/01/04 14:18:53 holyfoot@stripped +0 -15
    test fixed

  mysql-test/t/mysqltest.test
    1.23 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/mysql_client_test.test
    1.15 06/01/04 14:18:53 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/mysql.test
    1.5 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/innodb.test
    1.123 06/01/04 14:18:53 holyfoot@stripped +0 -26
    test fixed

  mysql-test/t/init_connect.test
    1.6 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/handler.test
    1.26 06/01/04 14:18:53 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/flush_table.test
    1.11 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/federated_transactions.test
    1.4 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/federated_bug_13118.test
    1.2 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/federated_archive.test
    1.4 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/federated.test
    1.20 06/01/04 14:18:53 holyfoot@stripped +2 -0
    test fixed

  mysql-test/t/delayed.test
    1.12 06/01/04 14:18:53 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/compress.test
    1.4 06/01/04 14:18:53 holyfoot@stripped +3 -0
    test fixed

  mysql-test/t/binlog_stm_ctype_cp932.test
    1.2 06/01/04 14:18:53 holyfoot@stripped +1 -0
    test fixed

  mysql-test/t/binlog_stm_blackhole.test
    1.2 06/01/04 14:18:53 holyfoot@stripped +1 -0
    test fixed

  mysql-test/t/binlog_stm_binlog.test
    1.2 06/01/04 14:18:53 holyfoot@stripped +1 -0
    test fixed

  mysql-test/t/backup.test
    1.17 06/01/04 14:18:53 holyfoot@stripped +3 -0
    test fixed

  libmysqld/libmysqld.c
    1.67 06/01/04 14:18:53 holyfoot@stripped +12 -2
    small fixes

  libmysqld/lib_sql.cc
    1.108 06/01/04 14:18:53 holyfoot@stripped +366 -145
    multiple-result support added

  libmysqld/embedded_priv.h
    1.13 06/01/04 14:18:53 holyfoot@stripped +14 -7
    embedded_query_result struct implemented

  libmysqld/emb_qcache.cc
    1.8 06/01/04 14:18:53 holyfoot@stripped +69 -60
    multiple-result support added

  libmysql/libmysql.c
    1.231 06/01/04 14:18:53 holyfoot@stripped +6 -6
    embedded-server related fixes

  include/mysql.h
    1.155 06/01/04 14:18:53 holyfoot@stripped +6 -3
    embedded_query_result structure added

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	holyfoot
# Host:	deer.(none)
# Root:	/home/hf/work/5.1.emb

--- 1.154/include/mysql.h	Mon Dec  5 23:47:00 2005
+++ 1.155/include/mysql.h	Wed Jan  4 14:18:53 2006
@@ -130,14 +130,14 @@
 
 #include "my_alloc.h"
 
+typedef struct embedded_query_result EMBEDDED_QUERY_RESULT;
 typedef struct st_mysql_data {
   my_ulonglong rows;
   unsigned int fields;
   MYSQL_ROWS *data;
   MEM_ROOT alloc;
-#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
-  MYSQL_ROWS **prev_ptr;
-#endif
+  /* extra info for embedded library */
+  struct embedded_query_result *embedded_info;
 } MYSQL_DATA;
 
 enum mysql_option 
@@ -287,6 +287,8 @@
     from mysql_stmt_close if close had to cancel result set of this object.
   */
   my_bool *unbuffered_fetch_owner;
+  /* needed for embedded server - no net buffer to store the 'info' */
+  char *info_buffer;
 } MYSQL;
 
 typedef struct st_mysql_res {
@@ -755,6 +757,7 @@
   const char *(*read_statistics)(MYSQL *mysql);
   my_bool (*next_result)(MYSQL *mysql);
   int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
+  int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
 #endif
 } MYSQL_METHODS;
 

--- 1.230/libmysql/libmysql.c	Thu Aug  4 16:25:02 2005
+++ 1.231/libmysql/libmysql.c	Wed Jan  4 14:18:53 2006
@@ -2722,13 +2722,13 @@
     /* Send row request to the server */
     int4store(buff, stmt->stmt_id);
     int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
-    if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
-                             NullS, 0, 1))
+    if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
+                                            buff, sizeof(buff), NullS, 0, 1))
     {
       set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
       return 1;
     }
-    if (cli_read_binary_rows(stmt))
+    if ((*mysql->methods->read_rows_from_cursor)(stmt))
       return 1;
     stmt->server_status= mysql->server_status;
 
@@ -5101,9 +5101,9 @@
   DBUG_ENTER("mysql_autocommit");
   DBUG_PRINT("enter", ("mode : %d", auto_mode));
 
-  if (auto_mode) /* set to true */
-    DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16));
-  DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16));
+  DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
+                                         "set autocommit=1":"set autocommit=0",
+                                         16));
 }
 
 

--- 1.506/sql/mysqld.cc	Thu Dec 22 08:10:52 2005
+++ 1.507/sql/mysqld.cc	Wed Jan  4 14:18:54 2006
@@ -2449,9 +2449,7 @@
     {
       NET *net= &thd->net;
       net->report_error= 1;
-#ifndef EMBEDDED_LIBRARY  /* TODO query cache in embedded library*/
       query_cache_abort(net);
-#endif
       if (!net->last_error[0])			// Return only first message
       {
 	strmake(net->last_error, str, sizeof(net->last_error)-1);

--- 1.111/sql/protocol.cc	Wed Nov 23 02:51:48 2005
+++ 1.112/sql/protocol.cc	Wed Jan  4 14:18:54 2006
@@ -29,6 +29,7 @@
 
 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
 static void write_eof_packet(THD *thd, NET *net);
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
 
 #ifndef EMBEDDED_LIBRARY
 bool Protocol::net_store_data(const char *from, uint length)
@@ -56,10 +57,6 @@
 
 void net_send_error(THD *thd, uint sql_errno, const char *err)
 {
-#ifndef EMBEDDED_LIBRARY 
-  uint length;
-  char buff[MYSQL_ERRMSG_SIZE+2], *pos;
-#endif
   NET *net= &thd->net;
   bool generate_warning= thd->killed != THD::KILL_CONNECTION;
   DBUG_ENTER("net_send_error");
@@ -106,42 +103,8 @@
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err);
   }
 
-#ifdef EMBEDDED_LIBRARY
-  net->last_errno= sql_errno;
-  strmake(net->last_error, err, sizeof(net->last_error)-1);
-  strmov(net->sqlstate, mysql_errno_to_sqlstate(sql_errno));
-#else
-
-  if (net->vio == 0)
-  {
-    if (thd->bootstrap)
-    {
-      /* In bootstrap it's ok to print on stderr */
-      fprintf(stderr,"ERROR: %d  %s\n",sql_errno,err);
-    }
-    DBUG_VOID_RETURN;
-  }
+  net_send_error_packet(thd, sql_errno, err);
 
-  if (net->return_errno)
-  {				// new client code; Add errno before message
-    int2store(buff,sql_errno);
-    pos= buff+2;
-    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
-    {
-      /* The first # is to make the protocol backward compatible */
-      buff[2]= '#';
-      pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
-    }
-    length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
-    err=buff;
-  }
-  else
-  {
-    length=(uint) strlen(err);
-    set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
-  }
-  VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
-#endif  /* EMBEDDED_LIBRARY*/
   thd->is_fatal_error=0;			// Error message is given
   thd->net.report_error= 0;
 
@@ -428,6 +391,47 @@
 {
   NET *net= &thd->net;
   return my_net_write(net, eof_buff, 1) || net_flush(net);
+}
+
+
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+{
+  NET *net= &thd->net;
+  uint length;
+  char buff[MYSQL_ERRMSG_SIZE+2], *pos;
+
+  DBUG_ENTER("send_error_packet");
+
+  if (net->vio == 0)
+  {
+    if (thd->bootstrap)
+    {
+      /* In bootstrap it's ok to print on stderr */
+      fprintf(stderr,"ERROR: %d  %s\n",sql_errno,err);
+    }
+    DBUG_VOID_RETURN;
+  }
+
+  if (net->return_errno)
+  {				// new client code; Add errno before message
+    int2store(buff,sql_errno);
+    pos= buff+2;
+    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+    {
+      /* The first # is to make the protocol backward compatible */
+      buff[2]= '#';
+      pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
+    }
+    length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
+    err=buff;
+  }
+  else
+  {
+    length=(uint) strlen(err);
+    set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+  }
+  VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
+  DBUG_VOID_RETURN;
 }
 
 #endif /* EMBEDDED_LIBRARY */

--- 1.227/sql/sql_class.cc	Thu Dec 22 08:10:53 2005
+++ 1.228/sql/sql_class.cc	Wed Jan  4 14:18:54 2006
@@ -951,7 +951,9 @@
   thd->sent_row_count++;
   if (!thd->vio_ok())
     DBUG_RETURN(0);
-  if (!thd->net.report_error)
+  if (thd->net.report_error)
+    protocol->remove_last_row();
+  else
     DBUG_RETURN(protocol->write());
   DBUG_RETURN(1);
 }
@@ -1983,10 +1985,8 @@
   cuted_fields= 0;
   transaction.savepoints= 0;
 
-#ifndef EMBEDDED_LIBRARY
   /* Surpress OK packets in case if we will execute statements */
   net.no_send_ok= TRUE;
-#endif
 }
 
 

--- 1.280/sql/sql_class.h	Thu Dec 22 08:10:55 2005
+++ 1.281/sql/sql_class.h	Wed Jan  4 14:18:54 2006
@@ -801,13 +801,16 @@
 
 #ifdef EMBEDDED_LIBRARY
   struct st_mysql  *mysql;
-  struct st_mysql_data *data;
   unsigned long	 client_stmt_id;
   unsigned long  client_param_count;
   struct st_mysql_bind *client_params;
   char *extra_data;
   ulong extra_length;
-  String query_rest;
+  struct st_mysql_data *cur_data;
+  struct st_mysql_data *first_data;
+  struct st_mysql_data **data_tail;
+  void clear_data_list();
+  struct st_mysql_data *alloc_new_dataset();
 #endif
   NET	  net;				// client connection descriptor
   MEM_ROOT warn_root;			// For warnings and errors
@@ -1441,6 +1444,11 @@
   */
   virtual void cleanup();
   void set_thd(THD *thd_arg) { thd= thd_arg; }
+#ifdef EMBEDDED_LIBRARY
+  virtual void begin_dataset() {}
+#else
+  void begin_dataset() {}
+#endif
 };
 
 

--- 1.500/sql/sql_parse.cc	Thu Dec 22 13:12:33 2005
+++ 1.501/sql/sql_parse.cc	Wed Jan  4 14:18:54 2006
@@ -1713,13 +1713,10 @@
       net->no_send_error= 0;
       /*
         Multiple queries exits, execute them individually
-	in embedded server - just store them to be executed later 
       */
-#ifndef EMBEDDED_LIBRARY
       if (thd->lock || thd->open_tables || thd->derived_tables ||
           thd->prelocked_mode)
         close_thread_tables(thd);
-#endif
       ulong length= (ulong)(packet_end-packet);
 
       log_slow_statement(thd);
@@ -1737,25 +1734,7 @@
       thd->set_time(); /* Reset the query start time. */
       /* TODO: set thd->lex->sql_command to SQLCOM_END here */
       VOID(pthread_mutex_unlock(&LOCK_thread_count));
-#ifndef EMBEDDED_LIBRARY
       mysql_parse(thd, packet, length);
-#else
-      /*
-	'packet' can point inside the query_rest's buffer
-	so we have to do memmove here
-       */
-      if (thd->query_rest.length() > length)
-      {
-	memmove(thd->query_rest.c_ptr(), packet, length);
-	thd->query_rest.length(length);
-      }
-      else
-	thd->query_rest.copy(packet, length, thd->query_rest.charset());
-
-      thd->server_status&= ~ (SERVER_QUERY_NO_INDEX_USED |
-                              SERVER_QUERY_NO_GOOD_INDEX_USED);
-      break;
-#endif /*EMBEDDED_LIBRARY*/
     }
 
     if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -4242,10 +4221,8 @@
             goto error;
         }
 
-#ifndef EMBEDDED_LIBRARY
 	my_bool nsok= thd->net.no_send_ok;
 	thd->net.no_send_ok= TRUE;
-#endif
 	if (sp->m_flags & sp_head::MULTI_RESULTS)
 	{
 	  if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
@@ -4255,9 +4232,7 @@
               back
             */
 	    my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
-#ifndef EMBEDDED_LIBRARY
 	    thd->net.no_send_ok= nsok;
-#endif
 	    goto error;
 	  }
           /*
@@ -4274,18 +4249,14 @@
 				 sp->m_db.str, sp->m_name.str, TRUE, 0) ||
           sp_change_security_context(thd, sp, &save_ctx))
 	{
-#ifndef EMBEDDED_LIBRARY
 	  thd->net.no_send_ok= nsok;
-#endif
 	  goto error;
 	}
 	if (save_ctx &&
             check_routine_access(thd, EXECUTE_ACL,
                                  sp->m_db.str, sp->m_name.str, TRUE, 0))
 	{
-#ifndef EMBEDDED_LIBRARY
 	  thd->net.no_send_ok= nsok;
-#endif
 	  sp_restore_security_context(thd, save_ctx);
 	  goto error;
 	}
@@ -4317,9 +4288,7 @@
 	sp_restore_security_context(thd, save_ctx);
 #endif
 
-#ifndef EMBEDDED_LIBRARY
 	thd->net.no_send_ok= nsok;
-#endif
         thd->server_status&= ~bits_to_be_cleared;
 
 	if (!res)

--- 1.129/mysql-test/t/view.test	Mon Dec 12 15:59:05 2005
+++ 1.130/mysql-test/t/view.test	Wed Jan  4 14:18:54 2006
@@ -2084,7 +2084,9 @@
 #
 -- error ER_MALFORMED_DEFINER
 create definer=some_user@`` sql security invoker view v1 as select 1;
+--disable_warnings
 create definer=some_user@localhost sql security invoker view v1 as select 1;
+--enable_warnings
 show create view v1;
 drop view v1;
 

--- 1.6/mysql-test/t/skip_grants.test	Thu Nov 10 23:24:51 2005
+++ 1.7/mysql-test/t/skip_grants.test	Wed Jan  4 14:18:54 2006
@@ -1,3 +1,6 @@
+# This tests not performed with embedded server
+-- source include/not_embedded.inc
+
 --disable_warnings
 drop table if exists t1,v1;
 drop view if exists t1,v1;

--- 1.3/mysql-test/t/federated_archive.test	Wed Sep 14 11:31:13 2005
+++ 1.4/mysql-test/t/federated_archive.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 source include/have_archive.inc;
 source include/federated.inc;
 

--- 1.1/mysql-test/t/federated_bug_13118.test	Sat Sep 17 04:17:33 2005
+++ 1.2/mysql-test/t/federated_bug_13118.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 source include/federated.inc;
 
 

--- 1.3/mysql-test/t/federated_transactions.test	Mon Dec 19 14:12:44 2005
+++ 1.4/mysql-test/t/federated_transactions.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 source include/have_bdb.inc;
 source include/federated.inc;
 

--- 1.5/mysql-test/t/init_connect.test	Thu Jul 28 18:12:34 2005
+++ 1.6/mysql-test/t/init_connect.test	Wed Jan  4 14:18:53 2006
@@ -2,6 +2,8 @@
 # Test of init_connect variable
 #
 
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 connect (con0,localhost,root,,);
 connection con0;
 select hex(@a);

--- 1.1/mysql-test/t/read_only.test	Mon Oct 17 13:52:22 2005
+++ 1.2/mysql-test/t/read_only.test	Wed Jan  4 14:18:54 2006
@@ -1,6 +1,9 @@
 # Test of the READ_ONLY global variable:
 # check that it blocks updates unless they are only on temporary tables.
 
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
+
 --disable_warnings
 DROP TABLE IF EXISTS t1,t2,t3;
 --enable_warnings

--- 1.7/libmysqld/emb_qcache.cc	Fri Apr  1 08:17:43 2005
+++ 1.8/libmysqld/emb_qcache.cc	Wed Jan  4 14:18:53 2006
@@ -18,6 +18,7 @@
 #ifdef HAVE_QUERY_CACHE
 #include <mysql.h>
 #include "emb_qcache.h"
+#include "embedded_priv.h"
 
 void Querycache_stream::store_char(char c)
 {
@@ -284,22 +285,25 @@
 
 uint emb_count_querycache_size(THD *thd)
 {
-  uint result;
-  MYSQL *mysql= thd->mysql;
-  MYSQL_FIELD *field= mysql->fields;
-  MYSQL_FIELD *field_end= field + mysql->field_count;
-  MYSQL_ROWS *cur_row=NULL;
-  my_ulonglong n_rows=0;
+  uint result= 0;
+  MYSQL_FIELD *field;
+  MYSQL_FIELD *field_end;
+  MYSQL_ROWS *cur_row;
+  my_ulonglong n_rows;
+  MYSQL_DATA *data= thd->first_data;
+
+  while (data->embedded_info->next)
+    data= data->embedded_info->next;
+  field= data->embedded_info->fields_list;
+  field_end= field + data->fields;
   
   if (!field)
-    return 0;
-  if (thd->data)
-  {
-    *thd->data->prev_ptr= NULL; // this marks the last record
-    cur_row= thd->data->data;
-    n_rows= thd->data->rows;
-  }
-  result= (uint) (4+8 + (42 + 4*n_rows)*mysql->field_count);
+    return result;
+  *data->embedded_info->prev_ptr= NULL; // this marks the last record
+  cur_row= data->data;
+  n_rows= data->rows;
+  /* n_fields + n_rows + (field_info + strlen * n_rows) * n_fields */
+  result+= (uint) (4+8 + (42 + 4*n_rows)*data->fields);
 
   for(; field < field_end; field++)
   {
@@ -313,34 +317,38 @@
   for (; cur_row; cur_row=cur_row->next)
   {
     MYSQL_ROW col= cur_row->data;
-    MYSQL_ROW col_end= col + mysql->field_count;
+    MYSQL_ROW col_end= col + data->fields;
     for (; col < col_end; col++)
       if (*col)
-	result+= *(uint *)((*col) - sizeof(uint));
+        result+= *(uint *)((*col) - sizeof(uint));
   }
   return result;
 }
 
 void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
 {
-  MYSQL *mysql= thd->mysql;
-  MYSQL_FIELD *field= mysql->fields;
-  MYSQL_FIELD *field_end= field + mysql->field_count;
-  MYSQL_ROWS *cur_row= NULL;
-  my_ulonglong n_rows= 0;
+  MYSQL_FIELD *field;
+  MYSQL_FIELD *field_end;
+  MYSQL_ROWS *cur_row;
+  my_ulonglong n_rows;
+  MYSQL_DATA *data= thd->first_data;
+
+  DBUG_ENTER("emb_store_querycache_result");
+
+  while (data->embedded_info->next)
+    data= data->embedded_info->next;
+  field= data->embedded_info->fields_list;
+  field_end= field + data->fields;
 
   if (!field)
-    return;
+    DBUG_VOID_RETURN;
 
-  if (thd->data)
-  {
-    *thd->data->prev_ptr= NULL; // this marks the last record
-    cur_row= thd->data->data;
-    n_rows= thd->data->rows;
-  }
+  *data->embedded_info->prev_ptr= NULL; // this marks the last record
+  cur_row= data->data;
+  n_rows= data->rows;
 
-  dst->store_int((uint)mysql->field_count);
-  dst->store_ll((uint)n_rows);
+  dst->store_int((uint)data->fields);
+  dst->store_ll((ulonglong)n_rows);
 
   for(; field < field_end; field++)
   {
@@ -356,14 +364,13 @@
     dst->store_str(field->org_table, field->org_table_length);
     dst->store_str(field->db, field->db_length);
     dst->store_str(field->catalog, field->catalog_length);
-
     dst->store_safe_str(field->def, field->def_length);
   }
   
   for (; cur_row; cur_row=cur_row->next)
   {
     MYSQL_ROW col= cur_row->data;
-    MYSQL_ROW col_end= col + mysql->field_count;
+    MYSQL_ROW col_end= col + data->fields;
     for (; col < col_end; col++)
     {
       uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0;
@@ -371,28 +378,34 @@
     }
   }
   DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
+  DBUG_VOID_RETURN;
 }
 
 int emb_load_querycache_result(THD *thd, Querycache_stream *src)
 {
-  MYSQL *mysql= thd->mysql;
-  MYSQL_DATA *data;
+  MYSQL_DATA *data= thd->alloc_new_dataset();
   MYSQL_FIELD *field;
   MYSQL_FIELD *field_end;
-  MEM_ROOT *f_alloc= &mysql->field_alloc;
+  MEM_ROOT *f_alloc;
   MYSQL_ROWS *row, *end_row;
   MYSQL_ROWS **prev_row;
   ulonglong rows;
   MYSQL_ROW columns;
+  DBUG_ENTER("emb_load_querycache_result");
 
-  mysql->field_count= src->load_int();
+  if (!data)
+    goto err;
+  init_alloc_root(&data->alloc, 8192,0);
+  f_alloc= &data->alloc;
+
+  data->fields= src->load_int();
   rows= src->load_ll();
 
   if (!(field= (MYSQL_FIELD *)
-	alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD))))
+        alloc_root(f_alloc,data->fields*sizeof(MYSQL_FIELD))))
     goto err;
-  mysql->fields= field;
-  for(field_end= field+mysql->field_count; field < field_end; field++)
+  data->embedded_info->fields_list= field;
+  for(field_end= field+data->fields; field < field_end; field++)
   {
     field->length= src->load_int();
     field->max_length= (unsigned int)src->load_int();
@@ -402,47 +415,43 @@
     field->decimals= (unsigned int)src->load_char();
 
     if (!(field->name= src->load_str(f_alloc, &field->name_length))          ||
-	!(field->table= src->load_str(f_alloc,&field->table_length))         ||
-	!(field->org_name= src->load_str(f_alloc, &field->org_name_length))  ||
-	!(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
-	!(field->db= src->load_str(f_alloc, &field->db_length))              ||
-	!(field->catalog= src->load_str(f_alloc, &field->catalog_length))    ||
-	src->load_safe_str(f_alloc, &field->def, &field->def_length))
+        !(field->table= src->load_str(f_alloc,&field->table_length))         ||
+        !(field->org_name= src->load_str(f_alloc, &field->org_name_length))  ||
+        !(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
+        !(field->db= src->load_str(f_alloc, &field->db_length))              ||
+        !(field->catalog= src->load_str(f_alloc, &field->catalog_length))    ||
+        src->load_safe_str(f_alloc, &field->def, &field->def_length))
       goto err;
   }
   
-  if (!rows)
-    return 0;
-  if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA), 
-				     MYF(MY_WME | MY_ZEROFILL))))
-    goto err;
-  thd->data= data;
-  init_alloc_root(&data->alloc, 8192,0);
-  row= (MYSQL_ROWS *)alloc_root(&data->alloc, (uint) (rows * sizeof(MYSQL_ROWS) +
-				rows * (mysql->field_count+1)*sizeof(char*)));
+  row= (MYSQL_ROWS *)alloc_root(&data->alloc,
+                                (uint) (rows * sizeof(MYSQL_ROWS) +
+                                        rows*(data->fields+1)*sizeof(char*)));
   end_row= row + rows;
   columns= (MYSQL_ROW)end_row;
   
   data->rows= rows;
-  data->fields= mysql->field_count;
   data->data= row;
+  if (!rows)
+    goto return_ok;
 
   for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
   {
     *prev_row= row;
     row->data= columns;
-    MYSQL_ROW col_end= columns + mysql->field_count;
+    MYSQL_ROW col_end= columns + data->fields;
     for (; columns < col_end; columns++)
       src->load_column(&data->alloc, columns);
 
     *(columns++)= NULL;
   }
   *prev_row= NULL;
-  data->prev_ptr= prev_row;
-
-  return 0;
+  data->embedded_info->prev_ptr= prev_row;
+return_ok:
+  send_eof(thd);
+  DBUG_RETURN(0);
 err:
-  return 1;
+  DBUG_RETURN(1);
 }
 
 #endif /*HAVE_QUERY_CACHE*/

--- 1.2/mysql-test/t/query_cache_notembedded.test	Thu Aug 11 15:06:26 2005
+++ 1.3/mysql-test/t/query_cache_notembedded.test	Wed Jan  4 14:18:54 2006
@@ -97,4 +97,88 @@
 SELECT * FROM t1;
 drop table t1;
 
+#
+# query in QC from normal execution and SP (BUG#6897)
+# improved to also test BUG#3583 and BUG#12990
+#
+flush query cache;
+reset query cache;
+flush status;
+delimiter //;
+create table t1 (s1 int)//
+create procedure f1 () begin
+select sql_cache * from t1;
+select sql_cache * from t1;
+select sql_cache * from t1;
+end;//
+create procedure f2 () begin
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1;
+end;//
+create procedure f3 () begin
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+end;//
+create procedure f4 () begin
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1 where s1=1;
+end;//
+delimiter ;//
+call f1();
+--replace_result 1 3
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+insert into t1 values (1);
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+call f1();
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+flush query cache;
+reset query cache;
+flush status;
+select sql_cache * from t1;
+select sql_cache * from t1 where s1=1;
+call f1();
+call f2();
+call f3();
+call f4();
+call f4();
+call f3();
+call f2();
+select sql_cache * from t1 where s1=1;
+insert into t1 values (2);
+call f1();
+select sql_cache * from t1 where s1=1;
+select sql_cache * from t1;
+call f1();
+call f3();
+call f3();
+call f1();
+
+drop procedure f1;
+drop procedure f2;
+drop procedure f3;
+drop procedure f4;
+drop table t1;
+
+
 set GLOBAL query_cache_size=0;

--- 1.81/sql-common/client.c	Wed Dec  7 03:49:58 2005
+++ 1.82/sql-common/client.c	Wed Jan  4 14:18:54 2006
@@ -1545,7 +1545,8 @@
   NULL,
   cli_read_statistics,
   cli_read_query_result,
-  cli_read_change_user_result
+  cli_read_change_user_result,
+  cli_read_binary_rows
 #endif
 };
 
@@ -2339,8 +2340,9 @@
   my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
   my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
   my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+  my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
   /* Clear pointers for better safety */
-  mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
+  mysql->info_buffer=mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
 }
 
 
@@ -2476,8 +2478,7 @@
   if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
     mysql->server_status|= SERVER_STATUS_IN_TRANS;
 
-  if (!(fields=(*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,
-					    protocol_41(mysql) ? 7 : 5)))
+  if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
     DBUG_RETURN(1);
   if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
 				    (uint) field_count,0,
--- New file ---
+++ mysql-test/t/ctype_cp932_notembedded.test	06/01/04 14:18:55
-- source include/not_embedded.inc
-- source include/have_cp932.inc

--character_set cp932
--disable_warnings
drop table if exists t1;
--enable_warnings

set names cp932;
set character_set_database = cp932;

# Test prepared statement with 0x8300 sequence in parameter while
# running with cp932 client character set.
RESET MASTER;
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
# TODO: Note that this doesn't actually test the code which was added for
# bug#11338 because this syntax for prepared statements causes the PS to
# be replicated differently than if we executed the PS from C or Java.
# Using this syntax, variable names are inserted into the binlog instead
# of values. The real goal of this test is to check the code that was
# added to Item_param::query_val_str() in order to do hex encoding of
# PS parameters when the client character set is cp932;
# Bug#11338 has an example java program which can be used to verify this 
# code (and I have used it to test the fix) until there is some way to
# exercise this code from mysql-test-run.
EXECUTE stmt1 USING @var1;
SHOW BINLOG EVENTS FROM 98;
SELECT HEX(f1) FROM t1;
DROP table t1;
# end test for bug#11338

--- New file ---
+++ mysql-test/t/innodb_notembedded.test	06/01/04 14:18:55
-- source include/not_embedded.inc
-- source include/have_innodb.inc

connect (a,localhost,root,,);
connect (b,localhost,root,,);


#
# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to
# non-blocking SELECT
#
create table t1 (col1 integer primary key, col2 integer) engine=innodb;
insert t1 values (1,100);
delimiter |;
create function f1 () returns integer begin
declare var1 int;
select col2 into var1 from t1 where col1=1 for update;
return var1;
end|
delimiter ;|
start transaction;
select f1();
connection b;
send update t1 set col2=0 where col1=1;
connection default;
select * from t1;
connection a;
rollback;
connection b;
reap;
rollback;
connection default;
drop table t1;
drop function f1;
disconnect a;
disconnect b;

--- New file ---
+++ mysql-test/t/sp_notembedded.test	06/01/04 14:18:55
# Can't test with embedded server
-- source include/not_embedded.inc

delimiter |;

#
# BUG#4902: Stored procedure with SHOW WARNINGS leads to packet error
#
# Added tests for show grants command
--disable_warnings
drop procedure if exists bug4902|
--enable_warnings
create procedure bug4902()
begin
  show grants for 'root'@'localhost';
end|
--disable_parsing
show binlog events;
show storage engines;
show master status;
show slave hosts;
show slave status;
--enable_parsing

call bug4902()|
call bug4902()|

drop procedure bug4902|

# We need separate SP for SHOW PROCESSLIST  since we want use replace_column
--disable_warnings
drop procedure if exists bug4902_2|
--enable_warnings
create procedure bug4902_2()
begin
  show processlist;
end|
--replace_column 1 # 6 # 3 localhost
call bug4902_2()|
--replace_column 1 # 6 # 3 localhost
call bug4902_2()|
drop procedure bug4902_2|


#
# BUG#5278: Stored procedure packets out of order if SET PASSWORD.
#
--disable_warnings
drop function if exists bug5278|
--enable_warnings
create function bug5278 () returns char
begin
  SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
  return 'okay';
end|

--error 1133
select bug5278()|
--error 1133
select bug5278()|
drop function bug5278|


--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (
	id   char(16) not null default '',
        data int not null
);
#
# BUG#3583: query cache doesn't work for stored procedures
#
--disable_warnings
drop procedure if exists bug3583|
--enable_warnings
--disable_warnings
drop procedure if exists bug3583|
--enable_warnings
create procedure bug3583()
begin
  declare c int;

  select * from t1;
  select count(*) into c from t1;
  select c;
end|

insert into t1 values ("x", 3), ("y", 5)|
set @x = @@query_cache_size|
set global query_cache_size = 10*1024*1024|

flush status|
flush query cache|
show status like 'Qcache_hits'|
call bug3583()|
show status like 'Qcache_hits'|
call bug3583()|
call bug3583()|
show status like 'Qcache_hits'|

set global query_cache_size = @x|
flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
drop table t1;

#
# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
#
--disable_warnings
drop procedure if exists bug6807|
--enable_warnings
create procedure bug6807()
begin
  declare id int;

  set id = connection_id();
  kill query id;
  select 'Not reached';
end|

--error 1317
call bug6807()|
--error 1317
call bug6807()|

drop procedure bug6807|

#
# BUG#10100: function (and stored procedure?) recursivity problem
#
--disable_warnings
drop function if exists bug10100f|
drop procedure if exists bug10100p|
drop procedure if exists bug10100t|
drop procedure if exists bug10100pt|
drop procedure if exists bug10100pv|
drop procedure if exists bug10100pd|
drop procedure if exists bug10100pc|
--enable_warnings
# routines with simple recursion
create function bug10100f(prm int) returns int
begin
  if prm > 1 then
    return prm * bug10100f(prm - 1);
  end if;
  return 1;
end|
create procedure bug10100p(prm int, inout res int)
begin
  set res = res * prm;
  if prm > 1 then
    call bug10100p(prm - 1, res);  
  end if;
end|
create procedure bug10100t(prm int)
begin
  declare res int;
  set res = 1;
  call bug10100p(prm, res);
  select res;
end|

# a procedure which use tables and recursion
create table t3 (a int)|
insert into t3 values (0)|
create view v1 as select a from t3;
create procedure bug10100pt(level int, lim int)
begin
  if level < lim then
    update t3 set a=level;
    FLUSH TABLES;
    call bug10100pt(level+1, lim);
  else
    select * from t3;
  end if;
end|
# view & recursion
create procedure bug10100pv(level int, lim int)
begin
  if level < lim then
    update v1 set a=level;
    FLUSH TABLES;
    call bug10100pv(level+1, lim);
  else
    select * from v1;
  end if;
end|
# dynamic sql & recursion
prepare stmt2 from "select * from t3;";
create procedure bug10100pd(level int, lim int)
begin
  if level < lim then
    select level;
    prepare stmt1 from "update t3 set a=a+2";
    execute stmt1;
    FLUSH TABLES;
    execute stmt1;
    FLUSH TABLES;
    execute stmt1;
    FLUSH TABLES;
    deallocate prepare stmt1;
    execute stmt2;
    select * from t3;
    call bug10100pd(level+1, lim);
  else
    execute stmt2;
  end if;
end|
# cursor & recursion
create procedure bug10100pc(level int, lim int)
begin
  declare lv int;
  declare c cursor for select a from t3;
  open c;
  if level < lim then
    select level;
    fetch c into lv;
    select lv;
    update t3 set a=level+lv;
    FLUSH TABLES;
    call bug10100pc(level+1, lim);
  else
    select * from t3;
  end if;
  close c;
end|

#end of the stack checking
set @@max_sp_recursion_depth=255|
set @var=1|
#disable log because error about stack overrun contains numbers which
#depend on a system
-- disable_result_log
-- error ER_STACK_OVERRUN_NEED_MORE
call bug10100p(255, @var)|
-- error ER_STACK_OVERRUN_NEED_MORE
call bug10100pt(1,255)|
-- error ER_STACK_OVERRUN_NEED_MORE
call bug10100pv(1,255)|
-- error ER_STACK_OVERRUN_NEED_MORE
call bug10100pd(1,255)|
-- error ER_STACK_OVERRUN_NEED_MORE
call bug10100pc(1,255)|
-- enable_result_log
set @@max_sp_recursion_depth=0|

deallocate prepare stmt2|

drop function bug10100f|
drop procedure bug10100p|
drop procedure bug10100t|
drop procedure bug10100pt|
drop procedure bug10100pv|
drop procedure bug10100pd|
drop procedure bug10100pc|
drop view v1|

delimiter ;|

--- New file ---
+++ mysql-test/t/subselect_notembedded.test	06/01/04 14:18:56
-- source include/not_embedded.inc

#
# BUG #10308: purge log with subselect
#

purge master logs before (select adddate(current_timestamp(), interval -4 day));



--- 1.1/mysql-test/t/wait_timeout.test	Tue Oct 11 21:12:10 2005
+++ 1.2/mysql-test/t/wait_timeout.test	Wed Jan  4 14:18:54 2006
@@ -1,3 +1,6 @@
+# This tests not performed with embedded server
+-- source include/not_embedded.inc
+
 #
 # Bug #8731: wait_timeout does not work on Mac OS X
 #

--- 1.14/mysql-test/t/mysql_client_test.test	Tue Oct 25 22:10:47 2005
+++ 1.15/mysql-test/t/mysql_client_test.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,6 @@
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
+
 # We run with different binaries for normal and --embedded-server
 #
 # If this test fails with "command "$MYSQL_CLIENT_TEST" failed",

--- 1.22/mysql-test/t/mysqltest.test	Fri Dec  9 20:18:18 2005
+++ 1.23/mysql-test/t/mysqltest.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,5 @@
+# This test should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 
 # ============================================================================
 #

--- 1.4/sql/sql_cursor.cc	Sat Nov 19 19:59:56 2005
+++ 1.5/sql/sql_cursor.cc	Wed Jan  4 14:18:54 2006
@@ -603,6 +603,7 @@
   THD *thd= table->in_use;
 
   int res= 0;
+  result->begin_dataset();
   for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++)
   {
     if ((res= table->file->rnd_next(table->record[0])))

--- 1.1/mysql-test/t/binlog_stm_binlog.test	Thu Dec 22 09:34:58 2005
+++ 1.2/mysql-test/t/binlog_stm_binlog.test	Wed Jan  4 14:18:53 2006
@@ -1,5 +1,6 @@
 # This is a wrapper for binlog.test so that the same test case can be used 
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
+-- source include/not_embedded.inc
 -- source include/have_binlog_format_statement.inc
 -- source extra/binlog_tests/binlog.test

--- 1.1/mysql-test/t/binlog_stm_blackhole.test	Thu Dec 22 09:34:58 2005
+++ 1.2/mysql-test/t/binlog_stm_blackhole.test	Wed Jan  4 14:18:53 2006
@@ -1,5 +1,6 @@
 # This is a wrapper for binlog.test so that the same test case can be used 
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
+-- source include/not_embedded.inc
 -- source include/have_binlog_format_statement.inc
 -- source extra/binlog_tests/blackhole.test

--- 1.1/mysql-test/t/binlog_stm_ctype_cp932.test	Thu Dec 22 09:34:58 2005
+++ 1.2/mysql-test/t/binlog_stm_ctype_cp932.test	Wed Jan  4 14:18:53 2006
@@ -1,5 +1,6 @@
 # This is a wrapper for binlog.test so that the same test case can be used 
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
+-- source include/not_embedded.inc
 -- source include/have_binlog_format_statement.inc
 -- source extra/binlog_tests/ctype_cp932.test

--- 1.11/mysql-test/t/delayed.test	Tue Aug  2 05:00:00 2005
+++ 1.12/mysql-test/t/delayed.test	Wed Jan  4 14:18:53 2006
@@ -3,6 +3,9 @@
 # (Can't be tested with purify :( )
 #
 
+# This tests not performed with embedded server
+-- source include/not_embedded.inc
+
 --disable_warnings
 drop table if exists t1;
 --enable_warnings

--- 1.10/mysql-test/t/flush_table.test	Thu Nov 24 00:44:53 2005
+++ 1.11/mysql-test/t/flush_table.test	Wed Jan  4 14:18:53 2006
@@ -4,6 +4,8 @@
 # Test of flush table
 #
 
+# Should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 --disable_warnings
 drop table if exists t1,t2;
 --enable_warnings

--- 1.122/mysql-test/t/innodb.test	Thu Dec 22 08:10:55 2005
+++ 1.123/mysql-test/t/innodb.test	Wed Jan  4 14:18:53 2006
@@ -1576,33 +1576,7 @@
 checksum table t1;
 drop table t1;
 
-#
-# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to
-# non-blocking SELECT
-#
-create table t1 (col1 integer primary key, col2 integer) engine=innodb;
-insert t1 values (1,100);
-delimiter |;
-create function f1 () returns integer begin
-declare var1 int;
-select col2 into var1 from t1 where col1=1 for update;
-return var1;
-end|
-delimiter ;|
-start transaction;
-select f1();
-connection b;
-send update t1 set col2=0 where col1=1;
 connection default;
-select * from t1;
-connection a;
-rollback;
-connection b;
-reap;
-rollback;
-connection default;
-drop table t1;
-drop function f1;
 disconnect a;
 disconnect b;
 

--- 1.12/libmysqld/embedded_priv.h	Mon May 17 12:05:30 2004
+++ 1.13/libmysqld/embedded_priv.h	Wed Jan  4 14:18:53 2006
@@ -16,18 +16,25 @@
 
 /* Prototypes for the embedded version of MySQL */
 
-#include <my_global.h>
-#include <mysql.h>
-#include <mysql_embed.h>
-#include <mysqld_error.h>
-#include <my_pthread.h>
-
 C_MODE_START
 void lib_connection_phase(NET *net, int phase);
 void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
 void *create_embedded_thd(int client_flag, char *db);
 int check_embedded_connection(MYSQL *mysql);
 void free_old_query(MYSQL *mysql);
-void embedded_get_error(MYSQL *mysql);
 extern MYSQL_METHODS embedded_methods;
+
+/* This one is used by embedded library to gather returning data */
+typedef struct embedded_query_result
+{
+  MYSQL_ROWS **prev_ptr;
+  unsigned int warning_count, server_status;
+  struct st_mysql_data *next;
+  my_ulonglong affected_rows, insert_id;
+  char info[MYSQL_ERRMSG_SIZE];
+  MYSQL_FIELD *fields_list;
+  unsigned int last_errno;
+  char sqlstate[SQLSTATE_LENGTH+1];
+} EQR;
+
 C_MODE_END

--- 1.53/mysql-test/t/query_cache.test	Sat Dec  3 10:53:14 2005
+++ 1.54/mysql-test/t/query_cache.test	Wed Jan  4 14:18:53 2006
@@ -822,29 +822,14 @@
 end;//
 delimiter ;//
 call f1();
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
 call f1();
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
 call f1();
 select sql_cache * from t1;
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
 insert into t1 values (1);
 select sql_cache * from t1;
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
 call f1();
 call f1();
 select sql_cache * from t1;
-show status like "Qcache_queries_in_cache";
-show status like "Qcache_inserts";
-show status like "Qcache_hits";
 flush query cache;
 reset query cache;
 flush status;

--- 1.31/sql/protocol.h	Wed Nov 23 02:50:32 2005
+++ 1.32/sql/protocol.h	Wed Jan  4 14:18:54 2006
@@ -91,6 +91,12 @@
   virtual bool store_date(TIME *time)=0;
   virtual bool store_time(TIME *time)=0;
   virtual bool store(Field *field)=0;
+#ifdef EMBEDDED_LIBRARY
+  int begin_dataset();
+  virtual void remove_last_row() {}
+#else
+  void remove_last_row() {}
+#endif
 };
 
 
@@ -117,6 +123,9 @@
   virtual bool store(float nr, uint32 decimals, String *buffer);
   virtual bool store(double from, uint32 decimals, String *buffer);
   virtual bool store(Field *field);
+#ifdef EMBEDDED_LIBRARY
+  void remove_last_row();
+#endif
 };
 
 

--- 1.107/libmysqld/lib_sql.cc	Wed Sep 28 21:23:18 2005
+++ 1.108/libmysqld/lib_sql.cc	Wed Jan  4 14:18:53 2006
@@ -42,21 +42,48 @@
 #undef ER
 #include "errmsg.h"
 #include <sql_common.h>
+#include "embedded_priv.h"
 
-void embedded_get_error(MYSQL *mysql)
+static my_bool emb_read_query_result(MYSQL *mysql);
+
+void THD::clear_data_list()
 {
-  THD *thd=(THD *) mysql->thd;
-  NET *net= &mysql->net;
-  if ((net->last_errno= thd->net.last_errno))
-  {
-    memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error));
-    memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate));
-  }
-  else
+  while (first_data)
   {
-    net->last_error[0]= 0;
-    strmov(net->sqlstate, not_error_sqlstate);
+    MYSQL_DATA *data= first_data;
+    first_data= data->embedded_info->next;
+    free_rows(data);
   }
+  data_tail= &first_data;
+  free_rows(cur_data);
+  cur_data= 0;
+}
+
+
+/*
+  Reads error information from the MYSQL_DATA and puts
+  it into proper MYSQL members
+
+  SYNOPSIS
+    embedded_get_error()
+    mysql        connection handler
+    data         query result
+
+  NOTES
+    after that function error information will be accessible
+       with usual functions like mysql_error()
+    data is my_free-d in this function
+    most of the data is stored in data->embedded_info structure
+*/
+
+void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
+{
+  NET *net= &mysql->net;
+  struct embedded_query_result *ei= data->embedded_info;
+  net->last_errno= ei->last_errno;
+  strmake(net->last_error, ei->info, sizeof(net->last_error));
+  memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
+  my_free((gptr) data, MYF(0));
 }
 
 static my_bool
@@ -68,11 +95,7 @@
   THD *thd=(THD *) mysql->thd;
   NET *net= &mysql->net;
 
-  if (thd->data)
-  {
-    free_rows(thd->data);
-    thd->data= 0;
-  }
+  thd->clear_data_list();
   /* Check that we are calling the client functions in right order */
   if (mysql->status != MYSQL_STATUS_READY)
   {
@@ -104,83 +127,101 @@
     arg_length= header_length;
   }
 
+  thd->net.no_send_error= 0;
   result= dispatch_command(command, thd, (char *) arg, arg_length + 1);
+  thd->cur_data= 0;
 
   if (!skip_check)
     result= thd->net.last_errno ? -1 : 0;
 
-  /*
-    If mysql->field_count is set it means the parsing of the query was OK
-    and metadata was returned (see Protocol::send_fields).
-    In this case we postpone the error to be returned in mysql_stmt_store_result
-    (see emb_read_rows) to behave just as standalone server.
-  */
-  if (!mysql->field_count)
-    embedded_get_error(mysql);
-  mysql->server_status= thd->server_status;
-  mysql->warning_count= ((THD*)mysql->thd)->total_warn_count;
   return result;
 }
 
 static void emb_flush_use_result(MYSQL *mysql)
 {
-  MYSQL_DATA *data= ((THD*)(mysql->thd))->data;
-
-  if (data)
+  THD *thd= (THD*) mysql->thd;
+  if (thd->cur_data)
+  {
+    free_rows(thd->cur_data);
+    thd->cur_data= 0;
+  }
+  else if (thd->first_data)
   {
+    MYSQL_DATA *data= thd->first_data;
+    thd->first_data= data->embedded_info->next;
     free_rows(data);
-    ((THD*)(mysql->thd))->data= NULL;
   }
 }
 
+
+/*
+  reads dataset from the next query result
+
+  SYNOPSIS
+  emb_read_rows()
+  mysql		connection handle
+  other parameters are not used
+
+  NOTES
+    It just gets next MYSQL_DATA from the result's queue
+
+  RETURN
+    pointer to MYSQL_DATA with the coming recordset
+*/
+
 static MYSQL_DATA *
 emb_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)),
 	      unsigned int fields __attribute__((unused)))
 {
-  MYSQL_DATA *result= ((THD*)mysql->thd)->data;
-  embedded_get_error(mysql);
-  if (mysql->net.last_errno)
-    return NULL;
-  if (!result)
+  MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data;
+  ((THD*)mysql->thd)->cur_data= 0;
+  if (result->embedded_info->last_errno)
   {
-    if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
-					 MYF(MY_WME | MY_ZEROFILL))))
-    {
-      NET *net = &mysql->net;
-      net->last_errno=CR_OUT_OF_MEMORY;
-      strmov(net->sqlstate, unknown_sqlstate);
-      strmov(net->last_error,ER(net->last_errno));
-      return NULL;
-    }    
-    return result;
+    embedded_get_error(mysql, result);
+    return NULL;
   }
-  *result->prev_ptr= NULL;
-  ((THD*)mysql->thd)->data= NULL;
+  *result->embedded_info->prev_ptr= NULL;
   return result;
 }
 
+
 static MYSQL_FIELD *emb_list_fields(MYSQL *mysql)
 {
+  MYSQL_DATA *res;
+  if (emb_read_query_result(mysql))
+    return 0;
+  res= ((THD*) mysql->thd)->cur_data;
+  ((THD*) mysql->thd)->cur_data= 0;
+  mysql->field_alloc= res->alloc;
+  my_free((gptr) res,MYF(0));
+  mysql->status= MYSQL_STATUS_READY;
   return mysql->fields;
 }
 
 static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
 {
-  THD *thd= (THD*)mysql->thd;
-  if (mysql->net.last_errno)
-    return 1;
+  THD *thd= (THD*) mysql->thd;
+  MYSQL_DATA *res;
+
   stmt->stmt_id= thd->client_stmt_id;
   stmt->param_count= thd->client_param_count;
-  stmt->field_count= mysql->field_count;
+  stmt->field_count= 0;
 
-  if (stmt->field_count != 0)
+  if (thd->first_data)
   {
+    if (emb_read_query_result(mysql))
+      return 1;
+    stmt->field_count= mysql->field_count;
+    mysql->status= MYSQL_STATUS_READY;
+    res= thd->cur_data;
+    thd->cur_data= NULL;
     if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
       mysql->server_status|= SERVER_STATUS_IN_TRANS;
 
     stmt->fields= mysql->fields;
-    stmt->mem_root= mysql->field_alloc;
+    stmt->mem_root= res->alloc;
     mysql->fields= NULL;
+    my_free((gptr) res,MYF(0));
   }
 
   return 0;
@@ -201,13 +242,42 @@
     *to= *column ? *(uint *)((*column) - sizeof(uint)) : 0;
 }
 
-static my_bool emb_mysql_read_query_result(MYSQL *mysql)
+static my_bool emb_read_query_result(MYSQL *mysql)
 {
-  if (mysql->net.last_errno)
-    return -1;
+  THD *thd= (THD*) mysql->thd;
+  MYSQL_DATA *res= thd->first_data;
+  DBUG_ASSERT(!thd->cur_data);
+  thd->first_data= res->embedded_info->next;
+  if (res->embedded_info->last_errno &&
+      !res->embedded_info->fields_list)
+  {
+    embedded_get_error(mysql, res);
+    return 1;
+  }
+
+  mysql->warning_count= res->embedded_info->warning_count;
+  mysql->server_status= res->embedded_info->server_status;
+  mysql->field_count= res->fields;
+  mysql->fields= res->embedded_info->fields_list;
+  mysql->affected_rows= res->embedded_info->affected_rows;
+  mysql->insert_id= res->embedded_info->insert_id;
+  mysql->net.last_errno= 0;
+  mysql->net.last_error[0]= 0;
+  mysql->info= 0;
 
-  if (mysql->field_count)
+  if (res->embedded_info->info[0])
+  {
+    strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1);
+    mysql->info= mysql->info_buffer;
+  }
+
+  if (res->embedded_info->fields_list)
+  {
     mysql->status=MYSQL_STATUS_GET_RESULT;
+    thd->cur_data= res;
+  }
+  else
+    my_free((gptr) res, MYF(0));
 
   return 0;
 }
@@ -215,14 +285,18 @@
 static int emb_stmt_execute(MYSQL_STMT *stmt)
 {
   DBUG_ENTER("emb_stmt_execute");
-  char header[4];
+  char header[5];
+  MYSQL_DATA *res;
+  THD *thd;
+
   int4store(header, stmt->stmt_id);
-  THD *thd= (THD*)stmt->mysql->thd;
+  header[4]= stmt->flags;
+  thd= (THD*)stmt->mysql->thd;
   thd->client_param_count= stmt->param_count;
   thd->client_params= stmt->params;
   if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
                            header, sizeof(header), 1) ||
-      emb_mysql_read_query_result(stmt->mysql))
+      emb_read_query_result(stmt->mysql))
   {
     NET *net= &stmt->mysql->net;
     set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
@@ -230,6 +304,8 @@
   }
   stmt->affected_rows= stmt->mysql->affected_rows;
   stmt->insert_id= stmt->mysql->insert_id;
+  stmt->server_status= stmt->mysql->server_status;
+
   DBUG_RETURN(0);
 }
 
@@ -240,22 +316,53 @@
     return 1;
   stmt->result= *data;
   my_free((char *) data, MYF(0));
+  set_stmt_errmsg(stmt, stmt->mysql->net.last_error,
+                  stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate);
   return 0;
 }
 
+int emb_read_rows_from_cursor(MYSQL_STMT *stmt)
+{
+  MYSQL *mysql= stmt->mysql;
+  THD *thd= (THD*) mysql->thd;
+  MYSQL_DATA *res= thd->first_data;
+  DBUG_ASSERT(!thd->first_data->embedded_info->next);
+  thd->first_data= 0;
+  if (res->embedded_info->last_errno)
+  {
+    embedded_get_error(mysql, res);
+    set_stmt_errmsg(stmt, mysql->net.last_error,
+                    mysql->net.last_errno, mysql->net.sqlstate);
+    return 1;
+  }
+
+  thd->cur_data= res;
+  mysql->warning_count= res->embedded_info->warning_count;
+  mysql->server_status= res->embedded_info->server_status;
+  mysql->net.last_errno= 0;
+  mysql->net.last_error[0]= 0;
+
+  return emb_read_binary_rows(stmt);
+}
+
 int emb_unbuffered_fetch(MYSQL *mysql, char **row)
 {
-  MYSQL_DATA *data= ((THD*)mysql->thd)->data;
-  embedded_get_error(mysql);
-  if (mysql->net.last_errno)
-    return mysql->net.last_errno;
+  THD *thd= (THD*) mysql->thd;
+  MYSQL_DATA *data= thd->cur_data;
+  if (data && data->embedded_info->last_errno)
+  {
+    embedded_get_error(mysql, data);
+    thd->cur_data= 0;
+    return 1;
+  }
   if (!data || !data->data)
   {
     *row= NULL;
     if (data)
     {
+      thd->cur_data= thd->first_data;
+      thd->first_data= data->embedded_info->next;
       free_rows(data);
-      ((THD*)mysql->thd)->data= NULL;
     }
   }
   else
@@ -269,9 +376,9 @@
 static void emb_free_embedded_thd(MYSQL *mysql)
 {
   THD *thd= (THD*)mysql->thd;
-  if (thd->data)
-    free_rows(thd->data);
+  thd->clear_data_list();
   thread_count--;
+  thd->store_globals();
   delete thd;
   mysql->thd=0;
 }
@@ -283,23 +390,11 @@
 }
 
 
-static MYSQL_RES * emb_mysql_store_result(MYSQL *mysql)
+static MYSQL_RES * emb_store_result(MYSQL *mysql)
 {
   return mysql_store_result(mysql);
 }
 
-my_bool emb_next_result(MYSQL *mysql)
-{
-  THD *thd= (THD*)mysql->thd;
-  DBUG_ENTER("emb_next_result");
-
-  if (emb_advanced_command(mysql, COM_QUERY,0,0,
-			   thd->query_rest.ptr(),thd->query_rest.length(),1) ||
-      emb_mysql_read_query_result(mysql))
-    DBUG_RETURN(1);
-
-  DBUG_RETURN(0);				/* No more results */
-}
 
 int emb_read_change_user_result(MYSQL *mysql, 
 				char *buff __attribute__((unused)),
@@ -310,10 +405,10 @@
 
 MYSQL_METHODS embedded_methods= 
 {
-  emb_mysql_read_query_result,
+  emb_read_query_result,
   emb_advanced_command,
   emb_read_rows,
-  emb_mysql_store_result,
+  emb_store_result,
   emb_fetch_lengths, 
   emb_flush_use_result,
   emb_list_fields,
@@ -323,8 +418,9 @@
   emb_unbuffered_fetch,
   emb_free_embedded_thd,
   emb_read_statistics,
-  emb_next_result,
-  emb_read_change_user_result
+  emb_read_query_result,
+  emb_read_change_user_result,
+  emb_read_rows_from_cursor
 };
 
 C_MODE_END
@@ -483,6 +579,7 @@
   THD *thd = (THD *)mysql->thd;
   thd->mysql= mysql;
   mysql->server_version= server_version;
+  init_alloc_root(&mysql->field_alloc, 8192, 0);
 }
 
 void *create_embedded_thd(int client_flag, char *db)
@@ -490,6 +587,7 @@
   THD * thd= new THD;
   thd->thread_id= thread_id++;
 
+  thd->thread_stack= (char*) &thd;
   if (thd->store_globals())
   {
     fprintf(stderr,"store_globals failed.\n");
@@ -498,7 +596,6 @@
 
   thd->mysys_var= my_thread_var;
   thd->dbug_thread_id= my_thread_id();
-  thd->thread_stack= (char*) &thd;
 
 /* TODO - add init_connect command execution */
 
@@ -517,9 +614,10 @@
   thd->security_ctx->db_access= DB_ACLS;
   thd->security_ctx->master_access= ~NO_ACCESS;
 #endif
-  thd->net.query_cache_query= 0;
-
-  thd->data= 0;
+  thd->cur_data= 0;
+  thd->first_data= 0;
+  thd->data_tail= &thd->first_data;
+  bzero((char*) &thd->net, sizeof(thd->net));
 
   thread_count++;
   return thd;
@@ -531,11 +629,15 @@
 #ifdef NO_EMBEDDED_ACCESS_CHECKS
 int check_embedded_connection(MYSQL *mysql)
 {
+  int result;
   THD *thd= (THD*)mysql->thd;
   Security_context *sctx= thd->security_ctx;
-  sctx->host_or_ip= sctx->host= (char*)my_localhost;
+  sctx->host_or_ip= sctx->host= (char*) my_localhost;
+  strmake(sctx->priv_host, (char*) my_localhost,  MAX_HOSTNAME-1);
   sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
-  return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+  result= check_user(thd, COM_CONNECT, NULL, 0, thd->db, true);
+  emb_read_query_result(mysql);
+  return result;
 }
 
 #else
@@ -616,26 +718,147 @@
 }
 
 
+/*
+  creates new result and hooks it to the list
+
+  SYNOPSIS
+  alloc_new_dataset()
+
+  NOTES
+    allocs the MYSQL_DATA + embedded_query_result couple
+    to store the next query result,
+    links these two and attach it to the THD::data_tail
+
+  RETURN
+    pointer to the newly created query result
+*/
+
+MYSQL_DATA *THD::alloc_new_dataset()
+{
+  MYSQL_DATA *data;
+  struct embedded_query_result *emb_data;
+  if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+                       &data, sizeof(*data),
+                       &emb_data, sizeof(*emb_data),
+                       NULL))
+    return NULL;
+
+  emb_data->prev_ptr= &data->data;
+  cur_data= data;
+  *data_tail= data;
+  data_tail= &emb_data->next;
+  data->embedded_info= emb_data;
+  return data;
+}
+
+
+/*
+  stores server_status and warning_count in the current
+  query result structures
+
+  SYNOPSIS
+  write_eof_packet()
+  thd		current thread
+
+  NOTES
+    should be called to after we get the recordset-result
+
+*/
+
+static void write_eof_packet(THD *thd)
+{
+  /*
+    The following test should never be true, but it's better to do it
+    because if 'is_fatal_error' is set the server is not going to execute
+    other queries (see the if test in dispatch_command / COM_QUERY)
+  */
+  if (thd->is_fatal_error)
+    thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
+  thd->cur_data->embedded_info->server_status= thd->server_status;
+  /*
+    Don't send warn count during SP execution, as the warn_list
+    is cleared between substatements, and mysqltest gets confused
+  */
+  thd->cur_data->embedded_info->warning_count=
+    (thd->spcont ? 0 : min(thd->total_warn_count, 65535));
+}
+
+
+/*
+  allocs new query result and initialises Protocol::alloc
+
+  SYNOPSIS
+  Protocol::begin_dataset()
+
+  RETURN
+    0 if success
+    1 if memory allocation failed
+*/
+
+int Protocol::begin_dataset()
+{
+  MYSQL_DATA *data= thd->alloc_new_dataset();
+  if (!data)
+    return 1;
+  alloc= &data->alloc;
+  init_alloc_root(alloc,8192,0);	/* Assume rowlength < 8192 */
+  alloc->min_malloc=sizeof(MYSQL_ROWS);
+  return 0;
+}
+
+
+/*
+  remove last row of current recordset
+
+  SYNOPSIS
+  Protocol_simple::remove_last_row()
+
+  NOTES
+    does the loop from the beginning of the current recordset to
+    the last record and cuts it off.
+    Not supposed to be frequently called.
+*/
+
+void Protocol_simple::remove_last_row()
+{
+  MYSQL_DATA *data= thd->cur_data;
+  MYSQL_ROWS **last_row_hook= &data->data;
+  uint count= data->rows;
+  DBUG_ENTER("Protocol_simple::remove_last_row");
+  while (--count)
+    last_row_hook= &(*last_row_hook)->next;
+
+  *last_row_hook= 0;
+  data->embedded_info->prev_ptr= last_row_hook;
+  data->rows--;
+
+  DBUG_VOID_RETURN;
+}
+
+
 bool Protocol::send_fields(List<Item> *list, uint flags)
 {
   List_iterator_fast<Item> it(*list);
   Item                     *item;
   MYSQL_FIELD              *client_field;
-  MYSQL                    *mysql= thd->mysql;
   MEM_ROOT                 *field_alloc;
   CHARSET_INFO             *thd_cs= thd->variables.character_set_results;
   CHARSET_INFO             *cs= system_charset_info;
-  
+  MYSQL_DATA               *data;
   DBUG_ENTER("send_fields");
 
-  if (!mysql)            // bootstrap file handling
+  if (!thd->mysql)            // bootstrap file handling
     DBUG_RETURN(0);
 
-  field_count= list->elements;
-  field_alloc= &mysql->field_alloc;
-  if (!(client_field= thd->mysql->fields= 
-	(MYSQL_FIELD *)alloc_root(field_alloc, 
-				  sizeof(MYSQL_FIELD) * field_count)))
+  if (begin_dataset())
+    goto err;
+
+  data= thd->cur_data;
+  data->fields= field_count= list->elements;
+  field_alloc= &data->alloc;
+
+  if (!(client_field= data->embedded_info->fields_list= 
+	(MYSQL_FIELD*)alloc_root(field_alloc, sizeof(MYSQL_FIELD)*field_count)))
     goto err;
 
   while ((item= it++))
@@ -643,6 +866,10 @@
     Send_field server_field;
     item->make_field(&server_field);
 
+    /* Keep things compatible for old clients */
+    if (server_field.type == MYSQL_TYPE_VARCHAR)
+      server_field.type= MYSQL_TYPE_VAR_STRING;
+
     client_field->db= dup_str_aux(field_alloc, server_field.db_name,
                                   strlen(server_field.db_name), cs, thd_cs);
     client_field->table= dup_str_aux(field_alloc, server_field.table_name,
@@ -703,7 +930,9 @@
     client_field->max_length= 0;
     ++client_field;
   }
-  thd->mysql->field_count= field_count;
+
+  if (flags & SEND_EOF)
+    write_eof_packet(thd);
 
   DBUG_RETURN(prepare_for_send(list));
  err:
@@ -723,25 +952,11 @@
 bool Protocol_prep::write()
 {
   MYSQL_ROWS *cur;
-  MYSQL_DATA *data= thd->data;
-
-  if (!data)
-  {
-    if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
-					MYF(MY_WME | MY_ZEROFILL))))
-      return true;
-    
-    alloc= &data->alloc;
-    init_alloc_root(alloc,8192,0);	/* Assume rowlength < 8192 */
-    alloc->min_malloc=sizeof(MYSQL_ROWS);
-    data->rows=0;
-    data->fields=field_count;
-    data->prev_ptr= &data->data;
-    thd->data= data;
-  }
+  MYSQL_DATA *data= thd->cur_data;
 
   data->rows++;
-  if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+packet->length())))
+  if (!(cur= (MYSQL_ROWS *)alloc_root(alloc,
+                                      sizeof(MYSQL_ROWS)+packet->length())))
   {
     my_error(ER_OUT_OF_RESOURCES,MYF(0));
     return true;
@@ -750,8 +965,8 @@
   memcpy(cur->data, packet->ptr()+1, packet->length()-1);
   cur->length= packet->length();       /* To allow us to do sanity checks */
 
-  *data->prev_ptr= cur;
-  data->prev_ptr= &cur->next;
+  *data->embedded_info->prev_ptr= cur;
+  data->embedded_info->prev_ptr= &cur->next;
   cur->next= 0;
   
   return false;
@@ -761,46 +976,52 @@
 send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
 {
   DBUG_ENTER("send_ok");
-  MYSQL *mysql= current_thd->mysql;
+  MYSQL_DATA *data;
+  MYSQL *mysql= thd->mysql;
+  
   if (!mysql)            // bootstrap file handling
     DBUG_VOID_RETURN;
-  mysql->affected_rows= affected_rows;
-  mysql->insert_id= id;
+  if (thd->net.no_send_ok)	// hack for re-parsing queries
+    DBUG_VOID_RETURN;
+  if (!(data= thd->alloc_new_dataset()))
+    return;
+  data->embedded_info->affected_rows= affected_rows;
+  data->embedded_info->insert_id= id;
   if (message)
-  {
-    strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1);
-    mysql->info= thd->net.last_error;
-  }
+    strmake(data->embedded_info->info, message,
+            sizeof(data->embedded_info->info)-1);
+
+  write_eof_packet(thd);
+  thd->cur_data= 0;
   DBUG_VOID_RETURN;
 }
 
 void
 send_eof(THD *thd)
 {
+  write_eof_packet(thd);
+  thd->cur_data= 0;
 }
 
+
+void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+{
+  MYSQL_DATA *data= thd->cur_data ? thd->cur_data : thd->alloc_new_dataset();
+  struct embedded_query_result *ei= data->embedded_info;
+
+  ei->last_errno= sql_errno;
+  strmake(ei->info, err, sizeof(ei->info)-1);
+  strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno));
+  thd->cur_data= 0;
+}
+
+
 void Protocol_simple::prepare_for_resend()
 {
   MYSQL_ROWS *cur;
-  MYSQL_DATA *data= thd->data;
-
+  MYSQL_DATA *data= thd->cur_data;
   DBUG_ENTER("send_data");
 
-  if (!data)
-  {
-    if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
-					MYF(MY_WME | MY_ZEROFILL))))
-      goto err;
-    
-    alloc= &data->alloc;
-    init_alloc_root(alloc,8192,0);	/* Assume rowlength < 8192 */
-    alloc->min_malloc=sizeof(MYSQL_ROWS);
-    data->rows=0;
-    data->fields=field_count;
-    data->prev_ptr= &data->data;
-    thd->data= data;
-  }
-
   data->rows++;
   if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *))))
   {
@@ -809,10 +1030,10 @@
   }
   cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS));
 
-  *data->prev_ptr= cur;
-  data->prev_ptr= &cur->next;
+  *data->embedded_info->prev_ptr= cur;
+  data->embedded_info->prev_ptr= &cur->next;
   next_field=cur->data;
-  next_mysql_field= thd->mysql->fields;
+  next_mysql_field= data->embedded_info->fields_list;
 err:
   DBUG_VOID_RETURN;
 }

--- 1.66/libmysqld/libmysqld.c	Thu Aug  4 13:30:19 2005
+++ 1.67/libmysqld/libmysqld.c	Wed Jan  4 14:18:53 2006
@@ -14,6 +14,11 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+#include <my_global.h>
+#include <mysql.h>
+#include <mysql_embed.h>
+#include <mysqld_error.h>
+#include <my_pthread.h>
 #include "embedded_priv.h"
 #include <my_sys.h>
 #include <mysys_err.h>
@@ -193,7 +198,12 @@
 
   if (!user)
     user= "";
-  mysql->user=my_strdup(user,MYF(0));
+   /* 
+      We need to alloc some space for mysql->info but don't want to
+      put extra 'my_free's in mysql_close.
+      So we alloc it with the 'user' string to be freed at once
+   */
+  mysql->user= my_strdup(user, MYF(0));
 
   port=0;
   unix_socket=0;
@@ -207,6 +217,7 @@
   if (db)
     client_flag|=CLIENT_CONNECT_WITH_DB;
 
+  mysql->info_buffer= my_malloc(MYSQL_ERRMSG_SIZE, MYF(0));
   mysql->thd= create_embedded_thd(client_flag, db_name);
 
   init_embedded_mysql(mysql, client_flag, db_name);
@@ -243,7 +254,6 @@
   DBUG_RETURN(mysql);
 
 error:
-  embedded_get_error(mysql);
   DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno,
 		      mysql->net.last_error));
   {

--- 1.3/mysql-test/t/compress.test	Thu Oct 13 14:27:55 2005
+++ 1.4/mysql-test/t/compress.test	Wed Jan  4 14:18:53 2006
@@ -1,6 +1,9 @@
 # Turn on compression between the client and server
 # and run a number of tests
 
+# Can't test with embedded server
+-- source include/not_embedded.inc
+
 -- source include/have_compress.inc
 
 connect (comp_con,localhost,root,,,,,COMPRESS);

--- 1.4/mysql-test/t/mysql.test	Sat Oct  8 04:48:56 2005
+++ 1.5/mysql-test/t/mysql.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,5 @@
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
 #
 # Testing the MySQL command line client(mysql)
 #

--- 1.19/mysql-test/t/federated.test	Tue Nov  1 05:26:36 2005
+++ 1.20/mysql-test/t/federated.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,5 @@
+# should work with embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 source include/federated.inc;
 
 connection slave;

--- 1.3/mysql-test/t/sp-destruct.test	Fri Nov 25 20:09:18 2005
+++ 1.4/mysql-test/t/sp-destruct.test	Wed Jan  4 14:18:54 2006
@@ -35,10 +35,13 @@
 
 # Unsupported tampering with the mysql.proc definition
 alter table mysql.proc drop type;
+--replace_result $MYSQL_TEST_DIR .
 --error ER_SP_PROC_TABLE_CORRUPT
 call bug14233();
+--replace_result $MYSQL_TEST_DIR .
 --error ER_SP_PROC_TABLE_CORRUPT
 create view v1 as select bug14233_f();
+--replace_result $MYSQL_TEST_DIR .
 --error ER_SP_PROC_TABLE_CORRUPT
 insert into t1 values (0);
 

--- 1.100/mysql-test/t/sp-error.test	Wed Dec  7 15:36:31 2005
+++ 1.101/mysql-test/t/sp-error.test	Wed Jan  4 14:18:54 2006
@@ -648,28 +648,6 @@
 drop procedure bug3294|
 
 #
-# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
-#
---disable_warnings
-drop procedure if exists bug6807|
---enable_warnings
-create procedure bug6807()
-begin
-  declare id int;
-
-  set id = connection_id();
-  kill query id;
-  select 'Not reached';
-end|
-
---error 1317
-call bug6807()|
---error 1317
-call bug6807()|
-
-drop procedure bug6807|
-
-#
 # BUG#876: Stored Procedures: Invalid SQLSTATE is allowed in 
 #          a DECLARE ? HANDLER FOR stmt.
 #

--- 1.7/mysql-test/t/sp-threads.test	Thu Aug 11 02:17:50 2005
+++ 1.8/mysql-test/t/sp-threads.test	Wed Jan  4 14:18:54 2006
@@ -1,3 +1,5 @@
+# This test should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
 #
 # Testing stored procedures with multiple connections,
 # except security/privilege tests, they go to sp-security.test

--- 1.168/mysql-test/t/sp.test	Thu Dec 22 08:10:55 2005
+++ 1.169/mysql-test/t/sp.test	Wed Jan  4 14:18:54 2006
@@ -1368,11 +1368,11 @@
 call ifac(20)|
 select * from fac|
 drop table fac|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 show function status like '%f%'|
 drop procedure ifac|
 drop function fac|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 show function status like '%f%'|
 
 
@@ -1455,7 +1455,7 @@
   end while;
 end|
 show create procedure opp|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 show procedure status like '%p%'|
 
 # This isn't the fastest way in the world to compute prime numbers, so
@@ -1473,7 +1473,7 @@
 drop table primes|
 drop procedure opp|
 drop procedure ip|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 show procedure status like '%p%'|
 
 
@@ -1541,13 +1541,13 @@
 create procedure bar(x char(16), y int)
  comment "111111111111" sql security invoker
  insert into test.t1 values (x, y)|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 show procedure status like 'bar'|
 alter procedure bar comment "2222222222" sql security definer|
 alter procedure bar comment "3333333333"|
 alter procedure bar|
 show create procedure bar|
---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 show procedure status like 'bar'|
 drop procedure bar|
 
@@ -2497,7 +2497,6 @@
   show databases like 'foo';
   show errors;
   show columns from t1;
-  show grants for 'root'@'localhost';
   show keys from t1;
   show open tables like 'foo';
   show privileges;
@@ -2519,20 +2518,6 @@
 
 drop procedure bug4902|
 
-# We need separate SP for SHOW PROCESSLIST  since we want use replace_column
---disable_warnings
-drop procedure if exists bug4902_2|
---enable_warnings
-create procedure bug4902_2()
-begin
-  show processlist;
-end|
---replace_column 1 # 6 # 3 localhost
-call bug4902_2()|
---replace_column 1 # 6 # 3 localhost
-call bug4902_2()|
-drop procedure bug4902_2|
-
 #
 # BUG#4904
 #
@@ -2747,44 +2732,6 @@
 delete from t1|
 drop procedure bug4941|
 
-
-#
-# BUG#3583: query cache doesn't work for stored procedures
-#
---disable_warnings
-drop procedure if exists bug3583|
---enable_warnings
---disable_warnings
-drop procedure if exists bug3583|
---enable_warnings
-create procedure bug3583()
-begin
-  declare c int;
-
-  select * from t1;
-  select count(*) into c from t1;
-  select c;
-end|
-
-insert into t1 values ("x", 3), ("y", 5)|
-set @x = @@query_cache_size|
-set global query_cache_size = 10*1024*1024|
-
-flush status|
-flush query cache|
-show status like 'Qcache_hits'|
-call bug3583()|
-show status like 'Qcache_hits'|
-call bug3583()|
-call bug3583()|
-show status like 'Qcache_hits'|
-
-set global query_cache_size = @x|
-flush status|
-flush query cache|
-delete from t1|
-drop procedure bug3583|
-
 #
 # BUG#4905: Stored procedure doesn't clear for "Rows affected"
 #
@@ -3094,24 +3041,6 @@
 drop function bug5240|
 
 #
-# BUG#5278: Stored procedure packets out of order if SET PASSWORD.
-#
---disable_warnings
-drop function if exists bug5278|
---enable_warnings
-create function bug5278 () returns char
-begin
-  SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
-  return 'okay';
-end|
-
---error 1133
-select bug5278()|
---error 1133
-select bug5278()|
-drop function bug5278|
-
-#
 # BUG#7992: rolling back temporary Item tree changes in SP
 #
 --disable_warnings
@@ -4733,24 +4662,6 @@
 call bug10100t(5)|
 
 #end of the stack checking
-set @@max_sp_recursion_depth=255|
-set @var=1|
-#disable log because error about stack overrun contains numbers which
-#depend on a system
--- disable_result_log
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100p(255, @var)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pt(1,255)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pv(1,255)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pd(1,255)|
--- error ER_STACK_OVERRUN_NEED_MORE
-call bug10100pc(1,255)|
--- enable_result_log
-set @@max_sp_recursion_depth=0|
-
 deallocate prepare stmt2|
 
 drop function bug10100f|

--- 1.16/mysql-test/t/backup.test	Sat Dec  3 18:01:51 2005
+++ 1.17/mysql-test/t/backup.test	Wed Jan  4 14:18:53 2006
@@ -1,3 +1,6 @@
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
+
 #
 # This test is a bit tricky as we can't use backup table to overwrite an old
 # table

--- 1.25/mysql-test/t/handler.test	Wed Nov 16 13:13:05 2005
+++ 1.26/mysql-test/t/handler.test	Wed Jan  4 14:18:53 2006
@@ -2,6 +2,9 @@
 # test of HANDLER ...
 #
 
+# should work in embedded server after mysqltest is fixed
+-- source include/not_embedded.inc
+
 --disable_warnings
 drop table if exists t1;
 --enable_warnings

--- 1.157/sql/sql_prepare.cc	Mon Dec 12 23:55:13 2005
+++ 1.158/sql/sql_prepare.cc	Wed Jan  4 14:18:54 2006
@@ -92,6 +92,12 @@
   virtual bool send_fields(List<Item> &list, uint flags);
   virtual bool send_data(List<Item> &items);
   virtual bool send_eof();
+#ifdef EMBEDDED_LIBRARY
+  void begin_dataset()
+  {
+    protocol.begin_dataset();
+  }
+#endif
 };
 
 /******************************************************************************
@@ -524,9 +530,10 @@
 
 void set_param_datetime(Item_param *param, uchar **pos, ulong len)
 {
-  MYSQL_TIME *to= (MYSQL_TIME*)*pos;
+  MYSQL_TIME tm= *((MYSQL_TIME*)*pos);
+  tm.neg= 0;
 
-  param->set_time(to, MYSQL_TIMESTAMP_DATETIME,
+  param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME,
                   MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
 }
 
Thread
bk commit into 5.1 tree (holyfoot:1.1988)holyfoot4 Jan