From: magnus.blaudd Date: October 3 2011 7:13am Subject: bzr push into mysql-trunk-cluster branch (magnus.blaudd:3372 to 3373) List-Archive: http://lists.mysql.com/commits/141270 Message-Id: <201110030713.p937DUZ8020705@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3373 magnus.blaudd@stripped 2011-10-03 [merge] Merge -r 3470 5.5-cluster->trunk-cluster 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 3372 Frazer Clement 2011-09-30 [merge] Merge mysql-5.5-cluster -> mysql-trunk-cluster Includes NDB$EPOCH_TRANS + Binlog events v1.1 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/binlog.cc 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/rpl_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-07 10:08:09 +0000 +++ b/mysql-test/t/disabled.def 2011-10-03 07:11:46 +0000 @@ -17,5 +17,3 @@ create-big : Bug#11748731 archive-big : Bug#11817185 2011-03-10 Anitha Disabled since this leads to timeout on Solaris Sparc 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-30 15:38:44 +0000 +++ b/sql/ha_ndbcluster.cc 2011-10-03 07:11:46 +0000 @@ -16298,7 +16298,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) { @@ -16984,6 +16984,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-30 15:38:44 +0000 +++ b/sql/ha_ndbcluster.h 2011-10-03 07:11:46 +0000 @@ -517,7 +517,7 @@ static void set_tabname(const char *path #ifndef NDB_WITHOUT_ONLINE_ALTER 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); @@ -537,6 +537,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-28 08:56:16 +0000 +++ b/sql/handler.cc 2011-10-03 07:11:46 +0000 @@ -3757,13 +3757,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 | @@ -3785,7 +3791,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]; @@ -3798,17 +3804,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); @@ -3819,85 +3820,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); } @@ -3919,7 +4096,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()) @@ -3956,6 +4133,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); } /* @@ -3976,12 +4154,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; @@ -4016,22 +4193,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); } } @@ -4048,6 +4232,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-28 18:53:09 +0000 +++ b/sql/handler.h 2011-10-03 07:11:46 +0000 @@ -1015,6 +1015,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; @@ -2371,7 +2372,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); @@ -2436,6 +2437,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-09-23 10:44:30 +0000 +++ b/sql/sql_table.cc 2011-10-03 07:11:46 +0000 @@ -5707,6 +5707,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]; @@ -6292,6 +6295,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; @@ -6309,13 +6313,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); @@ -6349,6 +6355,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, @@ -6363,11 +6387,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); @@ -7752,7 +7771,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)); } @@ -7795,10 +7815,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)); @@ -7809,7 +7830,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 @@ -7820,10 +7846,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()); @@ -7836,6 +7864,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;; @@ -7860,6 +7889,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, @@ -7867,6 +7899,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).