From 1dfa625f7b2a0767ce458c47122093a8c2ecf664 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Dec 2002 01:28:59 +0200 Subject: [PATCH] support of subselect without FROM reducing (SCRUM) fixed bug of calling setup_fields without correct lex->current_select pointer in mysql_derived more correct creation of reference in Item_field::fix_field mysql-test/r/subselect.result: new explain with subselect reduced mysql-test/t/subselect.test: new explain with subselect reduced sql/item.cc: support of subselect without FROM reducing more correct creation of reference in Item_field::fix_field sql/item.h: support of subselect without FROM reducing sql/item_cmpfunc.cc: support of subselect without FROM reducing sql/item_cmpfunc.h: support of subselect without FROM reducing sql/item_func.cc: support of subselect without FROM reducing sql/item_func.h: support of subselect without FROM reducing sql/item_row.cc: support of subselect without FROM reducing sql/item_row.h: support of subselect without FROM reducing sql/item_strfunc.h: fixed layout support of subselect without FROM reducing sql/item_subselect.cc: support of subselect without FROM reducing sql/item_subselect.h: support of subselect without FROM reducing sql/mysql_priv.h: reference in Item_field::fix_field related changes sql/sql_base.cc: reference in Item_field::fix_field related changes sql/sql_derived.cc: fixed bug of calling setup_fields without correct lex->current_select pointer --- mysql-test/r/subselect.result | 33 +++++++++++++++++++++++- mysql-test/t/subselect.test | 6 +++++ sql/item.cc | 42 ++++++++++++++++++------------ sql/item.h | 7 +++-- sql/item_cmpfunc.cc | 16 ++++++++++++ sql/item_cmpfunc.h | 12 +++++++++ sql/item_func.cc | 19 ++++++++++++++ sql/item_func.h | 7 +++++ sql/item_row.cc | 17 ++++++++++++- sql/item_row.h | 2 ++ sql/item_strfunc.h | 31 ++++++++++++++++------ sql/item_subselect.cc | 48 +++++++++++++++++++++++++++++++++++ sql/item_subselect.h | 1 + sql/mysql_priv.h | 2 +- sql/sql_base.cc | 5 +++- sql/sql_derived.cc | 9 ++++--- 16 files changed, 223 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 502fe0fad60..23aad50c6ae 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1,13 +1,32 @@ select (select 2); (select 2) 2 +explain select (select 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1247 Select 2 was reduced during optimisation SELECT (SELECT 1) UNION SELECT (SELECT 2); (SELECT 1) 1 2 +explain SELECT (SELECT 1) UNION SELECT (SELECT 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1247 Select 2 was reduced during optimisation +Note 1247 Select 4 was reduced during optimisation SELECT (SELECT (SELECT 0 UNION SELECT 0)); (SELECT (SELECT 0 UNION SELECT 0)) 0 +explain SELECT (SELECT (SELECT 0 UNION SELECT 0)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used +3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used +4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1247 Select 2 was reduced during optimisation SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a; Reference 'a' not supported (forward reference in item list) SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b; @@ -20,8 +39,9 @@ Reference 'a' not supported (forward reference in item list) EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 -3 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1247 Select 3 was reduced during optimisation SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; 1 1 @@ -629,6 +649,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t ref id id 5 const 1 Using where; Using index 3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: +Note 1247 Select 3 was reduced during optimisation Note 1247 Select 2 was reduced during optimisation EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); id select_type table type possible_keys key key_len ref rows Extra @@ -752,6 +773,16 @@ NULL select 10.5 > ANY (SELECT * from t); 10.5 > ANY (SELECT * from t) 1 +explain select (select a+1) from t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ALL NULL NULL NULL NULL 3 +Warnings: +Note 1247 Select 2 was reduced during optimisation +select (select a+1) from t; +(select a+1) +2.5 +NULL +4.5 drop table t; create table t (a float); select 10.5 IN (SELECT * from t LIMIT 1); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c77fc33f0ea..4e8e71e50f8 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1,6 +1,9 @@ select (select 2); +explain select (select 2); SELECT (SELECT 1) UNION SELECT (SELECT 2); +explain SELECT (SELECT 1) UNION SELECT (SELECT 2); SELECT (SELECT (SELECT 0 UNION SELECT 0)); +explain SELECT (SELECT (SELECT 0 UNION SELECT 0)); -- error 1245 SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a; -- error 1245 @@ -424,6 +427,8 @@ select 1.5 > ALL (SELECT * from t); select 10.5 > ALL (SELECT * from t); select 1.5 > ANY (SELECT * from t); select 10.5 > ANY (SELECT * from t); +explain select (select a+1) from t; +select (select a+1) from t; drop table t; #LIMIT is not supported now @@ -433,6 +438,7 @@ select 10.5 IN (SELECT * from t LIMIT 1); -- error 1235 select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5); drop table t; + create table t1 (a int, b int, c varchar(10)); create table t2 (a int); insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c'); diff --git a/sql/item.cc b/sql/item.cc index 461f2ba9de5..1603e179e5e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -546,8 +546,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!field) // If field is not checked { - Field *tmp; - if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field) + TABLE_LIST *where= 0; + Field *tmp= (Field *)not_found_field; + if (outer_resolving || + (tmp= find_field_in_tables(thd, this, tables, &where, 0)) == + not_found_field) { /* We can't find table field in table list of current select, @@ -565,12 +568,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) - for (SELECT_LEX *sl=cursel->outer_select(); + for (SELECT_LEX *sl=(outer_resolving?cursel:cursel->outer_select()); sl; sl= sl->outer_select()) { if ((tmp= find_field_in_tables(thd, this, - (last= sl)->get_table_list(), + (last= sl)->get_table_list(), &where, 0)) != not_found_field) break; if ((refer= find_item_in_list(this, sl->item_list, @@ -588,7 +591,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) else if (tmp == not_found_field && refer == (Item **)not_found_item) { // call to return error code - find_field_in_tables(thd, this, tables, 1); + find_field_in_tables(thd, this, tables, &where, 1); return -1; } else if (refer != (Item **)not_found_item) @@ -614,6 +617,17 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) found table as depended (of select where was found table) */ thd->lex.current_select->mark_as_dependent(last); + if (depended_from->having_fix_field) + { + Item_ref *rf; + *ref= rf= new Item_ref((where->db[0]?where->db:0), + (char *)where->alias, + (char *)field_name); + if (!rf) + return 1; + (rf)->outer_resolving= outer_resolving; + return rf->check_cols(1) || rf->fix_fields(thd, tables, ref); + } } } else if (!tmp) @@ -629,14 +643,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) table->used_fields++; table->used_keys&=field->part_of_key; } - if (depended_from != 0 && depended_from->having_fix_field) - { - *ref= new Item_ref((char *)db_name, (char *)table_name, - (char *)field_name); - if (!*ref) - return 1; - return (*ref)->check_cols(1) || (*ref)->fix_fields(thd, tables, ref); - } fixed= 1; return 0; } @@ -1007,13 +1013,17 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { if (!ref) { - SELECT_LEX *sl= thd->lex.current_select->outer_select(); + TABLE_LIST *where= 0; + SELECT_LEX *sl= (outer_resolving? + thd->lex.current_select->select_lex(): + thd->lex.current_select->outer_select()); /* Finding only in current select will be performed for selects that have not outer one and for derived tables (which not support using outer fields for now) */ - if ((ref= find_item_in_list(this, + if (outer_resolving || + (ref= find_item_in_list(this, *(thd->lex.current_select->get_item_list()), ((sl && thd->lex.current_select->master_unit()-> @@ -1041,7 +1051,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) (Item **)not_found_item) break; if ((tmp= find_field_in_tables(thd, this, - sl->get_table_list(), + sl->get_table_list(), &where, 0)) != not_found_field); if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) diff --git a/sql/item.h b/sql/item.h index 4e3c5f597ab..508c737e7b9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -96,6 +96,7 @@ public: CHARSET_INFO *thd_charset() const; CHARSET_INFO *charset() const { return str_value.charset(); }; void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } + virtual void set_outer_resolving() {} // Row emulation virtual uint cols() { return 1; } @@ -117,12 +118,14 @@ public: const char *table_name; const char *field_name; st_select_lex *depended_from; + bool outer_resolving; /* used for items from reduced subselect */ Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par) - :db_name(db_name_par),table_name(table_name_par), - field_name(field_name_par), depended_from(0) + :db_name(db_name_par), table_name(table_name_par), + field_name(field_name_par), depended_from(0), outer_resolving(0) { name = (char*) field_name_par; } const char *full_name() const; + void set_outer_resolving() { outer_resolving= 1; } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index df949a910bd..89ff5ef2822 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -946,6 +946,13 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 0; } +void Item_func_case::set_outer_resolving() +{ + first_expr->set_outer_resolving(); + else_expr->set_outer_resolving(); + Item_func::set_outer_resolving(); +} + bool Item_func_case::check_loop(uint id) { DBUG_ENTER("Item_func_case::check_loop"); @@ -1523,6 +1530,15 @@ bool Item_cond::check_loop(uint id) DBUG_RETURN(0); } +void Item_cond::set_outer_resolving() +{ + Item_func::set_outer_resolving(); + List_iterator li(list); + Item *item; + while ((item= li++)) + item->set_outer_resolving(); +} + void Item_cond::split_sum_func(List &fields) { List_iterator li(list); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index e3d8eb7746d..603d7123a6f 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -277,6 +277,11 @@ public: const char *func_name() const { return "interval"; } void update_used_tables(); bool check_loop(uint id); + void set_outer_resolving() + { + item->set_outer_resolving(); + Item_func::set_outer_resolving(); + } }; @@ -359,6 +364,7 @@ public: bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); Item *find_item(String *str); bool check_loop(uint id); + void set_outer_resolving(); }; @@ -643,6 +649,11 @@ class Item_func_in :public Item_int_func DBUG_RETURN(item->check_loop(id)); } bool nulls_in_row(); + void set_outer_resolving() + { + item->set_outer_resolving(); + Item_int_func::set_outer_resolving(); + } }; /* Functions used by where clause */ @@ -784,6 +795,7 @@ public: friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); bool check_loop(uint id); void top_level_item() { abort_on_null=1; } + void set_outer_resolving(); }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 19fd6b12c67..f0c956b873a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -146,6 +146,16 @@ bool Item_func::check_loop(uint id) DBUG_RETURN(0); } +void Item_func::set_outer_resolving() +{ + if (arg_count) + { + Item **arg,**arg_end; + for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++) + (*arg)->set_outer_resolving(); + } +} + void Item_func::split_sum_func(List &fields) { Item **arg,**arg_end; @@ -2356,6 +2366,15 @@ bool Item_func_match::check_loop(uint id) DBUG_RETURN(0); } +void Item_func_match::set_outer_resolving() +{ + Item_real_func::set_outer_resolving(); + List_iterator li(fields); + Item *item; + while ((item= li++)) + item->set_outer_resolving(); +} + bool Item_func_match::fix_index() { List_iterator_fast li(fields); diff --git a/sql/item_func.h b/sql/item_func.h index 36d6dcbe002..6ff2c7eef9d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -133,6 +133,7 @@ public: friend class udf_handler; Field *tmp_table_field(TABLE *t_arg); bool check_loop(uint id); + void set_outer_resolving(); }; @@ -632,6 +633,11 @@ public: DBUG_RETURN(1); DBUG_RETURN(item->check_loop(id)); } + void set_outer_resolving() + { + item->set_outer_resolving(); + Item_int_func::set_outer_resolving(); + } }; @@ -1006,6 +1012,7 @@ public: bool fix_index(); void init_search(bool no_order); bool check_loop(uint id); + void set_outer_resolving(); }; diff --git a/sql/item_row.cc b/sql/item_row.cc index 9d605e05242..b54653f4183 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -105,5 +105,20 @@ void Item_row::bring_value() { for (uint i= 0; i < arg_count; i++) items[i]->bring_value(); - return; +} + +void Item_row::set_outer_resolving() +{ + for (uint i= 0; i < arg_count; i++) + items[i]->set_outer_resolving(); +} + +bool Item_row::check_loop(uint id) +{ + if (Item::check_loop(id)) + return 1; + for (uint i= 0; i < arg_count; i++) + if (items[i]->check_loop(id)) + return 1; + return 0; } diff --git a/sql/item_row.h b/sql/item_row.h index cf67567c3ed..f33e0cc9821 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -64,6 +64,8 @@ public: bool const_item() const { return const_item_cache; }; enum Item_result result_type() const { return ROW_RESULT; } void update_used_tables(); + bool check_loop(uint id); + void set_outer_resolving(); uint cols() { return arg_count; } Item* el(uint i) { return items[i]; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index c8706c2c933..12b003d7d82 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -108,14 +108,19 @@ public: separator->fix_fields(thd, tlist, &separator) || Item_func::fix_fields(thd, tlist, ref)); } - const char *func_name() const { return "concat_ws"; } - bool check_loop(uint id) - { - DBUG_ENTER("Item_func_concat_ws::check_loop"); - if (Item_str_func::check_loop(id)) - DBUG_RETURN(1); - DBUG_RETURN(separator->check_loop(id)); - } + const char *func_name() const { return "concat_ws"; } + bool check_loop(uint id) + { + DBUG_ENTER("Item_func_concat_ws::check_loop"); + if (Item_str_func::check_loop(id)) + DBUG_RETURN(1); + DBUG_RETURN(separator->check_loop(id)); + } + void set_outer_resolving() + { + separator->set_outer_resolving(); + Item_func::set_outer_resolving(); + } }; class Item_func_reverse :public Item_str_func @@ -393,6 +398,11 @@ public: DBUG_RETURN(1); DBUG_RETURN(item->check_loop(id)); } + void set_outer_resolving() + { + item->set_outer_resolving(); + Item_str_func::set_outer_resolving(); + } }; @@ -421,6 +431,11 @@ public: DBUG_RETURN(1); DBUG_RETURN(item->check_loop(id)); } + void set_outer_resolving() + { + item->set_outer_resolving(); + Item_str_func::set_outer_resolving(); + } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 65c942a75ce..fe38c458495 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -146,6 +146,54 @@ void Item_singlerow_subselect::reset() value->null_value= 1; } +void Item_singlerow_subselect::select_transformer(st_select_lex_unit *unit) +{ + SELECT_LEX *select_lex= unit->first_select(); + + if (!select_lex->next_select() && !select_lex->table_list.elements && + select_lex->item_list.elements == 1) + { + + have_to_be_excluded= 1; + THD *thd= current_thd; + if (thd->lex.describe) + { + char warn_buff[MYSQL_ERRMSG_SIZE]; + sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_SELECT_REDUCED, warn_buff); + } + substitution= select_lex->item_list.head(); + substitution->set_outer_resolving(); + if (substitution->type() == FIELD_ITEM || + substitution->type() == REF_ITEM) + name= substitution->name; // Save name for correct resolving + + if (select_lex->where || select_lex->having) + { + Item *cond; + if (!select_lex->having) + cond= select_lex->where; + else if (!select_lex->where) + cond= select_lex->having; + else + if (!(cond= new Item_cond_and(select_lex->having, select_lex->where))) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + thd->fatal_error= 1; + return; + } + if (!(substitution= new Item_func_if(cond, substitution, + new Item_null()))) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + thd->fatal_error= 1; + return; + } + } + } +} + void Item_singlerow_subselect::store(uint i, Item *item) { row[i]->store(item); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 6063730d6a8..0d263f4aa39 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -106,6 +106,7 @@ public: decimals= item->decimals; } void reset(); + void select_transformer(st_select_lex_unit *unit); void store(uint i, Item* item); double val(); longlong val_int (); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index cf0cefd76da..616a0573772 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -463,7 +463,7 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name); extern const Field *not_found_field; Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, - bool report_error); + TABLE_LIST **where, bool report_error); Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, bool check_grant,bool allow_rowid); #ifdef HAVE_OPENSSL diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 87cc0d616a9..eb7fdf783d3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1654,6 +1654,7 @@ const Field *not_found_field= (Field*) 0x1; thd - pointer to current thread structure item - field item that should be found tables - tables for scaning + where - table where field found will be returned via this parameter report_error - if FALSE then do not report error if item not found and return not_found_field; @@ -1667,7 +1668,7 @@ const Field *not_found_field= (Field*) 0x1; Field * find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, - bool report_error) + TABLE_LIST **where, bool report_error) { Field *found=0; const char *db=item->db_name; @@ -1688,6 +1689,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, grant_option && !thd->master_access,1); if (find) { + (*where)= tables; if (find == WRONG_GRANT) return (Field*) 0; if (db || !thd->where) @@ -1742,6 +1744,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, { if (field == WRONG_GRANT) return (Field*) 0; + (*where)= tables; if (found) { if (!thd->where) // Returns first found diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index f7d845e9e36..db516ae5f41 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -63,6 +63,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) TMP_TABLE_PARAM tmp_table_param; bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE; DBUG_ENTER("mysql_derived"); + SELECT_LEX_NODE *save_current_select= lex->current_select; /* @@ -111,6 +112,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) } } + lex->current_select= sl; if (setup_fields(thd,tables,item_list,0,0,1)) { res=-1; @@ -119,7 +121,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); tmp_table_param.field_count=item_list.elements; if (!(table=create_tmp_table(thd, &tmp_table_param, item_list, - (ORDER*) 0, is_union && !unit->union_option, 1, + (ORDER*) 0, + is_union && !unit->union_option, 1, (sl->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR))) @@ -138,8 +141,6 @@ 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; - SELECT_LEX_NODE *save_current_select= lex->current_select; - lex->current_select= sl; if (is_union) res=mysql_union(thd,lex,derived_result,unit); else @@ -149,7 +150,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) sl->having, (ORDER*) NULL, sl->options | thd->options | SELECT_NO_UNLOCK, derived_result, unit, sl, 0); - lex->current_select= save_current_select; if (!res) { @@ -184,6 +184,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) if (res) free_tmp_table(thd,table); exit: + lex->current_select= save_current_select; close_thread_tables(thd); } DBUG_RETURN(res);