summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/mysql_priv.h9
-rw-r--r--sql/sql_class.cc22
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_derived.cc23
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_parse.cc108
-rw-r--r--sql/sql_select.cc153
-rw-r--r--sql/sql_union.cc23
-rw-r--r--sql/table.h3
9 files changed, 237 insertions, 111 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index d3901770230..dbf853431d6 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -373,9 +373,14 @@ int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result,
- SELECT_LEX_UNIT *unit, bool fake_select_lex);
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
+ bool fake_select_lex);
+void fix_tables_pointers(SELECT_LEX *select_lex);
+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);
+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,
Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b84bcf1df72..c090f2336c1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -357,6 +357,28 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(TABLE *table)
return new_table;
}
+int THD::send_explain_fields(select_result *result)
+{
+ List<Item> field_list;
+ Item *item;
+ field_list.push_back(new Item_int("id",0,3));
+ field_list.push_back(new Item_empty_string("select_type",19));
+ field_list.push_back(new Item_empty_string("table",NAME_LEN));
+ field_list.push_back(new Item_empty_string("type",10));
+ field_list.push_back(item=new Item_empty_string("possible_keys",
+ NAME_LEN*MAX_KEY));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_int("key_len",0,3));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("ref",
+ NAME_LEN*MAX_REF_PARTS));
+ item->maybe_null=1;
+ field_list.push_back(new Item_real("rows",0.0,0,10));
+ field_list.push_back(new Item_empty_string("Extra",255));
+ return (result->send_fields(field_list,1));
+}
/*****************************************************************************
** Functions to provide a interface to select results
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 82241f0ff1f..7be9a5ad9fe 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -315,6 +315,7 @@ public:
};
class delayed_insert;
+class select_result;
#define THD_SENTRY_MAGIC 0xfeedd1ff
#define THD_SENTRY_GONE 0xdeadbeef
@@ -442,6 +443,7 @@ public:
uint server_status,open_options;
uint32 query_length;
uint32 db_length;
+ uint select_number; //number of select (used for EXPLAIN)
enum_tx_isolation tx_isolation, session_tx_isolation;
char scramble[9];
uint8 query_cache_type; // type of query cache processing
@@ -576,6 +578,7 @@ public:
}
void add_changed_table(TABLE *table);
CHANGED_TABLE_LIST * changed_table_dup(TABLE *table);
+ int send_explain_fields(select_result *result);
};
/*
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index cde120f3774..539a9edb479 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -28,7 +28,8 @@
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
@@ -37,7 +38,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
SELECT_LEX *sl= unit->first_select();
List<Item> item_list;
TABLE *table;
- int res;
+ int res= 0;
select_union *derived_result;
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
TMP_TABLE_PARAM tmp_table_param;
@@ -56,7 +57,8 @@ 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);
+ res=mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived,
+ cursor, 0);
if (res) DBUG_RETURN(res);
}
}
@@ -66,7 +68,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
while ((item= it++))
item_list.push_back(item);
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (tables_is_opened || !(res=open_and_lock_tables(thd,tables)))
{
if (tables && setup_fields(thd,tables,item_list,0,0,1))
{
@@ -94,12 +96,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
- res=mysql_select(thd, tables, sl->item_list,
- sl->where, (ORDER *) sl->order_list.first,
- (ORDER*) sl->group_list.first,
- sl->having, (ORDER*) NULL,
- sl->options | thd->options | SELECT_NO_UNLOCK,
- derived_result, unit, 0);
+ res= mysql_select(thd, tables, sl->item_list,
+ sl->where, (ORDER *) sl->order_list.first,
+ (ORDER*) sl->group_list.first,
+ sl->having, (ORDER*) NULL,
+ sl->options | thd->options | SELECT_NO_UNLOCK,
+ derived_result, unit, sl, 0);
if (!res)
{
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
@@ -109,6 +111,7 @@ 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();
t->derived=(SELECT_LEX *)0; // just in case ...
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index b75826663ca..e6054f5604b 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -282,8 +282,10 @@ public:
List<Item_func_match> *ftfunc_list;
List<Item_func_match> ftfunc_list_alloc;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
+ const char *type; /* type of select for EXPLAIN */
uint in_sum_expr;
- bool create_refs,
+ uint select_number; /* number of select (used for EXPLAIN) */
+ bool create_refs,
braces, /* SELECT ... UNION (SELECT ... ) <- this braces */
depended, /* depended from outer select subselect */
/* TRUE when having fix field called in processing of this SELECT */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 9977eaad0ff..8166a156b8c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1254,7 +1254,7 @@ mysql_execute_command(void)
THD *thd= current_thd;
LEX *lex= &thd->lex;
TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
- SELECT_LEX *select_lex= lex->select;
+ SELECT_LEX *select_lex= &lex->select_lex;
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
@@ -1281,18 +1281,69 @@ mysql_execute_command(void)
#endif
}
+ select_result *explain_result= 0;
/*
- Skip if we are in the slave thread, some table rules have been given
- and the table list says the query should not be replicated
+ TODO: make derived tables processing 'inside' SELECT processing.
+ TODO: solve problem with depended derived tables in subselects
*/
- if (lex->derived_tables)
+ if (lex->sql_command == SQLCOM_SELECT &&
+ (select_lex->options & SELECT_DESCRIBE) &&
+ lex->derived_tables)
+ {
+ if (!(explain_result= new select_send()))
+ {
+ send_error(&thd->net, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
+ }
+ //check rights
+ for (TABLE_LIST *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 (TABLE_LIST *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;
cursor;
cursor= cursor->next)
if (cursor->derived && mysql_derived(thd, lex,
(SELECT_LEX_UNIT *)cursor->derived,
- cursor))
+ cursor, 0))
DBUG_VOID_RETURN;
}
if ((lex->select_lex.next_select_in_list() &&
@@ -1374,8 +1425,44 @@ mysql_execute_command(void)
if (!(res=open_and_lock_tables(thd,tables)))
{
- query_cache_store_query(thd, tables);
- res=handle_select(thd, lex, result);
+ if (select_lex->options & SELECT_DESCRIBE)
+ {
+ delete result; // we do not need it for explain
+ if (!explain_result)
+ if (!(explain_result= new select_send()))
+ {
+ send_error(&thd->net, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
+ }
+ else
+ thd->send_explain_fields(explain_result);
+ fix_tables_pointers(select_lex);
+ for ( SELECT_LEX *sl= select_lex;
+ sl && res == 0;
+ sl= sl->next_select_in_list())
+ {
+ SELECT_LEX *first= sl->master_unit()->first_select();
+ res= mysql_explain_select(thd, sl,
+ ((select_lex==sl)?"FIRST":
+ ((sl == first)?
+ ((sl->depended)?"DEPENDENT SUBSELECT":
+ "SUBSELECT"):
+ ((sl->depended)?"DEPENDENT UNION":
+ "UNION"))),
+ explain_result);
+ }
+ if (res > 0)
+ res= -res; // mysql_explain_select do not report error
+ MYSQL_LOCK *save_lock= thd->lock;
+ thd->lock= (MYSQL_LOCK *)0;
+ explain_result->send_eof();
+ thd->lock= save_lock;
+ }
+ else
+ {
+ query_cache_store_query(thd, tables);
+ res=handle_select(thd, lex, result);
+ }
}
else
delete result;
@@ -1866,7 +1953,7 @@ mysql_execute_command(void)
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
- result, unit, 0);
+ result, unit, select_lex, 0);
delete result;
}
else
@@ -2037,7 +2124,7 @@ mysql_execute_command(void)
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
- result, unit, 0);
+ result, unit, select_lex, 0);
delete result;
}
else
@@ -2803,6 +2890,7 @@ mysql_init_query(THD *thd)
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();
thd->free_list= 0;
thd->lex.union_option= 0;
@@ -2832,6 +2920,7 @@ bool
mysql_new_select(LEX *lex, bool move_down)
{
SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
+ select_lex->select_number= ++lex->thd->select_number;
if (!select_lex)
return 1;
select_lex->init_query();
@@ -2874,6 +2963,7 @@ 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);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d071743aec4..b87a79cc2c6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -144,7 +144,6 @@ static void init_sum_functions(Item_sum **func);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct, const char *message=NullS);
-static void describe_info(THD *thd, const char *info);
/*
This handles SELECT with and without UNION
@@ -154,19 +153,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
{
int res;
register SELECT_LEX *select_lex = &lex->select_lex;
- if (select_lex->next_select_in_list())
- {
- /* Fix tables 'to-be-unioned-from' list to point at opened tables */
- for (SELECT_LEX *sl= select_lex;
- sl;
- sl= sl->next_select_in_list())
- {
- for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
- cursor;
- cursor=cursor->next)
- cursor->table= cursor->table_list->table;
- }
- }
+ fix_tables_pointers(select_lex);
if (select_lex->next_select())
res=mysql_union(thd,lex,result);
else
@@ -178,7 +165,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
- result, &(lex->unit), 0);
+ result, &(lex->unit), &(lex->select_lex), 0);
if (res && result)
result->abort();
if (res || thd->net.report_error)
@@ -190,6 +177,22 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
return res;
}
+void fix_tables_pointers(SELECT_LEX *select_lex)
+{
+ if (select_lex->next_select_in_list())
+ {
+ /* Fix tables 'to-be-unioned-from' list to point at opened tables */
+ for (SELECT_LEX *sl= select_lex;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
+ cursor;
+ cursor=cursor->next)
+ cursor->table= cursor->table_list->table;
+ }
+ }
+}
/*****************************************************************************
** check fields, find best join, do the select and output fields.
@@ -209,7 +212,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
{
DBUG_ENTER("JOIN::prepare");
-
+
conds= conds_init;
order= order_init;
group_list= group_init;
@@ -344,7 +347,7 @@ int
JOIN::optimize()
{
DBUG_ENTER("JOIN::optimize");
-
+
#ifdef HAVE_REF_TO_FIELDS // Not done yet
/* Add HAVING to WHERE if possible */
if (having && !group_list && ! sum_func_count)
@@ -389,11 +392,8 @@ JOIN::optimize()
}
if (select_options & SELECT_DESCRIBE)
{
- if (union_part)
- select_describe(this, false, false, false,
- "Select tables optimized away");
- else
- describe_info(thd, "Select tables optimized away");
+ select_describe(this, false, false, false,
+ "Select tables optimized away");
delete procedure;
DBUG_RETURN(1);
}
@@ -647,10 +647,7 @@ JOIN::exec()
error=0;
if (select_options & SELECT_DESCRIBE)
{
- if (union_part)
- select_describe(this, false, false, false, "No tables used");
- else
- describe_info(thd, "No tables used");
+ select_describe(this, false, false, false, "No tables used");
}
else
{
@@ -674,16 +671,16 @@ JOIN::exec()
if (zero_result_cause)
{
- if (select_options & SELECT_DESCRIBE && union_part)
+ if (select_options & SELECT_DESCRIBE)
select_describe(this, false, false, false, zero_result_cause);
else
- error=return_zero_rows(result, tables_list, fields_list,
- tmp_table_param.sum_func_count != 0 &&
- !group_list,
- select_options,
- zero_result_cause,
- having,procedure,
- unit);
+ error= return_zero_rows(result, tables_list, fields_list,
+ tmp_table_param.sum_func_count != 0 &&
+ !group_list,
+ select_options,
+ zero_result_cause,
+ having,procedure,
+ unit);
DBUG_VOID_RETURN;
}
@@ -1004,7 +1001,8 @@ int
mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
ulong select_options, select_result *result,
- SELECT_LEX_UNIT *unit, bool fake_select_lex)
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
+ bool fake_select_lex)
{
JOIN *join = new JOIN(thd, fields, select_options, result);
@@ -1013,7 +1011,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
thd->used_tables=0; // Updated by setup_fields
if (join->prepare(tables, conds, order, group, having, proc_param,
- &(thd->lex.select_lex), unit, fake_select_lex))
+ select_lex, unit, fake_select_lex))
{
DBUG_RETURN(-1);
}
@@ -3087,11 +3085,6 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
{
DBUG_ENTER("return_zero_rows");
- if (select_options & SELECT_DESCRIBE)
- {
- describe_info(current_thd, info);
- DBUG_RETURN(0);
- }
if (procedure)
{
if (result->prepare(fields, unit)) // This hasn't been done yet
@@ -3725,6 +3718,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->blob_ptr_size=mi_portable_sizeof_char_ptr;
table->map=1;
table->tmp_table= TMP_TABLE;
+ table->derived_select_number= 0;
table->db_low_byte_first=1; // True for HEAP and MyISAM
table->temp_pool_slot = temp_pool_slot;
@@ -7139,7 +7133,6 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
Item *item;
List<Item> item_list;
THD *thd=join->thd;
- MYSQL_LOCK *save_lock;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
select_result *result=join->result;
DBUG_ENTER("select_describe");
@@ -7147,28 +7140,13 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
/* Don't log this into the slow query log */
select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
join->unit->offset_limit_cnt= 0;
- if (thd->lex.select == select_lex)
- {
- field_list.push_back(new Item_empty_string("table",NAME_LEN));
- field_list.push_back(new Item_empty_string("type",10));
- field_list.push_back(item=new Item_empty_string("possible_keys",
- NAME_LEN*MAX_KEY));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("key_len",0,3));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("ref",
- NAME_LEN*MAX_REF_PARTS));
- item->maybe_null=1;
- field_list.push_back(new Item_real("rows",0.0,0,10));
- field_list.push_back(new Item_empty_string("Extra",255));
- if (result->send_fields(field_list,1))
- return;
- }
if (message)
{
+ item_list.push_back(new Item_int((int)thd->lex.select->select_number));
+ item_list.push_back(new Item_string(thd->lex.select->type,
+ strlen(thd->lex.select->type),
+ default_charset_info));
item_list.push_back(new Item_empty_string("",0));
item_list.push_back(new Item_empty_string("",0));
item_list.push_back(new Item_empty_string("",0));
@@ -7192,9 +7170,24 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
String tmp1(buff1,sizeof(buff1),default_charset_info);
String tmp2(buff2,sizeof(buff2),default_charset_info);
item_list.empty();
+ item_list.push_back(new Item_int((int)thd->lex.select->select_number));
+ item_list.push_back(new Item_string(thd->lex.select->type,
+ strlen(thd->lex.select->type),
+ default_charset_info));
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
- item_list.push_back(new Item_string(table->table_name,strlen(table->table_name),default_charset_info));
+ if (table->tmp_table == TMP_TABLE && table->derived_select_number != 0)
+ {
+ // Derived table name generation
+ buff[512];
+ int len= my_snprintf(buff, 512, "<derived%u>",
+ table->derived_select_number);
+ item_list.push_back(new Item_string(buff, len, default_charset_info));
+ }
+ else
+ item_list.push_back(new Item_string(table->table_name,
+ strlen(table->table_name),
+ default_charset_info));
item_list.push_back(new Item_string(join_type_str[tab->type],strlen(join_type_str[tab->type]),default_charset_info));
tmp1.length(0); tmp2.length(0);
key_map bits;
@@ -7311,29 +7304,25 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
result->send_error(0,NullS);
}
}
- if (!join->thd->lex.select->next_select())
- {
- save_lock=thd->lock;
- thd->lock=(MYSQL_LOCK *)0;
- result->send_eof();
- thd->lock=save_lock;
- }
DBUG_VOID_RETURN;
}
-
-static void describe_info(THD *thd, const char *info)
+int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
+ select_result *result)
{
- List<Item> field_list;
- String *packet= &thd->packet;
+ select_lex->type= type;
+ thd->lex.select= select_lex;
+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
+ int res= mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
+ select_lex->item_list,
+ select_lex->where,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) thd->lex.proc_list.first,
+ select_lex->options | thd->options | SELECT_DESCRIBE,
+ result, unit, select_lex, 0);
- /* Don't log this into the slow query log */
- thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
- field_list.push_back(new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
- return; /* purecov: inspected */
- packet->length(0);
- net_store_data(packet,info);
- if (!my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
- send_eof(&thd->net);
+ return res;
}
+
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index e8ee3582135..f6ac17e5fe3 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -111,6 +111,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
DBUG_ENTER("st_select_lex_unit::prepare");
this->thd= thd;
this->result= result;
+ SELECT_LEX *lex_select_save= thd->lex.select;
/* Global option */
if (((void*)(global_parameters)) == ((void*)this))
@@ -148,9 +149,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
/* Create a list of items that will be in the result set */
while ((item= it++))
if (item_list.push_back(item))
- DBUG_RETURN(-1);
+ goto err;
if (setup_fields(thd,first_table,item_list,0,0,1))
- DBUG_RETURN(-1);
+ goto err;
}
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
@@ -162,7 +163,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
(first_select()->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
this)))
- DBUG_RETURN(-1);
+ goto err;
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list,sizeof(result_table_list));
@@ -171,7 +172,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
result_table_list.table=table;
if (!(union_result=new select_union(table)))
- DBUG_RETURN(-1);
+ goto err;
union_result->save_time_stamp=!describe;
union_result->tmp_table_param=&tmp_table_param;
@@ -202,9 +203,13 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
(ORDER*) NULL,
sl, this, 0);
if (res | thd->fatal_error)
- DBUG_RETURN(res | thd->fatal_error);
+ goto err;
}
+ thd->lex.select= lex_select_save;
DBUG_RETURN(res | thd->fatal_error);
+err:
+ thd->lex.select= lex_select_save;
+ DBUG_RETURN(-1);
}
int st_select_lex_unit::exec()
@@ -214,7 +219,7 @@ int st_select_lex_unit::exec()
{
if (optimized && item && item->assigned())
item->assigned(0); // We will reinit & rexecute unit
-
+ SELECT_LEX *lex_select_save= thd->lex.select;
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
thd->lex.select=sl;
@@ -234,8 +239,12 @@ int st_select_lex_unit::exec()
res= sl->join->error;
if (res)
+ {
+ thd->lex.select= lex_select_save;
DBUG_RETURN(res);
+ }
}
+ thd->lex.select= lex_select_save;
optimized= 1;
}
@@ -283,7 +292,7 @@ int st_select_lex_unit::exec()
0:
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
- thd->options, result, this, 1);
+ thd->options, result, this, first_select(), 1);
if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records;
}
diff --git a/sql/table.h b/sql/table.h
index b89701bfc8e..3b8a62a09b5 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -128,6 +128,9 @@ struct st_table {
uint temp_pool_slot;
+ /* number of select if it is derived table */
+ uint derived_select_number;
+
THD *in_use; /* Which thread uses this */
struct st_table *next,*prev;
};