From 1017889c14ec8f6d9525c659abb96c29f9634916 Mon Sep 17 00:00:00 2001 From: Zardosht Kasheff Date: Wed, 17 Apr 2013 00:02:08 -0400 Subject: [PATCH] [t:3987], merge hcr handlerton work to main git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@38554 c7de825b-a66e-492c-adef-691d508d4ae1 --- storage/tokudb/ha_tokudb.cc | 118 ++++++++++++++++++++++++++++++++--- storage/tokudb/ha_tokudb.h | 1 + storage/tokudb/hatoku_cmp.cc | 19 +++--- storage/tokudb/hatoku_cmp.h | 5 ++ 4 files changed, 128 insertions(+), 15 deletions(-) diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 1288d30b864..53ed05a4039 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -8029,7 +8029,7 @@ bool columns_have_default_null_blobs( return retval; } -bool tables_have_same_keys(TABLE* table, TABLE* altered_table, bool print_error) { +bool tables_have_same_keys(TABLE* table, TABLE* altered_table, bool print_error, bool check_field_index) { bool retval; if (table->s->keys != altered_table->s->keys) { if (print_error) { @@ -8116,7 +8116,13 @@ bool tables_have_same_keys(TABLE* table, TABLE* altered_table, bool print_error) retval = false; goto cleanup; } - if (!are_two_fields_same(curr_orig_field,curr_altered_field)) { + bool are_fields_same; + are_fields_same = (check_field_index) ? + (curr_orig_part->fieldnr == curr_altered_part->fieldnr && + fields_are_same_type(curr_orig_field, curr_altered_field)) : + (are_two_fields_same(curr_orig_field,curr_altered_field)); + + if (!are_fields_same) { if (print_error) { sql_print_error( "Key %s has different field at index %d", @@ -8144,7 +8150,7 @@ void ha_tokudb::print_alter_info( uint table_changes ) { - printf("***are keys of two tables same? %d\n", tables_have_same_keys(table,altered_table,false)); + printf("***are keys of two tables same? %d\n", tables_have_same_keys(table,altered_table,false, false)); printf("***alter flags set ***\n"); for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) { if (alter_flags->is_set(i)) { @@ -8244,22 +8250,85 @@ cleanup: return retval; } +bool column_rename_supported( + HA_ALTER_INFO* alter_info, + TABLE* orig_table, + TABLE* new_table + ) +{ + bool retval = false; + bool keys_same_for_cr; + uint num_fields_with_different_names = 0; + uint field_with_different_name = orig_table->s->fields; + if (orig_table->s->fields != new_table->s->fields) { + retval = false; + goto cleanup; + } + if (alter_info->contains_first_or_after) { + retval = false; + goto cleanup; + } + + for (uint i = 0; i < orig_table->s->fields; i++) { + Field* orig_field = orig_table->field[i]; + Field* new_field = new_table->field[i]; + if (!fields_are_same_type(orig_field, new_field)) { + retval = false; + goto cleanup; + } + if (!fields_have_same_name(orig_field, new_field)) { + num_fields_with_different_names++; + field_with_different_name = i; + } + } + // only allow one renamed field + if (num_fields_with_different_names != 1) { + retval = false; + goto cleanup; + } + assert(field_with_different_name < orig_table->s->fields); + // + // at this point, we have verified that the two tables have + // the same field types and with ONLY one field with a different name. + // We have also identified the field with the different name + // + // Now we need to check the indexes + // + keys_same_for_cr = tables_have_same_keys( + orig_table, + new_table, + false, + true + ); + if (!keys_same_for_cr) { + retval = false; + goto cleanup; + } + retval = true; +cleanup: + return retval; +} + int ha_tokudb::check_if_supported_alter(TABLE *altered_table, HA_CREATE_INFO *create_info, HA_ALTER_FLAGS *alter_flags, + HA_ALTER_INFO *alter_info, uint table_changes) { TOKUDB_DBUG_ENTER("check_if_supported_alter"); int retval; THD* thd = ha_thd(); - bool keys_same = tables_have_same_keys(table,altered_table, false); + bool keys_same = tables_have_same_keys(table,altered_table, false, false); if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) { + printf("has after or first %d\n", alter_info->contains_first_or_after); print_alter_info(altered_table, create_info, alter_flags, table_changes); } bool has_added_columns = alter_flags->is_set(HA_ADD_COLUMN); bool has_dropped_columns = alter_flags->is_set(HA_DROP_COLUMN); + bool has_column_rename = alter_flags->is_set(HA_CHANGE_COLUMN) && + alter_flags->is_set(HA_ALTER_COLUMN_NAME); // // We do not check for changes to foreign keys or primary keys. They are not supported // Changing the primary key implies changing keys in all dictionaries. that is why we don't @@ -8272,6 +8341,7 @@ int ha_tokudb::check_if_supported_alter(TABLE *altered_table, bool has_non_indexing_changes = false; bool has_non_dropped_changes = false; bool has_non_added_changes = false; + bool has_non_column_rename_changes = false; for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) { if (i == HA_DROP_INDEX || i == HA_DROP_UNIQUE_INDEX || @@ -8285,6 +8355,17 @@ int ha_tokudb::check_if_supported_alter(TABLE *altered_table, break; } } + for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) { + if (i == HA_ALTER_COLUMN_NAME|| + i == HA_CHANGE_COLUMN) + { + continue; + } + if (alter_flags->is_set(i)) { + has_non_column_rename_changes = true; + break; + } + } for (uint i = 0; i < HA_MAX_ALTER_FLAGS; i++) { if (i == HA_DROP_COLUMN) { continue; @@ -8406,6 +8487,29 @@ int ha_tokudb::check_if_supported_alter(TABLE *altered_table, else if (has_added_columns && !has_non_added_changes) { retval = HA_ALTER_SUPPORTED_WAIT_LOCK; } + else if (has_column_rename && !has_non_column_rename_changes) { + // we have identified a possible column rename, + // but let's do some more checks + + // we will only allow an hcr if there are no changes + // in column positions + if (alter_info->contains_first_or_after) { + retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED; + goto cleanup; + } + + // now need to verify that one and only one column + // has changed only its name. If we find anything to + // the contrary, we don't allow it, also check indexes + + bool cr_supported = column_rename_supported(alter_info, table, altered_table); + if (cr_supported) { + retval = HA_ALTER_SUPPORTED_WAIT_LOCK; + } + else { + retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED; + } + } else { retval = (get_disable_slow_alter(thd)) ? HA_ALTER_ERROR : HA_ALTER_NOT_SUPPORTED; } @@ -8841,8 +8945,8 @@ int ha_tokudb::alter_table_phase2( u_int32_t max_new_desc_size = 0; uchar* row_desc_buff = NULL; uchar* column_extra = NULL; - bool dropping_indexes = alter_info->index_drop_count > 0 && !tables_have_same_keys(table,altered_table,false); - bool adding_indexes = alter_info->index_add_count > 0 && !tables_have_same_keys(table,altered_table,false); + bool dropping_indexes = alter_info->index_drop_count > 0 && !tables_have_same_keys(table,altered_table,false, false); + bool adding_indexes = alter_info->index_add_count > 0 && !tables_have_same_keys(table,altered_table,false, false); tokudb_trx_data* trx = (tokudb_trx_data *) thd_data_get(thd, tokudb_hton->slot); is_fast_alter_running = true; @@ -8926,7 +9030,7 @@ int ha_tokudb::alter_table_phase2( error = HA_ERR_UNSUPPORTED; goto cleanup; } - if (!tables_have_same_keys(table, altered_table, true)) { + if (!tables_have_same_keys(table, altered_table, true, false)) { error = HA_ERR_UNSUPPORTED; goto cleanup; } diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h index 9fa681c9d4c..d109bec005b 100644 --- a/storage/tokudb/ha_tokudb.h +++ b/storage/tokudb/ha_tokudb.h @@ -567,6 +567,7 @@ public: int check_if_supported_alter(TABLE *altered_table, HA_CREATE_INFO *create_info, HA_ALTER_FLAGS *alter_flags, + HA_ALTER_INFO *alter_info, uint table_changes ); int alter_table_phase1(THD *thd, diff --git a/storage/tokudb/hatoku_cmp.cc b/storage/tokudb/hatoku_cmp.cc index 992b0b7bf1e..fb367d7401a 100644 --- a/storage/tokudb/hatoku_cmp.cc +++ b/storage/tokudb/hatoku_cmp.cc @@ -2861,9 +2861,8 @@ bool fields_have_same_name( return strcmp(a->field_name, b->field_name) == 0; } - -bool are_two_fields_same( - Field* a, +bool fields_are_same_type( + Field* a, Field* b ) { @@ -2871,11 +2870,6 @@ bool are_two_fields_same( enum_field_types a_mysql_type = a->real_type(); enum_field_types b_mysql_type = b->real_type(); // make sure have same names - if (strcmp(a->field_name, b->field_name) != 0) { - retval = false; - goto cleanup; - } - // make sure have same types if (a_mysql_type != b_mysql_type) { retval = false; @@ -2999,3 +2993,12 @@ cleanup: } +bool are_two_fields_same( + Field* a, + Field* b + ) +{ + return fields_have_same_name(a, b) && fields_are_same_type(a, b); +} + + diff --git a/storage/tokudb/hatoku_cmp.h b/storage/tokudb/hatoku_cmp.h index 66800971eaf..80953e28e59 100644 --- a/storage/tokudb/hatoku_cmp.h +++ b/storage/tokudb/hatoku_cmp.h @@ -366,6 +366,11 @@ bool fields_have_same_name( Field* b ); +bool fields_are_same_type( + Field* a, + Field* b + ); + bool are_two_fields_same( Field* a, Field* b