mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fixed bug mdev-277 as part of the fix for lp:944706
The cause for this bug is that the method JOIN::get_examined_rows iterates over all JOIN_TABs of the join assuming they are just a sequence. In the query above, the innermost subquery is merged into its parent query. When we call JOIN::get_examined_rows for the second-level subquery, the iteration that assumes sequential order of join tabs goes outside the join_tab array and calls the method JOIN_TAB::get_examined_rows on uninitialized memory. The fix is to iterate over JOIN_TABs in a way that takes into account the nested semi-join structure of JOIN_TABs. In particular iterate as select_describe.
This commit is contained in:
@ -270,6 +270,8 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
|
||||
bool *inherited_fl);
|
||||
JOIN_TAB *first_depth_first_tab(JOIN* join);
|
||||
JOIN_TAB *next_depth_first_tab(JOIN* join, JOIN_TAB* tab);
|
||||
JOIN_TAB *first_breadth_first_tab(JOIN *join);
|
||||
JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab);
|
||||
|
||||
/**
|
||||
This handles SELECT with and without UNION.
|
||||
@ -6615,19 +6617,18 @@ void JOIN::get_prefix_cost_and_fanout(uint n_tables,
|
||||
|
||||
double JOIN::get_examined_rows()
|
||||
{
|
||||
/* Each constant table examines one row, and the result is at most one row. */
|
||||
ha_rows examined_rows= const_tables;
|
||||
uint i= const_tables;
|
||||
ha_rows examined_rows;
|
||||
double prev_fanout= 1;
|
||||
JOIN_TAB *tab= first_breadth_first_tab(this);
|
||||
JOIN_TAB *prev_tab= tab;
|
||||
|
||||
if (table_count == const_tables)
|
||||
return examined_rows;
|
||||
examined_rows= tab->get_examined_rows();
|
||||
|
||||
examined_rows+= join_tab[i++].get_examined_rows();
|
||||
for (; i < table_count ; i++)
|
||||
while ((tab= next_breadth_first_tab(this, tab)))
|
||||
{
|
||||
prev_fanout *= best_positions[i-1].records_read;
|
||||
examined_rows+= join_tab[i].get_examined_rows() * prev_fanout;
|
||||
prev_fanout *= prev_tab->records_read;
|
||||
examined_rows+= tab->get_examined_rows() * prev_fanout;
|
||||
prev_tab= tab;
|
||||
}
|
||||
return examined_rows;
|
||||
}
|
||||
|
Reference in New Issue
Block a user