List:Internals« Previous MessageNext Message »
From:Lars Thalmann Date:July 14 2005 9:21pm
Subject:bk commit into 5.1 tree (lars:1.1846)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of lars. When lars 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.1846 05/07/14 23:20:29 lars@stripped +22 -0
  Merge mysql.com:/home/bkroot/mysql-5.1
  into  mysql.com:/home/bk/w1697-5.1

  sql/sql_lex.h
    1.168 05/07/14 23:20:13 lars@stripped +0 -0
    Automerged

  sql/share/errmsg.txt
    1.24 05/07/14 23:20:12 lars@stripped +0 -1
    Automerged

  sql/rpl/slave.cc
    1.252 05/07/14 23:10:04 lars@stripped +0 -0
    Auto merged

  sql/sql_yacc.yy
    1.361 05/07/14 23:10:03 lars@stripped +0 -0
    Auto merged

  sql/sql_show.cc
    1.234 05/07/14 23:10:02 lars@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.456 05/07/14 23:10:01 lars@stripped +0 -0
    Auto merged

  sql/sql_load.cc
    1.82 05/07/14 23:10:00 lars@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.247 05/07/14 23:10:00 lars@stripped +0 -0
    Auto merged

  sql/sql_class.cc
    1.170 05/07/14 23:10:00 lars@stripped +0 -0
    Auto merged

  sql/sql_acl.h
    1.39 05/07/14 23:09:59 lars@stripped +0 -0
    Auto merged

  sql/set_var.cc
    1.124 05/07/14 23:09:59 lars@stripped +0 -0
    Auto merged

  sql/mysqld.cc
    1.452 05/07/14 23:09:59 lars@stripped +0 -0
    Auto merged

  sql/log_event.h
    1.112 05/07/14 23:09:58 lars@stripped +0 -0
    Auto merged

  sql/log_event.cc
    1.180 05/07/14 23:09:58 lars@stripped +0 -0
    Auto merged

  sql/log.cc
    1.164 05/07/14 23:09:57 lars@stripped +0 -0
    Auto merged

  sql/lex.h
    1.138 05/07/14 23:09:57 lars@stripped +0 -0
    Auto merged

  sql/item_func.h
    1.111 05/07/14 23:09:57 lars@stripped +0 -0
    Auto merged

  sql/item_func.cc
    1.187 05/07/14 23:09:56 lars@stripped +0 -0
    Auto merged

  sql/ha_innodb.cc
    1.203 05/07/14 23:09:56 lars@stripped +0 -0
    Auto merged

  sql/rpl/slave.cc
    1.242.5.2 05/07/14 23:09:55 lars@stripped +0 -0
    Merge rename: sql/slave.cc -> sql/rpl/slave.cc

  sql/Makefile.am
    1.108 05/07/14 23:09:55 lars@stripped +0 -0
    Auto merged

  mysql-test/t/rpl_until.test
    1.18 05/07/14 23:09:55 lars@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.sh
    1.264 05/07/14 23:09:55 lars@stripped +0 -0
    Auto merged

# 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:	lars
# Host:	dhcppc0.ver
# Root:	/home/bk/w1697-5.1/RESYNC

--- 1.263/mysql-test/mysql-test-run.sh	2005-07-14 22:57:45 +02:00
+++ 1.264/mysql-test/mysql-test-run.sh	2005-07-14 23:09:55 +02:00
@@ -307,7 +307,7 @@
      --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
      --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem \
      --ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem"
-     MYSQL_TEST_SSL_OPTS="--ssl-ca=$BASEDIR/SSL/cacert.pem \
+     MYSQL_TEST_SSL_OPTS="--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
      --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem \
      --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem" ;;
     --no-manager | --skip-manager) USE_MANAGER=0 ;;
@@ -707,6 +707,9 @@
 if [ "x$USE_EMBEDDED_SERVER" = "x1" ]; then
   MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST -A --language=$LANGUAGE -A --datadir=$SLAVE_MYDDIR -A --character-sets-dir=$CHARSETSDIR"
 fi
+# Save path and name of mysqldump
+MYSQL_DUMP_DIR="$MYSQL_DUMP"
+export MYSQL_DUMP_DIR
 MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
 MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT"
 MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR  --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"

--- 1.107/sql/Makefile.am	2005-06-22 12:43:20 +02:00
+++ 1.108/sql/Makefile.am	2005-07-14 23:09:55 +02:00
@@ -21,8 +21,8 @@
 MYSQLBASEdir=		$(prefix)
 INCLUDES =		@ZLIB_INCLUDES@ \
 			@bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \
-			-I$(top_srcdir)/include -I$(top_srcdir)/regex \
-			-I$(srcdir) $(openssl_includes) -I$(top_builddir)/include
+			-I$(top_builddir)/include -I$(top_srcdir)/include \
+			-I$(top_srcdir)/regex -I$(srcdir) $(openssl_includes)
 WRAPLIBS=		@WRAPLIBS@
 SUBDIRS =		share
 libexec_PROGRAMS =	mysqld

--- 1.186/sql/item_func.cc	2005-07-14 22:57:47 +02:00
+++ 1.187/sql/item_func.cc	2005-07-14 23:09:56 +02:00
@@ -195,11 +195,10 @@
       ((Item_field *)(*arg))->no_const_subst= 1;
     /*
       We do not check conv->fixed, because Item_func_conv_charset which can
-      be return by safe_charset_converter can't be fixed at creation, also
-      it do not need tables (second argument) for name resolving
+      be return by safe_charset_converter can't be fixed at creation
     */
     *arg= conv;
-    conv->fix_fields(thd, 0, arg);
+    conv->fix_fields(thd, arg);
   }
   if (arena)
     thd->restore_backup_item_arena(arena, &backup);
@@ -262,7 +261,6 @@
   SYNOPSIS:
   fix_fields()
   thd		Thread object
-  tables	List of all open tables involved in the query
   ref		Pointer to where this object is used.  This reference
 		is used if we want to replace this object with another
 		one (for example in the summary functions).
@@ -291,7 +289,7 @@
 */
 
 bool
-Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_func::fix_fields(THD *thd, Item **ref)
 {
   DBUG_ASSERT(fixed == 0);
   Item **arg,**arg_end;
@@ -313,7 +311,7 @@
 	We can't yet set item to *arg as fix_fields may change *arg
 	We shouldn't call fix_fields() twice, so check 'fixed' field first
       */
-      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
+      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
 	return TRUE;				/* purecov: inspected */
       item= *arg;
 
@@ -569,6 +567,17 @@
 }
 
 
+my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
+{
+  DBUG_ASSERT(fixed);
+  double nr= val_real();
+  if (null_value)
+    return 0; /* purecov: inspected */
+  double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
+  return decimal_value;
+}
+
+
 void Item_func::fix_num_length_and_dec()
 {
   decimals= 0;
@@ -1883,8 +1892,7 @@
     return;
   }
   
-  switch (args[0]->result_type())
-  {
+  switch (args[0]->result_type()) {
   case REAL_RESULT:
   case STRING_RESULT:
     hybrid_type= REAL_RESULT;
@@ -1892,16 +1900,17 @@
     max_length= float_length(decimals);
     break;
   case INT_RESULT:
-    if ((decimals_to_set==0) &&
+    if (!decimals_to_set &&
         (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)))
     {
+      int length_can_increase= test(!truncate && (args[1]->val_int() < 0));
+      max_length= args[0]->max_length + length_can_increase;
       /* Here we can keep INT_RESULT */
       hybrid_type= INT_RESULT;
-      int length_can_increase= !truncate && (args[1]->val_int() < 0);
-      max_length= args[0]->max_length + length_can_increase;
       decimals= 0;
       break;
     }
+    /* fall through */
   case DECIMAL_RESULT:
   {
     hybrid_type= DECIMAL_RESULT;
@@ -2011,10 +2020,9 @@
 }
 
 
-bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
-                                Item **ref)
+bool Item_func_rand::fix_fields(THD *thd,Item **ref)
 {
-  if (Item_real_func::fix_fields(thd, tables, ref))
+  if (Item_real_func::fix_fields(thd, ref))
     return TRUE;
   used_tables_cache|= RAND_TABLE_BIT;
   if (arg_count)
@@ -2605,7 +2613,7 @@
 
 
 bool
-udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
+udf_handler::fix_fields(THD *thd, Item_result_field *func,
 			uint arg_count, Item **arguments)
 {
 #ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
@@ -2647,7 +2655,7 @@
 	 arg++,i++)
     {
       if (!(*arg)->fixed &&
-          (*arg)->fix_fields(thd, tables, arg))
+          (*arg)->fix_fields(thd, arg))
 	DBUG_RETURN(1);
       // we can't assign 'item' before, because fix_fields() can change arg
       Item *item= *arg;
@@ -3472,12 +3480,11 @@
   SELECT @a:= ).
 */
 
-bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
-					Item **ref)
+bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
 {
   DBUG_ASSERT(fixed == 0);
   /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
-  if (Item_func::fix_fields(thd, tables, ref) ||
+  if (Item_func::fix_fields(thd, ref) ||
       !(entry= get_variable(&thd->user_vars, name, 1)))
     return TRUE;
   /* 
@@ -4141,11 +4148,10 @@
 }
 
 
-bool Item_user_var_as_out_param::fix_fields(THD *thd, TABLE_LIST *tables,
-                                            Item **ref)
+bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
 {
   DBUG_ASSERT(fixed == 0);
-  if (Item::fix_fields(thd, tables, ref) ||
+  if (Item::fix_fields(thd, ref) ||
       !(entry= get_variable(&thd->user_vars, name, 1)))
     return TRUE;
   entry->type= STRING_RESULT;
@@ -4328,7 +4334,7 @@
 }
 
 
-bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
+bool Item_func_match::fix_fields(THD *thd, Item **ref)
 {
   DBUG_ASSERT(fixed == 0);
   Item *item;
@@ -4343,7 +4349,7 @@
     modifications to find_best and auto_close as complement to auto_init code
     above.
    */
-  if (Item_func::fix_fields(thd, tlist, ref) ||
+  if (Item_func::fix_fields(thd, ref) ||
       !args[0]->const_during_execution())
   {
     my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
@@ -4465,7 +4471,8 @@
 
 bool Item_func_match::eq(const Item *item, bool binary_cmp) const
 {
-  if (item->type() != FUNC_ITEM || ((Item_func*)item)->functype() != FT_FUNC ||
+  if (item->type() != FUNC_ITEM ||
+      ((Item_func*)item)->functype() != FT_FUNC ||
       flags != ((Item_func_match*)item)->flags)
     return 0;
 
@@ -4704,8 +4711,9 @@
 }
 
 
-Item_func_sp::Item_func_sp(sp_name *name)
-  :Item_func(), m_name(name), m_sp(NULL), result_field(NULL)
+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
+  :Item_func(), context(context_arg), m_name(name), m_sp(NULL),
+   result_field(NULL)
 {
   maybe_null= 1;
   m_name->init_qname(current_thd);
@@ -4713,8 +4721,10 @@
 }
 
 
-Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
-  :Item_func(list), m_name(name), m_sp(NULL), result_field(NULL)
+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
+                           sp_name *name, List<Item> &list)
+  :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),
+   result_field(NULL)
 {
   maybe_null= 1;
   m_name->init_qname(current_thd);
@@ -4729,6 +4739,7 @@
     delete result_field;
     result_field= NULL;
   }
+  m_sp= NULL;
   Item_func::cleanup();
 }
 
@@ -4821,42 +4832,36 @@
   DBUG_ENTER("Item_func_sp::execute");
   THD *thd= current_thd;
   ulong old_client_capabilites;
-  int res;
+  int res= -1;
   bool save_in_sub_stmt= thd->transaction.in_sub_stmt;
+  my_bool save_no_send_ok;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   st_sp_security_context save_ctx;
 #endif
 
-  if (! m_sp)
+  if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE)))
   {
-    if (!(m_sp= sp_find_function(thd, m_name, TRUE)))
-    {
-      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
-      DBUG_RETURN(-1);
-    }
+    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+    goto error;
   }
 
   old_client_capabilites= thd->client_capabilities;
   thd->client_capabilities &= ~CLIENT_MULTI_RESULTS;
 
 #ifndef EMBEDDED_LIBRARY
-  my_bool nsok= thd->net.no_send_ok;
+  save_no_send_ok= thd->net.no_send_ok;
   thd->net.no_send_ok= TRUE;
 #endif
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   if (check_routine_access(thd, EXECUTE_ACL, 
 			   m_sp->m_db.str, m_sp->m_name.str, 0, 0))
-      DBUG_RETURN(-1);
+    goto error_check;
   sp_change_security_context(thd, m_sp, &save_ctx);
   if (save_ctx.changed && 
       check_routine_access(thd, EXECUTE_ACL, 
 			   m_sp->m_db.str, m_sp->m_name.str, 0, 0))
-  {
-    sp_restore_security_context(thd, m_sp, &save_ctx);
-    thd->client_capabilities|= old_client_capabilites &  CLIENT_MULTI_RESULTS;
-    DBUG_RETURN(-1);
-  }
+    goto error_check_ctx;
 #endif
   /*
     Like for SPs, we don't binlog the substatements. If the statement which
@@ -4864,6 +4869,7 @@
     it's not (e.g. SELECT myfunc()) it won't be binlogged (documented known
     problem).
   */
+
   tmp_disable_binlog(thd); /* don't binlog the substatements */
   thd->transaction.in_sub_stmt= TRUE;
 
@@ -4879,15 +4885,20 @@
 		 ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
+error_check_ctx:
   sp_restore_security_context(thd, m_sp, &save_ctx);
 #endif
 
+  thd->client_capabilities|= old_client_capabilites &  CLIENT_MULTI_RESULTS;
+
+error_check:
 #ifndef EMBEDDED_LIBRARY
-  thd->net.no_send_ok= nsok;
+  thd->net.no_send_ok= save_no_send_ok;
 #endif
 
   thd->client_capabilities|= old_client_capabilites &  CLIENT_MULTI_RESULTS;
 
+error:
   DBUG_RETURN(res);
 }
 
@@ -4958,7 +4969,10 @@
   }
 
   if (!(field= sp_result_field()))
+  {
+    context->process_error(current_thd);
     DBUG_VOID_RETURN;
+  }
   decimals= field->decimals();
   max_length= field->field_length;
   maybe_null= 1;

--- 1.110/sql/item_func.h	2005-07-14 22:57:47 +02:00
+++ 1.111/sql/item_func.h	2005-07-14 23:09:57 +02:00
@@ -116,7 +116,7 @@
   Item_func(List<Item> &list);
   // Constructor used for Item_cond_and/or (see Item comment)
   Item_func(THD *thd, Item_func *item);
-  bool fix_fields(THD *,struct st_table_list *, Item **ref);
+  bool fix_fields(THD *, Item **ref);
   table_map used_tables() const;
   table_map not_null_tables() const;
   void update_used_tables();
@@ -187,6 +187,7 @@
   Item_real_func(Item *a,Item *b) :Item_func(a,b) {}
   Item_real_func(List<Item> &list) :Item_func(list) {}
   String *val_str(String*str);
+  my_decimal *val_decimal(my_decimal *decimal_value);
   longlong val_int()
     { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); }
   enum Item_result result_type () const { return REAL_RESULT; }
@@ -630,7 +631,7 @@
   const char *func_name() const { return "rand"; }
   bool const_item() const { return 0; }
   void update_used_tables();
-  bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
+  bool fix_fields(THD *thd, Item **ref);
 };
 
 
@@ -885,14 +886,15 @@
   udf_handler udf;
 
 public:
-  Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {}
+  Item_udf_func(udf_func *udf_arg)
+    :Item_func(), udf(udf_arg) {}
   Item_udf_func(udf_func *udf_arg, List<Item> &list)
     :Item_func(list), udf(udf_arg) {}
   const char *func_name() const { return udf.name(); }
-  bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
+  bool fix_fields(THD *thd, Item **ref)
   {
     DBUG_ASSERT(fixed == 0);
-    bool res= udf.fix_fields(thd, tables, this, arg_count, args);
+    bool res= udf.fix_fields(thd, this, arg_count, args);
     used_tables_cache= udf.used_tables_cache;
     const_item_cache= udf.const_item_cache;
     fixed= 1;
@@ -907,9 +909,11 @@
 class Item_func_udf_float :public Item_udf_func
 {
  public:
-  Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
-  Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
-    :Item_udf_func(udf_arg,list) {}
+  Item_func_udf_float(udf_func *udf_arg)
+    :Item_udf_func(udf_arg) {}
+  Item_func_udf_float(udf_func *udf_arg,
+                      List<Item> &list)
+    :Item_udf_func(udf_arg, list) {}
   longlong val_int()
   {
     DBUG_ASSERT(fixed == 1);
@@ -932,9 +936,11 @@
 class Item_func_udf_int :public Item_udf_func
 {
 public:
-  Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
-  Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
-    :Item_udf_func(udf_arg,list) {}
+  Item_func_udf_int(udf_func *udf_arg)
+    :Item_udf_func(udf_arg) {}
+  Item_func_udf_int(udf_func *udf_arg,
+                    List<Item> &list)
+    :Item_udf_func(udf_arg, list) {}
   longlong val_int();
   double val_real() { return (double) Item_func_udf_int::val_int(); }
   String *val_str(String *str);
@@ -946,9 +952,10 @@
 class Item_func_udf_decimal :public Item_udf_func
 {
 public:
-  Item_func_udf_decimal(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
+  Item_func_udf_decimal(udf_func *udf_arg)
+    :Item_udf_func(udf_arg) {}
   Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
-    :Item_udf_func(udf_arg,list) {}
+    :Item_udf_func(udf_arg, list) {}
   longlong val_int();
   double val_real();
   my_decimal *val_decimal(my_decimal *);
@@ -961,9 +968,10 @@
 class Item_func_udf_str :public Item_udf_func
 {
 public:
-  Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
+  Item_func_udf_str(udf_func *udf_arg)
+    :Item_udf_func(udf_arg) {}
   Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
-    :Item_udf_func(udf_arg,list) {}
+    :Item_udf_func(udf_arg, list) {}
   String *val_str(String *);
   double val_real()
   {
@@ -998,8 +1006,10 @@
 class Item_func_udf_float :public Item_real_func
 {
  public:
-  Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
-  Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {}
+  Item_func_udf_float(udf_func *udf_arg)
+    :Item_real_func() {}
+  Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
+    :Item_real_func(list) {}
   double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
 };
 
@@ -1007,8 +1017,10 @@
 class Item_func_udf_int :public Item_int_func
 {
 public:
-  Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {}
-  Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
+  Item_func_udf_int(udf_func *udf_arg)
+    :Item_int_func() {}
+  Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
+    :Item_int_func(list) {}
   longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
 };
 
@@ -1016,8 +1028,10 @@
 class Item_func_udf_decimal :public Item_int_func
 {
 public:
-  Item_func_udf_decimal(udf_func *udf_arg) :Item_int_func() {}
-  Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
+  Item_func_udf_decimal(udf_func *udf_arg)
+    :Item_int_func() {}
+  Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
+    :Item_int_func(list) {}
   my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
 };
 
@@ -1025,8 +1039,10 @@
 class Item_func_udf_str :public Item_func
 {
 public:
-  Item_func_udf_str(udf_func *udf_arg) :Item_func() {}
-  Item_func_udf_str(udf_func *udf_arg, List<Item> &list)  :Item_func(list) {}
+  Item_func_udf_str(udf_func *udf_arg)
+    :Item_func() {}
+  Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
+    :Item_func(list) {}
   String *val_str(String *)
     { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
   double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
@@ -1131,7 +1147,7 @@
   bool check();
   bool update();
   enum Item_result result_type () const { return cached_result_type; }
-  bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
+  bool fix_fields(THD *thd, Item **ref);
   void fix_length_and_dec();
   void print(String *str);
   void print_as_stmt(String *str);
@@ -1191,7 +1207,7 @@
   String *val_str(String *str);
   my_decimal *val_decimal(my_decimal *decimal_buffer);
   /* fix_fields() binds variable name with its entry structure */
-  bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
+  bool fix_fields(THD *thd, Item **ref);
   void print(String *str);
   void set_null_value(CHARSET_INFO* cs);
   void set_value(const char *str, uint length, CHARSET_INFO* cs);
@@ -1245,7 +1261,7 @@
   const char *func_name() const { return "match"; }
   void update_used_tables() {}
   table_map not_null_tables() const { return 0; }
-  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
+  bool fix_fields(THD *thd, Item **ref);
   bool eq(const Item *, bool binary_cmp) const;
   /* The following should be safe, even if we compare doubles */
   longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; }
@@ -1317,6 +1333,7 @@
 class Item_func_sp :public Item_func
 {
 private:
+  Name_resolution_context *context;
   sp_name *m_name;
   mutable sp_head *m_sp;
   TABLE *dummy_table;
@@ -1329,9 +1346,10 @@
 
 public:
 
-  Item_func_sp(sp_name *name);
+  Item_func_sp(Name_resolution_context *context_arg, sp_name *name);
 
-  Item_func_sp(sp_name *name, List<Item> &list);
+  Item_func_sp(Name_resolution_context *context_arg,
+               sp_name *name, List<Item> &list);
 
   virtual ~Item_func_sp()
   {}
@@ -1375,6 +1393,9 @@
       return NULL;
     return result_field->val_str(str);
   }
+
+  virtual bool change_context_processor(byte *cntx)
+    { context= (Name_resolution_context *)cntx; return FALSE; }
 
   void fix_length_and_dec();
 

--- 1.137/sql/lex.h	2005-03-22 10:44:30 +01:00
+++ 1.138/sql/lex.h	2005-07-14 23:09:57 +02:00
@@ -214,7 +214,9 @@
   { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
   { "GET_FORMAT",       SYM(GET_FORMAT)},
   { "GLOBAL",		SYM(GLOBAL_SYM)},
+#ifdef SP_GOTO
   { "GOTO",             SYM(GOTO_SYM)},
+#endif
   { "GRANT",		SYM(GRANT)},
   { "GRANTS",	        SYM(GRANTS)},
   { "GROUP",		SYM(GROUP)},
@@ -262,7 +264,10 @@
   { "KEY",		SYM(KEY_SYM)},
   { "KEYS",		SYM(KEYS)},
   { "KILL",		SYM(KILL_SYM)},
+#ifdef SP_GOTO
+  /* QQ This will go away when the GOTO label syntax is fixed */
   { "LABEL",            SYM(LABEL_SYM)},
+#endif
   { "LANGUAGE",         SYM(LANGUAGE_SYM)},
   { "LAST",		SYM(LAST_SYM)},
   { "LEADING",		SYM(LEADING)},

--- 1.163/sql/log.cc	2005-06-20 17:10:40 +02:00
+++ 1.164/sql/log.cc	2005-07-14 23:09:57 +02:00
@@ -1155,6 +1155,9 @@
       */
       if (my_stat(log_info.log_file_name,&s,MYF(0)))
         file_size= s.st_size;
+      else
+	sql_print_information("Failed to execute my_stat on file '%s'",
+			      log_info.log_file_name);
     }
     /*
       It's not fatal if we can't delete a log file ;

--- 1.179/sql/log_event.cc	2005-07-14 22:57:47 +02:00
+++ 1.180/sql/log_event.cc	2005-07-14 23:09:58 +02:00
@@ -2621,13 +2621,15 @@
 
 #ifndef MYSQL_CLIENT
 void Load_log_event::set_fields(const char* affected_db, 
-				List<Item> &field_list)
+				List<Item> &field_list,
+                                Name_resolution_context *context)
 {
   uint i;
   const char* field = fields;
   for (i= 0; i < num_fields; i++)
   {
-    field_list.push_back(new Item_field(affected_db, table_name, field));
+    field_list.push_back(new Item_field(context,
+                                        affected_db, table_name, field));
     field+= field_lens[i]  + 1;
   }
 }
@@ -2750,7 +2752,9 @@
       thd->query= load_data_query;
 
       if (sql_ex.opt_flags & REPLACE_FLAG)
+      {
 	handle_dup= DUP_REPLACE;
+      }
       else if (sql_ex.opt_flags & IGNORE_FLAG)
       {
         ignore= 1;
@@ -2792,7 +2796,8 @@
 
       ex.skip_lines = skip_lines;
       List<Item> field_list;
-      set_fields(thd->db,field_list);
+      thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
+      set_fields(thd->db, field_list, &thd->main_lex.select_lex.context);
       thd->variables.pseudo_thread_id= thread_id;
       List<Item> set_fields;
       if (net)
@@ -3620,7 +3625,7 @@
     Item_func_set_user_var can't substitute something else on its place =>
     0 can be passed as last argument (reference on item)
   */
-  e.fix_fields(thd, 0, 0);
+  e.fix_fields(thd, 0);
   /*
     A variable can just be considered as a table with
     a single record and with a single column. Thus, like

--- 1.111/sql/log_event.h	2005-06-20 17:10:42 +02:00
+++ 1.112/sql/log_event.h	2005-07-14 23:09:58 +02:00
@@ -875,7 +875,8 @@
 		 const char* table_name_arg,
 		 List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
 		 bool using_trans);
-  void set_fields(const char* db, List<Item> &fields_arg);
+  void set_fields(const char* db, List<Item> &fields_arg,
+                  Name_resolution_context *context);
   const char* get_db() { return db; }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);

--- 1.451/sql/mysqld.cc	2005-07-14 22:57:48 +02:00
+++ 1.452/sql/mysqld.cc	2005-07-14 23:09:59 +02:00
@@ -142,6 +142,7 @@
 #define zVOLSTATE_DEACTIVE 2
 #define zVOLSTATE_MAINTENANCE 3
 
+#include <nks/netware.h>
 #include <nks/vm.h>
 #include <library.h>
 #include <monitor.h>
@@ -3013,14 +3014,15 @@
 #endif
 
 #ifdef	__WIN__
-/* Before performing any socket operation (like retrieving hostname */
-/* in init_common_variables we have to call WSAStartup              */
-  if (!opt_disable_networking)
+  /*
+    Before performing any socket operation (like retrieving hostname
+    in init_common_variables we have to call WSAStartup
+  */
   {
     WSADATA WsaData;
     if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
     {
-      /* errors are not read yet, so we use test here */
+      /* errors are not read yet, so we use english text here */
       my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
       unireg_abort(1);
     }
@@ -4453,7 +4455,7 @@
    (gptr*) &default_collation_name, (gptr*) &default_collation_name,
    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
   {"default-storage-engine", OPT_STORAGE_ENGINE,
-   "Set the default storage engine (table tyoe) for tables.", 0, 0,
+   "Set the default storage engine (table type) for tables.", 0, 0,
    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default-table-type", OPT_STORAGE_ENGINE,
    "(deprecated) Use --default-storage-engine.", 0, 0,
@@ -5371,7 +5373,7 @@
    "Default pointer size to be used for MyISAM tables.",
    (gptr*) &myisam_data_pointer_size,
    (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG,
-   6, 2, 8, 0, 1, 0},
+   6, 2, 7, 0, 1, 0},
   {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
    "Deprecated option",
    (gptr*) &global_system_variables.myisam_max_extra_sort_file_size,
@@ -6313,9 +6315,6 @@
 #endif /* HAVE_REPLICATION */
   case (int) OPT_SLOW_QUERY_LOG:
     opt_slow_log=1;
-    break;
-  case (int) OPT_LOG_SLOW_ADMIN_STATEMENTS:
-    opt_log_slow_admin_statements= 1;
     break;
   case (int) OPT_SKIP_NEW:
     opt_specialflag|= SPECIAL_NO_NEW_FUNC;

--- 1.242.5.1/sql/slave.cc	2005-07-13 13:11:48 +02:00
+++ 1.252/sql/rpl/slave.cc	2005-07-14 23:10:04 +02:00
@@ -20,77 +20,67 @@
 
 #include <mysql.h>
 #include <myisam.h>
-#include "slave.h"
-#include "sql_repl.h"
-#include "rpl_filter.h"
+#include <rpl/slave.h>
+#include <rpl/mic.h>
+#include <rpl/master.h>
 #include "repl_failsafe.h"
 #include <thr_alarm.h>
 #include <my_dir.h>
 #include <sql_common.h>
 
-#define MAX_SLAVE_RETRY_PAUSE 5
 bool use_slave_mask = 0;
 MY_BITMAP slave_error_mask;
 
 typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
 
-volatile bool slave_sql_running = 0, slave_io_running = 0;
-char* slave_load_tmpdir = 0;
-MASTER_INFO *active_mi;
-bool replicate_same_server_id;
-ulonglong relay_log_space_limit = 0;
+/* Replication options - Applies to all subslaves */
 
-/*
-  When slave thread exits, we need to remember the temporary tables so we
-  can re-use them on slave start.
+bool      opt_replicate_same_server_id;
+char      *opt_slave_load_tmpdir= 0;
+ulonglong opt_relay_log_space_limit= 0;
 
-  TODO: move the vars below under MASTER_INFO
-*/
+/* Replication options - Used by mysql-test for debugging and testing */
+
+int       opt_disconnect_slave_event_count= 0;
+int       opt_abort_slave_event_count= 0;
 
-int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
-int events_till_abort = -1;
-static int events_till_disconnect = -1;
-
-typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
-
-static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev);
-static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
-static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli);
-static inline bool io_slave_killed(THD* thd,MASTER_INFO* mi);
-static inline bool sql_slave_killed(THD* thd,RELAY_LOG_INFO* rli);
-static int count_relay_log_space(RELAY_LOG_INFO* rli);
+typedef enum {SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
+
+static int process_io_rotate(Master_info* mi, Rotate_log_event* rev);
+static int process_io_create_file(Master_info* mi, Create_file_log_event* cev);
+static bool wait_for_relay_log_space(Relay_log_info* rli);
+static inline bool io_slave_killed(THD* thd,Master_info* mi);
 static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type);
-static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			  bool suppress_warnings);
-static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			     bool reconnect, bool suppress_warnings);
-static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
-		      void* thread_killed_arg);
+static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi);
+static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi,
+                          bool suppress_warnings);
+static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
+                             bool reconnect, bool suppress_warnings);
 static int request_table_dump(MYSQL* mysql, const char* db, const char* table);
 static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
-				  const char* table_name, bool overwrite);
-static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi);
+                                  const char* table_name, bool overwrite);
+static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi);
+int queue_event(Master_info* mi, const char* buf, ulong event_len);
 
 /*
-  Find out which replications threads are running
+  Find out which replication threads are running
 
   SYNOPSIS
     init_thread_mask()
-    mask		Return value here
-    mi			master_info for slave
-    inverse		If set, returns which threads are not running
+    mask                Return value here
+    mi                  master_info for slave
+    inverse             If set, returns which threads are not running
 
   IMPLEMENTATION
     Get a bit mask for which threads are running so that we can later restart
     these threads.
 
   RETURN
-    mask	If inverse == 0, running threads
-		If inverse == 1, stopped threads    
+    mask        If inverse == 0, running threads
+                If inverse == 1, stopped threads    
 */
 
-void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse)
+void init_thread_mask(int* mask, Master_info* mi, bool inverse)
 {
   bool set_io = mi->slave_running, set_sql = mi->rli.slave_running;
   register int tmp_mask=0;
@@ -104,307 +94,72 @@
 }
 
 
-/*
-  lock_slave_threads()
-*/
-
-void lock_slave_threads(MASTER_INFO* mi)
-{
-  //TODO: see if we can do this without dual mutex
-  pthread_mutex_lock(&mi->run_lock);
-  pthread_mutex_lock(&mi->rli.run_lock);
-}
+/* 
+   init_slave()
 
+   This function is called when mysqld starts and before client
+   connections are accepted.
 
-/*
-  unlock_slave_threads()
+   - Initialize slave structures for all named_masters that have info files
+   - Start slave threads for these named_masters
 */
-
-void unlock_slave_threads(MASTER_INFO* mi)
-{
-  //TODO: see if we can do this without dual mutex
-  pthread_mutex_unlock(&mi->rli.run_lock);
-  pthread_mutex_unlock(&mi->run_lock);
-}
-
-
-/* Initialize slave structures */
-
 int init_slave()
 {
+  Master_info *mi;
   DBUG_ENTER("init_slave");
 
   /*
-    This is called when mysqld starts. Before client connections are
-    accepted. However bootstrap may conflict with us if it does START SLAVE.
-    So it's safer to take the lock.
+    This function is called when mysqld starts and before client
+    connections are accepted.  However, bootstrap may conflict with us
+    if it does START SLAVE.  So it's safer to take the lock.
   */
   pthread_mutex_lock(&LOCK_active_mi);
-  /*
-    TODO: re-write this to interate through the list of files
-    for multi-master
-  */
-  active_mi= new MASTER_INFO;
-
-  /*
-    If master_host is not specified, try to read it from the master_info file.
-    If master_host is specified, create the master_info file if it doesn't
-    exists.
-  */
-  if (!active_mi)
-  {
-    sql_print_error("Failed to allocate memory for the master info structure");
-    goto err;
-  }
 
-  if (init_master_info(active_mi,master_info_file,relay_log_info_file,
-		       !master_host, (SLAVE_IO | SLAVE_SQL)))
+  /* Rename files (master.info -> default-master.info, etc) */
+  if (mic.upgrade51())
   {
-    sql_print_error("Failed to initialize the master info structure");
-    goto err;
+    sql_print_error("Upgrade to 5.1 failed.");
+    exit(1);
   }
 
-  if (server_id && !master_host && active_mi->host[0])
-    master_host= active_mi->host;
-
-  /* If server id is not set, start_slave_thread() will say it */
-
-  if (master_host && !opt_skip_slave_start)
+  /* Initialize Master_info:s from storage */
+  if (mic.init(mysql_data_home))
   {
-    if (start_slave_threads(1 /* need mutex */,
-			    0 /* no wait for start*/,
-			    active_mi,
-			    master_info_file,
-			    relay_log_info_file,
-			    SLAVE_IO | SLAVE_SQL))
-    {
-      sql_print_error("Failed to create slave threads");
-      goto err;
-    }
-  }
-  pthread_mutex_unlock(&LOCK_active_mi);
-  DBUG_RETURN(0);
-
-err:
-  pthread_mutex_unlock(&LOCK_active_mi);
-  DBUG_RETURN(1);
-}
-
-
-/*
-  Open the given relay log
-
-  SYNOPSIS
-    init_relay_log_pos()
-    rli			Relay information (will be initialized)
-    log			Name of relay log file to read from. NULL = First log
-    pos			Position in relay log file 
-    need_data_lock	Set to 1 if this functions should do mutex locks
-    errmsg		Store pointer to error message here
-    look_for_description_event 
-                        1 if we should look for such an event. We only need
-                        this when the SQL thread starts and opens an existing
-                        relay log and has to execute it (possibly from an
-                        offset >4); then we need to read the first event of
-                        the relay log to be able to parse the events we have
-                        to execute.
-
-  DESCRIPTION
-  - Close old open relay log files.
-  - If we are using the same relay log as the running IO-thread, then set
-    rli->cur_log to point to the same IO_CACHE entry.
-  - If not, open the 'log' binary file.
-
-  TODO
-    - check proper initialization of group_master_log_name/group_master_log_pos
-
-  RETURN VALUES
-    0	ok
-    1	error.  errmsg is set to point to the error message
-*/
-
-int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
-		       ulonglong pos, bool need_data_lock,
-		       const char** errmsg,
-                       bool look_for_description_event)
-{
-  DBUG_ENTER("init_relay_log_pos");
-  DBUG_PRINT("info", ("pos=%lu", pos));
-
-  *errmsg=0;
-  pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
-  
-  if (need_data_lock)
-    pthread_mutex_lock(&rli->data_lock);
-
-  /*
-    Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER
-    is, too, and init_slave() too; these 2 functions allocate a description
-    event in init_relay_log_pos, which is not freed by the terminating SQL slave
-    thread as that thread is not started by these functions. So we have to free
-    the description_event here, in case, so that there is no memory leak in
-    running, say, CHANGE MASTER.
-  */
-  delete rli->relay_log.description_event_for_exec;
-  /*
-    By default the relay log is in binlog format 3 (4.0).
-    Even if format is 4, this will work enough to read the first event
-    (Format_desc) (remember that format 4 is just lenghtened compared to format
-    3; format 3 is a prefix of format 4). 
-  */
-  rli->relay_log.description_event_for_exec= new
-    Format_description_log_event(3);
-  
-  pthread_mutex_lock(log_lock);
-  
-  /* Close log file and free buffers if it's already open */
-  if (rli->cur_log_fd >= 0)
-  {
-    end_io_cache(&rli->cache_buf);
-    my_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
+    sql_print_error("Could not initialize master info container");
+    pthread_mutex_unlock(&LOCK_active_mi); 
+    DBUG_RETURN(1);
   }
   
-  rli->group_relay_log_pos = rli->event_relay_log_pos = pos;
-
   /*
-    Test to see if the previous run was with the skip of purging
-    If yes, we do not purge when we restart
+    Auto-start all threads for all defined named_masters 
+    If server id is not set, start_slave_thread() will say it 
   */
-  if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1))
+  if (!opt_skip_slave_start)
   {
-    *errmsg="Could not find first log during relay log initialization";
-    goto err;
-  }
-
-  if (log && rli->relay_log.find_log_pos(&rli->linfo, log, 1))
-  {
-    *errmsg="Could not find target log during relay log initialization";
-    goto err;
-  }
-  strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
-	  sizeof(rli->group_relay_log_name)-1);
-  strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
-	  sizeof(rli->event_relay_log_name)-1);
-  if (rli->relay_log.is_active(rli->linfo.log_file_name))
-  {
-    /*
-      The IO thread is using this log file.
-      In this case, we will use the same IO_CACHE pointer to
-      read data as the IO thread is using to write data.
-    */
-    my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0);
-    if (check_binlog_magic(rli->cur_log,errmsg))
-      goto err;
-    rli->cur_log_old_open_count=rli->relay_log.get_open_count();
-  }
-  else
-  {
-    /*
-      Open the relay log and set rli->cur_log to point at this one
-    */
-    if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
-				     rli->linfo.log_file_name,errmsg)) < 0)
-      goto err;
-    rli->cur_log = &rli->cache_buf;
-  }
-  /*
-    In all cases, check_binlog_magic() has been called so we're at offset 4 for
-    sure.
-  */
-  if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */
-  {
-    Log_event* ev;
-    while (look_for_description_event) 
+    for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
     {
-      /*
-        Read the possible Format_description_log_event; if position
-        was 4, no need, it will be read naturally.
-      */
-      DBUG_PRINT("info",("looking for a Format_description_log_event"));
+      // Skip autostart if it is a non-initialized subslave
+      if (!mi->is_inited())
+	continue;
 
-      if (my_b_tell(rli->cur_log) >= pos)
-        break;
+      sql_print_information("RPL:%s:Autostarting SQL and IO threads",
+			    mi->named_master);
 
-      /*
-        Because of we have rli->data_lock and log_lock, we can safely read an
-        event
-      */
-      if (!(ev=Log_event::read_log_event(rli->cur_log,0,
-                                         rli->relay_log.description_event_for_exec)))
-      {
-        DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
-                           rli->cur_log->error));
-        if (rli->cur_log->error) /* not EOF */
-        {
-          *errmsg= "I/O error reading event at position 4";
-          goto err;
-        }
-        break;
-      }
-      else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
-      {
-        DBUG_PRINT("info",("found Format_description_log_event"));
-        delete rli->relay_log.description_event_for_exec;
-        rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev;
-        /*
-          As ev was returned by read_log_event, it has passed is_valid(), so
-          my_malloc() in ctor worked, no need to check again.
-        */
-        /*
-          Ok, we found a Format_description event. But it is not sure that this
-          describes the whole relay log; indeed, one can have this sequence
-          (starting from position 4):
-          Format_desc (of slave)
-          Rotate (of master)
-          Format_desc (of master)
-          So the Format_desc which really describes the rest of the relay log
-          is the 3rd event (it can't be further than that, because we rotate
-          the relay log when we queue a Rotate event from the master).
-          But what describes the Rotate is the first Format_desc.
-          So what we do is:
-          go on searching for Format_description events, until you exceed the
-          position (argument 'pos') or until you find another event than Rotate
-          or Format_desc.
-        */
-      }
-      else 
-      {
-        DBUG_PRINT("info",("found event of another type=%d",
-                           ev->get_type_code()));
-        look_for_description_event= (ev->get_type_code() == ROTATE_EVENT);
-        delete ev;
+      if (start_slave_threads(1 /* need mutex */,
+                              0 /* no wait for start*/,
+                              mi,
+                              SLAVE_IO | SLAVE_SQL))
+      {
+        sql_print_error("RPL:%s:Failed to create slave threads", 
+                        mi->named_master);
+        pthread_mutex_unlock(&LOCK_active_mi); 
+        DBUG_RETURN(1);
       }
     }
-    my_b_seek(rli->cur_log,(off_t)pos);
-#ifndef DBUG_OFF
-  {
-    char llbuf1[22], llbuf2[22];
-    DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
-                        llstr(my_b_tell(rli->cur_log),llbuf1), 
-                        llstr(rli->event_relay_log_pos,llbuf2)));
-  }
-#endif
-
   }
 
-err:
-  /*
-    If we don't purge, we can't honour relay_log_space_limit ;
-    silently discard it
-  */
-  if (!relay_log_purge)
-    rli->log_space_limit= 0;
-  pthread_cond_broadcast(&rli->data_cond);
-  
-  pthread_mutex_unlock(log_lock);
-
-  if (need_data_lock)
-    pthread_mutex_unlock(&rli->data_lock);
-  if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
-    *errmsg= "Invalid Format_description log event; could be out of memory";
-
-  DBUG_RETURN ((*errmsg) ? 1 : 0);
+  pthread_mutex_unlock(&LOCK_active_mi);
+  DBUG_RETURN(0);
 }
 
 
@@ -413,7 +168,7 @@
 
   SYNOPSIS
     init_slave_skip_errors()
-    arg		List of errors numbers to skip, separated with ','
+    arg         List of errors numbers to skip, separated with ','
 
   NOTES
     Called from get_options() in mysqld.cc on start-up
@@ -448,157 +203,9 @@
 }
 
 
-void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
-						bool skip_lock)  
-{
-  if (!skip_lock)
-    pthread_mutex_lock(&data_lock);
-  inc_event_relay_log_pos();
-  group_relay_log_pos= event_relay_log_pos;
-  strmake(group_relay_log_name,event_relay_log_name,
-	  sizeof(group_relay_log_name)-1);
-
-  notify_group_relay_log_name_update();
-        
-  /*
-    If the slave does not support transactions and replicates a transaction,
-    users should not trust group_master_log_pos (which they can display with
-    SHOW SLAVE STATUS or read from relay-log.info), because to compute
-    group_master_log_pos the slave relies on log_pos stored in the master's
-    binlog, but if we are in a master's transaction these positions are always
-    the BEGIN's one (excepted for the COMMIT), so group_master_log_pos does
-    not advance as it should on the non-transactional slave (it advances by
-    big leaps, whereas it should advance by small leaps).
-  */
-  /*
-    In 4.x we used the event's len to compute the positions here. This is
-    wrong if the event was 3.23/4.0 and has been converted to 5.0, because
-    then the event's len is not what is was in the master's binlog, so this
-    will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0
-    replication: Exec_master_log_pos is wrong). Only way to solve this is to
-    have the original offset of the end of the event the relay log. This is
-    what we do in 5.0: log_pos has become "end_log_pos" (because the real use
-    of log_pos in 4.0 was to compute the end_log_pos; so better to store
-    end_log_pos instead of begin_log_pos.
-    If we had not done this fix here, the problem would also have appeared
-    when the slave and master are 5.0 but with different event length (for
-    example the slave is more recent than the master and features the event
-    UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in
-    SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this
-    value which would lead to badly broken replication.
-    Even the relay_log_pos will be corrupted in this case, because the len is
-    the relay log is not "val".
-    With the end_log_pos solution, we avoid computations involving lengthes.
-  */
-  DBUG_PRINT("info", ("log_pos: %lu  group_master_log_pos: %lu",
-		      (long) log_pos, (long) group_master_log_pos));
-  if (log_pos) // 3.23 binlogs don't have log_posx
-  {
-    group_master_log_pos= log_pos;
-  }
-  pthread_cond_broadcast(&data_cond);
-  if (!skip_lock)
-    pthread_mutex_unlock(&data_lock);
-}
-
-
-void st_relay_log_info::close_temporary_tables()
-{
-  TABLE *table,*next;
-
-  for (table=save_temporary_tables ; table ; table=next)
-  {
-    next=table->next;
-    /*
-      Don't ask for disk deletion. For now, anyway they will be deleted when
-      slave restarts, but it is a better intention to not delete them.
-    */
-    close_temporary(table, 0);
-  }
-  save_temporary_tables= 0;
-  slave_open_temp_tables= 0;
-}
-
-/*
-  purge_relay_logs()
-
-  NOTES
-    Assumes to have a run lock on rli and that no slave thread are running.
-*/
-
-int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
-		     const char** errmsg)
+int terminate_slave_threads(Master_info* mi, int thread_mask, bool skip_lock)
 {
-  int error=0;
-  DBUG_ENTER("purge_relay_logs");
-
-  /*
-    Even if rli->inited==0, we still try to empty rli->master_log_* variables.
-    Indeed, rli->inited==0 does not imply that they already are empty.
-    It could be that slave's info initialization partly succeeded :
-    for example if relay-log.info existed but *relay-bin*.*
-    have been manually removed, init_relay_log_info reads the old
-    relay-log.info and fills rli->master_log_*, then init_relay_log_info
-    checks for the existence of the relay log, this fails and
-    init_relay_log_info leaves rli->inited to 0.
-    In that pathological case, rli->master_log_pos* will be properly reinited
-    at the next START SLAVE (as RESET SLAVE or CHANGE
-    MASTER, the callers of purge_relay_logs, will delete bogus *.info files
-    or replace them with correct files), however if the user does SHOW SLAVE
-    STATUS before START SLAVE, he will see old, confusing rli->master_log_*.
-    In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
-    to display fine in any case.
-  */
-
-  rli->group_master_log_name[0]= 0;
-  rli->group_master_log_pos= 0;
-
-  if (!rli->inited)
-  {
-    DBUG_PRINT("info", ("rli->inited == 0"));
-    DBUG_RETURN(0);
-  }
-
-  DBUG_ASSERT(rli->slave_running == 0);
-  DBUG_ASSERT(rli->mi->slave_running == 0);
-
-  rli->slave_skip_counter=0;
-  pthread_mutex_lock(&rli->data_lock);
-  if (rli->relay_log.reset_logs(thd))
-  {
-    *errmsg = "Failed during log reset";
-    error=1;
-    goto err;
-  }
-  /* Save name of used relay log file */
-  strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(),
-	  sizeof(rli->group_relay_log_name)-1);
-  strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
- 	  sizeof(rli->event_relay_log_name)-1);
-  rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
-  if (count_relay_log_space(rli))
-  {
-    *errmsg= "Error counting relay log space";
-    goto err;
-  }
-  if (!just_reset)
-    error= init_relay_log_pos(rli, rli->group_relay_log_name,
-                              rli->group_relay_log_pos,
-  			      0 /* do not need data lock */, errmsg, 0);
-  
-err:
-#ifndef DBUG_OFF
-  char buf[22];
-#endif  
-  DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf)));
-  pthread_mutex_unlock(&rli->data_lock);
-  DBUG_RETURN(error);
-}
-
-
-int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
-{
-  if (!mi->inited)
+  if (!mi->is_inited())
     return 0; /* successfully do nothing */
   int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
   pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
@@ -614,25 +221,27 @@
   }
   if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) && mi->slave_running)
   {
-    DBUG_PRINT("info",("Terminating IO thread"));
+    DBUG_PRINT("info",("I/O:%s:Terminating thread", mi->named_master));
+    sql_print_information("I/O:%s:Stopping", mi->named_master);
     mi->abort_slave=1;
     if ((error=terminate_slave_thread(mi->io_thd,io_lock,
-				      io_cond_lock,
-				      &mi->stop_cond,
-				      &mi->slave_running)) &&
-	!force_all)
+                                      io_cond_lock,
+                                      &mi->stop_cond,
+                                      &mi->slave_running)) &&
+        !force_all)
       DBUG_RETURN(error);
   }
   if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) && mi->rli.slave_running)
   {
-    DBUG_PRINT("info",("Terminating SQL thread"));
+    DBUG_PRINT("info",("SQL:%s:Terminating thread", mi->named_master));
+    sql_print_information("SQL:%s:Stopping", mi->named_master);
     DBUG_ASSERT(mi->rli.sql_thd != 0) ;
     mi->rli.abort_slave=1;
     if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
-				      sql_cond_lock,
-				      &mi->rli.stop_cond,
-				      &mi->rli.slave_running)) &&
-	!force_all)
+                                      sql_cond_lock,
+                                      &mi->rli.stop_cond,
+                                      &mi->rli.slave_running)) &&
+        !force_all)
       DBUG_RETURN(error);
   }
   DBUG_RETURN(0);
@@ -640,9 +249,9 @@
 
 
 int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
-			   pthread_mutex_t *cond_lock,
-			   pthread_cond_t* term_cond,
-			   volatile uint *slave_running)
+                           pthread_mutex_t *cond_lock,
+                           pthread_cond_t* term_cond,
+                           volatile uint *slave_running)
 {
   DBUG_ENTER("terminate_slave_thread");
   if (term_lock)
@@ -661,7 +270,7 @@
     be referening freed memory trying to kick it
   */
 
-  while (*slave_running)			// Should always be true
+  while (*slave_running)                        // Should always be true
   {
     DBUG_PRINT("loop", ("killing slave thread"));
     KICK_SLAVE(thd);
@@ -680,16 +289,16 @@
 
 
 int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
-		       pthread_mutex_t *cond_lock,
-		       pthread_cond_t *start_cond,
-		       volatile uint *slave_running,
-		       volatile ulong *slave_run_id,
-		       MASTER_INFO* mi,
+                       pthread_mutex_t *cond_lock,
+                       pthread_cond_t *start_cond,
+                       volatile uint *slave_running,
+                       volatile ulong *slave_run_id,
+                       Master_info* mi,
                        bool high_priority)
 {
   pthread_t th;
   ulong start_id;
-  DBUG_ASSERT(mi->inited);
+  DBUG_ASSERT(mi->is_inited());
   DBUG_ENTER("start_slave_thread");
 
   if (start_lock)
@@ -729,12 +338,12 @@
     {
       DBUG_PRINT("sleep",("Waiting for slave thread to start"));
       const char* old_msg = thd->enter_cond(start_cond,cond_lock,
-					    "Waiting for slave thread to start");
+                                            "Waiting for slave thread to start");
       pthread_cond_wait(start_cond,cond_lock);
       thd->exit_cond(old_msg);
       pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released
       if (thd->killed)
-	DBUG_RETURN(thd->killed_errno());
+        DBUG_RETURN(thd->killed_errno());
     }
   }
   if (start_lock)
@@ -753,8 +362,7 @@
 */
 
 int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
-			MASTER_INFO* mi, const char* master_info_fname,
-			const char* slave_info_fname, int thread_mask)
+                        Master_info* mi, int thread_mask)
 {
   pthread_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0;
   pthread_cond_t* cond_io=0,*cond_sql=0;
@@ -776,15 +384,15 @@
 
   if (thread_mask & SLAVE_IO)
     error=start_slave_thread(handle_slave_io,lock_io,lock_cond_io,
-			     cond_io,
-			     &mi->slave_running, &mi->slave_run_id,
-			     mi, 1); //high priority, to read the most possible
+                             cond_io,
+                             &mi->slave_running, &mi->slave_run_id,
+                             mi, 1); //high priority, to read the most possible
   if (!error && (thread_mask & SLAVE_SQL))
   {
     error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql,
-			     cond_sql,
-			     &mi->rli.slave_running, &mi->rli.slave_run_id,
-			     mi, 0);
+                             cond_sql,
+                             &mi->rli.slave_running, &mi->rli.slave_run_id,
+                             mi, 0);
     if (error)
       terminate_slave_threads(mi, thread_mask & SLAVE_IO, 0);
   }
@@ -792,23 +400,14 @@
 }
 
 
-#ifdef NOT_USED_YET
-static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
-{
-  end_master_info(mi);
-  return 0;
-}
-#endif
-
-
 /*
   Free all resources used by slave
 
   SYNOPSIS
-    end_slave()
+    end_all_named_masters()
 */
 
-void end_slave()
+void end_all_named_masters()
 {
   /*
     This is called when the server terminates, in close_connections().
@@ -818,23 +417,17 @@
     returns, then we terminate them here.
   */
   pthread_mutex_lock(&LOCK_active_mi);
-  if (active_mi)
+  Master_info *mi;
+  while ((mi= mic.get_head()))
   {
-    /*
-      TODO: replace the line below with
-      list_walk(&master_list, (list_walk_action)end_slave_on_walk,0);
-      once multi-master code is ready.
-    */
-    terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
-    end_master_info(active_mi);
-    delete active_mi;
-    active_mi= 0;
+    terminate_slave_threads(mi, SLAVE_FORCE_ALL);
+    mic.drop_head_master_info();
   }
   pthread_mutex_unlock(&LOCK_active_mi);
 }
 
 
-static bool io_slave_killed(THD* thd, MASTER_INFO* mi)
+static bool io_slave_killed(THD* thd, Master_info* mi)
 {
   DBUG_ASSERT(mi->io_thd == thd);
   DBUG_ASSERT(mi->slave_running); // tracking buffer overrun
@@ -842,21 +435,16 @@
 }
 
 
-static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli)
-{
-  DBUG_ASSERT(rli->sql_thd == thd);
-  DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun
-  return rli->abort_slave || abort_loop || thd->killed;
-}
-
-
 /*
   Writes an error message to rli->last_slave_error and rli->last_slave_errno
   (which will be displayed by SHOW SLAVE STATUS), and prints it to stderr.
 
+  This function should only be used to report errors occuring in the 
+  SQL thread.
+
   SYNOPSIS
     slave_print_error()
-    rli		
+    rli         
     err_code    The error code
     msg         The error message (usually related to the error code, but can
                 contain more information).
@@ -866,22 +454,21 @@
     void
 */
 
-void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...)
+void slave_print_error(Relay_log_info* rli, int err_code, const char* msg, ...)
 {
   va_list args;
   va_start(args,msg);
   my_vsnprintf(rli->last_slave_error,
-	       sizeof(rli->last_slave_error), msg, args);
+               sizeof(rli->last_slave_error), msg, args);
   rli->last_slave_errno = err_code;
   /* If the error string ends with '.', do not add a ',' it would be ugly */
   if (rli->last_slave_error[0] && 
       (*(strend(rli->last_slave_error)-1) == '.'))
-    sql_print_error("Slave: %s Error_code: %d", rli->last_slave_error,
-                    err_code);
+    sql_print_error("SQL:%s:%s, Error_code: %d", rli->mi->named_master,
+		    rli->last_slave_error, err_code);
   else
-    sql_print_error("Slave: %s, Error_code: %d", rli->last_slave_error,
-                    err_code);
-
+    sql_print_error("SQL:%s:%s, Error_code: %d", rli->mi->named_master,
+		    rli->last_slave_error, err_code);
 }
 
 /*
@@ -894,8 +481,8 @@
 void skip_load_data_infile(NET *net)
 {
   (void)net_request_file(net, "/dev/null");
-  (void)my_net_read(net);				// discard response
-  (void)net_write_command(net, 0, "", 0, "", 0);	// Send ok
+  (void)my_net_read(net);                               // discard response
+  (void)net_write_command(net, 0, "", 0, "", 0);        // Send ok
 }
 
 
@@ -919,52 +506,6 @@
 }
 
 
-static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-				 const char *default_val)
-{
-  uint length;
-  if ((length=my_b_gets(f,var, max_size)))
-  {
-    char* last_p = var + length -1;
-    if (*last_p == '\n')
-      *last_p = 0; // if we stopped on newline, kill it
-    else
-    {
-      /*
-	If we truncated a line or stopped on last char, remove all chars
-	up to and including newline.
-      */
-      int c;
-      while (((c=my_b_get(f)) != '\n' && c != my_b_EOF));
-    }
-    return 0;
-  }
-  else if (default_val)
-  {
-    strmake(var,  default_val, max_size-1);
-    return 0;
-  }
-  return 1;
-}
-
-
-static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
-{
-  char buf[32];
-  
-  if (my_b_gets(f, buf, sizeof(buf))) 
-  {
-    *var = atoi(buf);
-    return 0;
-  }
-  else if (default_val)
-  {
-    *var = default_val;
-    return 0;
-  }
-  return 1;
-}
-
 /*
   Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
   relying on the binlog's version. This is not perfect: imagine an upgrade
@@ -979,7 +520,7 @@
   1       error
 */
 
-static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi)
+static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
 {
   const char* errmsg= 0;
 
@@ -1036,14 +577,16 @@
   
   if (errmsg)
   {
-    sql_print_error(errmsg);
+    sql_print_error("I/O:%s:%s", mi->named_master, errmsg);
     return 1;
   }
 
   /* as we are here, we tried to allocate the event */
   if (!mi->rli.relay_log.description_event_for_queue)
   {
-    sql_print_error("Slave I/O thread failed to create a default Format_description_log_event");
+    sql_print_error("I/O:%s:Failed to create a default "
+                    "Format_description_log_event",
+                    mi->named_master);
     return 1;
   }
 
@@ -1064,8 +607,10 @@
   else
   {
     mi->clock_diff_with_master= 0; /* The "most sensible" value */
-    sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, \
-do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS");
+    sql_print_warning("I/O:%s:\"SELECT UNIX_TIMESTAMP()\" failed on master, "
+                      "do not trust column Seconds_Behind_Master of "
+                      "SHOW SLAVE STATUS",
+                      mi->named_master);
   }
   if (master_res)
     mysql_free_result(master_res);      
@@ -1085,7 +630,7 @@
   {
     if ((master_row= mysql_fetch_row(master_res)) &&
         (::server_id == strtoul(master_row[1], 0, 10)) &&
-        !replicate_same_server_id)
+        !opt_replicate_same_server_id)
       errmsg= "The slave I/O thread stops because master and slave have equal \
 MySQL server ids; these ids must be different for replication to work (or \
 the --replicate-same-server-id option must be used on slave but this does \
@@ -1157,7 +702,7 @@
 err:
   if (errmsg)
   {
-    sql_print_error(errmsg);
+    sql_print_error("I/O:%s:%s", mi->named_master, errmsg);
     return 1;
   }
 
@@ -1176,7 +721,7 @@
 */
 
 static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
-				  const char* table_name, bool overwrite)
+                                  const char* table_name, bool overwrite)
 {
   ulong packet_len;
   char *query, *save_db;
@@ -1200,8 +745,8 @@
   {
     char *err_msg; 
     err_msg= (char*) net->read_pos + ((mysql->server_capabilities &
-				       CLIENT_PROTOCOL_41) ?
-				      3+SQLSTATE_LENGTH+1 : 3);
+                                       CLIENT_PROTOCOL_41) ?
+                                      3+SQLSTATE_LENGTH+1 : 3);
     my_error(ER_MASTER, MYF(0), err_msg);
     DBUG_RETURN(1);
   }
@@ -1240,12 +785,12 @@
   DBUG_ASSERT(thd->db != 0);
   thd->db_length= strlen(thd->db);
   mysql_parse(thd, thd->query, packet_len); // run create table
-  thd->db = save_db;		// leave things the way the were before
+  thd->db = save_db;            // leave things the way the were before
   thd->db_length= save_db_length;
   thd->options = save_options;
   
   if (thd->query_error)
-    goto err;			// mysql_parse took care of the error send
+    goto err;                   // mysql_parse took care of the error send
 
   thd->proc_info = "Opening master dump table";
   tables.lock_type = TL_WRITE;
@@ -1289,15 +834,37 @@
 }
 
 
+/*
+  Implements SQL command: LOAD TABLE tablename FROM MASTER named_master
+*/
+int load_master_table(THD *thd, const char *db_name, const char *table_name,
+                      const char *named_master, MYSQL *mysql, bool overwrite)
+{
+  DBUG_ENTER("load_master_table");
+  DBUG_PRINT("enter", ("named_master: '%s', db_name: '%s', table_name: '%s'",
+                       named_master, db_name, table_name));
+
+  Master_info *mi;
+  if (!(mi= mic.get_master_info(named_master)))
+  {
+    my_error(ER_NAMED_MASTER_NOT_EXISTS, MYF(0), named_master);
+    mysql_close(mysql);
+    DBUG_RETURN(1);
+  }
+  DBUG_RETURN(fetch_master_table(thd, db_name, table_name, 
+				 mi, mysql, overwrite));
+}
+
+
 int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
-		       MASTER_INFO *mi, MYSQL *mysql, bool overwrite)
+                       Master_info *mi, MYSQL *mysql, bool overwrite)
 {
   int error= 1;
   const char *errmsg=0;
   bool called_connected= (mysql != NULL);
-  DBUG_ENTER("fetch_master_table");
-  DBUG_PRINT("enter", ("db_name: '%s'  table_name: '%s'",
-		       db_name,table_name));
+  DBUG_ENTER("load_master_table");
+  DBUG_PRINT("enter", ("db_name: '%s', table_name: '%s'", 
+                       db_name, table_name));
 
   if (!called_connected)
   { 
@@ -1322,7 +889,7 @@
     goto err;
   }
   if (create_table_from_dump(thd, mysql, db_name,
-			     table_name, overwrite))
+                             table_name, overwrite))
     goto err;    // create_table_from_dump have sent the error already
   error = 0;
 
@@ -1332,249 +899,14 @@
     mysql_close(mysql);
   if (errmsg && thd->vio_ok())
     my_message(error, errmsg, MYF(0));
-  DBUG_RETURN(test(error));			// Return 1 on error
-}
-
-
-void end_master_info(MASTER_INFO* mi)
-{
-  DBUG_ENTER("end_master_info");
-
-  if (!mi->inited)
-    DBUG_VOID_RETURN;
-  end_relay_log_info(&mi->rli);
-  if (mi->fd >= 0)
-  {
-    end_io_cache(&mi->file);
-    (void)my_close(mi->fd, MYF(MY_WME));
-    mi->fd = -1;
-  }
-  mi->inited = 0;
-
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(test(error));                     // Return 1 on error
 }
 
 
-static int init_relay_log_info(RELAY_LOG_INFO* rli,
-                               const char* info_fname)
-{
-  char fname[FN_REFLEN+128];
-  int info_fd;
-  const char* msg = 0;
-  int error = 0;
-  DBUG_ENTER("init_relay_log_info");
-
-  if (rli->inited)                       // Set if this function called
-    DBUG_RETURN(0);
-  fn_format(fname, info_fname, mysql_data_home, "", 4+32);
-  pthread_mutex_lock(&rli->data_lock);
-  info_fd = rli->info_fd;
-  rli->cur_log_fd = -1;
-  rli->slave_skip_counter=0;
-  rli->abort_pos_wait=0;
-  rli->log_space_limit= relay_log_space_limit;
-  rli->log_space_total= 0;
-
-  /*
-    The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
-    Note that the I/O thread flushes it to disk after writing every
-    event, in flush_master_info(mi, 1).
-  */
-
-  /*
-    For the maximum log size, we choose max_relay_log_size if it is
-    non-zero, max_binlog_size otherwise. If later the user does SET
-    GLOBAL on one of these variables, fix_max_binlog_size and
-    fix_max_relay_log_size will reconsider the choice (for example
-    if the user changes max_relay_log_size to zero, we have to
-    switch to using max_binlog_size for the relay log) and update
-    rli->relay_log.max_size (and mysql_bin_log.max_size).
-  */
-  {
-    char buf[FN_REFLEN];
-    const char *ln;
-    ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
-                                     1, buf);
-
-    /*
-      note, that if open() fails, we'll still have index file open
-      but a destructor will take care of that
-    */
-    if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) ||
-        rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
-                            (max_relay_log_size ? max_relay_log_size :
-                            max_binlog_size), 1))
-    {
-      pthread_mutex_unlock(&rli->data_lock);
-      sql_print_error("Failed in open_log() called from init_relay_log_info()");
-      DBUG_RETURN(1);
-    }
-  }
-
-  /* if file does not exist */
-  if (access(fname,F_OK))
-  {
-    /*
-      If someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (info_fd >= 0)
-      my_close(info_fd, MYF(MY_WME));
-    if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-    {
-      sql_print_error("Failed to create a new relay log info file (\
-file '%s', errno %d)", fname, my_errno);
-      msg= current_thd->net.last_error;
-      goto err;
-    }
-    if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
-		      MYF(MY_WME))) 
-    {
-      sql_print_error("Failed to create a cache on relay log info file '%s'",
-		      fname);
-      msg= current_thd->net.last_error;
-      goto err;
-    }
-
-    /* Init relay log with first entry in the relay index file */
-    if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
-			   &msg, 0))
-    {
-      sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
-      goto err;
-    }
-    rli->group_master_log_name[0]= 0;
-    rli->group_master_log_pos= 0;		
-    rli->info_fd= info_fd;
-  }
-  else // file exists
-  {
-    if (info_fd >= 0)
-      reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
-    else 
-    {
-      int error=0;
-      if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0)
-      {
-        sql_print_error("\
-Failed to open the existing relay log info file '%s' (errno %d)",
-			fname, my_errno);
-        error= 1;
-      }
-      else if (init_io_cache(&rli->info_file, info_fd,
-                             IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on relay log info file '%s'",
-			fname);
-        error= 1;
-      }
-      if (error)
-      {
-        if (info_fd >= 0)
-          my_close(info_fd, MYF(0));
-        rli->info_fd= -1;
-        rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-        pthread_mutex_unlock(&rli->data_lock);
-        DBUG_RETURN(1);
-      }
-    }
-         
-    rli->info_fd = info_fd;
-    int relay_log_pos, master_log_pos;
-    if (init_strvar_from_file(rli->group_relay_log_name,
-			      sizeof(rli->group_relay_log_name),
-                              &rli->info_file, "") ||
-       init_intvar_from_file(&relay_log_pos,
-			     &rli->info_file, BIN_LOG_HEADER_SIZE) ||
-       init_strvar_from_file(rli->group_master_log_name,
-			     sizeof(rli->group_master_log_name),
-                             &rli->info_file, "") ||
-       init_intvar_from_file(&master_log_pos, &rli->info_file, 0))
-    {
-      msg="Error reading slave log configuration";
-      goto err;
-    }
-    strmake(rli->event_relay_log_name,rli->group_relay_log_name,
-            sizeof(rli->event_relay_log_name)-1);
-    rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos;
-    rli->group_master_log_pos= master_log_pos;
-
-    if (init_relay_log_pos(rli,
-			   rli->group_relay_log_name,
-			   rli->group_relay_log_pos,
-			   0 /* no data lock*/,
-			   &msg, 0))
-    {
-      char llbuf[22];
-      sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
-		      rli->group_relay_log_name,
-		      llstr(rli->group_relay_log_pos, llbuf));
-      goto err;
-    }
-  }
-
-#ifndef DBUG_OFF
-  {
-    char llbuf1[22], llbuf2[22];
-    DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
-                        llstr(my_b_tell(rli->cur_log),llbuf1), 
-                        llstr(rli->event_relay_log_pos,llbuf2)));
-    DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
-    DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
-  }
-#endif
-
-  /*
-    Now change the cache from READ to WRITE - must do this
-    before flush_relay_log_info
-  */
-  reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
-  if ((error= flush_relay_log_info(rli)))
-    sql_print_error("Failed to flush relay log info file");
-  if (count_relay_log_space(rli))
-  {
-    msg="Error counting relay log space";
-    goto err;
-  }
-  rli->inited= 1;
-  pthread_mutex_unlock(&rli->data_lock);
-  DBUG_RETURN(error);
-
-err:
-  sql_print_error(msg);
-  end_io_cache(&rli->info_file);
-  if (info_fd >= 0)
-    my_close(info_fd, MYF(0));
-  rli->info_fd= -1;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  pthread_mutex_unlock(&rli->data_lock);
-  DBUG_RETURN(1);
-}
-
-
-static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
-{
-  MY_STAT s;
-  DBUG_ENTER("add_relay_log");
-  if (!my_stat(linfo->log_file_name,&s,MYF(0)))
-  {
-    sql_print_error("log %s listed in the index, but failed to stat",
-		    linfo->log_file_name);
-    DBUG_RETURN(1);
-  }
-  rli->log_space_total += s.st_size;
-#ifndef DBUG_OFF
-  char buf[22];
-  DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf)));
-#endif  
-  DBUG_RETURN(0);
-}
-
-
-static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
+static bool wait_for_relay_log_space(Relay_log_info* rli)
 {
   bool slave_killed=0;
-  MASTER_INFO* mi = rli->mi;
+  Master_info* mi= rli->mi;
   const char *save_proc_info;
   THD* thd = mi->io_thd;
 
@@ -1582,11 +914,11 @@
 
   pthread_mutex_lock(&rli->log_space_lock);
   save_proc_info= thd->enter_cond(&rli->log_space_cond,
-				  &rli->log_space_lock, 
-				  "\
+                                  &rli->log_space_lock, 
+                                  "\
 Waiting for the slave SQL thread to free enough relay log space");
   while (rli->log_space_limit < rli->log_space_total &&
-	 !(slave_killed=io_slave_killed(thd,mi)) &&
+         !(slave_killed=io_slave_killed(thd,mi)) &&
          !rli->ignore_log_space_limit)
     pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
   thd->exit_cond(save_proc_info);
@@ -1594,300 +926,6 @@
 }
 
 
-static int count_relay_log_space(RELAY_LOG_INFO* rli)
-{
-  LOG_INFO linfo;
-  DBUG_ENTER("count_relay_log_space");
-  rli->log_space_total= 0;
-  if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
-  {
-    sql_print_error("Could not find first log while counting relay log space");
-    DBUG_RETURN(1);
-  }
-  do
-  {
-    if (add_relay_log(rli,&linfo))
-      DBUG_RETURN(1);
-  } while (!rli->relay_log.find_next_log(&linfo, 1));
-  /* 
-     As we have counted everything, including what may have written in a
-     preceding write, we must reset bytes_written, or we may count some space 
-     twice.
-  */
-  rli->relay_log.reset_bytes_written();
-  DBUG_RETURN(0);
-}
-
-
-void init_master_info_with_options(MASTER_INFO* mi)
-{
-  mi->master_log_name[0] = 0;
-  mi->master_log_pos = BIN_LOG_HEADER_SIZE;		// skip magic number
-  
-  if (master_host)
-    strmake(mi->host, master_host, sizeof(mi->host) - 1);
-  if (master_user)
-    strmake(mi->user, master_user, sizeof(mi->user) - 1);
-  if (master_password)
-    strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
-  mi->port = master_port;
-  mi->connect_retry = master_connect_retry;
-  
-  mi->ssl= master_ssl;
-  if (master_ssl_ca)
-    strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1);
-  if (master_ssl_capath)
-    strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1);
-  if (master_ssl_cert)
-    strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1);
-  if (master_ssl_cipher)
-    strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1);
-  if (master_ssl_key)
-    strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1);
-}
-
-void clear_slave_error(RELAY_LOG_INFO* rli)
-{
-  /* Clear the errors displayed by SHOW SLAVE STATUS */
-  rli->last_slave_error[0]= 0;
-  rli->last_slave_errno= 0;
-}
-
-/*
-    Reset UNTIL condition for RELAY_LOG_INFO
-   SYNOPSYS
-    clear_until_condition()
-      rli - RELAY_LOG_INFO structure where UNTIL condition should be reset
- */
-void clear_until_condition(RELAY_LOG_INFO* rli)
-{
-  rli->until_condition= RELAY_LOG_INFO::UNTIL_NONE;
-  rli->until_log_name[0]= 0;
-  rli->until_log_pos= 0;
-}
-
-
-#define LINES_IN_MASTER_INFO_WITH_SSL 14
-
-
-int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
-                     const char* slave_info_fname,
-                     bool abort_if_no_master_info_file,
-                     int thread_mask)
-{
-  int fd,error;
-  char fname[FN_REFLEN+128];
-  DBUG_ENTER("init_master_info");
-
-  if (mi->inited)
-  {
-    /*
-      We have to reset read position of relay-log-bin as we may have
-      already been reading from 'hotlog' when the slave was stopped
-      last time. If this case pos_in_file would be set and we would
-      get a crash when trying to read the signature for the binary
-      relay log.
-
-      We only rewind the read position if we are starting the SQL
-      thread. The handle_slave_sql thread assumes that the read
-      position is at the beginning of the file, and will read the
-      "signature" and then fast-forward to the last position read.
-    */
-    if (thread_mask & SLAVE_SQL)
-    {
-      my_b_seek(mi->rli.cur_log, (my_off_t) 0);
-    }
-    DBUG_RETURN(0);
-  }
-
-  mi->mysql=0;
-  mi->file_id=1;
-  fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
-
-  /*
-    We need a mutex while we are changing master info parameters to
-    keep other threads from reading bogus info
-  */
-
-  pthread_mutex_lock(&mi->data_lock);
-  fd = mi->fd;
-
-  /* does master.info exist ? */
-
-  if (access(fname,F_OK))
-  {
-    if (abort_if_no_master_info_file)
-    {
-      pthread_mutex_unlock(&mi->data_lock);
-      DBUG_RETURN(0);
-    }
-    /*
-      if someone removed the file from underneath our feet, just close
-      the old descriptor and re-create the old file
-    */
-    if (fd >= 0)
-      my_close(fd, MYF(MY_WME));
-    if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-    {
-      sql_print_error("Failed to create a new master info file (\
-file '%s', errno %d)", fname, my_errno);
-      goto err;
-    }
-    if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
-		      MYF(MY_WME)))
-    {
-      sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
-      goto err;
-    }
-
-    mi->fd = fd;
-    init_master_info_with_options(mi);
-
-  }
-  else // file exists
-  {
-    if (fd >= 0)
-      reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
-    else
-    {
-      if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
-      {
-        sql_print_error("Failed to open the existing master info file (\
-file '%s', errno %d)", fname, my_errno);
-        goto err;
-      }
-      if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
-                        0, MYF(MY_WME)))
-      {
-        sql_print_error("Failed to create a cache on master info file (\
-file '%s')", fname);
-        goto err;
-      }
-    }
-
-    mi->fd = fd;
-    int port, connect_retry, master_log_pos, ssl= 0, lines;
-    char *first_non_digit;
-
-    /*
-       Starting from 4.1.x master.info has new format. Now its
-       first line contains number of lines in file. By reading this
-       number we will be always distinguish to which version our
-       master.info corresponds to. We can't simply count lines in
-       file since versions before 4.1.x could generate files with more
-       lines than needed.
-       If first line doesn't contain a number or contain number less than
-       14 then such file is treated like file from pre 4.1.1 version.
-       There is no ambiguity when reading an old master.info, as before
-       4.1.1, the first line contained the binlog's name, which is either
-       empty or has an extension (contains a '.'), so can't be confused
-       with an integer.
-
-       So we're just reading first line and trying to figure which version
-       is this.
-    */
-
-    /*
-       The first row is temporarily stored in mi->master_log_name,
-       if it is line count and not binlog name (new format) it will be
-       overwritten by the second row later.
-    */
-    if (init_strvar_from_file(mi->master_log_name,
-			      sizeof(mi->master_log_name), &mi->file,
-			      ""))
-      goto errwithmsg;
-
-    lines= strtoul(mi->master_log_name, &first_non_digit, 10);
-
-    if (mi->master_log_name[0]!='\0' &&
-        *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
-    {                                          // Seems to be new format
-      if (init_strvar_from_file(mi->master_log_name,
-            sizeof(mi->master_log_name), &mi->file, ""))
-        goto errwithmsg;
-    }
-    else
-      lines= 7;
-
-    if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
-	init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
-			      master_host) ||
-	init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
-			      master_user) ||
-        init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
-                              &mi->file, master_password) ||
-	init_intvar_from_file(&port, &mi->file, master_port) ||
-	init_intvar_from_file(&connect_retry, &mi->file,
-			      master_connect_retry))
-      goto errwithmsg;
-
-    /*
-       If file has ssl part use it even if we have server without
-       SSL support. But these option will be ignored later when
-       slave will try connect to master, so in this case warning
-       is printed.
-     */
-    if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
-        (init_intvar_from_file(&ssl, &mi->file, master_ssl) ||
-         init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
-                               &mi->file, master_ssl_ca) ||
-         init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
-                               &mi->file, master_ssl_capath) ||
-         init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
-                               &mi->file, master_ssl_cert) ||
-         init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher),
-                               &mi->file, master_ssl_cipher) ||
-         init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key),
-                              &mi->file, master_ssl_key)))
-      goto errwithmsg;
-#ifndef HAVE_OPENSSL
-    if (ssl)
-      sql_print_warning("SSL information in the master info file "
-                      "('%s') are ignored because this MySQL slave was compiled "
-                      "without SSL support.", fname);
-#endif /* HAVE_OPENSSL */
-
-    /*
-      This has to be handled here as init_intvar_from_file can't handle
-      my_off_t types
-    */
-    mi->master_log_pos= (my_off_t) master_log_pos;
-    mi->port= (uint) port;
-    mi->connect_retry= (uint) connect_retry;
-    mi->ssl= (my_bool) ssl;
-  }
-  DBUG_PRINT("master_info",("log_file_name: %s  position: %ld",
-			    mi->master_log_name,
-			    (ulong) mi->master_log_pos));
-
-  mi->rli.mi = mi;
-  if (init_relay_log_info(&mi->rli, slave_info_fname))
-    goto err;
-
-  mi->inited = 1;
-  // now change cache READ -> WRITE - must do this before flush_master_info
-  reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
-  if ((error=test(flush_master_info(mi, 1))))
-    sql_print_error("Failed to flush master info file");
-  pthread_mutex_unlock(&mi->data_lock);
-  DBUG_RETURN(error);
-
-errwithmsg:
-  sql_print_error("Error reading master configuration");
-
-err:
-  if (fd >= 0)
-  {
-    my_close(fd, MYF(0));
-    end_io_cache(&mi->file);
-  }
-  mi->fd= -1;
-  pthread_mutex_unlock(&mi->data_lock);
-  DBUG_RETURN(1);
-}
-
-
 int register_slave_on_master(MYSQL* mysql)
 {
   char buf[1024], *pos= buf;
@@ -1903,56 +941,59 @@
   /* 30 is a good safety margin */
   if (report_host_len + report_user_len + report_password_len + 30 >
       sizeof(buf))
-    return 0;					// safety
+    return 0;                                   // safety
 
   int4store(pos, server_id); pos+= 4;
   pos= net_store_data(pos, report_host, report_host_len); 
   pos= net_store_data(pos, report_user, report_user_len);
   pos= net_store_data(pos, report_password, report_password_len);
   int2store(pos, (uint16) report_port); pos+= 2;
-  int4store(pos, rpl_recovery_rank);	pos+= 4;
+  int4store(pos, rpl_recovery_rank);    pos+= 4;
   /* The master will fill in master_id */
-  int4store(pos, 0);			pos+= 4;
+  int4store(pos, 0);                    pos+= 4;
 
   if (simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf,
-			(uint) (pos- buf), 0))
+                        (uint) (pos- buf), 0))
   {
     sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'",
-		    mysql_errno(mysql),
-		    mysql_error(mysql));
+                    mysql_errno(mysql),
+                    mysql_error(mysql));
     return 1;
   }
   return 0;
 }
 
 
-bool show_master_info(THD* thd, MASTER_INFO* mi)
+bool show_slave_stat(THD* thd, const char* named_master)
 {
-  // TODO: fix this for multi-master
+  DBUG_ENTER("show_slave_stat");
+  DBUG_PRINT("enter",("named_master: %s", named_master));
+  
+  Master_info *mi;
+
   List<Item> field_list;
   Protocol *protocol= thd->protocol;
-  DBUG_ENTER("show_master_info");
 
   field_list.push_back(new Item_empty_string("Slave_IO_State",
-						     14));
+                                                     14));
   field_list.push_back(new Item_empty_string("Master_Host",
-						     sizeof(mi->host)));
+                                                     sizeof(mi->host)));
   field_list.push_back(new Item_empty_string("Master_User",
-						     sizeof(mi->user)));
+                                                     sizeof(mi->user)));
   field_list.push_back(new Item_return_int("Master_Port", 7,
-					   MYSQL_TYPE_LONG));
+                                           MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("Connect_Retry", 10,
-					   MYSQL_TYPE_LONG));
+                                           MYSQL_TYPE_LONG));
   field_list.push_back(new Item_empty_string("Master_Log_File",
-					     FN_REFLEN));
+                                             FN_REFLEN));
   field_list.push_back(new Item_return_int("Read_Master_Log_Pos", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_empty_string("Relay_Log_File",
-					     FN_REFLEN));
+                                             FN_REFLEN));
   field_list.push_back(new Item_return_int("Relay_Log_Pos", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
-					     FN_REFLEN));
+                                             FN_REFLEN));
   field_list.push_back(new Item_empty_string("Slave_IO_Running", 3));
   field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3));
   field_list.push_back(new Item_empty_string("Replicate_Do_DB", 20));
@@ -1961,15 +1002,15 @@
   field_list.push_back(new Item_empty_string("Replicate_Ignore_Table", 23));
   field_list.push_back(new Item_empty_string("Replicate_Wild_Do_Table", 24));
   field_list.push_back(new Item_empty_string("Replicate_Wild_Ignore_Table",
-					     28));
+                                             28));
   field_list.push_back(new Item_return_int("Last_Errno", 4, MYSQL_TYPE_LONG));
   field_list.push_back(new Item_empty_string("Last_Error", 20));
   field_list.push_back(new Item_return_int("Skip_Counter", 10,
-					   MYSQL_TYPE_LONG));
+                                           MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("Exec_Master_Log_Pos", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_return_int("Relay_Log_Space", 10,
-					   MYSQL_TYPE_LONGLONG));
+                                           MYSQL_TYPE_LONGLONG));
   field_list.push_back(new Item_empty_string("Until_Condition", 6));
   field_list.push_back(new Item_empty_string("Until_Log_File", FN_REFLEN));
   field_list.push_back(new Item_return_int("Until_Log_Pos", 10, 
@@ -1992,7 +1033,7 @@
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     DBUG_RETURN(TRUE);
 
-  if (mi->host[0])
+  if ((mi= mic.get_master_info(named_master)))
   {
     DBUG_PRINT("info",("host is set: '%s'", mi->host));
     String *packet= &thd->packet;
@@ -2014,8 +1055,8 @@
     protocol->store(mi->master_log_name, &my_charset_bin);
     protocol->store((ulonglong) mi->master_log_pos);
     protocol->store(mi->rli.group_relay_log_name +
-		    dirname_length(mi->rli.group_relay_log_name),
-		    &my_charset_bin);
+                    dirname_length(mi->rli.group_relay_log_name),
+                    &my_charset_bin);
     protocol->store((ulonglong) mi->rli.group_relay_log_pos);
     protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
     protocol->store(mi->slave_running ? "Yes":"No", &my_charset_bin);
@@ -2041,8 +1082,8 @@
     protocol->store((ulonglong) mi->rli.log_space_total);
 
     protocol->store(
-      mi->rli.until_condition==RELAY_LOG_INFO::UNTIL_NONE ? "None": 
-        ( mi->rli.until_condition==RELAY_LOG_INFO::UNTIL_MASTER_POS? "Master":
+      mi->rli.until_condition==Relay_log_info::UNTIL_NONE ? "None": 
+        ( mi->rli.until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master":
           "Relay"), &my_charset_bin);
     protocol->store(mi->rli.until_log_name, &my_charset_bin);
     protocol->store((ulonglong) mi->rli.until_log_pos);
@@ -2104,299 +1145,6 @@
   DBUG_RETURN(FALSE);
 }
 
-
-bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
-{
-  IO_CACHE* file = &mi->file;
-  char lbuf[22];
-  DBUG_ENTER("flush_master_info");
-  DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
-
-  /*
-    Flush the relay log to disk. If we don't do it, then the relay log while
-    have some part (its last kilobytes) in memory only, so if the slave server
-    dies now, with, say, from master's position 100 to 150 in memory only (not
-    on disk), and with position 150 in master.info, then when the slave
-    restarts, the I/O thread will fetch binlogs from 150, so in the relay log
-    we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the
-    SQL thread will jump from 100 to 150, and replication will silently break.
-
-    When we come to this place in code, relay log may or not be initialized;
-    the caller is responsible for setting 'flush_relay_log_cache' accordingly.
-  */
-  if (flush_relay_log_cache)
-    flush_io_cache(mi->rli.relay_log.get_log_file());
-
-  /*
-    We flushed the relay log BEFORE the master.info file, because if we crash
-    now, we will get a duplicate event in the relay log at restart. If we
-    flushed in the other order, we would get a hole in the relay log.
-    And duplicate is better than hole (with a duplicate, in later versions we
-    can add detection and scrap one event; with a hole there's nothing we can
-    do).
-  */
-
-  /*
-     In certain cases this code may create master.info files that seems 
-     corrupted, because of extra lines filled with garbage in the end 
-     file (this happens if new contents take less space than previous 
-     contents of file). But because of number of lines in the first line 
-     of file we don't care about this garbage.
-  */
-  
-  my_b_seek(file, 0L);
-  my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n",
-	      LINES_IN_MASTER_INFO_WITH_SSL,
-              mi->master_log_name, llstr(mi->master_log_pos, lbuf),
-	      mi->host, mi->user,
-	      mi->password, mi->port, mi->connect_retry,
-              (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
-              mi->ssl_cipher, mi->ssl_key);
-  flush_io_cache(file);
-  DBUG_RETURN(0);
-}
-
-
-st_relay_log_info::st_relay_log_info()
-  :info_fd(-1), cur_log_fd(-1), save_temporary_tables(0),
-   cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0),
-   ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0),
-   abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0),
-   inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
-   until_log_pos(0), retried_trans(0)
-{
-  group_relay_log_name[0]= event_relay_log_name[0]=
-    group_master_log_name[0]= 0;
-  last_slave_error[0]=0; until_log_name[0]= 0;
-
-  bzero((char*) &info_file, sizeof(info_file));
-  bzero((char*) &cache_buf, sizeof(cache_buf));
-  cached_charset_invalidate();
-  pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
-  pthread_cond_init(&data_cond, NULL);
-  pthread_cond_init(&start_cond, NULL);
-  pthread_cond_init(&stop_cond, NULL);
-  pthread_cond_init(&log_space_cond, NULL);
-  relay_log.init_pthread_objects();
-}
-
-
-st_relay_log_info::~st_relay_log_info()
-{
-  pthread_mutex_destroy(&run_lock);
-  pthread_mutex_destroy(&data_lock);
-  pthread_mutex_destroy(&log_space_lock);
-  pthread_cond_destroy(&data_cond);
-  pthread_cond_destroy(&start_cond);
-  pthread_cond_destroy(&stop_cond);
-  pthread_cond_destroy(&log_space_cond);
-  relay_log.cleanup();
-}
-
-/*
-  Waits until the SQL thread reaches (has executed up to) the
-  log/position or timed out.
-
-  SYNOPSIS
-    wait_for_pos()
-    thd             client thread that sent SELECT MASTER_POS_WAIT
-    log_name        log name to wait for
-    log_pos         position to wait for 
-    timeout         timeout in seconds before giving up waiting
-
-  NOTES
-    timeout is longlong whereas it should be ulong ; but this is
-    to catch if the user submitted a negative timeout.
-
-  RETURN VALUES
-    -2          improper arguments (log_pos<0)
-                or slave not running, or master info changed
-                during the function's execution,
-                or client thread killed. -2 is translated to NULL by caller
-    -1          timed out
-    >=0         number of log events the function had to wait
-                before reaching the desired log/position
- */
-
-int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
-                                    longlong log_pos,
-                                    longlong timeout)
-{
-  if (!inited)
-    return -1;
-  int event_count = 0;
-  ulong init_abort_pos_wait;
-  int error=0;
-  struct timespec abstime; // for timeout checking
-  const char *msg;
-  DBUG_ENTER("wait_for_pos");
-  DBUG_PRINT("enter",("log_name: '%s'  log_pos: %lu  timeout: %lu",
-                      log_name->c_ptr(), (ulong) log_pos, (ulong) timeout));
-
-  set_timespec(abstime,timeout);
-  pthread_mutex_lock(&data_lock);
-  msg= thd->enter_cond(&data_cond, &data_lock,
-                       "Waiting for the slave SQL thread to "
-                       "advance position");
-  /* 
-     This function will abort when it notices that some CHANGE MASTER or
-     RESET MASTER has changed the master info.
-     To catch this, these commands modify abort_pos_wait ; We just monitor
-     abort_pos_wait and see if it has changed.
-     Why do we have this mechanism instead of simply monitoring slave_running
-     in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that
-     the SQL thread be stopped?
-     This is becasue if someones does:
-     STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE;
-     the change may happen very quickly and we may not notice that
-     slave_running briefly switches between 1/0/1.
-  */
-  init_abort_pos_wait= abort_pos_wait;
-
-  /*
-    We'll need to
-    handle all possible log names comparisons (e.g. 999 vs 1000).
-    We use ulong for string->number conversion ; this is no
-    stronger limitation than in find_uniq_filename in sql/log.cc
-  */
-  ulong log_name_extension;
-  char log_name_tmp[FN_REFLEN]; //make a char[] from String
-
-  strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1));
-
-  char *p= fn_ext(log_name_tmp);
-  char *p_end;
-  if (!*p || log_pos<0)
-  {
-    error= -2; //means improper arguments
-    goto err;
-  }
-  // Convert 0-3 to 4
-  log_pos= max(log_pos, BIN_LOG_HEADER_SIZE);
-  /* p points to '.' */
-  log_name_extension= strtoul(++p, &p_end, 10);
-  /*
-    p_end points to the first invalid character.
-    If it equals to p, no digits were found, error.
-    If it contains '\0' it means conversion went ok.
-  */
-  if (p_end==p || *p_end)
-  {
-    error= -2;
-    goto err;
-  }    
-
-  /* The "compare and wait" main loop */
-  while (!thd->killed &&
-         init_abort_pos_wait == abort_pos_wait &&
-         slave_running)
-  {
-    bool pos_reached;
-    int cmp_result= 0;
-
-    DBUG_PRINT("info",
-               ("init_abort_pos_wait: %ld  abort_pos_wait: %ld",
-                init_abort_pos_wait, abort_pos_wait));
-    DBUG_PRINT("info",("group_master_log_name: '%s'  pos: %lu",
-                       group_master_log_name, (ulong) group_master_log_pos));
-
-    /*
-      group_master_log_name can be "", if we are just after a fresh
-      replication start or after a CHANGE MASTER TO MASTER_HOST/PORT
-      (before we have executed one Rotate event from the master) or
-      (rare) if the user is doing a weird slave setup (see next
-      paragraph).  If group_master_log_name is "", we assume we don't
-      have enough info to do the comparison yet, so we just wait until
-      more data. In this case master_log_pos is always 0 except if
-      somebody (wrongly) sets this slave to be a slave of itself
-      without using --replicate-same-server-id (an unsupported
-      configuration which does nothing), then group_master_log_pos
-      will grow and group_master_log_name will stay "".
-    */
-    if (*group_master_log_name)
-    {
-      char *basename= (group_master_log_name +
-                       dirname_length(group_master_log_name));
-      /*
-        First compare the parts before the extension.
-        Find the dot in the master's log basename,
-        and protect against user's input error :
-        if the names do not match up to '.' included, return error
-      */
-      char *q= (char*)(fn_ext(basename)+1);
-      if (strncmp(basename, log_name_tmp, (int)(q-basename)))
-      {
-        error= -2;
-        break;
-      }
-      // Now compare extensions.
-      char *q_end;
-      ulong group_master_log_name_extension= strtoul(q, &q_end, 10);
-      if (group_master_log_name_extension < log_name_extension)
-        cmp_result= -1 ;
-      else
-        cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ;
-
-      pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) ||
-                    cmp_result > 0);
-      if (pos_reached || thd->killed)
-        break;
-    }
-
-    //wait for master update, with optional timeout.
-    
-    DBUG_PRINT("info",("Waiting for master update"));
-    /*
-      We are going to pthread_cond_(timed)wait(); if the SQL thread stops it
-      will wake us up.
-    */
-    if (timeout > 0)
-    {
-      /*
-        Note that pthread_cond_timedwait checks for the timeout
-        before for the condition ; i.e. it returns ETIMEDOUT 
-        if the system time equals or exceeds the time specified by abstime
-        before the condition variable is signaled or broadcast, _or_ if
-        the absolute time specified by abstime has already passed at the time
-        of the call.
-        For that reason, pthread_cond_timedwait will do the "timeoutting" job
-        even if its condition is always immediately signaled (case of a loaded
-        master).
-      */
-      error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime);
-    }
-    else
-      pthread_cond_wait(&data_cond, &data_lock);
-    DBUG_PRINT("info",("Got signal of master update or timed out"));
-    if (error == ETIMEDOUT || error == ETIME)
-    {
-      error= -1;
-      break;
-    }
-    error=0;
-    event_count++;
-    DBUG_PRINT("info",("Testing if killed or SQL thread not running"));
-  }
-
-err:
-  thd->exit_cond(msg);
-  DBUG_PRINT("exit",("killed: %d  abort: %d  slave_running: %d \
-improper_arguments: %d  timed_out: %d",
-                     thd->killed_errno(),
-                     (int) (init_abort_pos_wait != abort_pos_wait),
-                     (int) slave_running,
-                     (int) (error == -2),
-                     (int) (error == -1)));
-  if (thd->killed || init_abort_pos_wait != abort_pos_wait ||
-      !slave_running) 
-  {
-    error= -2;
-  }
-  DBUG_RETURN( error ? error : event_count );
-}
-
 void set_slave_thread_options(THD* thd)
 {
   thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) |
@@ -2404,7 +1152,7 @@
   thd->variables.completion_type= 0;
 }
 
-void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli)
+void set_slave_thread_default_charset(THD* thd, Relay_log_info *rli)
 {
   thd->variables.character_set_client=
     global_system_variables.character_set_client;
@@ -2464,7 +1212,7 @@
 
 #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
   sigset_t set;
-  VOID(sigemptyset(&set));			// Get mask in use
+  VOID(sigemptyset(&set));                      // Get mask in use
   VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
 #endif
 
@@ -2478,8 +1226,8 @@
 }
 
 
-static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
-		      void* thread_killed_arg)
+int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
+	       void* thread_killed_arg)
 {
   int nap_time;
   thr_alarm_t alarmed;
@@ -2507,8 +1255,8 @@
 }
 
 
-static int request_dump(MYSQL* mysql, MASTER_INFO* mi,
-			bool *suppress_warnings)
+static int request_dump(MYSQL* mysql, Master_info* mi,
+                        bool *suppress_warnings)
 {
   char buf[FN_REFLEN + 10];
   int len;
@@ -2530,11 +1278,11 @@
       now we just fill up the error log :-)
     */
     if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
-      *suppress_warnings= 1;			// Suppress reconnect warning
+      *suppress_warnings= 1;                    // Suppress reconnect warning
     else
       sql_print_error("Error on COM_BINLOG_DUMP: %d  %s, will retry in %d secs",
-		      mysql_errno(mysql), mysql_error(mysql),
-		      master_connect_retry);
+                      mysql_errno(mysql), mysql_error(mysql),
+                      mi->connect_retry);
     DBUG_RETURN(1);
   }
 
@@ -2576,19 +1324,19 @@
   
   SYNOPSIS
     read_event()
-    mysql		MySQL connection
-    mi			Master connection information
-    suppress_warnings	TRUE when a normal net read timeout has caused us to
-			try a reconnect.  We do not want to print anything to
-			the error log in this case because this a anormal
-			event in an idle server.
+    mysql               MySQL connection
+    mi                  Master connection information
+    suppress_warnings   TRUE when a normal net read timeout has caused us to
+                        try a reconnect.  We do not want to print anything to
+                        the error log in this case because this a anormal
+                        event in an idle server.
 
     RETURN VALUES
-    'packet_error'	Error
-    number		Length of packet
+    'packet_error'      Error
+    number              Length of packet
 */
 
-static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
+static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings)
 {
   ulong len;
 
@@ -2596,11 +1344,9 @@
   /*
     my_real_read() will time us out
     We check if we were told to die, and if not, try reading again
-
-    TODO:  Move 'events_till_disconnect' to the MASTER_INFO structure
   */
 #ifndef DBUG_OFF
-  if (disconnect_slave_event_count && !(events_till_disconnect--))
+  if (opt_disconnect_slave_event_count && !(mi->events_till_disconnect--))
     return packet_error;      
 #endif
   
@@ -2610,34 +1356,36 @@
     if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
     {
       /*
-	We are trying a normal reconnect after a read timeout;
-	we suppress prints to .err file as long as the reconnect
-	happens without problems
+        We are trying a normal reconnect after a read timeout;
+        we suppress prints to .err file as long as the reconnect
+        happens without problems
       */
       *suppress_warnings= TRUE;
     }
     else
-      sql_print_error("Error reading packet from server: %s ( server_errno=%d)",
-		      mysql_error(mysql), mysql_errno(mysql));
+      sql_print_error("I/O:%s:Error reading packet from server: %s "
+                      "(server_errno=%d)",
+                      mi->named_master,
+                      mysql_error(mysql), mysql_errno(mysql));
     return packet_error;
   }
 
   /* Check if eof packet */
   if (len < 8 && mysql->net.read_pos[0] == 254)
   {
-    sql_print_information("Slave: received end packet from server, apparent "
+    sql_print_information("I/O:%s:Received end packet from server, apparent "
                           "master shutdown: %s",
-		     mysql_error(mysql));
+                          mi->named_master, mysql_error(mysql));
      return packet_error;
   }
   
   DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n",
-		      len, mysql->net.read_pos[4]));
+                      len, mysql->net.read_pos[4]));
   return len - 1;   
 }
 
 
-int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
+int check_expected_error(THD* thd, Relay_log_info* rli, int expected_error)
 {
   switch (expected_error) {
   case ER_NET_READ_ERROR:
@@ -2650,316 +1398,13 @@
   }
 }
 
-/*
-     Check if condition stated in UNTIL clause of START SLAVE is reached.
-   SYNOPSYS
-     st_relay_log_info::is_until_satisfied()
-   DESCRIPTION
-     Checks if UNTIL condition is reached. Uses caching result of last 
-     comparison of current log file name and target log file name. So cached 
-     value should be invalidated if current log file name changes 
-     (see st_relay_log_info::notify_... functions).
-     
-     This caching is needed to avoid of expensive string comparisons and 
-     strtol() conversions needed for log names comparison. We don't need to
-     compare them each time this function is called, we only need to do this 
-     when current log name changes. If we have UNTIL_MASTER_POS condition we 
-     need to do this only after Rotate_log_event::exec_event() (which is 
-     rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS 
-     condition then we should invalidate cached comarison value after 
-     inc_group_relay_log_pos() which called for each group of events (so we
-     have some benefit if we have something like queries that use 
-     autoincrement or if we have transactions).
-     
-     Should be called ONLY if until_condition != UNTIL_NONE !
-   RETURN VALUE
-     true - condition met or error happened (condition seems to have 
-            bad log file name)
-     false - condition not met
-*/
-
-bool st_relay_log_info::is_until_satisfied()
-{
-  const char *log_name;
-  ulonglong log_pos;
-
-  DBUG_ASSERT(until_condition != UNTIL_NONE);
-  
-  if (until_condition == UNTIL_MASTER_POS)
-  {
-    log_name= group_master_log_name;
-    log_pos= group_master_log_pos;
-  }
-  else
-  { /* until_condition == UNTIL_RELAY_POS */
-    log_name= group_relay_log_name;
-    log_pos= group_relay_log_pos;
-  }
-  
-  if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN)
-  {
-    /*
-      We have no cached comparison results so we should compare log names
-      and cache result.
-      If we are after RESET SLAVE, and the SQL slave thread has not processed
-      any event yet, it could be that group_master_log_name is "". In that case,
-      just wait for more events (as there is no sensible comparison to do).
-    */
-
-    if (*log_name)
-    {
-      const char *basename= log_name + dirname_length(log_name);
-      
-      const char *q= (const char*)(fn_ext(basename)+1);
-      if (strncmp(basename, until_log_name, (int)(q-basename)) == 0)
-      {
-        /* Now compare extensions. */
-        char *q_end;
-        ulong log_name_extension= strtoul(q, &q_end, 10);
-        if (log_name_extension < until_log_name_extension)
-          until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_LESS;
-        else
-          until_log_names_cmp_result= 
-            (log_name_extension > until_log_name_extension) ? 
-            UNTIL_LOG_NAMES_CMP_GREATER : UNTIL_LOG_NAMES_CMP_EQUAL ;
-      }
-      else  
-      {
-        /* Probably error so we aborting */
-        sql_print_error("Slave SQL thread is stopped because UNTIL "
-                        "condition is bad.");
-        return TRUE;
-      }
-    }
-    else
-      return until_log_pos == 0;
-  }
-    
-  return ((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && 
-           log_pos >= until_log_pos) ||
-          until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER);
-}
-
-
-void st_relay_log_info::cached_charset_invalidate()
-{
-  /* Full of zeroes means uninitialized. */
-  bzero(cached_charset, sizeof(cached_charset));
-}
-
-
-bool st_relay_log_info::cached_charset_compare(char *charset)
-{
-  if (bcmp(cached_charset, charset, sizeof(cached_charset)))
-  {
-    memcpy(cached_charset, charset, sizeof(cached_charset));
-    return 1;
-  }
-  return 0;
-}
-
-
-static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
-{
-  /*
-     We acquire this mutex since we need it for all operations except
-     event execution. But we will release it in places where we will
-     wait for something for example inside of next_event().
-   */
-  pthread_mutex_lock(&rli->data_lock);
-
-  if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE &&
-      rli->is_until_satisfied())
-  {
-    sql_print_error("Slave SQL thread stopped because it reached its"
-                    " UNTIL position %ld", (long) rli->until_pos());
-    /*
-      Setting abort_slave flag because we do not want additional message about
-      error in query execution to be printed.
-    */
-    rli->abort_slave= 1;
-    pthread_mutex_unlock(&rli->data_lock);
-    return 1;
-  }
-
-  Log_event * ev = next_event(rli);
-
-  DBUG_ASSERT(rli->sql_thd==thd);
-
-  if (sql_slave_killed(thd,rli))
-  {
-    pthread_mutex_unlock(&rli->data_lock);
-    delete ev;
-    return 1;
-  }
-  if (ev)
-  {
-    int type_code = ev->get_type_code();
-    int exec_res;
-
-    /*
-      Queries originating from this server must be skipped.
-      Low-level events (Format_desc, Rotate, Stop) from this server
-      must also be skipped. But for those we don't want to modify
-      group_master_log_pos, because these events did not exist on the master.
-      Format_desc is not completely skipped.
-      Skip queries specified by the user in slave_skip_counter.
-      We can't however skip events that has something to do with the
-      log files themselves.
-      Filtering on own server id is extremely important, to ignore execution of
-      events created by the creation/rotation of the relay log (remember that
-      now the relay log starts with its Format_desc, has a Rotate etc).
-    */
-
-    DBUG_PRINT("info",("type_code=%d, server_id=%d",type_code,ev->server_id));
-
-    if ((ev->server_id == (uint32) ::server_id &&
-         !replicate_same_server_id &&
-         type_code != FORMAT_DESCRIPTION_EVENT) ||
-        (rli->slave_skip_counter &&
-         type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
-         type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
-    {
-      DBUG_PRINT("info", ("event skipped"));
-      if (thd->options & OPTION_BEGIN)
-        rli->inc_event_relay_log_pos();
-      else
-      {
-        rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
-                                      type_code == STOP_EVENT ||
-                                      type_code == FORMAT_DESCRIPTION_EVENT) ?
-                                     LL(0) : ev->log_pos,
-                                     1/* skip lock*/);
-        flush_relay_log_info(rli);
-      }
-
-      /*
-        Protect against common user error of setting the counter to 1
-        instead of 2 while recovering from an insert which used auto_increment,
-        rand or user var.
-      */
-      if (rli->slave_skip_counter &&
-          !((type_code == INTVAR_EVENT ||
-             type_code == RAND_EVENT ||
-             type_code == USER_VAR_EVENT) &&
-            rli->slave_skip_counter == 1) &&
-          /*
-            The events from ourselves which have something to do with the relay
-            log itself must be skipped, true, but they mustn't decrement
-            rli->slave_skip_counter, because the user is supposed to not see
-            these events (they are not in the master's binlog) and if we
-            decremented, START SLAVE would for example decrement when it sees
-            the Rotate, so the event which the user probably wanted to skip
-            would not be skipped.
-          */
-          !(ev->server_id == (uint32) ::server_id &&
-            (type_code == ROTATE_EVENT || type_code == STOP_EVENT ||
-             type_code == START_EVENT_V3 || type_code == FORMAT_DESCRIPTION_EVENT)))
-        --rli->slave_skip_counter;
-      pthread_mutex_unlock(&rli->data_lock);
-      delete ev;
-      return 0;                                 // avoid infinite update loops
-    }
-    pthread_mutex_unlock(&rli->data_lock);
-
-    thd->server_id = ev->server_id; // use the original server id for logging
-    thd->set_time();				// time the query
-    thd->lex->current_select= 0;
-    if (!ev->when)
-      ev->when = time(NULL);
-    ev->thd = thd;
-    exec_res = ev->exec_event(rli);
-    DBUG_ASSERT(rli->sql_thd==thd);
-    /*
-       Format_description_log_event should not be deleted because it will be
-       used to read info about the relay log's format; it will be deleted when
-       the SQL thread does not need it, i.e. when this thread terminates.
-    */
-    if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
-    {
-      DBUG_PRINT("info", ("Deleting the event after it has been executed"));
-      delete ev;
-    }
-    if (slave_trans_retries)
-    {
-      if (exec_res &&
-          (thd->net.last_errno == ER_LOCK_DEADLOCK ||
-           thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) &&
-          !thd->is_fatal_error)
-      {
-        const char *errmsg;
-        /*
-          We were in a transaction which has been rolled back because of a
-          deadlock (currently, InnoDB deadlock detected by InnoDB) or lock
-          wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to
-          BEGIN log event and retry it all again.
-          We have to not only seek but also
-          a) init_master_info(), to seek back to hot relay log's start for later
-          (for when we will come back to this hot log after re-processing the
-          possibly existing old logs where BEGIN is: check_binlog_magic() will
-          then need the cache to be at position 0 (see comments at beginning of
-          init_master_info()).
-          b) init_relay_log_pos(), because the BEGIN may be an older relay log.
-        */
-        if (rli->trans_retries < slave_trans_retries)
-        {
-          if (init_master_info(rli->mi, 0, 0, 0, SLAVE_SQL))
-            sql_print_error("Failed to initialize the master info structure");
-          else if (init_relay_log_pos(rli,
-                                      rli->group_relay_log_name,
-                                      rli->group_relay_log_pos,
-                                      1, &errmsg, 1))
-            sql_print_error("Error initializing relay log position: %s",
-                            errmsg);
-          else
-          {
-            exec_res= 0;
-	    /* chance for concurrent connection to get more locks */
-            safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
-		       (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);
-            pthread_mutex_lock(&rli->data_lock); // because of SHOW STATUS
-	    rli->trans_retries++;
-            rli->retried_trans++;
-            pthread_mutex_unlock(&rli->data_lock);
-            DBUG_PRINT("info", ("Slave retries transaction "
-                                "rli->trans_retries: %lu", rli->trans_retries));
-	  }
-        }
-        else
-          sql_print_error("Slave SQL thread retried transaction %lu time(s) "
-                          "in vain, giving up. Consider raising the value of "
-                          "the slave_transaction_retries variable.",
-                          slave_trans_retries);
-      }
-      if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
-         rli->trans_retries= 0; // restart from fresh
-     }
-    return exec_res;
-  }
-  else
-  {
-    pthread_mutex_unlock(&rli->data_lock);
-    slave_print_error(rli, 0, "\
-Could not parse relay log event entry. The possible reasons are: the master's \
-binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
-binary log), the slave's relay log is corrupted (you can check this by running \
-'mysqlbinlog' on the relay log), a network problem, or a bug in the master's \
-or slave's MySQL code. If you want to check the master's binary log or slave's \
-relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \
-on this slave.\
-");
-    return 1;
-  }
-}
-
-
 /* Slave I/O Thread entry point */
 
 extern "C" pthread_handler_decl(handle_slave_io,arg)
 {
   THD *thd; // needs to be first for thread_stack
   MYSQL *mysql;
-  MASTER_INFO *mi = (MASTER_INFO*)arg;
+  Master_info *mi= (Master_info*)arg;
   char llbuff[22];
   uint retry_count;
 
@@ -2970,7 +1415,7 @@
 #ifndef DBUG_OFF
 slave_begin:
 #endif
-  DBUG_ASSERT(mi->inited);
+  DBUG_ASSERT(mi->is_inited());
   mysql= NULL ;
   retry_count= 0;
 
@@ -2979,7 +1424,8 @@
   mi->slave_run_id++;
 
 #ifndef DBUG_OFF
-  mi->events_till_abort = abort_slave_event_count;
+  /* Initialize event_till_abort for this subslave */
+  mi->events_till_abort= opt_abort_slave_event_count;
 #endif
 
   thd= new THD; // note that contructor of THD uses DBUG_ !
@@ -3004,8 +1450,8 @@
   pthread_cond_broadcast(&mi->start_cond);
 
   DBUG_PRINT("master_info",("log_file_name: '%s'  position: %s",
-			    mi->master_log_name,
-			    llstr(mi->master_log_pos,llbuff)));
+                            mi->master_log_name,
+                            llstr(mi->master_log_pos,llbuff)));
 
   if (!(mi->mysql = mysql = mysql_init(NULL)))
   {
@@ -3016,14 +1462,14 @@
   thd->proc_info = "Connecting to master";
   // we can get killed during safe_connect
   if (!safe_connect(thd, mysql, mi))
-    sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',\
-  replication started in log '%s' at position %s", mi->user,
-		    mi->host, mi->port,
-		    IO_RPL_LOG_NAME,
-		    llstr(mi->master_log_pos,llbuff));
+    sql_print_information("I/O:%s:Started at position '%s:%s'. Connected to '%s@%s:%d'", 
+                          mi->named_master,
+                          IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff),
+			  mi->user, mi->host, mi->port);
   else
   {
-    sql_print_information("Slave I/O thread killed while connecting to master");
+    sql_print_information("I/O:%s:killed while connecting to master",
+                          mi->named_master);
     goto err;
   }
 
@@ -3058,9 +1504,9 @@
       sql_print_error("Failed on request_dump()");
       if (io_slave_killed(thd,mi))
       {
-	sql_print_information("Slave I/O thread killed while requesting master \
-dump");
-	goto err;
+        sql_print_information("I/O:%s:killed while requesting master dump",
+                              mi->named_master);
+        goto err;
       }
 
       mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
@@ -3070,41 +1516,43 @@
 #endif
       end_server(mysql);
       /*
-	First time retry immediately, assuming that we can recover
-	right away - if first time fails, sleep between re-tries
-	hopefuly the admin can fix the problem sometime
+        First time retry immediately, assuming that we can recover
+        right away - if first time fails, sleep between re-tries
+        hopefuly the admin can fix the problem sometime
       */
       if (retry_count++)
       {
-	if (retry_count > master_retry_count)
-	  goto err;				// Don't retry forever
-	safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-		   (void*)mi);
+        if (retry_count > master_retry_count)
+          goto err;                             // Don't retry forever
+        safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
+                   (void*)mi);
       }
-      if (io_slave_killed(thd,mi))
+      if (io_slave_killed(thd, mi))
       {
-	sql_print_information("Slave I/O thread killed while retrying master \
-dump");
-	goto err;
+        sql_print_information("I/O:%s:Killed while retrying master dump",
+                              mi->named_master);
+        goto err;
       }
 
       thd->proc_info = "Reconnecting after a failed binlog dump request";
       if (!suppress_warnings)
-	sql_print_error("Slave I/O thread: failed dump request, \
-reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
-			llstr(mi->master_log_pos,llbuff));
+        sql_print_error("I/O:%s:Failed dump request, "
+                        "reconnecting to retry, position '%s:%s'",
+                        mi->named_master,
+                        IO_RPL_LOG_NAME,
+                        llstr(mi->master_log_pos,llbuff));
       if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
-	  io_slave_killed(thd,mi))
+          io_slave_killed(thd,mi))
       {
-	sql_print_information("Slave I/O thread killed during or \
-after reconnect");
-	goto err;
+        sql_print_information("I/O:%s:Killed during or after reconnect",
+                              mi->named_master);
+        goto err;
       }
 
       goto connected;
     }
 
-    while (!io_slave_killed(thd,mi))
+    while (!io_slave_killed(thd, mi))
     {
       bool suppress_warnings= 0;
       /*
@@ -3117,74 +1565,81 @@
       ulong event_len = read_event(mysql, mi, &suppress_warnings);
       if (io_slave_killed(thd,mi))
       {
-	if (global_system_variables.log_warnings)
-	  sql_print_information("Slave I/O thread killed while reading event");
-	goto err;
+        if (global_system_variables.log_warnings)
+          sql_print_information("I/O:%s:Killed while reading event",
+                                mi->named_master);
+        goto err;
       }
 
       if (event_len == packet_error)
       {
-	uint mysql_error_number= mysql_errno(mysql);
-	if (mysql_error_number == ER_NET_PACKET_TOO_LARGE)
-	{
-	  sql_print_error("\
-Log entry on master is longer than max_allowed_packet (%ld) on \
-slave. If the entry is correct, restart the server with a higher value of \
-max_allowed_packet",
-			  thd->variables.max_allowed_packet);
-	  goto err;
-	}
-	if (mysql_error_number == ER_MASTER_FATAL_ERROR_READING_BINLOG)
-	{
-	  sql_print_error(ER(mysql_error_number), mysql_error_number,
-			  mysql_error(mysql));
-	  goto err;
-	}
+        uint mysql_error_number= mysql_errno(mysql);
+        if (mysql_error_number == ER_NET_PACKET_TOO_LARGE)
+        {
+          sql_print_error("I/O:%s:Log entry on master is longer than "
+                          "max_allowed_packet (%ld) on slave. "
+                          "If the entry is correct, restart the server "
+                          "with a higher value of max_allowed_packet",
+                          mi->named_master,
+                          thd->variables.max_allowed_packet);
+          goto err;
+        }
+        if (mysql_error_number == ER_MASTER_FATAL_ERROR_READING_BINLOG)
+        {
+          sql_print_error(ER(mysql_error_number), mysql_error_number,
+                          mysql_error(mysql));
+          goto err;
+        }
         mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
-	thd->proc_info = "Waiting to reconnect after a failed master event read";
+        thd->proc_info = "Waiting to reconnect after a failed master event read";
 #ifdef SIGNAL_WITH_VIO_CLOSE
         thd->clear_active_vio();
 #endif
-	end_server(mysql);
-	if (retry_count++)
-	{
-	  if (retry_count > master_retry_count)
-	    goto err;				// Don't retry forever
-	  safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-		     (void*) mi);
-	}
-	if (io_slave_killed(thd,mi))
-	{
-	  if (global_system_variables.log_warnings)
-	    sql_print_information("Slave I/O thread killed while waiting to \
-reconnect after a failed read");
-	  goto err;
-	}
-	thd->proc_info = "Reconnecting after a failed master event read";
-	if (!suppress_warnings)
-	  sql_print_information("Slave I/O thread: Failed reading log event, \
-reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
-			  llstr(mi->master_log_pos, llbuff));
-	if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
-	    io_slave_killed(thd,mi))
-	{
-	  if (global_system_variables.log_warnings)
-	    sql_print_information("Slave I/O thread killed during or after a \
-reconnect done to recover from failed read");
-	  goto err;
-	}
-	goto connected;
+        end_server(mysql);
+        if (retry_count++)
+        {
+          if (retry_count > master_retry_count)
+            goto err;                           // Don't retry forever
+          safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
+                     (void*) mi);
+        }
+        if (io_slave_killed(thd,mi))
+        {
+          if (global_system_variables.log_warnings)
+            sql_print_information("I/O:%s:Killed while waiting to reconnect "
+                                  "after a failed read",
+                                  mi->named_master);
+          goto err;
+        }
+        thd->proc_info = "Reconnecting after a failed master event read";
+        if (!suppress_warnings)
+          sql_print_information("I/O:%s:Failed reading log event, "
+                                "reconnecting to retry, position '%s:%s'", 
+                                mi->named_master,
+                                IO_RPL_LOG_NAME,
+                                llstr(mi->master_log_pos, llbuff));
+        if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
+            io_slave_killed(thd,mi))
+        {
+          if (global_system_variables.log_warnings)
+            sql_print_information("I/O:%s:Killed during or after a "
+                                  "reconnect done to recover from failed read",
+                                  mi->named_master);
+          goto err;
+        }
+        goto connected;
       } // if (event_len == packet_error)
 
-      retry_count=0;			// ok event, reset retry counter
+      retry_count=0;                    // ok event, reset retry counter
       thd->proc_info = "Queueing master event to the relay log";
       if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
-		      event_len))
+                      event_len))
       {
-	sql_print_error("Slave I/O thread could not queue event from master");
-	goto err;
+        sql_print_error("I/O:%s:Could not queue event from master",
+                        mi->named_master);
+        goto err;
       }
-      flush_master_info(mi, 1); /* sure that we can flush the relay log */
+      mi->storage_flush(1 /* We are sure that we can flush the relay log */);
       /*
         See if the relay logs take too much space.
         We don't lock mi->rli.log_space_lock here; this dirty read saves time
@@ -3200,8 +1655,8 @@
 #ifndef DBUG_OFF
       {
         char llbuf1[22], llbuf2[22];
-        DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s \
-ignore_log_space_limit=%d",
+        DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s "
+                            "ignore_log_space_limit=%d",
                             llstr(mi->rli.log_space_limit,llbuf1),
                             llstr(mi->rli.log_space_total,llbuf2),
                             (int) mi->rli.ignore_log_space_limit)); 
@@ -3209,30 +1664,35 @@
 #endif
 
       if (mi->rli.log_space_limit && mi->rli.log_space_limit <
-	  mi->rli.log_space_total &&
+          mi->rli.log_space_total &&
           !mi->rli.ignore_log_space_limit)
-	if (wait_for_relay_log_space(&mi->rli))
-	{
-	  sql_print_error("Slave I/O thread aborted while waiting for relay \
-log space");
-	  goto err;
-	}
-      // TODO: check debugging abort code
+        if (wait_for_relay_log_space(&mi->rli))
+        {
+          sql_print_error("I/O:%s:Thread aborted while waiting for relay "
+                          "log space", mi->named_master);
+          goto err;
+        }
 #ifndef DBUG_OFF
-      if (abort_slave_event_count && !--events_till_abort)
+      /*
+	TODO: --event_till_abort is broken since before 
+	and should be fixed.
+      */
+      if (opt_abort_slave_event_count && 0 /*! --events_till_abort*/)
       {
-	sql_print_error("Slave I/O thread: debugging abort");
-	goto err;
+        sql_print_information("I/O:%s:Forced resurrection of I/O thread "
+                              "(--abort-slave-event-count=%d)",
+                              mi->named_master, opt_abort_slave_event_count);
+        goto err;
       }
 #endif
     } 
-  }
+  } 
 
-  // error = 0;
 err:
-  // print the current replication position
-  sql_print_information("Slave I/O thread exiting, read up to log '%s', position %s",
-		  IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
+  sql_print_information("I/O:%s:Stopped. Transfered up to position '%s:%s'",
+                        mi->named_master,
+                        IO_RPL_LOG_NAME, 
+                        llstr(mi->master_log_pos,llbuff));
   VOID(pthread_mutex_lock(&LOCK_thread_count));
   thd->query = thd->db = 0; // extra safety
   thd->query_length= thd->db_length= 0;
@@ -3249,7 +1709,7 @@
   /* Forget the relay log's format */
   delete mi->rli.relay_log.description_event_for_queue;
   mi->rli.relay_log.description_event_for_queue= 0;
-  // TODO: make rpl_status part of MASTER_INFO
+  // TODO: make rpl_status part of Master_info
   change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
   mi->abort_slave = 0; // TODO: check if this is needed
   DBUG_ASSERT(thd->net.buff != 0);
@@ -3258,15 +1718,15 @@
   THD_CHECK_SENTRY(thd);
   delete thd;
   pthread_mutex_unlock(&LOCK_thread_count);
-  pthread_cond_broadcast(&mi->stop_cond);	// tell the world we are done
+  pthread_cond_broadcast(&mi->stop_cond);       // tell the world we are done
   pthread_mutex_unlock(&mi->run_lock);
 #ifndef DBUG_OFF
-  if (abort_slave_event_count && !events_till_abort)
+  if (opt_abort_slave_event_count && !mi->events_till_abort)
     goto slave_begin;
 #endif  
   my_thread_end();
   pthread_exit(0);
-  DBUG_RETURN(0);				// Can't return anything here
+  DBUG_RETURN(0);                               // Can't return anything here
 }
 
 
@@ -3274,9 +1734,10 @@
 
 extern "C" pthread_handler_decl(handle_slave_sql,arg)
 {
-  THD *thd;			/* needs to be first for thread_stack */
+  THD *thd;                     /* needs to be first for thread_stack */
   char llbuff[22],llbuff1[22];
-  RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli; 
+  Master_info* mi= (Master_info*) arg;
+  Relay_log_info* rli= &((Master_info*) arg)->rli; 
   const char *errmsg;
 
   // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
@@ -3287,12 +1748,12 @@
 slave_begin:  
 #endif  
 
-  DBUG_ASSERT(rli->inited);
+  DBUG_ASSERT(rli->is_inited());
   pthread_mutex_lock(&rli->run_lock);
   DBUG_ASSERT(!rli->slave_running);
   errmsg= 0;
 #ifndef DBUG_OFF  
-  rli->events_till_abort = abort_slave_event_count;
+  ((Master_info*)arg)->events_till_abort = opt_abort_slave_event_count;
 #endif  
 
   thd = new THD; // note that contructor of THD uses DBUG_ !
@@ -3310,7 +1771,8 @@
     */
     pthread_cond_broadcast(&rli->start_cond);
     pthread_mutex_unlock(&rli->run_lock);
-    sql_print_error("Failed during slave thread initialization");
+    sql_print_error("SQL:%s:Failed during thread initialization",
+                    mi->named_master);
     goto err;
   }
   thd->init_for_queries();
@@ -3342,7 +1804,7 @@
     now.
     But the master timestamp is reset by RESET SLAVE & CHANGE MASTER.
   */
-  clear_slave_error(rli);
+  rli->clear_slave_error();
 
   //tell the I/O thread to take relay_log_space_limit into account from now on
   pthread_mutex_lock(&rli->log_space_lock);
@@ -3350,14 +1812,13 @@
   pthread_mutex_unlock(&rli->log_space_lock);
   rli->trans_retries= 0; // start from "no error"
 
-  if (init_relay_log_pos(rli,
-			 rli->group_relay_log_name,
-			 rli->group_relay_log_pos,
-			 1 /*need data lock*/, &errmsg,
-                         1 /*look for a description_event*/))
+  if (rli->init_relay_log_pos(rli->group_relay_log_name,
+                              rli->group_relay_log_pos,
+                              1 /*need data lock*/, &errmsg,
+                              1 /*look for a description_event*/))
   {
-    sql_print_error("Error initializing relay log position: %s",
-		    errmsg);
+    sql_print_error("SQL:%s:Error initializing relay log position: %s",
+                    mi->named_master, errmsg);
     goto err;
   }
   THD_CHECK_SENTRY(thd);
@@ -3388,13 +1849,15 @@
   DBUG_ASSERT(rli->sql_thd == thd);
 
   DBUG_PRINT("master_info",("log_file_name: %s  position: %s",
-			    rli->group_master_log_name,
-			    llstr(rli->group_master_log_pos,llbuff)));
+                            rli->group_master_log_name,
+                            llstr(rli->group_master_log_pos,llbuff)));
   if (global_system_variables.log_warnings)
-    sql_print_information("Slave SQL thread initialized, starting replication in \
-log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
-		    llstr(rli->group_master_log_pos,llbuff),rli->group_relay_log_name,
-		    llstr(rli->group_relay_log_pos,llbuff1));
+    sql_print_information("SQL:%s:Started at position '%s:%s', relay '%s:%s'",
+                          rli->mi->named_master,
+                          RPL_LOG_NAME, 
+                          llstr(rli->group_master_log_pos,llbuff),
+                          rli->group_relay_log_name,
+                          llstr(rli->group_relay_log_pos,llbuff1));
 
   /* execute init_slave variable */
   if (sys_init_slave.value_length)
@@ -3402,37 +1865,40 @@
     execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave);
     if (thd->query_error)
     {
-      sql_print_error("\
-Slave SQL thread aborted. Can't execute init_slave query");
+      sql_print_error("SQL:%s:Slave SQL thread aborted. "
+                      "Can't execute init_slave query", mi->named_master);
       goto err;
     }
   }
 
   /* Read queries from the IO/THREAD until this thread is killed */
 
-  while (!sql_slave_killed(thd,rli))
+  while (!sql_slave_killed(thd, rli))
   {
     thd->proc_info = "Reading event from the relay log";
     DBUG_ASSERT(rli->sql_thd == thd);
     THD_CHECK_SENTRY(thd);
-    if (exec_relay_log_event(thd,rli))
+    if (rli->exec_relay_log_event(thd))
     {
       // do not scare the user if SQL thread was simply killed or stopped
-      if (!sql_slave_killed(thd,rli))
-        sql_print_error("\
-Error running query, slave SQL thread aborted. Fix the problem, and restart \
-the slave SQL thread with \"SLAVE START\". We stopped at log \
-'%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
+      if (!sql_slave_killed(thd, rli))
+        sql_print_error("SQL:%s:Statement execution error, slave SQL thread "
+			"stopped at position %s:%s. "
+                        "Fix the problem, and restart the slave SQL thread with "
+                        "\"SLAVE START FOR MASTER '%s'\".", 
+                        mi->named_master, mi->named_master,
+                        RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
       goto err;
     }
   }
 
+ err:
   /* Thread stopped. Print the current replication position to the log */
-  sql_print_information("Slave SQL thread exiting, replication stopped in log "
- 			"'%s' at position %s",
-		        RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff));
+  sql_print_information("SQL:%s:Stopped. Applied up to position '%s:%s'",
+                        mi->named_master,
+                        RPL_LOG_NAME, 
+                        llstr(rli->group_master_log_pos,llbuff));
 
- err:
   VOID(pthread_mutex_lock(&LOCK_thread_count));
   /*
     Some extra safety, which should not been needed (normally, event deletion
@@ -3454,7 +1920,9 @@
   rli->relay_log.description_event_for_exec= 0;
   /* Wake up master_pos_wait() */
   pthread_mutex_unlock(&rli->data_lock);
-  DBUG_PRINT("info",("Signaling possibly waiting master_pos_wait() functions"));
+  DBUG_PRINT("info",("SQL:%s:Signaling possibly waiting master_pos_wait() "
+                     "functions",
+                     rli->mi->named_master));
   pthread_cond_broadcast(&rli->data_cond);
   rli->ignore_log_space_limit= 0; /* don't need any lock */
   /* we die so won't remember charset - re-update them on next thread start */
@@ -3479,12 +1947,12 @@
   // tell the world we are done
   pthread_mutex_unlock(&rli->run_lock);
 #ifndef DBUG_OFF // TODO: reconsider the code below
-  if (abort_slave_event_count && !rli->events_till_abort)
+  if (opt_abort_slave_event_count && !((Master_info*)arg)->events_till_abort)
     goto slave_begin;
 #endif  
   my_thread_end();
   pthread_exit(0);
-  DBUG_RETURN(0);				// Can't return anything here
+  DBUG_RETURN(0);                               // Can't return anything here
 }
 
 
@@ -3492,7 +1960,7 @@
   process_io_create_file()
 */
 
-static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
+static int process_io_create_file(Master_info* mi, Create_file_log_event* cev)
 {
   int error = 1;
   ulong num_bytes;
@@ -3516,8 +1984,8 @@
   
   if (unlikely(net_request_file(net,cev->fname)))
   {
-    sql_print_error("Slave I/O: failed requesting download of '%s'",
-		    cev->fname);
+    sql_print_error("I/O:%s:Failed requesting download of '%s'",
+                    mi->named_master, cev->fname);
     goto err;
   }
 
@@ -3533,13 +2001,13 @@
     {
       if (unlikely((num_bytes=my_net_read(net)) == packet_error))
       {
-	sql_print_error("Network read error downloading '%s' from master",
-			cev->fname);
-	goto err;
+        sql_print_error("I/O:%s:Network read error downloading '%s' "
+                        "from master", mi->named_master, cev->fname);
+        goto err;
       }
       if (unlikely(!num_bytes)) /* eof */
       {
-	net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
+        net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
         /*
           If we wrote Create_file_log_event, then we need to write
           Execute_load_log_event. If we did not write Create_file_log_event,
@@ -3547,43 +2015,43 @@
           INFILE had not existed, i.e. write nothing.
         */
         if (unlikely(cev_not_written))
-	  break;
-	Execute_load_log_event xev(thd,0,0);
-	xev.log_pos = cev->log_pos;
-	if (unlikely(mi->rli.relay_log.append(&xev)))
-	{
-	  sql_print_error("Slave I/O: error writing Exec_load event to \
-relay log");
-	  goto err;
-	}
-	mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
-	break;
+          break;
+        Execute_load_log_event xev(thd,0,0);
+        xev.log_pos = cev->log_pos;
+        if (unlikely(mi->rli.relay_log.append(&xev)))
+        {
+          sql_print_error("I/O:%s:Error writing Exec_load event to "
+                          "relay log", mi->named_master);
+          goto err;
+        }
+        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        break;
       }
       if (unlikely(cev_not_written))
       {
-	cev->block = (char*)net->read_pos;
-	cev->block_len = num_bytes;
-	if (unlikely(mi->rli.relay_log.append(cev)))
-	{
-	  sql_print_error("Slave I/O: error writing Create_file event to \
-relay log");
-	  goto err;
-	}
-	cev_not_written=0;
-	mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
+        cev->block = (char*)net->read_pos;
+        cev->block_len = num_bytes;
+        if (unlikely(mi->rli.relay_log.append(cev)))
+        {
+          sql_print_error("I/O:%s:Error writing Create_file event to "
+                          "relay log", mi->named_master);
+          goto err;
+        }
+        cev_not_written=0;
+        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
       }
       else
       {
-	aev.block = (char*)net->read_pos;
-	aev.block_len = num_bytes;
-	aev.log_pos = cev->log_pos;
-	if (unlikely(mi->rli.relay_log.append(&aev)))
-	{
-	  sql_print_error("Slave I/O: error writing Append_block event to \
-relay log");
-	  goto err;
-	}
-	mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ;
+        aev.block = (char*)net->read_pos;
+        aev.block_len = num_bytes;
+        aev.log_pos = cev->log_pos;
+        if (unlikely(mi->rli.relay_log.append(&aev)))
+        {
+          sql_print_error("I/O:%s:Error writing Append_block event to "
+                          "relay log", mi->named_master);
+          goto err;
+        }
+        mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total) ;
       }
     }
   }
@@ -3598,8 +2066,8 @@
 
   SYNOPSIS
     process_io_rotate()
-    mi			master_info for the slave
-    rev			The rotate log event read from the binary log
+    mi                  master_info for the slave
+    rev                 The rotate log event read from the binary log
 
   DESCRIPTION
     Updates the master info with the place in the next binary
@@ -3610,12 +2078,12 @@
     We assume we already locked mi->data_lock
 
   RETURN VALUES
-    0		ok
-    1	        Log event is illegal
+    0           ok
+    1           Log event is illegal
 
 */
 
-static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
+static int process_io_rotate(Master_info *mi, Rotate_log_event *rev)
 {
   DBUG_ENTER("process_io_rotate");
   safe_mutex_assert_owner(&mi->data_lock);
@@ -3626,14 +2094,14 @@
   memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
   mi->master_log_pos= rev->pos;
   DBUG_PRINT("info", ("master_log_pos: '%s' %d",
-		      mi->master_log_name, (ulong) mi->master_log_pos));
+                      mi->master_log_name, (ulong) mi->master_log_pos));
 #ifndef DBUG_OFF
   /*
     If we do not do this, we will be getting the first
     rotate event forever, so we need to not disconnect after one.
   */
-  if (disconnect_slave_event_count)
-    events_till_disconnect++;
+  if (opt_disconnect_slave_event_count)
+    mi->events_till_disconnect++;
 #endif
 
   /*
@@ -3662,14 +2130,14 @@
   Reads a 3.23 event and converts it to the slave's format. This code was
   copied from MySQL 4.0.
 */
-static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
-			   ulong event_len)
+static int queue_binlog_ver_1_event(Master_info *mi, const char *buf,
+                           ulong event_len)
 {
   const char *errmsg = 0;
   ulong inc_pos;
   bool ignore_event= 0;
   char *tmp_buf = 0;
-  RELAY_LOG_INFO *rli= &mi->rli;
+  Relay_log_info *rli= &mi->rli;
   DBUG_ENTER("queue_binlog_ver_1_event");
 
   /*
@@ -3680,7 +2148,8 @@
   {
     if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
     {
-      sql_print_error("Slave I/O: out of memory for Load event");
+      sql_print_error("I/O:%s:Out of memory for Load event",
+                      mi->named_master);
       DBUG_RETURN(1);
     }
     memcpy(tmp_buf,buf,event_len);
@@ -3698,16 +2167,18 @@
   /*
     This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to
     send the loaded file, and write it to the relay log in the form of
-    Append_block/Exec_load (the SQL thread needs the data, as that thread is not
-    connected to the master).
+    Append_block/Exec_load (the SQL thread needs the data, as that thread is 
+    not connected to the master).
   */
-  Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
-                                            mi->rli.relay_log.description_event_for_queue);
+  Log_event *ev = 
+    Log_event::read_log_event(buf,event_len, &errmsg,
+                              mi->rli.relay_log.description_event_for_queue);
   if (unlikely(!ev))
   {
-    sql_print_error("Read invalid event from master: '%s',\
- master could be corrupt but a more likely cause of this is a bug",
-		    errmsg);
+    sql_print_error("I/O:%s:Read invalid event from master: '%s', "
+                    "master could be corrupt but a more likely cause "
+                    "of this is a bug",
+                    mi->named_master, errmsg);
     my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
     DBUG_RETURN(1);
   }
@@ -3778,13 +2249,13 @@
   Reads a 4.0 event and converts it to the slave's format. This code was copied
   from queue_binlog_ver_1_event(), with some affordable simplifications.
 */
-static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf,
-			   ulong event_len)
+static int queue_binlog_ver_3_event(Master_info *mi, const char *buf,
+                           ulong event_len)
 {
   const char *errmsg = 0;
   ulong inc_pos;
   char *tmp_buf = 0;
-  RELAY_LOG_INFO *rli= &mi->rli;
+  Relay_log_info *rli= &mi->rli;
   DBUG_ENTER("queue_binlog_ver_3_event");
 
   /* read_log_event() will adjust log_pos to be end_log_pos */
@@ -3792,9 +2263,9 @@
                                             mi->rli.relay_log.description_event_for_queue);
   if (unlikely(!ev))
   {
-    sql_print_error("Read invalid event from master: '%s',\
- master could be corrupt but a more likely cause of this is a bug",
-		    errmsg);
+    sql_print_error("I/O:%s:Read invalid event from master: '%s',"
+                    "master could be corrupt but a more likely cause of this is a bug",
+                    mi->named_master, errmsg);
     my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
     DBUG_RETURN(1);
   }
@@ -3842,8 +2313,8 @@
     setup with 3.23 master or 4.0 master
 */
 
-static int queue_old_event(MASTER_INFO *mi, const char *buf,
-			   ulong event_len)
+static int queue_old_event(Master_info *mi, const char *buf,
+                           ulong event_len)
 {
   switch (mi->rli.relay_log.description_event_for_queue->binlog_version)
   {
@@ -3868,11 +2339,11 @@
   any >=5.0.0 format.
 */
 
-int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
+int queue_event(Master_info* mi,const char* buf, ulong event_len)
 {
   int error= 0;
   ulong inc_pos;
-  RELAY_LOG_INFO *rli= &mi->rli;
+  Relay_log_info *rli= &mi->rli;
   DBUG_ENTER("queue_event");
 
   if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
@@ -3971,7 +2442,7 @@
   */
 
   if ((uint4korr(buf + SERVER_ID_OFFSET) == ::server_id) &&
-      !replicate_same_server_id)
+      !opt_replicate_same_server_id)
   {
     /*
       Do not write it to the relay log.
@@ -4008,51 +2479,21 @@
 }
 
 
-void end_relay_log_info(RELAY_LOG_INFO* rli)
-{
-  DBUG_ENTER("end_relay_log_info");
-
-  if (!rli->inited)
-    DBUG_VOID_RETURN;
-  if (rli->info_fd >= 0)
-  {
-    end_io_cache(&rli->info_file);
-    (void) my_close(rli->info_fd, MYF(MY_WME));
-    rli->info_fd = -1;
-  }
-  if (rli->cur_log_fd >= 0)
-  {
-    end_io_cache(&rli->cache_buf);
-    (void)my_close(rli->cur_log_fd, MYF(MY_WME));
-    rli->cur_log_fd = -1;
-  }
-  rli->inited = 0;
-  rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
-  rli->relay_log.harvest_bytes_written(&rli->log_space_total);
-  /*
-    Delete the slave's temporary tables from memory.
-    In the future there will be other actions than this, to ensure persistance
-    of slave's temp tables after shutdown.
-  */
-  rli->close_temporary_tables();
-  DBUG_VOID_RETURN;
-}
-
 /*
   Try to connect until successful or slave killed
 
   SYNPOSIS
     safe_connect()
-    thd			Thread handler for slave
-    mysql		MySQL connection handle
-    mi			Replication handle
+    thd                 Thread handler for slave
+    mysql               MySQL connection handle
+    mi                  Replication handle
 
   RETURN
-    0	ok
-    #	Error
+    0   ok
+    #   Error
 */
 
-static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi)
 {
   return connect_to_master(thd, mysql, mi, 0, 0);
 }
@@ -4067,21 +2508,21 @@
     master_retry_count times
 */
 
-static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			     bool reconnect, bool suppress_warnings)
+static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
+                             bool reconnect, bool suppress_warnings)
 {
   int slave_was_killed;
-  int last_errno= -2;				// impossible error
+  int last_errno= -2;                           // impossible error
   ulong err_count=0;
   char llbuff[22];
   DBUG_ENTER("connect_to_master");
 
 #ifndef DBUG_OFF
-  events_till_disconnect = disconnect_slave_event_count;
+  mi->events_till_disconnect= opt_disconnect_slave_event_count;
 #endif
   ulong client_flag= CLIENT_REMEMBER_OPTIONS;
   if (opt_slave_compressed_protocol)
-    client_flag=CLIENT_COMPRESS;		/* We will use compression */
+    client_flag=CLIENT_COMPRESS;                /* We will use compression */
 
   mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
   mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
@@ -4101,23 +2542,23 @@
   mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
 
   while (!(slave_was_killed = io_slave_killed(thd,mi)) &&
-	 (reconnect ? mysql_reconnect(mysql) != 0 :
-	  mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
-			     mi->port, 0, client_flag) == 0))
+         (reconnect ? mysql_reconnect(mysql) != 0 :
+          mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
+                             mi->port, 0, client_flag) == 0))
   {
     /* Don't repeat last error */
     if ((int)mysql_errno(mysql) != last_errno)
     {
       last_errno=mysql_errno(mysql);
       suppress_warnings= 0;
-      sql_print_error("Slave I/O thread: error %s to master \
-'%s@%s:%d': \
-Error: '%s'  errno: %d  retry-time: %d  retries: %d",
-		      (reconnect ? "reconnecting" : "connecting"),
-		      mi->user,mi->host,mi->port,
-		      mysql_error(mysql), last_errno,
-		      mi->connect_retry,
-		      master_retry_count);
+      sql_print_error("I/O:%s:Error %s to master '%s@%s:%d': "
+                      "Error: '%s'  errno: %d  retry-time: %d  retries: %d",
+                      mi->named_master,
+                      (reconnect ? "reconnecting" : "connecting"),
+                      mi->user,mi->host,mi->port,
+                      mysql_error(mysql), last_errno,
+                      mi->connect_retry,
+                      master_retry_count);
     }
     /*
       By default we try forever. The reason is that failure will trigger
@@ -4133,7 +2574,7 @@
       break;
     }
     safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-	       (void*)mi);
+               (void*)mi);
   }
 
   if (!slave_was_killed)
@@ -4141,17 +2582,19 @@
     if (reconnect)
     { 
       if (!suppress_warnings && global_system_variables.log_warnings)
-	sql_print_information("Slave: connected to master '%s@%s:%d',\
-replication resumed in log '%s' at position %s", mi->user,
-			mi->host, mi->port,
-			IO_RPL_LOG_NAME,
-			llstr(mi->master_log_pos,llbuff));
+        sql_print_information("I/O:%s:Connected to master '%s@%s:%d', "
+                              "replication resumed at position '%s:%s'", 
+                              mi->named_master,
+                              mi->user,
+                              mi->host, mi->port,
+                              IO_RPL_LOG_NAME,
+                              llstr(mi->master_log_pos,llbuff));
     }
     else
     {
       change_rpl_status(RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE);
       mysql_log.write(thd, COM_CONNECT_OUT, "%s@%s:%d",
-		      mi->user, mi->host, mi->port);
+                      mi->user, mi->host, mi->port);
     }
 #ifdef SIGNAL_WITH_VIO_CLOSE
     thd->set_active_vio(mysql->net.vio);
@@ -4171,8 +2614,8 @@
     master_retry_count times
 */
 
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
-			  bool suppress_warnings)
+static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi,
+                          bool suppress_warnings)
 {
   DBUG_ENTER("safe_reconnect");
   DBUG_RETURN(connect_to_master(thd, mysql, mi, 1, suppress_warnings));
@@ -4180,406 +2623,15 @@
 
 
 /*
-  Store the file and position where the execute-slave thread are in the
-  relay log.
-
-  SYNOPSIS
-    flush_relay_log_info()
-    rli			Relay log information
-
-  NOTES
-    - As this is only called by the slave thread, we don't need to
-      have a lock on this.
-    - If there is an active transaction, then we don't update the position
-      in the relay log.  This is to ensure that we re-execute statements
-      if we die in the middle of an transaction that was rolled back.
-    - As a transaction never spans binary logs, we don't have to handle the
-      case where we do a relay-log-rotation in the middle of the transaction.
-      If this would not be the case, we would have to ensure that we
-      don't delete the relay log file where the transaction started when
-      we switch to a new relay log file.
-
-  TODO
-    - Change the log file information to a binary format to avoid calling
-      longlong2str.
-
-  RETURN VALUES
-    0	ok
-    1	write error
-*/
-
-bool flush_relay_log_info(RELAY_LOG_INFO* rli)
-{
-  bool error=0;
-  IO_CACHE *file = &rli->info_file;
-  char buff[FN_REFLEN*2+22*2+4], *pos;
-
-  my_b_seek(file, 0L);
-  pos=strmov(buff, rli->group_relay_log_name);
-  *pos++='\n';
-  pos=longlong2str(rli->group_relay_log_pos, pos, 10);
-  *pos++='\n';
-  pos=strmov(pos, rli->group_master_log_name);
-  *pos++='\n';
-  pos=longlong2str(rli->group_master_log_pos, pos, 10);
-  *pos='\n';
-  if (my_b_write(file, (byte*) buff, (ulong) (pos-buff)+1))
-    error=1;
-  if (flush_io_cache(file))
-    error=1;
-  /* Flushing the relay log is done by the slave I/O thread */
-  return error;
-}
-
-
-/*
-  Called when we notice that the current "hot" log got rotated under our feet.
-*/
-
-static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
-{
-  DBUG_ASSERT(rli->cur_log != &rli->cache_buf);
-  DBUG_ASSERT(rli->cur_log_fd == -1);
-  DBUG_ENTER("reopen_relay_log");
-
-  IO_CACHE *cur_log = rli->cur_log=&rli->cache_buf;
-  if ((rli->cur_log_fd=open_binlog(cur_log,rli->event_relay_log_name,
-				   errmsg)) <0)
-    DBUG_RETURN(0);
-  /*
-    We want to start exactly where we was before:
-    relay_log_pos	Current log pos
-    pending		Number of bytes already processed from the event
-  */
-  rli->event_relay_log_pos= max(rli->event_relay_log_pos, BIN_LOG_HEADER_SIZE);
-  my_b_seek(cur_log,rli->event_relay_log_pos);
-  DBUG_RETURN(cur_log);
-}
-
-
-Log_event* next_event(RELAY_LOG_INFO* rli)
-{
-  Log_event* ev;
-  IO_CACHE* cur_log = rli->cur_log;
-  pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); 
-  const char* errmsg=0;
-  THD* thd = rli->sql_thd;
-  
-  DBUG_ENTER("next_event");
-  DBUG_ASSERT(thd != 0);
-
-  /*
-    For most operations we need to protect rli members with data_lock,
-    so we assume calling function acquired this mutex for us and we will
-    hold it for the most of the loop below However, we will release it
-    whenever it is worth the hassle,  and in the cases when we go into a
-    pthread_cond_wait() with the non-data_lock mutex
-  */
-  safe_mutex_assert_owner(&rli->data_lock);
-  
-  while (!sql_slave_killed(thd,rli))
-  {
-    /*
-      We can have two kinds of log reading:
-      hot_log:
-        rli->cur_log points at the IO_CACHE of relay_log, which
-        is actively being updated by the I/O thread. We need to be careful
-        in this case and make sure that we are not looking at a stale log that
-        has already been rotated. If it has been, we reopen the log.
-
-      The other case is much simpler:
-        We just have a read only log that nobody else will be updating.
-    */
-    bool hot_log;
-    if ((hot_log = (cur_log != &rli->cache_buf)))
-    {
-      DBUG_ASSERT(rli->cur_log_fd == -1); // foreign descriptor
-      pthread_mutex_lock(log_lock);
-
-      /*
-	Reading xxx_file_id is safe because the log will only
-	be rotated when we hold relay_log.LOCK_log
-      */
-      if (rli->relay_log.get_open_count() != rli->cur_log_old_open_count)
-      {
-	// The master has switched to a new log file; Reopen the old log file
-	cur_log=reopen_relay_log(rli, &errmsg);
-	pthread_mutex_unlock(log_lock);
-	if (!cur_log)				// No more log files
-	  goto err;
-	hot_log=0;				// Using old binary log
-      }
-    }
-
-#ifndef DBUG_OFF
-    {
-      /* This is an assertion which sometimes fails, let's try to track it */
-      char llbuf1[22], llbuf2[22];
-      DBUG_PRINT("info", ("my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
-                          llstr(my_b_tell(cur_log),llbuf1),
-                          llstr(rli->event_relay_log_pos,llbuf2)));
-      DBUG_ASSERT(my_b_tell(cur_log) >= BIN_LOG_HEADER_SIZE);
-      DBUG_ASSERT(my_b_tell(cur_log) == rli->event_relay_log_pos);
-    }
-#endif
-    /*
-      Relay log is always in new format - if the master is 3.23, the
-      I/O thread will convert the format for us.
-      A problem: the description event may be in a previous relay log. So if
-      the slave has been shutdown meanwhile, we would have to look in old relay
-      logs, which may even have been deleted. So we need to write this
-      description event at the beginning of the relay log.
-      When the relay log is created when the I/O thread starts, easy: the
-      master will send the description event and we will queue it.
-      But if the relay log is created by new_file(): then the solution is:
-      MYSQL_LOG::open() will write the buffered description event.
-    */
-    if ((ev=Log_event::read_log_event(cur_log,0,
-                                      rli->relay_log.description_event_for_exec)))
-
-    {
-      DBUG_ASSERT(thd==rli->sql_thd);
-      /*
-        read it while we have a lock, to avoid a mutex lock in
-        inc_event_relay_log_pos()
-      */
-      rli->future_event_relay_log_pos= my_b_tell(cur_log);
-      if (hot_log)
-	pthread_mutex_unlock(log_lock);
-      DBUG_RETURN(ev);
-    }
-    DBUG_ASSERT(thd==rli->sql_thd);
-    if (opt_reckless_slave)			// For mysql-test
-      cur_log->error = 0;
-    if (cur_log->error < 0)
-    {
-      errmsg = "slave SQL thread aborted because of I/O error";
-      if (hot_log)
-	pthread_mutex_unlock(log_lock);
-      goto err;
-    }
-    if (!cur_log->error) /* EOF */
-    {
-      /*
-	On a hot log, EOF means that there are no more updates to
-	process and we must block until I/O thread adds some and
-	signals us to continue
-      */
-      if (hot_log)
-      {
-        /*
-          We say in Seconds_Behind_Master that we have "caught up". Note that
-          for example if network link is broken but I/O slave thread hasn't
-          noticed it (slave_net_timeout not elapsed), then we'll say "caught
-          up" whereas we're not really caught up. Fixing that would require
-          internally cutting timeout in smaller pieces in network read, no
-          thanks. Another example: SQL has caught up on I/O, now I/O has read
-          a new event and is queuing it; the false "0" will exist until SQL
-          finishes executing the new event; it will be look abnormal only if
-          the events have old timestamps (then you get "many", 0, "many").
-          Transient phases like this can't really be fixed.
-        */
-        time_t save_timestamp= rli->last_master_timestamp;
-        rli->last_master_timestamp= 0;
-
-	DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count);
-	/*
-	  We can, and should release data_lock while we are waiting for
-	  update. If we do not, show slave status will block
-	*/
-	pthread_mutex_unlock(&rli->data_lock);
-
-        /*
-          Possible deadlock : 
-          - the I/O thread has reached log_space_limit
-          - the SQL thread has read all relay logs, but cannot purge for some
-          reason:
-            * it has already purged all logs except the current one
-            * there are other logs than the current one but they're involved in
-            a transaction that finishes in the current one (or is not finished)
-          Solution :
-          Wake up the possibly waiting I/O thread, and set a boolean asking
-          the I/O thread to temporarily ignore the log_space_limit
-          constraint, because we do not want the I/O thread to block because of
-          space (it's ok if it blocks for any other reason (e.g. because the
-          master does not send anything). Then the I/O thread stops waiting 
-          and reads more events.
-          The SQL thread decides when the I/O thread should take log_space_limit
-          into account again : ignore_log_space_limit is reset to 0 
-          in purge_first_log (when the SQL thread purges the just-read relay
-          log), and also when the SQL thread starts. We should also reset
-          ignore_log_space_limit to 0 when the user does RESET SLAVE, but in
-          fact, no need as RESET SLAVE requires that the slave
-          be stopped, and the SQL thread sets ignore_log_space_limit to 0 when
-          it stops.
-        */
-        pthread_mutex_lock(&rli->log_space_lock);
-        // prevent the I/O thread from blocking next times
-        rli->ignore_log_space_limit= 1; 
-        /*
-          If the I/O thread is blocked, unblock it.
-          Ok to broadcast after unlock, because the mutex is only destroyed in
-          ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be
-          destroyed before we exit the present function.
-        */
-        pthread_mutex_unlock(&rli->log_space_lock);
-        pthread_cond_broadcast(&rli->log_space_cond);
-        // Note that wait_for_update unlocks lock_log !
-        rli->relay_log.wait_for_update(rli->sql_thd, 1);
-        // re-acquire data lock since we released it earlier
-        pthread_mutex_lock(&rli->data_lock);
-        rli->last_master_timestamp= save_timestamp;
-	continue;
-      }
-      /*
-	If the log was not hot, we need to move to the next log in
-	sequence. The next log could be hot or cold, we deal with both
-	cases separately after doing some common initialization
-      */
-      end_io_cache(cur_log);
-      DBUG_ASSERT(rli->cur_log_fd >= 0);
-      my_close(rli->cur_log_fd, MYF(MY_WME));
-      rli->cur_log_fd = -1;
-	
-      if (relay_log_purge)
-      {
-	/*
-          purge_first_log will properly set up relay log coordinates in rli.
-          If the group's coordinates are equal to the event's coordinates
-          (i.e. the relay log was not rotated in the middle of a group),
-          we can purge this relay log too.
-          We do ulonglong and string comparisons, this may be slow but
-          - purging the last relay log is nice (it can save 1GB of disk), so we
-          like to detect the case where we can do it, and given this,
-          - I see no better detection method
-          - purge_first_log is not called that often
-        */
-	if (rli->relay_log.purge_first_log
-            (rli,
-             rli->group_relay_log_pos == rli->event_relay_log_pos
-             && !strcmp(rli->group_relay_log_name,rli->event_relay_log_name)))
-	{
-	  errmsg = "Error purging processed logs";
-	  goto err;
-	}
-      }
-      else
-      {
-	/*
-	  If hot_log is set, then we already have a lock on
-	  LOCK_log.  If not, we have to get the lock.
-
-	  According to Sasha, the only time this code will ever be executed
-	  is if we are recovering from a bug.
-	*/
-	if (rli->relay_log.find_next_log(&rli->linfo, !hot_log))
-	{
-	  errmsg = "error switching to the next log";
-	  goto err;
-	}
-	rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE;
-	strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
-		sizeof(rli->event_relay_log_name)-1);
-	flush_relay_log_info(rli);
-      }
-
-      /*
-        Now we want to open this next log. To know if it's a hot log (the one
-        being written by the I/O thread now) or a cold log, we can use
-        is_active(); if it is hot, we use the I/O cache; if it's cold we open
-        the file normally. But if is_active() reports that the log is hot, this
-        may change between the test and the consequence of the test. So we may
-        open the I/O cache whereas the log is now cold, which is nonsense.
-        To guard against this, we need to have LOCK_log.
-      */
-
-      DBUG_PRINT("info",("hot_log: %d",hot_log));
-      if (!hot_log) /* if hot_log, we already have this mutex */
-        pthread_mutex_lock(log_lock);
-      if (rli->relay_log.is_active(rli->linfo.log_file_name))
-      {
-#ifdef EXTRA_DEBUG
-	if (global_system_variables.log_warnings)
-	  sql_print_information("next log '%s' is currently active",
-                                rli->linfo.log_file_name);
-#endif	  
-	rli->cur_log= cur_log= rli->relay_log.get_log_file();
-	rli->cur_log_old_open_count= rli->relay_log.get_open_count();
-	DBUG_ASSERT(rli->cur_log_fd == -1);
-	  
-	/*
-	  Read pointer has to be at the start since we are the only
-	  reader.
-          We must keep the LOCK_log to read the 4 first bytes, as this is a hot
-          log (same as when we call read_log_event() above: for a hot log we
-          take the mutex).
-	*/
-	if (check_binlog_magic(cur_log,&errmsg))
-        {
-          if (!hot_log) pthread_mutex_unlock(log_lock);
-	  goto err;
-        }
-        if (!hot_log) pthread_mutex_unlock(log_lock);
-	continue;
-      }
-      if (!hot_log) pthread_mutex_unlock(log_lock);
-      /*
-	if we get here, the log was not hot, so we will have to open it
-	ourselves. We are sure that the log is still not hot now (a log can get
-	from hot to cold, but not from cold to hot). No need for LOCK_log.
-      */
-#ifdef EXTRA_DEBUG
-      if (global_system_variables.log_warnings)
-	sql_print_information("next log '%s' is not active",
-                              rli->linfo.log_file_name);
-#endif	  
-      // open_binlog() will check the magic header
-      if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
-				       &errmsg)) <0)
-	goto err;
-    }
-    else
-    {
-      /*
-	Read failed with a non-EOF error.
-	TODO: come up with something better to handle this error
-      */
-      if (hot_log)
-	pthread_mutex_unlock(log_lock);
-      sql_print_error("Slave SQL thread: I/O error reading \
-event(errno: %d  cur_log->error: %d)",
-		      my_errno,cur_log->error);
-      // set read position to the beginning of the event
-      my_b_seek(cur_log,rli->event_relay_log_pos);
-      /* otherwise, we have had a partial read */
-      errmsg = "Aborting slave SQL thread because of partial event read";
-      break;					// To end of function
-    }
-  }
-  if (!errmsg && global_system_variables.log_warnings)
-  {
-    sql_print_information("Error reading relay log event: %s", 
-                          "slave SQL thread was killed");
-    DBUG_RETURN(0);
-  }
-
-err:
-  if (errmsg)
-    sql_print_error("Error reading relay log event: %s", errmsg);
-  DBUG_RETURN(0);
-}
-
-/*
   Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
   because of size is simpler because when we do it we already have all relevant
   locks; here we don't, so this function is mainly taking locks). 
   Returns nothing as we cannot catch any error (MYSQL_LOG::new_file() is void).
 */
-
-void rotate_relay_log(MASTER_INFO* mi)
+void rotate_relay_log(Master_info *mi)
 {
   DBUG_ENTER("rotate_relay_log");
-  RELAY_LOG_INFO* rli= &mi->rli;
+  Relay_log_info* rli= &mi->rli;
 
   /* We don't lock rli->run_lock. This would lead to deadlocks. */
   pthread_mutex_lock(&mi->run_lock);
@@ -4588,9 +2640,9 @@
      We need to test inited because otherwise, new_file() will attempt to lock
      LOCK_log, which may not be inited (if we're not a slave).
   */
-  if (!rli->inited)
+  if (!rli->is_inited())
   {
-    DBUG_PRINT("info", ("rli->inited == 0"));
+    DBUG_PRINT("info", ("rli->is_inited() == 0"));
     goto end;
   }
 

--- 1.38/sql/sql_acl.h	2005-06-20 17:10:47 +02:00
+++ 1.39/sql/sql_acl.h	2005-07-14 23:09:59 +02:00
@@ -107,8 +107,15 @@
 			      (((A) & DB_CHUNK2) >> 6) | \
 			      (((A) & DB_CHUNK3) >> 9) | \
 			      (((A) & DB_CHUNK4) >> 2))
-#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4))
-#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4))
+#define TBL_CHUNK0 DB_CHUNK0
+#define TBL_CHUNK1 DB_CHUNK1
+#define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL)
+#define fix_rights_for_table(A) (((A)        & TBL_CHUNK0) | \
+                                (((A) <<  4) & TBL_CHUNK1) | \
+                                (((A) << 11) & TBL_CHUNK2))
+#define get_rights_for_table(A) (((A) & TBL_CHUNK0)        | \
+                                (((A) & TBL_CHUNK1) >>  4) | \
+                                (((A) & TBL_CHUNK2) >> 11))
 #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8))
 #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8))
 #define fix_rights_for_procedure(A) ((((A) << 18) & EXECUTE_ACL) | \

--- 1.169/sql/sql_class.cc	2005-07-05 23:34:30 +02:00
+++ 1.170/sql/sql_class.cc	2005-07-14 23:10:00 +02:00
@@ -171,9 +171,6 @@
    spcont(NULL)
 {
   current_arena= this;
-#ifndef DBUG_OFF
-  backup_arena= 0;
-#endif
   host= user= priv_user= db= ip= 0;
   catalog= (char*)"std"; // the only catalog we have for now
   host_or_ip= "connecting host";
@@ -285,6 +282,8 @@
 #endif
   pthread_mutex_unlock(&LOCK_global_system_variables);
   server_status= SERVER_STATUS_AUTOCOMMIT;
+  if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
+    server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
   options= thd_startup_options;
   open_options=ha_open_options;
   update_lock_default= (variables.low_priority_updates ?
@@ -531,7 +530,7 @@
     next_insert_id= 0;
   }
   /* Free Items that were created during this execution */
-  free_items(free_list);
+  free_items();
   /*
     In the rest of code we assume that free_list never points to garbage:
     Keep this predicate true.
@@ -790,7 +789,10 @@
   void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
   if (change_mem == 0)
   {
-    fatal_error();
+    /*
+      OOM, thd->fatal_error() is called by the error handler of the
+      memroot. Just return.
+    */
     return;
   }
   change= new (change_mem) Item_change_record;
@@ -1457,17 +1459,16 @@
       (void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
     else
     {
-      Item_func_set_user_var *xx = new Item_func_set_user_var(mv->s, item);
+      Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
       /*
         Item_func_set_user_var can't substitute something else on its place =>
         0 can be passed as last argument (reference on item)
         Item_func_set_user_var can't be fixed after creation, so we do not
-        check xx->fixed
+        check var->fixed
       */
-      xx->fix_fields(thd, (TABLE_LIST*) thd->lex->select_lex.table_list.first,
-		     0);
-      xx->fix_length_and_dec();
-      vars.push_back(xx);
+      var->fix_fields(thd, 0);
+      var->fix_length_and_dec();
+      vars.push_back(var);
     }
   }
   return 0;
@@ -1488,6 +1489,21 @@
 }
 
 
+void Query_arena::free_items()
+{
+  Item *next;
+  DBUG_ENTER("Query_arena::free_items");
+  /* This works because items are allocated with sql_alloc() */
+  for (; free_list; free_list= next)
+  {
+    next= free_list->next;
+    free_list->delete_self();
+  }
+  /* Postcondition: free_list is 0 */
+  DBUG_VOID_RETURN;
+}
+
+
 /*
   Statement functions 
 */
@@ -1529,15 +1545,19 @@
 void
 Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
 {
+  DBUG_ENTER("Statement::set_n_backup_statement");
   backup->set_statement(this);
   set_statement(stmt);
+  DBUG_VOID_RETURN;
 }
 
 
 void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
 {
+  DBUG_ENTER("Statement::restore_backup_statement");
   stmt->set_statement(this);
   set_statement(backup);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -1559,11 +1579,12 @@
 void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
 {
   DBUG_ENTER("Query_arena::set_n_backup_item_arena");
-  DBUG_ASSERT(backup_arena == 0);
+  DBUG_ASSERT(backup->is_backup_arena == FALSE);
+
   backup->set_item_arena(this);
   set_item_arena(set);
 #ifndef DBUG_OFF
-  backup_arena= 1;
+  backup->is_backup_arena= TRUE;
 #endif
   DBUG_VOID_RETURN;
 }
@@ -1572,10 +1593,11 @@
 void Query_arena::restore_backup_item_arena(Query_arena *set, Query_arena *backup)
 {
   DBUG_ENTER("Query_arena::restore_backup_item_arena");
+  DBUG_ASSERT(backup->is_backup_arena);
   set->set_item_arena(this);
   set_item_arena(backup);
 #ifndef DBUG_OFF
-  backup_arena= 0;
+  backup->is_backup_arena= FALSE;
 #endif
   DBUG_VOID_RETURN;
 }

--- 1.246/sql/sql_class.h	2005-07-05 23:30:19 +02:00
+++ 1.247/sql/sql_class.h	2005-07-14 23:10:00 +02:00
@@ -659,6 +659,14 @@
 void free_tmp_table(THD *thd, TABLE *entry);
 
 
+/* The following macro is to make init of Query_arena simpler */
+#ifndef DBUG_OFF
+#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
+#else 
+#define INIT_ARENA_DBUG_INFO  
+#endif
+
+
 class Query_arena
 {
 public:
@@ -669,7 +677,7 @@
   Item *free_list;
   MEM_ROOT *mem_root;                   // Pointer to current memroot
 #ifndef DBUG_OFF
-  bool backup_arena;
+  bool is_backup_arena; /* True if this arena is used for backup. */
 #endif
   enum enum_state
   {
@@ -687,12 +695,13 @@
 
   Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
     free_list(0), mem_root(mem_root_arg), state(state_arg)
-  {}
+  { INIT_ARENA_DBUG_INFO; }
   /*
     This constructor is used only when Query_arena is created as
     backup storage for another instance of Query_arena.
   */
-  Query_arena() {};
+  Query_arena() { INIT_ARENA_DBUG_INFO; }
+
   virtual Type type() const;
   virtual ~Query_arena() {};
 
@@ -732,6 +741,8 @@
   void set_n_backup_item_arena(Query_arena *set, Query_arena *backup);
   void restore_backup_item_arena(Query_arena *set, Query_arena *backup);
   void set_item_arena(Query_arena *set);
+
+  void free_items();
 };
 
 
@@ -1433,10 +1444,10 @@
 };
 
 #define tmp_disable_binlog(A)       \
-  ulong save_options= (A)->options; \
-  (A)->options&= ~OPTION_BIN_LOG;
+  {ulong tmp_disable_binlog__save_options= (A)->options; \
+  (A)->options&= ~OPTION_BIN_LOG
 
-#define reenable_binlog(A)          (A)->options= save_options;
+#define reenable_binlog(A)   (A)->options= tmp_disable_binlog__save_options;}
 
 /* Flags for the THD::system_thread (bitmap) variable */
 #define SYSTEM_THREAD_DELAYED_INSERT 1

--- 1.167/sql/sql_lex.h	2005-07-14 22:57:53 +02:00
+++ 1.168/sql/sql_lex.h	2005-07-14 23:20:13 +02:00
@@ -305,7 +305,7 @@
     *link_next, **link_prev;          /* list of whole SELECT_LEX */
 public:
 
-  uint32 options;
+  ulong options;
   /*
     result of this query can't be cached, bit field, can be :
       UNCACHEABLE_DEPENDENT
@@ -372,7 +372,6 @@
    SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group 
    SELECT_LEXs
 */
-struct st_lex;
 class THD;
 class select_result;
 class JOIN;
@@ -471,6 +470,7 @@
 class st_select_lex: public st_select_lex_node
 {
 public:
+  Name_resolution_context context;
   char *db, *db1, *table1, *db2, *table2;      	/* For outer join using .. */
   Item *where, *having;                         /* WHERE & HAVING clauses */
   Item *prep_where; /* saved WHERE clause for prepared statement processing */
@@ -550,27 +550,6 @@
   /* exclude this select from check of unique_table() */
   bool exclude_from_table_unique_test;
 
-  /* 
-     SELECT for SELECT command st_select_lex. Used to privent scaning
-     item_list of non-SELECT st_select_lex (no sense find to finding
-     reference in it (all should be in tables, it is dangerouse due
-     to order of fix_fields calling for non-SELECTs commands (item list
-     can be not fix_fieldsd)). This value will be assigned for
-     primary select (sql_yac.yy) and for any subquery and
-     UNION SELECT (sql_parse.cc mysql_new_select())
-
-
-     INSERT for primary st_select_lex structure of simple INSERT/REPLACE
-     (used for name resolution, see Item_fiels & Item_ref fix_fields,
-     FALSE for INSERT/REPLACE ... SELECT, because it's
-     st_select_lex->table_list will be preprocessed (first table removed)
-     before passing to handle_select)
-
-     NOMATTER for other
-  */
-  enum {NOMATTER_MODE, SELECT_MODE, INSERT_MODE} resolve_mode;
-
-
   void init_query();
   void init_select();
   st_select_lex_unit* master_unit();
@@ -628,7 +607,13 @@
     order_list.first= 0;
     order_list.next= (byte**) &order_list.first;
   }
-  
+  /*
+    This method created for reiniting LEX in mysql_admin_table() and can be
+    used only if you are going remove all SELECT_LEX & units except belonger
+    to LEX (LEX::unit & LEX::select, for other purposes there are
+    SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree
+  */
+  void cut_subtree() { slave= 0; }
   bool test_limit();
 
   friend void lex_start(THD *thd, uchar *buf, uint length);
@@ -643,6 +628,11 @@
   static void print_order(String *str, ORDER *order);
   void print_limit(THD *thd, String *str);
   void fix_prepare_information(THD *thd, Item **conds);
+  /*
+    Destroy the used execution plan (JOIN) of this subtree (this
+    SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs).
+  */
+  bool cleanup();
 };
 typedef class st_select_lex SELECT_LEX;
 
@@ -819,8 +809,14 @@
   bool sp_lex_in_use;	/* Keep track on lex usage in SPs for error handling */
   bool all_privileges;
   sp_pcontext *spcont;
-  HASH spfuns;		/* Called functions */
-  HASH spprocs;		/* Called procedures */
+  /* Set of stored routines called by statement. */
+  HASH sroutines;
+  /*
+    List linking elements of 'sroutines' set. Allows you to add new elements
+    to this set as you iterate through the list of existing elements.
+  */
+  SQL_LIST sroutines_list;
+
   st_sp_chistics sp_chistics;
   bool only_view;       /* used for SHOW CREATE TABLE/VIEW */
   /*
@@ -853,17 +849,11 @@
   */
   uchar *fname_start, *fname_end;
 
-  st_lex() :result(0), sql_command(SQLCOM_END), query_tables_own_last(0)
-  {
-    extern byte *sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first);
-    hash_init(&spfuns, system_charset_info, 0, 0, 0, sp_lex_sp_key, 0, 0);
-    hash_init(&spprocs, system_charset_info, 0, 0, 0, sp_lex_sp_key, 0, 0);
-  }
+  st_lex();
 
   virtual ~st_lex()
   {
-    hash_free(&spfuns);
-    hash_free(&spprocs);
+    hash_free(&sroutines);
   }
 
   inline void uncacheable(uint8 cause)
@@ -900,7 +890,30 @@
   bool can_not_use_merged();
   bool only_view_structure();
   bool need_correct_ident();
+  uint8 get_effective_with_check(st_table_list *view);
+  /*
+    Is this update command where 'WHITH CHECK OPTION' clause is important
+
+    SYNOPSIS
+      st_lex::which_check_option_applicable()
 
+    RETURN
+      TRUE   have to take 'WHITH CHECK OPTION' clause into account
+      FALSE  'WHITH CHECK OPTION' clause do not need
+  */
+  inline bool which_check_option_applicable()
+  {
+    switch (sql_command) {
+    case SQLCOM_UPDATE:
+    case SQLCOM_UPDATE_MULTI:
+    case SQLCOM_INSERT:
+    case SQLCOM_INSERT_SELECT:
+    case SQLCOM_LOAD:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+  }
   inline bool requires_prelocking()
   {
     return test(query_tables_own_last);
@@ -914,7 +927,7 @@
   {
     return ( query_tables_own_last ? *query_tables_own_last : 0);
   }
-
+  void cleanup_after_one_table_open();
   void init_named_master(enum enum_sql_command cmd, const char* master)
   {
     sql_command= cmd;

--- 1.81/sql/sql_load.cc	2005-07-14 22:57:53 +02:00
+++ 1.82/sql/sql_load.cc	2005-07-14 23:10:00 +02:00
@@ -149,7 +149,8 @@
   }
   if (open_and_lock_tables(thd, table_list))
     DBUG_RETURN(TRUE);
-  if (setup_tables(thd, table_list, &unused_conds,
+  if (setup_tables(thd, &thd->lex->select_lex.context,
+                   table_list, &unused_conds,
 		   &thd->lex->select_lex.leaf_tables, FALSE))
      DBUG_RETURN(-1);
   if (!table_list->table ||               // do not suport join view
@@ -159,6 +160,11 @@
     my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
     DBUG_RETURN(TRUE);
   }
+  if (table_list->prepare_where(thd, 0, TRUE) ||
+      table_list->prepare_check_option(thd))
+  {
+    DBUG_RETURN(TRUE);
+  }
   /*
     Let us emit an error if we are loading data to table which is used
     in subselect in SET clause like we do it for INSERT.
@@ -190,8 +196,8 @@
       Let us also prepare SET clause, altough it is probably empty
       in this case.
     */
-    if (setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) ||
-        setup_fields(thd, 0, table_list, set_values, 1, 0, 0))
+    if (setup_fields(thd, 0, set_fields, 1, 0, 0) ||
+        setup_fields(thd, 0, set_values, 1, 0, 0))
       DBUG_RETURN(TRUE);
   }
   else
@@ -204,9 +210,9 @@
       LOAD DATA
     */
     table->file->ha_set_all_bits_in_write_set();
-    if (setup_fields(thd, 0, table_list, fields_vars, 2, 0, 0) ||
-        setup_fields(thd, 0, table_list, set_fields, 2, 0, 0) ||
-        check_that_all_fields_are_given_values(thd, table))
+    if (setup_fields(thd, 0, fields_vars, 2, 0, 0) ||
+        setup_fields(thd, 0, set_fields, 2, 0, 0) ||
+        check_that_all_fields_are_given_values(thd, table, table_list))
       DBUG_RETURN(TRUE);
     /*
       Check whenever TIMESTAMP field with auto-set feature specified
@@ -220,7 +226,7 @@
       check_that_all_fields_are_given_values() and setting use_timestamp
       since it may update query_id for some fields.
     */
-    if (setup_fields(thd, 0, table_list, set_values, 1, 0, 0))
+    if (setup_fields(thd, 0, set_values, 1, 0, 0))
       DBUG_RETURN(TRUE);
   }
 

--- 1.455/sql/sql_parse.cc	2005-07-14 22:57:53 +02:00
+++ 1.456/sql/sql_parse.cc	2005-07-14 23:10:01 +02:00
@@ -2197,6 +2197,8 @@
   TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
   table_list->schema_select_lex= sel;
   table_list->schema_table_reformed= 1;
+  statistic_increment(thd->status_var.com_stat[lex->orig_sql_command],
+                      &LOCK_status);
   DBUG_RETURN(0);
 }
 
@@ -2293,6 +2295,10 @@
   lex->first_lists_tables_same();
   /* should be assigned after making first tables same */
   all_tables= lex->query_tables;
+  /* set context for commands which do not use setup_tables */
+  select_lex->
+    context.resolve_in_table_list_only((TABLE_LIST*)select_lex->
+                                       table_list.first);
 
   /*
     Reset warning count for each query that uses tables
@@ -2302,8 +2308,7 @@
     Don't reset warnings when executing a stored routine.
   */
   if ((all_tables || &lex->select_lex != lex->all_selects_list ||
-       lex->spfuns.records || lex->spprocs.records) &&
-      !thd->spcont)
+       lex->sroutines.records) && !thd->spcont)
     mysql_reset_errors(thd, 0);
 
 #ifdef HAVE_REPLICATION
@@ -2355,10 +2360,6 @@
   }
 #endif /* !HAVE_REPLICATION */
 
-
-
-
-
   /*
     When option readonly is set deny operations which change tables.
     Except for the replication thread and the 'super' users.
@@ -2370,9 +2371,10 @@
     my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
     DBUG_RETURN(-1);
   }
+  if(lex->orig_sql_command == SQLCOM_END)
+    statistic_increment(thd->status_var.com_stat[lex->sql_command],
+                        &LOCK_status);
 
-  statistic_increment(thd->status_var.com_stat[lex->sql_command],
-		      &LOCK_status);
   switch (lex->sql_command) {
   case SQLCOM_SELECT:
   {
@@ -2576,7 +2578,7 @@
       goto error;
     /* PURGE MASTER LOGS BEFORE 'data' */
     it= (Item *)lex->value_list.head();
-    if ((!it->fixed &&it->fix_fields(lex->thd, 0, &it)) ||
+    if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
         it->check_cols(1))
     {
       my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
@@ -2942,9 +2944,7 @@
             CREATE from SELECT give its SELECT_LEX for SELECT,
             and item_list belong to SELECT
           */
-          select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
           res= handle_select(thd, lex, result, 0);
-          select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
           delete result;
         }
 	/* reset for PS */
@@ -3283,6 +3283,8 @@
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
     if ((res= insert_precheck(thd, all_tables)))
       break;
+    /* Skip first table, which is the table we are inserting in */
+    select_lex->context.table_list= first_table->next_local;
     res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
 		      lex->update_list, lex->value_list,
                       lex->duplicates, lex->ignore);
@@ -3293,6 +3295,7 @@
   case SQLCOM_REPLACE_SELECT:
   case SQLCOM_INSERT_SELECT:
   {
+    select_result *result;
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
     if ((res= insert_precheck(thd, all_tables)))
       break;
@@ -3304,27 +3307,24 @@
     /* Don't unlock tables until command is written to binary log */
     select_lex->options|= SELECT_NO_UNLOCK;
 
-    select_result *result;
     unit->set_limit(select_lex);
-
     if (!(res= open_and_lock_tables(thd, all_tables)))
     {
       /* Skip first table, which is the table we are inserting in */
       select_lex->table_list.first= (byte*)first_table->next_local;
 
       res= mysql_insert_select_prepare(thd);
+      lex->select_lex.context.table_list= first_table->next_local;
       if (!res && (result= new select_insert(first_table, first_table->table,
                                              &lex->field_list,
-                                             &lex->update_list, &lex->value_list,
+                                             &lex->update_list,
+                                             &lex->value_list,
                                              lex->duplicates, lex->ignore)))
       {
-        /*
-          insert/replace from SELECT give its SELECT_LEX for SELECT,
-          and item_list belong to SELECT
-        */
-	select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
+        /* Skip first table, which is the table we are inserting in */
+        select_lex->context.table_list= first_table->next_local;
+
 	res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
-	select_lex->resolve_mode= SELECT_LEX::INSERT_MODE;
         delete result;
       }
       /* revert changes for SP */
@@ -3333,7 +3333,6 @@
 
     if (first_table->view && !first_table->contain_auto_increment)
       thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
-
     break;
   }
   case SQLCOM_TRUNCATE:
@@ -3925,7 +3924,7 @@
   {
     Item *it= (Item *)lex->value_list.head();
 
-    if ((!it->fixed && it->fix_fields(lex->thd, 0, &it)) || it->check_cols(1))
+    if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
     {
       my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
 		 MYF(0));
@@ -5292,16 +5291,27 @@
     unit->link_prev= 0;
     unit->return_to= lex->current_select;
     select_lex->include_down(unit);
-    /* TODO: assign resolve_mode for fake subquery after merging with new tree */
+    /*
+      By default we assume that it is usual subselect and we have outer name
+      resolution context, if no we will assign it to 0 later
+    */
+    select_lex->context.outer_context= &select_lex->outer_select()->context;
   }
   else
   {
+    Name_resolution_context *outer_context;
     if (lex->current_select->order_list.first && !lex->current_select->braces)
     {
       my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
       DBUG_RETURN(1);
     }
     select_lex->include_neighbour(lex->current_select);
+    /*
+      we are not sure that we have one level of SELECTs above, so we take
+      outer_context address from first select of unit
+    */
+    outer_context=
+      select_lex->master_unit()->first_select()->context.outer_context;
     SELECT_LEX_UNIT *unit= select_lex->master_unit();
     SELECT_LEX *fake= unit->fake_select_lex;
     if (!fake)
@@ -5318,13 +5328,23 @@
       fake->make_empty_select();
       fake->linkage= GLOBAL_OPTIONS_TYPE;
       fake->select_limit= 0;
+
+      fake->context.outer_context= outer_context;
+      /* allow item list resolving in fake select for ORDER BY */
+      fake->context.resolve_in_select_list= TRUE;
+      fake->context.select_lex= fake;
     }
+    select_lex->context.outer_context= outer_context;
   }
 
   select_lex->master_unit()->global_parameters= select_lex;
   select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
   lex->current_select= select_lex;
-  select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
+  /*
+    in subquery is SELECT query and we allow resolution of names in SELECT
+    list
+  */
+  select_lex->context.resolve_in_select_list= TRUE;
   DBUG_RETURN(0);
 }
 
@@ -5555,6 +5575,21 @@
     DBUG_RETURN(1);
   }
 
+  if (type == FIELD_TYPE_TIMESTAMP && length)
+  {
+    /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1.
+       In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4),
+       and so on, the display width is ignored.
+    */
+    char buf[32];
+    my_snprintf(buf, sizeof(buf),
+                "TIMESTAMP(%s)", length, system_charset_info);
+    push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_WARN_DEPRECATED_SYNTAX,
+                        ER(ER_WARN_DEPRECATED_SYNTAX),
+                        buf, "TIMESTAMP");
+  }
+
   if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
 		type_modifier, default_value, on_update_value,
 		comment, change, interval_list, cs, uint_geom_type)))
@@ -5592,8 +5627,14 @@
   new_field->flags= type_modifier;
   new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ?
 			    Field::NEXT_NUMBER : Field::NONE);
-  new_field->decimals= decimals ? (uint) set_zone(atoi(decimals),0,
-						  NOT_FIXED_DEC-1) : 0;
+  new_field->decimals= decimals ? (uint)atoi(decimals) : 0;
+  if (new_field->decimals >= NOT_FIXED_DEC)
+  {
+    my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name,
+             NOT_FIXED_DEC-1);
+    DBUG_RETURN(NULL);
+  }
+
   new_field->sql_type=type;
   new_field->length=0;
   new_field->change=change;
@@ -5614,11 +5655,6 @@
     length=0; /* purecov: inspected */
   sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
 
-  if (new_field->length && new_field->decimals &&
-      new_field->length < new_field->decimals+1 &&
-      new_field->decimals != NOT_FIXED_DEC)
-    new_field->length=new_field->decimals+1; /* purecov: inspected */
-
   switch (type) {
   case FIELD_TYPE_TINY:
     if (!length) new_field->length=MAX_TINYINT_WIDTH+sign_len;
@@ -5644,22 +5680,24 @@
     break;
   case FIELD_TYPE_NEWDECIMAL:
     if (!length)
+      new_field->length= 10;
+    if (new_field->length > DECIMAL_MAX_PRECISION)
     {
-      if (!(new_field->length= new_field->decimals))
-        new_field->length= 10;                  // Default length for DECIMAL
+      my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name,
+               DECIMAL_MAX_PRECISION);
+      DBUG_RETURN(NULL);
     }
-    new_field->pack_length=
-      my_decimal_get_binary_size(new_field->length, new_field->decimals);
-    if (new_field->length <= DECIMAL_MAX_PRECISION &&
-        new_field->length >= new_field->decimals)
+    if (new_field->length < new_field->decimals)
     {
-      new_field->length=
-        my_decimal_precision_to_length(new_field->length, new_field->decimals,
-                                       type_modifier & UNSIGNED_FLAG);
-      break;
+      my_error(ER_SCALE_BIGGER_THAN_PRECISION, MYF(0), field_name);
+      DBUG_RETURN(NULL);
     }
-    my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
-    DBUG_RETURN(NULL);
+    new_field->length=
+      my_decimal_precision_to_length(new_field->length, new_field->decimals,
+                                     type_modifier & UNSIGNED_FLAG);
+    new_field->pack_length=
+      my_decimal_get_binary_size(new_field->length, new_field->decimals);
+    break;
   case MYSQL_TYPE_VARCHAR:
     /*
       Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
@@ -6428,9 +6466,10 @@
     */
 
     /*
-     Writing this command to the binlog may result in infinite loops when doing
-     mysqlbinlog|mysql, and anyway it does not really make sense to log it
-     automatically (would cause more trouble to users than it would help them)
+      Writing this command to the binlog may result in infinite loops
+      when doing mysqlbinlog|mysql, and anyway it does not really make
+      sense to log it automatically (would cause more trouble to users
+      than it would help them)
     */
     tmp_write_to_binlog= 0;
     mysql_log.new_file(1);

--- 1.233/sql/sql_show.cc	2005-07-14 22:57:54 +02:00
+++ 1.234/sql/sql_show.cc	2005-07-14 23:10:02 +02:00
@@ -347,6 +347,9 @@
   DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
                       table_list->table_name));
 
+  /* We want to preserve the tree for views. */
+  thd->lex->view_prepare_mode= TRUE;
+
   /* Only one table for now, but VIEW can involve several tables */
   if (open_normal_and_derived_tables(thd, table_list))
   {
@@ -1068,7 +1071,13 @@
   buff->append('.');
   append_identifier(thd, buff, table->view_name.str, table->view_name.length);
   buff->append(" AS ", 4);
-  buff->append(table->query.str, table->query.length);
+
+  /*
+    We can't just use table->query, because our SQL_MODE may trigger
+    a different syntax, like when ANSI_QUOTES is defined.
+  */
+  table->view->unit.print(buff);
+
   if (table->with_check != VIEW_CHECK_NONE)
   {
     if (table->with_check == VIEW_CHECK_LOCAL)
@@ -3239,11 +3248,13 @@
 int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 {
   ST_FIELD_INFO *field_info= schema_table->fields_info;
+  Name_resolution_context *context= &thd->lex->select_lex.context;
   for ( ; field_info->field_name; field_info++)
   {
     if (field_info->old_name)
     {
-      Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+      Item_field *field= new Item_field(context,
+                                        NullS, NullS, field_info->field_name);
       if (field)
       {
         field->set_name(field_info->old_name,
@@ -3263,12 +3274,14 @@
   char tmp[128];
   LEX *lex= thd->lex;
   SELECT_LEX *sel= lex->current_select;
+  Name_resolution_context *context= &sel->context;
 
   if (!sel->item_list.elements)
   {
     ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
     String buffer(tmp,sizeof(tmp), system_charset_info);
-    Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+    Item_field *field= new Item_field(context,
+                                      NullS, NullS, field_info->field_name);
     if (!field || add_item_to_list(thd, field))
       return 1;
     buffer.length(0);
@@ -3290,6 +3303,7 @@
   char tmp[128];
   String buffer(tmp,sizeof(tmp), thd->charset());
   LEX *lex= thd->lex;
+  Name_resolution_context *context= &lex->select_lex.context;
 
   ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
   buffer.length(0);
@@ -3301,7 +3315,8 @@
     buffer.append(lex->wild->ptr());
     buffer.append(")");
   }
-  Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+  Item_field *field= new Item_field(context,
+                                    NullS, NullS, field_info->field_name);
   if (add_item_to_list(thd, field))
     return 1;
   field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
@@ -3309,7 +3324,7 @@
   {
     field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
     field_info= &schema_table->fields_info[3];
-    field= new Item_field(NullS, NullS, field_info->field_name);
+    field= new Item_field(context, NullS, NullS, field_info->field_name);
     if (add_item_to_list(thd, field))
       return 1;
     field->set_name(field_info->old_name, strlen(field_info->old_name),
@@ -3324,6 +3339,8 @@
   int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
   int *field_num= fields_arr;
   ST_FIELD_INFO *field_info;
+  Name_resolution_context *context= &thd->lex->select_lex.context;
+
   for (; *field_num >= 0; field_num++)
   {
     field_info= &schema_table->fields_info[*field_num];
@@ -3331,7 +3348,8 @@
                                *field_num == 17 ||
                                *field_num == 18))
       continue;
-    Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+    Item_field *field= new Item_field(context,
+                                      NullS, NullS, field_info->field_name);
     if (field)
     {
       field->set_name(field_info->old_name,
@@ -3350,10 +3368,13 @@
   int fields_arr[]= {0, 2, 1, 3, -1};
   int *field_num= fields_arr;
   ST_FIELD_INFO *field_info;
+  Name_resolution_context *context= &thd->lex->select_lex.context;
+
   for (; *field_num >= 0; field_num++)
   {
     field_info= &schema_table->fields_info[*field_num];
-    Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+    Item_field *field= new Item_field(context,
+                                      NullS, NullS, field_info->field_name);
     if (field)
     {
       field->set_name(field_info->old_name,
@@ -3372,10 +3393,13 @@
   int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
   int *field_num= fields_arr;
   ST_FIELD_INFO *field_info;
+  Name_resolution_context *context= &thd->lex->select_lex.context;
+
   for (; *field_num >= 0; field_num++)
   {
     field_info= &schema_table->fields_info[*field_num];
-    Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+    Item_field *field= new Item_field(context,
+                                      NullS, NullS, field_info->field_name);
     if (field)
     {
       field->set_name(field_info->old_name,
@@ -3441,12 +3465,11 @@
 
     if (table_list->field_translation)
     {
-      Field_translator *end= table_list->field_translation +
-        sel->item_list.elements;
+      Field_translator *end= table_list->field_translation_end;
       for (transl= table_list->field_translation; transl < end; transl++)
       {
         if (!transl->item->fixed &&
-            transl->item->fix_fields(thd, table_list, &transl->item))
+            transl->item->fix_fields(thd, &transl->item))
           DBUG_RETURN(1);
       }
       DBUG_RETURN(0);
@@ -3463,11 +3486,12 @@
     {
       char *name= item->name;
       transl[i].item= item;
-      if (!item->fixed && item->fix_fields(thd, table_list, &transl[i].item))
+      if (!item->fixed && item->fix_fields(thd, &transl[i].item))
         DBUG_RETURN(1);
       transl[i++].name= name;
     }
     table_list->field_translation= transl;
+    table_list->field_translation_end= transl + sel->item_list.elements;
   }
 
   DBUG_RETURN(0);
@@ -3494,7 +3518,7 @@
   ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
   LEX_STRING db, table;
   DBUG_ENTER("mysql_schema_select");
-  /* 
+  /*
      We have to make non const db_name & table_name
      because of lower_case_table_names
   */
@@ -3502,7 +3526,7 @@
                   information_schema_name.length, 0);
   make_lex_string(thd, &table, schema_table->table_name,
                   strlen(schema_table->table_name), 0);
-  if (schema_table->old_format(thd, schema_table) ||      /* Handle old syntax */
+  if (schema_table->old_format(thd, schema_table) ||   /* Handle old syntax */
       !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
                               0, 0, TL_READ, (List<String> *) 0,
                               (List<String> *) 0))

--- 1.360/sql/sql_yacc.yy	2005-07-14 22:57:54 +02:00
+++ 1.361/sql/sql_yacc.yy	2005-07-14 23:10:03 +02:00
@@ -677,7 +677,7 @@
 	LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
         UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
 	NCHAR_STRING opt_component key_cache_name
-        sp_opt_label BIN_NUM
+        sp_opt_label BIN_NUM label_ident
 
 %type <lex_str_ptr>
 	opt_table_alias
@@ -765,7 +765,7 @@
 
 %type <udf_type> udf_func_type
 
-%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword
+%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
 
 %type <lex_user> user grant_user
 
@@ -1268,7 +1268,6 @@
 	    THD *thd= YYTHD;
 	    LEX *lex= thd->lex;
 	    lex->sql_command= SQLCOM_CREATE_VIEW;
-	    lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
 	    /* first table in list is target VIEW name */
 	    if (!lex->select_lex.add_table_to_list(thd, $5, NULL, 0))
               YYABORT;
@@ -1545,7 +1544,7 @@
 	    lex->sql_command= SQLCOM_CALL;
 	    lex->spname= $2;
 	    lex->value_list.empty();
-	    sp_add_to_hash(&lex->spprocs, $2);
+	    sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE);
 	  }
           '(' sp_cparam_list ')' {}
 	;
@@ -2067,7 +2066,7 @@
 
 	    lex->sphead->backpatch(lex->spcont->pop_label());
 	  }
-	| LEAVE_SYM IDENT
+	| LEAVE_SYM label_ident
 	  {
 	    LEX *lex= Lex;
 	    sp_head *sp = lex->sphead;
@@ -2097,7 +2096,7 @@
               sp->add_instr(i);
 	    }
 	  }
-	| ITERATE_SYM IDENT
+	| ITERATE_SYM label_ident
 	  {
 	    LEX *lex= Lex;
 	    sp_head *sp= lex->sphead;
@@ -2127,6 +2126,7 @@
 	  }
 	| LABEL_SYM IDENT
 	  {
+#ifdef SP_GOTO
 	    LEX *lex= Lex;
 	    sp_head *sp= lex->sphead;
 	    sp_pcontext *ctx= lex->spcont;
@@ -2144,9 +2144,14 @@
 	      lab->ctx= ctx;
               sp->backpatch(lab);
 	    }
+#else
+	    yyerror(ER(ER_SYNTAX_ERROR));
+	    YYABORT;
+#endif
 	  }
 	| GOTO_SYM IDENT
 	  {
+#ifdef SP_GOTO
 	    LEX *lex= Lex;
 	    sp_head *sp= lex->sphead;
 	    sp_pcontext *ctx= lex->spcont;
@@ -2199,6 +2204,10 @@
 	      i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
 	      sp->add_instr(i);
 	    }
+#else
+	    yyerror(ER(ER_SYNTAX_ERROR));
+	    YYABORT;
+#endif
 	  }
 	| OPEN_SYM ident
 	  {
@@ -2404,7 +2413,7 @@
 	;
 
 sp_labeled_control:
-	  IDENT ':'
+	  label_ident ':'
 	  {
 	    LEX *lex= Lex;
 	    sp_pcontext *ctx= lex->spcont;
@@ -2443,7 +2452,7 @@
 
 sp_opt_label:
         /* Empty  */    { $$= null_lex_str; }
-        | IDENT         { $$= $1; }
+        | label_ident   { $$= $1; }
 	;
 
 sp_unlabeled_control:
@@ -3396,7 +3405,6 @@
 	    LEX *lex= thd->lex;
 	    lex->sql_command= SQLCOM_CREATE_VIEW;
 	    lex->create_view_mode= VIEW_ALTER;
-	    lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
 	    /* first table in list is target VIEW name */
 	    lex->select_lex.add_table_to_list(thd, $4, NULL, 0);
 	  }
@@ -3971,7 +3979,6 @@
 	{
 	  LEX *lex= Lex;
 	  lex->sql_command= SQLCOM_SELECT;
-	  lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
 	}
 	;
 
@@ -4125,7 +4132,10 @@
 	| '*'
 	  {
 	    THD *thd= YYTHD;
-	    if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
+	    if (add_item_to_list(thd,
+                                 new Item_field(&thd->lex->current_select->
+                                                context,
+                                                NULL, NULL, "*")))
 	      YYABORT;
 	    (thd->lex->current_select->with_wild)++;
 	  };
@@ -4423,10 +4433,10 @@
 	      my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
 	      YYABORT;
 	    }
-	    $$= new Item_default_value($3);
+	    $$= new Item_default_value(&Select->context, $3);
 	  }
 	| VALUES '(' simple_ident ')'
-	  { $$= new Item_insert_value($3); }
+	  { $$= new Item_insert_value(&Select->context, $3); }
 	| FUNC_ARG0 '(' ')'
 	  {
 	    if (!$1.symbol->create_func)
@@ -4715,17 +4725,18 @@
 	    sp_name *name= new sp_name($1, $3);
 
 	    name->init_qname(YYTHD);
-	    sp_add_to_hash(&lex->spfuns, name);
+	    sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
 	    if ($5)
-	      $$= new Item_func_sp(name, *$5);
+	      $$= new Item_func_sp(&lex->current_select->context, name, *$5);
 	    else
-	      $$= new Item_func_sp(name);
+	      $$= new Item_func_sp(&lex->current_select->context, name);
 	    lex->safe_to_cache_query=0;
 	  }
 	| IDENT_sys '(' udf_expr_list ')'
           {
 #ifdef HAVE_DLOPEN
             udf_func *udf;
+            SELECT_LEX *sel= Select;
 
             if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
             {
@@ -4804,11 +4815,11 @@
 	      LEX *lex= Lex;
               sp_name *name= sp_name_current_db_new(YYTHD, $1);
 
-              sp_add_to_hash(&lex->spfuns, name);
+              sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
               if ($3)
-                $$= new Item_func_sp(name, *$3);
+                $$= new Item_func_sp(&lex->current_select->context, name, *$3);
               else
-                $$= new Item_func_sp(name);
+                $$= new Item_func_sp(&lex->current_select->context, name);
 	      lex->safe_to_cache_query=0;
 	    }
           }
@@ -5010,8 +5021,10 @@
 	  opt_gconcat_separator
 	 ')'
 	  {
-	    Select->in_sum_expr--;
-	    $$=new Item_func_group_concat($3,$5,Select->gorder_list,$7);
+            SELECT_LEX *sel= Select;
+	    sel->in_sum_expr--;
+	    $$=new Item_func_group_concat(&sel->context, $3, $5,
+                                          sel->gorder_list, $7);
 	    $5->empty();
 	  };
 
@@ -5430,16 +5443,30 @@
 	ident
 	  {
 	    SELECT_LEX *sel= Select;
-	    if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
+	    if (!($$= new Item_func_eq(new Item_field(&sel->context,
+                                                      sel->db1, sel->table1,
 						      $1.str),
-				       new Item_field(sel->db2, sel->table2,
+				       new Item_field(&sel->context,
+                                                      sel->db2, sel->table2,
 						      $1.str))))
 	      YYABORT;
 	  }
 	| using_list ',' ident
 	  {
 	    SELECT_LEX *sel= Select;
-	    if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
+	    if (!($$=
+                  new Item_cond_and(new
+                                    Item_func_eq(new
+                                                 Item_field(&sel->context,
+                                                            sel->db1,
+                                                            sel->table1,
+                                                            $3.str),
+                                                 new
+                                                 Item_field(&sel->context,
+                                                            sel->db2,
+                                                            sel->table2,
+                                                            $3.str)),
+                                    $1)))
 	      YYABORT;
 	  };
 
@@ -5677,7 +5704,7 @@
 
 ulong_num:
           NUM           { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
-	| HEX_NUM       { int error; $$= (ulong) strtol($1.str, (char**) 0, 16); }
+	| HEX_NUM       { $$= (ulong) strtol($1.str, (char**) 0, 16); }
 	| LONG_NUM      { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
 	| ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
         | DECIMAL_NUM   { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
@@ -5705,7 +5732,10 @@
 	    lex->proc_list.elements=0;
 	    lex->proc_list.first=0;
 	    lex->proc_list.next= (byte**) &lex->proc_list.first;
-	    if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
+	    if (add_proc_to_list(lex->thd, new Item_field(&lex->
+                                                          current_select->
+                                                          context,
+                                                          NULL,NULL,$2.str)))
 	      YYABORT;
 	    Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
 	  }
@@ -5956,7 +5986,6 @@
 	  mysql_init_select(lex);
 	  /* for subselects */
           lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
-	  lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
 	} insert_lock_option
 	opt_ignore insert2
 	{
@@ -5974,7 +6003,6 @@
 	  lex->sql_command = SQLCOM_REPLACE;
 	  lex->duplicates= DUP_REPLACE;
 	  mysql_init_select(lex);
-	  lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
 	}
 	replace_lock_option insert2
 	{
@@ -6092,7 +6120,7 @@
 
 expr_or_default:
 	expr	  { $$= $1;}
-	| DEFAULT {$$= new Item_default_value(); }
+	| DEFAULT {$$= new Item_default_value(&Select->context); }
 	;
 
 opt_insert_update:
@@ -6154,24 +6182,9 @@
 	simple_ident_nospvar equal expr_or_default
 	  {
 	  LEX *lex= Lex;
-          uint8 tmp= MY_ITEM_PREFER_1ST_TABLE;
 	  if (lex->update_list.push_back($1) || 
 	      lex->value_list.push_back($3))
 	      YYABORT;
-          /* 
-            INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY 
-              UPDATE a= a + b1.b
-   
-            Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items
-            to prevent find_field_in_tables() doing further item searching 
-            if it finds item occurence in first table in insert_table_list. 
-            This allows to avoid ambiguity in resolving 'a' field in 
-            example above.
-          */
-          $1->walk(&Item::set_flags_processor,
-                  (byte *) &tmp);
-          $3->walk(&Item::set_flags_processor,
-                  (byte *) &tmp);
 	  };
 
 opt_low_priority:
@@ -7088,15 +7101,17 @@
 table_wild:
 	ident '.' '*'
 	{
-	  $$ = new Item_field(NullS,$1.str,"*");
-	  Lex->current_select->with_wild++;
+          SELECT_LEX *sel= Select;
+	  $$ = new Item_field(&sel->context, NullS, $1.str, "*");
+	  sel->with_wild++;
 	}
 	| ident '.' ident '.' '*'
 	{
-	  $$ = new Item_field((YYTHD->client_capabilities &
+          SELECT_LEX *sel= Select;
+	  $$ = new Item_field(&sel->context, (YYTHD->client_capabilities &
                              CLIENT_NO_SCHEMA ? NullS : $1.str),
                              $3.str,"*");
-	  Lex->current_select->with_wild++;
+	  sel->with_wild++;
 	}
 	;
 
@@ -7121,8 +7136,8 @@
 	    SELECT_LEX *sel=Select;
 	    $$= (sel->parsing_place != IN_HAVING ||
 	         sel->get_in_sum_expr() > 0) ?
-                 (Item*) new Item_field(NullS,NullS,$1.str) :
-	         (Item*) new Item_ref(NullS,NullS,$1.str);
+                 (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
+	         (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
 	  }
         }
         | simple_ident_q { $$= $1; }
@@ -7134,8 +7149,8 @@
 	  SELECT_LEX *sel=Select;
 	  $$= (sel->parsing_place != IN_HAVING ||
 	       sel->get_in_sum_expr() > 0) ?
-              (Item*) new Item_field(NullS,NullS,$1.str) :
-	      (Item*) new Item_ref(NullS,NullS,$1.str);
+              (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
+	      (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
 	}
 	| simple_ident_q { $$= $1; }
 	;
@@ -7172,7 +7187,8 @@
               YYABORT;
             }
 
-            if (!(trg_fld= new Item_trigger_field(new_row ?
+            if (!(trg_fld= new Item_trigger_field(&lex->current_select->context,
+                                                  new_row ?
                                                   Item_trigger_field::NEW_ROW:
                                                   Item_trigger_field::OLD_ROW,
                                                   $3.str)))
@@ -7197,8 +7213,8 @@
 	    }
 	    $$= (sel->parsing_place != IN_HAVING ||
 	         sel->get_in_sum_expr() > 0) ?
-	        (Item*) new Item_field(NullS,$1.str,$3.str) :
-	        (Item*) new Item_ref(NullS,$1.str,$3.str);
+	        (Item*) new Item_field(&sel->context, NullS, $1.str, $3.str) :
+	        (Item*) new Item_ref(&sel->context, NullS, $1.str, $3.str);
           }
         }
 	| '.' ident '.' ident
@@ -7213,8 +7229,8 @@
 	  }
 	  $$= (sel->parsing_place != IN_HAVING ||
 	       sel->get_in_sum_expr() > 0) ?
-	      (Item*) new Item_field(NullS,$2.str,$4.str) :
-              (Item*) new Item_ref(NullS, $2.str, $4.str);
+	      (Item*) new Item_field(&sel->context, NullS, $2.str, $4.str) :
+              (Item*) new Item_ref(&sel->context, NullS, $2.str, $4.str);
 	}
 	| ident '.' ident '.' ident
 	{
@@ -7228,10 +7244,12 @@
 	  }
 	  $$= (sel->parsing_place != IN_HAVING ||
 	       sel->get_in_sum_expr() > 0) ?
-	      (Item*) new Item_field((YYTHD->client_capabilities &
+	      (Item*) new Item_field(&sel->context,
+                                     (YYTHD->client_capabilities &
 				      CLIENT_NO_SCHEMA ? NullS : $1.str),
 				     $3.str, $5.str) :
-	      (Item*) new Item_ref((YYTHD->client_capabilities &
+	      (Item*) new Item_ref(&sel->context,
+                                   (YYTHD->client_capabilities &
 				    CLIENT_NO_SCHEMA ? NullS : $1.str),
                                    $3.str, $5.str);
 	};
@@ -7338,6 +7356,16 @@
 	}
 	;
 
+label_ident:
+	IDENT_sys	    { $$=$1; }
+	| keyword_sp
+	{
+	  THD *thd= YYTHD;
+	  $$.str=    thd->strmake($1.str, $1.length);
+	  $$.length= $1.length;
+	}
+	;
+
 ident_or_text:
         ident                   { $$=$1;}
 	| TEXT_STRING_sys	{ $$=$1;}
@@ -7379,9 +7407,53 @@
           }
 	};
 
-/* Keyword that we allow for identifiers */
-
+/* Keyword that we allow for identifiers (except SP labels) */
 keyword:
+	keyword_sp		{}
+	| ASCII_SYM		{}
+	| BACKUP_SYM		{}
+	| BEGIN_SYM		{}
+	| BYTE_SYM		{}
+	| CACHE_SYM		{}
+	| CHARSET		{}
+	| CHECKSUM_SYM		{}
+	| CLOSE_SYM		{}
+	| COMMENT_SYM		{}
+	| COMMIT_SYM		{}
+	| CONTAINS_SYM          {}
+        | DEALLOCATE_SYM        {}
+	| DO_SYM		{}
+	| END			{}
+	| EXECUTE_SYM		{}
+	| FLUSH_SYM		{}
+	| HANDLER_SYM		{}
+	| HELP_SYM		{}
+	| LANGUAGE_SYM          {}
+	| NO_SYM		{}
+	| OPEN_SYM		{}
+        | PREPARE_SYM           {}
+	| REPAIR		{}
+	| RESET_SYM		{}
+	| RESTORE_SYM		{}
+	| ROLLBACK_SYM		{}
+	| SAVEPOINT_SYM		{}
+	| SECURITY_SYM		{}
+	| SIGNED_SYM		{}
+	| SLAVE			{}
+	| START_SYM		{}
+	| STOP_SYM		{}
+	| TRUNCATE_SYM		{}
+	| UNICODE_SYM		{}
+        | XA_SYM                {}
+	;
+
+/*
+ * Keywords that we allow for labels in SPs.
+ * Anything that's the beginning of a statement or characteristics
+ * must be in keyword above, otherwise we get (harmful) shift/reduce
+ * conflicts.
+ */
+keyword_sp:
 	ACTION			{}
 	| ADDDATE_SYM		{}
 	| AFTER_SYM		{}
@@ -7389,61 +7461,46 @@
 	| AGGREGATE_SYM		{}
 	| ALGORITHM_SYM		{}
 	| ANY_SYM		{}
-	| ASCII_SYM		{}
 	| AUTO_INC		{}
 	| AVG_ROW_LENGTH	{}
 	| AVG_SYM		{}
-	| BACKUP_SYM		{}
-	| BEGIN_SYM		{}
 	| BERKELEY_DB_SYM	{}
 	| BINLOG_SYM		{}
 	| BIT_SYM		{}
 	| BOOL_SYM		{}
 	| BOOLEAN_SYM		{}
-	| BYTE_SYM		{}
 	| BTREE_SYM		{}
-	| CACHE_SYM		{}
 	| CASCADED              {}
 	| CHAIN_SYM		{}
 	| CHANGED		{}
-	| CHARSET		{}
-	| CHECKSUM_SYM		{}
 	| CIPHER_SYM		{}
 	| CLIENT_SYM		{}
-	| CLOSE_SYM		{}
 	| COLLATION_SYM		{}
         | COLUMNS               {}
-	| COMMENT_SYM		{}
 	| COMMITTED_SYM		{}
-	| COMMIT_SYM		{}
 	| COMPACT_SYM		{}
 	| COMPRESSED_SYM	{}
 	| CONCURRENT		{}
 	| CONSISTENT_SYM	{}
-	| CONTAINS_SYM          {}
 	| CUBE_SYM		{}
 	| DATA_SYM		{}
 	| DATETIME		{}
 	| DATE_SYM		{}
 	| DAY_SYM		{}
-        | DEALLOCATE_SYM        {}
 	| DEFINER_SYM		{}
 	| DELAY_KEY_WRITE_SYM	{}
 	| DES_KEY_FILE		{}
 	| DIRECTORY_SYM		{}
 	| DISCARD		{}
-	| DO_SYM		{}
 	| DUMPFILE		{}
 	| DUPLICATE_SYM		{}
 	| DYNAMIC_SYM		{}
-	| END			{}
 	| ENUM			{}
 	| ENGINE_SYM		{}
 	| ENGINES_SYM		{}
 	| ERRORS		{}
 	| ESCAPE_SYM		{}
 	| EVENTS_SYM		{}
-	| EXECUTE_SYM		{}
         | EXPANSION_SYM         {}
 	| EXTENDED_SYM		{}
 	| FAST_SYM		{}
@@ -7454,16 +7511,13 @@
 	| FILE_SYM		{}
 	| FIRST_SYM		{}
 	| FIXED_SYM		{}
-	| FLUSH_SYM		{}
 	| FRAC_SECOND_SYM	{}
 	| GEOMETRY_SYM		{}
 	| GEOMETRYCOLLECTION	{}
 	| GET_FORMAT		{}
 	| GRANTS		{}
 	| GLOBAL_SYM		{}
-	| HANDLER_SYM		{}
 	| HASH_SYM		{}
-	| HELP_SYM		{}
 	| HOSTS_SYM		{}
 	| HOUR_SYM		{}
 	| IDENTIFIED_SYM	{}
@@ -7475,8 +7529,6 @@
 	| INNOBASE_SYM		{}
 	| INSERT_METHOD		{}
 	| RELAY_THREAD		{}
-	| LABEL_SYM             {}
-	| LANGUAGE_SYM          {}
 	| LAST_SYM		{}
 	| LEAVES                {}
 	| LEVEL_SYM		{}
@@ -7525,21 +7577,18 @@
 	| NDBCLUSTER_SYM	{}
 	| NEXT_SYM		{}
 	| NEW_SYM		{}
-	| NO_SYM		{}
 	| NONE_SYM		{}
 	| NVARCHAR_SYM		{}
 	| OFFSET_SYM		{}
 	| OLD_PASSWORD		{}
 	| ONE_SHOT_SYM		{}
         | ONE_SYM               {}
-	| OPEN_SYM		{}
 	| PACK_KEYS_SYM		{}
 	| PARTIAL		{}
 	| PASSWORD		{}
         | PHASE_SYM             {}
 	| POINT_SYM		{}
 	| POLYGON		{}
-        | PREPARE_SYM           {}
 	| PREV_SYM		{}
         | PRIVILEGES            {}
 	| PROCESS		{}
@@ -7557,41 +7606,31 @@
 	| RELAY_LOG_FILE_SYM	{}
 	| RELAY_LOG_POS_SYM	{}
 	| RELOAD		{}
-	| REPAIR		{}
 	| REPEATABLE_SYM	{}
 	| REPLICATION		{}
-	| RESET_SYM		{}
 	| RESOURCES		{}
-	| RESTORE_SYM		{}
         | RESUME_SYM            {}
 	| RETURNS_SYM           {}
-	| ROLLBACK_SYM		{}
 	| ROLLUP_SYM		{}
 	| ROUTINE_SYM		{}
 	| ROWS_SYM		{}
 	| ROW_FORMAT_SYM	{}
 	| ROW_SYM		{}
 	| RTREE_SYM		{}
-	| SAVEPOINT_SYM		{}
 	| SECOND_SYM		{}
-	| SECURITY_SYM		{}
 	| SERIAL_SYM		{}
 	| SERIALIZABLE_SYM	{}
 	| SESSION_SYM		{}
-	| SIGNED_SYM		{}
 	| SIMPLE_SYM		{}
 	| SHARE_SYM		{}
 	| SHUTDOWN		{}
-	| SLAVE			{}
 	| SNAPSHOT_SYM		{}
 	| SOUNDS_SYM		{}
 	| SQL_CACHE_SYM		{}
 	| SQL_BUFFER_RESULT	{}
 	| SQL_NO_CACHE_SYM	{}
 	| SQL_THREAD		{}
-	| START_SYM		{}
 	| STATUS_SYM		{}
-	| STOP_SYM		{}
 	| STORAGE_SYM		{}
 	| STRING_SYM		{}
 	| SUBDATE_SYM		{}
@@ -7604,7 +7643,6 @@
 	| TEMPTABLE_SYM		{}
 	| TEXT_SYM		{}
 	| TRANSACTION_SYM	{}
-	| TRUNCATE_SYM		{}
 	| TIMESTAMP		{}
 	| TIMESTAMP_ADD		{}
 	| TIMESTAMP_DIFF	{}
@@ -7615,7 +7653,6 @@
 	| FUNCTION_SYM		{}
 	| UNCOMMITTED_SYM	{}
 	| UNDEFINED_SYM		{}
-	| UNICODE_SYM		{}
 	| UNKNOWN_SYM		{}
 	| UNTIL_SYM		{}
 	| USER			{}
@@ -7627,7 +7664,6 @@
 	| WEEK_SYM		{}
 	| WORK_SYM		{}
 	| X509_SYM		{}
-        | XA_SYM                {}
 	| YEAR_SYM		{}
 	;
 
@@ -7768,12 +7804,6 @@
               yyerror(ER(ER_SYNTAX_ERROR));
               YYABORT;
             }
-            if (lex->query_tables)
-            {
-              my_message(ER_SP_SUBSELECT_NYI, ER(ER_SP_SUBSELECT_NYI),
-              MYF(0));
-              YYABORT;
-            }
             if ($4)
               it= $4;
             else
@@ -7782,11 +7812,14 @@
               it= new Item_null();
             }
 
-            if (!(trg_fld= new Item_trigger_field(Item_trigger_field::NEW_ROW,
+            if (!(trg_fld= new Item_trigger_field(&lex->current_select->
+                                                  context,
+                                                  Item_trigger_field::NEW_ROW,
                                                   $2.base_name.str)) ||
-                !(i= new sp_instr_set_trigger_field(
-                           lex->sphead->instructions(), lex->spcont,
-                           trg_fld, it)))
+                !(i= new sp_instr_set_trigger_field(lex->sphead->
+                                                    instructions(),
+                                                    lex->spcont, trg_fld,
+                                                    it, lex)))
               YYABORT;
 
             /*

--- 1.23/sql/share/errmsg.txt	2005-07-14 22:57:52 +02:00
+++ 1.24/sql/share/errmsg.txt	2005-07-14 23:20:12 +02:00
@@ -5021,7 +5021,7 @@
 	spa "La tabla destino %-.100s del %s no es actualizable"
 ER_FEATURE_DISABLED  
 	eng "The '%s' feature is disabled; you need MySQL built with '%s' to have it working"
@@ -5358,6 +5358,16 @@
 	eng "The statement (%lu) has no open cursor."
 ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
         eng "Explicit or implicit commit is not allowed in stored function or trigger."
+ER_NO_DEFAULT_FOR_VIEW_FIELD
+        eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
+ER_SP_NO_RECURSION
+        eng "Recursive stored routines are not allowed."
+ER_TOO_BIG_SCALE 42000 S1009
+        eng "Too big scale %d specified for column '%-.64s'. Maximum is %d."
+ER_TOO_BIG_PRECISION 42000 S1009
+        eng "Too big precision %d specified for column '%-.64s'. Maximum is %d."
+ER_SCALE_BIGGER_THAN_PRECISION 42000 S1009
+        eng "Scale may not be larger than the precision (column '%-.64s')."
 ER_NAMED_MASTER_NOT_EXISTS
 	eng "Named master '%s' does not exist"
 ER_NAMED_MASTER_EXISTS

--- 1.17/mysql-test/t/rpl_until.test	2005-07-14 22:57:46 +02:00
+++ 1.18/mysql-test/t/rpl_until.test	2005-07-14 23:09:55 +02:00
@@ -26,6 +26,7 @@
 connection slave;
 start slave until master_log_file='master-bin.000001', master_log_pos=319;
 sleep 2;
+wait_for_slave_to_stop;
 # here table should be still not deleted
 select * from t1;
 --replace_result $MASTER_MYPORT MASTER_MYPORT
@@ -37,13 +38,15 @@
 # again this table should be still not deleted
 select * from t1;
 sleep 2;
+wait_for_slave_to_stop;
 --replace_result $MASTER_MYPORT MASTER_MYPORT
 --replace_column 1 # 9 # 23 # 33 #
 show slave status;
 
 # try replicate all until second insert to t2;
 start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
-sleep 4;
+sleep 2;
+wait_for_slave_to_stop;
 select * from t2;
 --replace_result $MASTER_MYPORT MASTER_MYPORT
 --replace_column 1 # 9 # 23 # 33 #
@@ -59,8 +62,8 @@
 
 # this should stop immediately as we are already there
 start slave until master_log_file='master-bin.000001', master_log_pos=776;
-# 2 is not enough when running with valgrind
-real_sleep 4
+sleep 2;
+wait_for_slave_to_stop;
 # here the sql slave thread should be stopped
 --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
 --replace_column 1 # 9 # 23 # 33 #

--- 1.202/sql/ha_innodb.cc	2005-07-14 22:57:46 +02:00
+++ 1.203/sql/ha_innodb.cc	2005-07-14 23:09:56 +02:00
@@ -326,7 +326,7 @@
 /*=========================*/
 	trx_t*	trx)	/* in: transaction handle */
 {
-	if (UNIV_LIKELY(srv_thread_concurrency >= 20)) {
+	if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) {
 
 		return;
 	}
@@ -343,7 +343,7 @@
 /*========================*/
 	trx_t*	trx)	/* in: transaction handle */
 {
-	if (UNIV_LIKELY(srv_thread_concurrency >= 20)) {
+	if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) {
 
 		return;
 	}
@@ -1528,8 +1528,8 @@
 /*********************************************************************
 Commits a transaction in an InnoDB database or marks an SQL statement
 ended. */
-
-static int
+static
+int
 innobase_commit(
 /*============*/
 			/* out: 0 */
@@ -2987,22 +2987,45 @@
 		templ = prebuilt->mysql_template + n_requested_fields;
 		field = table->field[i];
 
-                ibool index_contains_field=
-                  dict_index_contains_col_or_prefix(index, i);
+		if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
+			/* Decide which columns we should fetch
+			and which we can skip. */
+			register const ibool	index_contains_field =
+				dict_index_contains_col_or_prefix(index, i);
+
+			if (!index_contains_field && prebuilt->read_just_key) {
+				/* If this is a 'key read', we do not need
+				columns that are not in the key */
+
+				goto skip_field;
+			}
+
+			if (index_contains_field && fetch_all_in_key) {
+				/* This field is needed in the query */
 
-		if (templ_type == ROW_MYSQL_REC_FIELDS && 
-                    ((prebuilt->read_just_key && !index_contains_field) ||
-		     (!(fetch_all_in_key && index_contains_field) &&
-		      !(fetch_primary_key_cols &&
-			dict_table_col_in_clustered_key(index->table, i)) &&
-                      (!(table->file->ha_get_bit_in_read_set(i+1) ||
-                        table->file->ha_get_bit_in_write_set(i+1)))))) {
+				goto include_field;
+			}
+
+			if (table->file->ha_get_bit_in_read_set(i+1) ||
+			    table->file->ha_get_bit_in_write_set(i+1)) {
+				/* This field is needed in the query */
+
+				goto include_field;
+			}
+
+			if (fetch_primary_key_cols
+			    && dict_table_col_in_clustered_key(index->table,
+									i)) {
+				/* This field is needed in the query */
+
+				goto include_field;
+			}
 
 			/* This field is not needed in the query, skip it */
 
 			goto skip_field;
 		}
-
+include_field:
 		n_requested_fields++;
 
 		templ->col_no = i;
@@ -3571,7 +3594,9 @@
 }
 
 /**************************************************************************
-Deletes a lock set to a row */
+Removes a new lock set on a row. This can be called after a row has been read
+in the processing of an UPDATE or a DELETE query, if the option
+innodb_locks_unsafe_for_binlog is set. */
 
 void
 ha_innobase::unlock_row(void)
@@ -3589,8 +3614,10 @@
 		mem_analyze_corruption((byte *) prebuilt->trx);
 		ut_error;
 	}
-
-	row_unlock_for_mysql(prebuilt);
+	
+	if (srv_locks_unsafe_for_binlog) {
+		row_unlock_for_mysql(prebuilt, FALSE);
+	}
 }
 
 /**********************************************************************
@@ -6024,6 +6051,7 @@
 			reads. */
 
 			prebuilt->select_lock_type = LOCK_S;
+			prebuilt->stored_select_lock_type = LOCK_S;
 		}
 
 		/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
@@ -6063,7 +6091,6 @@
 	trx->n_mysql_tables_in_use--;
 	prebuilt->mysql_has_locked = FALSE;
 
-
 	/* If the MySQL lock count drops to zero we know that the current SQL
 	statement has ended */
 
@@ -6596,12 +6623,14 @@
 int
 ha_innobase::innobase_read_and_init_auto_inc(
 /*=========================================*/
-				/* out: 0 or error code: deadlock or
-				lock wait timeout */
+				/* out: 0 or error code: deadlock or lock wait
+				timeout */
 	longlong*	ret)	/* out: auto-inc value */
 {
   	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
     	longlong        auto_inc;
+	ulint		old_select_lock_type;
+	ibool		trx_was_not_started	= FALSE;
   	int     	error;
 
   	ut_a(prebuilt);
@@ -6609,6 +6638,10 @@
                 (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 	ut_a(prebuilt->table);
 	
+	if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
+		trx_was_not_started = TRUE;
+	}
+
 	/* In case MySQL calls this in the middle of a SELECT query, release
 	possible adaptive hash latch to avoid deadlocks of threads */
 
@@ -6620,7 +6653,9 @@
 		/* Already initialized */
 		*ret = auto_inc;
 	
-		return(0);
+		error = 0;
+
+		goto func_exit_early;
 	}
 
 	error = row_lock_table_autoinc_for_mysql(prebuilt);
@@ -6628,7 +6663,7 @@
 	if (error != DB_SUCCESS) {
 		error = convert_error_code_to_mysql(error, user_thd);
 
-		goto func_exit;
+		goto func_exit_early;
 	}	
 
 	/* Check again if someone has initialized the counter meanwhile */
@@ -6637,30 +6672,37 @@
 	if (auto_inc != 0) {
 		*ret = auto_inc;
 	
-		return(0);
+		error = 0;
+
+		goto func_exit_early;
 	}
 
   	(void) extra(HA_EXTRA_KEYREAD);
   	index_init(table->s->next_number_index);
 
-	/* We use an exclusive lock when we read the max key value from the
-  	auto-increment column index. This is because then build_template will
-  	advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query
-  	id of the auto-increment column is not changed, and previously InnoDB
-  	did not fetch it, causing SHOW TABLE STATUS to show wrong values
-  	for the autoinc column. */
-
-  	prebuilt->select_lock_type = LOCK_X;
+	/* Starting from 5.0.9, we use a consistent read to read the auto-inc
+	column maximum value. This eliminates the spurious deadlocks caused
+	by the row X-lock that we previously used. Note the following flaw
+	in our algorithm: if some other user meanwhile UPDATEs the auto-inc
+	column, our consistent read will not return the largest value. We
+	accept this flaw, since the deadlocks were a bigger trouble. */
 
-  	/* Play safe and also give in another way the hint to fetch
-  	all columns in the key: */
+  	/* Fetch all the columns in the key */
   	
 	prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 
-	prebuilt->trx->mysql_n_tables_locked += 1;
-  
+	old_select_lock_type = prebuilt->select_lock_type;
+  	prebuilt->select_lock_type = LOCK_NONE;
+
+	/* Eliminate an InnoDB error print that happens when we try to SELECT
+	from a table when no table has been locked in ::external_lock(). */
+	prebuilt->trx->n_mysql_tables_in_use++;
+
 	error = index_last(table->record[1]);
 
+	prebuilt->trx->n_mysql_tables_in_use--;
+  	prebuilt->select_lock_type = old_select_lock_type;
+
   	if (error) {
 		if (error == HA_ERR_END_OF_FILE) {
 			/* The table was empty, initialize to 1 */
@@ -6668,7 +6710,10 @@
 
 			error = 0;
 		} else {
-			/* Deadlock or a lock wait timeout */
+			/* This should not happen in a consistent read */
+			fprintf(stderr,
+"InnoDB: Error: consistent read of auto-inc column returned %lu\n",
+								(ulong)error);
   			auto_inc = -1;
 
   			goto func_exit;
@@ -6688,7 +6733,18 @@
 
 	*ret = auto_inc;
 
-  	return(error);
+func_exit_early:
+	/* Since MySQL does not seem to call autocommit after SHOW TABLE
+	STATUS (even if we would register the trx here), we must commit our
+	transaction here if it was started here. This is to eliminate a
+	dangling transaction. */
+
+	if (trx_was_not_started) {
+
+		innobase_commit_low(prebuilt->trx);
+	}
+
+ 	return(error);
 }
 
 /***********************************************************************

--- 1.123/sql/set_var.cc	2005-07-05 18:46:01 +02:00
+++ 1.124/sql/set_var.cc	2005-07-14 23:09:59 +02:00
@@ -54,7 +54,8 @@
 
 #include "mysql_priv.h"
 #include <mysql.h>
-#include "slave.h"
+#include <rpl/slave.h>
+#include <rpl/mic.h>
 #include <my_getopt.h>
 #include <thr_alarm.h>
 #include <myisam.h>
@@ -120,6 +121,8 @@
 void fix_sql_mode_var(THD *thd, enum_var_type type);
 static byte *get_error_count(THD *thd);
 static byte *get_warning_count(THD *thd);
+static bool sys_update_master(THD *thd, set_var *var);
+static int  sys_check_master(THD *thd, set_var *var);
 
 /*
   Variable definition list
@@ -498,6 +501,14 @@
 					  OPTION_RELAXED_UNIQUE_CHECKS,
 					  1);
 
+/* Variables that are strings in THD */
+
+#ifdef HAVE_REPLICATION
+static sys_var_thd_str	sys_master("master", 
+				   sys_check_master,
+				   sys_update_master);
+#endif
+
 /* Local state variables */
 
 static sys_var_thd_ha_rows	sys_select_limit("sql_select_limit",
@@ -602,6 +613,7 @@
   &sys_log_warnings,
   &sys_long_query_time,
   &sys_low_priority_updates,
+  &sys_master,
   &sys_max_allowed_packet,
   &sys_max_binlog_cache_size,
   &sys_max_binlog_size,
@@ -858,6 +870,9 @@
   {sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS},
   {"lower_case_file_system",  (char*) &lower_case_file_system,      SHOW_MY_BOOL},
   {"lower_case_table_names",  (char*) &lower_case_table_names,      SHOW_INT},
+#ifdef HAVE_REPLICATION
+  {"master",                  (char*) &sys_master,                  SHOW_MASTER},
+#endif
   {sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet,	    SHOW_SYS},
   {sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS},
   {sys_max_binlog_size.name,    (char*) &sys_max_binlog_size,	    SHOW_SYS},
@@ -932,7 +947,7 @@
   {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size,	    SHOW_SYS},
 #ifdef HAVE_REPLICATION
   {sys_relay_log_purge.name,  (char*) &sys_relay_log_purge,         SHOW_SYS},
-  {"relay_log_space_limit",  (char*) &relay_log_space_limit,        SHOW_LONGLONG},
+  {"relay_log_space_limit",  (char*) &opt_relay_log_space_limit,    SHOW_LONGLONG},
 #endif
   {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank,       SHOW_SYS},
   {"secure_auth",             (char*) &sys_secure_auth,             SHOW_SYS},
@@ -947,7 +962,7 @@
 #ifdef HAVE_REPLICATION
   {sys_slave_compressed_protocol.name,
     (char*) &sys_slave_compressed_protocol,           SHOW_SYS},
-  {"slave_load_tmpdir",       (char*) &slave_load_tmpdir,           SHOW_CHAR_PTR},
+  {"slave_load_tmpdir",       (char*) &opt_slave_load_tmpdir,       SHOW_CHAR_PTR},
   {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout,	    SHOW_SYS},
   {"slave_skip_errors",       (char*) &slave_error_mask,            SHOW_SLAVE_SKIP_ERRORS},
   {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries,   SHOW_SYS},
@@ -1270,8 +1285,11 @@
                      max_binlog_size, max_relay_log_size));
   mysql_bin_log.set_max_size(max_binlog_size);
 #ifdef HAVE_REPLICATION
+  Master_info *mi;
+  // Lets make all relay logs have this max size
   if (!max_relay_log_size)
-    active_mi->rli.relay_log.set_max_size(max_binlog_size);
+    for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
+      mi->rli.relay_log.set_max_size(max_binlog_size);
 #endif
   DBUG_VOID_RETURN;
 }
@@ -1282,8 +1300,11 @@
   DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
                      max_binlog_size, max_relay_log_size));
 #ifdef HAVE_REPLICATION
-  active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
-                                        max_relay_log_size: max_binlog_size);
+  Master_info *mi;
+  // Lets make all relay logs have this max size
+  ulong max_size= max_relay_log_size ? max_relay_log_size : max_binlog_size;
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
+    mi->rli.relay_log.set_max_size(max_size);
 #endif
   DBUG_VOID_RETURN;
 }
@@ -2384,6 +2405,47 @@
   return error;
 }
 
+bool sys_var_thd_str::check(THD *thd, set_var *var)
+{
+  int res;
+  if (!check_func)
+    return 0;
+
+  if ((res=(*check_func)(thd, var)) < 0)
+    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+             name, var->value->str_value.ptr());
+  return res;
+}
+
+
+static int sys_check_master(THD *thd, set_var *var)
+{
+  var->save_result.str_value= var->value->str_value.c_ptr();
+  return 0;
+}
+
+
+static bool sys_update_master(THD *thd, set_var *var)
+{
+  char *res= 0;
+  pthread_mutex_lock(&LOCK_active_mi);
+  String *str= &var->value->str_value;
+  if (!(res= my_strdup_with_length(str->ptr(), str->length(), MYF(0))))
+    return 1;
+
+  my_free((char *) thd->variables.master, MYF(MY_ALLOW_ZERO_PTR));
+  thd->variables.master= res;
+
+  pthread_mutex_unlock(&LOCK_active_mi);
+  return 0;
+}
+
+
+byte *sys_var_thd_str::value_ptr(THD *thd, enum_var_type type,
+				 LEX_STRING *base)
+{
+  return (byte*) &thd->variables.master;
+}
 
 /*****************************************************************************
   Functions to handle SET NAMES and SET CHARACTER SET
@@ -2462,13 +2524,18 @@
 {
   int result= 0;
   pthread_mutex_lock(&LOCK_active_mi);
-  pthread_mutex_lock(&active_mi->rli.run_lock);
-  if (active_mi->rli.slave_running)
+  /* Check if any named master is running */
+  Master_info *mi;
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
   {
-    my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
-    result=1;
+    pthread_mutex_lock(&mi->rli.run_lock);
+    if (mi->rli.slave_running)
+    {
+      my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
+      result=1;
+    }
+    pthread_mutex_unlock(&mi->rli.run_lock);
   }
-  pthread_mutex_unlock(&active_mi->rli.run_lock);
   pthread_mutex_unlock(&LOCK_active_mi);
   var->save_result.ulong_value= (ulong) var->value->val_int();
   return result;
@@ -2478,19 +2545,24 @@
 bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
 {
   pthread_mutex_lock(&LOCK_active_mi);
-  pthread_mutex_lock(&active_mi->rli.run_lock);
-  /*
-    The following test should normally never be true as we test this
-    in the check function;  To be safe against multiple
-    SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
-  */
-  if (!active_mi->rli.slave_running)
+  /* Check if any named master is running */
+  Master_info *mi;
+  for (mi= mic.get_head(); mi != 0; mi= mic.get_next())
   {
-    pthread_mutex_lock(&active_mi->rli.data_lock);
-    active_mi->rli.slave_skip_counter= var->save_result.ulong_value;
-    pthread_mutex_unlock(&active_mi->rli.data_lock);
+    pthread_mutex_lock(&mi->rli.run_lock);
+    /*
+      The following test should normally never be true as we test this
+      in the check function;  To be safe against multiple
+      SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
+    */
+    if (!mi->rli.slave_running)
+    {
+      pthread_mutex_lock(&mi->rli.data_lock);
+      mi->rli.slave_skip_counter= var->save_result.ulong_value;
+      pthread_mutex_unlock(&mi->rli.data_lock);
+    }
+    pthread_mutex_unlock(&mi->rli.run_lock);
   }
-  pthread_mutex_unlock(&active_mi->rli.run_lock);
   pthread_mutex_unlock(&LOCK_active_mi);
   return 0;
 }
@@ -2888,8 +2960,8 @@
     First run a check of all variables that all updates will go ok.
     If yes, then execute all updates, returning an error if any one failed.
 
-    This should ensure that in all normal cases none all or variables are
-    updated
+    This should ensure that in all normal cases either none or all of the 
+    variables are updated.
 
     RETURN VALUE
     0	ok
Thread
bk commit into 5.1 tree (lars:1.1846)Lars Thalmann14 Jul