diff options
author | unknown <timour@askmonty.org> | 2012-05-18 14:52:01 +0300 |
---|---|---|
committer | unknown <timour@askmonty.org> | 2012-05-18 14:52:01 +0300 |
commit | e5bca74bfb47a1c45c995573fd58b1a751ccd884 (patch) | |
tree | 3c46da363263a383686012bcfd706a4940ed630d /sql | |
parent | da5214831d3d0f0880b4068a06ce062ca703293f (diff) | |
download | mariadb-git-e5bca74bfb47a1c45c995573fd58b1a751ccd884.tar.gz |
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_select.cc | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 933679a0d9c..10c841639a9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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; } |