diff --git a/sql/item.cc b/sql/item.cc index 4a04dc93a54e8f9abcd389aebde98d61a88f0085..62f7823d1e3faa3f0a06ce2bbe0a27b34ac98da2 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -23,7 +23,7 @@ #include <m_ctype.h> #include "my_dir.h" -static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX_NODE *current, +static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX *current, Item_ident *item); /***************************************************************************** @@ -809,7 +809,7 @@ bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate) item - item which should be marked */ -static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX_NODE *current, +static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX *current, Item_ident *item) { // store pointer on SELECT_LEX from wich item is dependent @@ -1413,7 +1413,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if (((*ref)->with_sum_func && name && (depended_from || !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE && - thd->lex.current_select->select_lex()->having_fix_field))) || + thd->lex.current_select->having_fix_field))) || !(*ref)->fixed) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f29ac3b3c9c5dfe90a6585cf928fd61977796bce..d295e5c826171bbea56cc1cc1b0256acabb9851f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -336,8 +336,8 @@ Item_exists_subselect::Item_exists_subselect(THD *thd, bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit) { - if (unit->global_parameters == unit && - unit->global_parameters->test_limit()) + if (unit->fake_select_lex && + unit->fake_select_lex->test_limit()) return(1); SELECT_LEX *sl= unit->first_select(); @@ -495,7 +495,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, SELECT_LEX_UNIT *unit= select_lex->master_unit(); substitution= optimizer= new Item_in_optimizer(left_expr, this); - SELECT_LEX_NODE *current= thd->lex.current_select, *up; + SELECT_LEX *current= thd->lex.current_select, *up; + thd->lex.current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) @@ -658,7 +659,7 @@ Item_in_subselect::row_value_transformer(JOIN *join, SELECT_LEX_UNIT *unit= select_lex->master_unit(); substitution= optimizer= new Item_in_optimizer(left_expr, this); - SELECT_LEX_NODE *current= thd->lex.current_select, *up; + SELECT_LEX *current= thd->lex.current_select, *up; thd->lex.current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) @@ -771,7 +772,7 @@ int subselect_single_select_engine::prepare() if (prepared) return 0; prepared= 1; - SELECT_LEX_NODE *save_select= thd->lex.current_select; + SELECT_LEX *save_select= thd->lex.current_select; thd->lex.current_select= select_lex; if (join->prepare(&select_lex->ref_pointer_array, (TABLE_LIST*) select_lex->table_list.first, @@ -876,7 +877,7 @@ int subselect_single_select_engine::exec() { DBUG_ENTER("subselect_single_select_engine::exec"); char const *save_where= join->thd->where; - SELECT_LEX_NODE *save_select= join->thd->lex.current_select; + SELECT_LEX *save_select= join->thd->lex.current_select; join->thd->lex.current_select= select_lex; if (!optimized) { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 67dffb35724d6b45ca1e0cb9d4b24bc65b805f63..4353427675975548ba8199c203770179a2345155 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1114,7 +1114,7 @@ void Item_sum_count_distinct::make_unique() bool Item_sum_count_distinct::setup(THD *thd) { List<Item> list; - SELECT_LEX *select_lex= current_lex->current_select->select_lex(); + SELECT_LEX *select_lex= current_lex->current_select; if (select_lex->linkage == GLOBAL_OPTIONS_TYPE) return 1; @@ -1607,7 +1607,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, original= 0; quick_group= 0; mark_as_sum_func(); - SELECT_LEX *select_lex= current_lex->current_select->select_lex(); + SELECT_LEX *select_lex= current_lex->current_select; order= 0; arg_show_fields= arg_count_field= is_select->elements; @@ -1786,7 +1786,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) bool Item_func_group_concat::setup(THD *thd) { List<Item> list; - SELECT_LEX *select_lex= current_lex->current_select->select_lex(); + SELECT_LEX *select_lex= current_lex->current_select; if (select_lex->linkage == GLOBAL_OPTIONS_TYPE) return 1; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ebb09b99df7de9f1c1bb4e8056c312f643d0019b..876c4f9e67047cf861eb1e9a6f4160aefe06d6b4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -304,7 +304,7 @@ multi_delete::initialize_tables(JOIN *join) table->file->ref_length, MEM_STRIP_BUF_SIZE); } - init_ftfuncs(thd, thd->lex.current_select->select_lex(), 1); + init_ftfuncs(thd, thd->lex.current_select, 1); DBUG_RETURN(thd->is_fatal_error != 0); } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 0f8b9b96455a0ecfded7f78679ab893442a5dc59..92e37f95f0eda01a147ea68492003e22e0330cbc 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -74,7 +74,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, bool is_union= select_cursor->next_select() && select_cursor->next_select()->linkage == UNION_TYPE; bool is_subsel= select_cursor->first_inner_unit() ? 1: 0; - SELECT_LEX_NODE *save_current_select= lex->current_select; + SELECT_LEX *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); /* diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9b372f6eedaae84cfbae516adc1b4f3432571fd8..8e3d6df054089c51aa327050b1eb69b798666a29 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -966,27 +966,17 @@ void st_select_lex_node::init_query() options= 0; linkage= UNSPECIFIED_TYPE; no_table_names_allowed= uncacheable= dependent= 0; - ref_pointer_array= 0; - cond_count= 0; } void st_select_lex_node::init_select() { - order_list.elements= 0; - order_list.first= 0; - order_list.next= (byte**) &order_list.first; - select_limit= HA_POS_ERROR; - offset_limit= 0; - select_items= 0; - with_sum_func= 0; - parsing_place= SELECT_LEX_NODE::NO_MATTER; } void st_select_lex_unit::init_query() { st_select_lex_node::init_query(); linkage= GLOBAL_OPTIONS_TYPE; - global_parameters= this; + global_parameters= first_select(); select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; union_option= 0; @@ -994,6 +984,7 @@ void st_select_lex_unit::init_query() item= 0; union_result= 0; table= 0; + fake_select_lex= 0; } void st_select_lex::init_query() @@ -1005,7 +996,8 @@ void st_select_lex::init_query() where= 0; olap= UNSPECIFIED_OLAP_TYPE; insert_select= having_fix_field= 0; - with_wild= 0; + cond_count= with_wild= 0; + ref_pointer_array= 0; } void st_select_lex::init_select() @@ -1027,6 +1019,14 @@ void st_select_lex::init_select() ftfunc_list_alloc.empty(); ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; + order_list.elements= 0; + order_list.first= 0; + order_list.next= (byte**) &order_list.first; + select_limit= HA_POS_ERROR; + offset_limit= 0; + select_items= 0; + with_sum_func= 0; + parsing_place= SELECT_LEX_NODE::NO_MATTER; } /* @@ -1044,6 +1044,23 @@ void st_select_lex_node::include_down(st_select_lex_node *upper) slave= 0; } +/* + include on level down (but do not link) + + SYNOPSYS + st_select_lex_node::include_standalone() + upper - reference on node underr which this node should be included + ref - references on reference on this node +*/ +void st_select_lex_node::include_standalone(st_select_lex_node *upper, + st_select_lex_node **ref) +{ + next= 0; + prev= ref; + master= upper; + slave= 0; +} + /* include neighbour (on same level) */ void st_select_lex_node::include_neighbour(st_select_lex_node *before) { @@ -1125,33 +1142,6 @@ void st_select_lex_unit::exclude_level() (*prev)= next; } -st_select_lex* st_select_lex_node::select_lex() -{ - DBUG_ENTER("st_select_lex_node::select_lex (never should be called)"); - DBUG_ASSERT(0); - DBUG_RETURN(0); -} - -bool st_select_lex_node::add_item_to_list(THD *thd, Item *item) -{ - return 1; -} - -bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc) -{ - return 1; -} - -bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc) -{ - return add_to_list(thd, order_list, item, asc); -} - -bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func) -{ - return 1; -} - /* st_select_lex_node::mark_as_dependent mark all st_select_lex struct from this to 'last' as dependent @@ -1165,31 +1155,26 @@ bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func) */ -void st_select_lex_node::mark_as_dependent(SELECT_LEX *last) +void st_select_lex::mark_as_dependent(SELECT_LEX *last) { /* Mark all selects from resolved to 1 before select where was found table as depended (of select where was found table) */ - for (SELECT_LEX_NODE *s= this; + for (SELECT_LEX *s= this; s &&s != last; s= s->outer_select()) if ( !s->dependent ) { // Select is dependent of outer select s->dependent= 1; - if (s->linkage != GLOBAL_OPTIONS_TYPE) - { - //s is st_select_lex* - - s->master_unit()->dependent= 1; - //Tables will be reopened many times - for (TABLE_LIST *tbl= - s->get_table_list(); - tbl; - tbl= tbl->next) - tbl->shared= 1; - } + s->master_unit()->dependent= 1; + //Tables will be reopened many times + for (TABLE_LIST *tbl= + s->get_table_list(); + tbl; + tbl= tbl->next) + tbl->shared= 1; } } @@ -1200,15 +1185,6 @@ TABLE_LIST* st_select_lex_node::get_table_list() { return 0; } List<Item>* st_select_lex_node::get_item_list() { return 0; } List<String>* st_select_lex_node::get_use_index() { return 0; } List<String>* st_select_lex_node::get_ignore_index() { return 0; } -TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table, - LEX_STRING *alias, - ulong table_join_options, - thr_lock_type flags, - List<String> *use_index, - List<String> *ignore_index) -{ - return 0; -} ulong st_select_lex_node::get_table_join_options() { @@ -1218,7 +1194,7 @@ ulong st_select_lex_node::get_table_join_options() /* prohibit using LIMIT clause */ -bool st_select_lex_node::test_limit() +bool st_select_lex::test_limit() { if (select_limit != HA_POS_ERROR) { @@ -1293,22 +1269,39 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first; TABLE_LIST **new_table_list= *result, *aux; SELECT_LEX *sl= (SELECT_LEX*)slave; - for (; sl; sl= sl->next_select()) + + /* + iterate all inner selects + fake_select (if exists), + fake_select->next_select() always is 0 + */ + for (; + sl; + sl= (sl->next_select() ? + sl->next_select() : + (sl == fake_select_lex ? + 0 : + fake_select_lex))) { // check usage of ORDER BY in union - if (sl->order_list.first && sl->next_select() && !sl->braces) + if (sl->order_list.first && sl->next_select() && !sl->braces && + sl->linkage != GLOBAL_OPTIONS_TYPE) { net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY"); return 1; } + if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived) - continue; + goto end; + for (SELECT_LEX_UNIT *inner= sl->first_inner_unit(); inner; inner= inner->next_unit()) + { if (inner->create_total_list_n_last_return(thd, lex, &slave_list_last, 0)) return 1; + } + if ((aux= (TABLE_LIST*) sl->table_list.first)) { TABLE_LIST *next; @@ -1342,6 +1335,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, } } } +end: if (slave_list_first) { *new_table_list= slave_list_first; @@ -1361,9 +1355,9 @@ st_select_lex* st_select_lex_unit::outer_select() return (st_select_lex*) master; } -st_select_lex* st_select_lex::select_lex() +bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) { - return this; + return add_to_list(thd, order_list, item, asc); } bool st_select_lex::add_item_to_list(THD *thd, Item *item) @@ -1433,18 +1427,6 @@ ulong st_select_lex::get_table_join_options() return table_join_options; } -st_select_lex::st_select_lex(struct st_lex *lex) - :fake_select(0) -{ - select_number= ++lex->thd->select_number; - init_query(); - init_select(); - include_neighbour(lex->current_select); - include_global((st_select_lex_node**)&lex->all_selects_list); - lex->current_select= this; -} - - /* There are st_select_lex::add_table_to_list & st_select_lex::set_lock_for_tables in sql_parse.cc diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a48aa5721e481824bc88778bf9646f2aa02021df..adf452376a74ddfb674490bddb2060c972a60ada 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -118,6 +118,12 @@ enum olap_type subselects or derived tables) for ordinary select_lex - list of all select_lex (for group operation like correcting list of opened tables) + - if unit contain several selects (union) then it have special + select_lex called fake_select_lex. It used for storing global parameters + and executing union. subqueries of global ORDER BY clause will be + attached to this fake_select_lex, which will allow them correctly + resolve fields of 'upper' union and other more outer selects. + for example for following query: select * @@ -138,6 +144,7 @@ enum olap_type main unit + fake0 select1 select2 select3 |^^ |^ s||| ||master @@ -146,7 +153,8 @@ enum olap_type v|||master slave || e||+-------------------------+ || V| neighbor | V| - unit 1.1<==================>unit1.2 unit2.1 + unit1.1<+==================>unit1.2 unit2.1 + fake1.1 fake2.1 select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2 |^ || @@ -158,13 +166,14 @@ enum olap_type relation in main unit will be following: main unit - |^^^ - |||| - |||+------------------------------+ - ||+--------------+ | - slave||master | | - V| neighbor | neighbor | - select1<========>select2<========>select3 + |^^^^|fake_select_lex + |||||+--------------------------------------------+ + ||||+--------------------------------------------+| + |||+------------------------------+ || + ||+--------------+ | || + slave||master | | || + V| neighbor | neighbor | master|V + select1<========>select2<========>select3 fake0 list of all select_lex will be following (as it will be constructed by parser): @@ -199,17 +208,6 @@ public: ulong options; enum sub_select_type linkage; - SQL_LIST order_list; /* ORDER clause */ - List<List_item> expr_list; - List<List_item> when_list; /* WHEN clause (expression) */ - ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ - // Arrays of pointers to top elements of all_fields list - Item **ref_pointer_array; - - uint select_items; /* number of items in select_list */ - uint cond_count; /* number of arguments of and/or/xor in where/having */ - enum_parsing_place parsing_place; /* where we are parsing expression */ - bool with_sum_func; /* sum function indicator */ bool dependent; /* dependent from outer select subselect */ bool uncacheable; /* result of this query can't be cached */ bool no_table_names_allowed; /* used for global order by */ @@ -226,18 +224,13 @@ public: virtual void init_select(); void include_down(st_select_lex_node *upper); void include_neighbour(st_select_lex_node *before); + void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref); void include_global(st_select_lex_node **plink); void exclude(); - virtual st_select_lex* select_lex(); - virtual bool add_item_to_list(THD *thd, Item *item); - bool add_order_to_list(THD *thd, Item *item, bool asc); - virtual bool add_group_to_list(THD *thd, Item *item, bool asc); - virtual bool add_ftfunc_to_list(Item_func_match *func); - virtual st_select_lex_unit* master_unit()= 0; virtual st_select_lex* outer_select()= 0; - virtual st_select_lex_node* return_after_parsing()= 0; + virtual st_select_lex* return_after_parsing()= 0; virtual bool set_braces(bool value); virtual bool inc_in_sum_expr(); @@ -247,16 +240,7 @@ public: virtual List<String>* get_use_index(); virtual List<String>* get_ignore_index(); virtual ulong get_table_join_options(); - virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table, - LEX_STRING *alias, - ulong table_options, - thr_lock_type flags= TL_UNLOCK, - List<String> *use_index= 0, - List<String> *ignore_index= 0); virtual void set_lock_for_tables(thr_lock_type lock_type) {} - void mark_as_dependent(st_select_lex *last); - - bool test_limit(); friend class st_select_lex_unit; friend bool mysql_new_select(struct st_lex *lex, bool move_down); @@ -293,14 +277,17 @@ public: Pointer to 'last' select or pointer to unit where stored global parameters for union */ - st_select_lex_node *global_parameters; + st_select_lex *global_parameters; //node on wich we should return current_select pointer after parsing subquery - st_select_lex_node *return_to; + st_select_lex *return_to; /* LIMIT clause runtime counters */ ha_rows select_limit_cnt, offset_limit_cnt; /* not NULL if union used in subselect, point to subselect item */ Item_subselect *item; + /* thread handler */ THD *thd; + /* fake SELECT_LEX for union processing */ + st_select_lex *fake_select_lex; uint union_option; @@ -312,11 +299,10 @@ public: st_select_lex* first_select() { return (st_select_lex*) slave; } st_select_lex* first_select_in_union() { - return (slave && slave->linkage == GLOBAL_OPTIONS_TYPE) ? - (st_select_lex*) slave->next : (st_select_lex*) slave; + return (st_select_lex*) slave; } st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } - st_select_lex_node* return_after_parsing() { return return_to; } + st_select_lex* return_after_parsing() { return return_to; } void exclude_level(); /* UNION methods */ @@ -354,6 +340,19 @@ public: 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 */ + + SQL_LIST order_list; /* ORDER clause */ + List<List_item> expr_list; + List<List_item> when_list; /* WHEN clause (expression) */ + ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ + // Arrays of pointers to top elements of all_fields list + Item **ref_pointer_array; + + uint select_items; /* number of items in select_list */ + uint cond_count; /* number of arguments of and/or/xor in where/having */ + enum_parsing_place parsing_place; /* where we are parsing expression */ + bool with_sum_func; /* sum function indicator */ + ulong table_join_options; uint in_sum_expr; uint select_number; /* number of select (used for EXPLAIN) */ @@ -369,8 +368,6 @@ public: before passing to handle_select) */ bool insert_select; - /* TRUE for fake select, which used in UNION processing */ - bool fake_select; void init_query(); void init_select(); @@ -389,31 +386,33 @@ public: { return &link_next; } - st_select_lex_node* return_after_parsing() + st_select_lex* return_after_parsing() { return master_unit()->return_after_parsing(); } + void mark_as_dependent(st_select_lex *last); + bool set_braces(bool value); bool inc_in_sum_expr(); uint get_in_sum_expr(); - st_select_lex* select_lex(); bool add_item_to_list(THD *thd, Item *item); bool add_group_to_list(THD *thd, Item *item, bool asc); bool add_ftfunc_to_list(Item_func_match *func); - - TABLE_LIST* get_table_list(); - List<Item>* get_item_list(); - List<String>* get_use_index(); - List<String>* get_ignore_index(); - ulong get_table_join_options(); + bool add_order_to_list(THD *thd, Item *item, bool asc); TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table, LEX_STRING *alias, ulong table_options, thr_lock_type flags= TL_UNLOCK, List<String> *use_index= 0, List<String> *ignore_index= 0); + + TABLE_LIST* get_table_list(); + List<Item>* get_item_list(); + List<String>* get_use_index(); + List<String>* get_ignore_index(); + ulong get_table_join_options(); void set_lock_for_tables(thr_lock_type lock_type); inline void init_order() { @@ -422,15 +421,14 @@ public: order_list.next= (byte**) &order_list.first; } + bool test_limit(); + friend void mysql_init_query(THD *thd); - st_select_lex(struct st_lex *lex); - st_select_lex() :fake_select(0) {} - void make_empty_select(st_select_lex *last_select) + st_select_lex() {} + void make_empty_select() { - select_number=INT_MAX; init_query(); init_select(); - include_neighbour(last_select); } }; typedef class st_select_lex SELECT_LEX; @@ -445,7 +443,7 @@ typedef struct st_lex SELECT_LEX_UNIT unit; /* most upper unit */ SELECT_LEX select_lex; /* first SELECT_LEX */ /* current SELECT_LEX in parsing */ - SELECT_LEX_NODE *current_select; + SELECT_LEX *current_select; /* list of all SELECT_LEX */ SELECT_LEX *all_selects_list; uchar *ptr,*tok_start,*tok_end,*end_of_query; @@ -517,7 +515,7 @@ typedef struct st_lex but we should merk all subselects as uncacheable from current till most upper */ - SELECT_LEX_NODE *sl; + SELECT_LEX *sl; SELECT_LEX_UNIT *un; for (sl= current_select, un= sl->master_unit(); un != &unit; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5070466007e8f41270a6cfe2db82900d49fa0e97..915bed8ae9c84ee684591a6693019e32ba630e36 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3474,10 +3474,10 @@ mysql_init_query(THD *thd) lex->select_lex.init_query(); lex->value_list.empty(); lex->param_list.empty(); - lex->unit.next= lex->unit.master= lex->unit.return_to= - lex->unit.link_next= 0; + lex->unit.next= lex->unit.master= + lex->unit.link_next= lex->unit.return_to=0; lex->unit.prev= lex->unit.link_prev= 0; - lex->unit.global_parameters= lex->unit.slave= lex->current_select= + lex->unit.slave= lex->unit.global_parameters= lex->current_select= lex->all_selects_list= &lex->select_lex; lex->select_lex.master= &lex->unit; lex->select_lex.prev= &lex->unit.slave; @@ -3506,10 +3506,9 @@ mysql_init_query(THD *thd) void mysql_init_select(LEX *lex) { - SELECT_LEX *select_lex= lex->current_select->select_lex(); + SELECT_LEX *select_lex= lex->current_select; select_lex->init_select(); - select_lex->master_unit()->select_limit= select_lex->select_limit= - lex->thd->variables.select_limit; + select_lex->select_limit= lex->thd->variables.select_limit; if (select_lex == &lex->select_lex) { lex->exchange= 0; @@ -3537,17 +3536,32 @@ mysql_new_select(LEX *lex, bool move_down) unit->init_query(); unit->init_select(); unit->thd= lex->thd; - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) - unit->include_neighbour(lex->current_select); - else - unit->include_down(lex->current_select); + unit->include_down(lex->current_select); unit->link_next= 0; unit->link_prev= 0; unit->return_to= lex->current_select; select_lex->include_down(unit); } else + { select_lex->include_neighbour(lex->current_select); + SELECT_LEX_UNIT *unit= select_lex->master_unit(); + SELECT_LEX *fake= unit->fake_select_lex; + if (!fake) + { + /* + as far as we included SELECT_LEX for UNION unit should have + fake SELECT_LEX for UNION processing + */ + fake= unit->fake_select_lex= new SELECT_LEX(); + fake->include_standalone(unit, + (SELECT_LEX_NODE**)&unit->fake_select_lex); + fake->select_number= INT_MAX; + fake->make_empty_select(); + fake->linkage= GLOBAL_OPTIONS_TYPE; + fake->select_limit= lex->thd->variables.select_limit; + } + } select_lex->master_unit()->global_parameters= select_lex; select_lex->include_global((st_select_lex_node**)&lex->all_selects_list); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ca0f673954e88227b2c063277b90381387e5d0de..38c8cffdd22c2031262109d6853e8c6a84f82f5d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -318,7 +318,7 @@ JOIN::prepare(Item ***rref_pointer_array, { Item_subselect *subselect; if ((subselect= select_lex->master_unit()->item) && - !select_lex->fake_select) + select_lex->linkage != GLOBAL_OPTIONS_TYPE) { Item_subselect::trans_res res; if ((res= subselect->select_transformer(this)) != @@ -5713,7 +5713,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), else { join->do_send_rows= 0; - join->unit->select_limit= HA_POS_ERROR; + if (join->unit->fake_select_lex) + join->unit->fake_select_lex->select_limit= HA_POS_ERROR; DBUG_RETURN(0); } } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 79e1e9843a86727604a7c19de9906748a3b7a789..7c9e6f0a24e4a183bd5804bcfa7d0d5a610d1cd2 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -115,7 +115,7 @@ bool select_union::flush() int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, bool tables_and_fields_initied) { - SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; + SELECT_LEX *lex_select_save= thd->lex.current_select; SELECT_LEX *select_cursor; DBUG_ENTER("st_select_lex_unit::prepare"); @@ -241,7 +241,7 @@ err: int st_select_lex_unit::exec() { int do_print_slow= 0; - SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; + SELECT_LEX *lex_select_save= thd->lex.current_select; SELECT_LEX *select_cursor=first_select_in_union(); DBUG_ENTER("st_select_lex_unit::exec"); @@ -318,8 +318,7 @@ int st_select_lex_unit::exec() /* Send result to 'result' */ - // to correct ORDER BY reference resolving - thd->lex.current_select= select_cursor; + res= -1; { List<Item_func_match> empty_list; @@ -327,8 +326,7 @@ int st_select_lex_unit::exec() if (!thd->is_fatal_error) // Check if EOM { - SELECT_LEX *fake_select = new SELECT_LEX(&thd->lex); - fake_select->fake_select= 1; + thd->lex.current_select= fake_select_lex; offset_limit_cnt= (select_cursor->braces ? global_parameters->offset_limit : 0); select_limit_cnt= (select_cursor->braces ? @@ -338,19 +336,19 @@ int st_select_lex_unit::exec() select_limit_cnt= HA_POS_ERROR; // no limit if (select_limit_cnt == HA_POS_ERROR) thd->options&= ~OPTION_FOUND_ROWS; - fake_select->ftfunc_list= &empty_list; - fake_select->table_list.link_in_list((byte *)&result_table_list, - (byte **)&result_table_list.next); - res= mysql_select(thd, &ref_pointer_array, &result_table_list, + fake_select_lex->ftfunc_list= &empty_list; + fake_select_lex->table_list.link_in_list((byte *)&result_table_list, + (byte **) + &result_table_list.next); + res= mysql_select(thd, &fake_select_lex->ref_pointer_array, + &result_table_list, 0, item_list, NULL, global_parameters->order_list.elements, (ORDER*)global_parameters->order_list.first, (ORDER*) NULL, NULL, (ORDER*) NULL, - thd->options, result, this, fake_select, 0); + thd->options, result, this, fake_select_lex, 0); if (found_rows_for_union && !res) thd->limit_found_rows = (ulonglong)table->file->records; - fake_select->exclude(); - delete fake_select; /* Mark for slow query log if any of the union parts didn't use indexes efficiently diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 659744ce677cc6767f07e403de163b5b5ce8988d..23ce607040d92a7aa26d7282f6e7d17427bcd577 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1835,7 +1835,7 @@ table_to_table: table_ident TO_SYM table_ident { LEX *lex=Lex; - SELECT_LEX_NODE *sl= lex->current_select; + SELECT_LEX *sl= lex->current_select; if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING, TL_IGNORE) || !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING, @@ -1871,7 +1871,7 @@ preload_keys: ; preload_keys_spec: - keys_or_index { Select->select_lex()->interval_list.empty(); } + keys_or_index { Select->interval_list.empty(); } preload_key_list_or_empty { LEX *lex=Lex; @@ -1907,7 +1907,7 @@ select_init: '(' SELECT_SYM select_part2 ')' { LEX *lex= Lex; - SELECT_LEX * sel= lex->current_select->select_lex(); + SELECT_LEX * sel= lex->current_select; if (sel->set_braces(1)) { send_error(lex->thd, ER_SYNTAX_ERROR); @@ -1921,14 +1921,14 @@ select_init: } /* select in braces, can't contain global parameters */ sel->master_unit()->global_parameters= - sel->master_unit(); + sel->master_unit()->fake_select_lex; } union_opt; select_init2: select_part2 { LEX *lex= Lex; - SELECT_LEX * sel= lex->current_select->select_lex(); + SELECT_LEX * sel= lex->current_select; if (lex->current_select->set_braces(0)) { send_error(lex->thd, ER_SYNTAX_ERROR); @@ -1947,7 +1947,7 @@ select_init2: select_part2: { LEX *lex=Lex; - SELECT_LEX * sel= lex->current_select->select_lex(); + SELECT_LEX * sel= lex->current_select; if (lex->current_select == &lex->select_lex) lex->lock_option= TL_READ; /* Only for global SELECT */ if (sel->linkage != UNION_TYPE) @@ -2038,7 +2038,7 @@ select_item_list: THD *thd= YYTHD; if (add_item_to_list(thd, new Item_field(NULL, NULL, "*"))) YYABORT; - (thd->lex.current_select->select_lex()->with_wild)++; + (thd->lex.current_select->with_wild)++; }; @@ -2668,9 +2668,9 @@ sum_expr: | COUNT_SYM '(' in_sum_expr ')' { $$=new Item_sum_count($3); } | COUNT_SYM '(' DISTINCT - { Select->select_lex()->in_sum_expr++; } + { Select->in_sum_expr++; } expr_list - { Select->select_lex()->in_sum_expr--; } + { Select->in_sum_expr--; } ')' { $$=new Item_sum_count_distinct(* $5); } | GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')' @@ -2726,7 +2726,7 @@ in_sum_expr: } expr { - Select->select_lex()->in_sum_expr--; + Select->in_sum_expr--; $$= $3; }; @@ -2780,13 +2780,13 @@ when_list: when_list2: expr THEN_SYM expr { - SELECT_LEX_NODE *sel=Select; + SELECT_LEX *sel=Select; sel->when_list.head()->push_back($1); sel->when_list.head()->push_back($3); } | when_list2 WHEN_SYM expr THEN_SYM expr { - SELECT_LEX_NODE *sel=Select; + SELECT_LEX *sel=Select; sel->when_list.head()->push_back($3); sel->when_list.head()->push_back($5); }; @@ -2803,7 +2803,7 @@ join_table_list: | join_table_list normal_join join_table_list USING { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->db1=$1->db; sel->table1=$1->alias; sel->db2=$3->db; sel->table2=$3->alias; } @@ -2814,7 +2814,7 @@ join_table_list: { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | join_table_list LEFT opt_outer JOIN_SYM join_table_list { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->db1=$1->db; sel->table1=$1->alias; sel->db2=$5->db; sel->table2=$5->alias; } @@ -2830,7 +2830,7 @@ join_table_list: { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; } | join_table_list RIGHT opt_outer JOIN_SYM join_table_list { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->db1=$1->db; sel->table1=$1->alias; sel->db2=$5->db; sel->table2=$5->alias; } @@ -2853,14 +2853,14 @@ normal_join: join_table: { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->use_index_ptr=sel->ignore_index_ptr=0; sel->table_join_options= 0; } table_ident opt_table_alias opt_key_definition { LEX *lex= Lex; - SELECT_LEX_NODE *sel= lex->current_select; + SELECT_LEX *sel= lex->current_select; if (!($$= sel->add_table_to_list(lex->thd, $2, $3, sel->get_table_join_options(), lex->lock_option, @@ -2910,28 +2910,28 @@ opt_key_definition: /* empty */ {} | USE_SYM key_usage_list { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->use_index= *$2; sel->use_index_ptr= &sel->use_index; } | FORCE_SYM key_usage_list { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->use_index= *$2; sel->use_index_ptr= &sel->use_index; sel->table_join_options|= TL_OPTION_FORCE_INDEX; } | IGNORE_SYM key_usage_list { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->ignore_index= *$2; sel->ignore_index_ptr= &sel->ignore_index; }; key_usage_list: - key_or_index { Select->select_lex()->interval_list.empty(); } + key_or_index { Select->interval_list.empty(); } '(' key_list_or_empty ')' - { $$= &Select->select_lex()->interval_list; } + { $$= &Select->interval_list; } ; key_list_or_empty: @@ -2941,22 +2941,22 @@ key_list_or_empty: key_usage_list2: key_usage_list2 ',' ident - { Select->select_lex()-> + { Select-> interval_list.push_back(new String((const char*) $3.str, $3.length, system_charset_info)); } | ident - { Select->select_lex()-> + { Select-> interval_list.push_back(new String((const char*) $1.str, $1.length, system_charset_info)); } | PRIMARY_SYM - { Select->select_lex()-> + { Select-> interval_list.push_back(new String("PRIMARY", 7, system_charset_info)); }; using_list: ident { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1, $1.str), new Item_field(sel->db2, sel->table2, @@ -2965,7 +2965,7 @@ using_list: } | using_list ',' ident { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1))) YYABORT; }; @@ -3001,10 +3001,10 @@ opt_all: ; where_clause: - /* empty */ { Select->select_lex()->where= 0; } + /* empty */ { Select->where= 0; } | WHERE expr { - Select->select_lex()->where= $2; + Select->where= $2; if ($2) $2->top_level_item(); } @@ -3014,11 +3014,11 @@ having_clause: /* empty */ | HAVING { - Select->select_lex()->parsing_place= SELECT_LEX_NODE::IN_HAVING; + Select->parsing_place= SELECT_LEX_NODE::IN_HAVING; } expr { - SELECT_LEX *sel= Select->select_lex(); + SELECT_LEX *sel= Select; sel->having= $3; sel->parsing_place= SELECT_LEX_NODE::NO_MATTER; if ($3) @@ -3056,7 +3056,7 @@ olap_opt: "global union parameters"); YYABORT; } - lex->current_select->select_lex()->olap= CUBE_TYPE; + lex->current_select->olap= CUBE_TYPE; net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE"); YYABORT; /* To be deleted in 5.1 */ } @@ -3069,7 +3069,7 @@ olap_opt: "global union parameters"); YYABORT; } - lex->current_select->select_lex()->olap= ROLLUP_TYPE; + lex->current_select->olap= ROLLUP_TYPE; } ; @@ -3086,7 +3086,7 @@ order_clause: { LEX *lex=Lex; if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && - lex->current_select->select_lex()->olap != + lex->current_select->olap != UNSPECIFIED_OLAP_TYPE) { net_printf(lex->thd, ER_WRONG_USAGE, @@ -3111,7 +3111,7 @@ order_dir: opt_limit_clause_init: /* empty */ { - SELECT_LEX_NODE *sel= Select; + SELECT_LEX *sel= Select; sel->offset_limit= 0L; sel->select_limit= Lex->thd->variables.select_limit; } @@ -3130,19 +3130,19 @@ limit_clause: limit_options: ULONG_NUM { - SELECT_LEX_NODE *sel= Select; + SELECT_LEX *sel= Select; sel->select_limit= $1; sel->offset_limit= 0L; } | ULONG_NUM ',' ULONG_NUM { - SELECT_LEX_NODE *sel= Select; + SELECT_LEX *sel= Select; sel->select_limit= $3; sel->offset_limit= $1; } | ULONG_NUM OFFSET_SYM ULONG_NUM { - SELECT_LEX_NODE *sel= Select; + SELECT_LEX *sel= Select; sel->select_limit= $1; sel->offset_limit= $3; } @@ -4117,14 +4117,14 @@ table_wild: ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); - Lex->current_select->select_lex()->with_wild++; + Lex->current_select->with_wild++; } | ident '.' ident '.' '*' { $$ = new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str,"*"); - Lex->current_select->select_lex()->with_wild++; + Lex->current_select->with_wild++; } ; @@ -4134,7 +4134,7 @@ order_ident: simple_ident: ident { - SELECT_LEX_NODE *sel=Select; + SELECT_LEX *sel=Select; $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,NullS,$1.str) : @@ -4144,7 +4144,7 @@ simple_ident: { THD *thd= YYTHD; LEX *lex= &thd->lex; - SELECT_LEX_NODE *sel= lex->current_select; + SELECT_LEX *sel= lex->current_select; if (sel->no_table_names_allowed) { my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, @@ -4160,7 +4160,7 @@ simple_ident: { THD *thd= YYTHD; LEX *lex= &thd->lex; - SELECT_LEX_NODE *sel= lex->current_select; + SELECT_LEX *sel= lex->current_select; if (sel->no_table_names_allowed) { my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, @@ -4176,7 +4176,7 @@ simple_ident: { THD *thd= YYTHD; LEX *lex= &thd->lex; - SELECT_LEX_NODE *sel= lex->current_select; + SELECT_LEX *sel= lex->current_select; if (sel->no_table_names_allowed) { my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, @@ -4858,7 +4858,7 @@ opt_table: '*' { LEX *lex= Lex; - lex->current_select->select_lex()->db= lex->thd->db; + lex->current_select->db= lex->thd->db; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) @@ -4870,7 +4870,7 @@ opt_table: | ident '.' '*' { LEX *lex= Lex; - lex->current_select->select_lex()->db = $1.str; + lex->current_select->db = $1.str; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) @@ -4882,7 +4882,7 @@ opt_table: | '*' '.' '*' { LEX *lex= Lex; - lex->current_select->select_lex()->db = NULL; + lex->current_select->db = NULL; if (lex->grant == GLOBAL_ACLS) lex->grant= GLOBAL_ACLS & ~GRANT_ACL; else if (lex->columns.elements) @@ -5077,11 +5077,12 @@ optional_order_or_limit: THD *thd= YYTHD; LEX *lex= &thd->lex; DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE); - SELECT_LEX *sel= lex->current_select->select_lex(); + SELECT_LEX *sel= lex->current_select; SELECT_LEX_UNIT *unit= sel->master_unit(); - unit->global_parameters= unit; - unit->no_table_names_allowed= 1; - lex->current_select= unit; + SELECT_LEX *fake= unit->fake_select_lex; + unit->global_parameters= fake; + fake->no_table_names_allowed= 1; + lex->current_select= fake; thd->where= "global ORDER clause"; } order_or_limit