summaryrefslogtreecommitdiff
path: root/sql/sql_union.cc
diff options
context:
space:
mode:
authormithun <mithun.c.y@oracle.com>2014-04-28 21:07:27 +0530
committermithun <mithun.c.y@oracle.com>2014-04-28 21:07:27 +0530
commit3d6d85b40dbe8938d8d2972053e0ea714c04a2d4 (patch)
treea3e9fb226447c5562d2902ccdddb1c043ba13745 /sql/sql_union.cc
parent5e881cc435370140c38241dc6451f4cb31c0a3b9 (diff)
downloadmariadb-git-3d6d85b40dbe8938d8d2972053e0ea714c04a2d4.tar.gz
Bug #18167356: EXPLAIN W/ EXISTS(SELECT* UNION SELECT*)
WHERE ONE OF SELECT* IS DISTINCT FAILS. ISSUE: ------ There are 2 issues related to explain union. 1. If we have subquery with union of selects. And, one of the select need temp table to materialize its results then it will replace its query structure with a simple select from temporary table. Trying to display new internal temporary table scan resulted in crash. But to display the query plan, we should save the original query structure. 2. Multiple execution of prepared explain statement which have union of subqueries resulted in crash. If we have constant subqueries, fake select used in union operation will be evaluated once before using it for explain. During first execution we have set fake select options to SELECT_DESCRIBE, but did not reset after the explain. Hence during next execution of prepared statement during first time evaluation of fake select we had our select options as SELECT_DESCRIBE this resulted in improperly initialized data structures and crash. SOLUTION: --------- 1. If called by explain now we save the original query structure. And this will be used for displaying. 2. Reset the fake select options after it is called for explain of union. sql/sql_select.cc: Reset the fake select options after it is called for explain of union sql/sql_union.cc: If called by explain but not from select_describe and we need a temp table, then we create a temp join to preserve original query structure.
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r--sql/sql_union.cc29
1 files changed, 29 insertions, 0 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index b0a25c2df97..d0660e8f117 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -511,6 +511,35 @@ bool st_select_lex_unit::exec()
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
saved_error= sl->join->optimize();
+
+ /*
+ If called by explain statement then we may need to save the original
+ JOIN LAYOUT so that we can display the plan. Otherwise original plan
+ will be replaced by a simple scan on temp table if subquery uses temp
+ table.
+ We check for following conditions to force join_tmp creation
+ 1. This is an EXPLAIN statement, and
+ 2. JOIN not yet saved in JOIN::optimize(), and
+ 3. Not called directly from select_describe(), and
+ 4. Belongs to a subquery that is const, and
+ 5. Need a temp table.
+ */
+ if (thd->lex->describe && // 1
+ !sl->uncacheable && // 2
+ !(sl->join->select_options & SELECT_DESCRIBE) && // 3
+ item && item->const_item()) // 4
+ {
+ /*
+ Force join->join_tmp creation, because this subquery will be
+ replaced by a simple select from the materialization temp table
+ by optimize() called by EXPLAIN and we need to preserve the
+ initial query structure so we can display it.
+ */
+ sl->uncacheable|= UNCACHEABLE_EXPLAIN;
+ sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
+ if (sl->join->need_tmp && sl->join->init_save_join_tab()) // 5
+ DBUG_RETURN(1);
+ }
}
if (!saved_error)
{