diff options
author | Sergei Golubchik <serg@mariadb.org> | 2018-04-10 11:33:47 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2018-05-17 15:13:47 +0200 |
commit | e17e7985999b10c602ba72258e9a4b6e5fb91ed5 (patch) | |
tree | 041a34266d19c2e414bffafd26f2cfd007a7b8c4 | |
parent | c368878fac7de6cb65790249990d28dcbf0ea255 (diff) | |
download | mariadb-git-e17e7985999b10c602ba72258e9a4b6e5fb91ed5.tar.gz |
cleanup: simplify multi-update's juggling with positions
introduce Item_temptable_rowid() that is used to store
table->file->position() in the temporary table record
-rw-r--r-- | sql/item_strfunc.cc | 20 | ||||
-rw-r--r-- | sql/item_strfunc.h | 21 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sql_select.h | 1 | ||||
-rw-r--r-- | sql/sql_update.cc | 54 |
5 files changed, 65 insertions, 49 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8df4e72462d..d5911e01cef 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5204,3 +5204,23 @@ null: my_free(names); return NULL; } + +Item_temptable_rowid::Item_temptable_rowid(TABLE *table_arg) + : Item_str_func(table_arg->in_use), table(table_arg) +{ + max_length= table->file->ref_length; +} + +void Item_temptable_rowid::fix_length_and_dec() +{ + used_tables_cache= table->map; + const_item_cache= false; +} + +String *Item_temptable_rowid::val_str(String *str) +{ + if (!((null_value= table->null_row))) + table->file->position(table->record[0]); + str_value.set((char*)(table->file->ref), max_length, &my_charset_bin); + return &str_value; +} diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index b3462a60d36..1132a947587 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1751,5 +1751,24 @@ public: { return get_item_copy<Item_func_dyncol_list>(thd, this); } }; -#endif /* ITEM_STRFUNC_INCLUDED */ +/* + this is used by JOIN_TAB::keep_current_rowid + and stores handler::position(). + It has nothing to do with _rowid pseudo-column, that the parser supports. +*/ +class Item_temptable_rowid :public Item_str_func +{ +public: + TABLE *table; + Item_temptable_rowid(TABLE *table_arg); + const Type_handler *type_handler() const { return &type_handler_string; } + Field *create_tmp_field(bool group, TABLE *table) + { return create_table_field_from_handler(table); } + String *val_str(String *str); + const char *func_name() const { return "<rowid>"; } + void fix_length_and_dec(); + Item *get_copy(THD *thd) + { return get_item_copy<Item_temptable_rowid>(thd, this); } +}; +#endif /* ITEM_STRFUNC_INCLUDED */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 07d92c5498b..f8d3fb778e3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -23400,13 +23400,10 @@ get_sort_by_table(ORDER *a,ORDER *b, List<TABLE_LIST> &tables, calc how big buffer we need for comparing group entries. */ -static void -calc_group_buffer(JOIN *join,ORDER *group) +void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group) { uint key_length=0, parts=0, null_parts=0; - if (group) - join->group= 1; for (; group ; group=group->next) { Item *group_item= *group->item; @@ -23476,9 +23473,16 @@ calc_group_buffer(JOIN *join,ORDER *group) if (group_item->maybe_null) null_parts++; } - join->tmp_table_param.group_length=key_length+null_parts; - join->tmp_table_param.group_parts=parts; - join->tmp_table_param.group_null_parts=null_parts; + param->group_length= key_length + null_parts; + param->group_parts= parts; + param->group_null_parts= null_parts; +} + +static void calc_group_buffer(JOIN *join, ORDER *group) +{ + if (group) + join->group= 1; + calc_group_buffer(&join->tmp_table_param, group); } diff --git a/sql/sql_select.h b/sql/sql_select.h index fdef2534812..20c2370d650 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2382,6 +2382,7 @@ int append_possible_keys(MEM_ROOT *alloc, String_list &list, TABLE *table, #define RATIO_TO_PACK_ROWS 2 #define MIN_STRING_LENGTH_TO_PACK_ROWS 10 +void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group); TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ORDER *group, bool distinct, bool save_sum_fields, ulonglong select_options, ha_rows rows_limit, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 26bd1d79d69..829bfa546ce 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2167,22 +2167,12 @@ loop_end: tbl->prepare_for_position(); join->map2table[tbl->tablenr]->keep_current_rowid= true; - Field_string *field= new Field_string(tbl->file->ref_length, 0, - &field_name, - &my_charset_bin); - if (!field) - DBUG_RETURN(1); - field->init(tbl); - /* - The field will be converted to varstring when creating tmp table if - table to be updated was created by mysql 4.1. Deny this. - */ - field->can_alter_field_type= 0; - Item_field *ifield= new (thd->mem_root) Item_field(join->thd, (Field *) field); - if (!ifield) + Item_temptable_rowid *item= + new (thd->mem_root) Item_temptable_rowid(tbl); + if (!item) DBUG_RETURN(1); - ifield->maybe_null= 0; - if (temp_fields.push_back(ifield, thd->mem_root)) + item->fix_fields(thd, 0); + if (temp_fields.push_back(item, thd->mem_root)) DBUG_RETURN(1); } while ((tbl= tbl_it++)); @@ -2193,10 +2183,10 @@ loop_end: group.direction= ORDER::ORDER_ASC; group.item= (Item**) temp_fields.head_ref(); - tmp_param->quick_group=1; - tmp_param->field_count=temp_fields.elements; - tmp_param->group_parts=1; - tmp_param->group_length= table->file->ref_length; + tmp_param->quick_group= 1; + tmp_param->field_count= temp_fields.elements; + tmp_param->func_count= temp_fields.elements - 1; + calc_group_buffer(tmp_param, &group); /* small table, ignore SQL_BIG_TABLES */ my_bool save_big_tables= thd->variables.big_tables; thd->variables.big_tables= FALSE; @@ -2384,29 +2374,11 @@ int multi_update::send_data(List<Item> ¬_used_values) { int error; TABLE *tmp_table= tmp_tables[offset]; - /* - For updatable VIEW store rowid of the updated table and - rowids of tables used in the CHECK OPTION condition. - */ - uint field_num= 0; - List_iterator_fast<TABLE> tbl_it(unupdated_check_opt_tables); - /* Set first tbl = table and then tbl to tables from tbl_it */ - TABLE *tbl= table; - do - { - tbl->file->position(tbl->record[0]); - memcpy((char*) tmp_table->field[field_num]->ptr, - (char*) tbl->file->ref, tbl->file->ref_length); - /* - For outer joins a rowid field may have no NOT_NULL_FLAG, - so we have to reset NULL bit for this field. - (set_notnull() resets NULL bit only if available). - */ - tmp_table->field[field_num]->set_notnull(); - field_num++; - } while ((tbl= tbl_it++)); - + if (copy_funcs(tmp_table_param[offset].items_to_copy, thd)) + DBUG_RETURN(1); /* Store regular updated fields in the row. */ + DBUG_ASSERT(1 + unupdated_check_opt_tables.elements == + tmp_table_param[offset].func_count); fill_record(thd, tmp_table, tmp_table->field + 1 + unupdated_check_opt_tables.elements, *values_for_table[offset], TRUE, FALSE); |