Commit fac3642c authored by unknown's avatar unknown

InnoDB: ignore intra-database foreign key references between tables

when dropping database (Bug #3058)


innobase/dict/dict0crea.c:
  Add a parameter to row_drop_table_for_mysql()
innobase/dict/dict0dict.c:
  Make dict_tables_have_same_db() a global function
innobase/include/dict0dict.h:
  Make dict_tables_have_same_db() a global function
innobase/include/row0mysql.h:
  Add a parameter to row_drop_table_for_mysql()
innobase/row/row0mysql.c:
  Add a parameter "drop_db" to row_drop_table_for_mysql()
  to skip foreign constraint checks on tables in same database
innobase/trx/trx0roll.c:
  Add a parameter to row_drop_table_for_mysql()
sql/ha_innodb.cc:
  Add a parameter "drop_db" to row_drop_table_for_mysql()
  innobase_drop_database(): allocate namebuf dynamically
parent ca68cb66
...@@ -999,13 +999,13 @@ dict_create_or_check_foreign_constraint_tables(void) ...@@ -999,13 +999,13 @@ dict_create_or_check_foreign_constraint_tables(void)
if (table1) { if (table1) {
fprintf(stderr, fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n"); "InnoDB: dropping incompletely created SYS_FOREIGN table\n");
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx); row_drop_table_for_mysql((char*)"SYS_FOREIGN", trx, TRUE);
} }
if (table2) { if (table2) {
fprintf(stderr, fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n"); "InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx); row_drop_table_for_mysql((char*)"SYS_FOREIGN_COLS", trx, TRUE);
} }
fprintf(stderr, fprintf(stderr,
...@@ -1054,8 +1054,8 @@ dict_create_or_check_foreign_constraint_tables(void) ...@@ -1054,8 +1054,8 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr, fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n"); "InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx); row_drop_table_for_mysql((char*)"SYS_FOREIGN", trx, TRUE);
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx); row_drop_table_for_mysql((char*)"SYS_FOREIGN_COLS", trx, TRUE);
error = DB_MUST_GET_MORE_FILE_SPACE; error = DB_MUST_GET_MORE_FILE_SPACE;
} }
......
...@@ -177,7 +177,7 @@ mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign ...@@ -177,7 +177,7 @@ mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign
/************************************************************************ /************************************************************************
Checks if the database name in two table names is the same. */ Checks if the database name in two table names is the same. */
static
ibool ibool
dict_tables_have_same_db( dict_tables_have_same_db(
/*=====================*/ /*=====================*/
......
...@@ -834,6 +834,17 @@ Releases the dictionary system mutex for MySQL. */ ...@@ -834,6 +834,17 @@ Releases the dictionary system mutex for MySQL. */
void void
dict_mutex_exit_for_mysql(void); dict_mutex_exit_for_mysql(void);
/*===========================*/ /*===========================*/
/************************************************************************
Checks if the database name in two table names is the same. */
ibool
dict_tables_have_same_db(
/*=====================*/
/* out: TRUE if same db name */
const char* name1, /* in: table name in the form
dbname '/' tablename */
const char* name2); /* in: table name in the form
dbname '/' tablename */
/* The following len must be at least 10000 bytes! */ /* The following len must be at least 10000 bytes! */
#define DICT_FOREIGN_ERR_BUF_LEN 10000 #define DICT_FOREIGN_ERR_BUF_LEN 10000
......
...@@ -329,7 +329,8 @@ row_drop_table_for_mysql( ...@@ -329,7 +329,8 @@ row_drop_table_for_mysql(
/*=====================*/ /*=====================*/
/* out: error code or DB_SUCCESS */ /* out: error code or DB_SUCCESS */
char* name, /* in: table name */ char* name, /* in: table name */
trx_t* trx); /* in: transaction handle */ trx_t* trx, /* in: transaction handle */
ibool drop_db);/* in: TRUE=dropping whole database */
/************************************************************************* /*************************************************************************
Drops a database for MySQL. */ Drops a database for MySQL. */
......
...@@ -1427,7 +1427,7 @@ row_create_table_for_mysql( ...@@ -1427,7 +1427,7 @@ row_create_table_for_mysql(
fprintf(stderr, fprintf(stderr,
"InnoDB: Warning: cannot create table %s because tablespace full\n", "InnoDB: Warning: cannot create table %s because tablespace full\n",
table->name); table->name);
row_drop_table_for_mysql(table->name, trx); row_drop_table_for_mysql(table->name, trx, FALSE);
} else { } else {
ut_a(err == DB_DUPLICATE_KEY); ut_a(err == DB_DUPLICATE_KEY);
...@@ -1542,7 +1542,7 @@ error_handling: ...@@ -1542,7 +1542,7 @@ error_handling:
trx_general_rollback_for_mysql(trx, FALSE, NULL); trx_general_rollback_for_mysql(trx, FALSE, NULL);
row_drop_table_for_mysql(index->table_name, trx); row_drop_table_for_mysql(index->table_name, trx, FALSE);
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
} }
...@@ -1607,7 +1607,7 @@ row_table_add_foreign_constraints( ...@@ -1607,7 +1607,7 @@ row_table_add_foreign_constraints(
trx_general_rollback_for_mysql(trx, FALSE, NULL); trx_general_rollback_for_mysql(trx, FALSE, NULL);
row_drop_table_for_mysql(name, trx); row_drop_table_for_mysql(name, trx, FALSE);
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
} }
...@@ -1638,7 +1638,7 @@ row_drop_table_for_mysql_in_background( ...@@ -1638,7 +1638,7 @@ row_drop_table_for_mysql_in_background(
name); */ name); */
/* Drop the table in InnoDB */ /* Drop the table in InnoDB */
error = row_drop_table_for_mysql(name, trx); error = row_drop_table_for_mysql(name, trx, FALSE);
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
fprintf(stderr, fprintf(stderr,
...@@ -1797,7 +1797,8 @@ row_drop_table_for_mysql( ...@@ -1797,7 +1797,8 @@ row_drop_table_for_mysql(
/*=====================*/ /*=====================*/
/* out: error code or DB_SUCCESS */ /* out: error code or DB_SUCCESS */
char* name, /* in: table name */ char* name, /* in: table name */
trx_t* trx) /* in: transaction handle */ trx_t* trx, /* in: transaction handle */
ibool drop_db)/* in: TRUE=dropping whole database */
{ {
dict_foreign_t* foreign; dict_foreign_t* foreign;
dict_table_t* table; dict_table_t* table;
...@@ -1981,7 +1982,9 @@ row_drop_table_for_mysql( ...@@ -1981,7 +1982,9 @@ row_drop_table_for_mysql(
foreign = UT_LIST_GET_NEXT(referenced_list, foreign); foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
} }
if (foreign && trx->check_foreigns) { if (foreign && trx->check_foreigns &&
!(drop_db && dict_tables_have_same_db(
name, foreign->foreign_table_name))) {
char* buf = dict_foreign_err_buf; char* buf = dict_foreign_err_buf;
/* We only allow dropping a referenced table if /* We only allow dropping a referenced table if
...@@ -2112,7 +2115,6 @@ loop: ...@@ -2112,7 +2115,6 @@ loop:
ut_a(strcmp(table_name, name) == 0); ut_a(strcmp(table_name, name) == 0);
table = dict_table_get_low(table_name); table = dict_table_get_low(table_name);
fprintf(stderr, "drop %p:%s\n", table, table_name);
ut_a(table); ut_a(table);
...@@ -2135,7 +2137,7 @@ fprintf(stderr, "drop %p:%s\n", table, table_name); ...@@ -2135,7 +2137,7 @@ fprintf(stderr, "drop %p:%s\n", table, table_name);
goto loop; goto loop;
} }
err = row_drop_table_for_mysql(table_name, trx); err = row_drop_table_for_mysql(table_name, trx, TRUE);
mem_free(table_name); mem_free(table_name);
......
...@@ -469,7 +469,7 @@ loop: ...@@ -469,7 +469,7 @@ loop:
fprintf(stderr, fprintf(stderr,
"InnoDB: Table found: dropping table %s in recovery\n", table->name); "InnoDB: Table found: dropping table %s in recovery\n", table->name);
err = row_drop_table_for_mysql(table->name, trx); err = row_drop_table_for_mysql(table->name, trx, TRUE);
ut_a(err == (int) DB_SUCCESS); ut_a(err == (int) DB_SUCCESS);
} }
......
...@@ -3631,7 +3631,8 @@ ha_innobase::delete_table( ...@@ -3631,7 +3631,8 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */ /* Drop the table in InnoDB */
error = row_drop_table_for_mysql(norm_name, trx); error = row_drop_table_for_mysql(norm_name, trx,
thd->lex.sql_command == SQLCOM_DROP_DB);
/* Flush the log to reduce probability that the .frm files and /* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs the InnoDB data dictionary get out-of-sync if the user runs
...@@ -3670,7 +3671,7 @@ innobase_drop_database( ...@@ -3670,7 +3671,7 @@ innobase_drop_database(
trx_t* trx; trx_t* trx;
char* ptr; char* ptr;
int error; int error;
char namebuf[10000]; char* namebuf;
/* Get the transaction associated with the current thd, or create one /* Get the transaction associated with the current thd, or create one
if not yet created */ if not yet created */
...@@ -3690,6 +3691,7 @@ innobase_drop_database( ...@@ -3690,6 +3691,7 @@ innobase_drop_database(
} }
ptr++; ptr++;
namebuf = my_malloc(len + 2, MYF(0));
memcpy(namebuf, ptr, len); memcpy(namebuf, ptr, len);
namebuf[len] = '/'; namebuf[len] = '/';
...@@ -3706,6 +3708,7 @@ innobase_drop_database( ...@@ -3706,6 +3708,7 @@ innobase_drop_database(
} }
error = row_drop_database_for_mysql(namebuf, trx); error = row_drop_database_for_mysql(namebuf, trx);
my_free(namebuf, MYF(0));
/* Flush the log to reduce probability that the .frm files and /* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs the InnoDB data dictionary get out-of-sync if the user runs
......
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