diff options
Diffstat (limited to 'sql/sql_lex.h')
-rw-r--r-- | sql/sql_lex.h | 234 |
1 files changed, 218 insertions, 16 deletions
diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 02c2ffb6a12..5c053022317 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -74,6 +74,16 @@ enum sub_select_type UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE }; + +inline int cmp_unit_op(enum sub_select_type op1, enum sub_select_type op2) +{ + DBUG_ASSERT(op1 >= UNION_TYPE && op1 <= EXCEPT_TYPE); + DBUG_ASSERT(op2 >= UNION_TYPE && op2 <= EXCEPT_TYPE); + return (op1 == INTERSECT_TYPE ? 1 : 0) - (op2 == INTERSECT_TYPE ? 1 : 0); +} + +bool check_intersect_prefix(SELECT_LEX* first_in_unit); + enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT}; enum enum_view_suid @@ -193,6 +203,7 @@ struct LEX_TYPE additional "partitions" column even if partitioning is not compiled in. */ #define DESCRIBE_PARTITIONS 4 +#define DESCRIBE_EXTENDED2 8 #ifdef MYSQL_SERVER @@ -431,7 +442,7 @@ public: unit is container of either - One SELECT - UNION of selects - select_lex and unit are both inherited form select_lex_node + select_lex and unit are both inherited form st_select_lex_node neighbors are two select_lex or units on the same level All select describing structures linked with following pointers: @@ -577,6 +588,7 @@ public: { return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE; } + bool distinct; bool no_table_names_allowed; /* used for global order by */ static void *operator new(size_t size, MEM_ROOT *mem_root) throw () @@ -597,10 +609,29 @@ public: void include_down(st_select_lex_node *upper); void add_slave(st_select_lex_node *slave_arg); void include_neighbour(st_select_lex_node *before); + void link_chain_down(st_select_lex_node *first); + void link_neighbour(st_select_lex_node *neighbour) + { + DBUG_ASSERT(next == NULL); + DBUG_ASSERT(neighbour != NULL); + next= neighbour; + neighbour->prev= &next; + } + void cut_next() { next= NULL; } void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref); void include_global(st_select_lex_node **plink); void exclude(); void exclude_from_tree(); + void exclude_from_global() + { + if (!link_prev) + return; + if (((*link_prev)= link_next)) + link_next->link_prev= link_prev; + link_next= NULL; + link_prev= NULL; + } + void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; } void move_node(st_select_lex_node *where_to_move) @@ -616,6 +647,22 @@ public: st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert, st_select_lex_node *end_chain_node); void move_as_slave(st_select_lex_node *new_master); + void set_linkage(enum sub_select_type l) + { + DBUG_ENTER("st_select_lex_node::set_linkage"); + DBUG_PRINT("info", ("node: %p linkage: %d->%d", this, linkage, l)); + linkage= l; + DBUG_VOID_RETURN; + } + /* + This method created for reiniting LEX in mysql_admin_table() and can be + used only if you are going remove all SELECT_LEX & units except belonger + to LEX (LEX::unit & LEX::select, for other purposes there are + SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree. + + It is also used in parsing to detach builtin select. + */ + void cut_subtree() { slave= 0; } friend class st_select_lex_unit; friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel); friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, @@ -625,6 +672,8 @@ public: friend bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *orig_table_list); friend bool TABLE_LIST::init_derived(THD *thd, bool init_view); + + friend class st_select_lex; private: void fast_exclude(); }; @@ -670,9 +719,9 @@ public: { } - TABLE *table; /* temporary table using for appending UNION results */ select_result *result; + st_select_lex *pre_last_parse; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) optimized_2, @@ -759,7 +808,7 @@ public: { return reinterpret_cast<st_select_lex*>(slave); } - inline void set_with_clause(With_clause *with_cl); + void set_with_clause(With_clause *with_cl); st_select_lex_unit* next_unit() { return reinterpret_cast<st_select_lex_unit*>(next); @@ -801,6 +850,16 @@ public: int save_union_explain(Explain_query *output); int save_union_explain_part2(Explain_query *output); unit_common_op common_op(); + + void reset_distinct(); + void fix_distinct(st_select_lex_unit *new_unit); + + void register_select_chain(SELECT_LEX *first_sel); + + bool set_nest_level(int new_nest_level); + bool check_parameters(SELECT_LEX *main_select); + + friend class st_select_lex; }; typedef class st_select_lex_unit SELECT_LEX_UNIT; @@ -922,6 +981,7 @@ public: SQL_I_List<ORDER> order_list; /* ORDER clause */ SQL_I_List<ORDER> gorder_list; Item *select_limit, *offset_limit; /* LIMIT clause parameters */ + bool is_set_query_expr_tail; /// Array of pointers to top elements of all_fields list Ref_ptr_array ref_pointer_array; @@ -1051,6 +1111,10 @@ public: void init_query(); void init_select(); st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } + inline void set_master_unit(st_select_lex_unit *master_unit) + { + master= (st_select_lex_node *)master_unit; + } st_select_lex_unit* first_inner_unit() { return (st_select_lex_unit*) slave; @@ -1283,6 +1347,32 @@ public: DBUG_ASSERT(this != sel); select_n_where_fields+= sel->select_n_where_fields; } + inline void set_linkage_and_distinct(enum sub_select_type l, bool d) + { + DBUG_ENTER("SELECT_LEX::set_linkage_and_distinct"); + DBUG_PRINT("info", ("select: %p distinct %d", this, d)); + set_linkage(l); + DBUG_ASSERT(l == UNION_TYPE || + l == INTERSECT_TYPE || + l == EXCEPT_TYPE); + if (d && master_unit() && master_unit()->union_distinct != this) + master_unit()->union_distinct= this; + distinct= d; + DBUG_VOID_RETURN; + } + bool set_nest_level(int new_nest_level); + bool check_parameters(SELECT_LEX *main_select); + void mark_select() + { + DBUG_ENTER("st_select_lex::mark_select()"); + DBUG_PRINT("info", ("Select #%d", select_number)); + DBUG_VOID_RETURN; + } + void register_unit(SELECT_LEX_UNIT *unit, + Name_resolution_context *outer_context); + SELECT_LEX_UNIT *attach_selects_chain(SELECT_LEX *sel, + Name_resolution_context *context); + void add_statistics(SELECT_LEX_UNIT *unit); }; typedef class st_select_lex SELECT_LEX; @@ -2664,7 +2754,8 @@ class Query_arena_memroot; struct LEX: public Query_tables_list { SELECT_LEX_UNIT unit; /* most upper unit */ - SELECT_LEX select_lex; /* first SELECT_LEX */ + inline SELECT_LEX *first_select_lex() {return unit.first_select();} + SELECT_LEX builtin_select; /* current SELECT_LEX in parsing */ SELECT_LEX *current_select; /* list of all SELECT_LEX */ @@ -2774,6 +2865,9 @@ public: required a local context, the parser pops the top-most context. */ List<Name_resolution_context> context_stack; + List<SELECT_LEX> last_select_stack; + SELECT_LEX *select_stack[MAX_SELECT_NESTING]; + uint select_stack_top; SQL_I_List<ORDER> proc_list; SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list; @@ -2813,6 +2907,8 @@ public: syntax error back. */ bool expr_allows_subselect; + bool selects_allow_into; + bool selects_allow_procedure; /* A special command "PARSE_VCOL_EXPR" is defined for the parser to translate a defining expression of a virtual column into an @@ -2867,6 +2963,8 @@ public: enum enum_yes_no_unknown tx_chain, tx_release; bool safe_to_cache_query; bool subqueries, ignore; + bool next_is_main; // use "main" SELECT_LEX for nrxt allocation; + bool next_is_down; // use "main" SELECT_LEX for nrxt allocation; st_parsing_options parsing_options; Alter_info alter_info; /* @@ -3068,20 +3166,24 @@ public: SELECT_LEX *sl; SELECT_LEX_UNIT *un; for (sl= current_select, un= sl->master_unit(); - un != &unit; - sl= sl->outer_select(), un= sl->master_unit()) + un && un != &unit; + sl= sl->outer_select(), un= (sl ? sl->master_unit() : NULL)) { - sl->uncacheable|= cause; - un->uncacheable|= cause; + sl->uncacheable|= cause; + un->uncacheable|= cause; } - select_lex.uncacheable|= cause; + if (sl) + sl->uncacheable|= cause; } + if (first_select_lex()) + first_select_lex()->uncacheable|= cause; } void set_trg_event_type_for_tables(); TABLE_LIST *unlink_first_table(bool *link_to_local); void link_first_table_back(TABLE_LIST *first, bool link_to_local); void first_lists_tables_same(); + void fix_first_select_number(); bool can_be_merged(); bool can_use_merged(); @@ -3119,14 +3221,90 @@ public: void cleanup_after_one_table_open(); - bool push_context(Name_resolution_context *context, MEM_ROOT *mem_root) + bool push_context(Name_resolution_context *context); + + void pop_context() { - return context_stack.push_front(context, mem_root); + DBUG_ENTER("LEX::pop_context"); + Name_resolution_context *context= context_stack.pop(); + DBUG_PRINT("info", ("Pop context %p Select: %p (%d)", + context, context->select_lex, + (context->select_lex ? + context->select_lex->select_number: + 0))); + DBUG_VOID_RETURN; } - void pop_context() + bool push_new_select(SELECT_LEX *last); + + SELECT_LEX *pop_new_select() + { + DBUG_ENTER("LEX::pop_new_select"); + SELECT_LEX* last= last_select_stack.pop(); + DBUG_PRINT("info", ("Pop last elect: %p (%d)", + last, last->select_number)); + DBUG_RETURN(last); + } + + SELECT_LEX *select_stack_head() + { + if (likely(select_stack_top)) + return select_stack[select_stack_top - 1]; + return NULL; + } + + + bool push_select(SELECT_LEX *select_lex) + { + DBUG_ENTER("LEX::push_select"); + DBUG_PRINT("info", ("Top Select was %p (%d) depth: %u pushed: %p (%d)", + select_stack_head(), + select_stack_top, + (select_stack_top ? + select_stack_head()->select_number : + 0), + select_lex, select_lex->select_number)); + if (unlikely(select_stack_top == MAX_SELECT_NESTING)) + { + my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0)); + DBUG_RETURN(TRUE); + } + if (push_context(&select_lex->context)) + DBUG_RETURN(TRUE); + select_stack[select_stack_top++]= select_lex; + current_select= select_lex; + DBUG_RETURN(FALSE); + } + + SELECT_LEX *pop_select() { - context_stack.pop(); + DBUG_ENTER("LEX::pop_select"); + SELECT_LEX *select_lex; + if (likely(select_stack_top)) + select_lex= select_stack[--select_stack_top]; + else + select_lex= 0; + DBUG_PRINT("info", ("Top Select is %p (%d) depth: %u poped: %p (%d)", + select_stack_head(), + select_stack_top, + (select_stack_top ? + select_stack_head()->select_number : + 0), + select_lex, + (select_lex ? select_lex->select_number : 0))); + DBUG_ASSERT(select_lex); + + pop_context(); + + if (unlikely(!select_stack_top)) + { + current_select= NULL; + DBUG_PRINT("info", ("Top Select is empty")); + } + else + current_select= select_stack[select_stack_top - 1]; + + DBUG_RETURN(select_lex); } bool copy_db_to(LEX_CSTRING *to); @@ -3160,9 +3338,8 @@ public: on its top. So select_lex (as the first added) will be at the tail of the list. */ - if (&select_lex == all_selects_list && !sroutines.records) + if (first_select_lex() == all_selects_list && !sroutines.records) { - DBUG_ASSERT(!all_selects_list->next_select_in_list()); return TRUE; } return FALSE; @@ -3731,6 +3908,7 @@ public: bool if_exists() const { return create_info.if_exists(); } SELECT_LEX *exclude_last_select(); + SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude); bool add_unit_in_brackets(SELECT_LEX *nselect); void check_automatic_up(enum sub_select_type type); bool create_or_alter_view_finalize(THD *thd, Table_ident *table_ident); @@ -3739,7 +3917,6 @@ public: bool add_create_view(THD *thd, DDL_options_st ddl, uint16 algorithm, enum_view_suid suid, Table_ident *table_ident); - bool add_grant_command(THD *thd, enum_sql_command sql_command_arg, stored_procedure_type type_arg); @@ -3748,6 +3925,31 @@ public: return create_info.vers_info; } sp_package *get_sp_package() const; + + bool make_select_in_brackets(SELECT_LEX* dummy_select, + SELECT_LEX *nselect, bool automatic); + + SELECT_LEX_UNIT *alloc_unit(); + SELECT_LEX *alloc_select(bool is_select); + SELECT_LEX_UNIT *create_unit(SELECT_LEX*); + SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit); + SELECT_LEX *link_selects_chain_down(SELECT_LEX *sel); + bool main_select_push(); + bool insert_select_hack(SELECT_LEX *sel); + SELECT_LEX *pop_new_select_and_wrap(); + + void set_main_unit(st_select_lex_unit *u) + { + unit.options= u->options; + unit.uncacheable= u->uncacheable; + unit.register_select_chain(u->first_select()); + unit.first_select()->options|= builtin_select.options; + unit.fake_select_lex= u->fake_select_lex; + unit.union_distinct= u->union_distinct; + unit.set_with_clause(u->with_clause); + builtin_select.exclude_from_global(); + } + bool check_main_unit_semantics(); }; |