Hello Sanja,
I reviewed your recent changes in "10.3-MDEV-11953" (and the attached additional patch for sql_yacc_ora.yy) I have some proposals: 1. Can you please move huge pieces of the code from sql_yacc.yy to LEX or other relevant classes? It makes the grammar much more readable (patches are aslo much more readable). I'd move the relevant pieces of the code to LEX as a separate patch, even before fixing the grammar. 2. You're adding too many main_select_push() and pop_select(). Please move them to upper level rules (it should be possible in many cases). Add new helper rules when needed. For example, this piece of code repeats many times: + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + expr + { + Lex->pop_select(); //main select + $$= $3; It deserved a rule, say, expr_with_select_push_pop. You can find a better name :) - Serg and I spent a lot of time working on this task: MDEV-8909 union parser cleanup (and its 13 dependency tasks, and 3 related tasks, see the "Issue links" section in MDEV). We think that it should be the parser who disallows bad grammar, instead of post-analysis with raising errors like ER_CANT_USE_OPTION_HERE. Please keep using the same approach. Thanks! On 04/06/2018 07:37 PM, Oleksandr Byelkin wrote: > > > > -------- Weitergeleitete Nachricht -------- > Betreff: [Commits] b32031991e4: initial oracle parser fix > Datum: Fri, 06 Apr 2018 17:34:31 +0200 > Von: Oleksandr Byelkin <sa...@mariadb.com> > Antwort an: maria-developers@lists.launchpad.net > An: comm...@mariadb.org > > > > revision-id: b32031991e4ba270f5c221f7f6068732d09efd53 > (mariadb-10.3.5-110-gb32031991e4) > parent(s): 60a502eb7efbe87bd8e3af3e3ece49a9eb83f8b3 > author: Oleksandr Byelkin > committer: Oleksandr Byelkin > timestamp: 2018-04-06 17:05:34 +0200 > message: > > initial oracle parser fix > > --- > sql/sql_yacc.yy | 8 +- > sql/sql_yacc_ora.yy | 2085 > +++++++++++++++++++++++++++++---------------------- > 2 files changed, 1183 insertions(+), 910 deletions(-) > > diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy > index e4cbff7114e..9372269b05d 100644 > --- a/sql/sql_yacc.yy > +++ b/sql/sql_yacc.yy > @@ -904,7 +904,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > %parse-param { THD *thd } > %lex-param { THD *thd } > /* > - Currently there are 96 shift/reduce conflicts. > + Currently there are 135 shift/reduce conflicts. > We should not introduce new conflicts any more. > */ > %expect 135 > @@ -9244,7 +9244,7 @@ table_value_constructor: > lex->push_select(sel)) > MYSQL_YYABORT; > sel->init_select(); > - sel->braces= FALSE; > + sel->braces= FALSE; // just initialisation > } > values_list > { > @@ -13763,8 +13763,10 @@ single_multi: > } > | table_wild_list > { > + /* XXX > if (Lex->main_select_push()) > MYSQL_YYABORT; > + */ > mysql_init_multi_delete(Lex); > YYPS->m_lock_type= TL_READ_DEFAULT; > YYPS->m_mdl_type= MDL_SHARED_READ; > @@ -13779,8 +13781,10 @@ single_multi: > } > | FROM table_alias_ref_list > { > + /* XXX > if (Lex->main_select_push()) > MYSQL_YYABORT; > + */ > mysql_init_multi_delete(Lex); > YYPS->m_lock_type= TL_READ_DEFAULT; > YYPS->m_mdl_type= MDL_SHARED_READ; > diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy > index c1512434d72..4a3ee348f89 100644 > --- a/sql/sql_yacc_ora.yy > +++ b/sql/sql_yacc_ora.yy > @@ -186,6 +186,20 @@ void ORAerror(THD *thd, const char *s) > LEX_CSTRING name; > uint offset; > } sp_cursor_name_and_offset; > + struct > + { > + enum sub_select_type unit_type; > + bool distinct; > + } unit_operation; > + struct > + { > + SELECT_LEX *first; > + SELECT_LEX *prev_last; > + } select_list; > + SQL_I_List<ORDER> *select_order; > + Lex_select_lock select_lock; > + Lex_select_limit select_limit; > + Lex_order_limit_lock *order_limit_lock; > > /* pointers */ > Create_field *create_field; > @@ -231,6 +245,7 @@ void ORAerror(THD *thd, const char *s) > > handlerton *db_type; > st_select_lex *select_lex; > + st_select_lex_unit *select_lex_unit; > struct p_elem_val *p_elem_value; > class Window_frame *window_frame; > class Window_frame_bound *window_frame_bound; > @@ -240,7 +255,6 @@ void ORAerror(THD *thd, const char *s) > /* enums */ > enum enum_sp_suid_behaviour sp_suid; > enum enum_view_suid view_suid; > - enum sub_select_type unit_type; > enum Condition_information_item::Name cond_info_item_name; > enum enum_diag_condition_item_name diag_condition_item_name; > enum Diagnostics_information::Which_area diag_area; > @@ -277,10 +291,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > %parse-param { THD *thd } > %lex-param { THD *thd } > /* > - Currently there are 104 shift/reduce conflicts. > + Currently there are 99 shift/reduce conflicts. > We should not introduce new conflicts any more. > */ > -%expect 104 > +%expect 99 > > /* > Comments for TOKENS. > @@ -599,6 +613,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > %token LEAVES > %token LEAVE_SYM > %token LEFT /* SQL-2003-R */ > +%token LEFT_PAREN_ALT /* INTERNAL */ > +%token LEFT_PAREN_WITH /* INTERNAL */ > +%token LEFT_PAREN_LIKE /* INTERNAL */ > %token LESS_SYM > %token LEVEL_SYM > %token LEX_HOSTNAME > @@ -1063,7 +1080,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > NCHAR_STRING > > %type <lex_str_ptr> > - opt_table_alias > + opt_table_alias_clause > + table_alias_clause > > %type <lex_string_with_pos> > ident ident_with_tok_start > @@ -1111,7 +1129,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > opt_temporary all_or_any opt_distinct opt_glimit_clause > opt_ignore_leaves fulltext_options union_option > opt_not > - select_derived_init transaction_access_mode_types > + transaction_access_mode_types > opt_natural_language_mode opt_query_expansion > opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment > ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt > @@ -1231,9 +1249,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > join_table_list join_table > table_factor table_ref esc_table_ref > table_primary_ident table_primary_derived > - select_derived derived_table_list > - select_derived_union > - derived_query_specification > + derived_table_list table_reference_list_parens > + nested_table_reference_list join_table_parens > %type <date_time_type> date_time_type; > %type <interval> interval > > @@ -1276,12 +1293,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, > size_t *yystacksize); > UNDERSCORE_CHARSET > > %type <select_lex> subselect > - get_select_lex get_select_lex_derived > query_specification > - query_term_union_not_ready > - query_term_union_ready > + table_value_constructor > + simple_table > + query_primary > + query_primary_parens > + > +%type <select_lex_unit> > query_expression_body > - select_paren_derived > + query_expression > + query_expression_unit > > %type <boolfunc2creator> comp_op > > @@ -1293,7 +1314,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > > %type <virtual_column> opt_check_constraint check_constraint > virtual_column_func > column_default_expr > -%type <unit_type> unit_type_decl > + > +%type <unit_operation> unit_type_decl > + > +%type <select_lock> > + opt_select_lock_type > + select_lock_type > + opt_lock_wait_timeout_new > + > +%type <select_limit> opt_limit_clause limit_clause limit_options > + > +%type <order_limit_lock> > + query_expression_tail > + order_or_limit > + > +%type <select_order> opt_order_clause order_clause order_list > > %type <NONE> > analyze_stmt_command > @@ -1313,7 +1348,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > assign_to_keycache_parts > preload_list preload_list_or_parts preload_keys preload_keys_parts > select_item_list select_item values_list no_braces > - opt_limit_clause delete_limit_clause fields opt_values values > + delete_limit_clause fields opt_values values > procedure_list procedure_list2 procedure_item > field_def handler opt_generated_always > opt_ignore opt_column opt_restrict > @@ -1333,9 +1368,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t > *yystacksize); > table_to_table_list table_to_table opt_table_list opt_as > handler_rkey_function handler_read_or_scan > single_multi table_wild_list table_wild_one opt_wild > - union_clause union_list > - subselect_start opt_and charset > - subselect_end select_var_list select_var_list_init help > + opt_and charset > + select_var_list select_var_list_init help > opt_extended_describe shutdown > opt_format_json > prepare prepare_src execute deallocate > @@ -1606,14 +1640,22 @@ deallocate_or_drop: > ; > > prepare: > - PREPARE_SYM ident FROM prepare_src > + PREPARE_SYM > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + ident FROM prepare_src > { > LEX *lex= thd->lex; > if (lex->table_or_sp_used()) > my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), > "PREPARE..FROM")); > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > lex->sql_command= SQLCOM_PREPARE; > - lex->prepared_stmt_name= $2; > + lex->prepared_stmt_name= $3; > + Lex->pop_select(); //main select > } > ; > > @@ -1632,10 +1674,21 @@ execute: > LEX *lex= thd->lex; > lex->sql_command= SQLCOM_EXECUTE; > lex->prepared_stmt_name= $2; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > execute_using > - {} > - | EXECUTE_SYM IMMEDIATE_SYM prepare_src > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > + | EXECUTE_SYM IMMEDIATE_SYM > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + prepare_src > { > if (Lex->table_or_sp_used()) > my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), > @@ -1643,7 +1696,11 @@ execute: > Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE; > } > execute_using > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > ; > > execute_using: > @@ -1928,13 +1985,20 @@ connection_name: > /* create a table */ > > create: > - create_or_replace opt_temporary TABLE_SYM opt_if_not_exists > table_ident > + create_or_replace opt_temporary TABLE_SYM opt_if_not_exists > { > LEX *lex= thd->lex; > lex->create_info.init(); > + if (lex->main_select_push()) > + MYSQL_YYABORT; > + lex->current_select->parsing_place= BEFORE_OPT_LIST; > if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 > | $4)) > MYSQL_YYABORT; > - if (!lex->builtin_select.add_table_to_list(thd, $5, NULL, > + } > + table_ident > + { > + LEX *lex= thd->lex; > + if (!lex->builtin_select.add_table_to_list(thd, $6, NULL, > TL_OPTION_UPDATING, > TL_WRITE, > MDL_EXCLUSIVE)) > MYSQL_YYABORT; > @@ -1960,13 +2024,16 @@ create: > ER_WARN_USING_OTHER_HANDLER, > ER_THD(thd, > ER_WARN_USING_OTHER_HANDLER), > > hton_name(lex->create_info.db_type)->str, > - $5->table.str); > + $6->table.str); > } > create_table_set_open_action_and_adjust_tables(lex); > + Lex->pop_select(); //main select > } > | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists > table_ident > { > LEX *lex= thd->lex; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > lex->create_info.init(); > if (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, > $1 | $4)) > MYSQL_YYABORT; > @@ -2021,42 +2088,69 @@ create: > $5->table.str); > } > create_table_set_open_action_and_adjust_tables(lex); > + Lex->pop_select(); //main select > } > - | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident > + | create_or_replace opt_unique INDEX_SYM opt_if_not_exists > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + ident > opt_key_algorithm_clause > ON table_ident > { > - if (Lex->add_create_index_prepare($8)) > + if (Lex->add_create_index_prepare($9)) > MYSQL_YYABORT; > - if (Lex->add_create_index($2, &$5, $6, $1 | $4)) > + if (Lex->add_create_index($2, &$6, $7, $1 | $4)) > MYSQL_YYABORT; > } > '(' key_list ')' opt_lock_wait_timeout normal_key_options > - opt_index_lock_algorithm { } > - | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident > + opt_index_lock_algorithm > + { > + Lex->pop_select(); //main select > + } > + | create_or_replace fulltext INDEX_SYM > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + opt_if_not_exists ident > ON table_ident > { > - if (Lex->add_create_index_prepare($7)) > + if (Lex->add_create_index_prepare($8)) > MYSQL_YYABORT; > - if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4)) > + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5)) > MYSQL_YYABORT; > } > '(' key_list ')' opt_lock_wait_timeout fulltext_key_options > - opt_index_lock_algorithm { } > - | create_or_replace spatial INDEX_SYM opt_if_not_exists ident > + opt_index_lock_algorithm > + { > + Lex->pop_select(); //main select > + } > + | create_or_replace spatial INDEX_SYM > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + opt_if_not_exists ident > ON table_ident > { > - if (Lex->add_create_index_prepare($7)) > + if (Lex->add_create_index_prepare($8)) > MYSQL_YYABORT; > - if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4)) > + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5)) > MYSQL_YYABORT; > } > '(' key_list ')' opt_lock_wait_timeout spatial_key_options > - opt_index_lock_algorithm { } > + opt_index_lock_algorithm > + { > + Lex->pop_select(); //main select > + } > | create_or_replace DATABASE opt_if_not_exists ident > { > Lex->create_info.default_table_charset= NULL; > Lex->create_info.used_fields= 0; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > opt_create_database_options > { > @@ -2064,51 +2158,94 @@ create: > if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $1 | $3)) > MYSQL_YYABORT; > lex->name= $4; > + Lex->pop_select(); //main select > } > | create_or_replace definer_opt opt_view_suid VIEW_SYM > opt_if_not_exists table_ident > { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > if (Lex->add_create_view(thd, $1 | $5, > DTYPE_ALGORITHM_UNDEFINED, $3, $6)) > MYSQL_YYABORT; > } > view_list_opt AS view_select > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace view_algorithm definer_opt opt_view_suid > VIEW_SYM > opt_if_not_exists table_ident > { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7)) > MYSQL_YYABORT; > } > view_list_opt AS view_select > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace definer_opt TRIGGER_SYM > - { Lex->create_info.set($1); } > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + Lex->create_info.set($1); > + } > trigger_tail > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace definer_opt PROCEDURE_SYM > - { Lex->create_info.set($1); } > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + Lex->create_info.set($1); > + } > sp_tail_standalone > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace definer_opt EVENT_SYM > - { Lex->create_info.set($1); } > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + Lex->create_info.set($1); > + } > event_tail > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace definer FUNCTION_SYM > - { Lex->create_info.set($1); } > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + Lex->create_info.set($1); > + } > sf_tail_standalone > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace no_definer FUNCTION_SYM > - { Lex->create_info.set($1); } > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + Lex->create_info.set($1); > + } > create_function_tail > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM > { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > Lex->create_info.set($1); > Lex->udf.type= UDFTYPE_AGGREGATE; > } > udf_tail > - { } > + { > + Lex->pop_select(); //main select > + } > | create_or_replace USER_SYM opt_if_not_exists clear_privileges > grant_list > opt_require_clause opt_resource_options > { > @@ -2815,8 +2952,13 @@ call: > { > if (Lex->call_statement_start(thd, $2)) > MYSQL_YYABORT; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + opt_sp_cparam_list > + { > + Lex->pop_select(); //main select > } > - opt_sp_cparam_list {} > ; > > /* CALL parameters */ > @@ -3346,10 +3488,16 @@ raise_stmt: > ; > > signal_stmt: > - SIGNAL_SYM signal_value opt_set_signal_information > + SIGNAL_SYM > { > - if (Lex->add_signal_statement(thd, $2)) > + if (Lex->main_select_push()) > + YYABORT; > + } > + signal_value opt_set_signal_information > + { > + if (Lex->add_signal_statement(thd, $3)) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > ; > > @@ -3475,9 +3623,14 @@ resignal_stmt: > ; > > get_diagnostics: > - GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information > + GET_SYM which_area DIAGNOSTICS_SYM > + { > + if (Lex->main_select_push()) > + YYABORT; > + } > + diagnostics_information > { > - Diagnostics_information *info= $4; > + Diagnostics_information *info= $5; > > info->set_which_da($2); > > @@ -3486,6 +3639,7 @@ get_diagnostics: > > if (Lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > ; > > @@ -3666,8 +3820,26 @@ sp_decl_idents: > > sp_opt_default: > /* Empty */ { $$ = NULL; } > - | DEFAULT expr { $$ = $2; } > - | SET_VAR expr { $$ = $2; } > + | DEFAULT > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + expr > + { > + Lex->pop_select(); //main select > + $$ = $3; > + } > + | SET_VAR > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + expr > + { > + Lex->pop_select(); //main select > + $$ = $3; > + } > ; > > sp_proc_stmt: > @@ -3784,10 +3956,15 @@ sp_proc_stmt_statement: > > sp_proc_stmt_return: > RETURN_SYM > - { Lex->sphead->reset_lex(thd); } > + { > + Lex->sphead->reset_lex(thd); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > expr > { > LEX *lex= Lex; > + lex->pop_select(); //main select > sp_head *sp= lex->sphead; > if (sp->m_handler->add_instr_freturn(thd, sp, lex->spcont, > $3, lex) || > @@ -3902,6 +4079,8 @@ assignment_source_expr: > { > DBUG_ASSERT(thd->free_list == NULL); > Lex->sphead->reset_lex(thd, $1); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > expr > { > @@ -3910,6 +4089,7 @@ assignment_source_expr: > $$->sp_lex_in_use= true; > $$->set_item_and_free_list($3, thd->free_list); > thd->free_list= NULL; > + Lex->pop_select(); //main select > if ($$->sphead->restore_lex(thd)) > MYSQL_YYABORT; > } > @@ -4030,9 +4210,14 @@ sp_fetch_list: > ; > > sp_if: > - { Lex->sphead->reset_lex(thd); } > + { > + Lex->sphead->reset_lex(thd); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > expr THEN_SYM > { > + Lex->pop_select(); //main select > LEX *lex= Lex; > sp_head *sp= lex->sphead; > sp_pcontext *ctx= lex->spcont; > @@ -4144,12 +4329,18 @@ case_stmt_specification: > ; > > case_stmt_body: > - { Lex->sphead->reset_lex(thd); /* For expr $2 */ } > + { > + Lex->sphead->reset_lex(thd); /* For expr $2 */ > + > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > expr > { > if (Lex->case_stmt_action_expr($2)) > MYSQL_YYABORT; > > + Lex->pop_select(); //main select > if (Lex->sphead->restore_lex(thd)) > MYSQL_YYABORT; > } > @@ -4173,6 +4364,9 @@ simple_when_clause: > WHEN_SYM > { > Lex->sphead->reset_lex(thd); /* For expr $3 */ > + > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > expr > { > @@ -4181,6 +4375,8 @@ simple_when_clause: > LEX *lex= Lex; > if (lex->case_stmt_action_when($3, true)) > MYSQL_YYABORT; > + > + lex->pop_select(); //main select > /* For expr $3 */ > if (lex->sphead->restore_lex(thd)) > MYSQL_YYABORT; > @@ -4197,12 +4393,17 @@ searched_when_clause: > WHEN_SYM > { > Lex->sphead->reset_lex(thd); /* For expr $3 */ > + > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > expr > { > LEX *lex= Lex; > if (lex->case_stmt_action_when($3, false)) > MYSQL_YYABORT; > + > + lex->pop_select(); //main select > /* For expr $3 */ > if (lex->sphead->restore_lex(thd)) > MYSQL_YYABORT; > @@ -4442,6 +4643,7 @@ while_body: > LEX *lex= Lex; > if (lex->sp_while_loop_expression(thd, $1)) > MYSQL_YYABORT; > + Lex->pop_select(); //main select pushed before while_body use > if (lex->sphead->restore_lex(thd)) > MYSQL_YYABORT; > } > @@ -4454,7 +4656,12 @@ while_body: > > repeat_body: > sp_proc_stmts1 UNTIL_SYM > - { Lex->sphead->reset_lex(thd); } > + { > + Lex->sphead->reset_lex(thd); > + > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > expr END REPEAT_SYM > { > LEX *lex= Lex; > @@ -4465,6 +4672,8 @@ repeat_body: > if (i == NULL || > lex->sphead->add_instr(i)) > MYSQL_YYABORT; > + > + lex->pop_select(); //main select > if (lex->sphead->restore_lex(thd)) > MYSQL_YYABORT; > /* We can shortcut the cont_backpatch here */ > @@ -4493,8 +4702,12 @@ sp_labeled_control: > if (Lex->sp_push_loop_label(thd, &$1)) > MYSQL_YYABORT; > Lex->sphead->reset_lex(thd); > + > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > while_body pop_sp_loop_label > + > { } > | labels_declaration_oracle FOR_SYM > { > @@ -4546,9 +4759,13 @@ sp_unlabeled_control: > if (Lex->sp_push_loop_empty_label(thd)) > MYSQL_YYABORT; > Lex->sphead->reset_lex(thd); > + > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > while_body > { > + // while body pop main select > Lex->sp_pop_loop_empty_label(thd); > } > | FOR_SYM > @@ -4981,20 +5198,10 @@ size_number: > */ > > create_body: > - '(' create_field_list ')' > + create_field_list_parens > { Lex->create_info.option_list= NULL; } > opt_create_table_options opt_create_partitioning > opt_create_select {} > | opt_create_table_options opt_create_partitioning > opt_create_select {} > - /* > - the following rule is redundant, but there's a shift/reduce > - conflict that prevents the rule above from parsing a syntax like > - CREATE TABLE t1 (SELECT 1); > - */ > - | '(' create_select_query_specification ')' > - | '(' create_select_query_specification ')' > - { Select->set_braces(1);} union_list {} > - | '(' create_select_query_specification ')' > - { Select->set_braces(1);} union_order_or_limit {} > | create_like > { > > @@ -5010,7 +5217,7 @@ create_body: > > create_like: > LIKE table_ident { $$= $2; } > - | '(' LIKE table_ident ')' { $$= $3; } > + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; } > ; > > opt_create_select: > @@ -5019,23 +5226,42 @@ opt_create_select: > ; > > create_select_query_expression: > - opt_with_clause SELECT_SYM create_select_part2 > opt_table_expression > - create_select_part4 > - { > - Select->set_braces(0); > - Select->set_with_clause($1); > + query_expression > + { > + SELECT_LEX *first_select= $1->first_select(); > + > + if (Lex->sql_command == SQLCOM_INSERT || > + Lex->sql_command == SQLCOM_REPLACE) > + { > + if (Lex->sql_command == SQLCOM_INSERT) > + Lex->sql_command= SQLCOM_INSERT_SELECT; > + else > + Lex->sql_command= SQLCOM_REPLACE_SELECT; > + } > + Lex->insert_select_hack(first_select); > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + > } > - union_clause > - | opt_with_clause SELECT_SYM create_select_part2 > - create_select_part3_union_not_ready create_select_part4 > + | LEFT_PAREN_WITH with_clause query_expression_body ')' > { > - Select->set_with_clause($1); > + SELECT_LEX *first_select= $3->first_select(); > + $3->set_with_clause($2); > + $2->attach_to(first_select); > + > + Lex->insert_select_hack(first_select); > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + > + if (Lex->sql_command == SQLCOM_INSERT || > + Lex->sql_command == SQLCOM_REPLACE) > + { > + if (Lex->sql_command == SQLCOM_INSERT) > + Lex->sql_command= SQLCOM_INSERT_SELECT; > + else > + Lex->sql_command= SQLCOM_REPLACE_SELECT; > + } > } > - | '(' create_select_query_specification ')' > - | '(' create_select_query_specification ')' > - { Select->set_braces(1);} union_list {} > - | '(' create_select_query_specification ')' > - { Select->set_braces(1);} union_order_or_limit {} > ; > > opt_create_partitioning: > @@ -5126,8 +5352,13 @@ partition_entry: > We enter here when opening the frm file to translate > partition info string into part_info data structure. > */ > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + partition > + { > + Lex->pop_select(); //main select > } > - partition {} > ; > > partition: > @@ -5742,56 +5973,6 @@ opt_part_option: > End of partition parser part > */ > > -create_select_query_specification: > - opt_with_clause SELECT_SYM create_select_part2 > create_select_part3 > - create_select_part4 > - { > - Select->set_with_clause($1); > - } > - ; > - > -create_select_part2: > - { > - LEX *lex=Lex; > - if (lex->sql_command == SQLCOM_INSERT) > - lex->sql_command= SQLCOM_INSERT_SELECT; > - else if (lex->sql_command == SQLCOM_REPLACE) > - lex->sql_command= SQLCOM_REPLACE_SELECT; > - /* > - The following work only with the local list, the global list > - is created correctly in this case > - */ > - > lex->current_select->table_list.save_and_clear(&lex->save_list); > - mysql_init_select(lex); > - lex->current_select->parsing_place= SELECT_LIST; > - } > - select_options select_item_list > - { > - Select->parsing_place= NO_MATTER; > - } > - ; > - > -create_select_part3: > - opt_table_expression > - | create_select_part3_union_not_ready > - ; > - > -create_select_part3_union_not_ready: > - table_expression order_or_limit > - | order_or_limit > - ; > - > -create_select_part4: > - opt_select_lock_type > - { > - /* > - The following work only with the local list, the global list > - is created correctly in this case > - */ > - Lex->current_select->table_list.push_front(&Lex->save_list); > - } > - ; > - > opt_as: > /* empty */ {} > | AS {} > @@ -6195,6 +6376,13 @@ create_field_list: > } > ; > > +create_field_list_parens: > + LEFT_PAREN_ALT field_list ')' > + { > + Lex->create_last_non_select_table= Lex->last_table(); > + } > + ; > + > field_list: > field_list_item > | field_list ',' field_list_item > @@ -6462,6 +6650,8 @@ parse_vcol_expr: > Prevent the end user from invoking this command. > */ > MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > expr > { > @@ -6469,13 +6659,29 @@ parse_vcol_expr: > if (!v) > MYSQL_YYABORT; > Lex->last_field->vcol_info= v; > + Lex->pop_select(); //main select > } > ; > > parenthesized_expr: > - subselect > + remember_tok_start > + query_expression > { > - $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1); > + if (!Lex->expr_allows_subselect || > + Lex->sql_command == (int)SQLCOM_PURGE) > + { > + thd->parse_error(ER_SYNTAX_ERROR, $1); > + MYSQL_YYABORT; > + } > + > + // Add the subtree of subquery to the current SELECT_LEX > + SELECT_LEX *curr_sel= Lex->select_stack_head(); > + DBUG_ASSERT(Lex->current_select == curr_sel); > + curr_sel->register_unit($2, &curr_sel->context); > + curr_sel->add_statistics($2); > + > + $$= new (thd->mem_root) > + Item_singlerow_subselect(thd, $2->first_select()); > if ($$ == NULL) > MYSQL_YYABORT; > } > @@ -7474,6 +7680,8 @@ alter: > Lex->alter_info.reset(); > Lex->no_write_to_binlog= 0; > Lex->create_info.storage_media= HA_SM_DEFAULT; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > DBUG_ASSERT(!Lex->m_sql_cmd); > } > alter_options TABLE_SYM table_ident opt_lock_wait_timeout > @@ -7494,12 +7702,15 @@ alter: > Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table(); > if (Lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > } > | ALTER DATABASE ident_or_empty > { > Lex->create_info.default_table_charset= NULL; > Lex->create_info.used_fields= 0; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > create_database_options > { > @@ -7508,6 +7719,7 @@ alter: > lex->name= $3; > if (lex->name.str == NULL && lex->copy_db_to(&lex->name)) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM > { > @@ -7523,6 +7735,8 @@ alter: > > if (lex->sphead) > my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE")); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > lex->sp_chistics.init(); > } > sp_a_chistics > @@ -7531,6 +7745,9 @@ alter: > > lex->sql_command= SQLCOM_ALTER_PROCEDURE; > lex->spname= $3; > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > | ALTER FUNCTION_SYM sp_name > { > @@ -7538,6 +7755,8 @@ alter: > > if (lex->sphead) > my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION")); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > lex->sp_chistics.init(); > } > sp_a_chistics > @@ -7546,14 +7765,23 @@ alter: > > lex->sql_command= SQLCOM_ALTER_FUNCTION; > lex->spname= $3; > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM > table_ident > { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > if (Lex->add_alter_view(thd, $2, $4, $6)) > MYSQL_YYABORT; > } > view_list_opt AS view_select > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > | ALTER definer_opt opt_view_suid VIEW_SYM table_ident > /* > We have two separate rules for ALTER VIEW rather that > @@ -7561,14 +7789,22 @@ alter: > with the ALTER EVENT below. > */ > { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5)) > MYSQL_YYABORT; > } > view_list_opt AS view_select > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > | ALTER definer_opt remember_name EVENT_SYM sp_name > { > - /* > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + /* > It is safe to use Lex->spname because > ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO > is not allowed. Lex->spname is used in the case of RENAME TO > @@ -7600,6 +7836,8 @@ alter: > */ > Lex->sql_command= SQLCOM_ALTER_EVENT; > Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr(); > + > + Lex->pop_select(); //main select > } > | ALTER TABLESPACE alter_tablespace_info > { > @@ -7643,6 +7881,8 @@ alter: > lex->create_info.init(); > lex->no_write_to_binlog= 0; > DBUG_ASSERT(!lex->m_sql_cmd); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > table_ident > { > @@ -7660,6 +7900,9 @@ alter: > Lex->m_sql_cmd= new (thd->mem_root) > Sql_cmd_alter_sequence($3); > if (Lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > ; > > @@ -8336,9 +8579,13 @@ checksum: > lex->sql_command = SQLCOM_CHECKSUM; > /* Will be overridden during execution. */ > YYPS->m_lock_type= TL_UNLOCK; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > table_list opt_checksum_type > - {} > + { > + Lex->pop_select(); //main select > + } > ; > > opt_checksum_type: > @@ -8364,6 +8611,8 @@ repair: > lex->alter_info.reset(); > /* Will be overridden during execution. */ > YYPS->m_lock_type= TL_UNLOCK; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > repair_table_or_view > { > @@ -8372,6 +8621,7 @@ repair: > lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table(); > if (lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > ; > > @@ -8400,6 +8650,8 @@ analyze: > ANALYZE_SYM opt_no_write_to_binlog table_or_tables > { > LEX *lex=Lex; > + if (lex->main_select_push()) > + YYABORT; > lex->sql_command = SQLCOM_ANALYZE; > lex->no_write_to_binlog= $2; > lex->check_opt.init(); > @@ -8414,6 +8666,7 @@ analyze: > lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table(); > if (lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > ; > > @@ -8530,6 +8783,8 @@ check: CHECK_SYM > lex->alter_info.reset(); > /* Will be overridden during execution. */ > YYPS->m_lock_type= TL_UNLOCK; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > check_view_or_table > { > @@ -8540,6 +8795,7 @@ check: CHECK_SYM > lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table(); > if (lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > ; > > @@ -8577,6 +8833,8 @@ optimize: > lex->alter_info.reset(); > /* Will be overridden during execution. */ > YYPS->m_lock_type= TL_UNLOCK; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > table_list opt_lock_wait_timeout > { > @@ -8585,6 +8843,7 @@ optimize: > lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table(); > if (lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > ; > > @@ -8598,9 +8857,13 @@ rename: > RENAME table_or_tables > { > Lex->sql_command= SQLCOM_RENAME_TABLE; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > table_to_table_list > - {} > + { > + Lex->pop_select(); //main select > + } > | RENAME USER_SYM clear_privileges rename_list > { > Lex->sql_command = SQLCOM_RENAME_USER; > @@ -8694,10 +8957,14 @@ preload: > LEX *lex=Lex; > lex->sql_command=SQLCOM_PRELOAD_KEYS; > lex->alter_info.reset(); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > preload_list_or_parts > - {} > - ; > + { > + Lex->pop_select(); //main select > + } > + ; > > preload_list_or_parts: > preload_keys_parts > @@ -8763,192 +9030,353 @@ opt_ignore_leaves: > > > select: > - opt_with_clause select_init > + query_expression > { > - LEX *lex= Lex; > - lex->sql_command= SQLCOM_SELECT; > - lex->current_select->set_with_clause($1); > + Lex->selects_allow_into= TRUE; > + Lex->selects_allow_procedure= TRUE; > + Lex->set_main_unit($1); > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + > + SELECT_LEX *fake= Lex->unit.fake_select_lex; > + if (fake) > + { > + fake->no_table_names_allowed= 1; > + Lex->push_select(fake); > + } > + else > + Lex->push_select(Lex->first_select_lex()); > + Lex->sql_command= SQLCOM_SELECT; > } > ; > > -select_init: > - SELECT_SYM select_options_and_item_list select_init3 > - | '(' select_paren ')' > - | '(' select_paren ')' union_list > - | '(' select_paren ')' union_order_or_limit > - ; > > -union_list_part2: > - SELECT_SYM select_options_and_item_list > select_init3_union_query_term > - | '(' select_paren_union_query_term ')' > - | '(' select_paren_union_query_term ')' union_list > - | '(' select_paren_union_query_term ')' union_order_or_limit > +simple_table: > + query_specification { $$= $1; } > + | table_value_constructor { $$= $1; } > ; > - > -select_paren: > + > +table_value_constructor: > + VALUES > + { > + LEX *lex= Lex; > + SELECT_LEX *sel; > + //lex->field_list.empty(); > + lex->many_values.empty(); > + lex->insert_list=0; > + if (!(sel= lex->alloc_select(TRUE)) || > + lex->push_select(sel)) > + MYSQL_YYABORT; > + sel->init_select(); > + sel->braces= FALSE; // just initialisation > + } > + values_list > + { > + LEX *lex=Lex; > + $$= lex->pop_select(); // above TVC select > + if (!($$->tvc= > + new (lex->thd->mem_root) > table_value_constr(lex->many_values, > + $$, > + > $$->options))) > + MYSQL_YYABORT; > + lex->many_values.empty(); > + } > + ; > + > +query_specification: > + SELECT_SYM > { > - /* > - In order to correctly parse UNION's global ORDER BY we > need to > - set braces before parsing the clause. > - */ > - Lex->current_select->set_braces(true); > + SELECT_LEX *sel; > + LEX *lex= Lex; > + if (!(sel= lex->alloc_select(TRUE)) || > + lex->push_select(sel)) > + MYSQL_YYABORT; > + sel->init_select(); > + sel->braces= FALSE; > } > - SELECT_SYM select_options_and_item_list select_part3 > - opt_select_lock_type > + select_options > { > - DBUG_ASSERT(Lex->current_select->braces); > + Select->parsing_place= SELECT_LIST; > } > - | '(' select_paren ')' > - ; > - > -select_paren_union_query_term: > + select_item_list > { > - /* > - In order to correctly parse UNION's global ORDER BY we > need to > - set braces before parsing the clause. > - */ > - Lex->current_select->set_braces(true); > + Select->parsing_place= NO_MATTER; > } > - SELECT_SYM select_options_and_item_list > select_part3_union_query_term > - opt_select_lock_type > + opt_into > + opt_from_clause > + opt_where_clause > + opt_group_clause > + opt_having_clause > + opt_window_clause > { > - DBUG_ASSERT(Lex->current_select->braces); > + $$= Lex->pop_select(); > } > - | '(' select_paren_union_query_term ')' > ; > > -select_paren_view: > - { > - /* > - In order to correctly parse UNION's global ORDER BY we > need to > - set braces before parsing the clause. > - */ > - Lex->current_select->set_braces(true); > - } > - SELECT_SYM select_options_and_item_list select_part3_view > - opt_select_lock_type > - { > - DBUG_ASSERT(Lex->current_select->braces); > - } > - | '(' select_paren_view ')' > +opt_from_clause: > + /* Empty */ > + | from_clause > + ; > + > +query_primary: > + simple_table > + { $$= $1; } > + | query_primary_parens > + { $$= $1; } > ; > > -/* The equivalent of select_paren for nested queries. */ > -select_paren_derived: > +query_primary_parens: > + '(' query_expression_unit > { > - Lex->current_select->set_braces(true); > + SELECT_LEX *last= $2->pre_last_parse->next_select(); > + int cmp= > cmp_unit_op($2->first_select()->next_select()->linkage, > + last->linkage); > + if (cmp < 0) > + { > + if (!check_intersect_prefix($2->first_select())) > + { > + if (Lex->pop_new_select_and_wrap() == NULL) > + MYSQL_YYABORT; > + } > + } > + Lex->push_select($2->fake_select_lex); > } > - SELECT_SYM select_part2_derived > - opt_table_expression > - opt_order_clause > - opt_limit_clause > - opt_select_lock_type > + query_expression_tail ')' > { > - DBUG_ASSERT(Lex->current_select->braces); > - $$= Lex->current_select->master_unit()->first_select(); > + Lex->pop_select(); > + if ($4) > + { > + ($4)->set_to($2->fake_select_lex); > + } > + $$= $2->first_select(); > } > - | '(' select_paren_derived ')' { $$= $2; } > - ; > - > -select_init3: > - opt_table_expression > - opt_select_lock_type > + | '(' query_primary > { > - /* Parentheses carry no meaning here */ > - Lex->current_select->set_braces(false); > + Lex->push_select($2); > } > - union_clause > - | select_part3_union_not_ready > - opt_select_lock_type > + query_expression_tail ')' > { > - /* Parentheses carry no meaning here */ > - Lex->current_select->set_braces(false); > + Lex->pop_select(); > + $$= $2; > + $$->braces= TRUE; > + if ($4) > + { > + if ($2->next_select()) > + { > + SELECT_LEX_UNIT *unit= $2->master_unit(); > + if (!unit) > + unit= Lex->create_unit($2); > + if (!unit) > + YYABORT; > + if (!unit->fake_select_lex->is_set_query_expr_tail) > + $4->set_to(unit->fake_select_lex); > + else > + { > + $$= Lex->wrap_unit_into_derived(unit); > + if (!$$) > + YYABORT; > + $4->set_to($$); > + } > + } > + else if (!$2->is_set_query_expr_tail) > + { > + $4->set_to($2); > + } > + else > + { > + SELECT_LEX_UNIT *unit= Lex->create_unit($2); > + if (!unit) > + YYABORT; > + $$= Lex->wrap_unit_into_derived(unit); > + if (!$$) > + YYABORT; > + $4->set_to($$); > + } > + } > } > ; > > - > -select_init3_union_query_term: > - opt_table_expression > - opt_select_lock_type > +query_expression_unit: > + query_primary > + unit_type_decl > + query_primary > { > - /* Parentheses carry no meaning here */ > - Lex->current_select->set_braces(false); > + SELECT_LEX *sel1; > + SELECT_LEX *sel2; > + if (!$1->next_select()) > + sel1= $1; > + else > + { > + sel1= Lex->wrap_unit_into_derived($1->master_unit()); > + if (!sel1) > + YYABORT; > + } > + if (!$3->next_select()) > + sel2= $3; > + else > + { > + sel2= Lex->wrap_unit_into_derived($3->master_unit()); > + if (!sel2) > + YYABORT; > + } > + sel1->link_neighbour(sel2); > + sel2->set_linkage_and_distinct($2.unit_type, $2.distinct); > + $$= Lex->create_unit(sel1); > + $$->pre_last_parse= sel1; > + if ($$ == NULL) > + YYABORT; > } > - union_clause > - | select_part3_union_not_ready_noproc > - opt_select_lock_type > + | query_expression_unit > + unit_type_decl > + query_primary > { > - /* Parentheses carry no meaning here */ > - Lex->current_select->set_braces(false); > + SELECT_LEX *sel1; > + if (!$3->next_select()) > + sel1= $3; > + else > + { > + sel1= Lex->wrap_unit_into_derived($3->master_unit()); > + if (!sel1) > + YYABORT; > + } > + SELECT_LEX *last= $1->pre_last_parse->next_select(); > + > + int cmp= cmp_unit_op($2.unit_type, last->linkage); > + if (cmp == 0) > + { > + // do nothing, this part will be just connected > + } > + else if (cmp > 0) > + { > + // Store beginning and continue to connect parts > + if (Lex->push_new_select($1->pre_last_parse)) > + MYSQL_YYABORT; > + } > + else /* cmp < 0 */ > + { > + // wrap stored part in a select, then continue to connect > parts > + if (!check_intersect_prefix($1->first_select())) > + { > + if ((last= Lex->pop_new_select_and_wrap()) == NULL) > + MYSQL_YYABORT; > + last->set_master_unit($1); > + } > + } > + last->link_neighbour(sel1); > + sel1->set_master_unit($1); > + sel1->set_linkage_and_distinct($2.unit_type, $2.distinct); > + $$= $1; > + $$->pre_last_parse= last; > } > ; > > - > -select_init3_view: > - opt_table_expression opt_select_lock_type > +query_expression_body: > + query_primary > { > - Lex->current_select->set_braces(false); > + Lex->push_select($1); > } > - | opt_table_expression opt_select_lock_type > + query_expression_tail > { > - Lex->current_select->set_braces(false); > + Lex->pop_select(); > + SELECT_LEX *sel= $1; > + if ($3) > + { > + if ($1->next_select()) > + { > + SELECT_LEX_UNIT *unit= $1->master_unit(); > + if (!unit) > + unit= Lex->create_unit($1); > + if (!unit) > + YYABORT; > + if (!unit->fake_select_lex->is_set_query_expr_tail) > + $3->set_to(unit->fake_select_lex); > + else > + { > + SELECT_LEX *sel= Lex->wrap_unit_into_derived(unit); > + if (!sel) > + YYABORT; > + $3->set_to(sel); > + } > + } > + else if (!$1->is_set_query_expr_tail) > + $3->set_to($1); > + else > + { > + SELECT_LEX_UNIT *unit= $1->master_unit(); > + if (!unit) > + unit= Lex->create_unit($1); > + if (!unit) > + YYABORT; > + sel= Lex->wrap_unit_into_derived(unit); > + if (!sel) > + YYABORT; > + $3->set_to(sel); > + } > + } > + $$= Lex->create_unit(sel); > + if ($$ == NULL) > + YYABORT; > } > - union_list_view > - | order_or_limit opt_select_lock_type > + | query_expression_unit > { > - Lex->current_select->set_braces(false); > + SELECT_LEX *last= $1->pre_last_parse->next_select(); > + int cmp= > cmp_unit_op($1->first_select()->next_select()->linkage, > + last->linkage); > + if (cmp < 0) > + { > + if (!check_intersect_prefix($1->first_select())) > + { > + if (Lex->pop_new_select_and_wrap() == NULL) > + MYSQL_YYABORT; > + } > + } > + Lex->push_select($1->fake_select_lex); > } > - | table_expression order_or_limit opt_select_lock_type > + query_expression_tail > { > - Lex->current_select->set_braces(false); > + Lex->pop_select(); > + if ($3) > + { > + ($3)->set_to($1->fake_select_lex); > + } > + $$= $1; > } > ; > > -/* > - The SELECT parts after select_item_list that cannot be followed by > UNION. > -*/ > - > -select_part3: > - opt_table_expression > - | select_part3_union_not_ready > - ; > - > -select_part3_union_query_term: > - opt_table_expression > - | select_part3_union_not_ready_noproc > - ; > - > -select_part3_view: > - opt_table_expression > - | order_or_limit > - | table_expression order_or_limit > +query_expression: > + opt_with_clause > + query_expression_body > + { > + if ($1) > + { > + $2->set_with_clause($1); > + $1->attach_to($2->first_select()); > + } > + $$= $2; > + } > ; > > -select_part3_union_not_ready: > - select_part3_union_not_ready_noproc > - | table_expression procedure_clause > - | table_expression order_or_limit procedure_clause > - ; > +subselect: > + remember_tok_start > + query_expression > + { > + if (!Lex->expr_allows_subselect || > + Lex->sql_command == (int)SQLCOM_PURGE) > + { > + thd->parse_error(ER_SYNTAX_ERROR, $1); > + MYSQL_YYABORT; > + } > > -select_part3_union_not_ready_noproc: > - order_or_limit > - | into opt_table_expression opt_order_clause opt_limit_clause > - | table_expression into > - | table_expression order_or_limit > - | table_expression order_or_limit into > - ; > + // Add the subtree of subquery to the current SELECT_LEX > + SELECT_LEX *curr_sel= Lex->select_stack_head(); > + DBUG_ASSERT(Lex->current_select == curr_sel); > + if (curr_sel) > + { > + curr_sel->register_unit($2, &curr_sel->context); > + curr_sel->add_statistics($2); > + } > > -select_options_and_item_list: > - { > - LEX *lex= Lex; > - SELECT_LEX *sel= lex->current_select; > - if (sel->linkage != UNION_TYPE) > - mysql_init_select(lex); > - lex->current_select->parsing_place= SELECT_LIST; > - } > - select_options select_item_list > - { > - Select->parsing_place= NO_MATTER; > + $$= $2->first_select(); > } > ; > > @@ -8956,18 +9384,6 @@ select_options_and_item_list: > /** > <table expression>, as in the SQL standard. > */ > -table_expression: > - from_clause > - opt_where_clause > - opt_group_clause > - opt_having_clause > - opt_window_clause > - ; > - > -opt_table_expression: > - /* Empty */ > - | table_expression > - ; > > from_clause: > FROM table_reference_list > @@ -9005,59 +9421,63 @@ select_option: > query_expression_option > | SQL_NO_CACHE_SYM > { > - /* > - Allow this flag only on the first top-level SELECT > statement, if > - SQL_CACHE wasn't specified, and only once per query. > - */ > - if (Lex->current_select != &Lex->builtin_select) > - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), > "SQL_NO_CACHE")); > - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE) > - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", > "SQL_NO_CACHE")); > - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE) > + /* > + Allow this flag once per query. > + */ > + if (Select->options & OPTION_NO_QUERY_CACHE) > my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE")); > - > - Lex->safe_to_cache_query=0; > - Lex->builtin_select.options&= ~OPTION_TO_QUERY_CACHE; > - Lex->builtin_select.sql_cache= SELECT_LEX::SQL_NO_CACHE; > + Select->options|= OPTION_NO_QUERY_CACHE; > } > | SQL_CACHE_SYM > { > - /* > - Allow this flag only on the first top-level SELECT > statement, if > - SQL_NO_CACHE wasn't specified, and only once per query. > - */ > - if (Lex->current_select != &Lex->builtin_select) > - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), > "SQL_CACHE")); > - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE) > - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", > "SQL_CACHE")); > - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE) > + /* > + Allow this flag once per query. > + */ > + if (Select->options & OPTION_TO_QUERY_CACHE) > my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE")); > - > - Lex->safe_to_cache_query=1; > - Lex->builtin_select.options|= OPTION_TO_QUERY_CACHE; > - Lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE; > + Select->options|= OPTION_TO_QUERY_CACHE; > } > ; > > opt_select_lock_type: > /* empty */ > - | FOR_SYM UPDATE_SYM opt_lock_wait_timeout > + { $$.empty(); } > + | select_lock_type > + { $$= $1; } > + ; > + > +select_lock_type: > + FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new > { > - LEX *lex=Lex; > - lex->current_select->lock_type= TL_WRITE; > - lex->current_select->set_lock_for_tables(TL_WRITE); > - lex->safe_to_cache_query=0; > + $$= $3; > + $$.defined_lock= TRUE; > + $$.update_lock= TRUE; > } > - | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout > + | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new > { > - LEX *lex=Lex; > - lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS; > - lex->current_select-> > - set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); > - lex->safe_to_cache_query=0; > + $$= $5; > + $$.defined_lock= TRUE; > + $$.update_lock= FALSE; > } > ; > > +opt_lock_wait_timeout_new: > + /* empty */ > + { > + $$.empty(); > + } > + | WAIT_SYM ulong_num > + { > + $$.defined_timeout= TRUE; > + $$.timeout= $2; > + } > + | NOWAIT_SYM > + { > + $$.defined_timeout= TRUE; > + $$.timeout= 0; > + } > + ; > + > select_item_list: > select_item_list ',' select_item > | select_item > @@ -11361,10 +11781,15 @@ esc_table_ref: > /* Equivalent to <table reference list> in the SQL:2003 standard. */ > /* Warning - may return NULL in case of incomplete SELECT */ > derived_table_list: > - esc_table_ref { $$=$1; } > + esc_table_ref > + { > + $$=$1; > + Select->add_joined_table($1); > + } > | derived_table_list ',' esc_table_ref > { > MYSQL_YYABORT_UNLESS($1 && ($$=$3)); > + Select->add_joined_table($3); > } > ; > > @@ -11383,11 +11808,18 @@ join_table: > left-associative joins. > */ > table_ref normal_join table_ref %prec TABLE_REF_PRIORITY > - { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; } > + { > + MYSQL_YYABORT_UNLESS($1 && ($$=$3)); > + Select->add_joined_table($1); > + Select->add_joined_table($3); > + $3->straight=$2; > + } > | table_ref normal_join table_ref > ON > { > MYSQL_YYABORT_UNLESS($1 && $3); > + Select->add_joined_table($1); > + Select->add_joined_table($3); > /* Change the current name resolution context to a local > context. */ > if (push_new_name_resolution_context(thd, $1, $3)) > MYSQL_YYABORT; > @@ -11404,6 +11836,8 @@ join_table: > USING > { > MYSQL_YYABORT_UNLESS($1 && $3); > + Select->add_joined_table($1); > + Select->add_joined_table($3); > } > '(' using_list ')' > { > @@ -11414,6 +11848,8 @@ join_table: > | table_ref NATURAL inner_join table_factor > { > MYSQL_YYABORT_UNLESS($1 && ($$=$4)); > + Select->add_joined_table($1); > + Select->add_joined_table($4); > $4->straight=$3; > add_join_natural($1,$4,NULL,Select); > } > @@ -11423,6 +11859,8 @@ join_table: > ON > { > MYSQL_YYABORT_UNLESS($1 && $5); > + Select->add_joined_table($1); > + Select->add_joined_table($5); > /* Change the current name resolution context to a local > context. */ > if (push_new_name_resolution_context(thd, $1, $5)) > MYSQL_YYABORT; > @@ -11439,6 +11877,8 @@ join_table: > | table_ref LEFT opt_outer JOIN_SYM table_factor > { > MYSQL_YYABORT_UNLESS($1 && $5); > + Select->add_joined_table($1); > + Select->add_joined_table($5); > } > USING '(' using_list ')' > { > @@ -11449,6 +11889,8 @@ join_table: > | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor > { > MYSQL_YYABORT_UNLESS($1 && $6); > + Select->add_joined_table($1); > + Select->add_joined_table($6); > add_join_natural($1,$6,NULL,Select); > $6->outer_join|=JOIN_TYPE_LEFT; > $$=$6; > @@ -11459,6 +11901,8 @@ join_table: > ON > { > MYSQL_YYABORT_UNLESS($1 && $5); > + Select->add_joined_table($1); > + Select->add_joined_table($5); > /* Change the current name resolution context to a local > context. */ > if (push_new_name_resolution_context(thd, $1, $5)) > MYSQL_YYABORT; > @@ -11476,6 +11920,8 @@ join_table: > | table_ref RIGHT opt_outer JOIN_SYM table_factor > { > MYSQL_YYABORT_UNLESS($1 && $5); > + Select->add_joined_table($1); > + Select->add_joined_table($5); > } > USING '(' using_list ')' > { > @@ -11487,6 +11933,8 @@ join_table: > | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor > { > MYSQL_YYABORT_UNLESS($1 && $6); > + Select->add_joined_table($1); > + Select->add_joined_table($6); > add_join_natural($6,$1,NULL,Select); > LEX *lex= Lex; > if (!($$= lex->current_select->convert_right_join())) > @@ -11521,40 +11969,70 @@ use_partition: > $$= $3; > } > ; > - > -/* > - This is a flattening of the rules <table factor> and <table primary> > - in the SQL:2003 standard, since we don't have <sample clause> > > - I.e. > - <table factor> ::= <table primary> [ <sample clause> ] > -*/ > -/* Warning - may return NULL in case of incomplete SELECT */ > table_factor: > - table_primary_ident > - | table_primary_derived > + table_primary_ident { $$= $1; } > + | table_primary_derived { $$= $1; } > + | join_table_parens { $$= $1; } > + | table_reference_list_parens { $$= $1; } > ; > > +table_reference_list_parens: > + '(' table_reference_list_parens ')' { $$= $2; } > + | '(' nested_table_reference_list ')' > + { > + if (!($$= Select->end_nested_join(thd))) > + MYSQL_YYABORT; > + } > + ; > + > +nested_table_reference_list: > + table_ref ',' table_ref > + { > + if (Select->init_nested_join(thd)) > + MYSQL_YYABORT; > + Select->add_joined_table($1); > + Select->add_joined_table($3); > + $$= $1->embedding; > + } > + | nested_table_reference_list ',' table_ref > + { > + Select->add_joined_table($3); > + $$= $1; > + } > + ; > + > +join_table_parens: > + '(' join_table_parens ')' { $$= $2; } > + | '(' join_table ')' > + { > + LEX *lex= Lex; > + if (!($$= lex->current_select->nest_last_join(thd))) > + { > + thd->parse_error(); > + MYSQL_YYABORT; > + } > + } > + ; > + > + > table_primary_ident: > + table_ident opt_use_partition > + opt_table_alias_clause opt_key_definition > { > SELECT_LEX *sel= Select; > sel->table_join_options= 0; > - } > - table_ident opt_use_partition opt_table_alias opt_key_definition > - { > - if (!($$= Select->add_table_to_list(thd, $2, $4, > + if (!($$= Select->add_table_to_list(thd, $1, $3, > > Select->get_table_join_options(), > YYPS->m_lock_type, > YYPS->m_mdl_type, > Select->pop_index_hints(), > - $3))) > + $2))) > MYSQL_YYABORT; > - Select->add_joined_table($$); > } > ; > > > - > /* > Represents a flattening of the following rules from the SQL:2003 > standard. This sub-rule corresponds to the sub-rule > @@ -11572,242 +12050,56 @@ table_primary_ident: > */ > > table_primary_derived: > - '(' get_select_lex select_derived_union ')' opt_table_alias > + query_primary_parens table_alias_clause > { > - /* Use $2 instead of Lex->current_select as derived table will > - alter value of Lex->current_select. */ > - if (!($3 || $5) && $2->embedding && > - !$2->embedding->nested_join->join_list.elements) > + LEX *lex=Lex; > + lex->derived_tables|= DERIVED_SUBQUERY; > + $1->linkage= DERIVED_TABLE_TYPE; > + $1->braces= FALSE; > + // Add the subtree of subquery to the current SELECT_LEX > + SELECT_LEX *curr_sel= Lex->select_stack_head(); > + DBUG_ASSERT(Lex->current_select == curr_sel); > + SELECT_LEX_UNIT *unit= $1->master_unit(); > + if (!unit) > { > - /* we have a derived table ($3 == NULL) but no alias, > - Since we are nested in further parentheses so we > - can pass NULL to the outer level parentheses > - Permits parsing of "((((select ...))) as xyz)" */ > - $$= 0; > + unit= Lex->create_unit($1); > + if (!unit) > + YYABORT; > } > - else if (!$3) > - { > - /* Handle case of derived table, alias may be NULL if there > - are no outer parentheses, add_table_to_list() will throw > - error in this case */ > - LEX *lex=Lex; > - lex->check_automatic_up(UNSPECIFIED_TYPE); > - SELECT_LEX *sel= lex->current_select; > - SELECT_LEX_UNIT *unit= sel->master_unit(); > - lex->current_select= sel= unit->outer_select(); > - Table_ident *ti= new (thd->mem_root) Table_ident(unit); > - if (ti == NULL) > - MYSQL_YYABORT; > - if (!($$= sel->add_table_to_list(thd, > - ti, $5, 0, > - TL_READ, MDL_SHARED_READ))) > + curr_sel->register_unit(unit, &curr_sel->context); > + curr_sel->add_statistics(unit); > > - MYSQL_YYABORT; > - sel->add_joined_table($$); > - //lex->pop_context("derived"); > - lex->nest_level--; > - } > - else if ($5 != NULL) > - { > - /* > - Tables with or without joins within parentheses cannot > - have aliases, and we ruled out derived tables above. > - */ > - thd->parse_error(); > - MYSQL_YYABORT; > - } > - else > - { > - /* nested join: FROM (t1 JOIN t2 ...), > - nest_level is the same as in the outer query */ > - $$= $3; > - } > - /* > - Fields in derived table can be used in upper select in > - case of merge. We do not add HAVING fields because we do > - not merge such derived. We do not add union because > - also do not merge them > - */ > - if ($$ && $$->derived && > - !$$->derived->first_select()->next_select()) > - > $$->select_lex->add_where_field($$->derived->first_select()); > - } > - /* Represents derived table with WITH clause */ > - | '(' get_select_lex subselect_start > - with_clause query_expression_body > - subselect_end ')' opt_table_alias > - { > - LEX *lex=Lex; > - SELECT_LEX *sel= $2; > - SELECT_LEX_UNIT *unit= $5->master_unit(); > Table_ident *ti= new (thd->mem_root) Table_ident(unit); > if (ti == NULL) > MYSQL_YYABORT; > - $5->set_with_clause($4); > - lex->current_select= sel; > - if (!($$= sel->add_table_to_list(lex->thd, > - ti, $8, 0, > - TL_READ, MDL_SHARED_READ))) > + if (!($$= curr_sel->add_table_to_list(lex->thd, > + ti, $2, 0, > + TL_READ, > MDL_SHARED_READ))) > MYSQL_YYABORT; > - sel->add_joined_table($$); > - } > - ; > - > -/* > - This rule accepts just about anything. The reason is that we have > - empty-producing rules in the beginning of rules, in this case > - subselect_start. This forces bison to take a decision which rules to > - reduce by long before it has seen any tokens. This approach ties us > - to a very limited class of parseable languages, and unfortunately > - SQL is not one of them. The chosen 'solution' was this rule, which > - produces just about anything, even complete bogus statements, for > - instance ( table UNION SELECT 1 ). > - Fortunately, we know that the semantic value returned by > - select_derived is NULL if it contained a derived table, and a pointer to > - the base table's TABLE_LIST if it was a base table. So in the rule > - regarding union's, we throw a parse error manually and pretend it > - was bison that did it. > - > - Also worth noting is that this rule concerns query expressions in > - the from clause only. Top level select statements and other types of > - subqueries have their own union rules. > -*/ > -select_derived_union: > - select_derived > - | select_derived union_order_or_limit > - { > - if ($1) > - { > - thd->parse_error(); > - MYSQL_YYABORT; > - } > - } > - | select_derived union_head_non_top > - { > - if ($1) > - { > - thd->parse_error(); > - MYSQL_YYABORT; > - } > } > - union_list_derived_part2 > - | derived_query_specification opt_select_lock_type > - | derived_query_specification order_or_limit opt_select_lock_type > - | derived_query_specification opt_select_lock_type > union_list_derived > - ; > - > -union_list_derived_part2: > - query_term_union_not_ready { Lex->pop_context(); } > - | query_term_union_ready { Lex->pop_context(); } > - | query_term_union_ready { Lex->pop_context(); } > union_list_derived > - ; > - > -union_list_derived: > - union_head_non_top union_list_derived_part2 > - ; > - > - > -/* The equivalent of select_init2 for nested queries. */ > -select_init2_derived: > - select_part2_derived > - { > - Select->set_braces(0); > - } > - ; > - > -/* The equivalent of select_part2 for nested queries. */ > -select_part2_derived: > - { > - LEX *lex= Lex; > - SELECT_LEX *sel= lex->current_select; > - if (sel->linkage != UNION_TYPE) > - mysql_init_select(lex); > - lex->current_select->parsing_place= SELECT_LIST; > - } > - opt_query_expression_options select_item_list > - { > - Select->parsing_place= NO_MATTER; > - } > - ; > - > -/* handle contents of parentheses in join expression */ > -select_derived: > - get_select_lex_derived derived_table_list > + | '(' > + query_expression > + ')' table_alias_clause > { > - LEX *lex= Lex; > - /* for normal joins, $2 != NULL and end_nested_join() != NULL, > - for derived tables, both must equal NULL */ > + LEX *lex=Lex; > + lex->derived_tables|= DERIVED_SUBQUERY; > + $2->first_select()->linkage= DERIVED_TABLE_TYPE; > > - if (!($$= $1->end_nested_join(lex->thd)) && $2) > - MYSQL_YYABORT; > - if (!$2 && $$) > - { > - thd->parse_error(); > - MYSQL_YYABORT; > - } > - } > - ; > > -/* > - Similar to query_specification, but for derived tables. > - Example: the inner parenthesized SELECT in this query: > - SELECT * FROM (SELECT * FROM t1); > -*/ > -derived_query_specification: > - SELECT_SYM select_derived_init select_derived2 > - { > - if ($2) > - Select->set_braces(1); > - $$= NULL; > - } > - ; > + // Add the subtree of subquery to the current SELECT_LEX > + SELECT_LEX *curr_sel= Lex->select_stack_head(); > + DBUG_ASSERT(Lex->current_select == curr_sel); > + curr_sel->register_unit($2, &curr_sel->context); > + curr_sel->add_statistics($2); > > -select_derived2: > - { > - LEX *lex= Lex; > - lex->derived_tables|= DERIVED_SUBQUERY; > - if (!lex->expr_allows_subselect || > - lex->sql_command == (int)SQLCOM_PURGE) > - { > - thd->parse_error(); > - MYSQL_YYABORT; > - } > - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || > - mysql_new_select(lex, 1, NULL)) > + Table_ident *ti= new (thd->mem_root) Table_ident($2); > + if (ti == NULL) > MYSQL_YYABORT; > - mysql_init_select(lex); > - lex->current_select->set_linkage(DERIVED_TABLE_TYPE); > - lex->current_select->parsing_place= SELECT_LIST; > - } > - select_options select_item_list > - { > - Select->parsing_place= NO_MATTER; > - } > - opt_table_expression > - ; > - > -get_select_lex: > - /* Empty */ { $$= Select; } > - ; > - > -get_select_lex_derived: > - get_select_lex > - { > - LEX *lex= Lex; > - if ($1->init_nested_join(lex->thd)) > + if (!($$= curr_sel->add_table_to_list(lex->thd, > + ti, $4, 0, > + TL_READ, > MDL_SHARED_READ))) > MYSQL_YYABORT; > } > - ; > - > -select_derived_init: > - { > - LEX *lex= Lex; > - > - TABLE_LIST *embedding= lex->current_select->embedding; > - $$= embedding && > - !embedding->nested_join->join_list.elements; > - /* return true if we are deeply nested */ > - } > ; > > opt_outer: > @@ -11939,9 +12231,14 @@ table_alias: > | '=' > ; > > -opt_table_alias: > +opt_table_alias_clause: > /* empty */ { $$=0; } > - | table_alias ident > + > + | table_alias_clause { $$= $1; } > + ; > + > +table_alias_clause: > + table_alias ident > { > $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING)); > if ($$ == NULL) > @@ -12108,7 +12405,7 @@ opt_window_partition_clause: > > opt_window_order_clause: > /* empty */ { } > - | ORDER_SYM BY order_list > + | ORDER_SYM BY order_list { Select->order_list= *($3); } > ; > > opt_window_frame_clause: > @@ -12232,64 +12529,35 @@ alter_order_item: > > opt_order_clause: > /* empty */ > + { $$= NULL; } > | order_clause > + { $$= $1; } > ; > > order_clause: > ORDER_SYM BY > { > - LEX *lex=Lex; > - SELECT_LEX *sel= lex->current_select; > - SELECT_LEX_UNIT *unit= sel-> master_unit(); > - if (sel->linkage != GLOBAL_OPTIONS_TYPE && > - sel->olap != UNSPECIFIED_OLAP_TYPE && > - (sel->linkage != UNION_TYPE || sel->braces)) > - { > - my_error(ER_WRONG_USAGE, MYF(0), > - "CUBE/ROLLUP", "ORDER BY"); > - MYSQL_YYABORT; > - } > - if (lex->sql_command != SQLCOM_ALTER_TABLE && > - !unit->fake_select_lex) > - { > - /* > - A query of the of the form (SELECT ...) ORDER BY > order_list is > - executed in the same way as the query > - SELECT ... ORDER BY order_list > - unless the SELECT construct contains ORDER BY or LIMIT > clauses. > - Otherwise we create a fake SELECT_LEX if it has not > been created > - yet. > - */ > - SELECT_LEX *first_sl= unit->first_select(); > - if (!unit->is_unit_op() && > - (first_sl->order_list.elements || > - first_sl->select_limit) && > - unit->add_fake_select_lex(thd)) > - MYSQL_YYABORT; > - } > - if (sel->master_unit()->is_unit_op() && !sel->braces) > - { > - /* > - At this point we don't know yet whether this is the last > - select in union or not, but we move ORDER BY to > - fake_select_lex anyway. If there would be one more select > - in union mysql_new_select will correctly throw error. > - */ > - DBUG_ASSERT(sel->master_unit()->fake_select_lex); > - lex->current_select= sel->master_unit()->fake_select_lex; > - } > + thd->where= "ORDER clause"; > } > order_list > { > - > + $$= $4; > } > ; > > order_list: > order_list ',' order_ident order_dir > - { if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; } > + { > + $$= $1; > + if (add_to_list(thd, *$$, $3,(bool) $4)) > + MYSQL_YYABORT; > + } > | order_ident order_dir > - { if (add_order_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; } > + { > + $$= new (thd->mem_root) SQL_I_List<ORDER>(); > + if (add_to_list(thd, *$$, $1, (bool) $2)) > + MYSQL_YYABORT; > + } > ; > > order_dir: > @@ -12299,63 +12567,61 @@ order_dir: > ; > > opt_limit_clause: > - /* empty */ {} > - | limit_clause {} > + /* empty */ > + { $$.empty(); } > + | limit_clause > + { $$= $1; } > ; > > -limit_clause_init: > - LIMIT > - { > - SELECT_LEX *sel= Select; > - if (sel->master_unit()->is_unit_op() && !sel->braces) > - { > - /* Move LIMIT that belongs to UNION to fake_select_lex */ > - Lex->current_select= sel->master_unit()->fake_select_lex; > - DBUG_ASSERT(Select); > - } > - } > - ; > - > limit_clause: > - limit_clause_init limit_options > + LIMIT limit_options > { > - SELECT_LEX *sel= Select; > - if (!sel->select_limit->basic_const_item() || > - sel->select_limit->val_int() > 0) > + $$= $2; > + if (!$$.select_limit->basic_const_item() || > + $$.select_limit->val_int() > 0) > Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); > } > - | limit_clause_init limit_options > + | LIMIT limit_options > ROWS_SYM EXAMINED_SYM limit_rows_option > { > + $$= $2; > Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); > } > - | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option > + | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option > { > + $$.select_limit= 0; > + $$.offset_limit= 0; > + $$.explicit_limit= 1; > Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); > } > ; > > +opt_global_limit_clause: > + opt_limit_clause > + { > + Select->explicit_limit= $1.explicit_limit; > + Select->select_limit= $1.select_limit; > + Select->offset_limit= $1.offset_limit; > + } > + > limit_options: > limit_option > { > - SELECT_LEX *sel= Select; > - sel->select_limit= $1; > - sel->offset_limit= 0; > - sel->explicit_limit= 1; > + $$.select_limit= $1; > + $$.offset_limit= 0; > + $$.explicit_limit= 1; > } > | limit_option ',' limit_option > { > - SELECT_LEX *sel= Select; > - sel->select_limit= $3; > - sel->offset_limit= $1; > - sel->explicit_limit= 1; > + $$.select_limit= $3; > + $$.offset_limit= $1; > + $$.explicit_limit= 1; > } > | limit_option OFFSET_SYM limit_option > { > - SELECT_LEX *sel= Select; > - sel->select_limit= $1; > - sel->offset_limit= $3; > - sel->explicit_limit= 1; > + $$.select_limit= $1; > + $$.offset_limit= $3; > + $$.explicit_limit= 1; > } > ; > > @@ -12424,6 +12690,66 @@ delete_limit_clause: > | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); > MYSQL_YYABORT; } > ; > > +query_expression_tail: > + /* empty */ { $$= NULL; } > + | order_or_limit opt_select_lock_type > + { > + $$= $1; > + $$->lock= $2; > + } > + | order_or_limit procedure_or_into opt_select_lock_type > + { > + $$= $1; > + $$->lock= $3; > + } > + | procedure_or_into opt_select_lock_type > + { > + $$= new(thd->mem_root) Lex_order_limit_lock; > + if (!$$) > + YYABORT; > + $$->order_list= NULL; > + $$->limit.empty(); > + $$->lock= $2; > + } > + | select_lock_type > + { > + $$= new(thd->mem_root) Lex_order_limit_lock; > + if (!$$) > + YYABORT; > + $$->order_list= NULL; > + $$->limit.empty(); > + $$->lock= $1; > + } > + ; > + > +procedure_or_into: > + procedure_clause > + | into > + | procedure_clause into > + ; > + > +order_or_limit: > + order_clause opt_limit_clause > + { > + $$= new(thd->mem_root) Lex_order_limit_lock; > + if (!$$) > + YYABORT; > + $$->order_list= $1; > + $$->limit= $2; > + } > + | limit_clause > + { > + Lex_order_limit_lock *op= $$= new(thd->mem_root) > Lex_order_limit_lock; > + if (!$$) > + YYABORT; > + op->order_list= NULL; > + op->limit= $1; > + $$->order_list= NULL; > + $$->limit= $1; > + } > + ; > + > + > opt_plus: > /* empty */ > | '+' > @@ -12493,14 +12819,11 @@ bool: > | TRUE_SYM { $$= 1; } > | FALSE_SYM { $$= 0; } > > - > procedure_clause: > PROCEDURE_SYM ident /* Procedure name */ > { > LEX *lex=Lex; > > - DBUG_ASSERT(&lex->builtin_select == lex->current_select); > - > lex->proc_list.elements=0; > lex->proc_list.first=0; > lex->proc_list.next= &lex->proc_list.first; > @@ -12520,6 +12843,7 @@ procedure_clause: > parameters are reduced. > */ > Lex->expr_allows_subselect= false; > + Select->options|= OPTION_PROCEDURE_CLAUSE; > } > '(' procedure_list ')' > { > @@ -12600,8 +12924,21 @@ select_outvar: > } > ; > > +opt_into: > + /* empty */ > + | into > + ; > into: > INTO into_destination > + { > + if (!(Select->options & OPTION_INTO_CLAUSE)) > + Select->options|= OPTION_INTO_CLAUSE; > + else > + { > + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "INTO"); > + MYSQL_YYABORT; > + } > + } > ; > > into_destination: > @@ -12647,10 +12984,15 @@ do: > LEX *lex=Lex; > lex->sql_command = SQLCOM_DO; > mysql_init_select(lex); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > expr_list > { > Lex->insert_list= $3; > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > ; > > @@ -12882,17 +13224,24 @@ insert: > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_INSERT; > - lex->duplicates= DUP_ERROR; > - mysql_init_select(lex); > + lex->duplicates= DUP_ERROR; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + mysql_init_select(lex); > + lex->current_select->parsing_place= BEFORE_OPT_LIST; > } > insert_lock_option > opt_ignore insert2 > { > Select->set_lock_for_tables($3); > - Lex->current_select= &Lex->builtin_select; > + Lex->current_select= Lex->first_select_lex(); > } > insert_field_spec opt_insert_update > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > ; > > replace: > @@ -12901,15 +13250,22 @@ replace: > LEX *lex=Lex; > lex->sql_command = SQLCOM_REPLACE; > lex->duplicates= DUP_REPLACE; > - mysql_init_select(lex); > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + mysql_init_select(lex); > + lex->current_select->parsing_place= BEFORE_OPT_LIST; > } > replace_lock_option insert2 > { > Select->set_lock_for_tables($3); > - Lex->current_select= &Lex->builtin_select; > + Lex->current_select= Lex->first_select_lex(); > } > insert_field_spec > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > ; > > insert_lock_option: > @@ -12955,35 +13311,47 @@ insert_table: > table_name_with_opt_use_partition > { > LEX *lex=Lex; > - lex->field_list.empty(); > + //lex->field_list.empty(); > lex->many_values.empty(); > lex->insert_list=0; > }; > > insert_field_spec: > insert_values {} > - | '(' ')' insert_values {} > - | '(' fields ')' insert_values {} > + | insert_field_list insert_values {} > | SET > { > LEX *lex=Lex; > if (!(lex->insert_list= new (thd->mem_root) List_item) || > lex->many_values.push_back(lex->insert_list, > thd->mem_root)) > MYSQL_YYABORT; > + lex->current_select->parsing_place= NO_MATTER; > } > ident_eq_list > ; > > +insert_field_list: > + LEFT_PAREN_ALT opt_fields ')' > + { > + Lex->current_select->parsing_place= AFTER_LIST; > + } > + ; > + > +opt_fields: > + /* empty */ > + | fields > + ; > + > fields: > fields ',' insert_ident > { Lex->field_list.push_back($3, thd->mem_root); } > | insert_ident { Lex->field_list.push_back($1, thd->mem_root); } > ; > > + > + > insert_values: > - VALUES values_list {} > - | VALUE_SYM values_list {} > - | create_select_query_expression {} > + create_select_query_expression {} > ; > > values_list: > @@ -13093,6 +13461,8 @@ update: > UPDATE_SYM > { > LEX *lex= Lex; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > mysql_init_select(lex); > lex->sql_command= SQLCOM_UPDATE; > lex->duplicates= DUP_ERROR; > @@ -13118,7 +13488,14 @@ update: > */ > Select->set_lock_for_tables($3); > } > - opt_where_clause opt_order_clause delete_limit_clause {} > + opt_where_clause opt_order_clause delete_limit_clause > + { > + if ($10) > + Select->order_list= *($10); > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > ; > > update_list: > @@ -13164,6 +13541,8 @@ delete: > mysql_init_select(lex); > YYPS->m_lock_type= TL_WRITE_DEFAULT; > YYPS->m_mdl_type= MDL_SHARED_WRITE; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > > lex->ignore= 0; > lex->builtin_select.init_order(); > @@ -13185,7 +13564,12 @@ single_multi: > } > opt_where_clause opt_order_clause > delete_limit_clause {} > - opt_select_expressions {} > + opt_select_expressions > + { > + if ($6) > + Select->order_list= *($6); > + Lex->pop_select(); //main select > + } > | table_wild_list > { > mysql_init_multi_delete(Lex); > @@ -13196,6 +13580,9 @@ single_multi: > { > if (multi_delete_set_locks_and_link_aux_tables(Lex)) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > | FROM table_alias_ref_list > { > @@ -13207,6 +13594,9 @@ single_multi: > { > if (multi_delete_set_locks_and_link_aux_tables(Lex)) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > ; > > @@ -13284,6 +13674,7 @@ truncate: > lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table(); > if (lex->m_sql_cmd == NULL) > MYSQL_YYABORT; > + Lex->pop_select(); //main select > } > opt_truncate_table_storage_clause { } > ; > @@ -13365,6 +13756,8 @@ show: > LEX *lex=Lex; > lex->wild=0; > lex->ident= null_clex_str; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > mysql_init_select(lex); > lex->current_select->parsing_place= SELECT_LIST; > lex->create_info.init(); > @@ -13372,6 +13765,7 @@ show: > show_param > { > Select->parsing_place= NO_MATTER; > + Lex->pop_select(); //main select > } > ; > > @@ -13387,7 +13781,7 @@ show_param: > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_TABLES; > - lex->builtin_select.db= $3; > + lex->first_select_lex()->db= $3; > if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES)) > MYSQL_YYABORT; > } > @@ -13395,7 +13789,7 @@ show_param: > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_TRIGGERS; > - lex->builtin_select.db= $3; > + lex->first_select_lex()->db= $3; > if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS)) > MYSQL_YYABORT; > } > @@ -13403,7 +13797,7 @@ show_param: > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_EVENTS; > - lex->builtin_select.db= $2; > + lex->first_select_lex()->db= $2; > if (prepare_schema_table(thd, lex, 0, SCH_EVENTS)) > MYSQL_YYABORT; > } > @@ -13411,7 +13805,7 @@ show_param: > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_TABLE_STATUS; > - lex->builtin_select.db= $3; > + lex->first_select_lex()->db= $3; > if (prepare_schema_table(thd, lex, 0, SCH_TABLES)) > MYSQL_YYABORT; > } > @@ -13419,7 +13813,7 @@ show_param: > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; > - lex->builtin_select.db= $3; > + lex->first_select_lex()->db= $3; > if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES)) > MYSQL_YYABORT; > } > @@ -13469,12 +13863,13 @@ show_param: > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; > } > - opt_limit_clause > + opt_global_limit_clause > | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in > binlog_from > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS; > - } opt_limit_clause > + } > + opt_global_limit_clause > | keys_or_index from_or_in table_ident opt_db opt_where_clause > { > LEX *lex= Lex; > @@ -13516,13 +13911,13 @@ show_param: > LEX_CSTRING var= {STRING_WITH_LEN("error_count")}; > (void) create_select_for_variable(thd, &var); > } > - | WARNINGS opt_limit_clause > + | WARNINGS opt_global_limit_clause > { Lex->sql_command = SQLCOM_SHOW_WARNS;} > - | ERRORS opt_limit_clause > + | ERRORS opt_global_limit_clause > { Lex->sql_command = SQLCOM_SHOW_ERRORS;} > | PROFILES_SYM > { Lex->sql_command = SQLCOM_SHOW_PROFILES; } > - | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause > + | PROFILE_SYM opt_profile_defs opt_profile_args > opt_global_limit_clause > { > LEX *lex= Lex; > lex->sql_command= SQLCOM_SHOW_PROFILE; > @@ -13829,7 +14224,7 @@ describe: > explainable_command > { > LEX *lex=Lex; > - lex->builtin_select.options|= SELECT_DESCRIBE; > + lex->first_select_lex()->options|= SELECT_DESCRIBE; > } > ; > > @@ -13855,6 +14250,8 @@ analyze_stmt_command: > > opt_extended_describe: > EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; } > + | EXTENDED_SYM ALL > + { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; } > | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; } > | opt_format_json {} > ; > @@ -13897,8 +14294,7 @@ flush: > lex->type= 0; > lex->no_write_to_binlog= $2; > } > - flush_options > - {} > + flush_options {} > ; > > flush_options: > @@ -13915,6 +14311,7 @@ flush_options: > opt_table_list opt_flush_lock > {} > | flush_options_list > + {} > ; > > opt_flush_lock: > @@ -14070,9 +14467,13 @@ purge: > LEX *lex=Lex; > lex->type=0; > lex->sql_command = SQLCOM_PURGE; > + if (lex->main_select_push()) > + MYSQL_YYABORT; > } > purge_options > - {} > + { > + Lex->pop_select(); //main select > + } > ; > > purge_options: > @@ -14090,6 +14491,8 @@ purge_option: > lex->value_list.empty(); > lex->value_list.push_front($2, thd->mem_root); > lex->sql_command= SQLCOM_PURGE_BEFORE; > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > ; > > @@ -14099,6 +14502,8 @@ kill: > KILL_SYM > { > LEX *lex=Lex; > + if (lex->main_select_push()) > + YYABORT; > lex->value_list.empty(); > lex->users_list.empty(); > lex->sql_command= SQLCOM_KILL; > @@ -14107,6 +14512,7 @@ kill: > kill_type kill_option kill_expr > { > Lex->kill_signal= (killed_state) ($3 | $4); > + Lex->pop_select(); //main select > } > ; > > @@ -14167,6 +14573,8 @@ load: > $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML"); > MYSQL_YYABORT; > } > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > load_data_lock opt_local INFILE TEXT_STRING_filesystem > { > @@ -14193,7 +14601,11 @@ load: > opt_xml_rows_identified_by > opt_field_term opt_line_term opt_ignore_lines > opt_field_or_var_spec > opt_load_data_set_spec > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > ; > > data_or_xml: > @@ -14597,17 +15009,21 @@ opt_with_clause: > > > with_clause: > - WITH opt_recursive > + WITH opt_recursive > { > + LEX *lex= Lex; > With_clause *with_clause= > new With_clause($2, Lex->curr_with_clause); > if (with_clause == NULL) > MYSQL_YYABORT; > - Lex->derived_tables|= DERIVED_WITH; > - Lex->curr_with_clause= with_clause; > + lex->derived_tables|= DERIVED_WITH; > + lex->curr_with_clause= with_clause; > with_clause->add_to_list(Lex->with_clauses_list_last_next); > + if (lex->current_select && > + lex->current_select->parsing_place == BEFORE_OPT_LIST) > + lex->current_select->parsing_place= NO_MATTER; > } > - with_list > + with_list > { > $$= Lex->curr_with_clause; > Lex->curr_with_clause= Lex->curr_with_clause->pop(); > @@ -14636,9 +15052,9 @@ with_list_element: > MYSQL_YYABORT; > Lex->with_column_list.empty(); > } > - AS '(' remember_name subselect remember_end ')' > + AS '(' remember_name query_expression remember_end ')' > { > - With_element *elem= new With_element($1, *$2, > $7->master_unit()); > + With_element *elem= new With_element($1, *$2, $7); > if (elem == NULL || Lex->curr_with_clause->add_with_element(elem)) > MYSQL_YYABORT; > if (elem->set_unparsed_spec(thd, $6+1, $8)) > @@ -15589,14 +16005,22 @@ set: > SET > { > LEX *lex=Lex; > + if (lex->main_select_push()) > + MYSQL_YYABORT; > lex->set_stmt_init(); > lex->var_list.empty(); > sp_create_assignment_lex(thd, yychar == YYEMPTY); > } > start_option_value_list > - {} > + { > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + } > | SET STATEMENT_SYM > { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > Lex->set_stmt_init(); > } > set_stmt_option_value_following_option_type_list > @@ -15606,6 +16030,9 @@ set: > my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), > "SET STATEMENT")); > lex->stmt_var_list= lex->var_list; > lex->var_list.empty(); > + Lex->pop_select(); //main select > + if (Lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > } > FOR_SYM verb_clause > {} > @@ -16038,9 +16465,13 @@ lock: > if (lex->sphead) > my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK")); > lex->sql_command= SQLCOM_LOCK_TABLES; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > table_lock_list opt_lock_wait_timeout > - {} > + { > + Lex->pop_select(); //main select > + } > ; > > opt_lock_wait_timeout: > @@ -16071,7 +16502,7 @@ table_lock_list: > ; > > table_lock: > - table_ident opt_table_alias lock_option > + table_ident opt_table_alias_clause lock_option > { > thr_lock_type lock_type= (thr_lock_type) $3; > bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE); > @@ -16105,9 +16536,13 @@ unlock: > if (lex->sphead) > my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK")); > lex->sql_command= SQLCOM_UNLOCK_TABLES; > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > } > table_or_tables > - {} > + { > + Lex->pop_select(); //main select > + } > ; > > /* > @@ -16115,25 +16550,36 @@ unlock: > */ > > handler: > - HANDLER_SYM table_ident OPEN_SYM opt_table_alias > + HANDLER_SYM > + { > + if (Lex->main_select_push()) > + MYSQL_YYABORT; > + } > + handler_tail > + { > + Lex->pop_select(); //main select > + } > + > +handler_tail: > + table_ident OPEN_SYM opt_table_alias_clause > { > LEX *lex= Lex; > if (lex->sphead) > my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); > lex->sql_command = SQLCOM_HA_OPEN; > - if (!lex->current_select->add_table_to_list(thd, $2, $4, 0)) > + if (!lex->current_select->add_table_to_list(thd, $1, $3, 0)) > MYSQL_YYABORT; > } > - | HANDLER_SYM table_ident_nodb CLOSE_SYM > + | table_ident_nodb CLOSE_SYM > { > LEX *lex= Lex; > if (lex->sphead) > my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); > lex->sql_command = SQLCOM_HA_CLOSE; > - if (!lex->current_select->add_table_to_list(thd, $2, 0, 0)) > + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0)) > MYSQL_YYABORT; > } > - | HANDLER_SYM table_ident_nodb READ_SYM > + | table_ident_nodb READ_SYM > { > LEX *lex=Lex; > if (lex->sphead) > @@ -16141,20 +16587,24 @@ handler: > lex->expr_allows_subselect= FALSE; > lex->sql_command = SQLCOM_HA_READ; > lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify > warnings */ > - Item *one= new (thd->mem_root) Item_int(thd, (int32) 1); > - if (one == NULL) > - MYSQL_YYABORT; > - lex->current_select->select_limit= one; > - lex->current_select->offset_limit= 0; > - lex->limit_rows_examined= 0; > - if (!lex->current_select->add_table_to_list(thd, $2, 0, 0)) > + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0)) > MYSQL_YYABORT; > } > - handler_read_or_scan opt_where_clause opt_limit_clause > + handler_read_or_scan opt_where_clause opt_global_limit_clause > { > - Lex->expr_allows_subselect= TRUE; > + LEX *lex=Lex; > + lex->expr_allows_subselect= TRUE; > + if (!lex->current_select->explicit_limit) > + { > + Item *one= new (thd->mem_root) Item_int(thd, (int32) 1); > + if (one == NULL) > + MYSQL_YYABORT; > + lex->current_select->select_limit= one; > + lex->current_select->offset_limit= 0; > + lex->limit_rows_examined= 0; > + } > /* Stored functions are not supported for HANDLER READ. */ > - if (Lex->uses_stored_routines()) > + if (lex->uses_stored_routines()) > { > my_error(ER_NOT_SUPPORTED_YET, MYF(0), > "stored functions in HANDLER ... READ"); > @@ -16800,83 +17250,16 @@ release: > */ > > unit_type_decl: > - UNION_SYM > - { $$= UNION_TYPE; } > + UNION_SYM union_option > + { $$.unit_type= UNION_TYPE; $$.distinct= $2; } > | INTERSECT_SYM > - { $$= INTERSECT_TYPE; } > + { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; } > | EXCEPT_SYM > - { $$= EXCEPT_TYPE; } > - > - > -union_clause: > - /* empty */ {} > - | union_list > - ; > - > -union_list: > - unit_type_decl union_option > - { > - if (Lex->add_select_to_union_list((bool)$2, $1, TRUE)) > - MYSQL_YYABORT; > - } > - union_list_part2 > - { > - /* > - Remove from the name resolution context stack the context > of the > - last select in the union. > - */ > - Lex->pop_context(); > - } > - ; > - > -union_list_view: > - unit_type_decl union_option > - { > - if (Lex->add_select_to_union_list((bool)$2, $1, TRUE)) > - MYSQL_YYABORT; > - } > - query_expression_body_view > - { > - Lex->pop_context(); > - } > - ; > - > -union_order_or_limit: > - { > - LEX *lex= thd->lex; > - DBUG_ASSERT(lex->current_select->linkage != > GLOBAL_OPTIONS_TYPE); > - SELECT_LEX *sel= lex->current_select; > - SELECT_LEX_UNIT *unit= sel->master_unit(); > - SELECT_LEX *fake= unit->fake_select_lex; > - if (fake) > - { > - fake->no_table_names_allowed= 1; > - lex->current_select= fake; > - } > - thd->where= "global ORDER clause"; > - } > - order_or_limit > - { > - thd->lex->current_select->no_table_names_allowed= 0; > - thd->where= ""; > - } > - ; > - > -order_or_limit: > - order_clause opt_limit_clause > - | limit_clause > - ; > + { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; } > > /* > Start a UNION, for non-top level query expressions. > */ > -union_head_non_top: > - unit_type_decl union_option > - { > - if (Lex->add_select_to_union_list((bool)$2, $1, FALSE)) > - MYSQL_YYABORT; > - } > - ; > > union_option: > /* empty */ { $$=1; } > @@ -16884,110 +17267,10 @@ union_option: > | ALL { $$=0; } > ; > > -/* > - Corresponds to the SQL Standard > - <query specification> ::= > - SELECT [ <set quantifier> ] <select list> <table expression> > - > - Notes: > - - We allow more options in addition to <set quantifier> > - - <table expression> is optional in MariaDB > -*/ > -query_specification: > - SELECT_SYM select_init2_derived opt_table_expression > - { > - $$= Lex->current_select->master_unit()->first_select(); > - } > - ; > - > -query_term_union_not_ready: > - query_specification order_or_limit opt_select_lock_type { $$= > $1; } > - | '(' select_paren_derived ')' union_order_or_limit { $$= > $2; } > - ; > - > -query_term_union_ready: > - query_specification opt_select_lock_type { $$= > $1; } > - | '(' select_paren_derived ')' { $$= > $2; } > - ; > - > -query_expression_body: > - query_term_union_not_ready { > $$= $1; } > - | query_term_union_ready { > $$= $1; } > - | query_term_union_ready union_list_derived { > $$= $1; } > - ; > - > -/* Corresponds to <query expression> in the SQL:2003 standard. */ > -subselect: > - subselect_start opt_with_clause query_expression_body > subselect_end > - { > - $3->set_with_clause($2); > - $$= $3; > - } > - ; > - > -subselect_start: > - { > - LEX *lex=Lex; > - if (!lex->expr_allows_subselect || > - lex->sql_command == (int)SQLCOM_PURGE) > - { > - thd->parse_error(); > - MYSQL_YYABORT; > - } > - /* > - we are making a "derived table" for the parenthesis > - as we need to have a lex level to fit the union > - after the parenthesis, e.g. > - (SELECT .. ) UNION ... becomes > - SELECT * FROM ((SELECT ...) UNION ...) > - */ > - if (mysql_new_select(Lex, 1, NULL)) > - MYSQL_YYABORT; > - } > - ; > - > -subselect_end: > - { > - LEX *lex=Lex; > - > - lex->check_automatic_up(UNSPECIFIED_TYPE); > - lex->pop_context(); > - SELECT_LEX *child= lex->current_select; > - lex->current_select = > lex->current_select->return_after_parsing(); > - lex->nest_level--; > - lex->current_select->n_child_sum_items += child->n_sum_items; > - /* > - A subselect can add fields to an outer select. Reserve > space for > - them. > - */ > - lex->current_select->select_n_where_fields+= > - child->select_n_where_fields; > - > - /* > - Aggregate functions in having clause may add fields to an > outer > - select. Count them also. > - */ > - lex->current_select->select_n_having_items+= > - child->select_n_having_items; > - } > - ; > - > -opt_query_expression_options: > - /* empty */ > - | query_expression_option_list > - ; > - > -query_expression_option_list: > - query_expression_option_list query_expression_option > - | query_expression_option > - ; > - > query_expression_option: > STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } > | HIGH_PRIORITY > { > - if (check_simple_select()) > - MYSQL_YYABORT; > YYPS->m_lock_type= TL_READ_HIGH_PRIORITY; > YYPS->m_mdl_type= MDL_SHARED_READ; > Select->options|= SELECT_HIGH_PRIORITY; > @@ -16996,18 +17279,8 @@ query_expression_option: > | UNIQUE_SYM { Select->options|= SELECT_DISTINCT; } > | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } > | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } > - | SQL_BUFFER_RESULT > - { > - if (check_simple_select()) > - MYSQL_YYABORT; > - Select->options|= OPTION_BUFFER_RESULT; > - } > - | SQL_CALC_FOUND_ROWS > - { > - if (check_simple_select()) > - MYSQL_YYABORT; > - Select->options|= OPTION_FOUND_ROWS; > - } > + | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; } > + | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; } > | ALL { Select->options|= SELECT_ALL; } > ; > > @@ -17095,32 +17368,28 @@ view_select: > lex->parsing_options.allows_variable= FALSE; > lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr(); > } > - opt_with_clause query_expression_body_view view_check_option > + query_expression > + view_check_option > { > LEX *lex= Lex; > + SQL_I_List<TABLE_LIST> *save= > &lex->first_select_lex()->table_list; > + lex->set_main_unit($2); > + if (lex->check_main_unit_semantics()) > + MYSQL_YYABORT; > + lex->first_select_lex()->table_list.push_front(save); > + lex->current_select= Lex->first_select_lex(); > size_t len= YYLIP->get_cpp_ptr() - > lex->create_view->select.str; > void *create_view_select= > thd->memdup(lex->create_view->select.str, len); > lex->create_view->select.length= len; > lex->create_view->select.str= (char *) create_view_select; > + size_t not_used; > trim_whitespace(thd->charset(), > - &lex->create_view->select); > - lex->create_view->check= $4; > + &lex->create_view->select, ¬_used); > + lex->create_view->check= $3; > lex->parsing_options.allows_variable= TRUE; > - lex->current_select->set_with_clause($2); > } > ; > > -/* > - SQL Standard <query expression body> for VIEWs. > - Does not include INTO and PROCEDURE clauses. > -*/ > -query_expression_body_view: > - SELECT_SYM select_options_and_item_list select_init3_view > - | '(' select_paren_view ')' > - | '(' select_paren_view ')' union_order_or_limit > - | '(' select_paren_view ')' union_list_view > - ; > - > view_check_option: > /* empty */ { $$= VIEW_CHECK_NONE; } > | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; } > _______________________________________________ > commits mailing list > comm...@mariadb.org > https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits > _______________________________________________ Mailing list: https://launchpad.net/~maria-developers Post to : maria-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~maria-developers More help : https://help.launchpad.net/ListHelp