Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
d5fbfb9a
Commit
d5fbfb9a
authored
Nov 28, 2014
by
Sergei Petrunia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EXPLAIN FORMAT=JSON: Add support for single-table UPDATE/DELETE.
parent
461dbd80
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
409 additions
and
197 deletions
+409
-197
mysql-test/r/explain_json.result
mysql-test/r/explain_json.result
+55
-4
mysql-test/t/explain_json.test
mysql-test/t/explain_json.test
+10
-0
sql/sql_delete.cc
sql/sql_delete.cc
+13
-13
sql/sql_explain.cc
sql/sql_explain.cc
+295
-18
sql/sql_explain.h
sql/sql_explain.h
+24
-11
sql/sql_lex.h
sql/sql_lex.h
+4
-3
sql/sql_select.cc
sql/sql_select.cc
+2
-130
sql/sql_select.h
sql/sql_select.h
+4
-16
sql/sql_update.cc
sql/sql_update.cc
+2
-2
No files found.
mysql-test/r/explain_json.result
View file @
d5fbfb9a
...
...
@@ -199,7 +199,7 @@ EXPLAIN
},
{
"query_block": {
"select_id":
1
,
"select_id":
2
,
"table": {
"table_name": "B",
"access_type": "ALL",
...
...
@@ -233,7 +233,7 @@ EXPLAIN
},
{
"query_block": {
"select_id":
1
,
"select_id":
2
,
"table": {
"table_name": "B",
"access_type": "ALL",
...
...
@@ -265,7 +265,7 @@ EXPLAIN
"subqueries": [
{
"query_block": {
"select_id":
1
,
"select_id":
2
,
"table": {
"table_name": "t1",
"access_type": "ALL",
...
...
@@ -295,7 +295,7 @@ EXPLAIN
"subqueries": [
{
"query_block": {
"select_id":
1
,
"select_id":
2
,
"table": {
"table_name": "t1",
"access_type": "ALL",
...
...
@@ -342,4 +342,55 @@ EXPLAIN
}
}
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;
mysql-test/t/explain_json.test
View file @
d5fbfb9a
...
...
@@ -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
;
--
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
;
sql/sql_delete.cc
View file @
d5fbfb9a
...
...
@@ -51,7 +51,7 @@
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
;
...
...
@@ -64,22 +64,23 @@ void Delete_plan::save_explain_data(Explain_query *query)
else
{
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
);
}
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
;
save_explain_data_intern
(
query
,
explain
);
save_explain_data_intern
(
mem_root
,
query
,
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
->
select_type
=
"SIMPLE"
;
...
...
@@ -141,10 +142,12 @@ void Update_plan::save_explain_data_intern(Explain_query *query,
}
explain
->
using_where
=
MY_TEST
(
select
&&
select
->
cond
);
explain
->
where_cond
=
select
?
select
->
cond
:
NULL
;
explain
->
using_filesort
=
using_filesort
;
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
;
...
...
@@ -157,11 +160,8 @@ void Update_plan::save_explain_data_intern(Explain_query *query,
{
if
(
index
!=
MAX_KEY
)
{
explain
->
key_str
.
append
(
table
->
key_info
[
index
].
name
);
char
buf
[
64
];
size_t
length
;
length
=
longlong10_to_str
(
table
->
key_info
[
index
].
key_length
,
buf
,
10
)
-
buf
;
explain
->
key_len_str
.
append
(
buf
,
length
);
explain
->
key
.
set
(
mem_root
,
&
table
->
key_info
[
index
],
table
->
key_info
[
index
].
key_length
);
}
}
explain
->
rows
=
scanned_rows
;
...
...
@@ -460,7 +460,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if
(
thd
->
lex
->
describe
)
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_serve_apcs
(
thd
,
1
););
...
...
@@ -698,7 +698,7 @@ produce_explain_and_leave:
We come here for various "degenerate" query plans: impossible WHERE,
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:
/*
...
...
sql/sql_explain.cc
View file @
d5fbfb9a
...
...
@@ -22,6 +22,10 @@
#include "sql_select.h"
#include "my_json_writer.h"
const
char
*
STR_DELETING_ALL_ROWS
=
"Deleting all rows"
;
const
char
*
STR_IMPOSSIBLE_WHERE
=
"Impossible WHERE"
;
const
char
*
STR_NO_ROWS_AFTER_PRUNING
=
"No matching rows after partition pruning"
;
Explain_query
::
Explain_query
(
THD
*
thd_arg
)
:
upd_del_plan
(
NULL
),
insert_plan
(
NULL
),
thd
(
thd_arg
),
apc_enabled
(
false
)
{
...
...
@@ -188,10 +192,7 @@ void Explain_query::print_explain_json(select_result_sink *output, bool is_analy
writer
.
start_object
();
if
(
upd_del_plan
)
{
//upd_del_plan->print_explain(this, output, explain_flags, is_analyze);
DBUG_ASSERT
(
0
);
}
upd_del_plan
->
print_explain_json
(
this
,
&
writer
,
is_analyze
);
else
if
(
insert_plan
)
{
//insert_plan->print_explain(this, output, explain_flags, is_analyze);
...
...
@@ -270,6 +271,120 @@ static void push_string_list(List<Item> *item_list, String_list &lines,
}
/*
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
*/
static
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
,
String_list
*
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
));
/* 'possible_keys' */
if
(
possible_keys
&&
!
possible_keys
->
is_empty
())
{
StringBuffer
<
64
>
possible_keys_buf
;
push_string_list
(
&
item_list
,
*
possible_keys
,
&
possible_keys_buf
);
}
else
item_list
.
push_back
(
item_null
);
/* '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
;
}
uint
Explain_union
::
make_union_table_name
(
char
*
buf
)
{
uint
childno
=
0
;
...
...
@@ -538,7 +653,7 @@ void Explain_select::print_explain_json(Explain_query *query,
Json_writer_nesting_guard
guard
(
writer
);
writer
->
add_member
(
"query_block"
).
start_object
();
writer
->
add_member
(
"select_id"
).
add_ll
(
1
);
writer
->
add_member
(
"select_id"
).
add_ll
(
select_id
);
if
(
message
)
{
writer
->
add_member
(
"table"
).
start_object
();
...
...
@@ -565,7 +680,15 @@ void Explain_table_access::push_extra(enum explain_extra_tag extra_tag)
}
void
Explain_table_access
::
fill_key_str
(
String
*
key_str
,
bool
is_json
)
/*
Put the contents of 'key' field of EXPLAIN otuput into key_str.
It is surprisingly complex:
- hash join shows #hash#used_key
- quick selects that use single index will print index name
*/
void
Explain_table_access
::
fill_key_str
(
String
*
key_str
,
bool
is_json
)
const
{
const
CHARSET_INFO
*
cs
=
system_charset_info
;
bool
is_hj
=
(
type
==
JT_HASH
||
type
==
JT_HASH_NEXT
||
...
...
@@ -607,7 +730,7 @@ void Explain_table_access::fill_key_str(String *key_str, bool is_json)
the column legacy, it is superceded by used_key_parts.
*/
void
Explain_table_access
::
fill_key_len_str
(
String
*
key_len_str
)
void
Explain_table_access
::
fill_key_len_str
(
String
*
key_len_str
)
const
{
bool
is_hj
=
(
type
==
JT_HASH
||
type
==
JT_HASH_NEXT
||
type
==
JT_HASH_RANGE
||
type
==
JT_HASH_INDEX_MERGE
);
...
...
@@ -996,9 +1119,6 @@ void Explain_table_access::print_explain_json(Json_writer *writer,
writer
->
end_object
();
}
// TODO: here, if quick select is not basic, print its nested form.
/* `ref` */
if
(
!
ref_list
.
is_empty
())
{
...
...
@@ -1320,7 +1440,7 @@ int Explain_delete::print_explain(Explain_query *query,
{
if
(
deleting_all_rows
)
{
const
char
*
msg
=
"Deleting all rows"
;
const
char
*
msg
=
STR_DELETING_ALL_ROWS
;
int
res
=
print_explain_message_line
(
output
,
explain_flags
,
is_analyze
,
1
/*select number*/
,
select_type
,
&
rows
,
msg
);
...
...
@@ -1335,6 +1455,27 @@ int Explain_delete::print_explain(Explain_query *query,
}
void
Explain_delete
::
print_explain_json
(
Explain_query
*
query
,
Json_writer
*
writer
,
bool
is_analyze
)
{
Json_writer_nesting_guard
guard
(
writer
);
if
(
deleting_all_rows
)
{
writer
->
add_member
(
"query_block"
).
start_object
();
writer
->
add_member
(
"select_id"
).
add_ll
(
1
);
writer
->
add_member
(
"table"
).
start_object
();
// just like mysql-5.6, we don't print table name. Is this ok?
writer
->
add_member
(
"message"
).
add_str
(
STR_DELETING_ALL_ROWS
);
writer
->
end_object
();
// table
writer
->
end_object
();
// query_block
return
;
}
Explain_update
::
print_explain_json
(
query
,
writer
,
is_analyze
);
}
int
Explain_update
::
print_explain
(
Explain_query
*
query
,
select_result_sink
*
output
,
uint8
explain_flags
,
...
...
@@ -1346,8 +1487,8 @@ int Explain_update::print_explain(Explain_query *query,
if
(
impossible_where
||
no_partitions
)
{
const
char
*
msg
=
impossible_where
?
"Impossible WHERE"
:
"No matching rows after partition pruning"
;
STR_IMPOSSIBLE_WHERE
:
STR_NO_ROWS_AFTER_PRUNING
;
int
res
=
print_explain_message_line
(
output
,
explain_flags
,
is_analyze
,
1
/*select number*/
,
select_type
,
...
...
@@ -1356,7 +1497,6 @@ int Explain_update::print_explain(Explain_query *query,
return
res
;
}
if
(
quick_info
)
{
quick_info
->
print_key
(
&
key_buf
);
...
...
@@ -1370,10 +1510,13 @@ int Explain_update::print_explain(Explain_query *query,
extra_str
.
append
(
quick_buf
);
}
}
else
else
if
(
key
.
get_key_name
())
{
key_buf
.
copy
(
key_str
);
key_len_buf
.
copy
(
key_len_str
);
const
char
*
name
=
key
.
get_key_name
();
key_buf
.
set
(
name
,
strlen
(
name
),
&
my_charset_bin
);
char
buf
[
64
];
size_t
length
=
longlong10_to_str
(
key
.
get_key_len
(),
buf
,
10
)
-
buf
;
key_len_buf
.
copy
(
buf
,
length
,
&
my_charset_bin
);
}
if
(
using_where
)
...
...
@@ -1417,7 +1560,7 @@ int Explain_update::print_explain(Explain_query *query,
table_name
.
c_ptr
(),
used_partitions_set
?
used_partitions
.
c_ptr
()
:
NULL
,
jtype
,
possible_keys_line
.
length
()
?
possible_keys_line
.
c_ptr
()
:
NULL
,
&
possible_keys
,
key_buf
.
length
()
?
key_buf
.
c_ptr
()
:
NULL
,
key_len_buf
.
length
()
?
key_len_buf
.
c_ptr
()
:
NULL
,
NULL
,
/* 'ref' is always NULL in single-table EXPLAIN DELETE */
...
...
@@ -1430,6 +1573,140 @@ int Explain_update::print_explain(Explain_query *query,
}
void
Explain_update
::
print_explain_json
(
Explain_query
*
query
,
Json_writer
*
writer
,
bool
is_analyze
)
{
Json_writer_nesting_guard
guard
(
writer
);
writer
->
add_member
(
"query_block"
).
start_object
();
writer
->
add_member
(
"select_id"
).
add_ll
(
1
);
if
(
impossible_where
||
no_partitions
)
{
const
char
*
msg
=
impossible_where
?
STR_IMPOSSIBLE_WHERE
:
STR_NO_ROWS_AFTER_PRUNING
;
writer
->
add_member
(
"table"
).
start_object
();
writer
->
add_member
(
"message"
).
add_str
(
msg
);
writer
->
end_object
();
// table
writer
->
end_object
();
// query_block
return
;
}
writer
->
add_member
(
"table"
).
start_object
();
if
(
get_type
()
==
EXPLAIN_UPDATE
)
writer
->
add_member
(
"update"
).
add_ll
(
1
);
else
writer
->
add_member
(
"delete"
).
add_ll
(
1
);
writer
->
add_member
(
"table_name"
).
add_str
(
table_name
);
writer
->
add_member
(
"access_type"
).
add_str
(
join_type_str
[
jtype
]);
if
(
!
possible_keys
.
is_empty
())
{
List_iterator_fast
<
char
>
it
(
possible_keys
);
const
char
*
name
;
writer
->
add_member
(
"possible_keys"
).
start_array
();
while
((
name
=
it
++
))
writer
->
add_str
(
name
);
writer
->
end_array
();
}
/* `key`, `key_length` */
if
(
quick_info
&&
quick_info
->
is_basic
())
{
StringBuffer
<
64
>
key_buf
;
StringBuffer
<
64
>
key_len_buf
;
quick_info
->
print_extra_recursive
(
&
key_buf
);
quick_info
->
print_key_len
(
&
key_len_buf
);
writer
->
add_member
(
"key"
).
add_str
(
key_buf
);
writer
->
add_member
(
"key_length"
).
add_str
(
key_len_buf
);
}
else
if
(
key
.
get_key_name
())
{
writer
->
add_member
(
"key"
).
add_str
(
key
.
get_key_name
());
writer
->
add_member
(
"key_length"
).
add_str
(
key
.
get_key_len
());
}
/* `used_key_parts` */
String_list
*
parts_list
=
NULL
;
if
(
quick_info
&&
quick_info
->
is_basic
())
parts_list
=
&
quick_info
->
range
.
key_parts_list
;
else
parts_list
=
&
key
.
key_parts_list
;
if
(
parts_list
&&
!
parts_list
->
is_empty
())
{
List_iterator_fast
<
char
>
it
(
*
parts_list
);
const
char
*
name
;
writer
->
add_member
(
"used_key_parts"
).
start_array
();
while
((
name
=
it
++
))
writer
->
add_str
(
name
);
writer
->
end_array
();
}
if
(
quick_info
&&
!
quick_info
->
is_basic
())
{
writer
->
add_member
(
"index_merge"
).
start_object
();
quick_info
->
print_json
(
writer
);
writer
->
end_object
();
}
#if 0
/* `ref` */
if (!ref_list.is_empty())
{
List_iterator_fast<char> it(ref_list);
const char *str;
writer->add_member("ref").start_array();
while ((str= it++))
writer->add_str(str);
writer->end_array();
}
#endif
/* `rows` */
writer
->
add_member
(
"rows"
).
add_ll
(
rows
);
/* `r_rows` */
if
(
is_analyze
&&
tracker
.
has_scans
())
{
ha_rows
avg_rows
=
tracker
.
get_avg_rows
();
writer
->
add_member
(
"r_rows"
).
add_ll
(
avg_rows
);
}
/* UPDATE/DELETE do not produce `filtered` estimate */
/* `r_filtered` */
if
(
is_analyze
)
{
double
r_filtered
=
tracker
.
get_filtered_after_where
();
writer
->
add_member
(
"r_filtered"
).
add_double
(
r_filtered
);
}
if
(
mrr_type
.
length
()
!=
0
)
writer
->
add_member
(
"mrr_type"
).
add_str
(
mrr_type
.
ptr
());
if
(
using_filesort
)
writer
->
add_member
(
"using_filesort"
).
add_ll
(
1
);
if
(
using_io_buffer
)
writer
->
add_member
(
"using_io_buffer"
).
add_ll
(
1
);
if
(
where_cond
)
{
writer
->
add_member
(
"attached_condition"
);
write_item
(
writer
,
where_cond
);
}
writer
->
end_object
();
// table
print_explain_json_for_children
(
query
,
writer
,
is_analyze
);
writer
->
end_object
();
// query_block
}
int
Explain_insert
::
print_explain
(
Explain_query
*
query
,
select_result_sink
*
output
,
uint8
explain_flags
,
...
...
sql/sql_explain.h
View file @
d5fbfb9a
...
...
@@ -432,6 +432,11 @@ class Explain_index_use : public Sql_alloc
public:
String_list
key_parts_list
;
Explain_index_use
()
{
clear
();
}
void
clear
()
{
key_name
=
NULL
;
...
...
@@ -440,8 +445,8 @@ public:
void
set
(
MEM_ROOT
*
root
,
KEY
*
key_name
,
uint
key_len_arg
);
void
set_pseudo_key
(
MEM_ROOT
*
root
,
const
char
*
key_name
);
inline
const
char
*
get_key_name
()
{
return
key_name
;
}
inline
uint
get_key_len
()
{
return
key_len
;
}
inline
const
char
*
get_key_name
()
const
{
return
key_name
;
}
inline
uint
get_key_len
()
const
{
return
key_len
;
}
};
...
...
@@ -584,8 +589,8 @@ public:
private:
void
append_tag_name
(
String
*
str
,
enum
explain_extra_tag
tag
);
void
fill_key_str
(
String
*
key_str
,
bool
is_json
);
void
fill_key_len_str
(
String
*
key_len_str
);
void
fill_key_str
(
String
*
key_str
,
bool
is_json
)
const
;
void
fill_key_len_str
(
String
*
key_len_str
)
const
;
double
get_r_filtered
();
void
tag_to_json
(
Json_writer
*
writer
,
enum
explain_extra_tag
tag
);
};
...
...
@@ -614,14 +619,22 @@ public:
StringBuffer
<
64
>
table_name
;
enum
join_type
jtype
;
StringBuffer
<
128
>
possible_keys_line
;
StringBuffer
<
128
>
key_str
;
StringBuffer
<
128
>
key_len_str
;
String_list
possible_keys
;
/* 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
;
Explain_quick_select
*
quick_info
;
bool
using_where
;
Item
*
where_cond
;
ha_rows
rows
;
bool
using_filesort
;
...
...
@@ -632,8 +645,8 @@ public:
virtual
int
print_explain
(
Explain_query
*
query
,
select_result_sink
*
output
,
uint8
explain_flags
,
bool
is_analyze
);
virtual
void
print_explain_json
(
Explain_query
*
query
,
Json_writer
*
writer
,
bool
is_analyze
)
{
/* EXPLAIN_JSON_NOT_IMPL */
}
virtual
void
print_explain_json
(
Explain_query
*
query
,
Json_writer
*
writer
,
bool
is_analyze
);
};
...
...
@@ -678,8 +691,8 @@ public:
virtual
int
print_explain
(
Explain_query
*
query
,
select_result_sink
*
output
,
uint8
explain_flags
,
bool
is_analyze
);
virtual
void
print_explain_json
(
Explain_query
*
query
,
Json_writer
*
writer
,
bool
is_analyze
)
{
/* EXPLAIN_JSON_NOT_IMPL */
}
virtual
void
print_explain_json
(
Explain_query
*
query
,
Json_writer
*
writer
,
bool
is_analyze
);
};
sql/sql_lex.h
View file @
d5fbfb9a
...
...
@@ -2303,8 +2303,9 @@ public:
void
set_impossible_where
()
{
impossible_where
=
true
;
}
void
set_no_partitions
()
{
no_partitions
=
true
;
}
void
save_explain_data
(
Explain_query
*
query
);
void
save_explain_data_intern
(
Explain_query
*
query
,
Explain_update
*
eu
);
void
save_explain_data
(
MEM_ROOT
*
mem_root
,
Explain_query
*
query
);
void
save_explain_data_intern
(
MEM_ROOT
*
mem_root
,
Explain_query
*
query
,
Explain_update
*
eu
);
virtual
~
Update_plan
()
{}
...
...
@@ -2335,7 +2336,7 @@ public:
scanned_rows
=
rows_arg
;
}
void
save_explain_data
(
Explain_query
*
query
);
void
save_explain_data
(
MEM_ROOT
*
mem_root
,
Explain_query
*
query
);
};
...
...
sql/sql_select.cc
View file @
d5fbfb9a
...
...
@@ -23126,135 +23126,7 @@ int print_explain_message_line(select_result_sink *result,
return
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
;
}
#if 0
int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
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,
return 1;
return 0;
}
#endif
/*
Append MRR information from quick select to the given string
...
...
sql/sql_select.h
View file @
d5fbfb9a
...
...
@@ -1832,8 +1832,10 @@ inline bool optimizer_flag(THD *thd, uint flag)
return
(
thd
->
variables
.
optimizer_switch
&
flag
);
}
/*
int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
SELECT_LEX *select_lex, uint8 select_options);
*/
uint
get_index_for_order
(
ORDER
*
order
,
TABLE
*
table
,
SQL_SELECT
*
select
,
ha_rows
limit
,
ha_rows
*
scanned_limit
,
...
...
@@ -1861,22 +1863,8 @@ int print_explain_message_line(select_result_sink *result,
ha_rows
*
rows
,
const
char
*
message
);
void
explain_append_mrr_info
(
QUICK_RANGE_SELECT
*
quick
,
String
*
res
);
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
);
void
make_possible_keys_line
(
TABLE
*
table
,
key_map
possible_keys
,
String
*
line
);
int
append_possible_keys
(
MEM_ROOT
*
alloc
,
String_list
&
list
,
TABLE
*
table
,
key_map
possible_keys
);
/****************************************************************************
Temporary table support for SQL Runtime
...
...
sql/sql_update.cc
View file @
d5fbfb9a
...
...
@@ -517,7 +517,7 @@ int mysql_update(THD *thd,
*/
if
(
thd
->
lex
->
describe
)
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_serve_apcs
(
thd
,
1
););
...
...
@@ -1037,7 +1037,7 @@ produce_explain_and_leave:
We come here for various "degenerate" query plans: impossible WHERE,
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:
int
err2
=
thd
->
lex
->
explain
->
send_explain
(
thd
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment