Some code optimisations related to EXPLAIN of derived tables and the

resulting code cleanup in our main loop.
parent bd6f8e0b
...@@ -71,8 +71,8 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from ...@@ -71,8 +71,8 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
explain select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from explain select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt; (select * from t2 where a>1) as tt;
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
3 DERIVED t2 ALL NULL NULL NULL NULL 2 where used
1 PRIMARY <derived3> system NULL NULL NULL NULL 1 1 PRIMARY <derived3> system NULL NULL NULL NULL 1
3 DERIVED t2 ALL NULL NULL NULL NULL 2 where used
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 where used; Using filesort 2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 where used; Using filesort
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1); select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a a
......
...@@ -399,8 +399,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, ...@@ -399,8 +399,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result); select_result *result);
int mysql_union(THD *thd, LEX *lex,select_result *result); int mysql_union(THD *thd, LEX *lex,select_result *result);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t, int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
bool tables_is_opened);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field, Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item); bool group,bool modify_item);
......
...@@ -28,8 +28,7 @@ ...@@ -28,8 +28,7 @@
static const char *any_db="*any*"; // Special symbol for check_access static const char *any_db="*any*"; // Special symbol for check_access
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t, int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
bool tables_is_opened)
{ {
/* /*
TODO: make derived tables with union inside (now only 1 SELECT may be TODO: make derived tables with union inside (now only 1 SELECT may be
...@@ -58,7 +57,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t, ...@@ -58,7 +57,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
if (cursor->derived) if (cursor->derived)
{ {
res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived, res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived,
cursor, 0); cursor);
if (res) DBUG_RETURN(res); if (res) DBUG_RETURN(res);
} }
} }
...@@ -68,7 +67,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t, ...@@ -68,7 +67,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
while ((item= it++)) while ((item= it++))
item_list.push_back(item); item_list.push_back(item);
if (tables_is_opened || !(res=open_and_lock_tables(thd,tables))) if (!(res=open_and_lock_tables(thd,tables)))
{ {
if (setup_fields(thd,tables,item_list,0,0,1)) if (setup_fields(thd,tables,item_list,0,0,1))
{ {
...@@ -112,7 +111,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t, ...@@ -112,7 +111,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
t->real_name=table->real_name; t->real_name=table->real_name;
t->table=table; t->table=table;
table->derived_select_number= sl->select_number; table->derived_select_number= sl->select_number;
sl->exclude(); if (!lex->describe)
sl->exclude();
t->db= (tables && tables->db && tables->db[0]) ? t->db : thd->db; t->db= (tables && tables->db && tables->db[0]) ? t->db : thd->db;
t->derived=(SELECT_LEX *)0; // just in case ... t->derived=(SELECT_LEX *)0; // just in case ...
} }
......
...@@ -959,6 +959,7 @@ void st_select_lex::init_query() ...@@ -959,6 +959,7 @@ void st_select_lex::init_query()
table_list.next= (byte**) &table_list.first; table_list.next= (byte**) &table_list.first;
item_list.empty(); item_list.empty();
join= 0; join= 0;
olap= UNSPECIFIED_OLAP_TYPE;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
......
...@@ -1328,74 +1328,24 @@ mysql_execute_command(THD *thd) ...@@ -1328,74 +1328,24 @@ mysql_execute_command(THD *thd)
#endif #endif
} }
select_result *explain_result= 0;
/* /*
TODO: make derived tables processing 'inside' SELECT processing. TODO: make derived tables processing 'inside' SELECT processing.
TODO: solve problem with depended derived tables in subselects TODO: solve problem with depended derived tables in subselects
*/ */
if (lex->sql_command == SQLCOM_SELECT && if (lex->derived_tables)
lex->describe && lex->derived_tables)
{
if (!(explain_result= new select_send()))
{
send_error(thd, ER_OUT_OF_RESOURCES);
DBUG_VOID_RETURN;
}
//check rights
for (cursor= tables;
cursor;
cursor= cursor->next)
if (cursor->derived)
{
TABLE_LIST *tables=
(TABLE_LIST *)((SELECT_LEX_UNIT *)
cursor->derived)->first_select()->table_list.first;
int res;
if (tables)
res= check_table_access(thd,SELECT_ACL, tables);
else
res= check_access(thd, SELECT_ACL, any_db);
if (res)
DBUG_VOID_RETURN;
}
thd->send_explain_fields(explain_result);
// EXPLAIN derived tables
for (cursor= tables;
cursor;
cursor= cursor->next)
if (cursor->derived)
{
SELECT_LEX *select_lex= ((SELECT_LEX_UNIT *)
cursor->derived)->first_select();
if (!open_and_lock_tables(thd,
(TABLE_LIST*) select_lex->table_list.first))
{
mysql_explain_select(thd, select_lex,
"DERIVED", explain_result);
// execute derived table SELECT to provide table for other SELECTs
if (mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived,
cursor, 1))
DBUG_VOID_RETURN;
}
else
DBUG_VOID_RETURN;
}
}
else if (lex->derived_tables)
{ {
for (TABLE_LIST *cursor= tables; for (TABLE_LIST *cursor= tables;
cursor; cursor;
cursor= cursor->next) cursor= cursor->next)
if (cursor->derived && (res=mysql_derived(thd, lex, if (cursor->derived && (res=mysql_derived(thd, lex,
(SELECT_LEX_UNIT *)cursor->derived, (SELECT_LEX_UNIT *)cursor->derived,
cursor, 0))) cursor)))
{ {
if (res < 0) if (res < 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
} }
if ((lex->select_lex.next_select_in_list() && if ((lex->select_lex.next_select_in_list() &&
lex->unit.create_total_list(thd, lex, &tables)) || lex->unit.create_total_list(thd, lex, &tables)) ||
(table_rules_on && tables && thd->slave_thread && (table_rules_on && tables && thd->slave_thread &&
...@@ -1435,19 +1385,18 @@ mysql_execute_command(THD *thd) ...@@ -1435,19 +1385,18 @@ mysql_execute_command(THD *thd)
{ {
if (lex->describe) if (lex->describe)
{ {
if (!explain_result) if (!(result= new select_send()))
if (!(explain_result= new select_send())) {
{ send_error(thd, ER_OUT_OF_RESOURCES);
send_error(thd, ER_OUT_OF_RESOURCES); DBUG_VOID_RETURN;
DBUG_VOID_RETURN; }
} else
else thd->send_explain_fields(result);
thd->send_explain_fields(explain_result);
fix_tables_pointers(select_lex); fix_tables_pointers(select_lex);
res= mysql_explain_union(thd, &thd->lex.unit, explain_result); res= mysql_explain_union(thd, &thd->lex.unit, result);
MYSQL_LOCK *save_lock= thd->lock; MYSQL_LOCK *save_lock= thd->lock;
thd->lock= (MYSQL_LOCK *)0; thd->lock= (MYSQL_LOCK *)0;
explain_result->send_eof(); result->send_eof();
thd->lock= save_lock; thd->lock= save_lock;
} }
else else
...@@ -2901,26 +2850,24 @@ void ...@@ -2901,26 +2850,24 @@ void
mysql_init_query(THD *thd) mysql_init_query(THD *thd)
{ {
DBUG_ENTER("mysql_init_query"); DBUG_ENTER("mysql_init_query");
thd->lex.unit.init_query(); LEX *lex=&thd->lex;
thd->lex.unit.init_select(); lex->unit.init_query();
thd->lex.select_lex.init_query(); lex->unit.init_select();
thd->lex.unit.slave= &thd->lex.select_lex; lex->select_lex.init_query();
thd->lex.unit.global_parameters= &thd->lex.select_lex; //Global limit & order lex->value_list.empty();
thd->lex.select_lex.master= &thd->lex.unit; lex->param_list.empty();
thd->lex.select_lex.prev= &thd->lex.unit.slave; lex->unit.global_parameters= lex->unit.slave= lex->current_select= &lex->select_lex;
thd->select_number= thd->lex.select_lex.select_number= 1; lex->select_lex.master= &lex->unit;
thd->lex.value_list.empty(); lex->select_lex.prev= &lex->unit.slave;
lex->olap=lex->describe=0;
lex->derived_tables= false;
thd->select_number= lex->select_lex.select_number= 1;
thd->free_list= 0; thd->free_list= 0;
thd->lex.current_select= &thd->lex.select_lex;
thd->lex.olap=thd->lex.describe=0;
thd->lex.select_lex.olap= UNSPECIFIED_OLAP_TYPE;
thd->fatal_error= 0; // Safety
thd->total_warn_count=0; // Warnings for this query thd->total_warn_count=0; // Warnings for this query
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0; thd->sent_row_count= thd->examined_row_count= 0;
thd->rand_used=0; thd->fatal_error= thd->rand_used=0;
thd->safe_to_cache_query= 1; thd->safe_to_cache_query= 1;
thd->lex.param_list.empty();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2932,7 +2879,6 @@ mysql_init_select(LEX *lex) ...@@ -2932,7 +2879,6 @@ mysql_init_select(LEX *lex)
select_lex->init_select(); select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit= select_lex->master_unit()->select_limit= select_lex->select_limit=
lex->thd->variables.select_limit; lex->thd->variables.select_limit;
select_lex->olap= UNSPECIFIED_OLAP_TYPE;
lex->exchange= 0; lex->exchange= 0;
lex->result= 0; lex->result= 0;
lex->proc_list.first= 0; lex->proc_list.first= 0;
...@@ -3016,14 +2962,13 @@ mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -3016,14 +2962,13 @@ mysql_parse(THD *thd, char *inBuf, uint length)
mysql_init_query(thd); mysql_init_query(thd);
thd->query_length = length; thd->query_length = length;
thd->lex.derived_tables= false;
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{ {
LEX *lex=lex_start(thd, (uchar*) inBuf, length); LEX *lex=lex_start(thd, (uchar*) inBuf, length);
if (!yyparse() && ! thd->fatal_error) if (!yyparse() && ! thd->fatal_error)
{ {
if (mqh_used && thd->user_connect && if (mqh_used && thd->user_connect &&
check_mqh(thd, thd->lex.sql_command)) check_mqh(thd, lex->sql_command))
{ {
thd->net.error = 0; thd->net.error = 0;
} }
......
...@@ -7458,8 +7458,10 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) ...@@ -7458,8 +7458,10 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
((sl->next_select_in_list())?"PRIMARY": ((sl->next_select_in_list())?"PRIMARY":
"SIMPLE"): "SIMPLE"):
((sl == first)? ((sl == first)?
((sl->linkage == DERIVED_TABLE_TYPE) ?
"DERIVED":
((sl->dependent)?"DEPENDENT SUBSELECT": ((sl->dependent)?"DEPENDENT SUBSELECT":
"SUBSELECT"): "SUBSELECT")):
((sl->dependent)?"DEPENDENT UNION": ((sl->dependent)?"DEPENDENT UNION":
"UNION"))), "UNION"))),
result); result);
......
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