summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-11-29 09:16:48 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-11-29 09:16:48 +0200
commitbe998bfdc5940925c4e6f5970a5c0c1efcd6d21e (patch)
treeda37097b62a506419285b832310ccc68434ef0a5
parentb26e603aebc0c375751cc1d08029b3fb603a0373 (diff)
downloadmariadb-git-be998bfdc5940925c4e6f5970a5c0c1efcd6d21e.tar.gz
MDEV-17859: Clean up the FOREIGN KEY handling
dict_create_add_foreigns_to_dictionary(): Do not commit the transaction. The operation can still fail in dict_load_foreigns(), and we want to be able to roll back the transaction. create_table_info_t::create_table(): Never reset m_drop_before_rollback, and never commit the transaction. We use a single point of rollback in ha_innobase::create(). Merge the logic from row_table_add_foreign_constraints().
-rw-r--r--storage/innobase/dict/dict0crea.cc9
-rw-r--r--storage/innobase/handler/ha_innodb.cc43
-rw-r--r--storage/innobase/include/row0mysql.h29
-rw-r--r--storage/innobase/row/row0mysql.cc90
4 files changed, 24 insertions, 147 deletions
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index d66762a011e..cc8c03761d8 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -2268,15 +2268,6 @@ dict_create_add_foreigns_to_dictionary(
}
}
- trx->op_info = "committing foreign key definitions";
-
- if (trx_is_started(trx)) {
-
- trx_commit(trx);
- }
-
- trx->op_info = "";
-
return(DB_SUCCESS);
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index fd970a069e3..67b0dd251af 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -12514,8 +12514,6 @@ int create_table_info_t::create_table(bool create_fk)
int primary_key_no;
uint i;
dict_table_t* innobase_table = NULL;
- const char* stmt;
- size_t stmt_len;
DBUG_ENTER("create_table");
@@ -12596,9 +12594,7 @@ int create_table_info_t::create_table(bool create_fk)
dict_table_close(innobase_table, TRUE, FALSE);
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
FTS_DOC_ID_INDEX_NAME);
- m_drop_before_rollback = false;
- error = -1;
- DBUG_RETURN(error);
+ DBUG_RETURN(-1);
case FTS_EXIST_DOC_ID_INDEX:
case FTS_NOT_EXIST_DOC_ID_INDEX:
break;
@@ -12638,15 +12634,28 @@ int create_table_info_t::create_table(bool create_fk)
dict_table_get_all_fts_indexes(innobase_table, fts->indexes);
}
- stmt = innobase_get_stmt_unsafe(m_thd, &stmt_len);
-
- if (stmt) {
- dberr_t err = row_table_add_foreign_constraints(
- create_fk ? m_trx : NULL, stmt, stmt_len, m_table_name,
- m_create_info->options & HA_LEX_CREATE_TMP_TABLE);
+ size_t stmt_len;
+ if (const char* stmt = innobase_get_stmt_unsafe(m_thd, &stmt_len)) {
+ dberr_t err = create_fk
+ ? dict_create_foreign_constraints(
+ m_trx, stmt, stmt_len, m_table_name,
+ m_flags2 & DICT_TF2_TEMPORARY)
+ : DB_SUCCESS;
+ if (err == DB_SUCCESS) {
+ /* Check that also referencing constraints are ok */
+ dict_names_t fk_tables;
+ err = dict_load_foreigns(m_table_name, NULL,
+ false, true,
+ DICT_ERR_IGNORE_NONE,
+ fk_tables);
+ while (err == DB_SUCCESS && !fk_tables.empty()) {
+ dict_load_table(fk_tables.front(), true,
+ DICT_ERR_IGNORE_NONE);
+ fk_tables.pop_front();
+ }
+ }
switch (err) {
-
case DB_PARENT_NO_INDEX:
push_warning_printf(
m_thd, Sql_condition::WARN_LEVEL_WARN,
@@ -12679,13 +12688,9 @@ int create_table_info_t::create_table(bool create_fk)
break;
}
- error = convert_error_code_to_mysql(err, m_flags, NULL);
-
- if (error) {
- /* row_table_add_foreign_constraints() dropped
- the table */
- m_drop_before_rollback = false;
- DBUG_RETURN(error);
+ if (err != DB_SUCCESS) {
+ DBUG_RETURN(convert_error_code_to_mysql(
+ err, m_flags, NULL));
}
}
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index b46d111b8bb..05b1f2e5dac 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -376,35 +376,6 @@ row_create_index_for_mysql(
large. */
MY_ATTRIBUTE((warn_unused_result));
/*********************************************************************//**
-Scans a table create SQL string and adds to the data dictionary
-the foreign key constraints declared in the string. This function
-should be called after the indexes for a table have been created.
-Each foreign key constraint must be accompanied with indexes in
-bot participating tables. The indexes are allowed to contain more
-fields than mentioned in the constraint.
-
-@param[in] trx transaction (NULL if not adding to dictionary)
-@param[in] sql_string table create statement where
- foreign keys are declared like:
- FOREIGN KEY (a, b) REFERENCES table2(c, d),
- table2 can be written also with the database
- name before it: test.table2; the default
- database id the database of parameter name
-@param[in] sql_length length of sql_string
-@param[in] name table full name in normalized form
-@param[in] reject_fks whether to fail with DB_CANNOT_ADD_CONSTRAINT
- if any foreign keys are found
-@return error code or DB_SUCCESS */
-dberr_t
-row_table_add_foreign_constraints(
- trx_t* trx,
- const char* sql_string,
- size_t sql_length,
- const char* name,
- bool reject_fks)
- MY_ATTRIBUTE((warn_unused_result));
-
-/*********************************************************************//**
The master thread in srv0srv.cc calls this regularly to drop tables which
we must drop in background after queries to them have ended. Such lazy
dropping of tables is needed in ALTER TABLE on Unix.
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index d79d544a88c..9f4b024b19f 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -2498,96 +2498,6 @@ error_handling:
}
/*********************************************************************//**
-Scans a table create SQL string and adds to the data dictionary
-the foreign key constraints declared in the string. This function
-should be called after the indexes for a table have been created.
-Each foreign key constraint must be accompanied with indexes in
-bot participating tables. The indexes are allowed to contain more
-fields than mentioned in the constraint.
-
-@param[in] trx transaction (NULL if not adding to dictionary)
-@param[in] sql_string table create statement where
- foreign keys are declared like:
- FOREIGN KEY (a, b) REFERENCES table2(c, d),
- table2 can be written also with the database
- name before it: test.table2; the default
- database id the database of parameter name
-@param[in] sql_length length of sql_string
-@param[in] name table full name in normalized form
-@param[in] reject_fks whether to fail with DB_CANNOT_ADD_CONSTRAINT
- if any foreign keys are found
-@return error code or DB_SUCCESS */
-dberr_t
-row_table_add_foreign_constraints(
- trx_t* trx,
- const char* sql_string,
- size_t sql_length,
- const char* name,
- bool reject_fks)
-{
- dberr_t err;
-
- DBUG_ENTER("row_table_add_foreign_constraints");
-
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
- ut_a(sql_string);
-
- if (trx) {
- trx->op_info = "adding foreign keys";
-
- trx_start_if_not_started_xa(trx, true);
-
- trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
-
- err = dict_create_foreign_constraints(
- trx, sql_string, sql_length, name, reject_fks);
-
- DBUG_EXECUTE_IF("ib_table_add_foreign_fail",
- err = DB_DUPLICATE_KEY;);
-
- DEBUG_SYNC_C("table_add_foreign_constraints");
- } else {
- err = DB_SUCCESS;
- }
-
- if (err == DB_SUCCESS) {
- /* Check that also referencing constraints are ok */
- dict_names_t fk_tables;
- err = dict_load_foreigns(name, NULL, false, true,
- DICT_ERR_IGNORE_NONE, fk_tables);
-
- while (err == DB_SUCCESS && !fk_tables.empty()) {
- dict_load_table(fk_tables.front(), true,
- DICT_ERR_IGNORE_NONE);
- fk_tables.pop_front();
- }
- }
-
- if (err != DB_SUCCESS && trx) {
- /* We have special error handling here */
-
- trx->error_state = DB_SUCCESS;
-
- if (trx_is_started(trx)) {
-
- 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);
- }
-
- trx->error_state = DB_SUCCESS;
- }
-
- DBUG_RETURN(err);
-}
-
-/*********************************************************************//**
Drops a table for MySQL as a background operation. MySQL relies on Unix
in ALTER TABLE to the fact that the table handler does not remove the
table before all handles to it has been removed. Furhermore, the MySQL's