summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorunknown <tsmith@quadxeon.mysql.com>2007-06-05 17:28:49 +0200
committerunknown <tsmith@quadxeon.mysql.com>2007-06-05 17:28:49 +0200
commitfdc8bc70375d974f6788618da00dd9cea9767e21 (patch)
treee7c3ff175d2ecad48c72ce1b883e1b4ba2fdf561 /sql/sql_table.cc
parenta998c2c8641be21cefe4e09e9413e17aad0ab896 (diff)
parent75485dc3498596b53d3e0eb04e6f4fe101996908 (diff)
downloadmariadb-git-fdc8bc70375d974f6788618da00dd9cea9767e21.tar.gz
Merge quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/50
into quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/maint/jun05/50 mysql-test/mysql-test-run.pl: Auto merged mysql-test/t/mysqltest.test: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc91
1 files changed, 42 insertions, 49 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 27d049e2d06..f850bf0c410 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2718,7 +2718,8 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
SYNOPSIS
mysql_create_like_table()
thd Thread object
- table Table list (one table only)
+ table Table list element for target table
+ src_table Table list element for source table
create_info Create info
table_ident Src table_ident
@@ -2727,61 +2728,52 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
TRUE error
*/
-bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
- HA_CREATE_INFO *create_info,
- Table_ident *table_ident)
+bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST *src_table,
+ HA_CREATE_INFO *create_info)
{
TABLE **tmp_table;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char *db= table->db;
char *table_name= table->table_name;
- char *src_db;
- char *src_table= table_ident->table.str;
int err;
bool res= TRUE;
db_type not_used;
-
- TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
- DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */
- src_db= table_ident->db.str;
/*
- Validate the source table
+ By taking name-lock on the source table and holding LOCK_open mutex we
+ ensure that no concurrent DDL operation will mess with this table. Note
+ that holding only name-lock is not enough for this, because it won't block
+ other DDL statements that only take name-locks on the table and don't
+ open it (simple name-locks are not exclusive between each other).
+
+ Unfortunately, simply opening this table is not enough for our purproses,
+ since in 5.0 ALTER TABLE may change .FRM files on disk even if there are
+ connections that still have old version of table open. This 'optimization'
+ was removed in 5.1 so there we open the source table instead of taking
+ name-lock on it.
+
+ We also have to acquire LOCK_open to make copying of .frm file, call to
+ ha_create_table() and binlogging atomic against concurrent DML and DDL
+ operations on the target table.
*/
- if (table_ident->table.length > NAME_LEN ||
- (table_ident->table.length &&
- check_table_name(src_table,table_ident->table.length)))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
- DBUG_RETURN(TRUE);
- }
- if (!src_db || check_db_name(src_db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL");
- DBUG_RETURN(-1);
- }
-
- bzero((gptr)&src_tables_list, sizeof(src_tables_list));
- src_tables_list.db= src_db;
- src_tables_list.table_name= src_table;
-
- if (lock_and_wait_for_table_name(thd, &src_tables_list))
+ if (lock_and_wait_for_table_name(thd, src_table))
goto err;
- if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
+ pthread_mutex_lock(&LOCK_open);
+
+ if ((tmp_table= find_temporary_table(thd, src_table->db,
+ src_table->table_name)))
strxmov(src_path, (*tmp_table)->s->path, reg_ext, NullS);
else
{
- strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
- reg_ext, NullS);
+ strxmov(src_path, mysql_data_home, "/", src_table->db, "/",
+ src_table->table_name, reg_ext, NullS);
/* Resolve symlinks (for windows) */
fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME));
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, src_path);
if (access(src_path, F_OK))
{
- my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table->table_name);
goto err;
}
}
@@ -2791,10 +2783,13 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
*/
if (mysql_frm_type(thd, src_path, &not_used) != FRMTYPE_TABLE)
{
- my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE");
+ my_error(ER_WRONG_OBJECT, MYF(0), src_table->db, src_table->table_name,
+ "BASE TABLE");
goto err;
}
+ DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000););
+
/*
Validate the destination table
@@ -2810,27 +2805,22 @@ 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));
/*
- 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
+ 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)
+ if (table_cache_has_open_placeholder(thd, db, table_name) ||
+ !access(dst_path, F_OK))
goto table_exists;
}
+ DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
+
/*
Create a new table by copying from source table
*/
@@ -2843,6 +2833,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
goto err;
}
+ DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000););
+
/*
As mysql_truncate don't work on a new table at this stage of
creation, instead create the table directly (for both normal
@@ -2867,6 +2859,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
goto err; /* purecov: inspected */
}
+ DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
+
// Must be written before unlock
if (mysql_bin_log.is_open())
{
@@ -2891,8 +2885,7 @@ table_exists:
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
err:
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, &src_tables_list);
+ unlock_table_name(thd, src_table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(res);
}