List:Commits« Previous MessageNext Message »
From:jani Date:April 12 2007 11:50am
Subject:bk commit into 5.0 tree (jani:1.2430)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of jani. When jani 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@stripped, 2007-04-12 12:50:02+03:00, jani@stripped +27 -0
  Merge jamppa@stripped:/home/bk/mysql-5.0
  into  ua141d10.elisa.omakaista.fi:/home/my/bk/mysql-5.0-marvel
  MERGE: 1.2425.1.16

  client/mysqldump.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.257.1.2

  mysql-test/r/sp.result@stripped, 2007-04-12 12:49:59+03:00,
jani@stripped +0 -0
    Merged from main 5.0
    MERGE: 1.222.1.2

  mysql-test/t/sp.test@stripped, 2007-04-12 12:46:05+03:00, jani@stripped
+0 -1
    Auto merged
    MERGE: 1.212.1.2

  mysys/my_malloc.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.12.1.1

  mysys/my_static.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.17.1.1

  mysys/safemalloc.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.27.1.1

  ndb/src/mgmclient/CommandInterpreter.cpp@stripped, 2007-04-12 12:46:05+03:00,
jani@stripped +0 -0
    Auto merged
    MERGE: 1.72.1.4

  sql-common/client.c@stripped, 2007-04-12 12:46:07+03:00, jani@stripped
+0 -0
    Auto merged
    MERGE: 1.110.1.1

  sql-common/my_time.c@stripped, 2007-04-12 12:46:08+03:00, jani@stripped
+0 -0
    Auto merged
    MERGE: 1.31.1.1

  sql/ha_archive.cc@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.83.1.1

  sql/ha_innodb.cc@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.309.1.1

  sql/ha_ndbcluster.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped
+0 -0
    Auto merged
    MERGE: 1.303.1.4

  sql/handler.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.229.1.2

  sql/item_cmpfunc.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped
+0 -0
    Auto merged
    MERGE: 1.241.1.1

  sql/item_func.h@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.160.1.1

  sql/log.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.206.1.3

  sql/log_event.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.229.1.1

  sql/mysql_priv.h@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.440.1.1

  sql/sp.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.127.1.1

  sql/sp_head.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.239.1.1

  sql/sql_delete.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.194.1.1

  sql/sql_insert.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.228.1.1

  sql/sql_load.cc@stripped, 2007-04-12 12:49:59+03:00, jani@stripped +2 -4
    Merged from main 5.0
    MERGE: 1.109.1.3

  sql/sql_show.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.344.1.2

  sql/sql_table.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.335.1.4

  sql/sql_update.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
    Auto merged
    MERGE: 1.212.1.1

  sql/table.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
    Auto merged
    MERGE: 1.245.1.2

# 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:	jani
# Host:	ua141d10.elisa.omakaista.fi
# Root:	/home/my/bk/mysql-5.0-marvel/RESYNC

--- 1.260/client/mysqldump.c	2007-04-12 12:50:13 +03:00
+++ 1.261/client/mysqldump.c	2007-04-12 12:50:13 +03:00
@@ -105,7 +105,8 @@
              *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
              *where=0, *order_by=0,
              *opt_compatible_mode_str= 0,
-             *err_ptr= 0;
+             *err_ptr= 0,
+             *log_error_file= NULL;
 static char **defaults_argv= 0;
 static char compatible_mode_normal_str[255];
 static ulong opt_compatible_mode= 0;
@@ -116,7 +117,9 @@
 static int   first_error=0;
 static DYNAMIC_STRING extended_row;
 #include <sslopt-vars.h>
-FILE  *md_result_file= 0;
+FILE *md_result_file= 0;
+FILE *stderror_file=0;
+
 #ifdef HAVE_SMEM
 static char *shared_memory_base_name=0;
 #endif
@@ -306,6 +309,9 @@
    0, 0, 0, 0, 0, 0},
   {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
    (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+  {"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
+   (gptr*) &log_error_file, (gptr*) &log_error_file, 0, GET_STR,
+   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"master-data", OPT_MASTER_DATA,
    "This causes the binary log position and filename to be appended to the "
    "output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
@@ -3789,6 +3795,16 @@
     free_resources(0);
     exit(exit_code);
   }
+
+  if (log_error_file)
+  {
+    if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
+    {
+      free_resources(0);
+      exit(EX_MYSQLERR);
+    }
+  }
+
   if (connect_to_db(current_host, current_user, opt_password))
   {
     free_resources(0);
@@ -3841,5 +3857,9 @@
   if (!path)
     write_footer(md_result_file);
   free_resources();
+
+  if (stderror_file)
+    fclose(stderror_file);
+
   return(first_error);
 } /* main */

--- 1.231/sql/handler.cc	2007-04-12 12:50:13 +03:00
+++ 1.232/sql/handler.cc	2007-04-12 12:50:13 +03:00
@@ -2438,14 +2438,14 @@
   Ask handler if the table exists in engine
 
   RETURN
-    0                   Table does not exist
-    1                   Table exists
-    #                   Error code
+    HA_ERR_NO_SUCH_TABLE     Table does not exist
+    HA_ERR_TABLE_EXIST       Table exists
+    #                        Error code
 
  */
 int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
 {
-  int error= 0;
+  int error= HA_ERR_NO_SUCH_TABLE;
   DBUG_ENTER("ha_table_exists_in_engine");
   DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
 #ifdef HAVE_NDBCLUSTER_DB

--- 1.242/sql/item_cmpfunc.cc	2007-04-12 12:50:13 +03:00
+++ 1.243/sql/item_cmpfunc.cc	2007-04-12 12:50:13 +03:00
@@ -1079,6 +1079,26 @@
 }
 
 
+bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const
+{
+  /* Assume we don't have rtti */
+  if (this == item)
+    return 1;
+  if (item->type() != FUNC_ITEM)
+    return 0;
+  Item_func *item_func=(Item_func*) item;
+  if (arg_count != item_func->arg_count ||
+      functype() != item_func->functype())
+    return 0;
+  if (negated != ((Item_func_opt_neg *) item_func)->negated)
+    return 0;
+  for (uint i=0; i < arg_count ; i++)
+    if (!args[i]->eq(item_func->arguments()[i], binary_cmp))
+      return 0;
+  return 1;
+}
+
+
 void Item_func_interval::fix_length_and_dec()
 {
   use_decimal_comparison= (row->element_index(0)->result_type() == DECIMAL_RESULT)
||

--- 1.162/sql/item_func.h	2007-04-12 12:50:13 +03:00
+++ 1.163/sql/item_func.h	2007-04-12 12:50:13 +03:00
@@ -1414,7 +1414,7 @@
   bool execute();
   bool execute_impl(THD *thd);
   bool init_result_field(THD *thd);
-
+  
 public:
 
   Item_func_sp(Name_resolution_context *context_arg, sp_name *name);
@@ -1424,6 +1424,8 @@
 
   virtual ~Item_func_sp()
   {}
+
+  table_map used_tables() const { return RAND_TABLE_BIT; }
 
   void cleanup();
 

--- 1.208/sql/log.cc	2007-04-12 12:50:14 +03:00
+++ 1.209/sql/log.cc	2007-04-12 12:50:14 +03:00
@@ -283,7 +283,7 @@
 #ifdef __NT__
 static int eventSource = 0;
 
-void setup_windows_event_source()
+static void setup_windows_event_source()
 {
   HKEY    hRegKey= NULL;
   DWORD   dwError= 0;
@@ -2229,37 +2229,6 @@
 } /* test_if_number */
 
 
-void print_buffer_to_file(enum loglevel level, const char *buffer)
-{
-  time_t skr;
-  struct tm tm_tmp;
-  struct tm *start;
-  DBUG_ENTER("print_buffer_to_file");
-  DBUG_PRINT("enter",("buffer: %s", buffer));
-
-  VOID(pthread_mutex_lock(&LOCK_error_log));
-
-  skr=time(NULL);
-  localtime_r(&skr, &tm_tmp);
-  start=&tm_tmp;
-  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
-          start->tm_year % 100,
-          start->tm_mon+1,
-          start->tm_mday,
-          start->tm_hour,
-          start->tm_min,
-          start->tm_sec,
-          (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
-           "Warning" : "Note"),
-          buffer);
-
-  fflush(stderr);
-
-  VOID(pthread_mutex_unlock(&LOCK_error_log));
-  DBUG_VOID_RETURN;
-}
-
-
 void sql_perror(const char *message)
 {
 #ifdef HAVE_STRERROR
@@ -2326,23 +2295,15 @@
 }
 
 #ifdef __NT__
-void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
-                                 uint length, int buffLen)
+static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
+                                        size_t length, size_t buffLen)
 {
   HANDLE event;
-  char   *buffptr;
-  LPCSTR *buffmsgptr;
+  char   *buffptr= buff;
   DBUG_ENTER("print_buffer_to_nt_eventlog");
 
-  buffptr= buff;
-  if (length > (uint)(buffLen-5))
-  {
-    char *newBuff= new char[length + 5];
-    strcpy(newBuff, buff);
-    buffptr= newBuff;
-  }
-  strmov(buffptr+length, "\r\n\r\n");
-  buffmsgptr= (LPCSTR*) &buffptr;               // Keep windows happy
+  /* Add ending CR/LF's to string, overwrite last chars if necessary */
+  strmov(buffptr+min(length, buffLen-5), "\r\n\r\n");
 
   setup_windows_event_source();
   if ((event= RegisterEventSource(NULL,"MySQL")))
@@ -2350,24 +2311,20 @@
     switch (level) {
       case ERROR_LEVEL:
         ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
-                    buffmsgptr, NULL);
+                    (LPCSTR*)&buffptr, NULL);
         break;
       case WARNING_LEVEL:
         ReportEvent(event, EVENTLOG_WARNING_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
-                    buffmsgptr, NULL);
+                    (LPCSTR*) &buffptr, NULL);
         break;
       case INFORMATION_LEVEL:
         ReportEvent(event, EVENTLOG_INFORMATION_TYPE, 0, MSG_DEFAULT, NULL, 1,
-                    0, buffmsgptr, NULL);
+                    0, (LPCSTR*) &buffptr, NULL);
         break;
     }
     DeregisterEventSource(event);
   }
 
-  /* if we created a string buffer, then delete it */
-  if (buffptr != buff)
-    delete[] buffptr;
-
   DBUG_VOID_RETURN;
 }
 #endif /* __NT__ */
@@ -2399,13 +2356,44 @@
                        va_list argsi __attribute__((unused)))
 {}
 #else /*!EMBEDDED_LIBRARY*/
+static void print_buffer_to_file(enum loglevel level, const char *buffer)
+{
+  time_t skr;
+  struct tm tm_tmp;
+  struct tm *start;
+  DBUG_ENTER("print_buffer_to_file");
+  DBUG_PRINT("enter",("buffer: %s", buffer));
+
+  VOID(pthread_mutex_lock(&LOCK_error_log));
+
+  skr=time(NULL);
+  localtime_r(&skr, &tm_tmp);
+  start=&tm_tmp;
+  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
+          start->tm_year % 100,
+          start->tm_mon+1,
+          start->tm_mday,
+          start->tm_hour,
+          start->tm_min,
+          start->tm_sec,
+          (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
+           "Warning" : "Note"),
+          buffer);
+
+  fflush(stderr);
+
+  VOID(pthread_mutex_unlock(&LOCK_error_log));
+  DBUG_VOID_RETURN;
+}
+
+
 void vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
 {
   char   buff[1024];
-  uint length;
+  size_t length;
   DBUG_ENTER("vprint_msg_to_log");
 
-  length= my_vsnprintf(buff, sizeof(buff)-5, format, args);
+  length= my_vsnprintf(buff, sizeof(buff), format, args);
   print_buffer_to_file(level, buff);
 
 #ifdef __NT__

--- 1.443/sql/mysql_priv.h	2007-04-12 12:50:14 +03:00
+++ 1.444/sql/mysql_priv.h	2007-04-12 12:50:14 +03:00
@@ -842,6 +842,8 @@
                   bool ignore);
 int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
                                            TABLE_LIST *table_list);
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+                                      enum_duplicates duplic);
 void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table,
                                                   enum_duplicates duplic);
 bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);

--- 1.195/sql/sql_delete.cc	2007-04-12 12:50:14 +03:00
+++ 1.196/sql/sql_delete.cc	2007-04-12 12:50:14 +03:00
@@ -217,7 +217,19 @@
   thd->proc_info="updating";
 
   if (table->triggers)
+  {
     table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+    if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+                                      TRG_ACTION_AFTER))
+    {
+      /*
+	The table has AFTER DELETE triggers that might access to subject table
+	and therefore might need delete to be done immediately. So we turn-off
+	the batching.
+      */
+      (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+    }
+  }
 
   while (!(error=info.read_record(&info)) && !thd->killed &&
 	 !thd->net.report_error)
@@ -540,7 +552,19 @@
       else
 	normal_tables= 1;
       if (tbl->triggers)
+      {
         tbl->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+	if (tbl->triggers->has_triggers(TRG_EVENT_DELETE,
+                                      TRG_ACTION_AFTER))
+	{
+	  /*
+	    The table has AFTER DELETE triggers that might access to subject 
+	    table and therefore might need delete to be done immediately. 
+	    So we turn-off the batching.
+	  */
+	  (void) tbl->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+	}
+      }
     }
     else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
              walk == delete_tables)

--- 1.229/sql/sql_insert.cc	2007-04-12 12:50:14 +03:00
+++ 1.230/sql/sql_insert.cc	2007-04-12 12:50:14 +03:00
@@ -330,6 +330,51 @@
 
 
 /*
+  Prepare triggers  for INSERT-like statement.
+
+  SYNOPSIS
+    prepare_triggers_for_insert_stmt()
+      thd     The current thread
+      table   Table to which insert will happen
+      duplic  Type of duplicate handling for insert which will happen
+
+  NOTE
+    Prepare triggers for INSERT-like statement by marking fields
+    used by triggers and inform handlers that batching of UPDATE/DELETE 
+    cannot be done if there are BEFORE UPDATE/DELETE triggers.
+*/
+
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+                                      enum_duplicates duplic)
+{
+  if (table->triggers)
+  {
+    if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+                                      TRG_ACTION_AFTER))
+    {
+      /*
+        The table has AFTER DELETE triggers that might access to 
+        subject table and therefore might need delete to be done 
+        immediately. So we turn-off the batching.
+      */ 
+      (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+    }
+    if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+                                      TRG_ACTION_AFTER))
+    {
+      /*
+        The table has AFTER UPDATE triggers that might access to subject 
+        table and therefore might need update to be done immediately. 
+        So we turn-off the batching.
+      */ 
+      (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+    }
+    mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+  }
+}
+
+
+/*
   Mark fields used by triggers for INSERT-like statement.
 
   SYNOPSIS
@@ -589,7 +634,7 @@
                                        (MODE_STRICT_TRANS_TABLES |
                                         MODE_STRICT_ALL_TABLES)));
 
-  mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+  prepare_triggers_for_insert_stmt(thd, table, duplic);
 
   if (table_list->prepare_where(thd, 0, TRUE) ||
       table_list->prepare_check_option(thd))
@@ -2528,8 +2573,8 @@
         table_list->prepare_check_option(thd));
 
   if (!res)
-    mark_fields_used_by_triggers_for_insert_stmt(thd, table,
-                                                 info.handle_duplicates);
+    prepare_triggers_for_insert_stmt(thd, table,
+                                     info.handle_duplicates);
   DBUG_RETURN(res);
 }
 

--- 1.111/sql/sql_load.cc	2007-04-12 12:50:14 +03:00
+++ 1.112/sql/sql_load.cc	2007-04-12 12:50:14 +03:00
@@ -222,7 +222,7 @@
       DBUG_RETURN(TRUE);
   }
 
-  mark_fields_used_by_triggers_for_insert_stmt(thd, table, handle_duplicates);
+  prepare_triggers_for_insert_stmt(thd, table, handle_duplicates);
 
   uint tot_length=0;
   bool use_blobs= 0, use_vars= 0;
@@ -532,7 +532,7 @@
   Item_field *sql_field;
   TABLE *table= table_list->table;
   ulonglong id;
-  bool no_trans_update_stmt;
+  bool no_trans_update_stmt, err;
   DBUG_ENTER("read_fixed_length");
 
   id= 0;
@@ -624,7 +624,9 @@
       DBUG_RETURN(-1);
     }
 
-    if (write_record(thd, table, &info))
+    err= write_record(thd, table, &info);
+    table->auto_increment_field_not_null= FALSE;
+    if (err)
       DBUG_RETURN(1);
     thd->no_trans_update.stmt= no_trans_update_stmt;
    
@@ -669,7 +671,7 @@
   TABLE *table= table_list->table;
   uint enclosed_length;
   ulonglong id;
-  bool no_trans_update_stmt;
+  bool no_trans_update_stmt, err;
   DBUG_ENTER("read_sep_field");
 
   enclosed_length=enclosed.length();
@@ -716,8 +718,6 @@
             DBUG_RETURN(1);
           }
           field->set_null();
-          if (field == table->next_number_field)
-            table->auto_increment_field_not_null= TRUE;
           if (!field->maybe_null())
           {
             if (field->type() == FIELD_TYPE_TIMESTAMP)
@@ -803,8 +803,9 @@
       DBUG_RETURN(-1);
     }
 
-
-    if (write_record(thd, table, &info))
+    err= write_record(thd, table, &info);
+    table->auto_increment_field_not_null= FALSE;
+    if (err)
       DBUG_RETURN(1);
     /*
       If auto_increment values are used, save the first one for

--- 1.345/sql/sql_show.cc	2007-04-12 12:50:14 +03:00
+++ 1.346/sql/sql_show.cc	2007-04-12 12:50:14 +03:00
@@ -496,9 +496,9 @@
   }
 #endif
   if (!my_strcasecmp(system_charset_info, dbname,
-                     information_schema_name.str))
+                     INFORMATION_SCHEMA_NAME.str))
   {
-    dbname= information_schema_name.str;
+    dbname= INFORMATION_SCHEMA_NAME.str;
     create.default_table_charset= system_charset_info;
   }
   else
@@ -1823,7 +1823,8 @@
 
 
 /* INFORMATION_SCHEMA name */
-LEX_STRING information_schema_name= {(char*)"information_schema", 18};
+LEX_STRING INFORMATION_SCHEMA_NAME=
+  { (char *) STRING_WITH_LEN("information_schema") };
 
 /* This is only used internally, but we need it here as a forward reference */
 extern ST_SCHEMA_TABLE schema_tables[];
@@ -2039,11 +2040,11 @@
     */
     if (!idx_field_vals->db_value ||
         !wild_case_compare(system_charset_info, 
-                           information_schema_name.str,
+                           INFORMATION_SCHEMA_NAME.str,
                            idx_field_vals->db_value))
     {
       *with_i_schema= 1;
-      if (files->push_back(thd->strdup(information_schema_name.str)))
+      if (files->push_back(thd->strdup(INFORMATION_SCHEMA_NAME.str)))
         return 1;
     }
     return (find_files(thd, files, NullS, mysql_data_home,
@@ -2058,11 +2059,11 @@
   */
   if (lex->orig_sql_command != SQLCOM_END)
   {
-    if (!my_strcasecmp(system_charset_info, information_schema_name.str,
+    if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str,
                        idx_field_vals->db_value))
     {
       *with_i_schema= 1;
-      return files->push_back(thd->strdup(information_schema_name.str));
+      return files->push_back(thd->strdup(INFORMATION_SCHEMA_NAME.str));
     }
     return files->push_back(thd->strdup(idx_field_vals->db_value));
   }
@@ -2071,7 +2072,7 @@
     Create list of existing databases. It is used in case
     of select from information schema table
   */
-  if (files->push_back(thd->strdup(information_schema_name.str)))
+  if (files->push_back(thd->strdup(INFORMATION_SCHEMA_NAME.str)))
     return 1;
   *with_i_schema= 1;
   return (find_files(thd, files, NullS,
@@ -2147,7 +2148,7 @@
   */
   thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
 
-  if (lsel)
+  if (lsel && lsel->table_list.first)
   {
     TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first;
     bool res;
@@ -3936,8 +3937,8 @@
      We have to make non const db_name & table_name
      because of lower_case_table_names
   */
-  make_lex_string(thd, &db, information_schema_name.str,
-                  information_schema_name.length, 0);
+  make_lex_string(thd, &db, INFORMATION_SCHEMA_NAME.str,
+                  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 */

--- 1.338/sql/sql_table.cc	2007-04-12 12:50:14 +03:00
+++ 1.339/sql/sql_table.cc	2007-04-12 12:50:14 +03:00
@@ -407,6 +407,7 @@
     set_or_name   "SET" or "ENUM" string for warning message
     name	  name of the checked column
     typelib	  list of values for the column
+    dup_val_count  returns count of duplicate elements
 
   DESCRIPTION
     This function prints an warning for each value in list
@@ -418,11 +419,12 @@
 
 void check_duplicates_in_interval(const char *set_or_name,
                                   const char *name, TYPELIB *typelib,
-                                  CHARSET_INFO *cs)
+                                  CHARSET_INFO *cs, unsigned int *dup_val_count)
 {
   TYPELIB tmp= *typelib;
   const char **cur_value= typelib->type_names;
   unsigned int *cur_length= typelib->type_lengths;
+  *dup_val_count= 0;  
   
   for ( ; tmp.count > 1; cur_value++, cur_length++)
   {
@@ -435,6 +437,7 @@
 			  ER_DUPLICATED_VALUE_IN_TYPE,
 			  ER(ER_DUPLICATED_VALUE_IN_TYPE),
 			  name,*cur_value,set_or_name);
+      (*dup_val_count)++;
     }
   }
 }
@@ -498,6 +501,7 @@
 			 int *timestamps, int *timestamps_with_niladic,
 			 uint table_flags)
 {
+  unsigned int dup_val_count;
   DBUG_ENTER("prepare_field");
 
   /*
@@ -573,7 +577,7 @@
     sql_field->unireg_check=Field::INTERVAL_FIELD;
     check_duplicates_in_interval("ENUM",sql_field->field_name,
                                  sql_field->interval,
-                                 sql_field->charset);
+                                 sql_field->charset, &dup_val_count);
     break;
   case FIELD_TYPE_SET:
     sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -583,7 +587,13 @@
     sql_field->unireg_check=Field::BIT_FIELD;
     check_duplicates_in_interval("SET",sql_field->field_name,
                                  sql_field->interval,
-                                 sql_field->charset);
+                                 sql_field->charset, &dup_val_count);
+    /* Check that count of unique members is not more then 64 */
+    if (sql_field->interval->count -  dup_val_count > sizeof(longlong)*8)
+    {
+       my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
+       DBUG_RETURN(1);
+    }
     break;
   case FIELD_TYPE_DATE:			// Rest of string types
   case FIELD_TYPE_NEWDATE:
@@ -1697,6 +1707,7 @@
                           alias);
       DBUG_RETURN(FALSE);
     }
+    DBUG_PRINT("info",("1"));
     my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
     DBUG_RETURN(TRUE);
   }
@@ -1707,6 +1718,7 @@
     {
       if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
         goto warn;
+      DBUG_PRINT("info",("2"));
       my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
       goto end;
     }
@@ -1725,14 +1737,25 @@
   {
     bool create_if_not_exists =
       create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
-    if (ha_table_exists_in_engine(thd, db, table_name))
-    {
-      DBUG_PRINT("info", ("Table with same name already existed in handler"));
-
-      if (create_if_not_exists)
-        goto warn;
-      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
-      goto end;
+    int retcode = ha_table_exists_in_engine(thd, db, table_name);
+    DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
+    switch (retcode)
+    {
+      case HA_ERR_NO_SUCH_TABLE:
+        /* Normal case, no table exists. we can go and create it */
+        break;
+      case HA_ERR_TABLE_EXIST:
+        DBUG_PRINT("info", ("Table existed in handler"));
+
+        if (create_if_not_exists)
+          goto warn;
+        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+        goto end;
+        break;
+      default:
+        DBUG_PRINT("info", ("error: %u from storage engine", retcode));
+        my_error(retcode, MYF(0),table_name);
+        goto end;
     }
   }
 
@@ -2068,7 +2091,9 @@
 
   /*
     Check if this is a table type that stores index and data separately,
-    like ISAM or MyISAM
+    like ISAM or MyISAM. We assume fixed order of engine file name
+    extentions array. First element of engine file name extentions array
+    is meta/index file extention. Second element - data file extention. 
   */
   if (!ext[0] || !ext[1])
     goto end;					// No data file

--- 1.214/sql/sql_update.cc	2007-04-12 12:50:14 +03:00
+++ 1.215/sql/sql_update.cc	2007-04-12 12:50:14 +03:00
@@ -436,7 +436,19 @@
                                 MODE_STRICT_ALL_TABLES)));
 
   if (table->triggers)
+  {
     table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+    if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+                                      TRG_ACTION_AFTER))
+    {
+      /*
+	The table has AFTER UPDATE triggers that might access to subject 
+	table and therefore might need update to be done immediately. 
+	So we turn-off the batching.
+      */ 
+      (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+    }
+  }
 
   /*
     We can use compare_record() to optimize away updates if
@@ -1001,6 +1013,20 @@
       table->no_keyread=1;
       table->used_keys.clear_all();
       table->pos_in_table_list= tl;
+      if (table->triggers)
+      {
+	table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+	if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+					  TRG_ACTION_AFTER))
+	{
+	  /*
+	    The table has AFTER UPDATE triggers that might access to subject 
+	    table and therefore might need update to be done immediately. 
+	    So we turn-off the batching.
+	  */ 
+	  (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+	}
+      }
     }
   }
 

--- 1.84/sql/ha_archive.cc	2007-04-12 12:50:14 +03:00
+++ 1.85/sql/ha_archive.cc	2007-04-12 12:50:14 +03:00
@@ -503,8 +503,8 @@
   We just implement one additional file extension.
 */
 static const char *ha_archive_exts[] = {
-  ARZ,
   ARM,
+  ARZ,
   NullS
 };
 

--- 1.306/sql/ha_ndbcluster.cc	2007-04-12 12:50:14 +03:00
+++ 1.307/sql/ha_ndbcluster.cc	2007-04-12 12:50:14 +03:00
@@ -203,6 +203,8 @@
 
   { 284, HA_ERR_TABLE_DEF_CHANGED, 0 },
 
+  {4009, HA_ERR_NO_CONNECTION, 1 },
+
   { 0, 1, 0 },
 
   { -1, -1, 1 }
@@ -2521,8 +2523,13 @@
       ERR_RETURN(op->getNdbError());
   }
 
-  // Execute update operation
-  if (!cursor && execute_no_commit(this,trans,false) != 0) {
+  /*
+    Execute update operation if we are not doing a scan for update
+    and there exist UPDATE AFTER triggers
+  */
+
+  if ((!cursor || m_update_cannot_batch) && 
+      execute_no_commit(this,trans,false) != 0) {
     no_uncommitted_rows_execute_failure();
     DBUG_RETURN(ndb_err(trans));
   }
@@ -2563,7 +2570,7 @@
 
     no_uncommitted_rows_update(-1);
 
-    if (!m_primary_key_update)
+    if (!(m_primary_key_update || m_delete_cannot_batch))
       // If deleting from cursor, NoCommit will be handled in next_result
       DBUG_RETURN(0);
   }
@@ -3404,6 +3411,16 @@
     DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
     m_use_write= FALSE;
     break;
+  case HA_EXTRA_DELETE_CANNOT_BATCH:
+    DBUG_PRINT("info", ("HA_EXTRA_DELETE_CANNOT_BATCH"));
+    m_delete_cannot_batch= TRUE;
+    break;
+  case HA_EXTRA_UPDATE_CANNOT_BATCH:
+    DBUG_PRINT("info", ("HA_EXTRA_UPDATE_CANNOT_BATCH"));
+    m_update_cannot_batch= TRUE;
+    break;
+  default:
+    break;
   }
   
   DBUG_RETURN(0);
@@ -3420,6 +3437,8 @@
   m_retrieve_primary_key= FALSE;
   m_ignore_dup_key= FALSE;
   m_use_write= FALSE;
+  m_delete_cannot_batch= FALSE;
+  m_update_cannot_batch= FALSE;
   DBUG_RETURN(0);
 }
 
@@ -4785,6 +4804,8 @@
   m_bulk_insert_rows((ha_rows) 1024),
   m_rows_changed((ha_rows) 0),
   m_bulk_insert_not_flushed(FALSE),
+  m_delete_cannot_batch(FALSE),
+  m_update_cannot_batch(FALSE),
   m_ops_pending(0),
   m_skip_auto_increment(TRUE),
   m_blobs_pending(0),
@@ -5067,14 +5088,11 @@
   dict->invalidateTable(name);
   if (!(tab= dict->getTable(name)))
   {
-    const NdbError err= dict->getNdbError();
-    if (err.code == 709)
-      DBUG_RETURN(0);
-    ERR_RETURN(err);
+    ERR_RETURN(dict->getNdbError());
   }
 
   DBUG_PRINT("info", ("Found table %s", tab->getName()));
-  DBUG_RETURN(1);
+  DBUG_RETURN(HA_ERR_TABLE_EXIST);
 }
 
 
@@ -5259,7 +5277,7 @@
     DBUG_PRINT("info", ("%s existed on disk", name));     
     // The .ndb file exists on disk, but it's not in list of tables in ndb
     // Verify that handler agrees table is gone.
-    if (ndbcluster_table_exists_in_engine(thd, db, file_name) == 0)    
+    if (ndbcluster_table_exists_in_engine(thd, db, file_name) == HA_ERR_NO_SUCH_TABLE)
     {
       DBUG_PRINT("info", ("NDB says %s does not exists", file_name));     
       it.remove();
@@ -6696,7 +6714,8 @@
     DBUG_RETURN(NULL);
   }
 
-  List<NDB_SHARE> util_open_tables;
+  uint share_list_size= 0;
+  NDB_SHARE **share_list= NULL;
   set_timespec(abstime, 0);
   for (;;)
   {
@@ -6726,7 +6745,22 @@
     /* Lock mutex and fill list with pointers to all open tables */
     NDB_SHARE *share;
     pthread_mutex_lock(&ndbcluster_mutex);
-    for (uint i= 0; i < ndbcluster_open_tables.records; i++)
+    uint i, record_count= ndbcluster_open_tables.records;
+    if (share_list_size < record_count)
+    {
+      NDB_SHARE ** new_share_list= new NDB_SHARE * [record_count];
+      if (!new_share_list)
+      {
+        sql_print_warning("ndb util thread: malloc failure, "
+                          "query cache not maintained properly");
+        pthread_mutex_unlock(&ndbcluster_mutex);
+        goto next;                               // At least do not crash
+      }
+      delete [] share_list;
+      share_list_size= record_count;
+      share_list= new_share_list;
+    }
+    for (i= 0; i < record_count; i++)
     {
       share= (NDB_SHARE *)hash_element(&ndbcluster_open_tables, i);
       share->use_count++; /* Make sure the table can't be closed */
@@ -6735,14 +6769,14 @@
                   i, share->table_name, share->use_count));
 
       /* Store pointer to table */
-      util_open_tables.push_back(share);
+      share_list[i]= share;
     }
     pthread_mutex_unlock(&ndbcluster_mutex);
 
-    /* Iterate through the  open files list */
-    List_iterator_fast<NDB_SHARE> it(util_open_tables);
-    while ((share= it++))
+    /* Iterate through the open files list */
+    for (i= 0; i < record_count; i++)
     {
+      share= share_list[i];
       /* Split tab- and dbname */
       char buf[FN_REFLEN];
       char *tabname, *db;
@@ -6791,10 +6825,7 @@
       /* Decrease the use count and possibly free share */
       free_share(share);
     }
-
-    /* Clear the list of open tables */
-    util_open_tables.empty();
-
+next:
     /* Calculate new time to wake up */
     int secs= 0;
     int msecs= ndb_cache_check_time;
@@ -6817,6 +6848,8 @@
     }
   }
 
+  if (share_list)
+    delete [] share_list;
   thd->cleanup();
   delete thd;
   delete ndb;
@@ -7114,7 +7147,7 @@
             Check that the field is part of the table of the handler
             instance and that we expect a field with of this result type.
           */
-          if (context->table == field->table)
+          if (context->table->s == field->table->s)
           {       
             const NDBTAB *tab= (const NDBTAB *) context->ndb_table;
             DBUG_PRINT("info", ("FIELD_ITEM"));

--- 1.224/mysql-test/r/sp.result	2007-04-12 12:50:14 +03:00
+++ 1.225/mysql-test/r/sp.result	2007-04-12 12:50:14 +03:00
@@ -5969,6 +5969,21 @@
 21.300000071526	NULL
 DROP FUNCTION bug25373|
 DROP TABLE t3|
+DROP DATABASE IF EXISTS mysqltest1|
+DROP DATABASE IF EXISTS mysqltest2|
+CREATE DATABASE mysqltest1|
+CREATE DATABASE mysqltest2|
+CREATE PROCEDURE mysqltest1.p1()
+DROP DATABASE mysqltest2|
+use mysqltest2|
+CALL mysqltest1.p1()|
+Warnings:
+Note	1049	Unknown database 'mysqltest2'
+SELECT DATABASE()|
+DATABASE()
+NULL
+DROP DATABASE mysqltest1|
+use test|
 drop function if exists bug20777|
 drop table if exists examplebug20777|
 create function bug20777(f1 bigint unsigned) returns bigint unsigned
@@ -6055,3 +6070,28 @@
 drop function bug20777;
 End of 5.0 tests.
 drop table t1,t2;
+CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
+CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
+set @a=0;
+CREATE function bug27354() RETURNS int deterministic
+begin
+insert into t1 values (null);
+set @a=@a+1;
+return @a;
+end|
+update t2 set b=1 where a=bug27354();
+select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */;
+count(t_1.a)	count(t_2.a)
+0	0
+insert into t2 values (1,1),(2,2),(3,3);
+update t2 set b=-b where a=bug27354();
+select * from t2 /* must return 1,-1 ... */;
+a	b
+1	-1
+2	-2
+3	-3
+select count(*) from t1 /* must be 3 */;
+count(*)
+3
+drop table t1,t2;
+drop function   bug27354;

--- 1.214/mysql-test/t/sp.test	2007-04-12 12:50:14 +03:00
+++ 1.215/mysql-test/t/sp.test	2007-04-12 12:50:14 +03:00
@@ -6929,6 +6929,47 @@
 SELECT SUM(f2), bug25373(f1) FROM t3 GROUP BY bug25373(f1) WITH ROLLUP|
 DROP FUNCTION bug25373|
 DROP TABLE t3|
+
+
+#
+# BUG#25082: Default database change on trigger execution breaks replication.
+#
+# As it turned out, this bug has actually two bugs. So, here we have two test
+# cases -- one in sp.test, the other in sp-security.test.
+#
+
+#
+# Test case 1: error on dropping the current database.
+#
+
+# Prepare.
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1|
+DROP DATABASE IF EXISTS mysqltest2|
+--enable_warnings
+
+CREATE DATABASE mysqltest1|
+CREATE DATABASE mysqltest2|
+
+# Test.
+
+CREATE PROCEDURE mysqltest1.p1()
+  DROP DATABASE mysqltest2|
+
+use mysqltest2|
+
+CALL mysqltest1.p1()|
+
+SELECT DATABASE()|
+
+# Cleanup.
+
+DROP DATABASE mysqltest1|
+
+use test|
+
+
 #
 # Bug#20777: Function w BIGINT UNSIGNED shows diff. behaviour --ps-protocol
 --disable_warnings
@@ -6996,3 +7037,26 @@
 delimiter ;|
 drop table t1,t2;
 
+CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
+CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
+set @a=0;
+
+delimiter |;
+CREATE function bug27354() RETURNS int deterministic
+begin
+insert into t1 values (null);
+set @a=@a+1;
+return @a;
+end|
+
+delimiter ;|
+update t2 set b=1 where a=bug27354();
+select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */;
+insert into t2 values (1,1),(2,2),(3,3);
+update t2 set b=-b where a=bug27354();
+select * from t2 /* must return 1,-1 ... */;
+select count(*) from t1 /* must be 3 */;
+
+
+drop table t1,t2;
+drop function   bug27354;

--- 1.128/sql/sp.cc	2007-04-12 12:50:14 +03:00
+++ 1.129/sql/sp.cc	2007-04-12 12:50:14 +03:00
@@ -441,14 +441,14 @@
   {
     sp_head *sp= newlex.sphead;
 
-    if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
+    if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE)))
       goto end;
     delete sp;
     ret= SP_PARSE_ERROR;
   }
   else
   {
-    if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
+    if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE)))
       goto end;
     *sphp= newlex.sphead;
     (*sphp)->set_definer(&definer_user_name, &definer_host_name);
@@ -1896,7 +1896,7 @@
     DBUG_RETURN(0);
   }
 
-  ret= mysql_change_db(thd, new_db.str, no_access_check);
+  ret= mysql_change_db(thd, &new_db, no_access_check);
 
   *dbchangedp= ret == 0;
   DBUG_RETURN(ret);

--- 1.241/sql/sp_head.cc	2007-04-12 12:50:14 +03:00
+++ 1.242/sql/sp_head.cc	2007-04-12 12:50:14 +03:00
@@ -954,6 +954,12 @@
                m_first_instance->m_last_cached_sp == this) ||
               (m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
 
+  /*
+    NOTE: The SQL Standard does not specify the context that should be
+    preserved for stored routines. However, at SAP/Walldorf meeting it was
+    decided that current database should be preserved.
+  */
+
   if (m_db.length &&
       (err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged)))
     goto done;
Thread
bk commit into 5.0 tree (jani:1.2430)jani12 Apr