From 74543698a76c02d1a81e17e5918ecbf6b795607b Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 5 Aug 2017 19:26:10 +0300 Subject: MDEV-13179 main.errors fails with wrong errno The problem was that the introduction of max-thread-mem-used can cause an allocation error very early, even before mysql_parse() is called. As mysql_parse() calls thd->reset_for_next_command(), which called clear_error(), the error number was lost. Fixed by adding an option to have unique messages for each KILL signal and change max-thread-mem-used to use this new feature. This removes a lot of problems with the original approach, where one could get errors signaled silenty almost any time. ixed by moving clear_error() from reset_for_next_command() to do_command(), before any memory allocation for the thread. Related changes: - reset_for_next_command() now have an optional parameter if we should call clear_error() or not. By default it's called, but not anymore from dispatch_command() which was the original problem. - Added optional paramater to clear_error() to force calling of reset_diagnostics_area(). Before clear_error() only called reset_diagnostics_area() if there was no error, so we normally called reset_diagnostics_area() twice. - This change removed several duplicated calls to clear_error() when starting a query. - Reset max_mem_used on COM_QUIT, to protect against kill during quit. - Use fatal_error() instead of setting is_fatal_error (cleanup) - Set fatal_error if max_thead_mem_used is signaled. (Same logic we use for other places where we are out of resources) --- 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 ace8ff1a7a9..29c382f57d6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4783,7 +4783,7 @@ int create_table_impl(THD *thd, thd->variables.option_bits|= OPTION_KEEP_LOG; thd->log_current_statement= 1; create_info->table_was_deleted= 1; - DBUG_EXECUTE_IF("send_kill_after_delete", thd->killed= KILL_QUERY; ); + DBUG_EXECUTE_IF("send_kill_after_delete", thd->set_killed(KILL_QUERY); ); /* Restart statement transactions for the case of CREATE ... SELECT. -- cgit v1.2.1 From 28ddc9b3bbbb56a3146779b1f0ccf42a6ef50f2b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 17:36:47 +0200 Subject: small cleanup --- sql/sql_table.cc | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5c5f2d373c7..623ed45b1d2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7615,20 +7615,18 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, while ((drop=drop_it++)) { if (drop->type == Alter_drop::COLUMN && - !my_strcasecmp(system_charset_info,field->field_name, drop->name)) - { - /* Reset auto_increment value if it was dropped */ - if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && - !(used_fields & HA_CREATE_USED_AUTO)) - { - create_info->auto_increment_value=0; - create_info->used_fields|=HA_CREATE_USED_AUTO; - } + !my_strcasecmp(system_charset_info, field->field_name, drop->name)) break; - } } if (drop) { + /* Reset auto_increment value if it was dropped */ + if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && + !(used_fields & HA_CREATE_USED_AUTO)) + { + create_info->auto_increment_value=0; + create_info->used_fields|=HA_CREATE_USED_AUTO; + } if (table->s->tmp_table == NO_TMP_TABLE) (void) delete_statistics_for_column(thd, table, field); drop_it.remove(); @@ -8975,11 +8973,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, alter_info->requested_algorithm != Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) || is_inplace_alter_impossible(table, create_info, alter_info) -#ifdef WITH_PARTITION_STORAGE_ENGINE - || (partition_changed && - !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)) -#endif - ) + || IF_PARTITIONING((partition_changed && + !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)), 0)) { if (alter_info->requested_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) -- cgit v1.2.1 From 04b288ae47dec8bd1a41902889956c4b0d711cc5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 18:52:38 +0200 Subject: MDEV-11114 Cannot drop column referenced by CHECK constraint SQL Standard behavior for DROP COLUMN xxx RESTRICT: * If a constraint (UNIQUE or CHECK) uses only the dropped column, it's automatically dropped too. If it uses many columns - an error. --- sql/sql_table.cc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 623ed45b1d2..dd425a2bbbc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7549,6 +7549,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, bool modified_primary_key= FALSE; Create_field *def; Field **f_ptr,*field; + MY_BITMAP *dropped_fields= NULL; // if it's NULL - no dropped fields DBUG_ENTER("mysql_prepare_alter_table"); /* @@ -7605,6 +7606,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, /* First collect all fields from table which isn't in drop_list */ + bitmap_clear_all(&table->tmp_set); for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++) { Alter_drop *drop; @@ -7630,6 +7632,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (table->s->tmp_table == NO_TMP_TABLE) (void) delete_statistics_for_column(thd, table, field); drop_it.remove(); + dropped_fields= &table->tmp_set; + bitmap_set_bit(dropped_fields, field->field_index); continue; } /* Check if field is changed */ @@ -7816,6 +7820,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, continue; } + const char *dropped_key_part= NULL; KEY_PART_INFO *key_part= key_info->key_part; key_parts.empty(); bool delete_index_stat= FALSE; @@ -7845,6 +7850,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (table->s->primary_key == i) modified_primary_key= TRUE; delete_index_stat= TRUE; + dropped_key_part= key_part_name; continue; // Field is removed } key_part_length= key_part->length; @@ -7927,6 +7933,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, key_type= Key::PRIMARY; else key_type= Key::UNIQUE; + if (dropped_key_part) + { + my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), dropped_key_part); + goto err; + } } else if (key_info->flags & HA_FULLTEXT) key_type= Key::FULLTEXT; @@ -7977,6 +7988,23 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, break; } } + /* see if the constraint depends on *only* on dropped fields */ + if (dropped_fields) + { + table->default_column_bitmaps(); + bitmap_clear_all(table->read_set); + check->expr->walk(&Item::register_field_in_read_map, 1, 0); + if (bitmap_is_subset(table->read_set, dropped_fields)) + drop= (Alter_drop*)1; + else if (bitmap_is_overlapping(dropped_fields, table->read_set)) + { + bitmap_intersect(table->read_set, dropped_fields); + uint field_nr= bitmap_get_first_set(table->read_set); + my_error(ER_BAD_FIELD_ERROR, MYF(0), + table->field[field_nr]->field_name, "CHECK"); + goto err; + } + } if (!drop) new_constraint_list.push_back(check, thd->mem_root); } -- cgit v1.2.1 From b2af0ddcf95ade838e67595fd09e9c4a60efbb04 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 13 Aug 2017 19:12:36 +0200 Subject: enable innodb tests for virtual indexed columns (sic!) collateral changes: * remove a test from innodb_virtual_basic that is already present in gcol_keys_innodb * set thd->abort_on_warning for inplace alter, just like it's set for copy_data_between_tables - to have warnings converted into errors identically in all alter algorithms * don't ignore errors in TABLE::update_virtual_field --- sql/sql_table.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dd425a2bbbc..1e2e7aedbd4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7179,6 +7179,7 @@ static bool mysql_inplace_alter_table(THD *thd, HA_CREATE_INFO *create_info= ha_alter_info->create_info; Alter_info *alter_info= ha_alter_info->alter_info; bool reopen_tables= false; + bool res; DBUG_ENTER("mysql_inplace_alter_table"); @@ -7313,11 +7314,12 @@ static bool mysql_inplace_alter_table(THD *thd, DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade"); THD_STAGE_INFO(thd, stage_alter_inplace); - if (table->file->ha_inplace_alter_table(altered_table, - ha_alter_info)) - { + /* We can abort alter table for any table type */ + thd->abort_on_warning= !ha_alter_info->ignore && thd->is_strict_mode(); + res= table->file->ha_inplace_alter_table(altered_table, ha_alter_info); + thd->abort_on_warning= false; + if (res) goto rollback; - } // Upgrade to EXCLUSIVE before commit. if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) -- cgit v1.2.1