Fixed bug #21493: crash for the second execution of a function
containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. Saved andor structure of the having conditions at the proper moment before any calls of split_sum_func2 that could modify the having structure adding new Item_ref objects. (These additions, are produced not with the statement mem_root, but rather with the execution mem_root.)
This commit is contained in:
parent
aa7ae80509
commit
d3d3cef88c
@ -5256,4 +5256,67 @@ a
|
||||
1
|
||||
use test|
|
||||
drop table t3|
|
||||
CREATE TABLE t3 (
|
||||
Member_ID varchar(15) NOT NULL,
|
||||
PRIMARY KEY (Member_ID)
|
||||
)|
|
||||
CREATE TABLE t4 (
|
||||
ID int(10) unsigned NOT NULL auto_increment,
|
||||
Member_ID varchar(15) NOT NULL default '',
|
||||
Action varchar(12) NOT NULL,
|
||||
Action_Date datetime NOT NULL,
|
||||
Track varchar(15) default NULL,
|
||||
User varchar(12) default NULL,
|
||||
Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
|
||||
CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (ID),
|
||||
KEY Action (Action),
|
||||
KEY Action_Date (Action_Date)
|
||||
)|
|
||||
INSERT INTO t3(Member_ID) VALUES
|
||||
('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')|
|
||||
INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES
|
||||
('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||
('111111', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||
('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
|
||||
('222222', 'Enrolled', '2006-03-07', 'CAD' ),
|
||||
('222222', 'Enrolled', '2006-03-07', 'CHF' ),
|
||||
('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
|
||||
('333333', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||
('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||
('444444', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||
('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||
('555555', 'Enrolled', '2006-07-21', 'CAD' ),
|
||||
('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
|
||||
('666666', 'Enrolled', '2006-02-09', 'CAD' ),
|
||||
('666666', 'Enrolled', '2006-05-12', 'CHF' ),
|
||||
('666666', 'Disenrolled', '2006-06-01', 'CAD' )|
|
||||
DROP FUNCTION IF EXISTS bug21493|
|
||||
Warnings:
|
||||
Note 1305 FUNCTION bug21493 does not exist
|
||||
CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45)
|
||||
BEGIN
|
||||
DECLARE tracks VARCHAR(45);
|
||||
SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4
|
||||
WHERE Member_ID=paramMember AND Action='Enrolled' AND
|
||||
(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4
|
||||
WHERE Member_ID=paramMember GROUP BY Track);
|
||||
RETURN tracks;
|
||||
END|
|
||||
SELECT bug21493('111111')|
|
||||
bug21493('111111')
|
||||
NULL
|
||||
SELECT bug21493('222222')|
|
||||
bug21493('222222')
|
||||
CAD
|
||||
SELECT bug21493(Member_ID) FROM t3|
|
||||
bug21493(Member_ID)
|
||||
NULL
|
||||
CAD
|
||||
CAD
|
||||
CAD
|
||||
CAD
|
||||
CHF
|
||||
DROP FUNCTION bug21493|
|
||||
DROP TABLE t3,t4|
|
||||
drop table t1,t2;
|
||||
|
@ -6188,6 +6188,73 @@ select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2|
|
||||
use test|
|
||||
drop table t3|
|
||||
|
||||
#
|
||||
# BUG#21493: Crash on the second call of a procedure containing
|
||||
# a select statement that uses an IN aggregating subquery
|
||||
#
|
||||
|
||||
CREATE TABLE t3 (
|
||||
Member_ID varchar(15) NOT NULL,
|
||||
PRIMARY KEY (Member_ID)
|
||||
)|
|
||||
|
||||
CREATE TABLE t4 (
|
||||
ID int(10) unsigned NOT NULL auto_increment,
|
||||
Member_ID varchar(15) NOT NULL default '',
|
||||
Action varchar(12) NOT NULL,
|
||||
Action_Date datetime NOT NULL,
|
||||
Track varchar(15) default NULL,
|
||||
User varchar(12) default NULL,
|
||||
Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
|
||||
CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (ID),
|
||||
KEY Action (Action),
|
||||
KEY Action_Date (Action_Date)
|
||||
)|
|
||||
|
||||
|
||||
INSERT INTO t3(Member_ID) VALUES
|
||||
('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')|
|
||||
|
||||
INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES
|
||||
('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||
('111111', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||
('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
|
||||
('222222', 'Enrolled', '2006-03-07', 'CAD' ),
|
||||
('222222', 'Enrolled', '2006-03-07', 'CHF' ),
|
||||
('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
|
||||
('333333', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||
('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||
('444444', 'Enrolled', '2006-03-01', 'CAD' ),
|
||||
('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
|
||||
('555555', 'Enrolled', '2006-07-21', 'CAD' ),
|
||||
('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
|
||||
('666666', 'Enrolled', '2006-02-09', 'CAD' ),
|
||||
('666666', 'Enrolled', '2006-05-12', 'CHF' ),
|
||||
('666666', 'Disenrolled', '2006-06-01', 'CAD' )|
|
||||
|
||||
#--disable_warnings
|
||||
DROP FUNCTION IF EXISTS bug21493|
|
||||
#--enable_warnings
|
||||
|
||||
CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45)
|
||||
BEGIN
|
||||
DECLARE tracks VARCHAR(45);
|
||||
SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4
|
||||
WHERE Member_ID=paramMember AND Action='Enrolled' AND
|
||||
(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4
|
||||
WHERE Member_ID=paramMember GROUP BY Track);
|
||||
RETURN tracks;
|
||||
END|
|
||||
|
||||
SELECT bug21493('111111')|
|
||||
SELECT bug21493('222222')|
|
||||
|
||||
SELECT bug21493(Member_ID) FROM t3|
|
||||
|
||||
DROP FUNCTION bug21493|
|
||||
DROP TABLE t3,t4|
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
@ -342,6 +342,7 @@ cleanup:
|
||||
*/
|
||||
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
||||
{
|
||||
Item *fake_conds= 0;
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
DBUG_ENTER("mysql_prepare_delete");
|
||||
|
||||
@ -367,7 +368,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
select_lex->fix_prepare_information(thd, conds);
|
||||
select_lex->fix_prepare_information(thd, conds, &fake_conds);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
@ -993,7 +993,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
update_non_unique_table_error(table_list, "INSERT", duplicate);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
select_lex->fix_prepare_information(thd, &fake_conds);
|
||||
select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds);
|
||||
select_lex->first_execution= 0;
|
||||
}
|
||||
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
|
||||
|
@ -2155,15 +2155,25 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
|
||||
|
||||
|
||||
/*
|
||||
fix some structures at the end of preparation
|
||||
Save WHERE/HAVING/ON clauses and replace them with disposable copies
|
||||
|
||||
SYNOPSIS
|
||||
st_select_lex::fix_prepare_information
|
||||
thd thread handler
|
||||
conds pointer on conditions which will be used for execution statement
|
||||
thd thread handler
|
||||
conds in/out pointer to WHERE condition to be met at execution
|
||||
having_conds in/out pointer to HAVING condition to be met at execution
|
||||
|
||||
DESCRIPTION
|
||||
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
|
||||
AND/OR trees.
|
||||
The function also calls fix_prepare_info_in_table_list that saves all
|
||||
ON expressions.
|
||||
*/
|
||||
|
||||
void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
|
||||
void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
|
||||
Item **having_conds)
|
||||
{
|
||||
if (!thd->stmt_arena->is_conventional() && first_execution)
|
||||
{
|
||||
@ -2173,6 +2183,11 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
|
||||
prep_where= *conds;
|
||||
*conds= where= prep_where->copy_andor_structure(thd);
|
||||
}
|
||||
if (*having_conds)
|
||||
{
|
||||
prep_having= *having_conds;
|
||||
*having_conds= having= prep_having->copy_andor_structure(thd);
|
||||
}
|
||||
fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first);
|
||||
}
|
||||
}
|
||||
|
@ -656,7 +656,7 @@ public:
|
||||
void print(THD *thd, String *str);
|
||||
static void print_order(String *str, ORDER *order);
|
||||
void print_limit(THD *thd, String *str);
|
||||
void fix_prepare_information(THD *thd, Item **conds);
|
||||
void fix_prepare_information(THD *thd, Item **conds, Item **having_conds);
|
||||
/*
|
||||
Destroy the used execution plan (JOIN) of this subtree (this
|
||||
SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs).
|
||||
|
@ -382,12 +382,14 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
if ((res= subselect->select_transformer(this)) !=
|
||||
Item_subselect::RES_OK)
|
||||
{
|
||||
select_lex->fix_prepare_information(thd, &conds);
|
||||
select_lex->fix_prepare_information(thd, &conds, &having);
|
||||
DBUG_RETURN((res == Item_subselect::RES_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select_lex->fix_prepare_information(thd, &conds, &having);
|
||||
|
||||
if (having && having->with_sum_func)
|
||||
having->split_sum_func2(thd, ref_pointer_array, all_fields,
|
||||
&having, TRUE);
|
||||
@ -499,7 +501,6 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
if (alloc_func_list())
|
||||
goto err;
|
||||
|
||||
select_lex->fix_prepare_information(thd, &conds);
|
||||
DBUG_RETURN(0); // All OK
|
||||
|
||||
err:
|
||||
@ -618,7 +619,6 @@ JOIN::optimize()
|
||||
build_bitmap_for_nested_joins(join_list, 0);
|
||||
|
||||
sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
|
||||
sel->prep_having= having ? having->copy_andor_structure(thd) : 0;
|
||||
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
@ -606,6 +606,7 @@ err:
|
||||
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
Item **conds, uint order_num, ORDER *order)
|
||||
{
|
||||
Item *fake_conds= 0;
|
||||
TABLE *table= table_list->table;
|
||||
TABLE_LIST tables;
|
||||
List<Item> all_fields;
|
||||
@ -645,7 +646,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
select_lex->fix_prepare_information(thd, conds);
|
||||
select_lex->fix_prepare_information(thd, conds, &fake_conds);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user