Commit ccd69427 authored by unknown's avatar unknown

MWL#89

Fixed a memory leak found by valgrind. The memory leak was
a result of JOINs corresponding to subselects in a global
ORDER BY of a UNION not being cleaned up because the
fake_select of the UNION didn't point down to the subquery
select.
parent 090b4a10
...@@ -326,23 +326,19 @@ bool Item_subselect::set_fake_select_as_master_processor(uchar *arg) ...@@ -326,23 +326,19 @@ bool Item_subselect::set_fake_select_as_master_processor(uchar *arg)
/* /*
Move the st_select_lex_unit of a subquery from a global ORDER BY clause to Move the st_select_lex_unit of a subquery from a global ORDER BY clause to
become a direct child of the fake_select of a UNION. In this way the become a direct child of the fake_select of a UNION. In this way the
ORDER BY is applied to the temporary table that contains the result of the ORDER BY that is applied to the temporary table that contains the result of
whole UNION, and all columns in the subquery are resolved against this table. the whole UNION, and all columns in the subquery are resolved against this
table. The transformation is applied only for immediate child subqueries of
Apply the transformation only for immediate child subqueries of a a UNION query.
UNION query.
*/ */
if (unit->outer_select()->master_unit()->fake_select_lex == fake_select) if (unit->outer_select()->master_unit()->fake_select_lex == fake_select)
{ {
/* /*
Set the master of the subquery to be the fake select (i.e. the whole UNION), Set the master of the subquery to be the fake select (i.e. the whole
instead of the last query in the UNION. UNION), instead of the last query in the UNION.
TODO:
This is a hack, instead we should call: unit->include_down(fake_select);
However, this call results in an infinite loop where
some_select_lex->master == some_select_lex.
*/ */
unit->set_master(fake_select); fake_select->add_slave(unit);
DBUG_ASSERT(unit->outer_select() == fake_select);
/* Adjust the name resolution context hierarchy accordingly. */ /* Adjust the name resolution context hierarchy accordingly. */
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
sl->context.outer_context= &(fake_select->context); sl->context.outer_context= &(fake_select->context);
......
...@@ -1684,6 +1684,31 @@ void st_select_lex_node::include_down(st_select_lex_node *upper) ...@@ -1684,6 +1684,31 @@ void st_select_lex_node::include_down(st_select_lex_node *upper)
slave= 0; slave= 0;
} }
void st_select_lex_node::add_slave(st_select_lex_node *slave_arg)
{
for (; slave; slave= slave->next)
if (slave == slave_arg)
return;
if (slave)
{
st_select_lex_node *slave_arg_slave= slave_arg->slave;
/* Insert in the front of list of slaves if any. */
slave_arg->include_neighbour(slave);
/* include_neighbour() sets slave_arg->slave=0, restore it. */
slave_arg->slave= slave_arg_slave;
/* Count on include_neighbour() setting the master. */
DBUG_ASSERT(slave_arg->master == this);
}
else
{
slave= slave_arg;
slave_arg->master= this;
}
}
/* /*
include on level down (but do not link) include on level down (but do not link)
......
...@@ -439,10 +439,10 @@ class st_select_lex_node { ...@@ -439,10 +439,10 @@ class st_select_lex_node {
st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {} st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {}
virtual ~st_select_lex_node() {} virtual ~st_select_lex_node() {}
inline st_select_lex_node* get_master() { return master; } inline st_select_lex_node* get_master() { return master; }
inline void set_master(st_select_lex_node* master_arg) { master= master_arg; }
virtual void init_query(); virtual void init_query();
virtual void init_select(); virtual void init_select();
void include_down(st_select_lex_node *upper); void include_down(st_select_lex_node *upper);
void add_slave(st_select_lex_node *slave_arg);
void include_neighbour(st_select_lex_node *before); void include_neighbour(st_select_lex_node *before);
void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref); void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref);
void include_global(st_select_lex_node **plink); void include_global(st_select_lex_node **plink);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment