summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_heap.cc14
-rw-r--r--sql/item.cc12
-rw-r--r--sql/item.h12
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/item_strfunc.cc18
-rw-r--r--sql/key.cc2
-rw-r--r--sql/set_var.cc1
-rw-r--r--sql/sql_select.cc119
-rw-r--r--sql/sql_select.h3
-rw-r--r--sql/sql_string.h4
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)
{