diff options
author | unknown <tsmith@siva.hindu.god> | 2007-05-17 14:17:50 -0600 |
---|---|---|
committer | unknown <tsmith@siva.hindu.god> | 2007-05-17 14:17:50 -0600 |
commit | ce5f0d1bc3ced3ea987d5fcb2f64204cb5c17661 (patch) | |
tree | e1f124ea0e96bfa5ff03cb4885b9f2dde79eb0d4 /sql/sql_table.cc | |
parent | db18dc9da096bdd0adf5d8b89896d6b041ee7f30 (diff) | |
parent | 75392f37078a8e3bf3098f40c84a24c18cd91d5b (diff) | |
download | mariadb-git-ce5f0d1bc3ced3ea987d5fcb2f64204cb5c17661.tar.gz |
Merge siva.hindu.god:/home/tsmith/m/bk/50
into siva.hindu.god:/home/tsmith/m/bk/maint/50
mysql-test/r/type_datetime.result:
Auto merged
mysql-test/t/outfile.test:
Auto merged
mysql-test/t/type_datetime.test:
Auto merged
sql/field.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_func.h:
Auto merged
sql/my_decimal.h:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 88 |
1 files changed, 66 insertions, 22 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 42d59a10712..079cc0d6456 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -62,8 +62,8 @@ static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd); # Size of path */ -static uint build_table_path(char *buff, size_t bufflen, const char *db, - const char *table, const char *ext) +uint build_table_path(char *buff, size_t bufflen, const char *db, + const char *table, const char *ext) { strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext, NullS); @@ -1722,7 +1722,14 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, VOID(pthread_mutex_lock(&LOCK_open)); if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - if (!access(path,F_OK)) + /* + Inspecting table cache for placeholders created by concurrent + CREATE TABLE ... SELECT statements to avoid interfering with them + is 5.0-only solution. Starting from 5.1 we solve this problem by + obtaining name-lock on the table to be created first. + */ + if (table_cache_has_open_placeholder(thd, db, table_name) || + !access(path, F_OK)) { if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) goto warn; @@ -2051,7 +2058,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, to finish the restore in the handler later on */ pthread_mutex_lock(&LOCK_open); - if (reopen_name_locked_table(thd, table)) + if (reopen_name_locked_table(thd, table, TRUE)) { unlock_table_name(thd, table); pthread_mutex_unlock(&LOCK_open); @@ -2158,7 +2165,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, to finish the repair in the handler later on. */ pthread_mutex_lock(&LOCK_open); - if (reopen_name_locked_table(thd, table_list)) + if (reopen_name_locked_table(thd, table_list, TRUE)) { unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); @@ -2803,10 +2810,24 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, } else { + bool exists; strxmov(dst_path, mysql_data_home, "/", db, "/", table_name, reg_ext, NullS); fn_format(dst_path, dst_path, "", "", MYF(MY_UNPACK_FILENAME)); - if (!access(dst_path, F_OK)) + + /* + Note that this critical section should actually cover most + of mysql_create_like_table() function. See bugs #18950 and + #23667 for more information. + Also note that starting from 5.1 we obtain name-lock on + target table instead of inspecting table cache for presence + of open placeholders (see comment in mysql_create_table()). + */ + pthread_mutex_lock(&LOCK_open); + exists= (table_cache_has_open_placeholder(thd, db, table_name) || + !access(dst_path, F_OK)); + pthread_mutex_unlock(&LOCK_open); + if (exists) goto table_exists; } @@ -3160,9 +3181,14 @@ view_err: else { char dir_buff[FN_REFLEN]; + bool exists; strxnmov(dir_buff, FN_REFLEN, mysql_real_data_home, new_db, NullS); - if (!access(fn_format(new_name_buff,new_name_buff,dir_buff,reg_ext,0), - F_OK)) + VOID(pthread_mutex_lock(&LOCK_open)); + exists= (table_cache_has_open_placeholder(thd, new_db, new_name) || + !access(fn_format(new_name_buff, new_name_buff, dir_buff, + reg_ext, 0), F_OK)); + VOID(pthread_mutex_unlock(&LOCK_open)); + if (exists) { /* Table will be closed in do_command() */ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); @@ -3247,8 +3273,22 @@ view_err: if (!error && (new_name != table_name || new_db != db)) { thd->proc_info="rename"; - /* Then do a 'simple' rename of the table */ - if (!access(new_name_buff,F_OK)) + /* + Then do a 'simple' rename of the table. First we need to close all + instances of 'source' table. + */ + close_cached_table(thd, table); + /* + Then, we want check once again that target table does not exist. + Note that we can't fully rely on results of previous check since + no lock was taken on target table during it. We also can't do this + before calling close_cached_table() as the latter temporarily + releases LOCK_open mutex. + Also note that starting from 5.1 we use approach with obtaining + of name-lock on target table. + */ + if (table_cache_has_open_placeholder(thd, new_db, new_name) || + !access(new_name_buff,F_OK)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name); error= -1; @@ -3256,7 +3296,6 @@ view_err: else { *fn_ext(new_name)=0; - close_cached_table(thd, table); if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias)) error= -1; else if (Table_triggers_list::change_table_name(thd, db, table_name, @@ -3806,17 +3845,6 @@ view_err: current_pid, thd->thread_id); if (lower_case_table_names) my_casedn_str(files_charset_info, old_name); - if (new_name != table_name || new_db != db) - { - if (!access(new_name_buff,F_OK)) - { - error=1; - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff); - VOID(quick_rm_table(new_db_type,new_db,tmp_name)); - VOID(pthread_mutex_unlock(&LOCK_open)); - goto err; - } - } #if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2)) if (table->file->has_transactions()) @@ -3835,6 +3863,22 @@ view_err: table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore #endif + if (new_name != table_name || new_db != db) + { + /* + Check that there is no table with target name. See the + comment describing code for 'simple' ALTER TABLE ... RENAME. + */ + if (table_cache_has_open_placeholder(thd, new_db, new_name) || + !access(new_name_buff,F_OK)) + { + error=1; + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff); + VOID(quick_rm_table(new_db_type,new_db,tmp_name)); + VOID(pthread_mutex_unlock(&LOCK_open)); + goto err; + } + } error=0; if (!need_copy_table) |