From f980950bb3b19df3de3030c531ecff99ecb323e1 Mon Sep 17 00:00:00 2001
From: unknown <Sinisa@sinisa.nasamreza.org>
Date: Sat, 9 Nov 2002 15:40:46 +0200
Subject: [PATCH] Some code optimisations related to EXPLAIN of derived tables
 and the resulting code cleanup in our main loop.

---
 mysql-test/r/subselect.result |   2 +-
 sql/mysql_priv.h              |   3 +-
 sql/sql_derived.cc            |  10 ++--
 sql/sql_lex.cc                |   1 +
 sql/sql_parse.cc              | 107 +++++++++-------------------------
 sql/sql_select.cc             |   4 +-
 6 files changed, 37 insertions(+), 90 deletions(-)

diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index b1bf134fdde..5674bf3c473 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -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 
 (select * from t2 where a>1) as tt;
 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	
+3	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	where used
 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);
 a
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index c61621bf91d..a6771c9754d 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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,
 			 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,
-		  bool tables_is_opened);
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
 Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
 			Item_result_field ***copy_func, Field **from_field,
 			bool group,bool modify_item);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 1335618b90d..93627409d27 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -28,8 +28,7 @@
 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,
-		  bool tables_is_opened)
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
 {
   /*
     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,
     if (cursor->derived)
     {
       res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived,
-			 cursor, 0);
+			 cursor);
       if (res) DBUG_RETURN(res);
     }
   }
@@ -68,7 +67,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
   while ((item= it++))
     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))
     {
@@ -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->table=table;
 	  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->derived=(SELECT_LEX *)0; // just in case ...
 	}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5327801bf9c..0865e6da05f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -959,6 +959,7 @@ void st_select_lex::init_query()
   table_list.next= (byte**) &table_list.first;
   item_list.empty();
   join= 0;
+  olap= UNSPECIFIED_OLAP_TYPE;
 }
 
 void st_select_lex::init_select()
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 57325ef19cf..4288773b00b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1328,74 +1328,24 @@ mysql_execute_command(THD *thd)
 #endif
   }
   
-  select_result *explain_result= 0;  
   /*
     TODO: make derived tables processing 'inside' SELECT processing.
     TODO: solve problem with depended derived tables in subselects
   */
-  if (lex->sql_command == SQLCOM_SELECT && 
-      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)
+if (lex->derived_tables)
   {
     for (TABLE_LIST *cursor= tables;
 	 cursor;
 	 cursor= cursor->next)
       if (cursor->derived && (res=mysql_derived(thd, lex,
 					   (SELECT_LEX_UNIT *)cursor->derived,
-						cursor, 0)))
+						cursor)))
       {  
 	if (res < 0)
 	  send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
 	DBUG_VOID_RETURN;
       }
-  }
+  } 
   if ((lex->select_lex.next_select_in_list() && 
        lex->unit.create_total_list(thd, lex, &tables)) ||
       (table_rules_on && tables && thd->slave_thread &&
@@ -1435,19 +1385,18 @@ mysql_execute_command(THD *thd)
     {
       if (lex->describe)
       {
-	if (!explain_result)
-	  if (!(explain_result= new select_send()))
-	  {
-	    send_error(thd, ER_OUT_OF_RESOURCES);
-	    DBUG_VOID_RETURN;
-	  }
-	  else
-	    thd->send_explain_fields(explain_result);
+	if (!(result= new select_send()))
+	{
+	  send_error(thd, ER_OUT_OF_RESOURCES);
+	  DBUG_VOID_RETURN;
+	}
+	else
+	  thd->send_explain_fields(result);
 	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;
 	thd->lock= (MYSQL_LOCK *)0;
-	explain_result->send_eof();
+	result->send_eof();
 	thd->lock= save_lock;
       }
       else
@@ -2901,26 +2850,24 @@ void
 mysql_init_query(THD *thd)
 {
   DBUG_ENTER("mysql_init_query");
-  thd->lex.unit.init_query();
-  thd->lex.unit.init_select();
-  thd->lex.select_lex.init_query();
-  thd->lex.unit.slave= &thd->lex.select_lex;
-  thd->lex.unit.global_parameters= &thd->lex.select_lex; //Global limit & order
-  thd->lex.select_lex.master= &thd->lex.unit;
-  thd->lex.select_lex.prev= &thd->lex.unit.slave;
-  thd->select_number= thd->lex.select_lex.select_number= 1;
-  thd->lex.value_list.empty();
+  LEX *lex=&thd->lex;
+  lex->unit.init_query();
+  lex->unit.init_select();
+  lex->select_lex.init_query();
+  lex->value_list.empty();
+  lex->param_list.empty();
+  lex->unit.global_parameters= lex->unit.slave= lex->current_select= &lex->select_lex;
+  lex->select_lex.master= &lex->unit;
+  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->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->last_insert_id_used= thd->query_start_used= thd->insert_id_used=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->lex.param_list.empty();
   DBUG_VOID_RETURN;
 }
 
@@ -2932,7 +2879,6 @@ mysql_init_select(LEX *lex)
   select_lex->init_select();
   select_lex->master_unit()->select_limit= select_lex->select_limit= 
     lex->thd->variables.select_limit;
-  select_lex->olap=   UNSPECIFIED_OLAP_TYPE;
   lex->exchange= 0;
   lex->result= 0;
   lex->proc_list.first= 0;
@@ -3016,14 +2962,13 @@ mysql_parse(THD *thd, char *inBuf, uint length)
 
   mysql_init_query(thd);
   thd->query_length = length;
-  thd->lex.derived_tables= false;
   if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
   {
     LEX *lex=lex_start(thd, (uchar*) inBuf, length);
     if (!yyparse() && ! thd->fatal_error)
     {
       if (mqh_used && thd->user_connect &&
-	  check_mqh(thd, thd->lex.sql_command))
+	  check_mqh(thd, lex->sql_command))
       {
 	thd->net.error = 0;
       }
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b9162daadaa..674caed0cd0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7458,8 +7458,10 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
 			       ((sl->next_select_in_list())?"PRIMARY":
 				"SIMPLE"):
 			       ((sl == first)?
+				((sl->linkage == DERIVED_TABLE_TYPE) ?
+				 "DERIVED":
 				((sl->dependent)?"DEPENDENT SUBSELECT":
-				 "SUBSELECT"):
+				 "SUBSELECT")):
 				((sl->dependent)?"DEPENDENT UNION":
 				 "UNION"))),
 			      result);
-- 
2.30.9