diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2018-09-06 22:45:19 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2018-09-06 22:45:19 +0200 |
commit | 31081593aabb116b6d8f86b6c7e76126edb392b4 (patch) | |
tree | 767a069f255359b5ea37e7c491dfeacf6e519fad /sql/sql_table.cc | |
parent | b0026e33af8fc3b25a42099c096a84591fd550e2 (diff) | |
parent | 3a4242fd57b3a2235d2478ed080941b67a82ad1b (diff) | |
download | mariadb-git-31081593aabb116b6d8f86b6c7e76126edb392b4.tar.gz |
Merge branch '11.0' into 10.1
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dc55754ff01..da65f168d84 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3316,6 +3316,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } } + /* Virtual fields are always NULL */ + if (sql_field->vcol_info) + sql_field->flags&= ~NOT_NULL_FLAG; + if (sql_field->sql_type == MYSQL_TYPE_SET || sql_field->sql_type == MYSQL_TYPE_ENUM) { @@ -9129,8 +9133,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, alter_ctx.tmp_name, strlen(alter_ctx.tmp_name), alter_ctx.tmp_name, TL_READ_NO_INSERT); /* Table is in thd->temporary_tables */ - (void) open_temporary_table(thd, &tbl); + if (open_temporary_table(thd, &tbl)) + goto err_new_table_cleanup; new_table= tbl.table; + DBUG_ASSERT(new_table); } else { @@ -9140,9 +9146,59 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, alter_ctx.get_tmp_path(), alter_ctx.new_db, alter_ctx.tmp_name, true, true); + if (!new_table) + goto err_new_table_cleanup; + + /* + Normally, an attempt to modify an FK parent table will cause + FK children to be prelocked, so the table-being-altered cannot + be modified by a cascade FK action, because ALTER holds a lock + and prelocking will wait. + + But if a new FK is being added by this very ALTER, then the target + table is not locked yet (it's a temporary table). So, we have to + lock FK parents explicitly. + */ + if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY) + { + List <FOREIGN_KEY_INFO> fk_list; + List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list); + FOREIGN_KEY_INFO *fk; + + /* tables_opened can be > 1 only for MERGE tables */ + DBUG_ASSERT(tables_opened == 1); + DBUG_ASSERT(&table_list->next_global == thd->lex->query_tables_last); + + new_table->file->get_foreign_key_list(thd, &fk_list); + while ((fk= fk_list_it++)) + { + if (lower_case_table_names) + { + char buf[NAME_LEN]; + uint len; + strmake_buf(buf, fk->referenced_db->str); + len = my_casedn_str(files_charset_info, buf); + thd->make_lex_string(fk->referenced_db, buf, len); + strmake_buf(buf, fk->referenced_table->str); + len = my_casedn_str(files_charset_info, buf); + thd->make_lex_string(fk->referenced_table, buf, len); + } + if (table_already_fk_prelocked(table_list, fk->referenced_db, + fk->referenced_table, TL_READ_NO_INSERT)) + continue; + + TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST)); + tl->init_one_table_for_prelocking(fk->referenced_db->str, fk->referenced_db->length, + fk->referenced_table->str, fk->referenced_table->length, + NULL, TL_READ_NO_INSERT, false, NULL, 0, + &thd->lex->query_tables_last); + } + + if (open_tables(thd, &table_list->next_global, &tables_opened, 0, + &alter_prelocking_strategy)) + goto err_new_table_cleanup; + } } - if (!new_table) - goto err_new_table_cleanup; /* Note: In case of MERGE table, we do not attach children. We do not copy data for MERGE tables. Only the children have data. |