summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2016-06-22 22:37:28 +0300
committerJan Lindström <jan.lindstrom@mariadb.com>2016-06-23 06:46:05 +0300
commitef92aaf9ece92c873ae0f3448ab2274c958ba3fe (patch)
tree0a66b9df3d0d723610d97978066684716e30578f /storage/innobase
parenta482e76e65a4fee70479e877929381c86b1ec62f (diff)
downloadmariadb-git-ef92aaf9ece92c873ae0f3448ab2274c958ba3fe.tar.gz
MDEV-10083: Orphan ibd file when playing with foreign keys
Analysis: row_drop_table_for_mysql did not allow dropping referenced table even in case when actual creating of the referenced table was not successfull if foreign_key_checks=1. Fix: Allow dropping referenced table even if foreign_key_checks=1 if actual table create returned error.
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/dict/dict0crea.c8
-rw-r--r--storage/innobase/handler/ha_innodb.cc3
-rw-r--r--storage/innobase/include/row0mysql.h5
-rw-r--r--storage/innobase/row/row0merge.c2
-rw-r--r--storage/innobase/row/row0mysql.c23
-rw-r--r--storage/innobase/trx/trx0roll.c2
6 files changed, 27 insertions, 16 deletions
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index 8102f570175..f8bcc6f2d5f 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/dict/dict0crea.c
@@ -1242,14 +1242,14 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created"
" SYS_FOREIGN table\n");
- row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created"
" SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE);
}
fprintf(stderr,
@@ -1298,8 +1298,8 @@ dict_create_or_check_foreign_constraint_tables(void)
"InnoDB: dropping incompletely created"
" SYS_FOREIGN tables\n");
- row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE);
+ row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 734dbe1cafd..780f3a6f82f 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7644,7 +7644,8 @@ ha_innobase::delete_table(
error = row_drop_table_for_mysql(norm_name, trx,
thd_sql_command(thd)
- == SQLCOM_DROP_DB);
+ == SQLCOM_DROP_DB,
+ FALSE);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 7abb0b67fff..0f66644d906 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -454,7 +454,10 @@ row_drop_table_for_mysql(
/*=====================*/
const char* name, /*!< in: table name */
trx_t* trx, /*!< in: transaction handle */
- ibool drop_db);/*!< in: TRUE=dropping whole database */
+ ibool drop_db,/*!< in: TRUE=dropping whole database */
+ ibool create_failed);/*!<in: TRUE=create table failed
+ because e.g. foreign key column
+ type mismatch. */
/*********************************************************************//**
Drop all temporary tables during crash recovery. */
UNIV_INTERN
diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
index f7d546c84c8..7d87d1f9c8f 100644
--- a/storage/innobase/row/row0merge.c
+++ b/storage/innobase/row/row0merge.c
@@ -2685,7 +2685,7 @@ row_merge_drop_table(
/* There must be no open transactions on the table. */
ut_a(table->n_mysql_handles_opened == 0);
- return(row_drop_table_for_mysql(table->name, trx, FALSE));
+ return(row_drop_table_for_mysql(table->name, trx, FALSE, FALSE));
}
/*********************************************************************//**
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 1a11e398959..6206bef6b56 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -1987,7 +1987,7 @@ err_exit:
if (dict_table_get_low(table->name, DICT_ERR_IGNORE_NONE)) {
- row_drop_table_for_mysql(table->name, trx, FALSE);
+ row_drop_table_for_mysql(table->name, trx, FALSE, TRUE);
trx_commit_for_mysql(trx);
} else {
dict_mem_table_free(table);
@@ -2117,7 +2117,7 @@ error_handling:
trx_general_rollback_for_mysql(trx, NULL);
- row_drop_table_for_mysql(table_name, trx, FALSE);
+ row_drop_table_for_mysql(table_name, trx, FALSE, TRUE);
trx_commit_for_mysql(trx);
@@ -2187,7 +2187,7 @@ row_table_add_foreign_constraints(
trx_general_rollback_for_mysql(trx, NULL);
- row_drop_table_for_mysql(name, trx, FALSE);
+ row_drop_table_for_mysql(name, trx, FALSE, TRUE);
trx_commit_for_mysql(trx);
@@ -2228,7 +2228,7 @@ row_drop_table_for_mysql_in_background(
/* Try to drop the table in InnoDB */
- error = row_drop_table_for_mysql(name, trx, FALSE);
+ error = row_drop_table_for_mysql(name, trx, FALSE, FALSE);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3078,7 +3078,10 @@ row_drop_table_for_mysql(
/*=====================*/
const char* name, /*!< in: table name */
trx_t* trx, /*!< in: transaction handle */
- ibool drop_db)/*!< in: TRUE=dropping whole database */
+ ibool drop_db,/*!< in: TRUE=dropping whole database */
+ ibool create_failed) /*!<in: TRUE=create table failed
+ because e.g. foreign key column
+ type mismatch. */
{
dict_foreign_t* foreign;
dict_table_t* table;
@@ -3193,7 +3196,11 @@ check_next_foreign:
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
- if (foreign && trx->check_foreigns
+ /* We should allow dropping a referenced table if creating
+ that referenced table has failed for some reason. For example
+ if referenced table is created but it column types that are
+ referenced do not match. */
+ if (foreign && trx->check_foreigns && !create_failed
&& !(drop_db && dict_tables_have_same_db(
name, foreign->foreign_table_name_lookup))) {
FILE* ef = dict_foreign_err_file;
@@ -3578,7 +3585,7 @@ row_mysql_drop_temp_tables(void)
table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
if (table) {
- row_drop_table_for_mysql(table_name, trx, FALSE);
+ row_drop_table_for_mysql(table_name, trx, FALSE, FALSE);
trx_commit_for_mysql(trx);
}
@@ -3708,7 +3715,7 @@ loop:
goto loop;
}
- err = row_drop_table_for_mysql(table_name, trx, TRUE);
+ err = row_drop_table_for_mysql(table_name, trx, TRUE, FALSE);
trx_commit_for_mysql(trx);
if (err != DB_SUCCESS) {
diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c
index ffd7bb3d146..877a478e50a 100644
--- a/storage/innobase/trx/trx0roll.c
+++ b/storage/innobase/trx/trx0roll.c
@@ -504,7 +504,7 @@ trx_rollback_active(
ut_print_name(stderr, trx, TRUE, table->name);
fputs(" in recovery\n", stderr);
- err = row_drop_table_for_mysql(table->name, trx, TRUE);
+ err = row_drop_table_for_mysql(table->name, trx, TRUE, FALSE);
trx_commit_for_mysql(trx);
ut_a(err == (int) DB_SUCCESS);