Commit d5fbfb9a authored by Sergei Petrunia's avatar Sergei Petrunia

EXPLAIN FORMAT=JSON: Add support for single-table UPDATE/DELETE.

parent 461dbd80
...@@ -199,7 +199,7 @@ EXPLAIN ...@@ -199,7 +199,7 @@ EXPLAIN
}, },
{ {
"query_block": { "query_block": {
"select_id": 1, "select_id": 2,
"table": { "table": {
"table_name": "B", "table_name": "B",
"access_type": "ALL", "access_type": "ALL",
...@@ -233,7 +233,7 @@ EXPLAIN ...@@ -233,7 +233,7 @@ EXPLAIN
}, },
{ {
"query_block": { "query_block": {
"select_id": 1, "select_id": 2,
"table": { "table": {
"table_name": "B", "table_name": "B",
"access_type": "ALL", "access_type": "ALL",
...@@ -265,7 +265,7 @@ EXPLAIN ...@@ -265,7 +265,7 @@ EXPLAIN
"subqueries": [ "subqueries": [
{ {
"query_block": { "query_block": {
"select_id": 1, "select_id": 2,
"table": { "table": {
"table_name": "t1", "table_name": "t1",
"access_type": "ALL", "access_type": "ALL",
...@@ -295,7 +295,7 @@ EXPLAIN ...@@ -295,7 +295,7 @@ EXPLAIN
"subqueries": [ "subqueries": [
{ {
"query_block": { "query_block": {
"select_id": 1, "select_id": 2,
"table": { "table": {
"table_name": "t1", "table_name": "t1",
"access_type": "ALL", "access_type": "ALL",
...@@ -342,4 +342,55 @@ EXPLAIN ...@@ -342,4 +342,55 @@ EXPLAIN
} }
} }
drop table t1; drop table t1;
#
# Single-table UPDATE/DELETE
#
explain format=json delete from t0;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"message": "Deleting all rows"
}
}
}
explain format=json delete from t0 where 1 > 2;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"message": "Impossible WHERE"
}
}
}
explain format=json delete from t0 where a < 3;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"delete": 1,
"table_name": "t0",
"access_type": "ALL",
"rows": 10,
"attached_condition": "(t0.a < 3)"
}
}
}
explain format=json update t0 set a=3 where a in (2,3,4);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"update": 1,
"table_name": "t0",
"access_type": "ALL",
"rows": 10,
"attached_condition": "(t0.a in (2,3,4))"
}
}
}
drop table t0; drop table t0;
...@@ -70,5 +70,15 @@ select * from t1 A, t1 B where A.a=B.a and A.b < 3 and B.b < 5; ...@@ -70,5 +70,15 @@ select * from t1 A, t1 B where A.a=B.a and A.b < 3 and B.b < 5;
drop table t1; drop table t1;
--echo #
--echo # Single-table UPDATE/DELETE
--echo #
explain format=json delete from t0;
explain format=json delete from t0 where 1 > 2;
explain format=json delete from t0 where a < 3;
explain format=json update t0 set a=3 where a in (2,3,4);
drop table t0; drop table t0;
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
invoked on a running DELETE statement. invoked on a running DELETE statement.
*/ */
void Delete_plan::save_explain_data(Explain_query *query) void Delete_plan::save_explain_data(MEM_ROOT *mem_root, Explain_query *query)
{ {
Explain_delete* explain= new Explain_delete; Explain_delete* explain= new Explain_delete;
...@@ -64,22 +64,23 @@ void Delete_plan::save_explain_data(Explain_query *query) ...@@ -64,22 +64,23 @@ void Delete_plan::save_explain_data(Explain_query *query)
else else
{ {
explain->deleting_all_rows= false; explain->deleting_all_rows= false;
Update_plan::save_explain_data_intern(query, explain); Update_plan::save_explain_data_intern(mem_root, query, explain);
} }
query->add_upd_del_plan(explain); query->add_upd_del_plan(explain);
} }
void Update_plan::save_explain_data(Explain_query *query) void Update_plan::save_explain_data(MEM_ROOT *mem_root, Explain_query *query)
{ {
Explain_update* explain= new Explain_update; Explain_update* explain= new Explain_update;
save_explain_data_intern(query, explain); save_explain_data_intern(mem_root, query, explain);
query->add_upd_del_plan(explain); query->add_upd_del_plan(explain);
} }
void Update_plan::save_explain_data_intern(Explain_query *query, void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
Explain_query *query,
Explain_update *explain) Explain_update *explain)
{ {
explain->select_type= "SIMPLE"; explain->select_type= "SIMPLE";
...@@ -141,10 +142,12 @@ void Update_plan::save_explain_data_intern(Explain_query *query, ...@@ -141,10 +142,12 @@ void Update_plan::save_explain_data_intern(Explain_query *query,
} }
explain->using_where= MY_TEST(select && select->cond); explain->using_where= MY_TEST(select && select->cond);
explain->where_cond= select? select->cond: NULL;
explain->using_filesort= using_filesort; explain->using_filesort= using_filesort;
explain->using_io_buffer= using_io_buffer; explain->using_io_buffer= using_io_buffer;
make_possible_keys_line(table, possible_keys, &explain->possible_keys_line); append_possible_keys(mem_root, explain->possible_keys, table,
possible_keys);
explain->quick_info= NULL; explain->quick_info= NULL;
...@@ -157,11 +160,8 @@ void Update_plan::save_explain_data_intern(Explain_query *query, ...@@ -157,11 +160,8 @@ void Update_plan::save_explain_data_intern(Explain_query *query,
{ {
if (index != MAX_KEY) if (index != MAX_KEY)
{ {
explain->key_str.append(table->key_info[index].name); explain->key.set(mem_root, &table->key_info[index],
char buf[64]; table->key_info[index].key_length);
size_t length;
length= longlong10_to_str(table->key_info[index].key_length, buf, 10) - buf;
explain->key_len_str.append(buf, length);
} }
} }
explain->rows= scanned_rows; explain->rows= scanned_rows;
...@@ -460,7 +460,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -460,7 +460,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (thd->lex->describe) if (thd->lex->describe)
goto produce_explain_and_leave; goto produce_explain_and_leave;
query_plan.save_explain_data(thd->lex->explain); query_plan.save_explain_data(thd->mem_root, thd->lex->explain);
DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start", DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start",
dbug_serve_apcs(thd, 1);); dbug_serve_apcs(thd, 1););
...@@ -698,7 +698,7 @@ produce_explain_and_leave: ...@@ -698,7 +698,7 @@ produce_explain_and_leave:
We come here for various "degenerate" query plans: impossible WHERE, We come here for various "degenerate" query plans: impossible WHERE,
no-partitions-used, impossible-range, etc. no-partitions-used, impossible-range, etc.
*/ */
query_plan.save_explain_data(thd->lex->explain); query_plan.save_explain_data(thd->mem_root, thd->lex->explain);
send_nothing_and_leave: send_nothing_and_leave:
/* /*
......
This diff is collapsed.
...@@ -432,6 +432,11 @@ class Explain_index_use : public Sql_alloc ...@@ -432,6 +432,11 @@ class Explain_index_use : public Sql_alloc
public: public:
String_list key_parts_list; String_list key_parts_list;
Explain_index_use()
{
clear();
}
void clear() void clear()
{ {
key_name= NULL; key_name= NULL;
...@@ -440,8 +445,8 @@ public: ...@@ -440,8 +445,8 @@ public:
void set(MEM_ROOT *root, KEY *key_name, uint key_len_arg); void set(MEM_ROOT *root, KEY *key_name, uint key_len_arg);
void set_pseudo_key(MEM_ROOT *root, const char *key_name); void set_pseudo_key(MEM_ROOT *root, const char *key_name);
inline const char *get_key_name() { return key_name; } inline const char *get_key_name() const { return key_name; }
inline uint get_key_len() { return key_len; } inline uint get_key_len() const { return key_len; }
}; };
...@@ -584,8 +589,8 @@ public: ...@@ -584,8 +589,8 @@ public:
private: private:
void append_tag_name(String *str, enum explain_extra_tag tag); void append_tag_name(String *str, enum explain_extra_tag tag);
void fill_key_str(String *key_str, bool is_json); void fill_key_str(String *key_str, bool is_json) const;
void fill_key_len_str(String *key_len_str); void fill_key_len_str(String *key_len_str) const;
double get_r_filtered(); double get_r_filtered();
void tag_to_json(Json_writer *writer, enum explain_extra_tag tag); void tag_to_json(Json_writer *writer, enum explain_extra_tag tag);
}; };
...@@ -614,14 +619,22 @@ public: ...@@ -614,14 +619,22 @@ public:
StringBuffer<64> table_name; StringBuffer<64> table_name;
enum join_type jtype; enum join_type jtype;
StringBuffer<128> possible_keys_line; String_list possible_keys;
StringBuffer<128> key_str;
StringBuffer<128> key_len_str; /* Used key when doing a full index scan (possibly with limit) */
Explain_index_use key;
/*
MRR that's used with quick select. This should probably belong to the
quick select
*/
StringBuffer<64> mrr_type; StringBuffer<64> mrr_type;
Explain_quick_select *quick_info; Explain_quick_select *quick_info;
bool using_where; bool using_where;
Item *where_cond;
ha_rows rows; ha_rows rows;
bool using_filesort; bool using_filesort;
...@@ -632,8 +645,8 @@ public: ...@@ -632,8 +645,8 @@ public:
virtual int print_explain(Explain_query *query, select_result_sink *output, virtual int print_explain(Explain_query *query, select_result_sink *output,
uint8 explain_flags, bool is_analyze); uint8 explain_flags, bool is_analyze);
virtual void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) virtual void print_explain_json(Explain_query *query, Json_writer *writer,
{ /* EXPLAIN_JSON_NOT_IMPL */} bool is_analyze);
}; };
...@@ -678,8 +691,8 @@ public: ...@@ -678,8 +691,8 @@ public:
virtual int print_explain(Explain_query *query, select_result_sink *output, virtual int print_explain(Explain_query *query, select_result_sink *output,
uint8 explain_flags, bool is_analyze); uint8 explain_flags, bool is_analyze);
virtual void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) virtual void print_explain_json(Explain_query *query, Json_writer *writer,
{ /* EXPLAIN_JSON_NOT_IMPL */} bool is_analyze);
}; };
...@@ -2303,8 +2303,9 @@ public: ...@@ -2303,8 +2303,9 @@ public:
void set_impossible_where() { impossible_where= true; } void set_impossible_where() { impossible_where= true; }
void set_no_partitions() { no_partitions= true; } void set_no_partitions() { no_partitions= true; }
void save_explain_data(Explain_query *query); void save_explain_data(MEM_ROOT *mem_root, Explain_query *query);
void save_explain_data_intern(Explain_query *query, Explain_update *eu); void save_explain_data_intern(MEM_ROOT *mem_root, Explain_query *query,
Explain_update *eu);
virtual ~Update_plan() {} virtual ~Update_plan() {}
...@@ -2335,7 +2336,7 @@ public: ...@@ -2335,7 +2336,7 @@ public:
scanned_rows= rows_arg; scanned_rows= rows_arg;
} }
void save_explain_data(Explain_query *query); void save_explain_data(MEM_ROOT *mem_root, Explain_query *query);
}; };
......
...@@ -23126,135 +23126,7 @@ int print_explain_message_line(select_result_sink *result, ...@@ -23126,135 +23126,7 @@ int print_explain_message_line(select_result_sink *result,
return 0; return 0;
} }
#if 0
/*
Make a comma-separated list of possible_keys names and add it into the string
*/
void make_possible_keys_line(TABLE *table, key_map possible_keys, String *line)
{
if (!possible_keys.is_clear_all())
{
uint j;
for (j=0 ; j < table->s->keys ; j++)
{
if (possible_keys.is_set(j))
{
if (line->length())
line->append(',');
line->append(table->key_info[j].name,
strlen(table->key_info[j].name),
system_charset_info);
}
}
}
}
/*
Print an EXPLAIN output row, based on information provided in the parameters
@note
Parameters that may have NULL value in EXPLAIN output, should be passed
(char*)NULL.
@return
0 - OK
1 - OOM Error
*/
int print_explain_row(select_result_sink *result,
uint8 options, bool is_analyze,
uint select_number,
const char *select_type,
const char *table_name,
const char *partitions,
enum join_type jtype,
const char *possible_keys,
const char *index,
const char *key_len,
const char *ref,
ha_rows *rows,
ha_rows *r_rows,
double r_filtered,
const char *extra)
{
Item *item_null= new Item_null();
List<Item> item_list;
Item *item;
item_list.push_back(new Item_int((int32) select_number));
item_list.push_back(new Item_string_sys(select_type));
item_list.push_back(new Item_string_sys(table_name));
if (options & DESCRIBE_PARTITIONS)
{
if (partitions)
{
item_list.push_back(new Item_string_sys(partitions));
}
else
item_list.push_back(item_null);
}
const char *jtype_str= join_type_str[jtype];
item_list.push_back(new Item_string_sys(jtype_str));
item= possible_keys? new Item_string_sys(possible_keys) : item_null;
item_list.push_back(item);
/* 'index */
item= index ? new Item_string_sys(index) : item_null;
item_list.push_back(item);
/* 'key_len */
item= key_len ? new Item_string_sys(key_len) : item_null;
item_list.push_back(item);
/* 'ref' */
item= ref ? new Item_string_sys(ref) : item_null;
item_list.push_back(item);
/* 'rows' */
if (rows)
{
item_list.push_back(new Item_int(*rows,
MY_INT64_NUM_DECIMAL_DIGITS));
}
else
item_list.push_back(item_null);
/* 'r_rows' */
if (is_analyze)
{
if (r_rows)
{
item_list.push_back(new Item_int(*r_rows,
MY_INT64_NUM_DECIMAL_DIGITS));
}
else
item_list.push_back(item_null);
}
/* 'filtered' */
const double filtered=100.0;
if (options & DESCRIBE_EXTENDED || is_analyze)
item_list.push_back(new Item_float(filtered, 2));
/* 'r_filtered' */
if (is_analyze)
item_list.push_back(new Item_float(r_filtered, 2));
/* 'Extra' */
if (extra)
item_list.push_back(new Item_string_sys(extra));
else
item_list.push_back(item_null);
if (result->send_data(item_list))
return 1;
return 0;
}
int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
SELECT_LEX *select_lex, uint8 explain_flags) SELECT_LEX *select_lex, uint8 explain_flags)
{ {
...@@ -23327,7 +23199,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, ...@@ -23327,7 +23199,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
return 1; return 1;
return 0; return 0;
} }
#endif
/* /*
Append MRR information from quick select to the given string Append MRR information from quick select to the given string
......
...@@ -1832,8 +1832,10 @@ inline bool optimizer_flag(THD *thd, uint flag) ...@@ -1832,8 +1832,10 @@ inline bool optimizer_flag(THD *thd, uint flag)
return (thd->variables.optimizer_switch & flag); return (thd->variables.optimizer_switch & flag);
} }
/*
int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
SELECT_LEX *select_lex, uint8 select_options); SELECT_LEX *select_lex, uint8 select_options);
*/
uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select,
ha_rows limit, ha_rows *scanned_limit, ha_rows limit, ha_rows *scanned_limit,
...@@ -1861,22 +1863,8 @@ int print_explain_message_line(select_result_sink *result, ...@@ -1861,22 +1863,8 @@ int print_explain_message_line(select_result_sink *result,
ha_rows *rows, ha_rows *rows,
const char *message); const char *message);
void explain_append_mrr_info(QUICK_RANGE_SELECT *quick, String *res); void explain_append_mrr_info(QUICK_RANGE_SELECT *quick, String *res);
int print_explain_row(select_result_sink *result, int append_possible_keys(MEM_ROOT *alloc, String_list &list, TABLE *table,
uint8 options, bool is_analyze, key_map possible_keys);
uint select_number,
const char *select_type,
const char *table_name,
const char *partitions,
enum join_type jtype,
const char *possible_keys,
const char *index,
const char *key_len,
const char *ref,
ha_rows *rows,
ha_rows *r_rows,
double r_filtered,
const char *extra);
void make_possible_keys_line(TABLE *table, key_map possible_keys, String *line);
/**************************************************************************** /****************************************************************************
Temporary table support for SQL Runtime Temporary table support for SQL Runtime
......
...@@ -517,7 +517,7 @@ int mysql_update(THD *thd, ...@@ -517,7 +517,7 @@ int mysql_update(THD *thd,
*/ */
if (thd->lex->describe) if (thd->lex->describe)
goto produce_explain_and_leave; goto produce_explain_and_leave;
query_plan.save_explain_data(thd->lex->explain); query_plan.save_explain_data(thd->mem_root, thd->lex->explain);
DBUG_EXECUTE_IF("show_explain_probe_update_exec_start", DBUG_EXECUTE_IF("show_explain_probe_update_exec_start",
dbug_serve_apcs(thd, 1);); dbug_serve_apcs(thd, 1););
...@@ -1037,7 +1037,7 @@ produce_explain_and_leave: ...@@ -1037,7 +1037,7 @@ produce_explain_and_leave:
We come here for various "degenerate" query plans: impossible WHERE, We come here for various "degenerate" query plans: impossible WHERE,
no-partitions-used, impossible-range, etc. no-partitions-used, impossible-range, etc.
*/ */
query_plan.save_explain_data(thd->lex->explain); query_plan.save_explain_data(thd->mem_root, thd->lex->explain);
emit_explain_and_leave: emit_explain_and_leave:
int err2= thd->lex->explain->send_explain(thd); int err2= thd->lex->explain->send_explain(thd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment