#At file:///work/bzr/mysql-5.0-bugteam/ based on revid:joro@stripped
2721 Gleb Shchepa 2009-04-01
Backport bug #37348 fix 5.1 --> 5.0.
Original commentary:
Bug #37348: Crash in or immediately after JOIN::make_sum_func_list
The optimizer pulls up aggregate functions which should be aggregated in
an outer select. At some point it may substitute such a function for a field
in the temporary table. The setup_copy_fields function doesn't take this
into account and may overrun the copy_field buffer.
Fixed by filtering out the fields referenced through the specialized
reference for aggregates (Item_aggregate_ref).
Added an assertion to make sure bugs that cause similar discrepancy
don't go undetected.
modified:
mysql-test/r/func_group.result
mysql-test/t/func_group.test
sql/item.cc
sql/item.h
sql/sql_select.cc
per-file messages:
mysql-test/r/func_group.result
Backport bug #37348 fix 5.1 --> 5.0.
mysql-test/t/func_group.test
Backport bug #37348 fix 5.1 --> 5.0.
sql/item.cc
Backport bug #37348 fix 5.1 --> 5.0.
sql/item.h
Backport bug #37348 fix 5.1 --> 5.0.
sql/sql_select.cc
Backport bug #37348 fix 5.1 --> 5.0.
=== modified file 'mysql-test/r/func_group.result'
--- a/mysql-test/r/func_group.result 2009-01-28 17:59:08 +0000
+++ b/mysql-test/r/func_group.result 2009-04-01 11:02:26 +0000
@@ -1448,4 +1448,41 @@ COUNT(*)
0
SET SQL_MODE=default;
DROP TABLE t1;
+CREATE TABLE derived1 (a bigint(21));
+INSERT INTO derived1 VALUES (2);
+CREATE TABLE D (
+pk int(11) NOT NULL AUTO_INCREMENT,
+int_nokey int(11) DEFAULT NULL,
+int_key int(11) DEFAULT NULL,
+filler blob,
+PRIMARY KEY (pk),
+KEY int_key (int_key)
+);
+INSERT INTO D VALUES
+(39,40,4,repeat(' X', 42)),
+(43,56,4,repeat(' X', 42)),
+(47,12,4,repeat(' X', 42)),
+(71,28,4,repeat(' X', 42)),
+(76,54,4,repeat(' X', 42)),
+(83,45,4,repeat(' X', 42)),
+(105,53,12,NULL);
+SELECT
+(SELECT COUNT( int_nokey )
+FROM derived1 AS X
+WHERE
+X.int_nokey < 61
+GROUP BY pk
+LIMIT 1)
+FROM D AS X
+WHERE X.int_key < 13
+GROUP BY int_nokey LIMIT 1;
+(SELECT COUNT( int_nokey )
+FROM derived1 AS X
+WHERE
+X.int_nokey < 61
+GROUP BY pk
+LIMIT 1)
+1
+DROP TABLE derived1;
+DROP TABLE D;
End of 5.0 tests
=== modified file 'mysql-test/t/func_group.test'
--- a/mysql-test/t/func_group.test 2008-11-24 15:30:47 +0000
+++ b/mysql-test/t/func_group.test 2009-04-01 11:02:26 +0000
@@ -955,5 +955,45 @@ SET SQL_MODE=default;
DROP TABLE t1;
+#
+# Bug #37348: Crash in or immediately after JOIN::make_sum_func_list
+#
+
+CREATE TABLE derived1 (a bigint(21));
+INSERT INTO derived1 VALUES (2);
+
+
+CREATE TABLE D (
+ pk int(11) NOT NULL AUTO_INCREMENT,
+ int_nokey int(11) DEFAULT NULL,
+ int_key int(11) DEFAULT NULL,
+ filler blob,
+ PRIMARY KEY (pk),
+ KEY int_key (int_key)
+);
+
+INSERT INTO D VALUES
+ (39,40,4,repeat(' X', 42)),
+ (43,56,4,repeat(' X', 42)),
+ (47,12,4,repeat(' X', 42)),
+ (71,28,4,repeat(' X', 42)),
+ (76,54,4,repeat(' X', 42)),
+ (83,45,4,repeat(' X', 42)),
+ (105,53,12,NULL);
+
+SELECT
+ (SELECT COUNT( int_nokey )
+ FROM derived1 AS X
+ WHERE
+ X.int_nokey < 61
+ GROUP BY pk
+ LIMIT 1)
+FROM D AS X
+WHERE X.int_key < 13
+GROUP BY int_nokey LIMIT 1;
+
+DROP TABLE derived1;
+DROP TABLE D;
+
###
--echo End of 5.0 tests
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2009-03-27 12:58:34 +0000
+++ b/sql/item.cc 2009-04-01 11:02:26 +0000
@@ -1323,6 +1323,7 @@ public:
else
Item_ident::print(str);
}
+ virtual Ref_Type ref_type() { return AGGREGATE_REF; }
};
=== modified file 'sql/item.h'
--- a/sql/item.h 2009-02-19 13:20:44 +0000
+++ b/sql/item.h 2009-04-01 11:02:26 +0000
@@ -1899,7 +1899,7 @@ class Item_ref :public Item_ident
protected:
void set_properties();
public:
- enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF };
+ enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */
Item **ref;
Item_ref(Name_resolution_context *context_arg,
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2009-03-19 13:44:58 +0000
+++ b/sql/sql_select.cc 2009-04-01 11:02:26 +0000
@@ -14205,6 +14205,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
Item *pos;
List_iterator_fast<Item> li(all_fields);
Copy_field *copy= NULL;
+ IF_DBUG(Copy_field *copy_start);
res_selected_fields.empty();
res_all_fields.empty();
List_iterator_fast<Item> itr(res_all_fields);
@@ -14217,12 +14218,19 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
goto err2;
param->copy_funcs.empty();
+ IF_DBUG(copy_start= copy);
for (i= 0; (pos= li++); i++)
{
Field *field;
char *tmp;
Item *real_pos= pos->real_item();
- if (real_pos->type() == Item::FIELD_ITEM)
+ /*
+ Aggregate functions can be substituted for fields (by e.g. temp tables).
+ We need to filter those substituted fields out.
+ */
+ if (real_pos->type() == Item::FIELD_ITEM &&
+ !(real_pos != pos &&
+ ((Item_ref *)pos)->ref_type() == Item_ref::AGGREGATE_REF))
{
Item_field *item;
if (!(item= new Item_field(thd, ((Item_field*) real_pos))))
@@ -14270,6 +14278,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
goto err;
if (copy)
{
+ DBUG_ASSERT (param->field_count > (uint) (copy - copy_start));
copy->set(tmp, item->result_field);
item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
#ifdef HAVE_purify
Thread |
---|
• bzr commit into mysql-5.0-bugteam branch (gshchepa:2721) Bug#37348 | Gleb Shchepa | 1 Apr |