backported the fix for bug #34773 to 5.0
This commit is contained in:
parent
cbe1a8a0f9
commit
979974c53b
@ -107,3 +107,51 @@ X X X X X X X X X
|
||||
X X X X X X X X X Range checked for each record (index map: 0xFFFFFFFFFF)
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INT);
|
||||
CREATE TABLE t2(a INT);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
INSERT INTO t2 VALUES (1),(2);
|
||||
EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
|
||||
2 DERIVED t2 ALL NULL NULL NULL NULL 2
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
|
||||
EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
|
||||
2 DERIVED t2 ALL NULL NULL NULL NULL 2
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
|
||||
prepare s1 from
|
||||
'EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
|
||||
execute s1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
|
||||
2 DERIVED t2 ALL NULL NULL NULL NULL 2
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
|
||||
prepare s1 from
|
||||
'EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
|
||||
execute s1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
|
||||
2 DERIVED t2 ALL NULL NULL NULL NULL 2
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
|
||||
execute s1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
|
||||
2 DERIVED t2 ALL NULL NULL NULL NULL 2
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
|
||||
DROP TABLE t1,t2;
|
||||
|
@ -94,4 +94,33 @@ EXPLAIN SELECT 1 FROM
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #34773: query with explain extended and derived table / other table
|
||||
# crashes server
|
||||
#
|
||||
|
||||
CREATE TABLE t1(a INT);
|
||||
CREATE TABLE t2(a INT);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
INSERT INTO t2 VALUES (1),(2);
|
||||
|
||||
EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
|
||||
|
||||
EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
|
||||
|
||||
prepare s1 from
|
||||
'EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
|
||||
execute s1;
|
||||
|
||||
prepare s1 from
|
||||
'EXPLAIN EXTENDED SELECT 1
|
||||
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
|
||||
execute s1;
|
||||
execute s1;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
# End of 5.0 tests.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
|
@ -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++;
|
||||
|
Loading…
x
Reference in New Issue
Block a user