diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mysql_priv.h | 9 | ||||
-rw-r--r-- | sql/sql_class.cc | 22 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_derived.cc | 23 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 108 | ||||
-rw-r--r-- | sql/sql_select.cc | 153 | ||||
-rw-r--r-- | sql/sql_union.cc | 23 | ||||
-rw-r--r-- | sql/table.h | 3 |
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; }; |