List:Commits« Previous MessageNext Message »
From:Martin Skold Date:September 9 2011 12:42pm
Subject:bzr push into mysql-5.5-cluster branch (Martin.Skold:3469 to 3470)
View as plain text  
 3470 Martin Skold	2011-09-09
      Added new abort phase for online alter to support the rollback of add index during failure in mysql-5.5 (for example at DDL lock timeout) in mysql-5.5.
       Enabled innodb_mysql_sync and kill tests and added new test case in ndb_alter_table_online2.

    modified:
      mysql-test/suite/ndb/r/ndb_alter_table_online2.result
      mysql-test/suite/ndb/t/ndb_alter_table_online2.test
      mysql-test/t/disabled.def
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster.h
      sql/handler.cc
      sql/handler.h
      sql/sql_table.cc
 3469 Frazer Clement	2011-09-09 [merge]
      Merge 7.1->5.5-cluster

    added:
      mysql-test/suite/ndb_binlog/r/ndb_binlog_log_transaction_id.result
      mysql-test/suite/ndb_binlog/t/ndb_binlog_get_row_extra_data.inc
      mysql-test/suite/ndb_binlog/t/ndb_binlog_log_transaction_id-master.opt
      mysql-test/suite/ndb_binlog/t/ndb_binlog_log_transaction_id.test
      mysql-test/suite/ndb_rpl/r/ndb_rpl_conflict_epoch_trans.result
      mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict_epoch_trans.cnf
      mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict_epoch_trans.test
      mysql-test/suite/ndb_rpl/t/ndb_trans_conflict_info.inc
      mysql-test/suite/ndb_rpl/t/ndb_trans_conflict_info_init.inc
      mysql-test/suite/ndb_rpl/t/ndb_trans_conflict_info_stable.inc
      mysql-test/suite/rpl/r/rpl_extra_row_data.result
      mysql-test/suite/rpl/t/rpl_extra_row_data-master.opt
      mysql-test/suite/rpl/t/rpl_extra_row_data-slave.opt
      mysql-test/suite/rpl/t/rpl_extra_row_data.test
      sql/ndb_conflict_trans.cc
      sql/ndb_conflict_trans.h
      storage/ndb/include/util/HashMap2.hpp
      storage/ndb/include/util/LinkedStack.hpp
      storage/ndb/src/common/util/HashMap2.cpp
      storage/ndb/src/common/util/LinkedStack.cpp
    modified:
      mysql-test/suite/ndb/r/ndb_basic.result
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster.h
      sql/ha_ndbcluster_binlog.cc
      sql/ha_ndbcluster_binlog.h
      sql/ha_ndbcluster_glue.h
      sql/log_event.cc
      sql/log_event.h
      sql/ndb_mi.cc
      sql/ndb_mi.h
      sql/ndb_share.h
      sql/rpl_constants.h
      sql/slave.h
      sql/sql_class.cc
      sql/sql_class.h
      storage/ndb/CMakeLists.txt
      storage/ndb/include/ndbapi/Ndb.hpp
      storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
      storage/ndb/src/common/portlib/NdbTCP.cpp
      storage/ndb/src/common/util/CMakeLists.txt
      storage/ndb/src/ndbapi/Ndb.cpp
      storage/ndb/src/ndbapi/Ndbif.cpp
      storage/ndb/src/ndbapi/TransporterFacade.cpp
      storage/ndb/src/ndbapi/TransporterFacade.hpp
      storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
      storage/ndb/src/ndbapi/trp_client.cpp
      storage/ndb/src/ndbapi/trp_client.hpp
=== modified file 'mysql-test/suite/ndb/r/ndb_alter_table_online2.result'
--- a/mysql-test/suite/ndb/r/ndb_alter_table_online2.result	2011-05-13 11:42:59 +0000
+++ b/mysql-test/suite/ndb/r/ndb_alter_table_online2.result	2011-09-09 12:41:37 +0000
@@ -98,6 +98,32 @@ name
 't1'
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~ test that aborted online alter rollback DDL transaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# Connection default
+START TRANSACTION;
+SELECT * FROM t1;
+pk	a	b	c
+1	5000	5000	5000
+# Connection con1
+SET lock_wait_timeout=1;
+ALTER ONLINE TABLE t1 ADD d INT;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ALTER ONLINE TABLE t1 ADD d INT;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1;
+pk	a	b	c
+1	5000	5000	5000
+COMMIT;
+
+ndb_show_tables completed.....
+
+select name from ndb_show_tables_results where id = @t1_id and name like '%t1%' and type like '%UserTable%';
+name
+'t1'
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~ cleanup section
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

=== modified file 'mysql-test/suite/ndb/t/ndb_alter_table_online2.test'
--- a/mysql-test/suite/ndb/t/ndb_alter_table_online2.test	2011-05-30 21:13:02 +0000
+++ b/mysql-test/suite/ndb/t/ndb_alter_table_online2.test	2011-09-09 12:41:37 +0000
@@ -16,6 +16,8 @@
 -- source include/not_windows.inc
 # -- source include/have_log_bin.inc
 
+connection default;
+
 --disable_warnings
 DROP TABLE IF EXISTS t1;
 CREATE DATABASE IF NOT EXISTS mysqlslap;
@@ -178,6 +180,34 @@ ALTER ONLINE TABLE t1 PARTITION BY HASH(
 --source ndb_show_tables_result.inc
 select name from ndb_show_tables_results where id = @t1_id and name like '%t1%' and type like '%UserTable%';
 
+
+--echo
+--echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--echo ~ test that aborted online alter rollback DDL transaction
+--echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--echo
+
+connect (con1,localhost,root,,test);
+
+--echo # Connection default
+connection default;
+START TRANSACTION;
+SELECT * FROM t1;
+
+--echo # Connection con1
+--connection con1
+SET lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+ALTER ONLINE TABLE t1 ADD d INT;
+--error ER_LOCK_WAIT_TIMEOUT
+ALTER ONLINE TABLE t1 ADD d INT;
+SELECT * FROM t1;
+
+connection default;
+COMMIT;
+--source ndb_show_tables_result.inc
+select name from ndb_show_tables_results where id = @t1_id and name like '%t1%' and type like '%UserTable%';
+
 --echo
 --echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 --echo ~ cleanup section

=== modified file 'mysql-test/t/disabled.def'
--- a/mysql-test/t/disabled.def	2011-09-05 07:48:52 +0000
+++ b/mysql-test/t/disabled.def	2011-09-09 12:41:37 +0000
@@ -18,6 +18,4 @@ archive-big              : Bug#11817185 
 file_contents            : Bug#12585902 file_contents.test fails when building from "bzr export"
 log_tables-big           : Bug#11756699 2010-11-15 mattiasj report already exists
 mysql_embedded           : Bug#12561297 seems to be fixed in 5.5.16 (I verified that it fails also in tag:mysql-5.5.15)
-innodb_mysql_sync        : Merge problems, DEBUG_SYNC wait conditions are not identical, Martin working on it
-kill                     : Merge problems, DEBUG_SYNC wait conditions are not identical, Martin working on it
 

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2011-09-09 09:30:43 +0000
+++ b/sql/ha_ndbcluster.cc	2011-09-09 12:41:37 +0000
@@ -16306,7 +16306,7 @@ HA_ALTER_FLAGS supported_alter_operation
 
 int ha_ndbcluster::check_if_supported_alter(TABLE *altered_table,
                                             HA_CREATE_INFO *create_info,
-                                            Alter_info *alter_info,
+                                            HA_ALTER_INFO *alter_info,
                                             HA_ALTER_FLAGS *alter_flags,
                                             uint table_changes)
 {
@@ -16992,6 +16992,31 @@ int ha_ndbcluster::alter_table_phase3(TH
   alter_info->data= 0;
   DBUG_RETURN(0);
 }
+
+int ha_ndbcluster::alter_table_abort(THD *thd, TABLE *table,
+                                     HA_ALTER_INFO *alter_info,
+                                     HA_ALTER_FLAGS *alter_flags)
+{
+  int error= 0;
+  Thd_ndb *thd_ndb= get_thd_ndb(thd);
+  NDB_ALTER_DATA *alter_data= (NDB_ALTER_DATA *) alter_info->data;
+  NDBDICT *dict= alter_data->dictionary;
+  DBUG_ENTER("alter_table_abort");
+  if (dict->endSchemaTrans(NdbDictionary::Dictionary::SchemaTransAbort)
+      == -1)
+  {
+    DBUG_PRINT("info", ("Failed to abort schema transaction"));
+    ERR_PRINT(dict->getNdbError());
+  }
+  /* ndb_share reference schema free */
+  DBUG_PRINT("NDB_SHARE", ("%s binlog schema free  use_count: %u",
+                           m_share->key, m_share->use_count));
+  delete alter_data;
+  alter_info->data= 0;
+  set_ndb_share_state(m_share, NSS_INITIAL);
+  free_share(&m_share); // Decrease ref_count
+  DBUG_RETURN(error);
+}
 #endif
 
 bool set_up_tablespace(st_alter_tablespace *alter_info,

=== modified file 'sql/ha_ndbcluster.h'
--- a/sql/ha_ndbcluster.h	2011-09-09 09:30:43 +0000
+++ b/sql/ha_ndbcluster.h	2011-09-09 12:41:37 +0000
@@ -514,7 +514,7 @@ static void set_tabname(const char *path
 #ifndef MCP_WL3749
   int check_if_supported_alter(TABLE *altered_table,
                                HA_CREATE_INFO *create_info,
-                               Alter_info *alter_info,
+                               HA_ALTER_INFO *alter_info,
                                HA_ALTER_FLAGS *alter_flags,
                                uint table_changes);
 
@@ -534,6 +534,10 @@ static void set_tabname(const char *path
                          HA_CREATE_INFO *create_info,
                          HA_ALTER_INFO *alter_info,
                          HA_ALTER_FLAGS *alter_flags);
+
+  int alter_table_abort(THD *thd, TABLE *table,
+                        HA_ALTER_INFO *alter_info,
+                        HA_ALTER_FLAGS *alter_flags);
 #endif
 
 private:

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2011-09-02 09:16:56 +0000
+++ b/sql/handler.cc	2011-09-09 12:41:37 +0000
@@ -3467,13 +3467,19 @@ is_index_maintenance_unique (TABLE *tabl
 int
 handler::check_if_supported_alter(TABLE *altered_table,
                                   HA_CREATE_INFO *create_info,
-                                  Alter_info *alter_info,
+                                  HA_ALTER_INFO *alter_info,
                                   HA_ALTER_FLAGS *alter_flags,
                                   uint table_changes)
 {
   DBUG_ENTER("check_if_supported_alter");
   int result= HA_ALTER_NOT_SUPPORTED;
   ulong handler_alter_flags= table->file->alter_table_flags(0);
+  Alter_info *old_alter_info= (Alter_info *) alter_info->data;
+  bool no_pk= ((table->s->primary_key == MAX_KEY) ||
+               alter_flags->is_set(HA_DROP_PK_INDEX));
+  uint candidate_key_count= alter_info->candidate_key_count;
+  bool need_lock_for_indexes= TRUE;
+  enum_alter_table_change_level need_copy_table= old_alter_info->change_level;
   HA_ALTER_FLAGS supported_alter_operations;
   supported_alter_operations=
     supported_alter_operations |
@@ -3495,7 +3501,7 @@ handler::check_if_supported_alter(TABLE 
     HA_ADD_CONSTRAINT;
   HA_ALTER_FLAGS not_supported= ~(supported_alter_operations);
   HA_ALTER_FLAGS fast_operations= not_supported & ~(not_fast_operations);
-  DBUG_PRINT("info", ("handler_alter_flags: %lu", handler_alter_flags));
+  DBUG_PRINT("info", ("handler_alter_flags: 0x%lx", handler_alter_flags));
 #ifndef DBUG_OFF
   {
     char dbug_string[HA_MAX_ALTER_FLAGS+1];
@@ -3508,17 +3514,12 @@ handler::check_if_supported_alter(TABLE 
   }
 #endif
 
-  /* Bug #49838 DROP INDEX and ADD UNIQUE INDEX for same index may corrupt definition at engine */
-  if (is_index_maintenance_unique(table, alter_info))
-    DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
-
   /* Check the old alter table flags */
   if ((*alter_flags & fast_operations).is_set() &&
       table_changes != IS_EQUAL_NO)
   {
     /* Not adding/dropping index check if supported as fast alter */
-    DBUG_PRINT("info", ("alter_info->change_level %u", alter_info->change_level));
-    if (alter_info->change_level == ALTER_TABLE_METADATA_ONLY &&
+    if (need_copy_table == ALTER_TABLE_METADATA_ONLY &&
         table->file->check_if_incompatible_data(create_info, table_changes)
         != COMPATIBLE_DATA_NO) 
       DBUG_RETURN(HA_ALTER_SUPPORTED_WAIT_LOCK);
@@ -3529,85 +3530,261 @@ handler::check_if_supported_alter(TABLE 
     DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
   else
   {
+    /* Adding or dropping index */
+
+    /* Bug #49838 DROP INDEX and ADD UNIQUE INDEX for same index may corrupt definition at engine */
+    if (is_index_maintenance_unique(table, old_alter_info))
+      DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+    
+    DBUG_EXECUTE_IF("alter_table_only_metadata_change", {
+        if (need_copy_table != ALTER_TABLE_METADATA_ONLY)
+          DBUG_RETURN(HA_ALTER_ERROR); });
+    DBUG_EXECUTE_IF("alter_table_only_index_change", {
+        if (need_copy_table != ALTER_TABLE_INDEX_CHANGED)
+          DBUG_RETURN(HA_ALTER_ERROR); });
+    
+    DBUG_PRINT("info", ("%i: need_copy_table %u", __LINE__, need_copy_table));
+    
+    /*
+      If there are index changes only, try to do them in-place. "Index
+      changes only" means also that the handler for the table does not
+      change. The table is open and locked. The handler can be accessed.
+    */
+    if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
+    {
+      int   pk_changed= 0;
+      ulong alter_flags= 0;
+      ulong needed_inplace_with_read_flags= 0;
+      ulong needed_inplace_flags= 0;
+      KEY   *key;
+      uint  *idx_p;
+      uint  *idx_end_p;
+      
+      alter_flags= table->file->alter_table_flags(old_alter_info->flags);
+      DBUG_PRINT("info", ("alter_flags: %lu", alter_flags));
+      /* Check dropped indexes. */
+      for (idx_p= alter_info->index_drop_buffer,
+             idx_end_p= idx_p + alter_info->index_drop_count;
+           idx_p < idx_end_p;
+           idx_p++)
+      {
+        key= table->key_info + *idx_p;
+        DBUG_PRINT("info", ("index dropped: '%s'", key->name));
+        if (key->flags & HA_NOSAME)
+        {
+          /* 
+             Unique key. Check for "PRIMARY". 
+             or if dropping last unique key
+          */
+          if ((uint) (key - table->key_info) == table->s->primary_key)
+          {
+            DBUG_PRINT("info", ("Dropping primary key"));
+            /* Primary key. */
+            needed_inplace_with_read_flags|= HA_INPLACE_DROP_PK_INDEX_NO_WRITE;
+            needed_inplace_flags|= HA_INPLACE_DROP_PK_INDEX_NO_READ_WRITE;
+            pk_changed++;
+            candidate_key_count--;
+          }
+          else
+          {
+            KEY_PART_INFO *part_end= key->key_part + key->key_parts;
+            bool is_candidate_key= true;
+            
+            /* Non-primary unique key. */
+            needed_inplace_with_read_flags|=
+              HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE;
+            needed_inplace_flags|= HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE;
+            
+            /*
+              Check if all fields in key are declared
+              NOT NULL and adjust candidate_key_count
+            */
+            for (KEY_PART_INFO *key_part= key->key_part;
+                 key_part < part_end;
+                 key_part++)
+              is_candidate_key=
+                (is_candidate_key && 
+                 (! table->field[key_part->fieldnr-1]->maybe_null()));
+            if (is_candidate_key)
+              candidate_key_count--;
+          }
+        }
+        else
+        {
+          /* Non-unique key. */
+          needed_inplace_with_read_flags|= HA_INPLACE_DROP_INDEX_NO_WRITE;
+          needed_inplace_flags|= HA_INPLACE_DROP_INDEX_NO_READ_WRITE;
+        }
+      }
+      no_pk= ((table->s->primary_key == MAX_KEY) ||
+              (needed_inplace_with_read_flags &
+               HA_INPLACE_DROP_PK_INDEX_NO_WRITE));
+      /* Check added indexes. */
+      for (idx_p= alter_info->index_add_buffer,
+             idx_end_p= idx_p + alter_info->index_add_count;
+           idx_p < idx_end_p;
+           idx_p++)
+      {
+        key= alter_info->key_info_buffer + *idx_p;
+        DBUG_PRINT("info", ("index added: '%s'", key->name));
+        if (key->flags & HA_NOSAME)
+        {
+          /* Unique key */
+          
+          KEY_PART_INFO *part_end= key->key_part + key->key_parts;    
+          bool is_candidate_key= true;
+          
+          /*
+            Check if all fields in key are declared
+            NOT NULL
+          */
+          for (KEY_PART_INFO *key_part= key->key_part;
+               key_part < part_end;
+               key_part++)
+            is_candidate_key=
+              (is_candidate_key && 
+               (! table->field[key_part->fieldnr]->maybe_null()));
+          
+          /*
+            Check for "PRIMARY"
+            or if adding first unique key
+            defined on non-nullable fields
+          */
+          
+          if ((!my_strcasecmp(system_charset_info,
+                              key->name, primary_key_name)) ||
+              (no_pk && candidate_key_count == 0 && is_candidate_key))
+          {
+            DBUG_PRINT("info", ("Adding primary key"));
+            /* Primary key. */
+            needed_inplace_with_read_flags|= HA_INPLACE_ADD_PK_INDEX_NO_WRITE;
+            needed_inplace_flags|= HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE;
+            pk_changed++;
+            no_pk= false;
+          }
+          else
+          {
+            /* Non-primary unique key. */
+            needed_inplace_with_read_flags|= HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE;
+            needed_inplace_flags|= HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE;
+          }
+        }
+        else
+        {
+          /* Non-unique key. */
+          needed_inplace_with_read_flags|= HA_INPLACE_ADD_INDEX_NO_WRITE;
+          needed_inplace_flags|= HA_INPLACE_ADD_INDEX_NO_READ_WRITE;
+        }
+      }
+      
+      if ((candidate_key_count > 0) &&
+          (needed_inplace_with_read_flags & HA_INPLACE_DROP_PK_INDEX_NO_WRITE))
+      {
+        /*
+          Dropped primary key when there is some other unique 
+          not null key that should be converted to primary key
+        */
+        needed_inplace_with_read_flags|= HA_INPLACE_ADD_PK_INDEX_NO_WRITE;
+        needed_inplace_flags|= HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE;
+        pk_changed= 2;
+      }
+      
+      DBUG_PRINT("info",
+                 ("needed_inplace_with_read_flags: 0x%lx, needed_inplace_flags: 0x%lx",
+                  needed_inplace_with_read_flags, needed_inplace_flags));
+      /*
+        In-place add/drop index is possible only if
+        the primary key is not added and dropped in the same statement.
+        Otherwise we have to recreate the table.
+        need_copy_table is no-zero at this place.
+      */
+      if ( pk_changed < 2 )
+      {
+        if ((alter_flags & needed_inplace_with_read_flags) ==
+            needed_inplace_with_read_flags)
+        {
+          /* All required in-place flags to allow concurrent reads are present. */
+          need_copy_table= ALTER_TABLE_METADATA_ONLY;
+          need_lock_for_indexes= FALSE;
+        }
+        else if ((alter_flags & needed_inplace_flags) == needed_inplace_flags)
+        {
+          /* All required in-place flags are present. */
+          need_copy_table= ALTER_TABLE_METADATA_ONLY;
+        }
+      }
+      DBUG_PRINT("info", ("need_copy_table: %u  need_lock: %d",
+                          need_copy_table, need_lock_for_indexes));
+    }
+
     /* Add index */
     if ((*alter_flags & HA_ADD_INDEX).is_set() ||
         (*alter_flags & HA_ALTER_INDEX).is_set())
     {
-      if (handler_alter_flags & HA_INPLACE_ADD_INDEX_NO_READ_WRITE)
+      if (need_copy_table)
+        result= HA_ALTER_NOT_SUPPORTED;
+      else if (need_lock_for_indexes)
         result= HA_ALTER_SUPPORTED_WAIT_LOCK;
-      else if (handler_alter_flags & HA_INPLACE_ADD_INDEX_NO_WRITE)
-        result= (result == HA_ALTER_SUPPORTED_WAIT_LOCK)?
-          HA_ALTER_SUPPORTED_WAIT_LOCK
-          : HA_ALTER_SUPPORTED_NO_LOCK;
       else
-        DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+        result= HA_ALTER_SUPPORTED_NO_LOCK;
     }
     /* Drop index */
     if ((*alter_flags & HA_DROP_INDEX).is_set() ||
         (*alter_flags & HA_ALTER_INDEX).is_set())
     {
-      if (handler_alter_flags & HA_INPLACE_DROP_INDEX_NO_READ_WRITE)
+      if (need_copy_table)
+        result= HA_ALTER_NOT_SUPPORTED;
+      else if (need_lock_for_indexes)
         result= HA_ALTER_SUPPORTED_WAIT_LOCK;
-      else if (handler_alter_flags & HA_INPLACE_DROP_INDEX_NO_WRITE)
-        result= (result == HA_ALTER_SUPPORTED_WAIT_LOCK)?
-          HA_ALTER_SUPPORTED_WAIT_LOCK
-          : HA_ALTER_SUPPORTED_NO_LOCK;
       else
-        DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+        result= HA_ALTER_SUPPORTED_NO_LOCK;
     }
     /* Add unique index */
     if ((*alter_flags & HA_ADD_UNIQUE_INDEX).is_set() ||
         (*alter_flags & HA_ALTER_UNIQUE_INDEX).is_set())
     {
-      if (handler_alter_flags & HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE)
+      if (need_copy_table)
+        result= HA_ALTER_NOT_SUPPORTED;
+      else if (need_lock_for_indexes)
         result= HA_ALTER_SUPPORTED_WAIT_LOCK;
-      else if (handler_alter_flags & HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE)
-        result= (result == HA_ALTER_SUPPORTED_WAIT_LOCK)?
-          HA_ALTER_SUPPORTED_WAIT_LOCK
-          : HA_ALTER_SUPPORTED_NO_LOCK;
       else
-        DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+        result= HA_ALTER_SUPPORTED_NO_LOCK;
     }
     /* Drop unique index */
     if ((*alter_flags & HA_DROP_UNIQUE_INDEX).is_set() ||
         (*alter_flags & HA_ALTER_UNIQUE_INDEX).is_set())
     {
-      if (handler_alter_flags & HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE)
+      if (need_copy_table)
+        result= HA_ALTER_NOT_SUPPORTED;
+      else if (need_lock_for_indexes)
         result= HA_ALTER_SUPPORTED_WAIT_LOCK;
-      else if (handler_alter_flags &HA_INPLACE_DROP_PK_INDEX_NO_WRITE)
-        result= (result == HA_ALTER_SUPPORTED_WAIT_LOCK)?
-          HA_ALTER_SUPPORTED_WAIT_LOCK
-          : HA_ALTER_SUPPORTED_NO_LOCK;
       else
-        DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+        result= HA_ALTER_SUPPORTED_NO_LOCK;
     }
     /* Add primary key */
     if ((*alter_flags & HA_ADD_PK_INDEX).is_set() ||
         (*alter_flags & HA_ALTER_PK_INDEX).is_set())
     {
-      if (handler_alter_flags & HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE)
+      if (need_copy_table)
+        result= HA_ALTER_NOT_SUPPORTED;
+      else if (need_lock_for_indexes)
         result= HA_ALTER_SUPPORTED_WAIT_LOCK;
-      else if (handler_alter_flags & HA_INPLACE_ADD_PK_INDEX_NO_WRITE)
-        result= (result == HA_ALTER_SUPPORTED_WAIT_LOCK)?
-          HA_ALTER_SUPPORTED_WAIT_LOCK
-          : HA_ALTER_SUPPORTED_NO_LOCK;
       else
-        DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+        result= HA_ALTER_SUPPORTED_NO_LOCK;
     }
     /* Drop primary key */
     if ((*alter_flags & HA_DROP_PK_INDEX).is_set() ||
         (*alter_flags & HA_ALTER_PK_INDEX).is_set())
     {
-      if (handler_alter_flags & HA_INPLACE_DROP_PK_INDEX_NO_READ_WRITE)
+      if (need_copy_table)
+        result= HA_ALTER_NOT_SUPPORTED;
+      else if (need_lock_for_indexes)
         result= HA_ALTER_SUPPORTED_WAIT_LOCK;
-      else if (handler_alter_flags &HA_INPLACE_DROP_PK_INDEX_NO_WRITE)
-        result= (result == HA_ALTER_SUPPORTED_WAIT_LOCK)?
-          HA_ALTER_SUPPORTED_WAIT_LOCK
-          : HA_ALTER_SUPPORTED_NO_LOCK;
       else
-        DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+        result= HA_ALTER_SUPPORTED_NO_LOCK;
     }
   }
+
   DBUG_RETURN(result);
 }
 
@@ -3629,7 +3806,7 @@ handler::alter_table_phase1(THD *thd,
 
   adding= adding | HA_ADD_INDEX | HA_ADD_UNIQUE_INDEX | HA_ADD_PK_INDEX |
     HA_ALTER_INDEX | HA_ALTER_UNIQUE_INDEX | HA_ALTER_PK_INDEX;
-  dropping= dropping | HA_DROP_INDEX | HA_DROP_UNIQUE_INDEX |
+  dropping= dropping | HA_DROP_INDEX | HA_DROP_UNIQUE_INDEX | HA_DROP_PK_INDEX |
     HA_ALTER_INDEX | HA_ALTER_UNIQUE_INDEX | HA_ALTER_PK_INDEX;
 
   if ((*alter_flags & adding).is_set())
@@ -3666,6 +3843,7 @@ handler::alter_table_phase1(THD *thd,
       table->key_info= key_info;
       table->file->print_error(error, MYF(0));
       table->key_info= save_key_info;
+      //my_error(error, MYF(0));
       DBUG_RETURN(error);
     }
     /*
@@ -3686,12 +3864,11 @@ handler::alter_table_phase1(THD *thd,
     {
       if ((error= final_add_index((handler_add_index *)alter_info->data, true)))
       {
-        print_error(error, MYF(0));
+        table->file->print_error(error, MYF(0));
         DBUG_RETURN(error);
       }
     }
 
-    DBUG_PRINT("info", ("Renumbering indexes"));
     /* The prepare_drop_index() method takes an array of key numbers. */
     key_numbers= (uint*) thd->alloc(sizeof(uint) * alter_info->index_drop_count);
     keyno_p= key_numbers;
@@ -3726,22 +3903,29 @@ handler::alter_table_phase2(THD *thd,
 
   adding= adding | HA_ADD_INDEX | HA_ADD_UNIQUE_INDEX | HA_ADD_PK_INDEX |
     HA_ALTER_INDEX | HA_ALTER_UNIQUE_INDEX | HA_ALTER_PK_INDEX;
-  dropping= dropping | HA_DROP_INDEX | HA_DROP_UNIQUE_INDEX |
+  dropping= dropping | HA_DROP_INDEX | HA_DROP_UNIQUE_INDEX | HA_DROP_PK_INDEX |
     HA_ALTER_INDEX | HA_ALTER_UNIQUE_INDEX | HA_ALTER_PK_INDEX;
 
   if ((*alter_flags & dropping).is_set())
   {
     if ((error= final_drop_index(table)))
     {
-      print_error(error, MYF(0));
+      table->file->print_error(error, MYF(0));
       DBUG_RETURN(error);
     }
   }
   else if ((*alter_flags & adding).is_set())
   {
+    DBUG_EXECUTE_IF("alter_table_rollback_new_index", {
+        error= ER_UNKNOWN_ERROR;
+        table->file->final_add_index((handler_add_index *)alter_info->data,
+                                     false);
+        my_error(error, MYF(0));
+        DBUG_RETURN(error);
+      });
     if ((error= final_add_index((handler_add_index *)alter_info->data, true)))
     {
-      print_error(error, MYF(0));
+      table->file->print_error(error, MYF(0));
       DBUG_RETURN(error);
     }
   }
@@ -3758,6 +3942,32 @@ handler::alter_table_phase3(THD *thd, TA
   DBUG_ENTER("alter_table_phase3");
   DBUG_RETURN(0);
 }
+
+int
+handler::alter_table_abort(THD *thd,
+                           HA_ALTER_INFO *alter_info,
+                           HA_ALTER_FLAGS *alter_flags)
+{
+  DBUG_ENTER("alter_table_abort");
+  int error= 0;
+  HA_ALTER_FLAGS adding;
+
+  adding= adding | HA_ADD_INDEX | HA_ADD_UNIQUE_INDEX | HA_ADD_PK_INDEX |
+    HA_ALTER_INDEX | HA_ALTER_UNIQUE_INDEX | HA_ALTER_PK_INDEX;
+
+  if ((*alter_flags & adding).is_set())
+  {
+    if ((error=
+         table->file->final_add_index((handler_add_index *)alter_info->data,
+                                      false)))
+      table->file->print_error(error, MYF(0));
+    else
+      table->file->print_error(ER_UNKNOWN_ERROR, MYF(0));
+    DBUG_RETURN(error);
+  }
+  DBUG_RETURN(0);
+}
+
 #endif
 
 /**

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2011-09-02 09:16:56 +0000
+++ b/sql/handler.h	2011-09-09 12:41:37 +0000
@@ -1147,6 +1147,7 @@ typedef struct st_ha_alter_information
 {
   KEY  *key_info_buffer;
   uint key_count;
+  uint candidate_key_count;
   uint index_drop_count;
   uint *index_drop_buffer;
   uint index_add_count;
@@ -2147,7 +2148,7 @@ public:
  */
  virtual int check_if_supported_alter(TABLE *altered_table,
                                       HA_CREATE_INFO *create_info,
-                                      Alter_info *alter_info,
+                                      HA_ALTER_INFO *alter_info,
                                       HA_ALTER_FLAGS *alter_flags,
                                       uint table_changes);
 
@@ -2212,6 +2213,19 @@ public:
                                 HA_CREATE_INFO *create_info,
                                 HA_ALTER_INFO *alter_info,
                                 HA_ALTER_FLAGS *alter_flags);
+
+ /**
+    Tell storage engine to abort (rollback) the ongoing online
+    alter table and release any allocated resources (this will be last call).
+
+    @param    thd               The thread handle
+    @param    alter_info        Storage place for data used during phase1
+                                and phase2 and phase3
+    @param    alter_flags       Bitmask that shows what has been changed
+ */
+ virtual int alter_table_abort(THD *thd,
+                               HA_ALTER_INFO *alter_info,
+                               HA_ALTER_FLAGS *alter_flags);
 #endif
 
   /**

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-08-31 10:39:08 +0000
+++ b/sql/sql_table.cc	2011-09-09 12:41:37 +0000
@@ -5449,6 +5449,9 @@ compare_tables(THD *thd,
       DBUG_PRINT("info", ("index added: '%s'", new_key->name));
     }
   }
+  if (ha_alter_info->index_drop_count || ha_alter_info->index_add_count)
+    alter_info->change_level= ALTER_TABLE_INDEX_CHANGED;
+  ha_alter_info->candidate_key_count= candidate_key_count;
 #ifndef DBUG_OFF
   {
     char dbug_string[HA_MAX_ALTER_FLAGS+1];
@@ -6017,6 +6020,7 @@ int mysql_fast_or_online_alter_table(THD
                                      HA_ALTER_INFO *alter_info,
                                      HA_ALTER_FLAGS *ha_alter_flags,
                                      enum enum_enable_or_disable keys_onoff,
+                                     bool need_lock_for_indexes,
                                      MDL_request *target_mdl_request)
 {
   int error= 0;
@@ -6034,13 +6038,15 @@ int mysql_fast_or_online_alter_table(THD
 
   DBUG_ENTER(" mysql_fast_or_online_alter_table");
   //VOID(pthread_mutex_lock(&LOCK_open));
-  if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
+  if (!table->s->tmp_table && need_lock_for_indexes &&
+      (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)))
   {
-    error= my_errno;
+    error= -1;
     goto err;
   }
   //VOID(pthread_mutex_unlock(&LOCK_open));
   thd_proc_info(thd, "manage keys");
+  DEBUG_SYNC(thd, "alter_table_manage_keys");
   alter_table_manage_keys(table, table->file->indexes_are_disabled(),
                           keys_onoff);
   error= trans_commit_stmt(thd);
@@ -6074,6 +6080,24 @@ int mysql_fast_or_online_alter_table(THD
        if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
        we need to wrap the next call with a DDL lock.
      */
+
+
+    /*
+      Wait for users of the table before continuing with next phase
+     */
+    if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
+    {
+      if ((error= table->file->alter_table_abort(thd,
+                                                 alter_info,
+                                                 ha_alter_flags)))
+      {
+        goto err;
+      }
+
+      error= my_errno;
+      goto err;
+    }
+
     if ((error= table->file->alter_table_phase2(thd,
                                                 altered_table,
                                                 create_info,
@@ -6088,11 +6112,6 @@ int mysql_fast_or_online_alter_table(THD
     and will be renamed to the original table name.
   */
   //VOID(pthread_mutex_lock(&LOCK_open));
-  if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
-  {
-    error= my_errno;
-    goto err;
-  }
 
   strcpy(table_name, altered_table->s->table_name.str);
   strcpy(db, altered_table->s->db.str);
@@ -7428,7 +7447,8 @@ bool mysql_alter_table(THD *thd,char *ne
     {
       char dbug_string[HA_MAX_ALTER_FLAGS+1];
       ha_alter_flags.print(dbug_string);
-      DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags:  %s",
+      DBUG_PRINT("info", ("change_level: %u, need_copy_table: %u, table_changes: %u, Real alter_flags:  %s",
+                          alter_info->change_level,
                           need_copy_table, table_changes,
                           (char *) dbug_string));
     }
@@ -7471,10 +7491,11 @@ bool mysql_alter_table(THD *thd,char *ne
       alter_info->create_list= create_list_orig;
       alter_info->alter_list= alter_list_orig;
       alter_info->key_list= key_list_orig;
-
+      ha_alter_info.data= alter_info;
+      
       alter_supported= (table->file->check_if_supported_alter(altered_table,
                                                               create_info,
-                                                              alter_info,
+                                                              &ha_alter_info,
                                                               &ha_alter_flags,
                                                               table_changes));
       
@@ -7485,7 +7506,12 @@ bool mysql_alter_table(THD *thd,char *ne
       alter_info->key_list= key_list;
       switch (alter_supported) {
       case HA_ALTER_SUPPORTED_WAIT_LOCK:
+        DBUG_PRINT("info", ("check_if_supported_alter: HA_ALTER_SUPPORTED_WAIT_LOCK"));
+        need_copy_table= FALSE;
+        need_lock_for_indexes= TRUE;
+        break;
       case HA_ALTER_SUPPORTED_NO_LOCK:
+        DBUG_PRINT("info", ("check_if_supported_alter: HA_ALTER_SUPPORTED_NO_LOCK"));
         /*
           @todo: Currently we always acquire an exclusive name
           lock on the table metadata when performing fast or online
@@ -7496,10 +7522,12 @@ bool mysql_alter_table(THD *thd,char *ne
           already now.
         */
         need_copy_table= FALSE;
-        if (alter_info->change_level == ALTER_TABLE_METADATA_ONLY)
-          need_lock_for_indexes= FALSE;
+        need_lock_for_indexes= FALSE;
         break;
       case HA_ALTER_NOT_SUPPORTED:
+        DBUG_PRINT("info", ("check_if_supported_alter: HA_ALTER_NOT_SUPPORTED"));
+        need_copy_table= TRUE;
+        need_lock_for_indexes= FALSE;
         if (alter_info->build_method == HA_BUILD_ONLINE)
         {
           my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query());
@@ -7512,6 +7540,7 @@ bool mysql_alter_table(THD *thd,char *ne
         need_copy_table= TRUE;
         break;
       case HA_ALTER_ERROR:
+        DBUG_PRINT("info", ("check_if_supported_alter: HA_ALTER_ERROR"));
       default:
 #ifdef WITH_PARTITION_STORAGE_ENGINE
         altered_table->part_info= NULL;;
@@ -7536,6 +7565,9 @@ bool mysql_alter_table(THD *thd,char *ne
 
     if (!need_copy_table)
     {
+      if (alter_info->keys_onoff != LEAVE_AS_IS ||
+          table->file->indexes_are_disabled())
+        need_lock_for_indexes= true;
       error= mysql_fast_or_online_alter_table(thd,
                                               table,
                                               altered_table,
@@ -7543,6 +7575,7 @@ bool mysql_alter_table(THD *thd,char *ne
                                               &ha_alter_info,
                                               &ha_alter_flags,
                                               alter_info->keys_onoff,
+                                              need_lock_for_indexes,
                                               &target_mdl_request);
       if (thd->lock)
       {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-cluster branch (Martin.Skold:3469 to 3470) Martin Skold9 Sep