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 <sanja@mariadb.com> Antwort an: maria-developers@lists.launchpad.net An: commits@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 commits@mariadb.org https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits