diff options
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r-- | sql/sql_lex.cc | 181 |
1 files changed, 112 insertions, 69 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 84a4ec4ed5b..a3718731d8c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -948,27 +948,17 @@ void st_select_lex_node::init_query() options= 0; linkage= UNSPECIFIED_TYPE; no_error= 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_n_having_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; @@ -976,6 +966,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() @@ -988,7 +979,9 @@ void st_select_lex::init_query() olap= UNSPECIFIED_OLAP_TYPE; having_fix_field= 0; resolve_mode= NOMATTER_MODE; - with_wild= 0; + cond_count= with_wild= 0; + ref_pointer_array= 0; + select_n_having_items= 0; } void st_select_lex::init_select() @@ -997,7 +990,6 @@ void st_select_lex::init_select() group_list.empty(); type= db= db1= table1= db2= table2= 0; having= 0; - group_list.empty(); use_index_ptr= ignore_index_ptr= 0; table_join_options= 0; in_sum_expr= with_wild= 0; @@ -1010,6 +1002,13 @@ 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; + with_sum_func= 0; + parsing_place= SELECT_LEX_NODE::NO_MATTER; } /* @@ -1027,6 +1026,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) { @@ -1108,33 +1124,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 @@ -1148,31 +1137,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; } } @@ -1190,10 +1174,49 @@ TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table, List<String> *use_index, List<String> *ignore_index, LEX_STRING *option) +ulong st_select_lex_node::get_table_join_options() { return 0; } -ulong st_select_lex_node::get_table_join_options() { return 0; } + +/* + prohibit using LIMIT clause +*/ +bool st_select_lex::test_limit() +{ + if (select_limit != HA_POS_ERROR) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), + "LIMIT & IN/ALL/ANY/SOME subquery"); + return(1); + } + // We need only 1 row to determinate existence + select_limit= 1; + // no sense in ORDER BY without LIMIT + order_list.empty(); + return(0); +} + + + + + + + + + + + + + + + + + + + + + /* @@ -1256,22 +1279,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; @@ -1294,15 +1334,18 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, return 1; } *new_table_list= cursor; + cursor->table_list= aux; //to be able mark this table as shared new_table_list= &cursor->next; *new_table_list= 0; // end result list } else - aux->shared= 1; // Mark that it's used twice + // Mark that it's used twice + cursor->table_list->shared= aux->shared= 1; aux->table_list= cursor; } } } +end: if (slave_list_first) { *new_table_list= slave_list_first; @@ -1322,9 +1365,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) @@ -1394,17 +1437,17 @@ ulong st_select_lex::get_table_join_options() return table_join_options; } -st_select_lex::st_select_lex(struct st_lex *lex) +bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) { - 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; + if (ref_pointer_array) + return 0; + return (ref_pointer_array= + (Item **)thd->alloc(sizeof(Item*) * + (item_list.elements + + select_n_having_items + + order_group_num)* 5)) == 0; } - /* There are st_select_lex::add_table_to_list & st_select_lex::set_lock_for_tables in sql_parse.cc |