summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_lex.cc38
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_select.cc7
-rw-r--r--sql/sql_union.cc48
4 files changed, 74 insertions, 21 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index e863308159e..853b4d8cc1a 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3170,7 +3170,41 @@ bool st_select_lex_unit::union_needs_tmp_table()
global_parameters()->order_list.elements != 0 ||
thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
thd->lex->sql_command == SQLCOM_REPLACE_SELECT;
-}
+}
+
+
+/*
+ @brief
+ Check if the ORDER BY clause is redundant or empty
+
+ @retval
+ TRUE order by is redundant or empty
+ FALSE OTHERWISE
+*/
+
+bool st_select_lex_unit::is_order_by_clause_redundant()
+{
+ if (global_parameters()->order_list.elements == 0)
+ return true;
+ if (is_union_op_inside_in_predicate())
+ return true;
+ return false;
+}
+
+
+/*
+ @brief
+ Check if UNION is in side an IN/ALL/ANY subquery
+
+ @retval
+ TRUE UNION inside in an IN/ALL/ANY subquery
+ FALSE Otherwise
+*/
+bool st_select_lex_unit::is_union_op_inside_in_predicate()
+{
+ return is_union() && item && item->is_in_predicate();
+}
+
/**
@brief Set the initial purpose of this TABLE_LIST object in the list of used
@@ -4678,7 +4712,7 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
eu->add_select(sl->select_number);
eu->fake_select_type= "UNION RESULT";
- eu->using_filesort= MY_TEST(global_parameters()->order_list.first);
+ eu->using_filesort= MY_TEST(!is_order_by_clause_redundant());
eu->using_tmp= union_needs_tmp_table();
// Save the UNION node
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index cdf80daa928..f18c9f72cce 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -699,6 +699,8 @@ public:
void set_thd(THD *thd_arg) { thd= thd_arg; }
inline bool is_union ();
bool union_needs_tmp_table();
+ bool is_order_by_clause_redundant();
+ bool is_union_op_inside_in_predicate();
void set_unique_exclude();
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7a1a7baaa1c..912f28d7168 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -590,6 +590,13 @@ void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
DBUG_PRINT("info", ("DISTINCT removed"));
}
+ if (subq_select_lex->master_unit()->is_union_op_inside_in_predicate() &&
+ subq_select_lex->master_unit()->fake_select_lex == subq_select_lex &&
+ subq_select_lex->order_list.elements)
+ {
+ subq_select_lex->join->order= NULL;
+ }
+
/*
Remove GROUP BY if there are no aggregate functions and no HAVING
clause
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 0e623777ef0..3f03baf73ec 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -331,6 +331,35 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg,
(*order->item)->walk(&Item::set_fake_select_as_master_processor, 0,
(uchar*) fake_select_lex);
}
+
+ /*
+ If we are reading UNION output and the UNION is in the
+ IN/ANY/ALL subquery, then ORDER BY is redundant and hence should
+ be removed.
+ Example:
+ select ... col IN (select col2 FROM t1 union select col3 from t2 ORDER BY 1)
+
+ (as for ORDER BY ... LIMIT, it currently not supported inside
+ IN/ALL/ANY subqueries)
+ ORDER BY LIMIT is allowed in EXISTS subqueries, so we don't remove
+ the ORDER BY clause from EXISTS subqueries
+ (For non-UNION this removal of ORDER BY clause is done in
+ check_and_do_in_subquery_rewrites())
+ @see remove_redundant_subquery_clauses
+ */
+ if (is_union_op_inside_in_predicate())
+ {
+ for (ORDER *ord= global_parameters()->order_list.first; ord; ord= ord->next)
+ {
+ /*
+ The subqueries inside the ORDER BY clause are marked as eliminated.
+ This is done to avoid adding the subqueries as children of the
+ fake_select_lex in the EXPLAIN structures.
+ */
+ (*ord->item)->walk(&Item::mark_as_eliminated_processor, FALSE, NULL);
+ }
+ }
+
}
@@ -388,25 +417,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
is_union_select= is_union() || fake_select_lex;
- /*
- If we are reading UNION output and the UNION is in the
- IN/ANY/ALL/EXISTS subquery, then ORDER BY is redundant and hence should
- be removed.
- Example:
- select ... col IN (select col2 FROM t1 union select col3 from t2 ORDER BY 1)
-
- (as for ORDER BY ... LIMIT, it currently not supported inside
- IN/ALL/ANY subqueries)
- (For non-UNION this removal of ORDER BY clause is done in
- check_and_do_in_subquery_rewrites())
- */
- if (is_union() && item &&
- (item->is_in_predicate() || item->is_exists_predicate()))
- {
- global_parameters()->order_list.first= NULL;
- global_parameters()->order_list.elements= 0;
- }
-
/* Global option */
if (is_union_select)