Commit 99a8bfe6 authored by Sergey Petrunya's avatar Sergey Petrunya

[SHOW] EXPLAIN UPDATE/DELETE, code re-structuring

- Update view.result (old EXPLAIN didn't match the execution)
- Put in a stub code to work around the 
  SELECT ... UNION SELECT ... ORDER BY (subuqery) problem
parent 79392b93
...@@ -16,4 +16,4 @@ read_many_rows_innodb : Bug#11748886 2010-11-15 mattiasj report already exist ...@@ -16,4 +16,4 @@ read_many_rows_innodb : Bug#11748886 2010-11-15 mattiasj report already exist
archive-big : Bug#11817185 2011-03-10 Anitha Disabled since this leads to timeout on Solaris Sparc archive-big : Bug#11817185 2011-03-10 Anitha Disabled since this leads to timeout on Solaris Sparc
log_tables-big : Bug#11756699 2010-11-15 mattiasj report already exists log_tables-big : Bug#11756699 2010-11-15 mattiasj report already exists
mysql_embedded : Bug#12561297 2011-05-14 Anitha Dependent on PB2 changes - eventum#41836 mysql_embedded : Bug#12561297 2011-05-14 Anitha Dependent on PB2 changes - eventum#41836
show_explain : Psergey: random timeout in range-checked-for-each record query. #show_explain : Psergey: random timeout in range-checked-for-each record query.
...@@ -3584,7 +3584,7 @@ View Create View character_set_client collation_connection ...@@ -3584,7 +3584,7 @@ View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` FORCE INDEX (PRIMARY) FORCE INDEX (`b`) order by `t1`.`a` latin1 latin1_swedish_ci v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` FORCE INDEX (PRIMARY) FORCE INDEX (`b`) order by `t1`.`a` latin1 latin1_swedish_ci
EXPLAIN SELECT * FROM v1; EXPLAIN SELECT * FROM v1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 4 NULL 15 1 SIMPLE t1 ALL NULL NULL NULL NULL 15
CREATE VIEW v2 AS SELECT * FROM t1 USE KEY () ORDER BY a; CREATE VIEW v2 AS SELECT * FROM t1 USE KEY () ORDER BY a;
SHOW CREATE VIEW v2; SHOW CREATE VIEW v2;
View Create View character_set_client collation_connection View Create View character_set_client collation_connection
......
...@@ -159,7 +159,9 @@ void Update_plan::save_query_plan_footprint_intern(QPF_query *query, QPF_update ...@@ -159,7 +159,9 @@ void Update_plan::save_query_plan_footprint_intern(QPF_query *query, QPF_update
qpf->add_child(unit->first_select()->select_number); qpf->add_child(unit->first_select()->select_number);
//TODO: temporary?: //TODO: temporary?:
unit->save_qpf(query); // A: yes. optimizing children subqueries has caused them to save QPFs,
// automatically.
//unit->save_qpf(query);
} }
} }
......
...@@ -4172,29 +4172,32 @@ bool st_select_lex::is_merged_child_of(st_select_lex *ancestor) ...@@ -4172,29 +4172,32 @@ bool st_select_lex::is_merged_child_of(st_select_lex *ancestor)
return all_merged; return all_merged;
} }
/*
This is used by SHOW EXPLAIN. It assuses query plan has been already
collected into QPF structures and we only need to print it out.
*/
int LEX::print_explain(select_result_sink *output, uint8 explain_flags, int LEX::print_explain(select_result_sink *output, uint8 explain_flags,
bool *printed_anything) bool *printed_anything) //TODO: remove printed_anything
{ {
/* if (upd_del_plan) int res;
if (query_plan_footprint)
{ {
upd_del_plan->print_explain(output, explain_flags, printed_anything); res= query_plan_footprint->print_explain(output, explain_flags);
return 0; *printed_anything= true;
}*/ }
//int res= unit.print_explain(output, explain_flags, printed_anything); else
{
//psergey-todo: here, we should make Query Plan Footprint, and then produce res= 0;
// an EXPLAIN output from it. *printed_anything= false;
/* }
The new, QueryPlanFootprint way: return res;
*/
QPF_query qpf;
unit.save_qpf(&qpf);
//return res;
return 0;
} }
/*
*/
void st_select_lex::save_qpf(QPF_query *output) void st_select_lex::save_qpf(QPF_query *output)
{ {
int res; int res;
...@@ -4261,92 +4264,12 @@ void st_select_lex::save_qpf(QPF_query *output) ...@@ -4261,92 +4264,12 @@ void st_select_lex::save_qpf(QPF_query *output)
return ;//res; return ;//res;
} }
#if 0
int st_select_lex::print_explain(select_result_sink *output,
uint8 explain_flags,
bool *printed_anything)
{
int res;
if (join && join->have_query_plan == JOIN::QEP_AVAILABLE)
{
/*
There is a number of reasons join can be marked as degenerate, so all
three conditions below can happen simultaneously, or individually:
*/
*printed_anything= TRUE;
if (!join->table_count || !join->tables_list || join->zero_result_cause)
{
/* It's a degenerate join */
const char *cause= join->zero_result_cause ? join-> zero_result_cause :
"No tables used";
res= join->print_explain(output, explain_flags, TRUE, FALSE, FALSE,
FALSE, cause);
}
else
{
res= join->print_explain(output, explain_flags, TRUE,
join->need_tmp, // need_tmp_table
!join->skip_sort_order && !join->no_order &&
(join->order || join->group_list), // bool need_order
join->select_distinct, // bool distinct
NULL); //const char *message
}
if (res)
goto err;
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
unit;
unit= unit->next_unit())
{
/*
Display subqueries only if they are not parts of eliminated WHERE/ON
clauses.
*/
if (!(unit->item && unit->item->eliminated))
{
if ((res= unit->print_explain(output, explain_flags, printed_anything)))
goto err;
}
}
}
else
{
const char *msg;
if (!join)
DBUG_ASSERT(0); /* Seems not to be possible */
/* Not printing anything useful, don't touch *printed_anything here */
if (join->have_query_plan == JOIN::QEP_NOT_PRESENT_YET)
msg= "Not yet optimized";
else
{
DBUG_ASSERT(join->have_query_plan == JOIN::QEP_DELETED);
msg= "Query plan already deleted";
}
set_explain_type(TRUE/* on_the_fly */);
res= print_explain_message_line(output, 0/*options*/, select_number, type,
msg);
}
err:
return res;
}
#endif
int st_select_lex_unit::save_qpf(QPF_query *output) int st_select_lex_unit::save_union_qpf(QPF_query *output)
{ {
//int res= 0;
SELECT_LEX *first= first_select(); SELECT_LEX *first= first_select();
if (!first->next_select())
{
/* This is a 1-way UNION, i.e. not really a UNION */
if (!output->get_select(first->select_number))
first->save_qpf(output);
return 0;
}
QPF_union *qpfu= new (output->mem_root) QPF_union; QPF_union *qpfu= new (output->mem_root) QPF_union;
/* /*
TODO: The following code should be eliminated. If we have a capability to TODO: The following code should be eliminated. If we have a capability to
save Query Plan Footprints, we should just save them, and never need to save Query Plan Footprints, we should just save them, and never need to
...@@ -4380,53 +4303,48 @@ int st_select_lex_unit::save_qpf(QPF_query *output) ...@@ -4380,53 +4303,48 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
// Save the UNION node // Save the UNION node
output->add_node(qpfu); output->add_node(qpfu);
#if 0 qpfu->fake_select_type= "UNION RESULT";
/* Note: fake_select_lex->join may be NULL or non-NULL at this point */ qpfu->using_filesort= test(global_parameters->order_list.first);
return 0;
}
int st_select_lex_unit::save_union_qpf_part2(QPF_query *output)
{
QPF_union *qpfu= output->get_union(first_select()->select_number);
if (fake_select_lex) if (fake_select_lex)
{ {
res= print_fake_select_lex_join(output, TRUE /* on the fly */, for (SELECT_LEX_UNIT *unit= fake_select_lex->first_inner_unit();
fake_select_lex, explain_flags); unit; unit= unit->next_unit())
{
if (!(unit->item && unit->item->eliminated))
{
qpfu->add_child(unit->first_select()->select_number);
}
}
} }
return res;
#endif
return 0; return 0;
} }
#if 0
int st_select_lex_unit::print_explain(select_result_sink *output, int st_select_lex_unit::save_qpf(QPF_query *output)
uint8 explain_flags, bool *printed_anything)
{ {
int res= 0; //int res= 0;
SELECT_LEX *first= first_select(); SELECT_LEX *first= first_select();
if (first && !first->next_select() && !first->join)
{
/*
If there is only one child, 'first', and it has join==NULL, emit "not in
EXPLAIN state" error.
*/
const char *msg="Query plan already deleted";
first->set_explain_type(TRUE/* on_the_fly */);
res= print_explain_message_line(output, 0/*options*/, first->select_number,
first->type, msg);
return res;
}
for (SELECT_LEX *sl= first; sl; sl= sl->next_select()) if (!first->next_select())
{ {
if ((res= sl->print_explain(output, explain_flags, printed_anything))) /* This is a 1-way UNION, i.e. not really a UNION */
break; if (!output->get_select(first->select_number))
first->save_qpf(output);
return 0;
} }
/* Note: fake_select_lex->join may be NULL or non-NULL at this point */ save_union_qpf(output);
if (fake_select_lex)
{ return 0;
res= print_fake_select_lex_join(output, TRUE /* on the fly */,
fake_select_lex, explain_flags);
}
return res;
} }
#endif
/** /**
A routine used by the parser to decide whether we are specifying a full A routine used by the parser to decide whether we are specifying a full
......
...@@ -733,6 +733,8 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -733,6 +733,8 @@ class st_select_lex_unit: public st_select_lex_node {
List<Item> *get_unit_column_types(); List<Item> *get_unit_column_types();
int save_qpf(QPF_query *output); int save_qpf(QPF_query *output);
int save_union_qpf(QPF_query *output);
int save_union_qpf_part2(QPF_query *output);
}; };
typedef class st_select_lex_unit SELECT_LEX_UNIT; typedef class st_select_lex_unit SELECT_LEX_UNIT;
......
This diff is collapsed.
...@@ -626,6 +626,9 @@ bool st_select_lex_unit::exec() ...@@ -626,6 +626,9 @@ bool st_select_lex_unit::exec()
saved_error= optimize(); saved_error= optimize();
save_union_qpf(thd->lex->query_plan_footprint);
if (uncacheable || !item || !item->assigned() || describe) if (uncacheable || !item || !item->assigned() || describe)
{ {
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select()) for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
...@@ -772,6 +775,9 @@ bool st_select_lex_unit::exec() ...@@ -772,6 +775,9 @@ bool st_select_lex_unit::exec()
*/ */
if (!fake_select_lex->ref_pointer_array) if (!fake_select_lex->ref_pointer_array)
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items; fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
save_union_qpf_part2(thd->lex->query_plan_footprint);
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array, saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list, &result_table_list,
......
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