Commit a220fc48 authored by unknown's avatar unknown
Browse files

Merge olga.mysql.com:/home/igor/mysql-5.0-opt

into  olga.mysql.com:/home/igor/dev-opt/mysql-5.0-opt-bug27229


sql/item.cc:
  Auto merged
sql/item_sum.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
parents 3e6787d3 1f8bdbe4
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -3905,3 +3905,22 @@ COUNT(*) a
2	2
3	3
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4);
INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44);
SELECT COUNT(*) c, a,
(SELECT GROUP_CONCAT(COUNT(a)) FROM t2 WHERE m = a)
FROM t1 GROUP BY a;
c	a	(SELECT GROUP_CONCAT(COUNT(a)) FROM t2 WHERE m = a)
2	2	2
3	3	3
1	4	1,1
SELECT COUNT(*) c, a,
(SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
FROM t1 GROUP BY a;
c	a	(SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
2	2	3
3	3	4
1	4	2,2
DROP table t1,t2;
+19 −0
Original line number Diff line number Diff line
@@ -2763,3 +2763,22 @@ SELECT COUNT(*), a
    HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1;

DROP TABLE t1,t2;

#
# Bug #27229: GROUP_CONCAT in subselect with COUNT() as an argument 
#  

CREATE TABLE t1 (a int, b int);
CREATE TABLE t2 (m int, n int);
INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4);
INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44);

SELECT COUNT(*) c, a,
       (SELECT GROUP_CONCAT(COUNT(a)) FROM t2 WHERE m = a)
  FROM t1 GROUP BY a;

SELECT COUNT(*) c, a,
       (SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
  FROM t1 GROUP BY a;

DROP table t1,t2;
+6 −3
Original line number Diff line number Diff line
@@ -1261,15 +1261,18 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
      Exception is Item_direct_view_ref which we need to convert to
      Item_ref to allow fields from view being stored in tmp table.
    */
    Item_aggregate_ref *item_ref;
    uint el= fields.elements;
    Item *new_item, *real_itm= real_item();
    Item *real_itm= real_item();

    ref_pointer_array[el]= real_itm;
    if (!(new_item= new Item_aggregate_ref(&thd->lex->current_select->context,
    if (!(item_ref= new Item_aggregate_ref(&thd->lex->current_select->context,
                                           ref_pointer_array + el, 0, name)))
      return;                                   // fatal_error is set
    if (type() == SUM_FUNC_ITEM)
      item_ref->depended_from= ((Item_sum *) this)->depended_from(); 
    fields.push_front(real_itm);
    thd->change_item_tree(ref, new_item);
    thd->change_item_tree(ref, item_ref);
  }
}

+18 −15
Original line number Diff line number Diff line
@@ -61,9 +61,9 @@ bool Item_sum::init_sum_func_check(THD *thd)
  /* Save a pointer to object to be used in items for nested set functions */
  thd->lex->in_sum_func= this;
  nest_level= thd->lex->current_select->nest_level;
  nest_level_tables_count= thd->lex->current_select->join->tables;
  ref_by= 0;
  aggr_level= -1;
  aggr_sel= NULL;
  max_arg_level= -1;
  max_sum_func_level= -1;
  return FALSE;
@@ -151,7 +151,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
    invalid= aggr_level < 0 && !(allow_sum_func & (1 << nest_level));
  }
  if (!invalid && aggr_level < 0)
  {
    aggr_level= nest_level;
    aggr_sel= thd->lex->current_select;
  }
  /*
    By this moment we either found a subquery where the set function is
    to be aggregated  and assigned a value that is  >= 0 to aggr_level,
@@ -212,7 +215,6 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
bool Item_sum::register_sum_func(THD *thd, Item **ref)
{
  SELECT_LEX *sl;
  SELECT_LEX *aggr_sl= NULL;
  nesting_map allow_sum_func= thd->lex->allow_sum_func;
  for (sl= thd->lex->current_select->master_unit()->outer_select() ;
       sl && sl->nest_level > max_arg_level;
@@ -222,7 +224,7 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
    {
      /* Found the most nested subquery where the function can be aggregated */
      aggr_level= sl->nest_level;
      aggr_sl= sl;
      aggr_sel= sl;
    }
  }
  if (sl && (allow_sum_func & (1 << sl->nest_level)))
@@ -233,21 +235,22 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
      The set function will be aggregated in this subquery.
    */   
    aggr_level= sl->nest_level;
    aggr_sl= sl;
    aggr_sel= sl;

  }
  if (aggr_level >= 0)
  {
    ref_by= ref;
    /* Add the object to the list of registered objects assigned to aggr_sl */
    if (!aggr_sl->inner_sum_func_list)
    /* Add the object to the list of registered objects assigned to aggr_sel */
    if (!aggr_sel->inner_sum_func_list)
      next= this;
    else
    {
      next= aggr_sl->inner_sum_func_list->next;
      aggr_sl->inner_sum_func_list->next= this;
      next= aggr_sel->inner_sum_func_list->next;
      aggr_sel->inner_sum_func_list->next= this;
    }
    aggr_sl->inner_sum_func_list= this;
    aggr_sl->with_sum_func= 1;
    aggr_sel->inner_sum_func_list= this;
    aggr_sel->with_sum_func= 1;

    /* 
      Mark Item_subselect(s) as containing aggregate function all the way up
@@ -265,11 +268,11 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
      has aggregate functions directly referenced (i.e. not through a sub-select).
    */
    for (sl= thd->lex->current_select; 
         sl && sl != aggr_sl && sl->master_unit()->item;
         sl && sl != aggr_sel && sl->master_unit()->item;
         sl= sl->master_unit()->outer_select() )
      sl->master_unit()->item->with_sum_func= 1;
  }
  thd->lex->current_select->mark_as_dependent(aggr_sl);
  thd->lex->current_select->mark_as_dependent(aggr_sel);
  return FALSE;
}

@@ -299,10 +302,10 @@ 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),
  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),
  forced_const(item->forced_const), 
  nest_level_tables_count(item->nest_level_tables_count)
  forced_const(item->forced_const) 
{
  if (arg_count <= 2)
    args=tmp_args;
@@ -447,7 +450,7 @@ void Item_sum::update_used_tables ()

    /* the aggregate function is aggregated into its local context */
    if (aggr_level == nest_level)
      used_tables_cache |=  (1 << nest_level_tables_count) - 1;
      used_tables_cache |=  (1 << aggr_sel->join->tables) - 1;
  }
}

+3 −1
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ class Item_sum :public Item_result_field
  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 */
  int8 aggr_level;        /* nesting level of the aggregating subquery       */
  int8 max_arg_level;     /* max level of unbound column references          */
@@ -242,7 +243,6 @@ class Item_sum :public Item_result_field
protected:  
  table_map used_tables_cache;
  bool forced_const;
  byte nest_level_tables_count;

public:  

@@ -365,6 +365,8 @@ class Item_sum :public Item_result_field
  bool init_sum_func_check(THD *thd);
  bool check_sum_func(THD *thd, Item **ref);
  bool register_sum_func(THD *thd, Item **ref);
  st_select_lex *depended_from() 
    { return (nest_level == aggr_level ? 0 : aggr_sel); }
};


Loading