mirror of
https://github.com/MariaDB/server.git
synced 2026-04-28 11:15:33 +02:00
Patch for Bug#13805127: Stored program cache produces wrong result in same THD.
Background:
- as described in MySQL Internals Prepared Stored
(http://forge.mysql.com/wiki/MySQL_Internals_Prepared_Stored),
the Optimizer sometimes does destructive changes to the parsed
LEX-object (Item-tree), which makes it impossible to re-use
that tree for PS/SP re-execution.
- in order to be able to re-use the Item-tree, the destructive
changes are remembered and rolled back after the statement execution.
The problem, discovered by this bug, was that the objects representing
GROUP-BY clause did not restored after query execution. So, the GROUP-BY
part of the statement could not be properly re-initialized for re-execution
after destructive changes.
Those objects do not take part in the Item-tree, so they can not be saved
using the approach for Item-tree.
The fix is as follows:
- introduce a new array in st_select_lex to store the original
ORDER pointers, representing the GROUP-BY clause;
- Initialize this array in fix_prepare_information().
- restore the list of GROUP-BY items in reinit_stmt_before_use().
This commit is contained in:
parent
d1809a5c85
commit
ed41846161
8 changed files with 485 additions and 2 deletions
|
|
@ -389,6 +389,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= 0;
|
||||
lex->subqueries= FALSE;
|
||||
lex->context_analysis_only= 0;
|
||||
|
|
@ -1773,6 +1775,8 @@ void st_select_lex::init_select()
|
|||
{
|
||||
st_select_lex_node::init_select();
|
||||
group_list.empty();
|
||||
if (group_list_ptrs)
|
||||
group_list_ptrs->clear();
|
||||
type= db= 0;
|
||||
having= 0;
|
||||
table_join_options= 0;
|
||||
|
|
@ -3100,6 +3104,8 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
|
|||
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.
|
||||
|
|
@ -3111,6 +3117,19 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
|
|||
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;
|
||||
|
|
@ -3362,3 +3381,7 @@ void binlog_unsafe_map_init()
|
|||
BINLOG_DIRECT_OFF & TRX_CACHE_NOT_EMPTY);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||
template class Mem_root_array<ORDER*, true>;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue