diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2013-06-20 22:30:30 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2013-06-20 22:30:30 +0400 |
commit | ab4a13b2b91e260d8c75a3c41b7ff5c24747cee0 (patch) | |
tree | 39626d12d01af8959bcdd846e4c5edd5f92667c2 /sql | |
parent | 52cfa54c1d211a17a9df7c38a4568ddc4d09e6d9 (diff) | |
download | mariadb-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.cc | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 38 | ||||
-rw-r--r-- | sql/sql_select.h | 6 |
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: |