From f195286a3eae6328a1f90948205e90201c0479c5 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 24 Aug 2018 18:08:56 +0300 Subject: MDEV-17021 Server crash or assertion `length <= column->length' failure in write_block_record Problem was that the number of NULL bit's was record wrong in the .frm file because there could be more fields marked NOT_NULL after the number of not_null fields where recorded. Fixed by copying test for virtual fields from prepare_create_field() The code change, only the test, doesn't have to be merged to 10.3 as this is fixed there. --- sql/sql_table.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9a2b4901d4e..f89a6d64fa6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3328,6 +3328,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) { -- cgit v1.2.1 From 63ad6a9e1a33ddd5547767b2894e09ae66196f69 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 2 Sep 2018 09:24:33 +0400 Subject: MDEV-15890 Strange error message if you try to FLUSH TABLES after LOCK TABLES . Check if the argument of the FLUSH TABLE is a VIEW and handle it accordingly. --- sql/sql_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5bf349b81e4..dc55754ff01 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2070,7 +2070,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, in its elements. */ table->table= find_table_for_mdl_upgrade(thd, table->db, - table->table_name, false); + table->table_name, NULL); if (!table->table) DBUG_RETURN(true); table->mdl_request.ticket= table->table->mdl_ticket; -- cgit v1.2.1 From 9180e8666b8e31239d2e2075b703fb8bc8effc13 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Jul 2018 01:03:14 +0200 Subject: MDEV-16465 Invalid (old?) table or database name or hang in ha_innobase::delete_table and log semaphore wait upon concurrent DDL with foreign keys ALTER TABLE locks the table with TL_READ_NO_INSERT, to prevent the source table modifications while it's being copied. But there's an indirect way of modifying a table, via cascade FK actions. After previous commits, 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. --- sql/sql_table.cc | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f89a6d64fa6..640c6b50fbb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9057,8 +9057,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 { @@ -9067,9 +9069,48 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, new_table= open_table_uncached(thd, new_db_type, 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 fk_list; + List_iterator 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 (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. -- cgit v1.2.1 From 0ccba62db385139caae514f70b31187bdce0de88 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 5 Sep 2018 19:47:37 +0200 Subject: MDEV-16465 Invalid (old?) table or database name or hang in ha_innobase::delete_table and log semaphore wait upon concurrent DDL with foreign keys lowercase db and table names before prelocking. Post-fix for 9180e8666b8 This fixes failures on main.lowercase_table4 on Windows --- sql/sql_table.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 640c6b50fbb..5d20ad3967c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9095,6 +9095,17 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, 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; -- cgit v1.2.1