summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2013-06-20 22:30:30 +0400
committerSergey Petrunya <psergey@askmonty.org>2013-06-20 22:30:30 +0400
commitab4a13b2b91e260d8c75a3c41b7ff5c24747cee0 (patch)
tree39626d12d01af8959bcdd846e4c5edd5f92667c2 /sql
parent52cfa54c1d211a17a9df7c38a4568ddc4d09e6d9 (diff)
downloadmariadb-git-ab4a13b2b91e260d8c75a3c41b7ff5c24747cee0.tar.gz
Switching [EXPLAIN] UPDATE/DELETE to rely on query plan footprints.
This requires that subselect's footprints are saved before it is deleted. Attempt to save select's QPF exposes one to a variety of edge cases: - the select may be a UNION's "fake select" which has no valid id - optimization may fail in the middle (but subsequent JOIN::optimize() calls will succeed, despite the fact that there never was a query plan)
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_select.cc38
-rw-r--r--sql/sql_select.h6
3 files changed, 40 insertions, 10 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 455ef55944d..3161dc85fb9 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4341,7 +4341,8 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
if (!first->next_select())
{
/* This is a 1-way UNION, i.e. not really a UNION */
- first->save_qpf(output);
+ if (!output->get_select(first->select_number))
+ first->save_qpf(output);
return 0;
}
@@ -4371,7 +4372,8 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
{
- sl->save_qpf(output);
+ if (!output->get_select(sl->select_number))
+ sl->save_qpf(output);
qpfu->add_select(sl->select_number);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 91da7526c72..eed6ed5e09f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1005,17 +1005,26 @@ err:
int JOIN::optimize()
{
+ bool was_optimized= optimized;
int res= optimize_inner();
/*
If we're inside a non-correlated subquery, this function may be
called for the second time after the subquery has been executed
and deleted. The second call will not produce a valid query plan, it will
short-circuit because optimized==TRUE.
+
+ "was_optimized != optimized" is here to handle this case:
+ - first optimization starts, gets an error (from a const. cheap
+ subquery), returns 1
+ - another JOIN::optimize() call made, and now join->optimize() will
+ return 0, even though we never had a query plan.
*/
- if (!res && have_query_plan != QEP_DELETED)
+ if (was_optimized != optimized && !res && have_query_plan != QEP_DELETED)
have_query_plan= QEP_AVAILABLE;
return res;
}
+
+
/**
global select optimisation.
@@ -2301,7 +2310,6 @@ void JOIN::exec()
select_lex->select_number))
dbug_serve_apcs(thd, 1);
);
-
thd->apc_target.disable();
}
@@ -11099,7 +11107,33 @@ void JOIN::cleanup(bool full)
DBUG_PRINT("enter", ("full %u", (uint) full));
if (full)
+ {
+ //
+ if (select_lex->select_number != UINT_MAX &&
+ select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
+ have_query_plan != QEP_NOT_PRESENT_YET &&
+ !thd->lex->query_plan_footprint->get_select(select_lex->select_number))
+ {
+ const char *message= NULL;
+
+ if (!table_count || !tables_list || zero_result_cause)
+ {
+ /* It's a degenerate join */
+ message= zero_result_cause ? zero_result_cause : "No tables used";
+ }
+
+ save_qpf(thd->lex->query_plan_footprint,
+ need_tmp, // need_tmp_table
+ !skip_sort_order && !no_order &&
+ (order || group_list), // bool need_order
+ select_distinct, // bool distinct
+ message); // message
+ }
+
+ //
+
have_query_plan= QEP_DELETED; //psergey: this is a problem!
+ }
if (table)
{
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 5ec09fcfcb8..6d4dfed479e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1462,12 +1462,6 @@ public:
{
return (unit->item && unit->item->is_in_predicate());
}
-/*
- int print_explain(select_result_sink *result, uint8 explain_flags,
- bool on_the_fly,
- bool need_tmp_table, bool need_order,
- bool distinct,const char *message);
-*/
int save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
bool distinct, const char *message);
private: