mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
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.
This commit is contained in:
@@ -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)
|
|||||||
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 @@ public:
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user