Commit b5f152dc authored by Georgi Kodinov's avatar Georgi Kodinov
Browse files

Bug#34773: query with explain extended and derived table / other table

crashes server

When creating temporary table that contains aggregate functions a 
non-reversible source transformation was performed to redirect aggregate
function arguments towards temporary table columns.
This caused EXPLAIN EXTENDED to fail because it was trying to resolve
references to the (freed) temporary table.
Fixed by preserving the original aggregate function arguments and
using them (instead of the transformed ones) for EXPLAIN EXTENDED.
parent 77e54c03
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -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	filtered	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer
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	filtered	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer
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	filtered	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer
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	filtered	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer
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	filtered	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	
2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	100.00	Using join buffer
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;
+29 −0
Original line number Diff line number Diff line
@@ -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.
+2 −2
Original line number Diff line number Diff line
@@ -6919,7 +6919,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:
@@ -7182,7 +7182,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
+34 −3
Original line number Diff line number Diff line
@@ -369,6 +369,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
}
@@ -379,18 +383,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);
}


@@ -425,12 +439,13 @@ void Item_sum::make_field(Send_field *tmp_field)

void Item_sum::print(String *str, enum_query_type query_type)
{
  Item **pargs= orig_args;
  str->append(func_name());
  for (uint i=0 ; i < arg_count ; i++)
  {
    if (i)
      str->append(',');
    args[i]->print(str, query_type);
    pargs[i]->print(str, query_type);
  }
  str->append(')');
}
@@ -535,6 +550,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)
{
@@ -586,6 +608,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;
}
@@ -673,6 +696,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;
}
@@ -3141,6 +3165,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 */
@@ -3368,6 +3398,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;
}
+18 −7
Original line number Diff line number Diff line
@@ -228,10 +228,8 @@ class Item_sum :public Item_result_field
    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 @@ class Item_sum :public Item_result_field
  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 @@ class Item_sum :public Item_result_field
  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 @@ class Item_udf_sum : public Item_sum
    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; }
Loading