diff options
author | Igor Babaev <igor@askmonty.org> | 2012-08-14 12:42:14 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-08-14 12:42:14 -0700 |
commit | 822e5da0d069e6567713464e7492097fab33e55d (patch) | |
tree | acfd13bd545ee4d5fe2209922827588be09b6e42 /sql/sql_table.cc | |
parent | 3116e3ad6164c96edc2a27c3438f325c4dc464f3 (diff) | |
parent | 7cc2f8decabe83fb304458748ba907f011848309 (diff) | |
download | mariadb-git-822e5da0d069e6567713464e7492097fab33e55d.tar.gz |
Merge 5.5->5.5-mwl248
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 129 |
1 files changed, 114 insertions, 15 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8557e0e598c..5cdfb62a047 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1956,6 +1956,49 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, /** + Find the comment in the query. + That's auxiliary function to be used handling DROP TABLE [comment]. + + @param thd Thread handler + @param comment_pos How many characters to skip before the comment. + Can be either 9 for DROP TABLE or + 17 for DROP TABLE IF EXISTS + @param comment_start returns the beginning of the comment if found. + + @retval 0 no comment found + @retval >0 the lenght of the comment found + +*/ +static uint32 comment_length(THD *thd, uint32 comment_pos, + const char **comment_start) +{ + const char *query= thd->query(); + const char *query_end= query + thd->query_length(); + const uchar *const state_map= thd->charset()->state_map; + + for (; query < query_end; query++) + { + if (state_map[*query] == MY_LEX_SKIP) + continue; + if (comment_pos-- == 0) + break; + } + if (query > query_end - 3 /* comment can't be shorter than 4 */ || + state_map[*query] != MY_LEX_LONG_COMMENT || query[1] != '*') + return 0; + + *comment_start= query; + + for (query+= 3; query < query_end; query++) + { + if (query[-1] == '*' && query[0] == '/') + return query - *comment_start + 1; + } + return 0; +} + + +/** Execute the drop of a normal or temporary table. @param thd Thread handler @@ -2030,11 +2073,20 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, { if (!drop_temporary) { + const char *comment_start; + uint32 comment_len; + built_query.set_charset(system_charset_info); if (if_exists) built_query.append("DROP TABLE IF EXISTS "); else built_query.append("DROP TABLE "); + + if ((comment_len= comment_length(thd, if_exists ? 17:9, &comment_start))) + { + built_query.append(comment_start, comment_len); + built_query.append(" "); + } } if (thd->is_current_stmt_binlog_format_row() || if_exists) @@ -6091,8 +6143,26 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } else { + MDL_request_list mdl_requests; + MDL_request target_db_mdl_request; + target_mdl_request.init(MDL_key::TABLE, new_db, new_name, MDL_EXCLUSIVE, MDL_TRANSACTION); + mdl_requests.push_front(&target_mdl_request); + + /* + If we are moving the table to a different database, we also + need IX lock on the database name so that the target database + is protected by MDL while the table is moved. + */ + if (new_db != db) + { + target_db_mdl_request.init(MDL_key::SCHEMA, new_db, "", + MDL_INTENTION_EXCLUSIVE, + MDL_TRANSACTION); + mdl_requests.push_front(&target_db_mdl_request); + } + /* Global intention exclusive lock must have been already acquired when table to be altered was open, so there is no need to do it here. @@ -6101,14 +6171,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, "", "", MDL_INTENTION_EXCLUSIVE)); - if (thd->mdl_context.try_acquire_lock(&target_mdl_request)) + if (thd->mdl_context.acquire_locks(&mdl_requests, + thd->variables.lock_wait_timeout)) DBUG_RETURN(TRUE); - if (target_mdl_request.ticket == NULL) - { - /* Table exists and is locked by some thread. */ - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); - DBUG_RETURN(TRUE); - } + DEBUG_SYNC(thd, "locked_table_name"); /* Table maybe does not exist, but we got an exclusive lock @@ -6540,11 +6606,23 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, 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. + + Also, in-place is not possible if we add a primary key + and drop another key in the same statement. If the drop fails, + we will not be able to revert adding of primary key. */ if ( pk_changed < 2 ) { - if ((alter_flags & needed_inplace_with_read_flags) == - needed_inplace_with_read_flags) + if ((needed_inplace_with_read_flags & HA_INPLACE_ADD_PK_INDEX_NO_WRITE) && + index_drop_count > 0) + { + /* + Do copy, not in-place ALTER. + Avoid setting ALTER_TABLE_METADATA_ONLY. + */ + } + else 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; @@ -6822,17 +6900,38 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, Tell the handler to prepare for drop indexes. This re-numbers the indexes to get rid of gaps. */ - if ((error= table->file->prepare_drop_index(table, key_numbers, - index_drop_count))) + error= table->file->prepare_drop_index(table, key_numbers, + index_drop_count); + if (!error) { - table->file->print_error(error, MYF(0)); - goto err_new_table_cleanup; + /* Tell the handler to finally drop the indexes. */ + error= table->file->final_drop_index(table); } - /* Tell the handler to finally drop the indexes. */ - if ((error= table->file->final_drop_index(table))) + if (error) { table->file->print_error(error, MYF(0)); + if (index_add_count) // Drop any new indexes added. + { + /* + Temporarily set table-key_info to include information about the + indexes added above that we now need to drop. + */ + KEY *save_key_info= table->key_info; + table->key_info= key_info_buffer; + if ((error= table->file->prepare_drop_index(table, index_add_buffer, + index_add_count))) + table->file->print_error(error, MYF(0)); + else if ((error= table->file->final_drop_index(table))) + table->file->print_error(error, MYF(0)); + table->key_info= save_key_info; + } + + /* + Mark this TABLE instance as stale to avoid + out-of-sync index information. + */ + table->m_needs_reopen= true; goto err_new_table_cleanup; } } |