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
1951d40a
Commit
1951d40a
authored
Jun 18, 2013
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SHOW] EXPLAIN UPDATE/DELETE, code re-structuring
- Make EXPLAIN UPDATE/DELETE use "Query Plan Footprints", too.
parent
1c6fc3f6
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
152 additions
and
115 deletions
+152
-115
sql/opt_qpf.cc
sql/opt_qpf.cc
+13
-3
sql/opt_qpf.h
sql/opt_qpf.h
+5
-2
sql/sql_delete.cc
sql/sql_delete.cc
+79
-73
sql/sql_lex.cc
sql/sql_lex.cc
+2
-4
sql/sql_lex.h
sql/sql_lex.h
+13
-5
sql/sql_update.cc
sql/sql_update.cc
+40
-28
No files found.
sql/opt_qpf.cc
View file @
1951d40a
...
...
@@ -12,6 +12,7 @@
QPF_query
::
QPF_query
()
{
upd_del_plan
=
NULL
;
memset
(
&
unions
,
0
,
sizeof
(
unions
));
memset
(
&
selects
,
0
,
sizeof
(
selects
));
}
...
...
@@ -19,6 +20,7 @@ QPF_query::QPF_query()
QPF_query
::~
QPF_query
()
{
delete
upd_del_plan
;
uint
i
;
for
(
i
=
0
;
i
<
MAX_TABLES
;
i
++
)
delete
unions
[
i
];
...
...
@@ -70,9 +72,17 @@ void QPF_query::add_node(QPF_node *node)
int
QPF_query
::
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
)
{
// Start with id=1
QPF_node
*
node
=
get_node
(
1
);
return
node
->
print_explain
(
this
,
output
,
explain_flags
);
if
(
upd_del_plan
)
{
upd_del_plan
->
print_explain
(
output
,
explain_flags
);
return
0
;
}
else
{
// Start with id=1
QPF_node
*
node
=
get_node
(
1
);
return
node
->
print_explain
(
this
,
output
,
explain_flags
);
}
}
...
...
sql/opt_qpf.h
View file @
1951d40a
...
...
@@ -161,6 +161,9 @@ public:
/* This will return a select (even if there is a union with this id) */
QPF_select
*
get_select
(
uint
select_id
);
/* Delete_plan inherits from Update_plan */
Update_plan
*
upd_del_plan
;
private:
QPF_union
*
unions
[
MAX_TABLES
];
...
...
@@ -269,10 +272,10 @@ public:
key_map
range_checked_map
;
// valid with ET_USING_MRR
StringBuffer
<
64
>
mrr_type
;
StringBuffer
<
64
>
mrr_type
;
// valid with ET_USING_JOIN_BUFFER
StringBuffer
<
64
>
join_buffer_type
;
StringBuffer
<
64
>
join_buffer_type
;
//TABLE *firstmatch_table;
StringBuffer
<
64
>
firstmatch_table_name
;
...
...
sql/sql_delete.cc
View file @
1951d40a
...
...
@@ -51,8 +51,7 @@
invoked on a running DELETE statement.
*/
int
Delete_plan
::
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
,
bool
*
printed_anything
)
int
Delete_plan
::
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
)
{
if
(
deleting_all_rows
)
{
...
...
@@ -62,37 +61,15 @@ int Delete_plan::print_explain(select_result_sink *output, uint8 explain_flags,
{
return
1
;
}
*
printed_anything
=
true
;
return
0
;
}
return
Update_plan
::
print_explain
(
output
,
explain_flags
,
printed_anything
);
return
Update_plan
::
print_explain
(
output
,
explain_flags
);
}
int
Update_plan
::
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
,
bool
*
printed_anything
)
void
Update_plan
::
save_query_plan_footprint
()
{
if
(
impossible_where
)
{
const
char
*
msg
=
"Impossible where"
;
if
(
print_explain_message_line
(
output
,
explain_flags
,
1
/*select number*/
,
"SIMPLE"
,
msg
))
{
return
1
;
}
*
printed_anything
=
true
;
return
0
;
}
select_lex
->
set_explain_type
(
TRUE
);
select_lex
->
set_explain_type
(
FALSE
);
/*
Print an EXPLAIN line. We dont have join, so we can't directly use
JOIN::print_explain.
We do have a SELECT_LEX (TODO but how is it useful? it has select_type..
and that's it?)
*/
enum
join_type
jtype
;
if
(
select
&&
select
->
quick
)
{
int
quick_type
=
select
->
quick
->
get_type
();
...
...
@@ -112,35 +89,53 @@ int Update_plan::print_explain(select_result_sink *output, uint8 explain_flags,
jtype
=
JT_NEXT
;
}
StringBuffer
<
128
>
possible_keys_line
;
using_where
=
test
(
select
&&
select
->
cond
);
//using_filesort is already set
make_possible_keys_line
(
table
,
possible_keys
,
&
possible_keys_line
);
const
char
*
key_name
;
const
char
*
key_len
;
StringBuffer
<
128
>
key_str
;
StringBuffer
<
128
>
key_len_str
;
StringBuffer
<
128
>
extra_str
;
/* Calculate key_len */
if
(
select
&&
select
->
quick
)
{
select
->
quick
->
add_keys_and_lengths
(
&
key_str
,
&
key_len_str
);
key_name
=
key_str
.
c_ptr
();
key_len
=
key_len_str
.
c_ptr
();
}
else
{
key_name
=
(
index
==
MAX_KEY
)
?
NULL
:
table
->
key_info
[
index
].
name
;
key_len
=
NULL
;
if
(
index
!=
MAX_KEY
)
{
key_str
.
append
(
table
->
key_info
[
index
].
name
);
}
// key_len stays NULL
}
if
(
select
&&
select
->
cond
)
extra_str
.
append
(
STRING_WITH_LEN
(
"Using where"
));
if
(
select
&&
select
->
quick
&&
select
->
quick
->
get_type
()
==
QUICK_SELECT_I
::
QS_TYPE_RANGE
)
{
explain_append_mrr_info
((
QUICK_RANGE_SELECT
*
)
select
->
quick
,
&
extra_str
);
explain_append_mrr_info
((
QUICK_RANGE_SELECT
*
)
select
->
quick
,
&
mrr_type
);
}
}
int
Update_plan
::
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
)
{
StringBuffer
<
64
>
extra_str
;
if
(
impossible_where
)
{
const
char
*
msg
=
"Impossible where"
;
if
(
print_explain_message_line
(
output
,
explain_flags
,
1
/*select number*/
,
"SIMPLE"
,
msg
))
{
return
1
;
}
return
0
;
}
if
(
using_where
)
extra_str
.
append
(
STRING_WITH_LEN
(
"Using where"
));
if
(
mrr_type
.
length
()
!=
0
)
{
if
(
extra_str
.
length
()
!=
0
)
extra_str
.
append
(
STRING_WITH_LEN
(
"; "
));
extra_str
.
append
(
mrr_type
);
}
if
(
using_filesort
)
...
...
@@ -160,15 +155,14 @@ int Update_plan::print_explain(select_result_sink *output, uint8 explain_flags,
select_lex
->
type
,
table
->
pos_in_table_list
->
alias
,
// partitions,
jtype
,
(
enum
join_type
)
jtype
,
possible_keys_line
.
length
()
?
possible_keys_line
.
c_ptr
()
:
NULL
,
key_
name
,
key_len
,
key_
str
.
length
()
?
key_str
.
c_ptr
()
:
NULL
,
key_len
_str
.
length
()
?
key_len_str
.
c_ptr
()
:
NULL
,
NULL
,
/* 'ref' is always NULL in single-table EXPLAIN DELETE */
select
?
select
->
records
:
table_rows
,
extra_str
.
c_ptr
());
*
printed_anything
=
true
;
/*
psergey-todo: handle all this through saving QPF.
...
...
@@ -211,10 +205,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SELECT_LEX
*
select_lex
=
&
thd
->
lex
->
select_lex
;
killed_state
killed_status
=
NOT_KILLED
;
THD
::
enum_binlog_query_type
query_type
=
THD
::
ROW_QUERY_TYPE
;
Delete_plan
query
_plan
;
query_plan
.
index
=
MAX_KEY
;
query_plan
.
using_filesort
=
FALSE
;
Delete_plan
*
query_plan
=
new
Delete
_plan
;
query_plan
->
index
=
MAX_KEY
;
query_plan
->
using_filesort
=
FALSE
;
DBUG_ENTER
(
"mysql_delete"
);
if
(
open_and_lock_tables
(
thd
,
table_list
,
TRUE
,
0
))
...
...
@@ -238,8 +232,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
}
thd_proc_info
(
thd
,
"init"
);
table
->
map
=
1
;
query_plan
.
select_lex
=
&
thd
->
lex
->
select_lex
;
query_plan
.
table
=
table
;
query_plan
->
select_lex
=
&
thd
->
lex
->
select_lex
;
query_plan
->
table
=
table
;
if
(
mysql_prepare_delete
(
thd
,
table_list
,
&
conds
))
DBUG_RETURN
(
TRUE
);
...
...
@@ -314,7 +308,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
ha_rows
const
maybe_deleted
=
table
->
file
->
stats
.
records
;
DBUG_PRINT
(
"debug"
,
(
"Trying to use delete_all_rows()"
));
query_plan
.
set_delete_all_rows
(
maybe_deleted
);
query_plan
->
set_delete_all_rows
(
maybe_deleted
);
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
...
...
@@ -344,7 +338,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if
(
result
==
Item
::
COND_FALSE
)
// Impossible where
{
limit
=
0
;
query_plan
.
set_impossible_where
();
query_plan
->
set_impossible_where
();
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
}
...
...
@@ -372,7 +366,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
DBUG_RETURN
(
TRUE
);
if
((
select
&&
select
->
check_quick
(
thd
,
safe_update
,
limit
))
||
!
limit
)
{
query_plan
.
set_impossible_where
();
query_plan
->
set_impossible_where
();
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
...
...
@@ -413,20 +407,22 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if
(
select
&&
select
->
quick
&&
select
->
quick
->
unique_key_range
())
{
// Single row select (always "ordered")
query_plan
.
using_filesort
=
FALSE
;
query_plan
.
index
=
MAX_KEY
;
query_plan
->
using_filesort
=
FALSE
;
query_plan
->
index
=
MAX_KEY
;
}
else
query_plan
.
index
=
get_index_for_order
(
order
,
table
,
select
,
limit
,
&
query_plan
.
using_filesort
,
&
reverse
);
query_plan
->
index
=
get_index_for_order
(
order
,
table
,
select
,
limit
,
&
query_plan
->
using_filesort
,
&
reverse
);
}
query_plan
.
select
=
select
;
query_plan
.
possible_keys
=
table
->
quick_keys
;
query_plan
.
table_rows
=
table
->
file
->
stats
.
records
;
thd
->
lex
->
upd_del_plan
=
&
query_plan
;
query_plan
->
select
=
select
;
query_plan
->
possible_keys
=
table
->
quick_keys
;
query_plan
->
table_rows
=
table
->
file
->
stats
.
records
;
thd
->
lex
->
query_plan_footprint
=
new
QPF_query
;
thd
->
lex
->
query_plan_footprint
->
upd_del_plan
=
query_plan
;
/*
Ok, we have generated a query plan for the DELETE.
- if we're running EXPLAIN DELETE, goto produce explain output
...
...
@@ -435,11 +431,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
query_plan
->
save_query_plan_footprint
();
thd
->
apc_target
.
enable
();
DBUG_EXECUTE_IF
(
"show_explain_probe_delete_exec_start"
,
dbug_serve_apcs
(
thd
,
1
););
if
(
query_plan
.
using_filesort
)
if
(
query_plan
->
using_filesort
)
{
ha_rows
examined_rows
;
ha_rows
found_rows
;
...
...
@@ -447,7 +444,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SORT_FIELD
*
sortorder
;
{
DBUG_ASSERT
(
query_plan
.
index
==
MAX_KEY
);
DBUG_ASSERT
(
query_plan
->
index
==
MAX_KEY
);
table
->
sort
.
io_cache
=
(
IO_CACHE
*
)
my_malloc
(
sizeof
(
IO_CACHE
),
MYF
(
MY_FAE
|
MY_ZEROFILL
|
MY_THREAD_SPECIFIC
));
...
...
@@ -483,7 +480,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
thd
->
apc_target
.
disable
();
DBUG_RETURN
(
TRUE
);
}
if
(
query_plan
.
index
==
MAX_KEY
||
(
select
&&
select
->
quick
))
if
(
query_plan
->
index
==
MAX_KEY
||
(
select
&&
select
->
quick
))
{
if
(
init_read_record
(
&
info
,
thd
,
table
,
select
,
1
,
1
,
FALSE
))
{
...
...
@@ -494,7 +491,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
}
}
else
init_read_record_idx
(
&
info
,
thd
,
table
,
1
,
query_plan
.
index
,
reverse
);
init_read_record_idx
(
&
info
,
thd
,
table
,
1
,
query_plan
->
index
,
reverse
);
init_ftfuncs
(
thd
,
select_lex
,
1
);
thd_proc_info
(
thd
,
"updating"
);
...
...
@@ -587,6 +584,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
(
void
)
table
->
file
->
extra
(
HA_EXTRA_NORMAL
);
thd
->
apc_target
.
disable
();
if
(
thd
->
lex
->
query_plan_footprint
)
{
delete
thd
->
lex
->
query_plan_footprint
;
thd
->
lex
->
query_plan_footprint
=
NULL
;
}
cleanup:
/*
Invalidate the table in the query cache if something changed. This must
...
...
@@ -650,21 +652,25 @@ cleanup:
/* Special exits */
exit_without_my_ok:
thd
->
lex
->
upd_del_plan
=
&
query_plan
;
query_plan
->
save_query_plan_footprint
();
thd
->
lex
->
query_plan_footprint
->
upd_del_plan
=
query_plan
;
select_send
*
result
;
bool
printed_anything
;
if
(
!
(
result
=
new
select_send
()))
return
1
;
/* purecov: inspected */
List
<
Item
>
dummy
;
/* note: looked in 5.6 and they too use a dummy list like this */
result
->
prepare
(
dummy
,
&
thd
->
lex
->
unit
);
thd
->
send_explain_fields
(
result
);
int
err2
=
thd
->
lex
->
print_explain
(
result
,
0
/* explain flags*/
,
&
printed_anything
);
int
err2
=
thd
->
lex
->
query_plan_footprint
->
print_explain
(
result
,
0
);
if
(
err2
)
result
->
abort_result_set
();
else
result
->
send_eof
();
delete
thd
->
lex
->
query_plan_footprint
;
thd
->
lex
->
query_plan_footprint
=
NULL
;
delete
select
;
free_underlaid_joins
(
thd
,
select_lex
);
...
...
sql/sql_lex.cc
View file @
1951d40a
...
...
@@ -448,7 +448,6 @@ void lex_start(THD *thd)
lex
->
thd
=
lex
->
unit
.
thd
=
thd
;
lex
->
upd_del_plan
=
NULL
;
lex
->
context_stack
.
empty
();
lex
->
unit
.
init_query
();
lex
->
unit
.
init_select
();
...
...
@@ -2561,7 +2560,6 @@ LEX::LEX()
INITIAL_LEX_PLUGIN_LIST_SIZE
,
0
);
reset_query_tables_list
(
TRUE
);
mi
.
init
();
upd_del_plan
=
NULL
;
}
...
...
@@ -4176,11 +4174,11 @@ bool st_select_lex::is_merged_child_of(st_select_lex *ancestor)
int
LEX
::
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
,
bool
*
printed_anything
)
{
if
(
upd_del_plan
)
/*
if (upd_del_plan)
{
upd_del_plan->print_explain(output, explain_flags, printed_anything);
return 0;
}
}
*/
//int res= unit.print_explain(output, explain_flags, printed_anything);
//psergey-todo: here, we should make Query Plan Footprint, and then produce
...
...
sql/sql_lex.h
View file @
1951d40a
...
...
@@ -2378,6 +2378,7 @@ public:
SQL_SELECT
*
select
;
uint
index
;
ha_rows
table_rows
;
/* Use if select==NULL */
/*
Top-level select_lex. Most of its fields are not used, we need it only to
get to the subqueries.
...
...
@@ -2390,11 +2391,20 @@ public:
/* Set this plan to be a plan to do nothing because of impossible WHRE*/
void
set_impossible_where
()
{
impossible_where
=
true
;
}
virtual
int
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
,
bool
*
printed_anything
);
virtual
int
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
);
virtual
~
Update_plan
()
{}
Update_plan
()
:
impossible_where
(
false
),
using_filesort
(
false
)
{}
void
save_query_plan_footprint
();
/* Query Plan Footprint fields */
// cant use it here: enum join_type
int
jtype
;
bool
using_where
;
StringBuffer
<
128
>
possible_keys_line
;
StringBuffer
<
128
>
key_str
;
StringBuffer
<
128
>
key_len_str
;
StringBuffer
<
64
>
mrr_type
;
};
...
...
@@ -2414,8 +2424,7 @@ public:
deleting_all_rows
=
true
;
table_rows
=
rows_arg
;
}
int
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
,
bool
*
printed_anything
);
int
print_explain
(
select_result_sink
*
output
,
uint8
explain_flags
);
};
...
...
@@ -2432,7 +2441,6 @@ struct LEX: public Query_tables_list
SELECT_LEX
*
all_selects_list
;
/* For single-table DELETE: its query plan */
Update_plan
*
upd_del_plan
;
QPF_query
*
query_plan_footprint
;
char
*
length
,
*
dec
,
*
change
;
...
...
sql/sql_update.cc
View file @
1951d40a
...
...
@@ -276,9 +276,7 @@ int mysql_update(THD *thd,
ulonglong
id
;
List
<
Item
>
all_fields
;
killed_state
killed_status
=
NOT_KILLED
;
Update_plan
query_plan
;
query_plan
.
index
=
MAX_KEY
;
query_plan
.
using_filesort
=
FALSE
;
Update_plan
*
query_plan
;
bool
apc_target_enabled
=
false
;
// means was enabled *by code this function*
DBUG_ENTER
(
"mysql_update"
);
...
...
@@ -317,9 +315,12 @@ int mysql_update(THD *thd,
/* Calculate "table->covering_keys" based on the WHERE */
table
->
covering_keys
=
table
->
s
->
keys_in_use
;
table
->
quick_keys
.
clear_all
();
query_plan
.
select_lex
=
&
thd
->
lex
->
select_lex
;
query_plan
.
table
=
table
;
query_plan
=
new
Update_plan
;
query_plan
->
index
=
MAX_KEY
;
query_plan
->
using_filesort
=
FALSE
;
query_plan
->
select_lex
=
&
thd
->
lex
->
select_lex
;
query_plan
->
table
=
table
;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Force privilege re-checking for views after they have been opened. */
want_privilege
=
(
table_list
->
view
?
UPDATE_ACL
:
...
...
@@ -378,7 +379,7 @@ int mysql_update(THD *thd,
if
(
cond_value
==
Item
::
COND_FALSE
)
{
limit
=
0
;
// Impossible WHERE
query_plan
.
set_impossible_where
();
query_plan
->
set_impossible_where
();
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
}
...
...
@@ -411,7 +412,7 @@ int mysql_update(THD *thd,
if
(
error
||
!
limit
||
thd
->
is_error
()
||
(
select
&&
select
->
check_quick
(
thd
,
safe_update
,
limit
)))
{
query_plan
.
set_impossible_where
();
query_plan
->
set_impossible_where
();
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
...
...
@@ -453,16 +454,16 @@ int mysql_update(THD *thd,
if
(
select
&&
select
->
quick
&&
select
->
quick
->
unique_key_range
())
{
// Single row select (always "ordered"): Ok to use with key field UPDATE
need_sort
=
FALSE
;
query_plan
.
index
=
MAX_KEY
;
query_plan
->
index
=
MAX_KEY
;
used_key_is_modified
=
FALSE
;
}
else
{
query_plan
.
index
=
get_index_for_order
(
order
,
table
,
select
,
limit
,
&
need_sort
,
&
reverse
);
query_plan
->
index
=
get_index_for_order
(
order
,
table
,
select
,
limit
,
&
need_sort
,
&
reverse
);
if
(
select
&&
select
->
quick
)
{
DBUG_ASSERT
(
need_sort
||
query_plan
.
index
==
select
->
quick
->
index
);
DBUG_ASSERT
(
need_sort
||
query_plan
->
index
==
select
->
quick
->
index
);
used_key_is_modified
=
(
!
select
->
quick
->
unique_key_range
()
&&
select
->
quick
->
is_keys_used
(
table
->
write_set
));
}
...
...
@@ -470,11 +471,11 @@ int mysql_update(THD *thd,
{
if
(
need_sort
)
{
// Assign table scan index to check below for modified key fields:
query_plan
.
index
=
table
->
file
->
key_used_on_scan
;
query_plan
->
index
=
table
->
file
->
key_used_on_scan
;
}
if
(
query_plan
.
index
!=
MAX_KEY
)
if
(
query_plan
->
index
!=
MAX_KEY
)
{
// Check if we are modifying a key that we are used to search with:
used_key_is_modified
=
is_key_used
(
table
,
query_plan
.
index
,
table
->
write_set
);
used_key_is_modified
=
is_key_used
(
table
,
query_plan
->
index
,
table
->
write_set
);
}
}
}
...
...
@@ -484,10 +485,11 @@ int mysql_update(THD *thd,
- Save the decisions in the query plan
- if we're running EXPLAIN UPDATE, get out
*/
query_plan
.
select
=
select
;
query_plan
.
possible_keys
=
table
->
quick_keys
;
query_plan
.
table_rows
=
table
->
file
->
stats
.
records
;
thd
->
lex
->
upd_del_plan
=
&
query_plan
;
query_plan
->
select
=
select
;
query_plan
->
possible_keys
=
table
->
quick_keys
;
query_plan
->
table_rows
=
table
->
file
->
stats
.
records
;
thd
->
lex
->
query_plan_footprint
=
new
QPF_query
;
thd
->
lex
->
query_plan_footprint
->
upd_del_plan
=
query_plan
;
/*
Ok, we have generated a query plan for the UPDATE.
...
...
@@ -496,7 +498,8 @@ int mysql_update(THD *thd,
*/
if
(
thd
->
lex
->
describe
)
goto
exit_without_my_ok
;
query_plan
->
save_query_plan_footprint
();
thd
->
apc_target
.
enable
();
apc_target_enabled
=
true
;
DBUG_EXECUTE_IF
(
"show_explain_probe_update_exec_start"
,
...
...
@@ -515,8 +518,8 @@ int mysql_update(THD *thd,
DBUG_ASSERT
(
table
->
read_set
==
&
table
->
def_read_set
);
DBUG_ASSERT
(
table
->
write_set
==
&
table
->
def_write_set
);
if
(
query_plan
.
index
<
MAX_KEY
&&
old_covering_keys
.
is_set
(
query_plan
.
index
))
table
->
add_read_columns_used_by_index
(
query_plan
.
index
);
if
(
query_plan
->
index
<
MAX_KEY
&&
old_covering_keys
.
is_set
(
query_plan
->
index
))
table
->
add_read_columns_used_by_index
(
query_plan
->
index
);
else
table
->
use_all_columns
();
...
...
@@ -582,13 +585,13 @@ int mysql_update(THD *thd,
Full index scan must be started with init_read_record_idx
*/
if
(
query_plan
.
index
==
MAX_KEY
||
(
select
&&
select
->
quick
))
if
(
query_plan
->
index
==
MAX_KEY
||
(
select
&&
select
->
quick
))
{
if
(
init_read_record
(
&
info
,
thd
,
table
,
select
,
0
,
1
,
FALSE
))
goto
err
;
}
else
init_read_record_idx
(
&
info
,
thd
,
table
,
1
,
query_plan
.
index
,
reverse
);
init_read_record_idx
(
&
info
,
thd
,
table
,
1
,
query_plan
->
index
,
reverse
);
thd_proc_info
(
thd
,
"Searching rows for update"
);
ha_rows
tmp_limit
=
limit
;
...
...
@@ -1002,6 +1005,12 @@ err:
if
(
apc_target_enabled
)
thd
->
apc_target
.
disable
();
if
(
thd
->
lex
->
query_plan_footprint
)
{
delete
thd
->
lex
->
query_plan_footprint
;
thd
->
lex
->
query_plan_footprint
=
NULL
;
}
delete
select
;
free_underlaid_joins
(
thd
,
select_lex
);
table
->
disable_keyread
();
...
...
@@ -1010,22 +1019,25 @@ err:
exit_without_my_ok:
DBUG_ASSERT
(
!
apc_target_enabled
);
thd
->
lex
->
upd_del_plan
=
&
query_plan
;
query_plan
->
save_query_plan_footprint
();
thd
->
lex
->
query_plan_footprint
->
upd_del_plan
=
query_plan
;
select_send
*
result
;
bool
printed_anything
;
if
(
!
(
result
=
new
select_send
()))
return
1
;
/* purecov: inspected */
List
<
Item
>
dummy
;
/* note: looked in 5.6 and they too use a dummy list like this */
result
->
prepare
(
dummy
,
&
thd
->
lex
->
unit
);
thd
->
send_explain_fields
(
result
);
int
err2
=
thd
->
lex
->
print_explain
(
result
,
0
/* explain flags*/
,
&
printed_anything
);
int
err2
=
thd
->
lex
->
query_plan_footprint
->
print_explain
(
result
,
0
);
if
(
err2
)
result
->
abort_result_set
();
else
result
->
send_eof
();
delete
thd
->
lex
->
query_plan_footprint
;
thd
->
lex
->
query_plan_footprint
=
NULL
;
delete
select
;
free_underlaid_joins
(
thd
,
select_lex
);
DBUG_RETURN
((
error
>=
0
||
thd
->
is_error
())
?
1
:
0
);
...
...
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