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: