diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 008384a6590..c9f181a14e8 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -7160,7 +7160,7 @@ bool subselect_single_column_match_engine::partial_match() void Item_subselect::register_as_with_rec_ref(With_element *with_elem) { - with_elem->sq_with_rec_ref.link_in_list(this, &this->next_with_rec_ref); + with_elem->sq_with_rec_ref.insert(this, &this->next_with_rec_ref); with_recursive_reference= true; } diff --git a/sql/sp.cc b/sql/sp.cc index 8a81e19e3ee..5598de585ad 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2415,7 +2415,7 @@ bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena, MDL_REQUEST_INIT_BY_KEY(&rn->mdl_request, key, MDL_SHARED, MDL_TRANSACTION); if (my_hash_insert(&prelocking_ctx->sroutines, (uchar *)rn)) return FALSE; - prelocking_ctx->sroutines_list.link_in_list(rn, &rn->next); + prelocking_ctx->sroutines_list.insert(rn, &rn->next); rn->belong_to_view= belong_to_view; rn->m_handler= handler; rn->m_sp_cache_version= 0; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 24be3c4908c..c051e37bbdd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3166,7 +3166,7 @@ int sp_head::add_instr(sp_instr *instr) if (instr_trig_fld_list) { m_cur_instr_trig_field_items.save_and_clear(instr_trig_fld_list); - m_trg_table_fields.link_in_list( + m_trg_table_fields.insert( instr_trig_fld_list, &instr_trig_fld_list->first->next_trig_field_list); } diff --git a/sql/sp_instr.cc b/sql/sp_instr.cc index be0a10bdf71..c0cce803832 100644 --- a/sql/sp_instr.cc +++ b/sql/sp_instr.cc @@ -1386,7 +1386,7 @@ bool sp_instr_set_trigger_field::on_after_expr_parsing(THD *thd) if (!val || !trigger_field) return true; - thd->spcont->m_sp->m_cur_instr_trig_field_items.link_in_list( + thd->spcont->m_sp->m_cur_instr_trig_field_items.insert( trigger_field, &trigger_field->next_trg_field); value= val; diff --git a/sql/sql_class.h b/sql/sql_class.h index 208e4ba10e6..7e63b2e7515 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -7601,7 +7601,8 @@ class multi_update :public select_result_interceptor { TABLE_LIST *all_tables; /* query/update command tables */ List *leaves; /* list of leaves of join table tree */ - List updated_leaves; /* list of of updated leaves */ + List updated_leaves; /* a superset of tables which will be updated */ + List update_targets; /* the tables that will be UPDATE'd */ TABLE_LIST *update_tables; TABLE **tmp_tables, *main_table, *table_to_update; TMP_TABLE_PARAM *tmp_table_param; @@ -7633,6 +7634,7 @@ class multi_update :public select_result_interceptor ha_rows updated_sys_ver; bool has_vers_fields; + const table_map tables_to_update; public: multi_update(THD *thd_arg, TABLE_LIST *ut, List *leaves_list, diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index f3c7f98785d..b3434b42eb2 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -51,7 +51,7 @@ bool With_clause::add_with_element(With_element *elem) elem->owner= this; elem->number= with_list.elements; elem->spec->with_element= elem; - with_list.link_in_list(elem, &elem->next); + with_list.insert(elem, &elem->next); return false; } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 73739b5cf0b..2a8ab83bd3e 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1112,7 +1112,7 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) void TABLE_LIST::register_as_derived_with_rec_ref(With_element *rec_elem) { - rec_elem->derived_with_rec_ref.link_in_list(this, &this->next_with_rec_ref); + rec_elem->derived_with_rec_ref.insert(this, &this->next_with_rec_ref); is_derived_with_recursive_reference= true; get_unit()->uncacheable|= UNCACHEABLE_DEPENDENT; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 590555c5232..cfb1ad4f5f9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -242,7 +242,7 @@ bool LEX::set_trigger_new_row(const LEX_CSTRING *name, Item *val, Let us add this item to list of all Item_trigger_field objects in trigger. */ - sphead->m_cur_instr_trig_field_items.link_in_list(trg_fld, + sphead->m_cur_instr_trig_field_items.insert(trg_fld, &trg_fld->next_trg_field); return sphead->add_instr(sp_fld); @@ -8263,7 +8263,7 @@ Item *LEX::create_and_link_Item_trigger_field(THD *thd, in trigger. */ if (likely(trg_fld)) - sphead->m_cur_instr_trig_field_items.link_in_list(trg_fld, + sphead->m_cur_instr_trig_field_items.insert(trg_fld, &trg_fld->next_trg_field); return trg_fld; diff --git a/sql/sql_list.h b/sql/sql_list.h index 697dc754f22..48456dc8945 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -61,7 +61,7 @@ public: next= &first; } - inline void link_in_list(T *element, T **next_ptr) + inline void insert(T *element, T **next_ptr) { elements++; (*next)= element; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7513e3e5b8f..c2f842aea56 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2065,7 +2065,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * */ table_list.select_lex= thd->lex->first_select_lex(); thd->lex-> - first_select_lex()->table_list.link_in_list(&table_list, + first_select_lex()->table_list.insert(&table_list, &table_list.next_local); thd->lex->add_to_query_tables(&table_list); @@ -8003,7 +8003,7 @@ add_proc_to_list(THD* thd, Item *item) item_ptr = (Item**) (order+1); *item_ptr= item; order->item=item_ptr; - thd->lex->proc_list.link_in_list(order, &order->next); + thd->lex->proc_list.insert(order, &order->next); return 0; } @@ -8024,7 +8024,7 @@ bool add_to_list(THD *thd, SQL_I_List &list, Item *item,bool asc) order->used=0; order->counter_used= 0; order->fast_field_copier_setup= 0; - list.link_in_list(order, &order->next); + list.insert(order, &order->next); DBUG_RETURN(0); } @@ -8202,7 +8202,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, and SELECT. */ if (likely(!ptr->sequence)) - table_list.link_in_list(ptr, &ptr->next_local); + table_list.insert(ptr, &ptr->next_local); ptr->next_name_resolution_table= NULL; #ifdef WITH_PARTITION_STORAGE_ENGINE ptr->partition_names= partition_names; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 66f6021c1c0..a601f4ef0b6 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1056,7 +1056,7 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg, bool first_execution) { thd_arg->lex->current_select= fake_select_lex; - fake_select_lex->table_list.link_in_list(&result_table_list, + fake_select_lex->table_list.insert(&result_table_list, &result_table_list.next_local); fake_select_lex->context.table_list= fake_select_lex->context.first_name_resolution_table= diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 0c1decb3221..f8ac085a514 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1782,25 +1782,47 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) } -multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, +multi_update::multi_update(THD *thd_arg, + TABLE_LIST *table_list, List *leaves_list, - List *field_list, List *value_list, - enum enum_duplicates handle_duplicates_arg, - bool ignore_arg): - select_result_interceptor(thd_arg), - all_tables(table_list), leaves(leaves_list), update_tables(0), - tmp_tables(0), updated(0), found(0), fields(field_list), - values(value_list), table_count(0), copy_field(0), - handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1), - transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0), - updated_sys_ver(0) + List *field_list, + List *value_list, + enum enum_duplicates handle_duplicates_arg, + bool ignore_arg) + : select_result_interceptor(thd_arg), + all_tables(table_list), + leaves(leaves_list), + update_tables(0), + tmp_tables(0), + updated(0), + found(0), + fields(field_list), + values(value_list), + table_count(0), + copy_field(0), + handle_duplicates(handle_duplicates_arg), + do_update(1), + trans_safe(1), + transactional_tables(0), + ignore(ignore_arg), + error_handled(0), + prepared(0), + updated_sys_ver(0), + tables_to_update(get_table_map(fields)) { + // Defer error reporting to multi_update::init whne tables_to_update is zero + // because we don't have exceptions and we can't return values from a constructor. } bool multi_update::init(THD *thd) { - table_map tables_to_update= get_table_map(fields); + if (!tables_to_update) + { + my_message(ER_NO_TABLES_USED, ER_THD(thd, ER_NO_TABLES_USED), MYF(0)); + return true; + } + List_iterator_fast li(*leaves); TABLE_LIST *tbl; while ((tbl =li++)) @@ -1812,6 +1834,24 @@ bool multi_update::init(THD *thd) if (updated_leaves.push_back(tbl, thd->mem_root)) return true; } + + List_iterator updated_leaves_iter(updated_leaves); + TABLE_LIST *table_ref; + while ((table_ref= updated_leaves_iter++)) + { + /* TODO: add support of view of join support */ + if (table_ref->is_jtbm()) + continue; + + TABLE *table= table_ref->table; + if (tables_to_update & table->map) + update_targets.push_back(table_ref); + } + table_count= update_targets.elements; + tmp_tables = thd->calloc(table_count); + tmp_table_param = thd->calloc(table_count); + fields_for_table= thd->alloc(table_count); + values_for_table= thd->alloc(table_count); return false; } @@ -1838,14 +1878,13 @@ int multi_update::prepare(List ¬_used_values, { TABLE_LIST *table_ref; - SQL_I_List update; - table_map tables_to_update; + SQL_I_List update_list; Item_field *item; List_iterator_fast field_it(*fields); List_iterator_fast value_it(*values); uint i, max_fields; uint leaf_table_count= 0; - List_iterator ti(updated_leaves); + List_iterator update_targets_iter(update_targets); DBUG_ENTER("multi_update::prepare"); if (prepared) @@ -1856,98 +1895,69 @@ int multi_update::prepare(List ¬_used_values, thd->cuted_fields=0L; THD_STAGE_INFO(thd, stage_updating_main_table); - tables_to_update= get_table_map(fields); - - if (!tables_to_update) - { - my_message(ER_NO_TABLES_USED, ER_THD(thd, ER_NO_TABLES_USED), MYF(0)); - DBUG_RETURN(1); - } - /* We gather the set of columns read during evaluation of SET expression in TABLE::tmp_set by pointing TABLE::read_set to it and then restore it after setup_fields(). */ - while ((table_ref= ti++)) + while ((table_ref= update_targets_iter++)) { - if (table_ref->is_jtbm()) - continue; - TABLE *table= table_ref->table; - if (tables_to_update & table->map) - { - DBUG_ASSERT(table->read_set == &table->def_read_set); - table->read_set= &table->tmp_set; - bitmap_clear_all(table->read_set); - } + DBUG_ASSERT(table->read_set == &table->def_read_set); + table->read_set= &table->tmp_set; + bitmap_clear_all(table->read_set); } /* We have to check values after setup_tables to get covering_keys right in reference tables */ - int error= setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, NULL, 0) || TABLE::check_assignability_explicit_fields(*fields, *values, ignore); - ti.rewind(); - while ((table_ref= ti++)) + /* + Restore TABLE::tmp_set as we promised just before setup_tables. + */ + update_targets_iter.rewind(); + while ((table_ref= update_targets_iter++)) { - if (table_ref->is_jtbm()) - continue; - TABLE *table= table_ref->table; - if (tables_to_update & table->map) - { - table->read_set= &table->def_read_set; - bitmap_union(table->read_set, &table->tmp_set); - if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE)) - table->file->prepare_for_modify(true, true); - } + table->read_set= &table->def_read_set; + bitmap_union(table->read_set, &table->tmp_set); + if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE)) + table->file->prepare_for_modify(true, true); } if (unlikely(error)) DBUG_RETURN(1); /* - Save tables being updated in update_tables - update_table->shared is position for table - Don't use key read on tables that are updated + Save tables that we will update into update_list. + table_ref->shared links this table to its corresponding temporary table + for collecting row ids. + Don't use key read on tables that are updated. */ - - update.empty(); - ti.rewind(); - while ((table_ref= ti++)) + update_list.empty(); + update_targets_iter.rewind(); + for (uint index= 0; (table_ref= update_targets_iter++);) { - /* TODO: add support of view of join support */ - if (table_ref->is_jtbm()) - continue; TABLE *table=table_ref->table; leaf_table_count++; - if (tables_to_update & table->map) - { - TABLE_LIST *tl= (TABLE_LIST*) thd->memdup(table_ref, - sizeof(*tl)); - if (!tl) - DBUG_RETURN(1); - update.link_in_list(tl, &tl->next_local); - table_ref->shared= tl->shared= table_count++; - table->no_keyread=1; - table->covering_keys.clear_all(); - table->prepare_triggers_for_update_stmt_or_event(); - table->reset_default_fields(); - } + TABLE_LIST *tl= (TABLE_LIST*) thd->memdup(table_ref, + sizeof(*tl)); + if (!tl) + DBUG_RETURN(1); + update_list.insert(tl, &tl->next_local); + table_ref->shared= tl->shared= index++; + table->no_keyread=1; + table->covering_keys.clear_all(); + table->prepare_triggers_for_update_stmt_or_event(); + table->reset_default_fields(); } - table_count= update.elements; - update_tables= update.first; + update_tables= update_list.first; - tmp_tables = thd->calloc(table_count); - tmp_table_param = thd->calloc(table_count); - fields_for_table= thd->alloc(table_count); - values_for_table= thd->alloc(table_count); if (unlikely(thd->is_fatal_error)) DBUG_RETURN(1); for (i=0 ; i < table_count ; i++) @@ -2129,7 +2139,7 @@ multi_update::initialize_tables(JOIN *join) for (table_ref= update_tables; table_ref; table_ref= table_ref->next_local) { TABLE *table=table_ref->table; - uint cnt= table_ref->shared; + uint index= table_ref->shared; List temp_fields; ORDER group; TMP_TABLE_PARAM *tmp_param; @@ -2191,8 +2201,6 @@ loop_end: } } - tmp_param= tmp_table_param+cnt; - /* Create a temporary table to store all fields that are changed for this table. The first field in the temporary table is a pointer to the @@ -2205,9 +2213,6 @@ loop_end: TABLE *tbl= table; do { - LEX_CSTRING field_name; - field_name.str= tbl->alias.c_ptr(); - field_name.length= strlen(field_name.str); /* Signal each table (including tables referenced by WITH CHECK OPTION clause) for which we will store row position in the temporary table @@ -2225,13 +2230,14 @@ loop_end: DBUG_RETURN(1); } while ((tbl= tbl_it++)); - temp_fields.append(fields_for_table[cnt]); + temp_fields.append(fields_for_table[index]); /* Make an unique key over the first field to avoid duplicated updates */ bzero((char*) &group, sizeof(group)); group.direction= ORDER::ORDER_ASC; group.item= (Item**) temp_fields.head_ref(); + tmp_param= &tmp_table_param[index]; tmp_param->init(); tmp_param->tmp_name="update"; tmp_param->field_count= temp_fields.elements; @@ -2240,13 +2246,13 @@ loop_end: /* small table, ignore @@big_tables */ my_bool save_big_tables= thd->variables.big_tables; thd->variables.big_tables= FALSE; - tmp_tables[cnt]=create_tmp_table(thd, tmp_param, temp_fields, + tmp_tables[index]=create_tmp_table(thd, tmp_param, temp_fields, (ORDER*) &group, 0, 0, TMP_TABLE_ALL_COLUMNS, HA_POS_ERROR, &empty_clex_str); thd->variables.big_tables= save_big_tables; - if (!tmp_tables[cnt]) + if (!tmp_tables[index]) DBUG_RETURN(1); - tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE); + tmp_tables[index]->file->extra(HA_EXTRA_WRITE_CACHE); } join->tmp_table_keep_current_rowid= TRUE; DBUG_RETURN(0);