diff options
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 122 |
1 files changed, 96 insertions, 26 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 75d7f4c9fbf..165a82e4b27 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -37,7 +37,9 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); static int copy_data_between_tables(TABLE *from,TABLE *to, List<create_field> &create, bool ignore, uint order_num, ORDER *order, - ha_rows *copied,ha_rows *deleted); + ha_rows *copied,ha_rows *deleted, + enum enum_enable_or_disable keys_onoff); + static bool prepare_blob_field(THD *thd, create_field *sql_field); static bool check_engine(THD *thd, const char *table_name, HA_CREATE_INFO *create_info); @@ -5196,6 +5198,54 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, /* + Manages enabling/disabling of indexes for ALTER TABLE + + SYNOPSIS + alter_table_manage_keys() + table Target table + indexes_were_disabled Whether the indexes of the from table + were disabled + keys_onoff ENABLE | DISABLE | LEAVE_AS_IS + + RETURN VALUES + FALSE OK + TRUE Error +*/ + +static +bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, + enum enum_enable_or_disable keys_onoff) +{ + int error= 0; + DBUG_ENTER("alter_table_manage_keys"); + DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d", + table, indexes_were_disabled, keys_onoff)); + + switch (keys_onoff) { + case ENABLE: + error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + break; + case LEAVE_AS_IS: + if (!indexes_were_disabled) + break; + /* fall-through: disabled indexes */ + case DISABLE: + error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + } + + if (error == HA_ERR_WRONG_COMMAND) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->s->table_name); + error= 0; + } else if (error) + table->file->print_error(error, MYF(0)); + + DBUG_RETURN(error); +} + + +/* Alter table */ @@ -5443,13 +5493,35 @@ view_err: if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && !table->s->tmp_table) // no need to touch frm { - error=0; VOID(pthread_mutex_lock(&LOCK_open)); - if (new_name != table_name || new_db != db) + + switch (alter_info->keys_onoff) { + case LEAVE_AS_IS: + error= 0; + break; + case ENABLE: + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + /* COND_refresh will be signaled in close_thread_tables() */ + break; + case DISABLE: + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + /* COND_refresh will be signaled in close_thread_tables() */ + break; + } + if (error == HA_ERR_WRONG_COMMAND) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), + table->alias); + error= 0; + } + + if (!error && (new_name != table_name || new_db != db)) { thd->proc_info="rename"; /* Then do a 'simple' rename of the table */ - error=0; if (!access(new_name_buff,F_OK)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name); @@ -5472,31 +5544,14 @@ view_err: } } - if (!error) - { - switch (alter_info->keys_onoff) { - case LEAVE_AS_IS: - break; - case ENABLE: - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ - break; - case DISABLE: - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ - break; - } - } - if (error == HA_ERR_WRONG_COMMAND) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->alias); - error=0; + error= 0; } + if (!error) { write_bin_log(thd, TRUE, thd->query, thd->query_length); @@ -5509,7 +5564,7 @@ view_err: error= -1; } VOID(pthread_mutex_unlock(&LOCK_open)); - table_list->table=0; // For query cache + table_list->table= NULL; // For query cache query_cache_invalidate3(thd, table_list, 0); DBUG_RETURN(error); } @@ -6112,7 +6167,18 @@ view_err: new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->next_number_field=new_table->found_next_number_field; error=copy_data_between_tables(table, new_table, create_list, ignore, - order_num, order, &copied, &deleted); + order_num, order, &copied, &deleted, + alter_info->keys_onoff); + } + else + { + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + table->file->ha_external_lock(thd, F_WRLCK); + alter_table_manage_keys(table, table->file->indexes_are_disabled(), + alter_info->keys_onoff); + table->file->ha_external_lock(thd, F_UNLCK); + VOID(pthread_mutex_unlock(&LOCK_open)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -6529,7 +6595,8 @@ copy_data_between_tables(TABLE *from,TABLE *to, bool ignore, uint order_num, ORDER *order, ha_rows *copied, - ha_rows *deleted) + ha_rows *deleted, + enum enum_enable_or_disable keys_onoff) { int error; Copy_field *copy,*copy_end; @@ -6563,6 +6630,9 @@ copy_data_between_tables(TABLE *from,TABLE *to, if (to->file->ha_external_lock(thd, F_WRLCK)) DBUG_RETURN(-1); + /* We need external lock before we can disable/enable keys */ + alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); + /* We can abort alter table for any table type */ thd->no_trans_update= 0; thd->abort_on_warning= !ignore && test(thd->variables.sql_mode & |