Commit ca373395 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 648e6046
......@@ -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
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
whole UNION, and all columns in the subquery are resolved against this table.
Apply the transformation only for immediate child subqueries of a
UNION query.
ORDER BY that is applied to the temporary table that contains the result of
the whole UNION, and all columns in the subquery are resolved against this
table. The transformation is applied only for immediate child subqueries of
a UNION query.
*/
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),
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.
Set the master of the subquery to be the fake select (i.e. the whole
UNION), instead of the last query in the UNION.
*/
unit->set_master(fake_select);
fake_select->add_slave(unit);
DBUG_ASSERT(unit->outer_select() == fake_select);
/* Adjust the name resolution context hierarchy accordingly. */
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
sl->context.outer_context= &(fake_select->context);
......
......@@ -1684,6 +1684,31 @@ void st_select_lex_node::include_down(st_select_lex_node *upper)
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)
......
......@@ -439,10 +439,10 @@ public:
st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {}
virtual ~st_select_lex_node() {}
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_select();
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_standalone(st_select_lex_node *sel, st_select_lex_node **ref);
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