From 83123412f00d9b69f1c5ea39b160d1d27be701a9 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 18 Apr 2018 19:34:12 +0200 Subject: MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info Added metadate info after prepare EXPLAIN/ANALYZE. --- sql/sql_class.cc | 29 +++++++++++++++++++++-------- sql/sql_class.h | 2 ++ sql/sql_prepare.cc | 24 ++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0971d4fdaaa..628dcee0570 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2405,18 +2405,31 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length) } -int THD::send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze) +void THD::prepare_explain_fields(select_result *result, + List *field_list, + uint8 explain_flags, + bool is_analyze) { - List field_list; if (lex->explain_json) - make_explain_json_field_list(field_list, is_analyze); + make_explain_json_field_list(*field_list, is_analyze); else - make_explain_field_list(field_list, explain_flags, is_analyze); + make_explain_field_list(*field_list, explain_flags, is_analyze); + + result->prepare(*field_list, NULL); +} - result->prepare(field_list, NULL); - return (result->send_result_set_metadata(field_list, - Protocol::SEND_NUM_ROWS | - Protocol::SEND_EOF)); + +int THD::send_explain_fields(select_result *result, + uint8 explain_flags, + bool is_analyze) +{ + List field_list; + int rc; + prepare_explain_fields(result, &field_list, explain_flags, is_analyze); + rc= result->send_result_set_metadata(field_list, + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF); + return(rc); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 8dde68b7fba..e93bd00eec0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3331,6 +3331,8 @@ public: void add_changed_table(TABLE *table); void add_changed_table(const char *key, long key_length); CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); + void prepare_explain_fields(select_result *result, List *field_list, + uint8 explain_flags, bool is_analyze); int send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze); void make_explain_field_list(List &field_list, uint8 explain_flags, diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 455d6b3cb86..89b7e490cb9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2475,8 +2475,28 @@ static bool check_prepared_statement(Prepared_statement *stmt) break; } if (res == 0) - DBUG_RETURN(stmt->is_sql_prepare() ? - FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush())); + { + if (!stmt->is_sql_prepare()) + { + if (lex->describe || lex->analyze_stmt) + { + if (!lex->result && + !(lex->result= new (stmt->mem_root) select_send(thd))) + DBUG_RETURN(TRUE); + List field_list; + thd->prepare_explain_fields(lex->result, &field_list, + lex->describe, lex->analyze_stmt); + res= send_prep_stmt(stmt, lex->result->field_count(field_list)) || + lex->result->send_result_set_metadata(field_list, + Protocol::SEND_EOF); + } + else + res= send_prep_stmt(stmt, 0); + if (!res) + thd->protocol->flush(); + } + DBUG_RETURN(FALSE); + } error: DBUG_RETURN(TRUE); } -- cgit v1.2.1