summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2018-04-10 11:33:47 +0200
committerSergei Golubchik <serg@mariadb.org>2018-05-17 15:13:47 +0200
commite17e7985999b10c602ba72258e9a4b6e5fb91ed5 (patch)
tree041a34266d19c2e414bffafd26f2cfd007a7b8c4
parentc368878fac7de6cb65790249990d28dcbf0ea255 (diff)
downloadmariadb-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.cc20
-rw-r--r--sql/item_strfunc.h21
-rw-r--r--sql/sql_select.cc18
-rw-r--r--sql/sql_select.h1
-rw-r--r--sql/sql_update.cc54
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> &not_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);