List:Commits« Previous MessageNext Message »
From:konstantin Date:July 12 2006 10:19pm
Subject:bk commit into 5.1 tree (kostja:1.2243)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of kostja. When kostja 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, 2006-07-13 00:18:59+04:00, kostja@stripped +14 -0
  Merge bk-internal.mysql.com:/home/bk/mysql-5.1
  into  bodhi.local:/opt/local/work/mysql-5.1-runtime-merge
  MERGE: 1.2239.1.11

  mysql-test/r/federated.result@stripped, 2006-07-13 00:18:53+04:00, kostja@stripped +0 -0
    Manual merge.
    MERGE: 1.30.1.4

  mysql-test/t/federated.test@stripped, 2006-07-13 00:18:53+04:00, kostja@stripped +64 -13
    Manual merge.
    MERGE: 1.26.1.4

  sql/ha_ndbcluster.cc@stripped, 2006-07-13 00:15:02+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.336.1.6

  sql/ha_partition.cc@stripped, 2006-07-13 00:15:02+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.60.1.1

  sql/log_event.cc@stripped, 2006-07-13 00:15:02+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.232.1.2

  sql/mysql_priv.h@stripped, 2006-07-13 00:15:03+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.416.1.2

  sql/sql_delete.cc@stripped, 2006-07-13 00:15:03+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.186.1.1

  sql/sql_insert.cc@stripped, 2006-07-13 00:18:53+04:00, kostja@stripped +5 -5
    Manual merge.
    MERGE: 1.208.1.2

  sql/sql_load.cc@stripped, 2006-07-13 00:15:03+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.100.1.1

  sql/sql_parse.cc@stripped, 2006-07-13 00:15:04+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.565.1.5

  sql/sql_table.cc@stripped, 2006-07-13 00:15:04+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.356.1.1

  sql/sql_trigger.cc@stripped, 2006-07-13 00:15:04+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.56.1.2

  sql/sql_update.cc@stripped, 2006-07-13 00:15:04+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.198.1.1

  sql/table.cc@stripped, 2006-07-13 00:15:05+04:00, kostja@stripped +0 -0
    Auto merged
    MERGE: 1.227.1.1

# 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:	kostja
# Host:	bodhi.local
# Root:	/opt/local/work/mysql-5.1-runtime-merge/RESYNC

--- 1.234/sql/log_event.cc	2006-07-13 00:19:17 +04:00
+++ 1.235/sql/log_event.cc	2006-07-13 00:19:17 +04:00
@@ -1934,6 +1934,16 @@ end:
   thd->query_length= 0;
   VOID(pthread_mutex_unlock(&LOCK_thread_count));
   close_thread_tables(thd);      
+  /*
+    As a disk space optimization, future masters will not log an event for
+    LAST_INSERT_ID() if that function returned 0 (and thus they will be able
+    to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
+    variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
+    resetting below we are ready to support that.
+  */
+  thd->first_successful_insert_id_in_prev_stmt_for_binlog= 0;
+  thd->first_successful_insert_id_in_prev_stmt= 0;
+  thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
   free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
   /*
     If there was an error we stop. Otherwise we increment positions. Note that
@@ -3425,11 +3435,11 @@ int Intvar_log_event::exec_event(struct 
 {
   switch (type) {
   case LAST_INSERT_ID_EVENT:
-    thd->last_insert_id_used = 1;
-    thd->last_insert_id = val;
+    thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
+    thd->first_successful_insert_id_in_prev_stmt= val;
     break;
   case INSERT_ID_EVENT:
-    thd->next_insert_id = val;
+    thd->force_one_auto_inc_interval(val);
     break;
   }
   rli->inc_event_relay_log_pos();
@@ -5353,10 +5363,10 @@ int Rows_log_event::exec_event(st_relay_
 
     /*
       lock_tables() reads the contents of thd->lex, so they must be
-      initialized, so we should call lex_start(); to be even safer, we
-      call mysql_init_query() which does a more complete set of inits.
+      initialized. Contrary to in Table_map_log_event::exec_event() we don't
+      call mysql_init_query() as that may reset the binlog format.
     */
-    mysql_init_query(thd, NULL, 0);
+    lex_start(thd, NULL, 0);
 
     while ((error= lock_tables(thd, rli->tables_to_lock,
                                rli->tables_to_lock_count, &need_reopen)))
@@ -5860,6 +5870,12 @@ int Table_map_log_event::exec_event(st_r
   else
   {
     /*
+      open_tables() reads the contents of thd->lex, so they must be
+      initialized, so we should call lex_start(); to be even safer, we
+      call mysql_init_query() which does a more complete set of inits.
+    */
+    mysql_init_query(thd, NULL, 0);
+    /*
       Check if the slave is set to use SBR.  If so, it should switch
       to using RBR until the end of the "statement", i.e., next
       STMT_END_F or next error.
@@ -5875,12 +5891,6 @@ int Table_map_log_event::exec_event(st_r
       Note that for any table that should not be replicated, a filter is needed.
     */
     uint count;
-    /*
-      open_tables() reads the contents of thd->lex, so they must be
-      initialized, so we should call lex_start(); to be even safer, we
-      call mysql_init_query() which does a more complete set of inits.
-    */
-    mysql_init_query(thd, NULL, 0);
     if ((error= open_tables(thd, &table_list, &count, 0)))
     {
       if (thd->query_error || thd->is_fatal_error)

--- 1.419/sql/mysql_priv.h	2006-07-13 00:19:17 +04:00
+++ 1.420/sql/mysql_priv.h	2006-07-13 00:19:17 +04:00
@@ -1970,6 +1970,17 @@ inline int hexchar_to_int(char c)
 }
 
 /*
+  is_user_table()
+  return true if the table was created explicitly
+*/
+
+inline bool is_user_table(TABLE * table)
+{
+  const char *name= table->s->table_name.str;
+  return strncmp(name, tmp_file_prefix, tmp_file_prefix_length);
+}
+
+/*
   Some functions that are different in the embedded library and the normal
   server
 */

--- 1.187/sql/sql_delete.cc	2006-07-13 00:19:17 +04:00
+++ 1.188/sql/sql_delete.cc	2006-07-13 00:19:17 +04:00
@@ -986,12 +986,12 @@ trunc_by_del:
   thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
   ha_enable_transaction(thd, FALSE);
   mysql_init_select(thd->lex);
-#ifdef HAVE_ROW_BASED_REPLICATION
+  bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
   thd->clear_current_stmt_binlog_row_based();
-#endif
   error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
                       HA_POS_ERROR, LL(0), TRUE);
   ha_enable_transaction(thd, TRUE);
   thd->options= save_options;
+  thd->current_stmt_binlog_row_based= save_binlog_row_based;
   DBUG_RETURN(error);
 }

--- 1.211/sql/sql_insert.cc	2006-07-13 00:19:18 +04:00
+++ 1.212/sql/sql_insert.cc	2006-07-13 00:19:18 +04:00
@@ -219,9 +219,6 @@ static int check_insert_fields(THD *thd,
       }
     }
   }
-  if (table->found_next_number_field)
-    table->mark_auto_increment_column();
-  table->mark_columns_needed_for_insert();
   // For the values we need select_priv
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
@@ -451,6 +448,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   thd->proc_info="update";
   if (duplic != DUP_ERROR || ignore)
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+  if (duplic == DUP_REPLACE &&
+      (!table->triggers || !table->triggers->has_delete_triggers()))
+    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
   /*
     let's *try* to start bulk inserts. It won't necessary
     start them as values_list.elements should be greater than
@@ -479,6 +479,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     error= 1;
   }
 
+  table->mark_columns_needed_for_insert();
+
   if (table_list->prepare_where(thd, 0, TRUE) ||
       table_list->prepare_check_option(thd))
     error= 1;
@@ -653,6 +655,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
   if (duplic != DUP_ERROR || ignore)
     table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+  if (duplic == DUP_REPLACE &&
+      (!table->triggers || !table->triggers->has_delete_triggers()))
+    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
   if (error)
     goto abort;
@@ -2037,9 +2042,8 @@ bool delayed_insert::handle_inserts(void
 {
   int error;
   ulong max_rows;
-  bool using_ignore=0,
-    using_bin_log= mysql_bin_log.is_open();
-
+  bool using_ignore= 0, using_opt_replace= 0,
+       using_bin_log= mysql_bin_log.is_open();
   delayed_row *row;
   DBUG_ENTER("handle_inserts");
 
@@ -2098,6 +2102,13 @@ bool delayed_insert::handle_inserts(void
       table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
       using_ignore=1;
     }
+    if (info.handle_duplicates == DUP_REPLACE &&
+        (!table->triggers ||
+         !table->triggers->has_delete_triggers()))
+    {
+      table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+      using_opt_replace= 1;
+    }
     thd.clear_error(); // reset error for binlog
     if (write_record(&thd, table, &info))
     {
@@ -2111,6 +2122,11 @@ bool delayed_insert::handle_inserts(void
       using_ignore=0;
       table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
     }
+    if (using_opt_replace)
+    {
+      using_opt_replace= 0;
+      table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
+    }
 
     if (row->log_query && row->query.str != NULL &&
mysql_bin_log.is_open())
     {
@@ -2384,6 +2400,9 @@ select_insert::prepare(List<Item> &value
   thd->cuted_fields=0;
   if (info.ignore || info.handle_duplicates != DUP_ERROR)
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+  if (info.handle_duplicates == DUP_REPLACE &&
+      (!table->triggers || !table->triggers->has_delete_triggers()))
+    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
   thd->no_trans_update= 0;
   thd->abort_on_warning= (!info.ignore &&
                           (thd->variables.sql_mode &
@@ -2393,6 +2412,10 @@ select_insert::prepare(List<Item> &value
          check_that_all_fields_are_given_values(thd, table, table_list)) ||
         table_list->prepare_where(thd, 0, TRUE) ||
         table_list->prepare_check_option(thd));
+
+  if (!res)
+    table->mark_columns_needed_for_insert();
+
   DBUG_RETURN(res);
 }
 
@@ -2587,6 +2610,7 @@ bool select_insert::send_eof()
 
   error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0;
   table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+  table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
   if (info.copied || info.deleted || info.updated)
   {
@@ -2861,6 +2885,9 @@ select_create::prepare(List<Item> &value
   thd->cuted_fields=0;
   if (info.ignore || info.handle_duplicates != DUP_ERROR)
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+  if (info.handle_duplicates == DUP_REPLACE &&
+      (!table->triggers || !table->triggers->has_delete_triggers()))
+    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
   if (!thd->prelocked_mode)
     table->file->ha_start_bulk_insert((ha_rows) 0);
   thd->no_trans_update= 0;
@@ -2868,8 +2895,10 @@ select_create::prepare(List<Item> &value
                           (thd->variables.sql_mode &
                            (MODE_STRICT_TRANS_TABLES |
                             MODE_STRICT_ALL_TABLES)));
-  DBUG_RETURN(check_that_all_fields_are_given_values(thd, table,
-                                                     table_list));
+  if (check_that_all_fields_are_given_values(thd, table, table_list))
+    DBUG_RETURN(1);
+  table->mark_columns_needed_for_insert();
+  DBUG_RETURN(0);
 }
 
 
@@ -2943,6 +2972,7 @@ bool select_create::send_eof()
   else
   {
     table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
     VOID(pthread_mutex_lock(&LOCK_open));
     mysql_unlock_tables(thd, thd->extra_lock);
     if (!table->s->tmp_table)
@@ -2968,6 +2998,7 @@ void select_create::abort()
   if (table)
   {
     table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
     handlerton *table_type=table->s->db_type;
     if (!table->s->tmp_table)
     {

--- 1.102/sql/sql_load.cc	2006-07-13 00:19:18 +04:00
+++ 1.103/sql/sql_load.cc	2006-07-13 00:19:18 +04:00
@@ -501,13 +501,12 @@ bool mysql_load(THD *thd,sql_exchange *e
     error=ha_autocommit_or_rollback(thd,error);
 
 err:
+  table->file->ha_release_auto_increment();
   if (thd->lock)
   {
     mysql_unlock_tables(thd, thd->lock);
     thd->lock=0;
   }
-  if (table != NULL)
-    table->file->release_auto_increment();
   thd->abort_on_warning= 0;
   DBUG_RETURN(error);
 }
@@ -643,14 +642,6 @@ read_fixed_length(THD *thd, COPY_INFO &i
     thd->no_trans_update= no_trans_update;
    
     /*
-      If auto_increment values are used, save the first one
-       for LAST_INSERT_ID() and for the binary/update log.
-       We can't use insert_id() as we don't want to touch the
-       last_insert_id_used flag.
-    */
-    if (!id && thd->insert_id_used)
-      id= thd->last_insert_id;
-    /*
       We don't need to reset auto-increment field since we are restoring
       its default value at the beginning of each loop iteration.
     */
@@ -666,8 +657,6 @@ read_fixed_length(THD *thd, COPY_INFO &i
     thd->row_count++;
 continue_loop:;
   }
-  if (id && !read_info.error)
-    thd->insert_id(id);			// For binary/update log
   DBUG_RETURN(test(read_info.error));
 }
 
@@ -811,14 +800,6 @@ read_sep_field(THD *thd, COPY_INFO &info
     if (write_record(thd, table, &info))
       DBUG_RETURN(1);
     /*
-      If auto_increment values are used, save the first one
-       for LAST_INSERT_ID() and for the binary/update log.
-       We can't use insert_id() as we don't want to touch the
-       last_insert_id_used flag.
-    */
-    if (!id && thd->insert_id_used)
-      id= thd->last_insert_id;
-    /*
       We don't need to reset auto-increment field since we are restoring
       its default value at the beginning of each loop iteration.
     */
@@ -837,8 +818,6 @@ read_sep_field(THD *thd, COPY_INFO &info
     thd->row_count++;
 continue_loop:;
   }
-  if (id && !read_info.error)
-    thd->insert_id(id);			// For binary/update log
   DBUG_RETURN(test(read_info.error));
 }
 

--- 1.567/sql/sql_parse.cc	2006-07-13 00:19:20 +04:00
+++ 1.568/sql/sql_parse.cc	2006-07-13 00:19:20 +04:00
@@ -818,6 +818,37 @@ static void reset_mqh(LEX_USER *lu, bool
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 }
 
+void thd_init_client_charset(THD *thd, uint cs_number)
+{
+  /*
+   Use server character set and collation if
+   - opt_character_set_client_handshake is not set
+   - client has not specified a character set
+   - client character set is the same as the servers
+   - client character set doesn't exists in server
+  */
+  if (!opt_character_set_client_handshake ||
+      !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
+      !my_strcasecmp(&my_charset_latin1,
+                     global_system_variables.character_set_client->name,
+                     thd->variables.character_set_client->name))
+  {
+    thd->variables.character_set_client=
+      global_system_variables.character_set_client;
+    thd->variables.collation_connection=
+      global_system_variables.collation_connection;
+    thd->variables.character_set_results=
+      global_system_variables.character_set_results;
+  }
+  else
+  {
+    thd->variables.character_set_results=
+      thd->variables.collation_connection= 
+      thd->variables.character_set_client;
+  }
+}
+
+
 /*
     Perform handshake, authorize client and update thd ACL variables.
   SYNOPSIS
@@ -953,33 +984,7 @@ static int check_connection(THD *thd)
     thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
     thd->max_client_packet_length= uint4korr(net->read_pos+4);
     DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
-    /*
-      Use server character set and collation if
-      - opt_character_set_client_handshake is not set
-      - client has not specified a character set
-      - client character set is the same as the servers
-      - client character set doesn't exists in server
-    */
-    if (!opt_character_set_client_handshake ||
-        !(thd->variables.character_set_client=
-	  get_charset((uint) net->read_pos[8], MYF(0))) ||
-	!my_strcasecmp(&my_charset_latin1,
-		       global_system_variables.character_set_client->name,
-		       thd->variables.character_set_client->name))
-    {
-      thd->variables.character_set_client=
-	global_system_variables.character_set_client;
-      thd->variables.collation_connection=
-	global_system_variables.collation_connection;
-      thd->variables.character_set_results=
-	global_system_variables.character_set_results;
-    }
-    else
-    {
-      thd->variables.character_set_results=
-      thd->variables.collation_connection= 
-	thd->variables.character_set_client;
-    }
+    thd_init_client_charset(thd, (uint) net->read_pos[8]);
     thd->update_charset();
     end= (char*) net->read_pos+32;
   }
@@ -2558,11 +2563,6 @@ mysql_execute_command(THD *thd)
   statistic_increment(thd->status_var.com_stat[lex->sql_command],
                       &LOCK_status);
 
-#ifdef HAVE_ROW_BASED_REPLICATION
-  if (lex->binlog_row_based_if_mixed)
-    thd->set_current_stmt_binlog_row_based_if_mixed();
-#endif /*HAVE_ROW_BASED_REPLICATION*/
-
   switch (lex->sql_command) {
   case SQLCOM_SHOW_EVENTS:
     if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
@@ -3112,6 +3112,12 @@ end_with_restore_list:
 	}
       }
       /* Don't yet allow changing of symlinks with ALTER TABLE */
+      if (lex->create_info.data_file_name)
+        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+                     "DATA DIRECTORY option ignored");
+      if (lex->create_info.index_file_name)
+        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+                     "INDEX DIRECTORY option ignored");
       lex->create_info.data_file_name=lex->create_info.index_file_name=0;
       /* ALTER TABLE ends previous transaction */
       if (end_active_trans(thd))
@@ -3382,8 +3388,9 @@ end_with_restore_list:
     res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
 		      lex->update_list, lex->value_list,
                       lex->duplicates, lex->ignore);
+    /* do not show last insert ID if VIEW does not have auto_inc */
     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
+      thd->first_successful_insert_id_in_cur_stmt= 0;
     break;
   }
   case SQLCOM_REPLACE_SELECT:
@@ -3443,9 +3450,9 @@ end_with_restore_list:
       /* revert changes for SP */
       select_lex->table_list.first= (byte*) first_table;
     }
-
+    /* do not show last insert ID if VIEW does not have auto_inc */
     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
+      thd->first_successful_insert_id_in_cur_stmt= 0;
     break;
   }
   case SQLCOM_TRUNCATE:
@@ -5189,9 +5196,6 @@ end:
   */
   if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
     reset_one_shot_variables(thd);
-#ifdef HAVE_ROW_BASED_REPLICATION
-  thd->reset_current_stmt_binlog_row_based();
-#endif /*HAVE_ROW_BASED_REPLICATION*/
 
   /*
     The return value for ROW_COUNT() is "implementation dependent" if the
@@ -5823,6 +5827,7 @@ mysql_init_query(THD *thd, uchar *buf, u
  DESCRIPTION
    This needs to be called before execution of every statement
    (prepared or conventional).
+   It is not called by substatements of routines.
 
  TODO
    Make it a method of THD and align its name with the rest of
@@ -5833,9 +5838,12 @@ mysql_init_query(THD *thd, uchar *buf, u
 void mysql_reset_thd_for_next_command(THD *thd)
 {
   DBUG_ENTER("mysql_reset_thd_for_next_command");
+  DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
   thd->free_list= 0;
   thd->select_number= 1;
-  thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
+  thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty();
+  thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 
+    thd->query_start_used= 0;
   thd->is_fatal_error= thd->time_zone_used= 0;
   thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | 
                           SERVER_QUERY_NO_INDEX_USED |
@@ -5862,6 +5870,12 @@ void mysql_reset_thd_for_next_command(TH
     thd->rand_used= 0;
     thd->sent_row_count= thd->examined_row_count= 0;
   }
+  /*
+    Because we come here only for start of top-statements, binlog format is
+    constant inside a complex statement (using stored functions) etc.
+  */
+  thd->reset_current_stmt_binlog_row_based();
+
   DBUG_VOID_RETURN;
 }
 

--- 1.357/sql/sql_table.cc	2006-07-13 00:19:21 +04:00
+++ 1.358/sql/sql_table.cc	2006-07-13 00:19:21 +04:00
@@ -4964,7 +4964,6 @@ bool mysql_alter_table(THD *thd,char *ne
   char path[FN_REFLEN];
   char reg_path[FN_REFLEN+1];
   ha_rows copied,deleted;
-  ulonglong next_insert_id;
   uint db_create_options, used_fields;
   handlerton *old_db_type, *new_db_type;
   HA_CREATE_INFO *create_info;
@@ -5784,7 +5783,6 @@ bool mysql_alter_table(THD *thd,char *ne
   thd->count_cuted_fields= CHECK_FIELD_WARN;	// calc cuted fields
   thd->cuted_fields=0L;
   thd->proc_info="copy to tmp table";
-  next_insert_id=thd->next_insert_id;		// Remember for logging
   copied=deleted=0;
   if (new_table && !(new_table->file->ha_table_flags() &
HA_NO_COPY_ON_ALTER))
   {
@@ -5794,7 +5792,6 @@ bool mysql_alter_table(THD *thd,char *ne
     error=copy_data_between_tables(table, new_table, create_list, ignore,
 				   order_num, order, &copied, &deleted);
   }
-  thd->last_insert_id=next_insert_id;		// Needed for correct log
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
   /* If we did not need to copy, we might still need to add/drop indexes. */
@@ -6223,6 +6220,7 @@ copy_data_between_tables(TABLE *from,TAB
   ha_rows examined_rows;
   bool auto_increment_field_copied= 0;
   ulong save_sql_mode;
+  ulonglong prev_insert_id;
   DBUG_ENTER("copy_data_between_tables");
 
   /*
@@ -6328,6 +6326,7 @@ copy_data_between_tables(TABLE *from,TAB
     {
       copy_ptr->do_copy(copy_ptr);
     }
+    prev_insert_id= to->file->next_insert_id;
     if ((error=to->file->ha_write_row((byte*) to->record[0])))
     {
       if (!ignore ||
@@ -6351,7 +6350,7 @@ copy_data_between_tables(TABLE *from,TAB
 	to->file->print_error(error,MYF(0));
 	break;
       }
-      to->file->restore_auto_increment();
+      to->file->restore_auto_increment(prev_insert_id);
       delete_count++;
     }
     else
@@ -6385,6 +6384,7 @@ copy_data_between_tables(TABLE *from,TAB
   free_io_cache(from);
   *copied= found_count;
   *deleted=delete_count;
+  to->file->ha_release_auto_increment();
   if (to->file->ha_external_lock(thd,F_UNLCK))
     error=1;
   DBUG_RETURN(error > 0 ? -1 : 0);

--- 1.199/sql/sql_update.cc	2006-07-13 00:19:21 +04:00
+++ 1.200/sql/sql_update.cc	2006-07-13 00:19:21 +04:00
@@ -135,7 +135,8 @@ int mysql_update(THD *thd,
   SQL_SELECT	*select;
   READ_RECORD	info;
   SELECT_LEX    *select_lex= &thd->lex->select_lex;
-  bool need_reopen;
+  bool          need_reopen;
+  ulonglong     id;
   DBUG_ENTER("mysql_update");
 
   for ( ; ; )
@@ -676,6 +677,10 @@ int mysql_update(THD *thd,
     thd->lock=0;
   }
 
+  /* If LAST_INSERT_ID(X) was used, report X */
+  id= thd->arg_of_last_insert_id_function ?
+    thd->first_successful_insert_id_in_prev_stmt : 0;
+
   if (error < 0)
   {
     char buff[STRING_BUFFER_USUAL_SIZE];
@@ -683,8 +688,7 @@ int mysql_update(THD *thd,
 	    (ulong) thd->cuted_fields);
     thd->row_count_func=
       (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
-    send_ok(thd, (ulong) thd->row_count_func,
-	    thd->insert_id_used ? thd->insert_id() : 0L,buff);
+    send_ok(thd, (ulong) thd->row_count_func, id, buff);
     DBUG_PRINT("info",("%d records updated",updated));
   }
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;		/* calc cuted fields */
@@ -1634,6 +1638,7 @@ err2:
 bool multi_update::send_eof()
 {
   char buff[STRING_BUFFER_USUAL_SIZE];
+  ulonglong id;
   thd->proc_info="updating reference tables";
 
   /* Does updates for the last n - 1 tables, returns 0 if ok */
@@ -1686,12 +1691,12 @@ bool multi_update::send_eof()
     return TRUE;
   }
 
-
+  id= thd->arg_of_last_insert_id_function ?
+    thd->first_successful_insert_id_in_prev_stmt : 0;
   sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
 	  (ulong) thd->cuted_fields);
   thd->row_count_func=
     (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
-  ::send_ok(thd, (ulong) thd->row_count_func,
-	    thd->insert_id_used ? thd->insert_id() : 0L,buff);
+  ::send_ok(thd, (ulong) thd->row_count_func, id, buff);
   return FALSE;
 }

--- 1.230/sql/table.cc	2006-07-13 00:19:21 +04:00
+++ 1.231/sql/table.cc	2006-07-13 00:19:21 +04:00
@@ -3925,16 +3925,7 @@ void st_table::mark_auto_increment_colum
 void st_table::mark_columns_needed_for_delete()
 {
   if (triggers)
-  {
-    if (triggers->bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] ||
-        triggers->bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER])
-    {
-      /* TODO: optimize to only add columns used by trigger */
-      use_all_columns();
-      return;
-    }
-  }
-
+    triggers->mark_fields_used(TRG_EVENT_DELETE);
   if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
   {
     Field **reg_field;
@@ -3985,15 +3976,7 @@ void st_table::mark_columns_needed_for_u
 {
   DBUG_ENTER("mark_columns_needed_for_update");
   if (triggers)
-  {
-    if (triggers->bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE] ||
-        triggers->bodies[TRG_EVENT_UPDATE][TRG_ACTION_AFTER])
-    {
-      /* TODO: optimize to only add columns used by trigger */
-      use_all_columns();
-      DBUG_VOID_RETURN;
-    }
-  }
+    triggers->mark_fields_used(TRG_EVENT_UPDATE);
   if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
   {
     /* Mark all used key columns for read */
@@ -4036,13 +4019,14 @@ void st_table::mark_columns_needed_for_i
 {
   if (triggers)
   {
-    if (triggers->bodies[TRG_EVENT_INSERT][TRG_ACTION_BEFORE] ||
-        triggers->bodies[TRG_EVENT_INSERT][TRG_ACTION_AFTER])
-    {
-      /* TODO: optimize to only add columns used by trigger */
-      use_all_columns();
-      return;
-    }
+    /*
+      We don't need to mark columns which are used by ON DELETE and
+      ON UPDATE triggers, which may be invoked in case of REPLACE or
+      INSERT ... ON DUPLICATE KEY UPDATE, since before doing actual
+      row replacement or update write_record() will mark all table
+      fields as used.
+    */
+    triggers->mark_fields_used(TRG_EVENT_INSERT);
   }
   if (found_next_number_field)
     mark_auto_increment_column();

--- 1.59/sql/sql_trigger.cc	2006-07-13 00:19:21 +04:00
+++ 1.60/sql/sql_trigger.cc	2006-07-13 00:19:21 +04:00
@@ -733,7 +733,8 @@ bool Table_triggers_list::prepare_record
       QQ: it is supposed that it is ok to use this function for field
       cloning...
     */
-    if (!(*old_fld= (*fld)->new_field(&table->mem_root, table)))
+    if (!(*old_fld= (*fld)->new_field(&table->mem_root, table,
+                                      table == (*fld)->table)))
       return 1;
     (*old_fld)->move_field_offset((my_ptrdiff_t)(table->record[1] -
                                           table->record[0]));

--- 1.338/sql/ha_ndbcluster.cc	2006-07-13 00:19:21 +04:00
+++ 1.339/sql/ha_ndbcluster.cc	2006-07-13 00:19:21 +04:00
@@ -2473,9 +2473,7 @@ int ha_ndbcluster::write_row(byte *recor
 
       m_skip_auto_increment= FALSE;
       update_auto_increment();
-      /* Ensure that handler is always called for auto_increment values */
-      thd->next_insert_id= 0;
-      m_skip_auto_increment= !auto_increment_column_changed;
+      m_skip_auto_increment= (insert_id_for_cur_row == 0);
     }
   }
 
@@ -4785,7 +4783,7 @@ int ha_ndbcluster::create(const char *na
         expect it to be there.
       */
       if (!ndbcluster_create_event(ndb, m_table, event_name.c_ptr(), share,
-                                   share && do_event_op /* push warning */))
+                                   share && do_event_op ? 2 : 1/* push warning
*/))
       {
         if (ndb_extra_logging)
           sql_print_information("NDB Binlog: CREATE TABLE Event: %s",
@@ -5179,7 +5177,7 @@ int ha_ndbcluster::rename_table(const ch
     const NDBTAB *ndbtab= ndbtab_g2.get_table();
 
     if (!ndbcluster_create_event(ndb, ndbtab, event_name.c_ptr(), share,
-                                 share && ndb_binlog_running /* push warning */))
+                                 share && ndb_binlog_running ? 2 : 1/* push
warning */))
     {
       if (ndb_extra_logging)
         sql_print_information("NDB Binlog: RENAME Event: %s",

--- 1.61/sql/ha_partition.cc	2006-07-13 00:19:21 +04:00
+++ 1.62/sql/ha_partition.cc	2006-07-13 00:19:21 +04:00
@@ -5284,7 +5284,7 @@ int ha_partition::cmp_ref(const byte *re
                 MODULE auto increment
 ****************************************************************************/
 
-void ha_partition::restore_auto_increment()
+void ha_partition::restore_auto_increment(ulonglong)
 {
   DBUG_ENTER("ha_partition::restore_auto_increment");
 

--- 1.32/mysql-test/r/federated.result	2006-07-13 00:19:21 +04:00
+++ 1.33/mysql-test/r/federated.result	2006-07-13 00:19:21 +04:00
@@ -1558,6 +1558,8 @@ id
 3
 4
 5
+DROP TABLE federated.t1;
+DROP TABLE federated.t1;
 DROP TABLE IF EXISTS federated.bug_17377_table;
 CREATE TABLE federated.bug_17377_table (
 `fld_cid` bigint(20) NOT NULL auto_increment,
@@ -1630,6 +1632,92 @@ a	b	c
 5	6	30
 drop tables federated.t1, federated.t2;
 drop table federated.t1;
+create table federated.t1 (i1 int, i2 int, i3 int);
+create table federated.t2 (id int, c1 varchar(20), c2 varchar(20));
+create table federated.t1 (i1 int, i2 int, i3 int) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:SLAVE_PORT/federated/t1';
+create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:SLAVE_PORT/federated/t2';
+insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
+insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
+select * from federated.t1 order by i1;
+i1	i2	i3
+1	5	10
+2	2	2
+3	7	12
+4	5	2
+9	10	15
+select * from federated.t2;
+id	c1	c2
+9	abc	def
+5	opq	lmn
+2	test t	t test
+update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
+select * from federated.t1 order by i1;
+i1	i2	i3
+1	5	10
+2	15	2
+3	7	12
+4	5	2
+9	15	15
+select * from federated.t2 order by id;
+id	c1	c2
+2	test t	ppc
+5	opq	lmn
+9	abc	ppc
+delete   federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
+select * from federated.t1 order by i1;
+i1	i2	i3
+2	15	2
+3	7	12
+9	15	15
+select * from federated.t2 order by id;
+id	c1	c2
+2	test t	ppc
+9	abc	ppc
+drop table federated.t1, federated.t2;
+drop table federated.t1, federated.t2;
+create table federated.t1 (i1 int, i2 int, i3 int, primary key (i1));
+create table federated.t2 (id int, c1 varchar(20), c2 varchar(20), primary key (id));
+create table federated.t1 (i1 int auto_increment not null, i2 int, i3 int, primary key
(i1)) ENGINE=FEDERATED CONNECTION='mysql://root@stripped:SLAVE_PORT/federated/t1';
+create table federated.t2 (id int auto_increment not null, c1 varchar(20), c2
varchar(20), primary key(id)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:SLAVE_PORT/federated/t2';
+insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
+insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
+select * from federated.t1 order by i1;
+i1	i2	i3
+1	5	10
+2	2	2
+3	7	12
+4	5	2
+9	10	15
+select * from federated.t2 order by id;
+id	c1	c2
+2	test t	t test
+5	opq	lmn
+9	abc	def
+update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
+select * from federated.t1 order by i1;
+i1	i2	i3
+1	5	10
+2	15	2
+3	7	12
+4	5	2
+9	15	15
+select * from federated.t2 order by id;
+id	c1	c2
+2	test t	ppc
+5	opq	lmn
+9	abc	ppc
+delete federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
+select * from federated.t1 order by i1;
+i1	i2	i3
+2	15	2
+3	7	12
+9	15	15
+select * from federated.t2 order by id;
+id	c1	c2
+2	test t	ppc
+9	abc	ppc
+drop table federated.t1, federated.t2;
+drop table federated.t1, federated.t2;
 DROP TABLE IF EXISTS federated.t1;
 DROP DATABASE IF EXISTS federated;
 DROP TABLE IF EXISTS federated.t1;

--- 1.28/mysql-test/t/federated.test	2006-07-13 00:19:21 +04:00
+++ 1.29/mysql-test/t/federated.test	2006-07-13 00:19:21 +04:00
@@ -1256,6 +1256,10 @@ SELECT LAST_INSERT_ID();
 INSERT INTO federated.t1 VALUES ();
 SELECT LAST_INSERT_ID();
 SELECT * FROM federated.t1;
+DROP TABLE federated.t1;
+
+connection slave;
+DROP TABLE federated.t1;
 
 #
 # Bug#17377 Federated Engine returns wrong Data, always the rows
@@ -1310,7 +1314,6 @@ select * from federated.t1 where fld_par
 DROP TABLE federated.t1;
 connection slave;
 DROP TABLE federated.bug_17377_table;
-DROP TABLE federated.t1;
 
 #
 # Test multi updates and deletes without keys
@@ -1405,4 +1408,56 @@ drop tables federated.t1, federated.t2;
 connection slave;
 drop table federated.t1;
 
---source include/federated_cleanup.inc
+#
+# BUG 19773 Crash when using multi-table updates, deletes
+# with federated tables
+#
+connection slave;
+create table federated.t1 (i1 int, i2 int, i3 int);
+create table federated.t2 (id int, c1 varchar(20), c2 varchar(20));
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table federated.t1 (i1 int, i2 int, i3 int) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:$SLAVE_MYPORT/federated/t1';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:$SLAVE_MYPORT/federated/t2';
+insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
+insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
+select * from federated.t1 order by i1;
+select * from federated.t2;
+update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
+select * from federated.t1 order by i1;
+select * from federated.t2 order by id;
+delete   federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
+select * from federated.t1 order by i1;
+select * from federated.t2 order by id;
+drop table federated.t1, federated.t2;
+connection slave;
+drop table federated.t1, federated.t2;
+
+# Test multi updates and deletes with keys
+connection slave;
+create table federated.t1 (i1 int, i2 int, i3 int, primary key (i1));
+create table federated.t2 (id int, c1 varchar(20), c2 varchar(20), primary key (id));
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table federated.t1 (i1 int auto_increment not null, i2 int, i3 int, primary
key (i1)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:$SLAVE_MYPORT/federated/t1';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table federated.t2 (id int auto_increment not null, c1 varchar(20), c2
varchar(20), primary key(id)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:$SLAVE_MYPORT/federated/t2';
+insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
+insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
+select * from federated.t1 order by i1;
+select * from federated.t2 order by id;
+update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
+select * from federated.t1 order by i1;
+select * from federated.t2 order by id;
+delete federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
+select * from federated.t1 order by i1;
+select * from federated.t2 order by id;
+drop table federated.t1, federated.t2;
+
+connection slave;
+drop table federated.t1, federated.t2;
+
+source include/federated_cleanup.inc;
Thread
bk commit into 5.1 tree (kostja:1.2243)konstantin12 Jul