#At file:///export/home/didrik/repo/trunk-bug11766429-prep-having/ based on revid:alexander.nozdrin@stripped
3185 Tor Didriksen 2011-06-10
Bug#11766429 - 59533: RE-EXECUTE OF PREPARED STATEMENT CRASHES IN ITEM_REF::FIX_FIELDS WITH
The second element of the GROUP BY list was const, and removed by remove_const.
Solution: re-establish the list before second execution.
@ sql/sql_lex.cc
Add group_list_ptrs to remember the group_by list next pointers.
@ sql/sql_lex.h
Add group_list_ptrs to remember the group_by list next pointers.
@ sql/sql_prepare.cc
Re-establish group_list in reinit_stmt_before_use()
modified:
mysql-test/r/group_by.result
mysql-test/t/group_by.test
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_prepare.cc
=== modified file 'mysql-test/r/group_by.result'
--- a/mysql-test/r/group_by.result 2011-05-26 05:50:01 +0000
+++ b/mysql-test/r/group_by.result 2011-06-10 09:52:57 +0000
@@ -1967,3 +1967,23 @@ field1 field2
DROP TABLE t1;
DROP TABLE where_subselect;
# End of Bug #58782
+#
+# Bug #11766429
+# RE-EXECUTE OF PREPARED STATEMENT CRASHES IN ITEM_REF::FIX_FIELDS WITH
+#
+CREATE TABLE t1(a INT, KEY(a));
+INSERT INTO t1 VALUES (0);
+CREATE TABLE t2(b INT, KEY(b));
+INSERT INTO t2 VALUES (0),(0);
+PREPARE stmt FROM '
+SELECT 1 FROM t2
+LEFT JOIN t1 ON NULL
+GROUP BY t2.b, t1.a
+HAVING a <> 2';
+EXECUTE stmt;
+1
+EXECUTE stmt;
+1
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
+# End of Bug #11766429
=== modified file 'mysql-test/t/group_by.test'
--- a/mysql-test/t/group_by.test 2011-02-18 10:59:18 +0000
+++ b/mysql-test/t/group_by.test 2011-06-10 09:52:57 +0000
@@ -1359,3 +1359,26 @@ DROP TABLE t1;
DROP TABLE where_subselect;
--echo # End of Bug #58782
+
+--echo #
+--echo # Bug #11766429
+--echo # RE-EXECUTE OF PREPARED STATEMENT CRASHES IN ITEM_REF::FIX_FIELDS WITH
+--echo #
+
+CREATE TABLE t1(a INT, KEY(a));
+INSERT INTO t1 VALUES (0);
+CREATE TABLE t2(b INT, KEY(b));
+INSERT INTO t2 VALUES (0),(0);
+
+PREPARE stmt FROM '
+SELECT 1 FROM t2
+LEFT JOIN t1 ON NULL
+GROUP BY t2.b, t1.a
+HAVING a <> 2';
+EXECUTE stmt;
+EXECUTE stmt;
+
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
+
+--echo # End of Bug #11766429
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2011-05-26 15:20:09 +0000
+++ b/sql/sql_lex.cc 2011-06-10 09:52:57 +0000
@@ -380,6 +380,8 @@ void lex_start(THD *thd)
lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
lex->select_lex.init_order();
lex->select_lex.group_list.empty();
+ if (lex->select_lex.group_list_ptrs)
+ lex->select_lex.group_list_ptrs->clear();
lex->describe= DESCRIBE_NONE;
lex->subqueries= FALSE;
lex->context_analysis_only= 0;
@@ -1776,6 +1778,8 @@ void st_select_lex::init_select()
st_select_lex_node::init_select();
sj_nests.empty();
group_list.empty();
+ if (group_list_ptrs)
+ group_list_ptrs->clear();
type= db= 0;
having= 0;
table_join_options= 0;
@@ -3059,6 +3063,8 @@ static void fix_prepare_info_in_table_li
The passed WHERE and HAVING are to be saved for the future executions.
This function saves it, and returns a copy which can be thrashed during
this execution of the statement. By saving/thrashing here we mean only
+ We also save the chain of ORDER::next in group_list, in case
+ the list is modified by remove_const().
AND/OR trees.
The function also calls fix_prepare_info_in_table_list that saves all
ON expressions.
@@ -3070,6 +3076,19 @@ void st_select_lex::fix_prepare_informat
if (!thd->stmt_arena->is_conventional() && first_execution)
{
first_execution= 0;
+ if (group_list.first)
+ {
+ if (!group_list_ptrs)
+ {
+ void *mem= thd->stmt_arena->alloc(sizeof(Group_list_ptrs));
+ group_list_ptrs= new (mem) Group_list_ptrs(thd->stmt_arena->mem_root);
+ }
+ group_list_ptrs->reserve(group_list.elements);
+ for (ORDER *order= group_list.first; order; order= order->next)
+ {
+ group_list_ptrs->push_back(order);
+ }
+ }
if (*conds)
{
prep_where= *conds;
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2011-05-12 17:29:19 +0000
+++ b/sql/sql_lex.h 2011-06-10 09:52:57 +0000
@@ -24,6 +24,7 @@
#include "sql_trigger.h"
#include "item.h" /* From item_subselect.h: subselect_union_engine */
#include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */
+#include "mem_root_array.h"
/* YACC and LEX Definitions */
@@ -185,6 +186,7 @@ enum enum_drop_mode
#define TL_OPTION_ALIAS 8
typedef List<Item> List_item;
+typedef Mem_root_array<ORDER*, true> Group_list_ptrs;
/* SERVERS CACHE CHANGES */
typedef struct st_lex_server_options
@@ -628,7 +630,16 @@ public:
enum olap_type olap;
/* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */
SQL_I_List<TABLE_LIST> table_list;
- SQL_I_List<ORDER> group_list; /* GROUP BY clause. */
+
+ /*
+ GROUP BY clause.
+ This list may be mutated during optimization (by remove_const()),
+ so for prepared statements, we keep a copy of the ORDER.next pointers in
+ group_list_ptrs, and re-establish the original list before each execution.
+ */
+ SQL_I_List<ORDER> group_list;
+ Group_list_ptrs *group_list_ptrs;
+
List<Item> item_list; /* list of fields & expressions */
List<String> interval_list;
bool is_item_list_lookup;
@@ -819,7 +830,8 @@ public:
bool test_limit();
friend void lex_start(THD *thd);
- st_select_lex() : n_sum_items(0), n_child_sum_items(0) {}
+ st_select_lex() : group_list_ptrs(NULL), n_sum_items(0), n_child_sum_items(0)
+ {}
void make_empty_select()
{
init_query();
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2011-06-10 07:49:17 +0000
+++ b/sql/sql_prepare.cc 2011-06-10 09:52:57 +0000
@@ -2428,6 +2428,14 @@ void reinit_stmt_before_use(THD *thd, LE
DBUG_ASSERT(sl->join == 0);
ORDER *order;
/* Fix GROUP list */
+ if (sl->group_list_ptrs && sl->group_list_ptrs->size() > 0)
+ {
+ for (uint ix= 0; ix < sl->group_list_ptrs->size() - 1; ++ix)
+ {
+ order= sl->group_list_ptrs->at(ix);
+ order->next= sl->group_list_ptrs->at(ix+1);
+ }
+ }
for (order= sl->group_list.first; order; order= order->next)
order->item= &order->item_ptr;
/* Fix ORDER list */
Attachment: [text/bzr-bundle] bzr/tor.didriksen@oracle.com-20110610095257-ulh6hd2evlxkkx6d.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk branch (tor.didriksen:3185) Bug#11766429 | Tor Didriksen | 10 Jun |