Commit ae73b7d8 authored by Marko Mäkelä's avatar Marko Mäkelä

Fix FOREIGN KEY error handling on DDL

dict_create_add_foreigns_to_dictionary(): Do not commit the transaction.
We want simple rollback in case dict_load_foreigns() would fail.

create_table_info_t::create_table(), row_create_index_for_mysql(),
row_table_add_foreign_constraints(): Before invoking rollback, drop
the table. Rollback would invoke trx_t::evict_table(), and after that
dropping the table would be a no-op.

ha_innobase::create(): Before rollback, drop the table. If the SQL
layer invoked ha_innobase::delete_table() later, it would be a no-op
because the rollback would have invoked trx_t::evict_table().

FIXME: Introduce an undo log record so that the data file would be
deleted on rollback. Also, avoid unnecessary access to the tablespace
during DROP TABLE or the rollback of CREATE TABLE. If the file is going
to be deleted anyway, we should not bother to mark the pages free.
parent 51bd08c8
......@@ -2233,6 +2233,8 @@ dict_create_add_foreigns_to_dictionary(
return(DB_ERROR);
}
error = DB_SUCCESS;
for (dict_foreign_set::const_iterator it = local_fk_set.begin();
it != local_fk_set.end();
++it) {
......@@ -2244,21 +2246,11 @@ dict_create_add_foreigns_to_dictionary(
table->name.m_name, foreign, trx);
if (error != DB_SUCCESS) {
return(error);
break;
}
}
trx->op_info = "committing foreign key definitions";
if (trx_is_started(trx)) {
trx_commit(trx);
}
trx->op_info = "";
return(DB_SUCCESS);
return error;
}
/****************************************************************//**
......
......@@ -12356,12 +12356,9 @@ int create_table_info_t::create_table(bool create_fk)
error = convert_error_code_to_mysql(err, 0, NULL);
if (error) {
trx_rollback_to_savepoint(m_trx, NULL);
m_trx->error_state = DB_SUCCESS;
row_drop_table_for_mysql(m_table_name, m_trx,
SQLCOM_DROP_DB);
trx_rollback_to_savepoint(m_trx, NULL);
m_trx->error_state = DB_SUCCESS;
DBUG_RETURN(error);
}
......@@ -12586,6 +12583,8 @@ ha_innobase::create(
}
if ((error = info.create_table(own_trx))) {
row_drop_table_for_mysql(norm_name, trx, SQLCOM_DROP_TABLE,
true);
trx_rollback_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx);
if (own_trx) {
......
......@@ -2606,16 +2606,10 @@ row_create_index_for_mysql(
trx->error_state = DB_SUCCESS;
if (trx_is_started(trx)) {
row_drop_table_for_mysql(table->name.m_name, trx,
SQLCOM_DROP_TABLE, true);
trx_rollback_to_savepoint(trx, NULL);
}
row_drop_table_for_mysql(table->name.m_name, trx,
SQLCOM_DROP_TABLE, true);
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
ut_ad(!trx_is_started(trx));
}
trx->error_state = DB_SUCCESS;
......@@ -2693,15 +2687,13 @@ row_table_add_foreign_constraints(
trx->error_state = DB_SUCCESS;
if (trx_is_started(trx)) {
/* FIXME: Introduce an undo log record for
creating tablespaces and data files, so that
they would be deleted on rollback. */
row_drop_table_for_mysql(name, trx, SQLCOM_DROP_TABLE,
true);
trx_rollback_to_savepoint(trx, NULL);
}
row_drop_table_for_mysql(name, trx, SQLCOM_DROP_TABLE, true);
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
ut_ad(!trx_is_started(trx));
}
trx->error_state = DB_SUCCESS;
......
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