Below is the list of changes that have just been committed into a local
5.0 repository of igor. When igor does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-03-21 21:31:39-07:00, igor@stripped +9 -0
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Ensured correct setting of the depended_from field in references
generated for set functions aggregated in outer selects.
A wrong value of this field resulted in wrong maps returned by
used_tables() for these references.
Made sure that a temporary table field is added for any set function
aggregated in outer context when creation of a temporary table is
needed to execute the inner subquery.
mysql-test/r/subselect.result@stripped, 2007-03-21 21:31:34-07:00, igor@stripped +19 -0
Added a test case for bug #27229.
mysql-test/t/subselect.test@stripped, 2007-03-21 21:31:34-07:00, igor@stripped +19 -0
Added a test case for bug #27229.
sql/item.cc@stripped, 2007-03-21 21:31:34-07:00, igor@stripped +5 -3
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Ensured correct setting of the depended_from field in references
generated for set functions aggregated in outer selects.
sql/item_sum.cc@stripped, 2007-03-21 21:31:34-07:00, igor@stripped +17 -14
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Added the field aggr_sel to the objects of the class Item_sum.
In any Item_sum object created for a set function this field
has to contain a pointer to the select where the set function
is aggregated.
sql/item_sum.h@stripped, 2007-03-21 21:31:34-07:00, igor@stripped +3 -1
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Added the field aggr_sel to the objects of the class Item_sum.
In any Item_sum object created for a set function this field
has to contain a pointer to the select where the set function
is aggregated.
Added a method that says whether a set function is aggregated
in outer context and, if so, returns the aggregating select.
Removed the field nest_level_tables_count introduced by the
patch for bug 24484 as aggr_sel->join->tables contains the
sane number.
sql/sql_base.cc@stripped, 2007-03-21 21:31:35-07:00, igor@stripped +0 -2
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Added the field aggr_sel to the objects of the class Item_sum.
Removed changes introduced by the patch for bug 24484 as
the field leaf_count of the THD class is not used anymore.
sql/sql_class.h@stripped, 2007-03-21 21:31:35-07:00, igor@stripped +0 -3
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Added the field aggr_sel to the objects of the class Item_sum.
Removed changes introduce by the patch for bug 24484 as
the field leaf_count of the THD class is not used anymore.
sql/sql_insert.cc@stripped, 2007-03-21 21:31:35-07:00, igor@stripped +2 -4
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
Added the field aggr_sel to the objects of the class Item_sum.
Removed changes introduce by the patch for bug 24484 as
the field leaf_count of the THD class is not used anymore.
sql/sql_select.cc@stripped, 2007-03-21 21:31:35-07:00, igor@stripped +9 -2
Fixed bug #27229: crash when a set function aggregated in outer
context was used as an argument of GROUP_CONCAT.
When creating a temporary table a field is added in it for any
set function aggregated in outer context.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: igor
# Host: olga.mysql.com
# Root: /home/igor/dev-opt/mysql-5.0-opt-bug27229
--- 1.256/sql/item.cc 2007-03-21 21:31:45 -07:00
+++ 1.257/sql/item.cc 2007-03-21 21:31:45 -07:00
@@ -1261,15 +1261,17 @@
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
+ 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);
}
}
--- 1.198/sql/item_sum.cc 2007-03-21 21:31:45 -07:00
+++ 1.199/sql/item_sum.cc 2007-03-21 21:31:45 -07:00
@@ -61,9 +61,9 @@
/* 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 @@
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::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 @@
{
/* 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 @@
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)
+ 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 @@
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(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 @@
/* 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;
}
}
--- 1.111/sql/item_sum.h 2007-03-21 21:31:45 -07:00
+++ 1.112/sql/item_sum.h 2007-03-21 21:31:45 -07:00
@@ -233,6 +233,7 @@
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 @@
protected:
table_map used_tables_cache;
bool forced_const;
- byte nest_level_tables_count;
public:
@@ -365,6 +365,8 @@
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); }
};
--- 1.371/sql/sql_base.cc 2007-03-21 21:31:45 -07:00
+++ 1.372/sql/sql_base.cc 2007-03-21 21:31:45 -07:00
@@ -4864,7 +4864,6 @@
TABLE_LIST *leaves_tmp = NULL;
bool first_table= true;
- thd->leaf_count= 0;
if (setup_tables (thd, context, from_clause, tables, conds,
&leaves_tmp, select_insert))
return TRUE;
@@ -4882,7 +4881,6 @@
return TRUE;
}
first_table= false;
- thd->leaf_count++;
}
return FALSE;
}
--- 1.326/sql/sql_class.h 2007-03-21 21:31:45 -07:00
+++ 1.327/sql/sql_class.h 2007-03-21 21:31:45 -07:00
@@ -1492,9 +1492,6 @@
query_id_t first_query_id;
} binlog_evt_union;
- /* pass up the count of "leaf" tables in a JOIN out of setup_tables() */
- byte leaf_count;
-
THD();
~THD();
--- 1.226/sql/sql_insert.cc 2007-03-21 21:31:45 -07:00
+++ 1.227/sql/sql_insert.cc 2007-03-21 21:31:45 -07:00
@@ -2349,14 +2349,12 @@
DBUG_ASSERT(select_lex->leaf_tables != 0);
lex->leaf_tables_insert= select_lex->leaf_tables;
/* skip all leaf tables belonged to view where we are insert */
- for (first_select_leaf_table= select_lex->leaf_tables->next_leaf,
- thd->leaf_count --;
+ for (first_select_leaf_table= select_lex->leaf_tables->next_leaf;
first_select_leaf_table &&
first_select_leaf_table->belong_to_view &&
first_select_leaf_table->belong_to_view ==
lex->leaf_tables_insert->belong_to_view;
- first_select_leaf_table= first_select_leaf_table->next_leaf,
- thd->leaf_count --)
+ first_select_leaf_table= first_select_leaf_table->next_leaf)
{}
select_lex->leaf_tables= first_select_leaf_table;
DBUG_RETURN(FALSE);
--- 1.499/sql/sql_select.cc 2007-03-21 21:31:45 -07:00
+++ 1.500/sql/sql_select.cc 2007-03-21 21:31:46 -07:00
@@ -412,7 +412,12 @@
&select_lex->leaf_tables, FALSE,
SELECT_ACL, SELECT_ACL))
DBUG_RETURN(-1);
- tables= thd->leaf_count;
+
+ TABLE_LIST *table_ptr;
+ for (table_ptr= select_lex->leaf_tables;
+ table_ptr;
+ table_ptr= table_ptr->next_leaf)
+ tables++;
if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) ||
@@ -9186,7 +9191,9 @@
Item::Type type=item->type();
if (not_all_columns)
{
- if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
+ if (item->with_sum_func && type != Item::SUM_FUNC_ITEM &&
+ (type == Item::SUBSELECT_ITEM ||
+ (item->used_tables() & ~PSEUDO_TABLE_BITS)))
{
/*
Mark that the we have ignored an item that refers to a summary
--- 1.180/mysql-test/r/subselect.result 2007-03-21 21:31:46 -07:00
+++ 1.181/mysql-test/r/subselect.result 2007-03-21 21:31:46 -07:00
@@ -3905,3 +3905,22 @@
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;
--- 1.145/mysql-test/t/subselect.test 2007-03-21 21:31:46 -07:00
+++ 1.146/mysql-test/t/subselect.test 2007-03-21 21:31:46 -07:00
@@ -2763,3 +2763,22 @@
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;
| Thread |
|---|
| • bk commit into 5.0 tree (igor:1.2489) BUG#27229 | igor | 22 Mar |