Commit 14d00cd7 authored by Michael Widenius's avatar Michael Widenius

Fixed MDEV-6451: "Error 'Table 't1' already exists' on query" with slave_ddl_exec_mode=IDEMPOTENT

There was a race condition in lock_table_names() which didn't properly test for CREATE OR REPLACE for slaves.


sql/sql_parse.cc:
  Copy create_info flags to thd for lock_table_names()
sql/sql_table.cc:
  Copy create_info flags to thd for lock_table_names()
parent 7019d450
...@@ -2945,7 +2945,11 @@ case SQLCOM_PREPARE: ...@@ -2945,7 +2945,11 @@ case SQLCOM_PREPARE:
goto end_with_restore_list; goto end_with_restore_list;
} }
/* Copy temporarily the statement flags to thd for lock_table_names() */
uint save_thd_create_info_options= thd->lex->create_info.options;
thd->lex->create_info.options|= create_info.options;
res= open_and_lock_tables(thd, lex->query_tables, TRUE, 0); res= open_and_lock_tables(thd, lex->query_tables, TRUE, 0);
thd->lex->create_info.options= save_thd_create_info_options;
if (res) if (res)
{ {
/* Got error or warning. Set res to 1 if error */ /* Got error or warning. Set res to 1 if error */
......
...@@ -4971,7 +4971,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, ...@@ -4971,7 +4971,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
const char *db= create_table->db; const char *db= create_table->db;
const char *table_name= create_table->table_name; const char *table_name= create_table->table_name;
bool is_trans= FALSE; bool is_trans= FALSE;
bool result= 0; bool result;
int create_table_mode; int create_table_mode;
TABLE_LIST *pos_in_locked_tables= 0; TABLE_LIST *pos_in_locked_tables= 0;
MDL_ticket *mdl_ticket= 0; MDL_ticket *mdl_ticket= 0;
...@@ -4979,8 +4979,16 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, ...@@ -4979,8 +4979,16 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
DBUG_ASSERT(create_table == thd->lex->query_tables); DBUG_ASSERT(create_table == thd->lex->query_tables);
/* Copy temporarily the statement flags to thd for lock_table_names() */
uint save_thd_create_info_options= thd->lex->create_info.options;
thd->lex->create_info.options|= create_info->options;
/* Open or obtain an exclusive metadata lock on table being created */ /* Open or obtain an exclusive metadata lock on table being created */
if (open_and_lock_tables(thd, create_table, FALSE, 0)) result= open_and_lock_tables(thd, create_table, FALSE, 0);
thd->lex->create_info.options= save_thd_create_info_options;
if (result)
{ {
/* is_error() may be 0 if table existed and we generated a warning */ /* is_error() may be 0 if table existed and we generated a warning */
DBUG_RETURN(thd->is_error()); DBUG_RETURN(thd->is_error());
...@@ -5275,7 +5283,14 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -5275,7 +5283,14 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
Thus by holding both these locks we ensure that our statement is Thus by holding both these locks we ensure that our statement is
properly isolated from all concurrent operations which matter. properly isolated from all concurrent operations which matter.
*/ */
if (open_tables(thd, &thd->lex->query_tables, &not_used, 0))
/* Copy temporarily the statement flags to thd for lock_table_names() */
uint save_thd_create_info_options= thd->lex->create_info.options;
thd->lex->create_info.options|= create_info->options;
res= open_tables(thd, &thd->lex->query_tables, &not_used, 0);
thd->lex->create_info.options= save_thd_create_info_options;
if (res)
{ {
res= thd->is_error(); res= thd->is_error();
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment