diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_heap.cc | 14 | ||||
-rw-r--r-- | sql/item.cc | 12 | ||||
-rw-r--r-- | sql/item.h | 12 | ||||
-rw-r--r-- | sql/item_func.cc | 5 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 18 | ||||
-rw-r--r-- | sql/key.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 119 | ||||
-rw-r--r-- | sql/sql_select.h | 3 | ||||
-rw-r--r-- | sql/sql_string.h | 4 |
10 files changed, 143 insertions, 47 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index c8d0e5c1c18..24f21718b8c 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -521,9 +521,17 @@ int ha_heap::create(const char *name, TABLE *table_arg, seg->null_bit= 0; seg->null_pos= 0; } - // We have to store field->key_type() as seg->type can differ from it - if (field->flags & AUTO_INCREMENT_FLAG) + if (field->flags & AUTO_INCREMENT_FLAG && + table_arg->found_next_number_field && + key == table_arg->next_number_index) + { + /* + Store key number and type for found auto_increment key + We have to store type as seg->type can differ from it + */ + auto_key= key+ 1; auto_key_type= field->key_type(); + } } } mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); @@ -535,8 +543,8 @@ int ha_heap::create(const char *name, TABLE *table_arg, found_real_auto_increment= share->next_number_key_offset == 0; } HP_CREATE_INFO hp_create_info; + hp_create_info.auto_key= auto_key; hp_create_info.auto_key_type= auto_key_type; - hp_create_info.with_auto_increment= found_real_auto_increment; hp_create_info.auto_increment= (create_info->auto_increment_value ? create_info->auto_increment_value - 1 : 0); hp_create_info.max_table_size=current_thd->variables.max_heap_table_size; diff --git a/sql/item.cc b/sql/item.cc index e6be934e334..64fc2696f1f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -586,6 +586,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); + /* + The above line executes str_value.realloc() internally, + which alligns Alloced_length using ALLIGN_SIZE. + In the case of Item_string::str_value we don't want + Alloced_length to be longer than str_length. + Otherwise, some functions like Item_func_concat::val_str() + try to reuse str_value as a buffer for concatenation result + for optimization purposes, so our string constant become + corrupted. See bug#8785 for more details. + Let's shrink Alloced_length to str_length to avoid this problem. + */ + conv->str_value.shrink_to_length(); return conv; } diff --git a/sql/item.h b/sql/item.h index a2bf33398cc..31b490d6ed8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -790,6 +790,17 @@ public: Item *safe_charset_converter(CHARSET_INFO *tocs); }; +class Item_null_result :public Item_null +{ +public: + Field *result_field; + Item_null_result() : Item_null(), result_field(0) {} + bool is_result_field() { return result_field != 0; } + void save_in_result_field(bool no_conversions) + { + save_in_field(result_field, no_conversions); + } +}; /* Item represents one placeholder ('?') of prepared statement */ @@ -1274,6 +1285,7 @@ public: void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } enum_field_types field_type() const { return (*ref)->field_type(); } + Field *get_tmp_table_field() { return result_field; } table_map used_tables() const { return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); diff --git a/sql/item_func.cc b/sql/item_func.cc index 684ba814cd4..5eb87c2e92b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2096,11 +2096,6 @@ longlong Item_func_char_length::val_int() longlong Item_func_coercibility::val_int() { DBUG_ASSERT(fixed == 1); - if (args[0]->null_value) - { - null_value= 1; - return 0; - } null_value= 0; return (longlong) args[0]->collation.derivation; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a9ec7139ea7..81120bbe3f7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -267,8 +267,7 @@ String *Item_func_concat::val_str(String *str) current_thd->variables.max_allowed_packet); goto null; } - if (!args[0]->const_item() && - res->alloced_length() >= res->length()+res2->length()) + if (res->alloced_length() >= res->length()+res2->length()) { // Use old buffer res->append(*res2); } @@ -2308,12 +2307,11 @@ void Item_func_set_collation::print(String *str) String *Item_func_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); uint dummy_errors; - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->csname,strlen(res->charset()->csname), + CHARSET_INFO *cs= args[0]->collation.collation; + null_value= 0; + str->copy(cs->csname, strlen(cs->csname), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2321,12 +2319,11 @@ String *Item_func_charset::val_str(String *str) String *Item_func_collation::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); uint dummy_errors; + CHARSET_INFO *cs= args[0]->collation.collation; - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->name,strlen(res->charset()->name), + null_value= 0; + str->copy(cs->name, strlen(cs->name), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2490,6 +2487,7 @@ String* Item_func_export_set::val_str(String* str) uint num_set_values = 64; ulonglong mask = 0x1; str->length(0); + str->set_charset(collation.collation); /* Check if some argument is a NULL value */ if (args[0]->null_value || args[1]->null_value || args[2]->null_value) diff --git a/sql/key.cc b/sql/key.cc index c5ed60b129c..3299c3db8f8 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -368,7 +368,7 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields) f.rewind(); while ((field=(Item_field*) f++)) { - if (key_part->field == field->field) + if (key_part->field->eq(field->field)) return 1; } } diff --git a/sql/set_var.cc b/sql/set_var.cc index 1f4713471ba..23dbb22399b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -926,6 +926,7 @@ struct show_var_st init_vars[]= { {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, #ifdef HAVE_REPLICATION {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, + {"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG}, #endif {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b970c184489..1ada220b446 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -191,7 +191,7 @@ static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, uint elements, List<Item> &items); static void init_tmptable_sum_functions(Item_sum **func); static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); -static void copy_sum_funcs(Item_sum **func_ptr); +static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr); static bool init_sum_functions(Item_sum **func, Item_sum **end); @@ -1386,7 +1386,6 @@ JOIN::exec() { DBUG_VOID_RETURN; } - curr_join->group_list= 0; } thd->proc_info="Copying to group table"; @@ -1447,7 +1446,7 @@ JOIN::exec() if (curr_join->tmp_having) curr_join->tmp_having->update_used_tables(); if (remove_duplicates(curr_join, curr_tmp_table, - curr_join->fields_list, curr_join->tmp_having)) + *curr_fields_list, curr_join->tmp_having)) DBUG_VOID_RETURN; curr_join->tmp_having=0; curr_join->select_distinct=0; @@ -10132,26 +10131,32 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (join->procedure) join->procedure->end_group(); - if (idx < (int) join->send_group_parts) + int send_group_parts= join->send_group_parts; + if (idx < send_group_parts) { if (!join->first_record) { /* No matching rows for group function */ join->clear(); } - copy_sum_funcs(join->sum_funcs); - if (!join->having || join->having->val_int()) + copy_sum_funcs(join->sum_funcs, + join->sum_funcs_end[send_group_parts]); + if (join->having && join->having->val_int() == 0) + error= -1; + else if ((error=table->file->write_row(table->record[0]))) { - if ((error=table->file->write_row(table->record[0]))) - { - if (create_myisam_from_heap(join->thd, table, - &join->tmp_table_param, - error, 0)) - DBUG_RETURN(-1); // Not a table_is_full error - } - else - join->send_records++; + if (create_myisam_from_heap(join->thd, table, + &join->tmp_table_param, + error, 0)) + DBUG_RETURN(-1); + } + if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + { + if (join->rollup_write_data((uint) (idx+1), table)) + error= 1; } + if (error > 0) + DBUG_RETURN(-1); if (end_of_records) DBUG_RETURN(0); } @@ -12413,11 +12418,10 @@ update_tmptable_sum_func(Item_sum **func_ptr, /* Copy result of sum functions to record in tmp_table */ static void -copy_sum_funcs(Item_sum **func_ptr) +copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr) { - Item_sum *func; - for (; (func = *func_ptr) ; func_ptr++) - (void) func->save_in_result_field(1); + for (; func_ptr != end_ptr ; func_ptr++) + (void) (*func_ptr)->save_in_result_field(1); return; } @@ -12539,14 +12543,16 @@ bool JOIN::rollup_init() */ tmp_table_param.group_parts= send_group_parts; - if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) + - sizeof(List<Item>) + - ref_pointer_array_size) - * send_group_parts))) + if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) + + sizeof(Item**) + + sizeof(List<Item>) + + ref_pointer_array_size) + * send_group_parts ))) return 1; + + rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts); rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); - rollup.item_null= new (thd->mem_root) Item_null(); /* Prepare space for field list for the different levels @@ -12554,12 +12560,16 @@ bool JOIN::rollup_init() */ for (i= 0 ; i < send_group_parts ; i++) { + rollup.null_items[i]= new (thd->mem_root) Item_null_result(); List<Item> *rollup_fields= &rollup.fields[i]; rollup_fields->empty(); rollup.ref_pointer_arrays[i]= ref_array; ref_array+= all_fields.elements; + } + for (i= 0 ; i < send_group_parts; i++) + { for (j=0 ; j < fields_list.elements ; j++) - rollup_fields->push_back(rollup.item_null); + rollup.fields[i].push_back(rollup.null_items[i]); } return 0; } @@ -12663,7 +12673,8 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, { /* Check if this is something that is part of this group by */ ORDER *group_tmp; - for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next) + for (group_tmp= start_group, i-- ; + group_tmp ; group_tmp= group_tmp->next, i++) { if (*group_tmp->item == item) { @@ -12672,7 +12683,9 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, set to NULL in this level */ item->maybe_null= 1; // Value will be null sometimes - item= rollup.item_null; + Item_null_result *null_item= rollup.null_items[i]; + null_item->result_field= ((Item_field *) item)->result_field; + item= null_item; break; } } @@ -12733,6 +12746,58 @@ int JOIN::rollup_send_data(uint idx) } /* + Write all rollup levels higher than the current one to a temp table + + SYNOPSIS: + rollup_write_data() + idx Level we are on: + 0 = Total sum level + 1 = First group changed (a) + 2 = Second group changed (a,b) + table reference to temp table + + SAMPLE + SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP + + RETURN + 0 ok + 1 if write_data_failed() +*/ + +int JOIN::rollup_write_data(uint idx, TABLE *table) +{ + uint i; + for (i= send_group_parts ; i-- > idx ; ) + { + /* Get reference pointers to sum functions in place */ + memcpy((char*) ref_pointer_array, + (char*) rollup.ref_pointer_arrays[i], + ref_pointer_array_size); + if ((!having || having->val_int())) + { + int error; + Item *item; + List_iterator_fast<Item> it(rollup.fields[i]); + while ((item= it++)) + { + if (item->type() == Item::NULL_ITEM && item->is_result_field()) + item->save_in_result_field(1); + } + copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]); + if ((error= table->file->write_row(table->record[0]))) + { + if (create_myisam_from_heap(thd, table, &tmp_table_param, + error, 0)) + return 1; + } + } + } + /* Restore ref_pointer_array */ + set_items_ref_array(current_ref_pointer_array); + return 0; +} + +/* clear results if there are not rows found for group (end_send_group/end_write_group) diff --git a/sql/sql_select.h b/sql/sql_select.h index f00fd476edd..02e1dde8a7f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -135,7 +135,7 @@ typedef struct st_rollup { enum State { STATE_NONE, STATE_INITED, STATE_READY }; State state; - Item *item_null; + Item_null_result **null_items; Item ***ref_pointer_arrays; List<Item> *fields; } ROLLUP; @@ -323,6 +323,7 @@ class JOIN :public Sql_alloc bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields, Item_sum ***func); int rollup_send_data(uint idx); + int rollup_write_data(uint idx, TABLE *table); bool test_in_subselect(Item **where); void join_free(bool full); void clear(); diff --git a/sql/sql_string.h b/sql/sql_string.h index 2debeb61787..fc1e9f171b6 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -205,6 +205,10 @@ public: } } } + inline void shrink_to_length() + { + Alloced_length= str_length; + } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { |