11/*
22 Copyright (c) 2000, 2016, Oracle and/or its affiliates.
3- Copyright (c) 2010, 2018 , MariaDB
3+ Copyright (c) 2010, 2019 , MariaDB
44
55 This program is free software; you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published by
@@ -8504,6 +8504,50 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
85048504 }
85058505 }
85068506
8507+ /*
8508+ Normally, an attempt to modify an FK parent table will cause
8509+ FK children to be prelocked, so the table-being-altered cannot
8510+ be modified by a cascade FK action, because ALTER holds a lock
8511+ and prelocking will wait.
8512+
8513+ But if a new FK is being added by this very ALTER, then the target
8514+ table is not locked yet (it's a temporary table). So, we have to
8515+ lock FK parents explicitly.
8516+ */
8517+ if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY)
8518+ {
8519+ List_iterator<Key> fk_list_it (alter_info->key_list );
8520+
8521+ while (Key *key= fk_list_it++)
8522+ {
8523+ if (key->type != Key::FOREIGN_KEY)
8524+ continue ;
8525+
8526+ Foreign_key *fk= static_cast <Foreign_key*>(key);
8527+ char dbuf[NAME_LEN];
8528+ char tbuf[NAME_LEN];
8529+ const char *ref_db= fk->ref_db .str ? fk->ref_db .str : alter_ctx->new_db ;
8530+ const char *ref_table= fk->ref_table .str ;
8531+ MDL_request mdl_request;
8532+
8533+ if (lower_case_table_names)
8534+ {
8535+ strmake_buf (dbuf, ref_db);
8536+ my_casedn_str (system_charset_info, dbuf);
8537+ strmake_buf (tbuf, ref_table);
8538+ my_casedn_str (system_charset_info, tbuf);
8539+ ref_db= dbuf;
8540+ ref_table= tbuf;
8541+ }
8542+
8543+ mdl_request.init (MDL_key::TABLE, ref_db, ref_table, MDL_SHARED_NO_WRITE,
8544+ MDL_TRANSACTION);
8545+ if (thd->mdl_context .acquire_lock (&mdl_request,
8546+ thd->variables .lock_wait_timeout ))
8547+ DBUG_RETURN (true );
8548+ }
8549+ }
8550+
85078551 DBUG_RETURN (false );
85088552}
85098553
@@ -9504,6 +9548,7 @@ do_continue:;
95049548
95059549 /* Mark that we have created table in storage engine. */
95069550 no_ha_table= false ;
9551+ DEBUG_SYNC (thd, " alter_table_intermediate_table_created" );
95079552
95089553 new_table=
95099554 thd->create_and_open_tmp_table (new_db_type, &frm, alter_ctx.get_tmp_path (),
@@ -9517,54 +9562,6 @@ do_continue:;
95179562 /* in case of alter temp table send the tracker in OK packet */
95189563 SESSION_TRACKER_CHANGED (thd, SESSION_STATE_CHANGE_TRACKER, NULL );
95199564 }
9520- else
9521- {
9522- /*
9523- Normally, an attempt to modify an FK parent table will cause
9524- FK children to be prelocked, so the table-being-altered cannot
9525- be modified by a cascade FK action, because ALTER holds a lock
9526- and prelocking will wait.
9527-
9528- But if a new FK is being added by this very ALTER, then the target
9529- table is not locked yet (it's a temporary table). So, we have to
9530- lock FK parents explicitly.
9531- */
9532- if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY)
9533- {
9534- List <FOREIGN_KEY_INFO> fk_list;
9535- List_iterator<FOREIGN_KEY_INFO> fk_list_it (fk_list);
9536- FOREIGN_KEY_INFO *fk;
9537-
9538- /* tables_opened can be > 1 only for MERGE tables */
9539- DBUG_ASSERT (tables_opened == 1 );
9540- DBUG_ASSERT (&table_list->next_global == thd->lex ->query_tables_last );
9541-
9542- new_table->file ->get_foreign_key_list (thd, &fk_list);
9543- while ((fk= fk_list_it++))
9544- {
9545- MDL_request mdl_request;
9546-
9547- if (lower_case_table_names)
9548- {
9549- char buf[NAME_LEN];
9550- uint len;
9551- strmake_buf (buf, fk->referenced_db ->str );
9552- len = my_casedn_str (files_charset_info, buf);
9553- thd->make_lex_string (fk->referenced_db , buf, len);
9554- strmake_buf (buf, fk->referenced_table ->str );
9555- len = my_casedn_str (files_charset_info, buf);
9556- thd->make_lex_string (fk->referenced_table , buf, len);
9557- }
9558-
9559- mdl_request.init (MDL_key::TABLE,
9560- fk->referenced_db ->str , fk->referenced_table ->str ,
9561- MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
9562- if (thd->mdl_context .acquire_lock (&mdl_request,
9563- thd->variables .lock_wait_timeout ))
9564- goto err_new_table_cleanup;
9565- }
9566- }
9567- }
95689565
95699566 /*
95709567 Note: In case of MERGE table, we do not attach children. We do not
0 commit comments