backported the fix for bug #34773 to 5.0

This commit is contained in:
Georgi Kodinov 2008-12-09 20:35:02 +02:00
commit 979974c53b
8 changed files with 143 additions and 24 deletions

View file

@ -6795,7 +6795,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
*/
Item_sum *item_sum= (Item_sum *) item;
if (item_sum->keep_field_type())
return get_real_type(item_sum->args[0]);
return get_real_type(item_sum->get_arg(0));
break;
}
case FUNC_ITEM:
@ -7059,7 +7059,7 @@ void Item_type_holder::get_full_info(Item *item)
if (item->type() == Item::SUM_FUNC_ITEM &&
(((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
((Item_sum*)item)->sum_func() == Item_sum::MIN_FUNC))
item = ((Item_sum*)item)->args[0];
item = ((Item_sum*)item)->get_arg(0);
/*
We can have enum/set type after merging only if we have one enum|set
field (or MIN|MAX(enum|set field)) and number of NULL fields

View file

@ -370,6 +370,10 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
args[i++]= item;
}
}
if (!(orig_args= (Item **) sql_alloc(sizeof(Item *) * arg_count)))
{
args= NULL;
}
mark_as_sum_func();
list.empty(); // Fields are used
}
@ -380,18 +384,28 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
*/
Item_sum::Item_sum(THD *thd, Item_sum *item):
Item_result_field(thd, item), arg_count(item->arg_count),
Item_result_field(thd, item),
aggr_sel(item->aggr_sel),
nest_level(item->nest_level), aggr_level(item->aggr_level),
quick_group(item->quick_group), used_tables_cache(item->used_tables_cache),
quick_group(item->quick_group),
arg_count(item->arg_count), orig_args(NULL),
used_tables_cache(item->used_tables_cache),
forced_const(item->forced_const)
{
if (arg_count <= 2)
{
args=tmp_args;
orig_args=tmp_orig_args;
}
else
{
if (!(args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
return;
if (!(orig_args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
return;
}
memcpy(args, item->args, sizeof(Item*)*arg_count);
memcpy(orig_args, item->orig_args, sizeof(Item*)*arg_count);
}
@ -426,12 +440,13 @@ void Item_sum::make_field(Send_field *tmp_field)
void Item_sum::print(String *str)
{
Item **pargs= orig_args;
str->append(func_name());
for (uint i=0 ; i < arg_count ; i++)
{
if (i)
str->append(',');
args[i]->print(str);
pargs[i]->print(str);
}
str->append(')');
}
@ -532,6 +547,13 @@ void Item_sum::update_used_tables ()
}
Item *Item_sum::set_arg(int i, THD *thd, Item *new_val)
{
thd->change_item_tree(args + i, new_val);
return new_val;
}
String *
Item_sum_num::val_str(String *str)
{
@ -583,6 +605,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
if (check_sum_func(thd, ref))
return TRUE;
memcpy (orig_args, args, sizeof (Item *) * arg_count);
fixed= 1;
return FALSE;
}
@ -670,6 +693,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
if (check_sum_func(thd, ref))
return TRUE;
orig_args[0]= args[0];
fixed= 1;
return FALSE;
}
@ -3107,6 +3131,12 @@ Item_func_group_concat(Name_resolution_context *context_arg,
sizeof(ORDER*)*arg_count_order)))
return;
if (!(orig_args= (Item **) sql_alloc(sizeof(Item *) * arg_count)))
{
args= NULL;
return;
}
order= (ORDER**)(args + arg_count);
/* fill args items of show and sort */
@ -3334,6 +3364,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
if (check_sum_func(thd, ref))
return TRUE;
memcpy (orig_args, args, sizeof (Item *) * arg_count);
fixed= 1;
return FALSE;
}

View file

@ -228,10 +228,8 @@ public:
VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC
};
Item **args, *tmp_args[2];
Item **ref_by; /* pointer to a ref to the object used to register it */
Item_sum *next; /* next in the circular chain of registered objects */
uint arg_count;
Item_sum *in_sum_func; /* embedding set function if any */
st_select_lex * aggr_sel; /* select where the function is aggregated */
int8 nest_level; /* number of the nesting level of the set function */
@ -248,24 +246,32 @@ public:
List<Item_field> outer_fields;
protected:
uint arg_count;
Item **args, *tmp_args[2];
/*
Copy of the arguments list to hold the original set of arguments.
Used in EXPLAIN EXTENDED instead of the current argument list because
the current argument list can be altered by usage of temporary tables.
*/
Item **orig_args, *tmp_orig_args[2];
table_map used_tables_cache;
bool forced_const;
public:
void mark_as_sum_func();
Item_sum() :arg_count(0), quick_group(1), forced_const(FALSE)
Item_sum() :quick_group(1), arg_count(0), forced_const(FALSE)
{
mark_as_sum_func();
}
Item_sum(Item *a) :args(tmp_args), arg_count(1), quick_group(1),
forced_const(FALSE)
Item_sum(Item *a) :quick_group(1), arg_count(1), args(tmp_args),
orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a;
mark_as_sum_func();
}
Item_sum( Item *a, Item *b ) :args(tmp_args), arg_count(2), quick_group(1),
forced_const(FALSE)
Item_sum( Item *a, Item *b ) :quick_group(1), arg_count(2), args(tmp_args),
orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a; args[1]=b;
mark_as_sum_func();
@ -374,6 +380,10 @@ public:
bool register_sum_func(THD *thd, Item **ref);
st_select_lex *depended_from()
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
Item *get_arg(int i) { return args[i]; }
Item *set_arg(int i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
};
@ -981,6 +991,7 @@ public:
if (udf.fix_fields(thd, this, this->arg_count, this->args))
return TRUE;
memcpy (orig_args, args, sizeof (Item *) * arg_count);
return check_sum_func(thd, ref);
}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }

View file

@ -7735,7 +7735,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
DBUG_RETURN(NULL);
/* The argument of MIN/MAX. */
Item *expr= min_max_item->args[0]->real_item();
Item *expr= min_max_item->get_arg(0)->real_item();
if (expr->type() == Item::FIELD_ITEM) /* Is it an attribute? */
{
if (! min_max_arg_item)

View file

@ -160,7 +160,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
to the number of rows in the tables if this number is exact and
there are no outer joins.
*/
if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null &&
if (!conds && !((Item_sum_count*) item)->get_arg(0)->maybe_null &&
!outer_tables && is_exact_count)
{
((Item_sum_count*) item)->make_const(count);
@ -176,7 +176,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
parts of the key is found in the COND, then we can use
indexes to find the key.
*/
Item *expr=item_sum->args[0];
Item *expr=item_sum->get_arg(0);
if (expr->real_item()->type() == Item::FIELD_ITEM)
{
byte key_buff[MAX_KEY_LENGTH];
@ -319,7 +319,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
parts of the key is found in the COND, then we can use
indexes to find the key.
*/
Item *expr=item_sum->args[0];
Item *expr=item_sum->get_arg(0);
if (expr->real_item()->type() == Item::FIELD_ITEM)
{
byte key_buff[MAX_KEY_LENGTH];

View file

@ -9444,11 +9444,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
{ /* Can't calc group yet */
((Item_sum*) item)->result_field=0;
for (i=0 ; i < ((Item_sum*) item)->arg_count ; i++)
Item_sum *sum_item= (Item_sum *) item;
sum_item->result_field=0;
for (i=0 ; i < sum_item->get_arg_count() ; i++)
{
Item **argp= ((Item_sum*) item)->args + i;
Item *arg= *argp;
Item *arg= sum_item->get_arg(i);
if (!arg->const_item())
{
uint field_index= (uint) (reg_field - table->field);
@ -9478,7 +9478,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
string_total_length+= new_field->pack_length();
}
thd->mem_root= mem_root_save;
thd->change_item_tree(argp, new Item_field(new_field));
arg= sum_item->set_arg(i, thd, new Item_field(new_field));
thd->mem_root= &table->mem_root;
if (!(new_field->flags & NOT_NULL_FLAG))
{
@ -9487,7 +9487,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
new_field->maybe_null() is still false, it will be
changed below. But we have to setup Item_field correctly
*/
(*argp)->maybe_null=1;
arg->maybe_null=1;
}
new_field->query_id= thd->query_id;
}
@ -13922,9 +13922,9 @@ count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
param->quick_group=0; // UDF SUM function
param->sum_func_count++;
for (uint i=0 ; i < sum_item->arg_count ; i++)
for (uint i=0 ; i < sum_item->get_arg_count() ; i++)
{
if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM)
if (sum_item->get_arg(i)->real_item()->type() == Item::FIELD_ITEM)
param->field_count++;
else
param->func_count++;