Re: [Maria-developers] Fwd: [Commits] b32031991e4: initial oracle parser fix
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
Am 10.04.2018 um 10:58 schrieb Alexander Barkov:
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. OK
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). Impossible
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 :)
OK
- 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. The task did not made parser recognizing brackets, and I have no ideas how to return parser errors when all SELECT parsed in the same way in difference from the previous parser which could recognize only one level of SELECTs. Thanks!
[skip]
Hello Sanja, On 04/10/2018 03:37 PM, Oleksandr Byelkin wrote:
Am 10.04.2018 um 10:58 schrieb Alexander Barkov:
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. OK
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). Impossible
It's possible. I easily removed 15 push/pop pairs. But it does not look nice either. It's easier to read when all "create" alternatives reside in the same "create" rule. Ok. I won't insist on that. Just adding "expr" with push/pop should be good enough.
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 :)
OK
- 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. The task did not made parser recognizing brackets, and I have no ideas how to return parser errors when all SELECT parsed in the same way in difference from the previous parser which could recognize only one level of SELECTs.
Can you give an example of a query that is not parsed by the current 10.3 parser, but is parsed in 10.3-MDEV-11953 ? Thanks.
Thanks!
[skip]
Hi, Alexander! Am 10.04.2018 um 15:00 schrieb Alexander Barkov:
Hello Sanja,
[skip]
Can you give an example of a query that is not parsed by the current 10.3 parser, but is parsed in 10.3-MDEV-11953 ? There is mysql-test/main/brackets.test
Hello Sanja, Igor, This patch removes a lot of main_select_push() / pop_select() that you had to add into *.yy files in the 10.3-MDEV-11953 branch. The patch does the following: - Disallows creation of Item_field in the select stack is empty. An error is returned instead (ER_BAD_FIELD_ERROR). The point is that Item_field requires a Name_resolution_context, which is not available with the empty select stack. This additionally fixed the problem reported in: MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable - Disallows creation of Item_sum and Item_windowfunc the same way, as they also need a Name_resolution_context. It fixed the second part of MDEV-14347, about aggregate and window functions. It also fixed: MDEV-15870 Using aggregate and window function in unexpected places can crash the server (repeatable since 10.2) - Adds FOR_LOOP_BOUND into enum_parsing_place, to force creation of a temporary Item_field when inside a FOR loop: FOR x IN ident If the "ident" is later resolves to a cursor name, then the loop is treated as "explicit cursor FOR loop", otherwise it's a normal field name and therefore the same error (ER_BAD_FIELD_ERROR) is returned. - Adds a new method LEX::create_item_query_expression() to reuse the same code in sql_yacc.yy and sql_yacc_ora.yy. Adds a test for curr_sel, in case of NULL resets curr_sel to &lex->builtin_select. - Adds tests to cover IN and EXISTS subselects in various query parts. This was very weakly covered. While working on this patch I had problems with IN and EXISTS subselects, so I had to cover them. - Adds a function relink_hack() to properly bind st_select_lex containing an IN/EXISTS subselect to thd->lex->builtin_select. This is needed for the cases when the statement does not do main_select_push(). I does not know this code well, so you can fine a better solution. Please suggest. I propose the following plan: 1. Move tests for IN/EXISTS from this patch just to 10.3 and rebase your branch. 2. Please review the remaining main_select_push()/pop_select(). Note, these rules must have push/pop for sure, as they need Item_field as a part of their syntax: insert: update: delete: show: handler: But some of push/pop pairs should also be further removed: - Some rules can probably assume (and assert) that the select stack is not empty, as the parent rule must have pushed an entry earlier: partition_entry: parse_vcol_expr: single_multi: - Non-TABLE related entries in: create: alter: cannot use Item_field (e.g CREATE DATABASE or ALTER DATABASE), so push/pop can be removed. - I'm not sure about load: set: I can study these separately (if we generally agree on the plan). 3. Move the part of the patch fixing MDEV-15870 and MDEV-14347 to 10.4, so then you rebase on top of it. Alternatively, just keep MDEV-15870 and MDEV-14347 as a part of 10.3-MDEV-11953. Please decide. On 04/10/2018 03:37 PM, Oleksandr Byelkin wrote:
Am 10.04.2018 um 10:58 schrieb Alexander Barkov:
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. OK
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). Impossible
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 :)
OK
- 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. The task did not made parser recognizing brackets, and I have no ideas how to return parser errors when all SELECT parsed in the same way in difference from the previous parser which could recognize only one level of SELECTs. Thanks!
[skip]
On 04/16/2018 10:38 AM, Alexander Barkov wrote:
- Adds a function relink_hack() to properly bind st_select_lex containing an IN/EXISTS subselect to thd->lex->builtin_select. This is needed for the cases when the statement does not do main_select_push(). I does not know this code well, so you can fine a better solution.
Sorry for typos. I meant: I do not know this code well, so you can find a better solution.
participants (2)
-
Alexander Barkov
-
Oleksandr Byelkin