diff options
Diffstat (limited to 'sql/sql_yacc_ora.yy')
-rw-r--r-- | sql/sql_yacc_ora.yy | 3179 |
1 files changed, 1670 insertions, 1509 deletions
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index c2684c3ea7f..02fa9c81f88 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -68,6 +68,7 @@ #include "sql_lex.h" #include "sql_sequence.h" #include "my_base.h" +#include "sql_type_json.h" /* this is to get the bison compilation windows warnings out */ #ifdef _MSC_VER @@ -184,6 +185,20 @@ void ORAerror(THD *thd, const char *s) Lex_for_loop_bounds_st for_loop_bounds; Lex_trim_st trim; vers_history_point_t vers_history_point; + 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; @@ -204,6 +219,7 @@ void ORAerror(THD *thd, const char *s) class sp_lex_cursor *sp_cursor_stmt; LEX_CSTRING *lex_str_ptr; LEX_USER *lex_user; + USER_AUTH *user_auth; List<Condition_information_item> *cond_info_list; List<DYNCALL_CREATE_DEF> *dyncol_def_list; List<Item> *item_list; @@ -229,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; @@ -237,8 +254,8 @@ void ORAerror(THD *thd, const char *s) /* enums */ enum enum_sp_suid_behaviour sp_suid; + enum enum_sp_aggregate_type sp_aggregate_type; 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; @@ -278,10 +295,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 55 shift/reduce conflicts. + Currently there are 41 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 54 +%expect 41 /* Comments for TOKENS. @@ -438,6 +455,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token LEADING /* SQL-2003-R */ %token LEAVE_SYM %token LEFT /* SQL-2003-R */ +%token LEFT_PAREN_ALT /* INTERNAL */ +%token LEFT_PAREN_WITH /* INTERNAL */ +%token LEFT_PAREN_LIKE /* INTERNAL */ %token LEX_HOSTNAME %token LIKE /* SQL-2003-R */ %token LIMIT @@ -500,6 +520,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token PERCENT_RANK_SYM %token PERCENTILE_CONT_SYM %token PERCENTILE_DISC_SYM +%token PORTION_SYM /* SQL-2016-R */ %token POSITION_SYM /* SQL-2003-N */ %token PRECISION /* SQL-2003-R */ %token PRIMARY_SYM /* SQL-2003-R */ @@ -628,6 +649,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); Non-reserved keywords */ +%token <kwd> ACCOUNT_SYM /* MYSQL */ %token <kwd> ACTION /* SQL-2003-N */ %token <kwd> ADMIN_SYM /* SQL-2003-N */ %token <kwd> ADDDATE_SYM /* MYSQL-FUNC */ @@ -745,6 +767,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token <kwd> EXIT_MARIADB_SYM /* PLSQL-R */ %token <kwd> EXIT_ORACLE_SYM /* PLSQL-R */ %token <kwd> EXPANSION_SYM +%token <kwd> EXPIRE_SYM /* MySQL */ %token <kwd> EXPORT_SYM %token <kwd> EXTENDED_SYM %token <kwd> EXTENT_SIZE_SYM @@ -860,6 +883,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token <kwd> NAME_SYM /* SQL-2003-N */ %token <kwd> NATIONAL_SYM /* SQL-2003-R */ %token <kwd> NCHAR_SYM /* SQL-2003-R */ +%token <kwd> NEVER_SYM /* MySQL */ %token <kwd> NEW_SYM /* SQL-2003-R */ %token <kwd> NEXT_SYM /* SQL-2003-N */ %token <kwd> NEXTVAL_SYM /* PostgreSQL sequence function */ @@ -983,6 +1007,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token <kwd> SQL_CALC_FOUND_ROWS %token <kwd> SQL_NO_CACHE_SYM %token <kwd> SQL_THREAD +%token <kwd> STAGE_SYM %token <kwd> STARTS_SYM %token <kwd> START_SYM /* SQL-2003-R */ %token <kwd> STATEMENT_SYM @@ -1071,6 +1096,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); /* A dummy token to force the priority of table_ref production in a join. */ %left CONDITIONLESS_JOIN %left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT ON_SYM USING + %left SET_VAR %left OR_SYM OR2_SYM %left XOR @@ -1089,6 +1115,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %left '^' %left MYSQL_CONCAT_SYM %left NEG '~' NOT2_SYM BINARY +%left SUBQUERY_AS_EXPR %left COLLATE_SYM /* @@ -1180,7 +1207,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ALTER TABLE t1 ADD SYSTEM VERSIONING; */ %left PREC_BELOW_CONTRACTION_TOKEN2 -%left TEXT_STRING '(' VALUE_SYM VERSIONING_SYM +%left TEXT_STRING '(' ')' VALUE_SYM VERSIONING_SYM +%left EMPTY_FROM_CLAUSE +%right INTO %type <lex_str> DECIMAL_NUM FLOAT_NUM NUM LONG_NUM @@ -1213,7 +1242,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 <ident_cli> IDENT @@ -1247,7 +1277,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <simple_string> remember_name remember_end remember_end_opt - remember_tok_start remember_tok_end + remember_tok_start wild_and_where %type <const_simple_string> @@ -1283,7 +1313,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 @@ -1292,7 +1322,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_default_time_precision case_stmt_body opt_bin_mod opt_for_system_time_clause opt_if_exists_table_element opt_if_not_exists_table_element - opt_recursive opt_format_xid + opt_recursive opt_format_xid opt_for_portion_of_time_clause %type <object_ddl_options> create_or_replace @@ -1373,6 +1403,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else ident_list ident_list_arg opt_expr_list decode_when_list_oracle + execute_using + execute_params %type <sp_cursor_stmt> sp_cursor_stmt_lex @@ -1405,12 +1437,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <table_list> 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_simple_table - derived_query_specification - derived_table_value_constructor + table_primary_ident table_primary_ident_opt_parens + table_primary_derived table_primary_derived_opt_parens + derived_table_list table_reference_list_parens + nested_table_reference_list join_table_parens + update_table_list %type <date_time_type> date_time_type; %type <interval> interval @@ -1433,6 +1464,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <lex_user> user grant_user grant_role user_or_role current_role admin_option_for_role user_maybe_role +%type <user_auth> opt_auth_str auth_expression auth_token + %type <charset> opt_collate charset_name @@ -1446,14 +1479,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); UNDERSCORE_CHARSET %type <select_lex> subselect - get_select_lex get_select_lex_derived - simple_table query_specification - query_term_union_not_ready - query_term_union_ready - query_expression_body - select_paren_derived table_value_constructor + simple_table + query_simple + query_primary + subquery + select_into_query_specification + +%type <select_lex_unit> + query_expression + query_expression_no_with_clause + query_expression_body_ext + query_expression_body_ext_parens + query_expression_body + query_specification_start %type <boolfunc2creator> comp_op @@ -1465,11 +1505,30 @@ 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_procedure_or_into + 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 + opt_query_expression_tail + order_or_limit + order_limit_lock + opt_order_limit_lock + +%type <select_order> opt_order_clause order_clause order_list %type <NONE> - analyze_stmt_command - query verb_clause create change select do drop insert replace insert2 + analyze_stmt_command backup backup_statements + query verb_clause create change select select_into + do drop insert replace insert2 insert_values update delete truncate rename compound_statement show describe load alter optimize keycache preload flush reset purge begin_stmt_mariadb commit rollback savepoint release @@ -1485,7 +1544,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 no_braces_with_names opt_values_with_names values_with_names procedure_list procedure_list2 procedure_item field_def handler opt_generated_always @@ -1509,18 +1568,16 @@ 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 + prepare execute deallocate statement sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa opt_field_or_var_spec fields_or_vars opt_load_data_set_spec view_list_opt view_list view_select - trigger_tail sp_tail sf_tail event_tail - udf_tail create_function_tail + trigger_tail event_tail install uninstall partition_entry binlog_base64_event normal_key_options normal_key_opts all_key_opt spatial_key_options fulltext_key_options normal_key_opt @@ -1529,6 +1586,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); key_using_alg part_column_list period_for_system_time + period_for_application_time server_def server_options_list server_option definer_opt no_definer definer get_diagnostics parse_vcol_expr vcol_opt_specifier vcol_opt_attribute @@ -1539,7 +1597,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_delete_gtid_domain asrow_attribute set_assign - sf_tail_standalone sp_tail_standalone opt_constraint_no_id END_OF_INPUT @@ -1565,6 +1622,7 @@ END_OF_INPUT %type <plsql_cursor_attr> plsql_cursor_attr %type <sp_suid> sp_suid +%type <sp_aggregate_type> opt_aggregate %type <num> sp_decl_idents sp_decl_idents_init_vars %type <num> sp_handler_type sp_hcond_list @@ -1622,13 +1680,16 @@ END_OF_INPUT %type <frame_exclusion> opt_window_frame_exclusion; %type <window_frame_bound> window_frame_start window_frame_bound; -%type <NONE> +%type <kwd> '-' '+' '*' '/' '%' '(' ')' - ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM BETWEEN_SYM CASE_SYM + ',' '!' '{' '}' '&' '|' + +%type <NONE> + AND_SYM OR_SYM BETWEEN_SYM CASE_SYM THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM MYSQL_CONCAT_SYM ORACLE_CONCAT_SYM -%type <with_clause> opt_with_clause with_clause +%type <with_clause> with_clause %type <lex_str_ptr> query_name @@ -1664,8 +1725,8 @@ rule: <-- starts at col 1 query: END_OF_INPUT { - if (likely(!thd->bootstrap) && - unlikely(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT))) + if (!thd->bootstrap && + (!(thd->lex->lex_options & OPTION_LEX_FOUND_COMMENT))) my_yyabort_error((ER_EMPTY_QUERY, MYF(0))); thd->lex->sql_command= SQLCOM_EMPTY_QUERY; @@ -1719,6 +1780,7 @@ statement: alter | analyze | analyze_stmt_command + | backup | binlog_base64_event | call | change @@ -1761,6 +1823,7 @@ statement: | rollback | savepoint | select + | select_into | set | set_assign | signal_stmt @@ -1779,9 +1842,7 @@ statement: deallocate: deallocate_or_drop PREPARE_SYM ident { - LEX *lex= thd->lex; - lex->sql_command= SQLCOM_DEALLOCATE_PREPARE; - lex->prepared_stmt_name= $3; + Lex->stmt_deallocate_prepare($3); } ; @@ -1791,72 +1852,58 @@ deallocate_or_drop: ; prepare: - PREPARE_SYM ident FROM prepare_src - { - LEX *lex= thd->lex; - if (unlikely(lex->table_or_sp_used())) - my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), - "PREPARE..FROM")); - lex->sql_command= SQLCOM_PREPARE; - lex->prepared_stmt_name= $2; - } - ; - -prepare_src: - { Lex->expr_allows_subselect= false; } + PREPARE_SYM ident FROM + { Lex->clause_that_disallows_subselect= "PREPARE..FROM"; } expr { - Lex->prepared_stmt_code= $2; - Lex->expr_allows_subselect= true; + Lex->clause_that_disallows_subselect= NULL; + if (Lex->stmt_prepare($2, $5)) + MYSQL_YYABORT; } ; execute: - EXECUTE_SYM ident + EXECUTE_SYM ident execute_using { - LEX *lex= thd->lex; - lex->sql_command= SQLCOM_EXECUTE; - lex->prepared_stmt_name= $2; + if (Lex->stmt_execute($2, $3)) + MYSQL_YYABORT; } + | EXECUTE_SYM IMMEDIATE_SYM + { Lex->clause_that_disallows_subselect= "EXECUTE IMMEDIATE"; } + expr + { Lex->clause_that_disallows_subselect= NULL; } execute_using - {} - | EXECUTE_SYM IMMEDIATE_SYM prepare_src { - if (unlikely(Lex->table_or_sp_used())) - my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), - "EXECUTE IMMEDIATE")); - Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE; + if (Lex->stmt_execute_immediate($4, $6)) + MYSQL_YYABORT; } - execute_using - {} ; execute_using: - /* nothing */ - | USING { Lex->expr_allows_subselect= false; } - execute_var_list + /* nothing */ { $$= NULL; } + | USING + { Lex->clause_that_disallows_subselect= "EXECUTE..USING"; } + execute_params { - if (unlikely(Lex->table_or_sp_used())) - my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), - "EXECUTE..USING")); - Lex->expr_allows_subselect= true; + $$= $3; + Lex->clause_that_disallows_subselect= NULL; } ; -execute_var_list: - execute_var_list ',' execute_var_ident - | execute_var_ident - ; - -execute_var_ident: +execute_params: expr_or_default { - if (unlikely(Lex->prepared_stmt_params.push_back($1, - thd->mem_root))) + if (unlikely(!($$= List<Item>::make(thd->mem_root, $1)))) + MYSQL_YYABORT; + } + | execute_params ',' expr_or_default + { + if (($$= $1)->push_back($3, thd->mem_root)) MYSQL_YYABORT; } ; + /* help */ help: @@ -2115,19 +2162,24 @@ 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; if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_create_table())) MYSQL_YYABORT; lex->create_info.init(); - if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, - $1 | $4))) + 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 (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_WRITE, - MDL_EXCLUSIVE))) + } + table_ident + { + LEX *lex= thd->lex; + if (!lex->first_select_lex()-> + add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING, + TL_WRITE, MDL_SHARED_UPGRADABLE)) MYSQL_YYABORT; lex->alter_info.reset(); /* @@ -2142,12 +2194,14 @@ create: create_body { LEX *lex= thd->lex; - lex->current_select= &lex->select_lex; 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; if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_create_sequence())) MYSQL_YYABORT; lex->create_info.init(); @@ -2155,10 +2209,9 @@ create: $1 | $4))) MYSQL_YYABORT; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_WRITE, - MDL_EXCLUSIVE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; /* @@ -2181,8 +2234,9 @@ create: if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1))) { my_error(ER_SEQUENCE_INVALID_DATA, MYF(0), - lex->select_lex.table_list.first->db.str, - lex->select_lex.table_list.first->table_name.str); + lex->first_select_lex()->table_list.first->db.str, + lex->first_select_lex()->table_list.first-> + table_name.str); MYSQL_YYABORT; } @@ -2195,42 +2249,64 @@ create: Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE; Lex->create_info.sequence= 1; - lex->current_select= &lex->select_lex; 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 (unlikely(Lex->add_create_index_prepare($8))) + if (Lex->add_create_index_prepare($9)) MYSQL_YYABORT; - if (unlikely(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 (unlikely(Lex->add_create_index_prepare($7))) + if (Lex->add_create_index_prepare($8)) MYSQL_YYABORT; - if (unlikely(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 (unlikely(Lex->add_create_index_prepare($7))) + if (Lex->add_create_index_prepare($8)) MYSQL_YYABORT; - if (unlikely(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; @@ -2247,50 +2323,120 @@ create: | create_or_replace definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident { - if (unlikely(Lex->add_create_view(thd, $1 | $5, - DTYPE_ALGORITHM_UNDEFINED, $3, - $6))) + 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 (unlikely(Lex->add_create_view(thd, $1 | $6, $2, $4, $7))) + 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 - { } - | create_or_replace definer_opt PROCEDURE_SYM - { Lex->create_info.set($1); } + { + Lex->pop_select(); //main select + } + | create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists + { + if (Lex->stmt_create_procedure_start($1 | $4)) + MYSQL_YYABORT; + } sp_tail_standalone - { } + { + Lex->stmt_create_routine_finalize(); + } | create_or_replace definer_opt EVENT_SYM - { Lex->create_info.set($1); } - event_tail - { } - | create_or_replace definer FUNCTION_SYM - { Lex->create_info.set($1); } - sf_tail_standalone - { } - | create_or_replace no_definer FUNCTION_SYM - { Lex->create_info.set($1); } - create_function_tail - { } - | 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 - { } - | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list - opt_require_clause opt_resource_options + event_tail + { + Lex->pop_select(); //main select + } + | create_or_replace definer opt_aggregate FUNCTION_SYM opt_if_not_exists + sp_name RETURN_ORACLE_SYM + { + if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6)) + MYSQL_YYABORT; + } + sf_return_type + sf_c_chistics_and_body_standalone + opt_sp_name + { + if (Lex->stmt_create_stored_function_finalize_standalone($11)) + MYSQL_YYABORT; + } + | create_or_replace definer opt_aggregate FUNCTION_SYM opt_if_not_exists + sp_name '(' + { + if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6)) + MYSQL_YYABORT; + } + sp_fdparam_list ')' + RETURN_ORACLE_SYM sf_return_type + sf_c_chistics_and_body_standalone + opt_sp_name + { + if (Lex->stmt_create_stored_function_finalize_standalone($14)) + MYSQL_YYABORT; + } + | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists + sp_name RETURN_ORACLE_SYM + { + if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6)) + MYSQL_YYABORT; + } + sf_return_type + sf_c_chistics_and_body_standalone + opt_sp_name + { + if (Lex->stmt_create_stored_function_finalize_standalone($11)) + MYSQL_YYABORT; + } + | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists + sp_name '(' + { + if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6)) + MYSQL_YYABORT; + } + sp_fdparam_list ')' + RETURN_ORACLE_SYM sf_return_type + sf_c_chistics_and_body_standalone + opt_sp_name + { + if (Lex->stmt_create_stored_function_finalize_standalone($14)) + MYSQL_YYABORT; + } + | create_or_replace no_definer opt_aggregate FUNCTION_SYM opt_if_not_exists + ident RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys + { + if (Lex->stmt_create_udf_function($1 | $5, $3, $6, + (Item_result) $8, $10)) + MYSQL_YYABORT; + } + | create_or_replace USER_SYM opt_if_not_exists clear_privileges + grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration { if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))) @@ -2326,7 +2472,7 @@ create: &sp_handler_package_spec, $5, $1 | $4)))) MYSQL_YYABORT; - pkg->set_chistics(Lex->sp_chistics); + pkg->set_c_chistics(Lex->sp_chistics); } opt_package_specification_element_list END remember_end_opt opt_sp_name @@ -2346,7 +2492,7 @@ create: &sp_handler_package_body, $6, $1 | $5)))) MYSQL_YYABORT; - pkg->set_chistics(Lex->sp_chistics); + pkg->set_c_chistics(Lex->sp_chistics); Lex->sp_block_init(thd); } package_implementation_declare_section @@ -2423,13 +2569,14 @@ package_specification_function: MYSQL_YYABORT; thd->lex= $2; if (unlikely(!$2->make_sp_head_no_recursive(thd, spname, - &sp_handler_package_function))) + &sp_handler_package_function, + NOT_AGGREGATE))) MYSQL_YYABORT; $1->sphead->get_package()->m_current_routine= $2; (void) is_native_function_with_warn(thd, &$3); } opt_sp_parenthesized_fdparam_list - sf_return_type + RETURN_ORACLE_SYM sf_return_type sp_c_chistics { sp_head *sp= thd->lex->sphead; @@ -2449,7 +2596,8 @@ package_specification_procedure: MYSQL_YYABORT; thd->lex= $2; if (unlikely(!$2->make_sp_head_no_recursive(thd, spname, - &sp_handler_package_procedure))) + &sp_handler_package_procedure, + DEFAULT_AGGREGATE))) MYSQL_YYABORT; $1->sphead->get_package()->m_current_routine= $2; } @@ -2499,11 +2647,6 @@ package_implementation_function_body: } sp_body opt_package_routine_end_name { - if (unlikely(Lex->sphead->m_flags & sp_head::HAS_AGGREGATE_INSTR)) - { - my_yyabort_error((ER_NOT_AGGREGATE_FUNCTION, MYF(0))); - } - Lex->sphead->set_chistics_agg_type(NOT_AGGREGATE); if (unlikely(thd->lex->sp_body_finalize_function(thd) || thd->lex->sphead->check_package_routine_end_name($5))) MYSQL_YYABORT; @@ -2523,7 +2666,7 @@ package_implementation_procedure_body: sp_body opt_package_routine_end_name { if (unlikely(thd->lex->sp_body_finalize_procedure(thd) || - thd->lex->sphead->check_package_routine_end_name($5))) + thd->lex->sphead->check_package_routine_end_name($5))) MYSQL_YYABORT; thd->lex= $2; } @@ -2561,10 +2704,6 @@ package_specification_element: } ; -create_function_tail: - sf_tail_standalone { } - | udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; } - ; opt_sequence: /* empty */ { } @@ -2884,20 +3023,17 @@ ev_sql_stmt: if (unlikely(!lex->make_sp_head(thd, lex->event_parse_data->identifier, - &sp_handler_procedure))) + &sp_handler_procedure, + DEFAULT_AGGREGATE))) MYSQL_YYABORT; lex->sphead->set_body_start(thd, lip->get_cpp_ptr()); } sp_proc_stmt { - LEX *lex= thd->lex; - /* return back to the original memory root ASAP */ - lex->sphead->set_stmt_end(thd); - lex->sphead->restore_thd_mem_root(thd); - - lex->event_parse_data->body_changed= TRUE; + if (Lex->sp_body_finalize_event(thd)) + MYSQL_YYABORT; } ; @@ -2909,13 +3045,16 @@ clear_privileges: lex->columns.empty(); lex->grant= lex->grant_tot_col= 0; lex->all_privileges= 0; - lex->select_lex.db= null_clex_str; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char *)&(lex->mqh),sizeof(lex->mqh)); + lex->first_select_lex()->db= null_clex_str; + lex->account_options.reset(); } ; +opt_aggregate: + /* Empty */ { $$= NOT_AGGREGATE; } + | AGGREGATE_SYM { $$= GROUP_AGGREGATE; } + ; + sp_name: ident '.' ident { @@ -3029,7 +3168,18 @@ sp_cparams: /* Stored FUNCTION parameter declaration list */ sp_fdparam_list: /* Empty */ - | sp_fdparams + { + Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start(); + Lex->sphead->m_param_end= Lex->sphead->m_param_begin; + } + | + { + Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start(); + } + sp_fdparams + { + Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start(); + } ; sp_fdparams: @@ -3136,18 +3286,6 @@ sp_opt_inout: | IN_SYM OUT_SYM { $$= sp_variable::MODE_INOUT; } ; -sp_parenthesized_fdparam_list: - '(' - { - Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start() + 1; - } - sp_fdparam_list - ')' - { - Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start(); - } - ; - sp_parenthesized_pdparam_list: '(' { @@ -3170,7 +3308,7 @@ sp_no_param: opt_sp_parenthesized_fdparam_list: sp_no_param - | sp_parenthesized_fdparam_list + | '(' sp_fdparam_list ')' ; opt_sp_parenthesized_pdparam_list: @@ -3265,12 +3403,8 @@ optionally_qualified_column_ident: row_field_name: ident_directly_assignable { - if (unlikely(check_string_char_length(&$1, 0, NAME_CHAR_LEN, - system_charset_info, 1))) - my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str)); - if (unlikely(!($$= new (thd->mem_root) Spvar_definition()))) + if (!($$= Lex->row_field_name(thd, $1))) MYSQL_YYABORT; - Lex->init_last_field($$, &$1, thd->variables.collation_database); } ; @@ -3281,17 +3415,12 @@ row_field_definition: row_field_definition_list: row_field_definition { - if (unlikely(!($$= new (thd->mem_root) Row_definition_list())) || - unlikely($$->push_back($1, thd->mem_root))) + if (!($$= Row_definition_list::make(thd->mem_root, $1))) MYSQL_YYABORT; } | row_field_definition_list ',' row_field_definition { - uint unused; - if (unlikely($1->find_row_field_by_name(&$3->field_name, &unused))) - my_yyabort_error((ER_DUP_FIELDNAME, MYF(0), $3->field_name.str)); - $$= $1; - if (unlikely($$->push_back($3, thd->mem_root))) + if (($$= $1)->append_uniq(thd->mem_root, $3)) MYSQL_YYABORT; } ; @@ -3415,10 +3544,13 @@ sp_cursor_stmt: { DBUG_ASSERT(thd->free_list == NULL); Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } select { DBUG_ASSERT(Lex == $1); + Lex->pop_select(); //main select if (unlikely($1->stmt_finalize(thd)) || unlikely($1->sphead->restore_lex(thd))) MYSQL_YYABORT; @@ -3547,7 +3679,7 @@ raise_stmt_oracle: signal_stmt: SIGNAL_SYM signal_value opt_set_signal_information { - if (unlikely(Lex->add_signal_statement(thd, $2))) + if (Lex->add_signal_statement(thd, $2)) MYSQL_YYABORT; } ; @@ -3929,48 +4061,17 @@ sp_proc_stmt_statement: Lex_input_stream *lip= YYLIP; lex->sphead->reset_lex(thd); + /* + We should not push main select here, it will be done or not + done by the statement, we just provide only new LEX for the + statement here as if it is start of parsing new statement. + */ lex->sphead->m_tmp_query= lip->get_tok_start(); } sp_statement { - LEX *lex= thd->lex; - Lex_input_stream *lip= YYLIP; - sp_head *sp= lex->sphead; - - sp->m_flags|= sp_get_flags_for_command(lex); - /* "USE db" doesn't work in a procedure */ - if (unlikely(lex->sql_command == SQLCOM_CHANGE_DB)) - my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE")); - /* - Don't add an instruction for SET statements, since all - instructions for them were already added during processing - of "set" rule. - */ - DBUG_ASSERT(lex->sql_command != SQLCOM_SET_OPTION || - lex->var_list.is_empty()); - if (lex->sql_command != SQLCOM_SET_OPTION) - { - sp_instr_stmt *i=new (thd->mem_root) - sp_instr_stmt(sp->instructions(), lex->spcont, lex); - if (unlikely(i == NULL)) - MYSQL_YYABORT; - - /* - Extract the query statement from the tokenizer. The - end is either lex->ptr, if there was no lookahead, - lex->tok_end otherwise. - */ - if (yychar == YYEMPTY) - i->m_query.length= lip->get_ptr() - sp->m_tmp_query; - else - i->m_query.length= lip->get_tok_start() - sp->m_tmp_query;; - if (unlikely(!(i->m_query.str= strmake_root(thd->mem_root, - sp->m_tmp_query, - i->m_query.length))) || - unlikely(sp->add_instr(i))) - MYSQL_YYABORT; - } - if (unlikely(sp->restore_lex(thd))) + if (Lex->sp_proc_stmt_statement_finalize(thd, yychar == YYEMPTY) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -3983,11 +4084,16 @@ RETURN_ALLMODES_SYM: sp_proc_stmt_return: RETURN_ALLMODES_SYM - { Lex->sphead->reset_lex(thd); } + { + Lex->sphead->reset_lex(thd); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; + } expr { LEX *lex= Lex; sp_head *sp= lex->sphead; + Lex->pop_select(); //main select if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont, $3, lex)) || unlikely(sp->restore_lex(thd))) @@ -4004,7 +4110,16 @@ sp_proc_stmt_return: ; reset_lex_expr: - { Lex->sphead->reset_lex(thd); } expr { $$= $2; } + { + Lex->sphead->reset_lex(thd); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; + } + expr + { + $$= $2; + Lex->pop_select(); //main select + } ; sp_proc_stmt_exit_oracle: @@ -4020,14 +4135,14 @@ sp_proc_stmt_exit_oracle: } | EXIT_ORACLE_SYM WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_exit_statement(thd, $3)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_exit_statement(thd, $3) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } | EXIT_ORACLE_SYM label_ident WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_exit_statement(thd, &$2, $4)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_exit_statement(thd, &$2, $4) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4045,14 +4160,14 @@ sp_proc_stmt_continue_oracle: } | CONTINUE_ORACLE_SYM WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_continue_statement(thd, $3)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_continue_statement(thd, $3) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } | CONTINUE_ORACLE_SYM label_ident WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_continue_statement(thd, &$2, $4)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_continue_statement(thd, &$2, $4) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4103,6 +4218,8 @@ assignment_source_expr: { DBUG_ASSERT(thd->free_list == NULL); Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } expr { @@ -4111,7 +4228,8 @@ assignment_source_expr: $$->sp_lex_in_use= true; $$->set_item_and_free_list($3, thd->free_list); thd->free_list= NULL; - if (unlikely($$->sphead->restore_lex(thd))) + Lex->pop_select(); //main select + if ($$->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4120,6 +4238,9 @@ for_loop_bound_expr: assignment_source_lex { Lex->sphead->reset_lex(thd, $1); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; + Lex->current_select->parsing_place= FOR_LOOP_BOUND; } expr { @@ -4127,8 +4248,10 @@ for_loop_bound_expr: $$= $1; $$->sp_lex_in_use= true; $$->set_item_and_free_list($3, NULL); + Lex->pop_select(); //main select if (unlikely($$->sphead->restore_lex(thd))) MYSQL_YYABORT; + Lex->current_select->parsing_place= NO_MATTER; } ; @@ -4178,7 +4301,12 @@ sp_proc_stmt_fetch_head: ; sp_proc_stmt_fetch: - sp_proc_stmt_fetch_head sp_fetch_list { } + sp_proc_stmt_fetch_head sp_fetch_list { } + | FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM + { + if (unlikely(Lex->sp_add_agg_cfetch())) + MYSQL_YYABORT; + } ; sp_proc_stmt_close: @@ -4233,7 +4361,11 @@ sp_fetch_list: ; sp_if: - { Lex->sphead->reset_lex(thd); } + { + Lex->sphead->reset_lex(thd); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; + } expr THEN_SYM { LEX *lex= Lex; @@ -4247,6 +4379,7 @@ sp_if: unlikely(sp->add_cont_backpatch(i)) || unlikely(sp->add_instr(i))) MYSQL_YYABORT; + Lex->pop_select(); //main select if (unlikely(sp->restore_lex(thd))) MYSQL_YYABORT; } @@ -4347,12 +4480,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(true)) + MYSQL_YYABORT; + } expr { if (unlikely(Lex->case_stmt_action_expr($2))) MYSQL_YYABORT; - if (unlikely(Lex->sphead->restore_lex(thd))) + + Lex->pop_select(); //main select + if (Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } simple_when_clause_list @@ -4375,6 +4514,8 @@ simple_when_clause: WHEN_SYM { Lex->sphead->reset_lex(thd); /* For expr $3 */ + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } expr { @@ -4383,6 +4524,7 @@ simple_when_clause: LEX *lex= Lex; if (unlikely(lex->case_stmt_action_when($3, true))) MYSQL_YYABORT; + Lex->pop_select(); //main select /* For expr $3 */ if (unlikely(lex->sphead->restore_lex(thd))) MYSQL_YYABORT; @@ -4399,12 +4541,15 @@ searched_when_clause: WHEN_SYM { Lex->sphead->reset_lex(thd); /* For expr $3 */ + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } expr { LEX *lex= Lex; if (unlikely(lex->case_stmt_action_when($3, false))) MYSQL_YYABORT; + Lex->pop_select(); //main select /* For expr $3 */ if (unlikely(lex->sphead->restore_lex(thd))) MYSQL_YYABORT; @@ -4593,9 +4738,15 @@ opt_sp_for_loop_direction: ; sp_for_loop_index_and_bounds: - ident_directly_assignable sp_for_loop_bounds + ident_directly_assignable { - if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $2))) + if (Lex->main_select_push(true)) + MYSQL_YYABORT; + } + sp_for_loop_bounds + { + Lex->pop_select(); //main select + if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $3))) MYSQL_YYABORT; } ; @@ -4641,8 +4792,11 @@ while_body: LEX *lex= Lex; if (unlikely(lex->sp_while_loop_expression(thd, $1))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + Lex->pop_select(); //main select + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; + if (lex->main_select_push(true)) + MYSQL_YYABORT; } sp_proc_stmts1 END LOOP_SYM { @@ -4653,7 +4807,11 @@ while_body: repeat_body: sp_proc_stmts1 UNTIL_SYM - { Lex->sphead->reset_lex(thd); } + { + Lex->sphead->reset_lex(thd); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; + } expr END REPEAT_SYM { LEX *lex= Lex; @@ -4664,7 +4822,8 @@ repeat_body: if (unlikely(i == NULL) || unlikely(lex->sphead->add_instr(i))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + Lex->pop_select(); //main select + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; /* We can shortcut the cont_backpatch here */ i->m_cont_dest= ip+1; @@ -4692,6 +4851,8 @@ sp_labeled_control: if (unlikely(Lex->sp_push_loop_label(thd, &$1))) MYSQL_YYABORT; Lex->sphead->reset_lex(thd); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } while_body pop_sp_loop_label { } @@ -4743,6 +4904,8 @@ sp_unlabeled_control: if (unlikely(Lex->sp_push_loop_empty_label(thd))) MYSQL_YYABORT; Lex->sphead->reset_lex(thd); + if (Lex->main_select_push(true)) + MYSQL_YYABORT; } while_body { @@ -5144,26 +5307,16 @@ 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 { Lex->create_info.add(DDL_options_st::OPT_LIKE); - TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd, - $1, NULL, 0, TL_READ, MDL_SHARED_READ); + TABLE_LIST *src_table= Lex->first_select_lex()-> + add_table_to_list(thd, $1, NULL, 0, TL_READ, MDL_SHARED_READ); if (unlikely(! src_table)) MYSQL_YYABORT; /* CREATE TABLE ... LIKE is not allowed for views. */ @@ -5173,7 +5326,7 @@ create_body: create_like: LIKE table_ident { $$= $2; } - | '(' LIKE table_ident ')' { $$= $3; } + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; } ; opt_create_select: @@ -5182,23 +5335,19 @@ 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 + { + if (Lex->parsed_insert_select($1->first_select())) + 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_no_with_clause ')' { - Select->set_with_clause($1); + SELECT_LEX *first_select= $3->first_select(); + $3->set_with_clause($2); + $2->attach_to(first_select); + if (Lex->parsed_insert_select(first_select)) + MYSQL_YYABORT; } - | '(' 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: @@ -5286,8 +5435,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: @@ -5936,56 +6090,6 @@ opt_versioning_interval_start: 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 {} @@ -6213,7 +6317,7 @@ create_table_option: } | UNION_SYM opt_equal { - Lex->select_lex.table_list.save_and_clear(&Lex->save_list); + Lex->first_select_lex()->table_list.save_and_clear(&Lex->save_list); } '(' opt_table_list ')' { @@ -6222,8 +6326,8 @@ create_table_option: from the global list. */ LEX *lex=Lex; - lex->create_info.merge_list= lex->select_lex.table_list.first; - lex->select_lex.table_list= lex->save_list; + lex->create_info.merge_list= lex->first_select_lex()->table_list.first; + lex->first_select_lex()->table_list= lex->save_list; /* When excluding union list from the global list we assume that elements of the former immediately follow elements which represent @@ -6326,7 +6430,7 @@ versioning_option: { if (DBUG_EVALUATE_IF("sysvers_force", 0, 1)) { - my_error(ER_VERS_TEMPORARY, MYF(0)); + my_error(ER_VERS_NOT_SUPPORTED, MYF(0), "CREATE TEMPORARY TABLE"); MYSQL_YYABORT; } } @@ -6413,6 +6517,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 @@ -6423,6 +6534,7 @@ field_list_item: | key_def | constraint_def | period_for_system_time + | PERIOD_SYM period_for_application_time { } ; column_def: @@ -6519,7 +6631,7 @@ key_def: constraint_def: opt_constraint check_constraint { - Lex->add_constraint(&$1, $2, FALSE); + Lex->add_constraint($1, $2, FALSE); } ; @@ -6528,7 +6640,15 @@ period_for_system_time: PERIOD_SYM FOR_SYSTEM_TIME_SYM '(' ident ',' ident ')' { Vers_parse_info &info= Lex->vers_get_info(); - info.set_system_time($4, $6); + info.set_period($4, $6); + } + ; + +period_for_application_time: + FOR_SYM ident '(' ident ',' ident ')' + { + if (Lex->add_period($2, $4, $6)) + MYSQL_YYABORT; } ; @@ -6717,6 +6837,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 { @@ -6724,17 +6846,12 @@ parse_vcol_expr: if (unlikely(!v)) MYSQL_YYABORT; Lex->last_field->vcol_info= v; + Lex->pop_select(); //main select } ; parenthesized_expr: - subselect - { - $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | expr + expr | expr ',' expr_list { $3->push_front($1, thd->mem_root); @@ -6753,6 +6870,16 @@ virtual_column_func: MYSQL_YYABORT; $$= v; } + | subquery + { + Item *item; + if (!(item= new (thd->mem_root) Item_singlerow_subselect(thd, $1))) + MYSQL_YYABORT; + Virtual_column_info *v= add_virtual_expression(thd, item); + if (unlikely(!v)) + MYSQL_YYABORT; + $$= v; + } ; expr_or_literal: column_default_non_parenthesized_expr | signed_literal ; @@ -7037,7 +7164,7 @@ field_type_lob: | JSON_SYM opt_compressed { Lex->charset= &my_charset_utf8mb4_bin; - $$.set(&type_handler_long_blob); + $$.set(&type_handler_json_longtext); } ; @@ -7146,7 +7273,6 @@ opt_field_length_default_1: | field_length { $$= $1; } ; - /* In sql_mode=ORACLE, real size of VARCHAR and CHAR with no length in SP parameters is fixed at runtime with the length of real args. @@ -7808,23 +7934,25 @@ alter: Lex->name= null_clex_str; Lex->table_type= TABLE_TYPE_UNKNOWN; Lex->sql_command= SQLCOM_ALTER_TABLE; - Lex->duplicates= DUP_ERROR; - Lex->select_lex.init_order(); + Lex->duplicates= DUP_ERROR; + Lex->first_select_lex()->order_list.empty(); Lex->create_info.init(); Lex->create_info.row_type= ROW_TYPE_NOT_USED; 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 { - if (unlikely(!Lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_UPGRADABLE))) + if (!Lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, + TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE)) MYSQL_YYABORT; - Lex->select_lex.db= (Lex->select_lex.table_list.first)->db; + Lex->first_select_lex()->db= + (Lex->first_select_lex()->table_list.first)->db; Lex->create_last_non_select_table= Lex->last_table(); Lex->mark_first_table_as_inserting(); } @@ -7837,11 +7965,14 @@ alter: if (unlikely(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(true)) + MYSQL_YYABORT; } create_database_options { @@ -7851,6 +7982,7 @@ alter: if (lex->name.str == NULL && unlikely(lex->copy_db_to(&lex->name))) MYSQL_YYABORT; + Lex->pop_select(); //main select } | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM { @@ -7866,6 +7998,8 @@ alter: if (unlikely(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 @@ -7874,6 +8008,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 { @@ -7881,6 +8018,8 @@ alter: if (unlikely(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 @@ -7889,14 +8028,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 (unlikely(Lex->add_alter_view(thd, $2, $4, $6))) + 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 @@ -7904,14 +8052,22 @@ alter: with the ALTER EVENT below. */ { - if (unlikely(Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))) + 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 @@ -7943,6 +8099,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 { @@ -7972,7 +8130,7 @@ alter: } OPTIONS_SYM '(' server_options_list ')' { } /* ALTER USER foo is allowed for MySQL compatibility. */ | ALTER USER_SYM opt_if_exists clear_privileges grant_list - opt_require_clause opt_resource_options + opt_require_clause opt_resource_options opt_account_locking opt_password_expiration { Lex->create_info.set($3); Lex->sql_command= SQLCOM_ALTER_USER; @@ -7986,16 +8144,17 @@ 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 { LEX *lex= Lex; - if (unlikely(!(lex->create_info.seq_create_info= - new (thd->mem_root) sequence_definition())) || - unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_SEQUENCE, - TL_WRITE, - MDL_EXCLUSIVE))) + if (!(lex->create_info.seq_create_info= new (thd->mem_root) + sequence_definition()) || + !lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_SEQUENCE, + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; } sequence_defs @@ -8004,6 +8163,42 @@ alter: Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3); if (unlikely(Lex->m_sql_cmd == NULL)) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } + ; + +opt_account_locking: + /* Nothing */ {} + | ACCOUNT_SYM LOCK_SYM + { + Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED; + } + | ACCOUNT_SYM UNLOCK_SYM + { + Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED; + } + ; +opt_password_expiration: + /* Nothing */ {} + | PASSWORD_SYM EXPIRE_SYM + { + Lex->account_options.password_expire= PASSWORD_EXPIRE_NOW; + } + | PASSWORD_SYM EXPIRE_SYM NEVER_SYM + { + Lex->account_options.password_expire= PASSWORD_EXPIRE_NEVER; + } + | PASSWORD_SYM EXPIRE_SYM DEFAULT + { + Lex->account_options.password_expire= PASSWORD_EXPIRE_DEFAULT; + } + | PASSWORD_SYM EXPIRE_SYM INTERVAL_SYM NUM DAY_SYM + { + Lex->account_options.password_expire= PASSWORD_EXPIRE_INTERVAL; + if (!(Lex->account_options.num_expiration_days= atoi($4.str))) + my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $4.str)); } ; @@ -8152,22 +8347,7 @@ alter_commands: | EXCHANGE_SYM PARTITION_SYM alt_part_name_item WITH TABLE_SYM table_ident have_partitioning { - LEX *lex= thd->lex; - lex->select_lex.db= $6->db; - if (lex->select_lex.db.str == NULL && - unlikely(lex->copy_db_to(&lex->select_lex.db))) - MYSQL_YYABORT; - lex->name= $6->table; - lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $6, NULL, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_NO_WRITE))) - MYSQL_YYABORT; - DBUG_ASSERT(!lex->m_sql_cmd); - lex->m_sql_cmd= new (thd->mem_root) - Sql_cmd_alter_table_exchange_partition(); - if (unlikely(lex->m_sql_cmd == NULL)) + if (Lex->stmt_alter_table_exchange_partition($6)) MYSQL_YYABORT; } ; @@ -8291,6 +8471,13 @@ alter_list_item: { Lex->alter_info.flags|= ALTER_ADD_PERIOD; } + | ADD + PERIOD_SYM opt_if_not_exists_table_element period_for_application_time + { + Table_period_info &period= Lex->create_info.period_info; + period.create_if_not_exists= Lex->check_exists; + Lex->alter_info.flags|= ALTER_ADD_CHECK_CONSTRAINT; + } | add_column '(' create_field_list ')' { LEX *lex=Lex; @@ -8305,7 +8492,7 @@ alter_list_item: | ADD CONSTRAINT IF_SYM not EXISTS field_ident check_constraint { Lex->alter_info.flags|= ALTER_ADD_CHECK_CONSTRAINT; - Lex->add_constraint(&$6, $7, TRUE); + Lex->add_constraint($6, $7, TRUE); } | CHANGE opt_column opt_if_exists_table_element field_ident field_spec opt_place @@ -8403,9 +8590,9 @@ alter_list_item: | RENAME opt_to table_ident { LEX *lex=Lex; - lex->select_lex.db= $3->db; - if (lex->select_lex.db.str == NULL && - unlikely(lex->copy_db_to(&lex->select_lex.db))) + lex->first_select_lex()->db= $3->db; + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) MYSQL_YYABORT; if (unlikely(check_table_name($3->table.str,$3->table.length, FALSE)) || @@ -8426,7 +8613,7 @@ alter_list_item: $5->name, $4->csname)); if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($5))) MYSQL_YYABORT; - Lex->alter_info.flags|= ALTER_OPTIONS; + Lex->alter_info.flags|= ALTER_CONVERT_TO; } | create_table_options_space_separated { @@ -8458,6 +8645,14 @@ alter_list_item: { Lex->alter_info.flags|= ALTER_DROP_PERIOD; } + | DROP PERIOD_SYM opt_if_exists_table_element FOR_SYM ident + { + Alter_drop *ad= new Alter_drop(Alter_drop::PERIOD, $5.str, $3); + if (unlikely(ad == NULL)) + MYSQL_YYABORT; + Lex->alter_info.drop_list.push_back(ad, thd->mem_root); + Lex->alter_info.flags|= ALTER_DROP_CHECK_CONSTRAINT; + } ; opt_index_lock_algorithm: @@ -8527,7 +8722,6 @@ alter_option: } ; - opt_restrict: /* empty */ { Lex->drop_mode= DROP_DEFAULT; } | RESTRICT { Lex->drop_mode= DROP_RESTRICT; } @@ -8806,6 +9000,7 @@ persistent_column_stat_spec: } table_column_list ')' + { } ; persistent_index_stat_spec: @@ -8819,6 +9014,7 @@ persistent_index_stat_spec: } table_index_list ')' + { } ; table_column_list: @@ -8961,9 +9157,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; @@ -9061,9 +9261,13 @@ 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: @@ -9108,9 +9312,9 @@ adm_partition: cache_keys_spec: { - Lex->select_lex.alloc_index_hints(thd); - Select->set_index_hint_type(INDEX_HINT_USE, - INDEX_HINT_MASK_ALL); + Lex->first_select_lex()->alloc_index_hints(thd); + Lex->first_select_lex()->set_index_hint_type(INDEX_HINT_USE, + INDEX_HINT_MASK_ALL); } cache_key_list_or_empty ; @@ -9130,245 +9334,390 @@ opt_ignore_leaves: Select : retrieve data from table */ - select: - opt_with_clause select_init + query_expression_no_with_clause { - LEX *lex= Lex; - lex->sql_command= SQLCOM_SELECT; - lex->current_select->set_with_clause($1); + if (Lex->push_select($1->fake_select_lex ? + $1->fake_select_lex : + $1->first_select())) + MYSQL_YYABORT; + } + opt_procedure_or_into + { + Lex->pop_select(); + $1->set_with_clause(NULL); + if (Lex->select_finalize($1, $3)) + MYSQL_YYABORT; + } + | with_clause query_expression_no_with_clause + { + if (Lex->push_select($2->fake_select_lex ? + $2->fake_select_lex : + $2->first_select())) + MYSQL_YYABORT; + } + opt_procedure_or_into + { + Lex->pop_select(); + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + if (Lex->select_finalize($2, $4)) + MYSQL_YYABORT; } ; -select_init: - SELECT_SYM select_options_and_item_list select_init3 - | table_value_constructor - | table_value_constructor union_list - | table_value_constructor union_order_or_limit - | '(' 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 - | table_value_constructor - | table_value_constructor union_list - | table_value_constructor union_order_or_limit - | '(' select_paren_union_query_term ')' - | '(' select_paren_union_query_term ')' union_list - | '(' select_paren_union_query_term ')' union_order_or_limit - ; -select_paren: +select_into: + select_into_query_specification { - Lex->current_select->set_braces(true); + if (Lex->push_select($1)) + MYSQL_YYABORT; } - table_value_constructor select_part3 + opt_order_limit_lock { - DBUG_ASSERT(Lex->current_select->braces); - } - | + SELECT_LEX_UNIT *unit; + if (!(unit = Lex->create_unit($1))) + MYSQL_YYABORT; + if ($3) + unit= Lex->add_tail_to_query_expression_body(unit, $3); + if (Lex->select_finalize(unit)) + MYSQL_YYABORT; + } + | with_clause + select_into_query_specification { - /* - 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); + if (Lex->push_select($2)) + MYSQL_YYABORT; } - SELECT_SYM select_options_and_item_list select_part3 - opt_select_lock_type + opt_order_limit_lock { - DBUG_ASSERT(Lex->current_select->braces); + SELECT_LEX_UNIT *unit; + if (!(unit = Lex->create_unit($2))) + MYSQL_YYABORT; + if ($4) + unit= Lex->add_tail_to_query_expression_body(unit, $4); + unit->set_with_clause($1); + $1->attach_to($2); + if (Lex->select_finalize(unit)) + MYSQL_YYABORT; } - | '(' select_paren ')' - ; + ; -select_parent_union_query_term_proper: - SELECT_SYM select_options_and_item_list select_part3_union_query_term - opt_select_lock_type - | table_value_constructor select_part3_union_query_term + +simple_table: + query_specification { $$= $1; } + | table_value_constructor { $$= $1; } ; -select_paren_union_query_term: +table_value_constructor: + VALUES + { + if (Lex->parsed_TVC_start()) + MYSQL_YYABORT; + } + values_list + { + if (!($$= Lex->parsed_TVC_end())) + MYSQL_YYABORT; + } + ; + +query_specification_start: + 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_parent_union_query_term_proper + select_options { - DBUG_ASSERT(Lex->current_select->braces); + Select->parsing_place= SELECT_LIST; } - | '(' select_paren_union_query_term ')' - ; - -select_parent_view_proper: - SELECT_SYM select_options_and_item_list select_part3_view - opt_select_lock_type - | table_value_constructor select_part3_view - ; + select_item_list + { + Select->parsing_place= NO_MATTER; + } + ; -select_paren_view: +query_specification: + query_specification_start + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_window_clause { - /* - 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); + $$= Lex->pop_select(); } - select_parent_view_proper + ; + +select_into_query_specification: + query_specification_start + 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_view ')' ; -/* The equivalent of select_paren for nested queries. */ -select_paren_derived: +/** + + The following grammar for query expressions conformant to + the latest SQL Standard is supported: + + <query expression> ::= + [ <with clause> ] <query expression body> + [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ] + + <with clause> ::= + WITH [ RECURSIVE ] <with_list + + <with list> ::= + <with list element> [ { <comma> <with list element> }... ] + + <with list element> ::= + <query name> [ '(' <with column list> ')' ] + AS <table subquery> + + <with column list> ::= + <column name list> + + <query expression body> :: + <query term> + | <query expression body> UNION [ ALL | DISTINCT ] <query term> + | <query expression body> EXCEPT [ DISTINCT ] <query term> + + <query term> ::= + <query primary> + | <query term> INTERSECT [ DISTINCT ] <query primary> + + <query primary> ::= + <simple table> + | '(' <query expression body> + [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ] + ')' + + <simple table> + <query specification> + | <table value constructor> + + <subquery> + '(' <query_expression> ')' + +*/ + +/* + query_expression produces the same expressions as + <query expression> +*/ + +query_expression: + query_expression_no_with_clause { - Lex->current_select->set_braces(true); + $1->set_with_clause(NULL); + $$= $1; } - table_value_constructor + | with_clause + query_expression_no_with_clause { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + $$= $2; } - | + ; + +/* + query_expression_no_with_clause produces the same expressions as + <query expression> without [ <with clause> ] +*/ + +query_expression_no_with_clause: + query_expression_body_ext { $$= $1; } + | query_expression_body_ext_parens { $$= $1; } + ; + +/* + query_expression_body_ext produces the same expressions as + <query expression body> + [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ] + | '('... <query expression body> + [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ] + ')'... + Note: number of ')' must be equal to the number of '(' in the rule above +*/ + +query_expression_body_ext: + query_expression_body { - Lex->current_select->set_braces(true); + if ($1->first_select()->next_select()) + { + if (Lex->parsed_multi_operand_query_expression_body($1)) + MYSQL_YYABORT; + } } - SELECT_SYM select_part2_derived - opt_table_expression - opt_order_clause - opt_limit_clause - opt_select_lock_type + opt_query_expression_tail { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + if (!$3) + $$= $1; + else + $$= Lex->add_tail_to_query_expression_body($1, $3); } - | '(' select_paren_derived ')' { $$= $2; } - ; - -select_init3: - opt_table_expression - opt_select_lock_type + | query_expression_body_ext_parens { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + Lex->push_select(!$1->first_select()->next_select() ? + $1->first_select() : $1->fake_select_lex); } - 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); + if (!($$= Lex->add_tail_to_query_expression_body_ext_parens($1, $3))) + MYSQL_YYABORT; } ; - -select_init3_union_query_term: - opt_table_expression - opt_select_lock_type - { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); - } - union_clause - | select_part3_union_not_ready_noproc - opt_select_lock_type +query_expression_body_ext_parens: + '(' query_expression_body_ext_parens ')' + { $$= $2; } + | '(' query_expression_body_ext ')' { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + SELECT_LEX *sel= $2->first_select()->next_select() ? + $2->fake_select_lex : $2->first_select(); + sel->braces= true; + $$= $2; } ; +/* + query_expression_body produces the same expressions as + <query expression body> +*/ -select_init3_view: - opt_table_expression opt_select_lock_type +query_expression_body: + query_simple { - Lex->current_select->set_braces(false); + Lex->push_select($1); + if (!($$= Lex->create_unit($1))) + MYSQL_YYABORT; } - | opt_table_expression opt_select_lock_type + | query_expression_body + unit_type_decl { - Lex->current_select->set_braces(false); + if (!$1->first_select()->next_select()) + { + Lex->pop_select(); + } } - union_list_view - | order_or_limit opt_select_lock_type + query_primary { - Lex->current_select->set_braces(false); + if (!($$= Lex->add_primary_to_query_expression_body($1, $4, + $2.unit_type, + $2.distinct, + TRUE))) + MYSQL_YYABORT; } - | table_expression order_or_limit opt_select_lock_type + | query_expression_body_ext_parens + unit_type_decl + query_primary { - Lex->current_select->set_braces(false); + if (!($$= Lex->add_primary_to_query_expression_body_ext_parens( + $1, $3, + $2.unit_type, + $2.distinct))) + MYSQL_YYABORT; } ; /* - The SELECT parts after select_item_list that cannot be followed by UNION. + query_primary produces the same expressions as + <query primary> */ -select_part3: - opt_table_expression - | select_part3_union_not_ready +query_primary: + query_simple + { $$= $1; } + | query_expression_body_ext_parens + { $$= $1->first_select(); } ; -select_part3_union_query_term: - opt_table_expression - | select_part3_union_not_ready_noproc - ; +/* + query_simple produces the same expressions as + <simple table> +*/ -select_part3_view: - opt_table_expression - | order_or_limit - | table_expression order_or_limit +query_simple: + simple_table { $$= $1;} ; -select_part3_union_not_ready: - select_part3_union_not_ready_noproc - | table_expression procedure_clause - | table_expression order_or_limit procedure_clause +subselect: + query_expression + { + if (!($$= Lex->parsed_subselect($1))) + 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 - ; +/* + subquery produces the same expressions as + <subquery> + + Consider the production rule of the SQL Standard + subquery: + '(' query_expression ')' + + This rule is equivalent to the rule + subquery: + '(' query_expression_no_with_clause ')' + | '(' with_clause query_expression_no_with_clause ')' + that in its turn is equivalent to + subquery: + '(' query_expression_body_ext ')' + | query_expression_body_ext_parens + | '(' with_clause query_expression_no_with_clause ')' + + The latter can be re-written into + subquery: + query_expression_body_ext_parens + | '(' with_clause query_expression_no_with_clause ')' + + The last rule allows us to resolve properly the shift/reduce conflict + when subquery is used in expressions such as in the following queries + select (select * from t1 limit 1) + t2.a from t2 + select * from t1 where t1.a [not] in (select t2.a from t2) + + In the rule below %prec SUBQUERY_AS_EXPR forces the parser to perform a shift + operation rather then a reduce operation when ')' is encountered and can be + considered as the last symbol a query expression. +*/ -select_options_and_item_list: +subquery: + query_expression_body_ext_parens %prec SUBQUERY_AS_EXPR { - 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; + if (!$1->fake_select_lex) + $1->first_select()->braces= false; + else + $1->fake_select_lex->braces= false; + if (!($$= Lex->parsed_subselect($1))) + YYABORT; } - select_options select_item_list + | '(' with_clause query_expression_no_with_clause ')' { - Select->parsing_place= NO_MATTER; + $3->set_with_clause($2); + $2->attach_to($3->first_select()); + if (!($$= Lex->parsed_subselect($3))) + YYABORT; } ; - -/** - <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 +opt_from_clause: + /* empty */ %prec EMPTY_FROM_CLAUSE + | from_clause ; from_clause: @@ -9418,8 +9767,9 @@ history_point: TIMESTAMP TEXT_STRING { Item *item; - if (!(item= create_temporal_literal(thd, $2.str, $2.length, YYCSCL, - MYSQL_TYPE_DATETIME, true))) + if (!(item= type_handler_datetime2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true))) MYSQL_YYABORT; $$= Vers_history_point(VERS_TIMESTAMP, item); } @@ -9433,6 +9783,33 @@ history_point: } ; +for_portion_of_time_clause: + FOR_SYM PORTION_SYM OF_SYM remember_tok_start ident FROM + bit_expr TO_SYM bit_expr + { + if (unlikely(0 == strcasecmp($5.str, "SYSTEM_TIME"))) + { + thd->parse_error(ER_SYNTAX_ERROR, $4); + MYSQL_YYABORT; + } + Lex->period_conditions.init(SYSTEM_TIME_FROM_TO, + Vers_history_point(VERS_TIMESTAMP, $7), + Vers_history_point(VERS_TIMESTAMP, $9), + $5); + } + ; + +opt_for_portion_of_time_clause: + /* empty */ + { + $$= false; + } + | for_portion_of_time_clause + { + $$= true; + } + ; + opt_for_system_time_clause: /* empty */ { @@ -9472,59 +9849,68 @@ 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 (unlikely(Lex->current_select != &Lex->select_lex)) - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)) - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE")); - if (unlikely(Lex->select_lex.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->select_lex.options&= ~OPTION_TO_QUERY_CACHE; - Lex->select_lex.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 (unlikely(Lex->current_select != &Lex->select_lex)) - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)) - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE")); - if (unlikely(Lex->select_lex.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->select_lex.options|= OPTION_TO_QUERY_CACHE; - Lex->select_lex.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 + +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, false); - 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, false); - lex->safe_to_cache_query=0; + $$= $5; + $$.defined_lock= TRUE; + $$.update_lock= FALSE; } ; +opt_select_lock_type: + /* empty */ + { + $$.empty(); + } + | select_lock_type + { + $$= $1; + } + ; + +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 @@ -9574,12 +9960,6 @@ remember_tok_start: } ; -remember_tok_end: - { - $$= (char*) YYLIP->get_tok_end(); - } - ; - remember_name: { $$= (char*) YYLIP->get_cpp_tok_start(); @@ -9809,15 +10189,15 @@ bool_pri: ; predicate: - bit_expr IN_SYM '(' subselect ')' + bit_expr IN_SYM subquery { - $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4); + $$= new (thd->mem_root) Item_in_subselect(thd, $1, $3); if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | bit_expr not IN_SYM '(' subselect ')' + | bit_expr not IN_SYM subquery { - Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5); + Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $4); if (unlikely(item == NULL)) MYSQL_YYABORT; $$= negate_expression(thd, item); @@ -10206,7 +10586,21 @@ column_default_non_parenthesized_expr: | param_marker { $$= $1; } | variable | sum_expr + { + if (!Lex->select_stack_top) + { + my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0)); + MYSQL_YYABORT; + } + } | window_func_expr + { + if (!Lex->select_stack_top) + { + my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0)); + MYSQL_YYABORT; + } + } | inverse_distribution_function | ROW_SYM '(' expr ',' expr_list ')' { @@ -10322,6 +10716,11 @@ primary_expr: column_default_non_parenthesized_expr | explicit_cursor_attr | '(' parenthesized_expr ')' { $$= $2; } + | subquery + { + if (!($$= Lex->create_item_query_expression(thd, $1->master_unit()))) + MYSQL_YYABORT; + } ; string_factor_expr: @@ -10385,7 +10784,7 @@ function_call_keyword_timestamp: } | TIMESTAMP '(' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_add_time(thd, $3, $5, 1, 0); + $$= new (thd->mem_root) Item_func_timestamp(thd, $3, $5); if (unlikely($$ == NULL)) MYSQL_YYABORT; } @@ -11364,6 +11763,21 @@ window_func: { ((Item_sum *) $1)->mark_as_window_func_sum_expr(); } + | + function_call_generic + { + Item* item = (Item*)$1; + /* Only UDF aggregate here possible */ + if ((item == NULL) || + (item->type() != Item::SUM_FUNC_ITEM) + || (((Item_sum *)item)->sum_func() != Item_sum::UDF_SUM_FUNC)) + { + thd->parse_error(); + MYSQL_YYABORT; + } + + ((Item_sum *) $1)->mark_as_window_func_sum_expr(); + } ; simple_window_func: @@ -11718,6 +12132,10 @@ cast_type_temporal: DATE_SYM { $$.set(&type_handler_newdate); } | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); } | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); } + | INTERVAL_SYM DAY_SECOND_SYM field_length + { + $$.set(&type_handler_interval_DDhhmmssff, 0, $3); + } ; opt_expr_list: @@ -11728,9 +12146,7 @@ opt_expr_list: expr_list: expr { - $$= new (thd->mem_root) List<Item>; - if (unlikely($$ == NULL) || - unlikely($$->push_back($1, thd->mem_root))) + if (unlikely(!($$= List<Item>::make(thd->mem_root, $1)))) MYSQL_YYABORT; } | expr_list ',' expr @@ -11842,10 +12258,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); } ; @@ -11856,15 +12277,9 @@ derived_table_list: */ join_table: /* INNER JOIN variants */ - /* - Use %prec to evaluate production 'table_ref' before 'normal_join' - so that [INNER | CROSS] JOIN is properly nested as other - left-associative joins. - */ table_ref normal_join table_ref %prec CONDITIONLESS_JOIN { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); - if (unlikely(Select->add_cross_joined_table($1, $3, $2))) MYSQL_YYABORT; } @@ -11872,6 +12287,8 @@ join_table: 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 (unlikely(push_new_name_resolution_context(thd, $1, $3))) MYSQL_YYABORT; @@ -11879,7 +12296,7 @@ join_table: } expr { - $3->straight=$2; + $3->straight=$2; add_join_on(thd, $3, $6); $3->on_context= Lex->pop_context(); Select->parsing_place= NO_MATTER; @@ -11888,6 +12305,8 @@ join_table: USING { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); } '(' using_list ')' { @@ -11898,6 +12317,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); } @@ -11907,6 +12328,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 (unlikely(push_new_name_resolution_context(thd, $1, $5))) MYSQL_YYABORT; @@ -11923,6 +12346,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 ')' { @@ -11933,6 +12358,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; @@ -11943,6 +12370,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 (unlikely(push_new_name_resolution_context(thd, $1, $5))) MYSQL_YYABORT; @@ -11960,6 +12389,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 ')' { @@ -11971,6 +12402,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 (unlikely(!($$= lex->current_select->convert_right_join()))) @@ -12003,240 +12436,63 @@ use_partition: PARTITION_SYM '(' using_list ')' have_partitioning { $$= $3; + Select->parsing_place= Select->save_parsing_place; + Select->save_parsing_place= NO_MATTER; } ; - -/* - 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: - { - DBUG_ASSERT(Select); - SELECT_LEX *sel= Select; - sel->table_join_options= 0; - } - table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition - { - if (unlikely(!($$= Select->add_table_to_list(thd, $2, $5, - Select->get_table_join_options(), - YYPS->m_lock_type, - YYPS->m_mdl_type, - Select-> - pop_index_hints(), - $3)))) - MYSQL_YYABORT; - Select->add_joined_table($$); - if ($4) - $$->vers_conditions= Lex->vers_conditions; + table_primary_ident_opt_parens { $$= $1; } + | table_primary_derived_opt_parens { $$= $1; } + | join_table_parens + { + $1->nested_join->nest_type= 0; + $$= $1; } + | table_reference_list_parens { $$= $1; } ; +table_primary_ident_opt_parens: + table_primary_ident { $$= $1; } + | '(' table_primary_ident_opt_parens ')' { $$= $2; } + ; - -/* - Represents a flattening of the following rules from the SQL:2003 - standard. This sub-rule corresponds to the sub-rule - <table primary> ::= ... | <derived table> [ AS ] <correlation name> - - <derived table> ::= <table subquery> - <table subquery> ::= <subquery> - <subquery> ::= <left paren> <query expression> <right paren> - <query expression> ::= [ <with clause> ] <query expression body> - - For the time being we use the non-standard rule - select_derived_union which is a compromise between the standard - and our parser. Possibly this rule could be replaced by our - query_expression_body. -*/ - -table_primary_derived: - '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias - { - /* Use $2 instead of Lex->current_select as derived table will - alter value of Lex->current_select. */ - if (!($3 || $6) && $2->embedding && - !$2->embedding->nested_join->join_list.elements) - { - /* 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; - } - 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 (unlikely(ti == NULL)) - MYSQL_YYABORT; - if (unlikely(!($$= sel->add_table_to_list(thd, - ti, $6, 0, - TL_READ, - MDL_SHARED_READ)))) - MYSQL_YYABORT; - sel->add_joined_table($$); - lex->pop_context(); - lex->nest_level--; - } - else if (unlikely($6 != 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()); - if ($5) - { - MYSQL_YYABORT_UNLESS(!$3); - $$->vers_conditions= Lex->vers_conditions; - } - } - /* Represents derived table with WITH clause */ - | '(' get_select_lex subselect_start - with_clause query_expression_body - subselect_end ')' opt_for_system_time_clause 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 (unlikely(ti == NULL)) - MYSQL_YYABORT; - $5->set_with_clause($4); - lex->current_select= sel; - if (unlikely(!($$= sel->add_table_to_list(lex->thd, - ti, $9, 0, - TL_READ, - MDL_SHARED_READ)))) - MYSQL_YYABORT; - sel->add_joined_table($$); - if ($8) - $$->vers_conditions= Lex->vers_conditions; - } +table_primary_derived_opt_parens: + table_primary_derived { $$= $1; } + | '(' table_primary_derived_opt_parens ')' { $$= $2; } ; -/* - 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 (unlikely($1)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - } - | select_derived union_head_non_top +table_reference_list_parens: + '(' table_reference_list_parens ')' { $$= $2; } + | '(' nested_table_reference_list ')' { - if (unlikely($1)) - { - thd->parse_error(); + if (!($$= Select->end_nested_join(thd))) MYSQL_YYABORT; - } - } - union_list_derived_part2 - | derived_simple_table opt_select_lock_type - | derived_simple_table order_or_limit opt_select_lock_type - | derived_simple_table 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: +nested_table_reference_list: + table_ref ',' table_ref { - 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; + if (Select->init_nested_join(thd)) + MYSQL_YYABORT; + Select->add_joined_table($1); + Select->add_joined_table($3); + $$= $1->embedding; } - opt_query_expression_options select_item_list + | nested_table_reference_list ',' table_ref { - Select->parsing_place= NO_MATTER; + Select->add_joined_table($3); + $$= $1; } ; -/* handle contents of parentheses in join expression */ -select_derived: - get_select_lex_derived derived_table_list +join_table_parens: + '(' join_table_parens ')' { $$= $2; } + | '(' join_table ')' { LEX *lex= Lex; - /* for normal joins, $2 != NULL and end_nested_join() != NULL, - for derived tables, both must equal NULL */ - - if (unlikely(!($$= $1->end_nested_join(lex->thd)) && $2)) - MYSQL_YYABORT; - if (unlikely(!$2 && $$)) + if (!($$= lex->current_select->nest_last_join(thd))) { thd->parse_error(); MYSQL_YYABORT; @@ -12244,84 +12500,33 @@ select_derived: } ; -derived_simple_table: - derived_query_specification { $$= $1; } - | derived_table_value_constructor { $$= $1; } - ; -/* - 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; - } - ; -derived_table_value_constructor: - VALUES - { - Lex->tvc_start(); - } - values_list +table_primary_ident: + table_ident opt_use_partition opt_for_system_time_clause + opt_table_alias_clause opt_key_definition { - if (Lex->tvc_finalize_derived()) + SELECT_LEX *sel= Select; + sel->table_join_options= 0; + if (!($$= Select->add_table_to_list(thd, $1, $4, + Select->get_table_join_options(), + YYPS->m_lock_type, + YYPS->m_mdl_type, + Select->pop_index_hints(), + $2))) MYSQL_YYABORT; - $$= NULL; + if ($3) + $$->vers_conditions= Lex->vers_conditions; } ; - -select_derived2: +table_primary_derived: + subquery + opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - lex->derived_tables|= DERIVED_SUBQUERY; - if (unlikely(!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE)) - { - thd->parse_error(); + if (!($$= Lex->parsed_derived_table($1->master_unit(), $2, $3))) MYSQL_YYABORT; - } - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || - unlikely(mysql_new_select(lex, 1, NULL))) - MYSQL_YYABORT; - mysql_init_select(lex); - lex->current_select->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 (unlikely($1->init_nested_join(lex->thd))) - 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: @@ -12454,9 +12659,13 @@ table_alias: | '=' ; -opt_table_alias: +opt_table_alias_clause: /* empty */ { $$=0; } - | table_alias ident_table_alias + | table_alias_clause { $$= $1; } + ; + +table_alias_clause: + table_alias ident_table_alias { $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING)); if (unlikely($$ == NULL)) @@ -12552,7 +12761,7 @@ olap_opt: SQL-2003: GROUP BY ... CUBE(col1, col2, col3) */ LEX *lex=Lex; - if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)) + if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE)) my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE", "global union parameters")); lex->current_select->olap= CUBE_TYPE; @@ -12569,7 +12778,7 @@ olap_opt: SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3) */ LEX *lex= Lex; - if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)) + if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE)) my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP", "global union parameters")); lex->current_select->olap= ROLLUP_TYPE; @@ -12611,6 +12820,7 @@ window_spec: opt_window_ref opt_window_partition_clause opt_window_order_clause opt_window_frame_clause ')' + { } ; opt_window_ref: @@ -12630,7 +12840,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: @@ -12756,70 +12966,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 (unlikely(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 (unlikely(!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 (unlikely(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 (unlikely(add_order_to_list(thd, $1,(bool) $2))) + $$= new (thd->mem_root) SQL_I_List<ORDER>(); + if (add_to_list(thd, *$$, $1, (bool) $2)) MYSQL_YYABORT; - } + } ; order_dir: @@ -12829,63 +13004,62 @@ 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; } ; @@ -12949,6 +13123,88 @@ delete_limit_clause: | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; } ; +order_limit_lock: + order_or_limit + { + $$= $1; + $$->lock.empty(); + } + | order_or_limit select_lock_type + { + $$= $1; + $$->lock= $2; + } + | select_lock_type + { + $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + $$->order_list= NULL; + $$->limit.empty(); + $$->lock= $1; + } + ; +opt_order_limit_lock: + /* empty */ + { + Lex->pop_select(); + $$= NULL; + } + | order_limit_lock { $$= $1; } + ; + +query_expression_tail: + order_limit_lock + ; + +opt_query_expression_tail: + opt_order_limit_lock + ; + +opt_procedure_or_into: + /* empty */ + { + $$.empty(); + } + | procedure_clause opt_select_lock_type + { + $$= $2; + } + | into opt_select_lock_type + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, + ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), + "<select expression> INTO <destination>;", + "'SELECT <select list> INTO <destination>" + " FROM...'"); + $$= $2; + } + ; + + +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 */ | '+' @@ -13025,8 +13281,6 @@ procedure_clause: { LEX *lex=Lex; - DBUG_ASSERT(&lex->select_lex == lex->current_select); - lex->proc_list.elements=0; lex->proc_list.first=0; lex->proc_list.next= &lex->proc_list.first; @@ -13041,16 +13295,16 @@ procedure_clause: /* PROCEDURE CLAUSE cannot handle subquery as one of its parameter, - so set expr_allows_subselect as false to disallow any subqueries - further. Reset expr_allows_subselect back to true once the - parameters are reduced. + so disallow any subqueries further. + Alow subqueries back once the parameters are reduced. */ - Lex->expr_allows_subselect= false; + Lex->clause_that_disallows_subselect= "PROCEDURE"; + Select->options|= OPTION_PROCEDURE_CLAUSE; } '(' procedure_list ')' { /* Subqueries are allowed from now.*/ - Lex->expr_allows_subselect= true; + Lex->clause_that_disallows_subselect= NULL; } ; @@ -13129,6 +13383,7 @@ select_outvar: into: INTO into_destination + {} ; into_destination: @@ -13176,11 +13431,14 @@ do: { LEX *lex=Lex; lex->sql_command = SQLCOM_DO; + if (lex->main_select_push(true)) + MYSQL_YYABORT; mysql_init_select(lex); } expr_list { Lex->insert_list= $3; + Lex->pop_select(); //main select } ; @@ -13198,11 +13456,16 @@ drop: } table_list opt_lock_wait_timeout opt_restrict {} - | DROP INDEX_SYM opt_if_exists_table_element ident ON table_ident opt_lock_wait_timeout + | DROP INDEX_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + opt_if_exists_table_element ident ON table_ident opt_lock_wait_timeout { LEX *lex=Lex; Alter_drop *ad= (new (thd->mem_root) - Alter_drop(Alter_drop::KEY, $4.str, $3)); + Alter_drop(Alter_drop::KEY, $5.str, $4)); if (unlikely(ad == NULL)) MYSQL_YYABORT; lex->sql_command= SQLCOM_DROP_INDEX; @@ -13210,10 +13473,11 @@ drop: lex->alter_info.flags= ALTER_DROP_INDEX; lex->alter_info.drop_list.push_back(ad, thd->mem_root); if (unlikely(!lex->current_select-> - add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING, + add_table_to_list(thd, $7, NULL, TL_OPTION_UPDATING, TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE))) MYSQL_YYABORT; + Lex->pop_select(); //main select } | DROP DATABASE opt_if_exists ident { @@ -13338,10 +13602,11 @@ table_list: table_name: table_ident { - if (unlikely(!Select->add_table_to_list(thd, $1, NULL, - TL_OPTION_UPDATING, - YYPS->m_lock_type, - YYPS->m_mdl_type))) + if (!thd->lex->current_select_or_default()-> + add_table_to_list(thd, $1, NULL, + TL_OPTION_UPDATING, + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } ; @@ -13414,17 +13679,23 @@ insert: { LEX *lex= Lex; lex->sql_command= SQLCOM_INSERT; - lex->duplicates= DUP_ERROR; + 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, true); - Lex->current_select= &Lex->select_lex; + 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; Lex->mark_first_table_as_inserting(); } ; @@ -13435,15 +13706,21 @@ replace: LEX *lex=Lex; lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; + 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, true); - Lex->current_select= &Lex->select_lex; + Lex->current_select= Lex->first_select_lex(); } insert_field_spec { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; Lex->mark_first_table_as_inserting(); } ; @@ -13485,10 +13762,13 @@ insert2: ; insert_table: + { + Select->save_parsing_place= Select->parsing_place; + } 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; } @@ -13496,8 +13776,7 @@ insert_table: insert_field_spec: insert_values {} - | '(' ')' insert_values {} - | '(' fields ')' insert_values {} + | insert_field_list insert_values {} | SET { LEX *lex=Lex; @@ -13505,20 +13784,33 @@ insert_field_spec: unlikely(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: @@ -13662,23 +13954,43 @@ opt_insert_update: } ; +update_table_list: + table_ident opt_use_partition for_portion_of_time_clause + opt_table_alias_clause opt_key_definition + { + SELECT_LEX *sel= Select; + sel->table_join_options= 0; + if (!($$= Select->add_table_to_list(thd, $1, $4, + Select->get_table_join_options(), + YYPS->m_lock_type, + YYPS->m_mdl_type, + Select->pop_index_hints(), + $2))) + MYSQL_YYABORT; + $$->period_conditions= Lex->period_conditions; + } + | join_table_list { $$= $1; } + ; + /* Update rows in a table */ 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; } - opt_low_priority opt_ignore join_table_list + opt_low_priority opt_ignore update_table_list SET update_list { - SELECT_LEX *slex= &Lex->select_lex; + SELECT_LEX *slex= Lex->first_select_lex(); if (slex->table_list.elements > 1) Lex->sql_command= SQLCOM_UPDATE_MULTI; - else if (unlikely(slex->get_table_list()->derived)) + else if (slex->get_table_list()->derived) { /* it is single table update and it is update of derived table */ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), @@ -13692,7 +14004,14 @@ update: */ slex->set_lock_for_tables($3, slex->table_list.elements == 1); } - 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: @@ -13736,12 +14055,13 @@ delete: { LEX *lex= Lex; lex->sql_command= SQLCOM_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; + mysql_init_select(lex); lex->ignore= 0; - lex->select_lex.init_order(); + lex->first_select_lex()->order_list.empty(); } delete_part2 ; @@ -13762,6 +14082,7 @@ delete_part2: | HISTORY_SYM delete_single_table opt_delete_system_time { Lex->last_table()->vers_conditions= Lex->vers_conditions; + Lex->pop_select(); //main select } ; @@ -13780,12 +14101,25 @@ delete_single_table: } ; +delete_single_table_for_period: + delete_single_table opt_for_portion_of_time_clause + { + if ($2) + Lex->last_table()->period_conditions= Lex->period_conditions; + } + ; + single_multi: - delete_single_table + delete_single_table_for_period opt_where_clause opt_order_clause delete_limit_clause - opt_select_expressions {} + opt_select_expressions + { + if ($3) + Select->order_list= *($3); + Lex->pop_select(); //main select + } | table_wild_list { mysql_init_multi_delete(Lex); @@ -13796,6 +14130,9 @@ single_multi: { if (unlikely(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 { @@ -13807,6 +14144,9 @@ single_multi: { if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex))) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } ; @@ -13875,9 +14215,9 @@ truncate: LEX* lex= Lex; lex->sql_command= SQLCOM_TRUNCATE; lex->alter_info.reset(); - lex->select_lex.options= 0; - lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED; - lex->select_lex.init_order(); + lex->first_select_lex()->options= 0; + lex->sql_cache= LEX::SQL_CACHE_UNSPECIFIED; + lex->first_select_lex()->order_list.empty(); YYPS->m_lock_type= TL_WRITE; YYPS->m_mdl_type= MDL_EXCLUSIVE; } @@ -13969,6 +14309,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(); @@ -13976,6 +14318,7 @@ show: show_param { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } ; @@ -13991,40 +14334,40 @@ show_param: { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLES; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES)) MYSQL_YYABORT; } | opt_full TRIGGERS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TRIGGERS; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS)) MYSQL_YYABORT; } | EVENTS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_EVENTS; - lex->select_lex.db= $2; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_EVENTS))) + lex->first_select_lex()->db= $2; + if (prepare_schema_table(thd, lex, 0, SCH_EVENTS)) MYSQL_YYABORT; } | TABLE_SYM STATUS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLE_STATUS; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TABLES)) MYSQL_YYABORT; } | OPEN_SYM TABLES opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES)) MYSQL_YYABORT; } | PLUGINS_SYM @@ -14073,12 +14416,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; @@ -14120,13 +14464,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; @@ -14188,7 +14532,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL,0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL,0)) MYSQL_YYABORT; lex->create_info.storage_media= HA_SM_DEFAULT; } @@ -14196,7 +14540,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0)) MYSQL_YYABORT; lex->table_type= TABLE_TYPE_VIEW; } @@ -14204,7 +14548,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0)) MYSQL_YYABORT; lex->table_type= TABLE_TYPE_SEQUENCE; } @@ -14418,10 +14762,12 @@ describe: describe_command table_ident { LEX *lex= Lex; + if (lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; lex->sql_command= SQLCOM_SHOW_FIELDS; - lex->select_lex.db= null_clex_str; + lex->first_select_lex()->db= null_clex_str; lex->verbose= 0; if (unlikely(prepare_schema_table(thd, lex, $2, SCH_COLUMNS))) MYSQL_YYABORT; @@ -14429,18 +14775,20 @@ describe: opt_describe_column { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } | describe_command opt_extended_describe { Lex->describe|= DESCRIBE_NORMAL; } explainable_command { LEX *lex=Lex; - lex->select_lex.options|= SELECT_DESCRIBE; + lex->first_select_lex()->options|= SELECT_DESCRIBE; } ; explainable_command: select + | select_into | insert | replace | update @@ -14461,6 +14809,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 {} ; @@ -14503,8 +14853,7 @@ flush: lex->type= 0; lex->no_write_to_binlog= $2; } - flush_options - {} + flush_options {} ; flush_options: @@ -14521,6 +14870,7 @@ flush_options: opt_table_list opt_flush_lock {} | flush_options_list + {} ; opt_flush_lock: @@ -14606,6 +14956,8 @@ flush_option: { Lex->type|= REFRESH_DES_KEY_FILE; } | RESOURCES { Lex->type|= REFRESH_USER_RESOURCES; } + | SSL_SYM + { Lex->type|= REFRESH_SSL;} | IDENT_sys remember_tok_start { Lex->type|= REFRESH_GENERIC; @@ -14627,6 +14979,43 @@ opt_table_list: | table_list {} ; +backup: + BACKUP_SYM backup_statements {} + ; + +backup_statements: + STAGE_SYM ident + { + int type; + if (unlikely(Lex->sphead)) + my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP STAGE")); + if ((type= find_type($2.str, &backup_stage_names, + FIND_TYPE_NO_PREFIX)) <= 0) + my_yyabort_error((ER_BACKUP_UNKNOWN_STAGE, MYF(0), $2.str)); + Lex->sql_command= SQLCOM_BACKUP; + Lex->backup_stage= (backup_stages) (type-1); + break; + } + | LOCK_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + table_ident + { + if (unlikely(!Select->add_table_to_list(thd, $3, NULL, 0, + TL_READ, MDL_SHARED_HIGH_PRIO))) + MYSQL_YYABORT; + Lex->sql_command= SQLCOM_BACKUP_LOCK; + Lex->pop_select(); //main select + } + | UNLOCK_SYM + { + /* Table list is empty for unlock */ + Lex->sql_command= SQLCOM_BACKUP_LOCK; + } + ; + opt_delete_gtid_domain: /* empty */ {} | DELETE_DOMAIN_ID_SYM '=' '(' delete_domain_id_list ')' @@ -14701,34 +15090,21 @@ master_reset_options: ; purge: - PURGE - { - LEX *lex=Lex; - lex->type=0; - lex->sql_command = SQLCOM_PURGE; - } - purge_options - {} - ; - -purge_options: - master_or_binary LOGS_SYM purge_option - ; - -purge_option: - TO_SYM TEXT_STRING_sys + PURGE master_or_binary LOGS_SYM TO_SYM TEXT_STRING_sys { - Lex->to_log = $2.str; + Lex->stmt_purge_to($5); } - | BEFORE_SYM expr + | PURGE master_or_binary LOGS_SYM BEFORE_SYM + { Lex->clause_that_disallows_subselect= "PURGE..BEFORE"; } + expr { - LEX *lex= Lex; - lex->value_list.empty(); - lex->value_list.push_front($2, thd->mem_root); - lex->sql_command= SQLCOM_PURGE_BEFORE; + Lex->clause_that_disallows_subselect= NULL; + if (Lex->stmt_purge_before($6)) + MYSQL_YYABORT; } ; + /* kill threads */ kill: @@ -14778,8 +15154,16 @@ kill_expr: shutdown: SHUTDOWN { Lex->sql_command= SQLCOM_SHUTDOWN; } + shutdown_option {} ; +shutdown_option: + /* Empty */ { Lex->is_shutdown_wait_for_slaves= false; } + | WAIT_SYM FOR_SYM ALL SLAVES + { + Lex->is_shutdown_wait_for_slaves= true; + } + ; /* change database */ use: @@ -14787,7 +15171,7 @@ use: { LEX *lex=Lex; lex->sql_command=SQLCOM_CHANGE_DB; - lex->select_lex.db= $2; + lex->first_select_lex()->db= $2; } ; @@ -14804,6 +15188,9 @@ load: $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML"); MYSQL_YYABORT; } + if (Lex->main_select_push()) + MYSQL_YYABORT; + mysql_init_select(lex); } load_data_lock opt_local INFILE TEXT_STRING_filesystem { @@ -14835,6 +15222,9 @@ load: 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; Lex->mark_first_table_as_inserting(); } ; @@ -15035,11 +15425,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - /* - it is OK only emulate fix_fields, because we need only - value of constant - */ - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | HEX_STRING @@ -15048,7 +15433,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | BIN_NUM @@ -15061,7 +15445,6 @@ hex_or_bin_String: it is OK only emulate fix_fields, because we need only value of constant */ - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } ; @@ -15210,52 +15593,43 @@ NUM_literal: temporal_literal: DATE_SYM TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_DATE, - true)))) + if (unlikely(!($$= type_handler_newdate.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } | TIME_SYM TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_TIME, - true)))) + if (unlikely(!($$= type_handler_time2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } | TIMESTAMP TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_DATETIME, - true)))) + if (unlikely(!($$= type_handler_datetime2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } ; - -opt_with_clause: - /*empty */ { $$= 0; } - | with_clause - { - $$= $1; - } - ; - - with_clause: - WITH opt_recursive + WITH opt_recursive { + LEX *lex= Lex; With_clause *with_clause= new With_clause($2, Lex->curr_with_clause); if (unlikely(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(); @@ -15284,17 +15658,16 @@ with_list_element: MYSQL_YYABORT; Lex->with_column_list.empty(); } - AS '(' remember_tok_start subselect remember_tok_end ')' + AS '(' query_expression ')' { LEX *lex= thd->lex; const char *query_start= lex->sphead ? lex->sphead->m_tmp_query : thd->query(); - char *spec_start= $6 + 1; - With_element *elem= new With_element($1, *$2, $7->master_unit()); - if (unlikely(elem == NULL) || - unlikely(Lex->curr_with_clause->add_with_element(elem))) + const char *spec_start= $5.pos() + 1; + With_element *elem= new With_element($1, *$2, $6); + if (elem == NULL || Lex->curr_with_clause->add_with_element(elem)) MYSQL_YYABORT; - if (elem->set_unparsed_spec(thd, spec_start, $8, + if (elem->set_unparsed_spec(thd, spec_start, $7.pos(), spec_start - query_start)) MYSQL_YYABORT; } @@ -15630,11 +16003,9 @@ ident_or_text: user_maybe_role: ident_or_text { - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user = $1; - $$->host= null_clex_str; // User or Role, see get_current_user() - $$->reset_auth(); if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15643,10 +16014,9 @@ user_maybe_role: } | ident_or_text '@' ident_or_text { - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; - $$->reset_auth(); if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15676,8 +16046,7 @@ user_maybe_role: if (unlikely(!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_user; - $$->plugin= empty_clex_str; - $$->auth= empty_clex_str; + $$->auth= new (thd->mem_root) USER_AUTH(); } ; @@ -15977,6 +16346,7 @@ keyword_data_type: */ keyword_sp_var_and_label: ACTION + | ACCOUNT_SYM | ADDDATE_SYM | ADMIN_SYM | AFTER_SYM @@ -16060,6 +16430,7 @@ keyword_sp_var_and_label: | EXCEPTION_MARIADB_SYM | EXCHANGE_SYM | EXPANSION_SYM + | EXPIRE_SYM | EXPORT_SYM | EXTENDED_SYM | EXTENT_SIZE_SYM @@ -16152,6 +16523,7 @@ keyword_sp_var_and_label: | NAME_SYM | NEXT_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2 | NEXTVAL_SYM + | NEVER_SYM | NEW_SYM | NOCACHE_SYM | NOCYCLE_SYM @@ -16238,6 +16610,7 @@ keyword_sp_var_and_label: | SQL_BUFFER_RESULT | SQL_NO_CACHE_SYM | SQL_THREAD + | STAGE_SYM | STARTS_SYM | STATEMENT_SYM | STATUS_SYM @@ -16305,14 +16678,23 @@ set: SET { LEX *lex=Lex; + if (lex->main_select_push(true)) + MYSQL_YYABORT; lex->set_stmt_init(); lex->var_list.empty(); - sp_create_assignment_lex(thd, yychar == YYEMPTY); + if (sp_create_assignment_lex(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; } 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 @@ -16322,6 +16704,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 {} @@ -16333,7 +16718,8 @@ set_assign: LEX *lex=Lex; lex->set_stmt_init(); lex->var_list.empty(); - sp_create_assignment_lex(thd, yychar == YYEMPTY); + if(sp_create_assignment_lex(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; } set_expr_or_default { @@ -16346,7 +16732,8 @@ set_assign: LEX *lex=Lex; lex->set_stmt_init(); lex->var_list.empty(); - sp_create_assignment_lex(thd, yychar == YYEMPTY); + if (sp_create_assignment_lex(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; } set_expr_or_default { @@ -16366,7 +16753,8 @@ set_assign: } lex->set_stmt_init(); lex->var_list.empty(); - sp_create_assignment_lex(thd, yychar == YYEMPTY); + if (sp_create_assignment_lex(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; } set_expr_or_default { @@ -16436,7 +16824,8 @@ option_value_list_continued: /* Repeating list of option values after first option value. */ option_value_list: { - sp_create_assignment_lex(thd, yychar == YYEMPTY); + if (sp_create_assignment_lex(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; } option_value { @@ -16445,7 +16834,8 @@ option_value_list: } | option_value_list ',' { - sp_create_assignment_lex(thd, yychar == YYEMPTY); + if (sp_create_assignment_lex(thd, yychar == YYEMPTY)) + MYSQL_YYABORT; } option_value { @@ -16711,21 +17101,29 @@ opt_for_user: thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; lex->definer->user= current_user; - lex->definer->plugin= empty_clex_str; - lex->definer->auth= empty_clex_str; + lex->definer->auth= new (thd->mem_root) USER_AUTH(); } | FOR_SYM user equal { Lex->definer= $2; } ; text_or_password: - TEXT_STRING { Lex->definer->pwhash= $1;} - | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; } + TEXT_STRING + { + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->auth_str= $1; + } + | PASSWORD_SYM '(' TEXT_STRING ')' + { + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->pwtext= $3; + } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { - Lex->definer->pwtext= $3; - Lex->definer->pwhash.str= Item_func_password::alloc(thd, + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->pwtext= $3; + Lex->definer->auth->auth_str.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->pwhash.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + Lex->definer->auth->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -16795,7 +17193,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); @@ -16806,7 +17204,7 @@ table_lock: ? MDL_SHARED_WRITE : MDL_SHARED_NO_READ_WRITE; - if (unlikely(!Select-> + if (unlikely(!Lex->current_select_or_default()-> add_table_to_list(thd, $1, $2, table_options, lock_type, mdl_type))) MYSQL_YYABORT; @@ -16843,32 +17241,42 @@ 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 (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); lex->sql_command = SQLCOM_HA_OPEN; - if (unlikely(!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 (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); lex->sql_command = SQLCOM_HA_CLOSE; - if (unlikely(!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 (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); - lex->expr_allows_subselect= FALSE; + lex->clause_that_disallows_subselect= "HANDLER..READ"; 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); @@ -16877,15 +17285,24 @@ handler: lex->current_select->select_limit= one; lex->current_select->offset_limit= 0; lex->limit_rows_examined= 0; - if (unlikely(!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->clause_that_disallows_subselect= NULL; + 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 (unlikely(Lex->uses_stored_routines())) + if (lex->uses_stored_routines()) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "stored functions in HANDLER ... READ"); @@ -17083,7 +17500,7 @@ current_role: if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_role; - $$->reset_auth(); + $$->auth= NULL; } ; @@ -17100,7 +17517,7 @@ grant_role: MYSQL_YYABORT; $$->user= $1; $$->host= empty_clex_str; - $$->reset_auth(); + $$->auth= NULL; if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -17190,23 +17607,23 @@ require_list_element: SUBJECT_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->x509_subject)) + if (lex->account_options.x509_subject.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT")); - lex->x509_subject=$2.str; + lex->account_options.x509_subject= $2; } | ISSUER_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->x509_issuer)) + if (lex->account_options.x509_issuer.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER")); - lex->x509_issuer=$2.str; + lex->account_options.x509_issuer= $2; } | CIPHER_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->ssl_cipher)) + if (lex->account_options.ssl_cipher.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER")); - lex->ssl_cipher=$2.str; + lex->account_options.ssl_cipher= $2; } ; @@ -17214,7 +17631,7 @@ grant_ident: '*' { LEX *lex= Lex; - if (unlikely(lex->copy_db_to(&lex->current_select->db))) + if (unlikely(lex->copy_db_to(&lex->first_select_lex()->db))) MYSQL_YYABORT; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; @@ -17224,7 +17641,7 @@ grant_ident: | ident '.' '*' { LEX *lex= Lex; - lex->current_select->db= $1; + lex->first_select_lex()->db= $1; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; else if (unlikely(lex->columns.elements)) @@ -17233,7 +17650,7 @@ grant_ident: | '*' '.' '*' { LEX *lex= Lex; - lex->current_select->db= null_clex_str; + lex->first_select_lex()->db= null_clex_str; if (lex->grant == GLOBAL_ACLS) lex->grant= GLOBAL_ACLS & ~GRANT_ACL; else if (unlikely(lex->columns.elements)) @@ -17242,7 +17659,7 @@ grant_ident: | table_ident { LEX *lex=Lex; - if (unlikely(!lex->current_select-> + if (unlikely(!lex->first_select_lex()-> add_table_to_list(thd, $1,NULL, TL_OPTION_UPDATING))) MYSQL_YYABORT; @@ -17297,29 +17714,65 @@ grant_user: user IDENTIFIED_SYM BY TEXT_STRING { $$= $1; - $1->pwtext= $4; - if (unlikely(Lex->sql_command == SQLCOM_REVOKE)) - MYSQL_YYABORT; + $1->auth= new (thd->mem_root) USER_AUTH(); + $1->auth->pwtext= $4; } | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING { $$= $1; - $1->pwhash= $5; + $1->auth= new (thd->mem_root) USER_AUTH(); + $1->auth->auth_str= $5; } - | user IDENTIFIED_SYM via_or_with ident_or_text + | user IDENTIFIED_SYM via_or_with auth_expression { $$= $1; - $1->plugin= $4; - $1->auth= empty_clex_str; + $1->auth= $4; } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as TEXT_STRING_sys + | user_or_role + { + $$= $1; + } + ; + +auth_expression: + auth_token OR_SYM auth_expression + { + $$= $1; + DBUG_ASSERT($$->next == NULL); + $$->next= $3; + } + | auth_token { $$= $1; - $1->plugin= $4; - $1->auth= $6; } - | user_or_role - { $$= $1; } + ; + +auth_token: + ident_or_text opt_auth_str + { + $$= $2; + $$->plugin= $1; + } + ; + +opt_auth_str: + /* empty */ + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + } + | using_or_as TEXT_STRING_sys + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + $$->auth_str= $2; + } + | using_or_as PASSWORD_SYM '(' TEXT_STRING ')' + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + $$->pwtext= $4; + } ; opt_column_list: @@ -17328,7 +17781,7 @@ opt_column_list: LEX *lex=Lex; lex->grant |= lex->which_columns; } - | '(' column_list ')' + | '(' column_list ')' { } ; column_list: @@ -17369,52 +17822,47 @@ opt_require_clause: /* empty */ | REQUIRE_SYM require_list { - Lex->ssl_type=SSL_TYPE_SPECIFIED; + Lex->account_options.ssl_type= SSL_TYPE_SPECIFIED; } | REQUIRE_SYM SSL_SYM { - Lex->ssl_type=SSL_TYPE_ANY; + Lex->account_options.ssl_type= SSL_TYPE_ANY; } | REQUIRE_SYM X509_SYM { - Lex->ssl_type=SSL_TYPE_X509; + Lex->account_options.ssl_type= SSL_TYPE_X509; } | REQUIRE_SYM NONE_SYM { - Lex->ssl_type=SSL_TYPE_NONE; + Lex->account_options.ssl_type= SSL_TYPE_NONE; } ; resource_option: MAX_QUERIES_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.questions=$2; - lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR; + Lex->account_options.questions=$2; + Lex->account_options.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR; } | MAX_UPDATES_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.updates=$2; - lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR; + Lex->account_options.updates=$2; + Lex->account_options.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR; } | MAX_CONNECTIONS_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.conn_per_hour= $2; - lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR; + Lex->account_options.conn_per_hour= $2; + Lex->account_options.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR; } | MAX_USER_CONNECTIONS_SYM int_num { - LEX *lex=Lex; - lex->mqh.user_conn= $2; - lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; + Lex->account_options.user_conn= $2; + Lex->account_options.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; } | MAX_STATEMENT_TIME_SYM NUM_literal { - LEX *lex=Lex; - lex->mqh.max_statement_time= $2->val_real(); - lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; + Lex->account_options.max_statement_time= $2->val_real(); + Lex->account_options.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; } ; @@ -17463,8 +17911,8 @@ compound_statement: sp_proc_stmt_compound_ok { Lex->sql_command= SQLCOM_COMPOUND; - Lex->sphead->set_stmt_end(thd); - Lex->sphead->restore_thd_mem_root(thd); + if (Lex->sp_body_finalize_procedure(thd)) + MYSQL_YYABORT; } ; @@ -17551,214 +17999,27 @@ 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 (unlikely(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 (unlikely(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 (unlikely(Lex->add_select_to_union_list((bool)$2, $1, FALSE))) - MYSQL_YYABORT; - } - ; - union_option: /* empty */ { $$=1; } | DISTINCT { $$=1; } | ALL { $$=0; } ; -simple_table: - query_specification { $$= $1; } - | table_value_constructor { $$= $1; } - ; - -table_value_constructor: - VALUES - { - Lex->tvc_start(); - } - values_list - { - $$= Lex->current_select; - if (Lex->tvc_finalize()) - MYSQL_YYABORT; - } - ; - -/* - 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: - simple_table order_or_limit opt_select_lock_type { $$= $1; } - | '(' select_paren_derived ')' union_order_or_limit { $$= $2; } - ; - -query_term_union_ready: - simple_table 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 (unlikely(!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 (unlikely(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 subquery (and all the subsequent query blocks in a UNION) can - add columns to an outer query block. Reserve space for them. - Aggregate functions in having clause can also add fields to an - outer select. - */ - for (SELECT_LEX *temp= child->master_unit()->first_select(); - temp != NULL; temp= temp->next_select()) - { - lex->current_select->select_n_where_fields+= - temp->select_n_where_fields; - lex->current_select->select_n_having_items+= - temp->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 (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; YYPS->m_lock_type= TL_READ_HIGH_PRIORITY; YYPS->m_mdl_type= MDL_SHARED_READ; Select->options|= SELECT_HIGH_PRIORITY; @@ -17767,18 +18028,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 (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; - Select->options|= OPTION_BUFFER_RESULT; - } - | SQL_CALC_FOUND_ROWS - { - if (unlikely(Lex->check_simple_select(&$1))) - 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; } ; @@ -17811,9 +18062,7 @@ definer: DEFINER_SYM '=' user_or_role { Lex->definer= $3; - Lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - Lex->ssl_cipher= Lex->x509_subject= Lex->x509_issuer= 0; - bzero(&(Lex->mqh), sizeof(Lex->mqh)); + Lex->account_options.reset(); } ; @@ -17842,7 +18091,7 @@ view_suid: view_list_opt: /* empty */ {} - | '(' view_list ')' + | '(' view_list ')' { } ; view_list: @@ -17866,35 +18115,14 @@ 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; - 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; - trim_whitespace(thd->charset(), - &lex->create_view->select); - lex->create_view->check= $4; - lex->parsing_options.allows_variable= TRUE; - lex->current_select->set_with_clause($2); + if (Lex->parsed_create_view($2, $3)) + MYSQL_YYABORT; } ; -/* - 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 - | table_value_constructor - | table_value_constructor union_order_or_limit - | table_value_constructor union_list_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; } @@ -17971,7 +18199,8 @@ trigger_tail: (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($17); lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr(); - if (unlikely(!lex->make_sp_head(thd, $4, &sp_handler_trigger))) + if (unlikely(!lex->make_sp_head(thd, $4, &sp_handler_trigger, + DEFAULT_AGGREGATE))) MYSQL_YYABORT; lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); @@ -17979,15 +18208,9 @@ trigger_tail: sp_proc_stmt /* $19 */ { /* $20 */ LEX *lex= Lex; - sp_head *sp= lex->sphead; - if (unlikely(sp->check_unresolved_goto())) - MYSQL_YYABORT; lex->sql_command= SQLCOM_CREATE_TRIGGER; - sp->set_stmt_end(thd); - sp->restore_thd_mem_root(thd); - - if (unlikely(sp->is_not_allowed_in_function("trigger"))) + if (lex->sp_body_finalize_trigger(thd)) MYSQL_YYABORT; /* @@ -17995,11 +18218,10 @@ trigger_tail: sp_proc_stmt alternatives are not saving/restoring LEX, so lex->query_tables can be wiped out. */ - if (unlikely(!lex->select_lex. - add_table_to_list(thd, $10, (LEX_CSTRING*) 0, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_NO_WRITE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $10, (LEX_CSTRING*) 0, + TL_OPTION_UPDATING, TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; } ; @@ -18010,25 +18232,7 @@ trigger_tail: **************************************************************************/ -udf_tail: - opt_if_not_exists ident - RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys - { - LEX *lex= thd->lex; - if (unlikely(lex->add_create_options_with_check($1))) - MYSQL_YYABORT; - if (unlikely(is_native_function(thd, & $2))) - my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $2.str)); - lex->sql_command= SQLCOM_CREATE_FUNCTION; - lex->udf.name= $2; - lex->udf.returns= (Item_result) $4; - lex->udf.dl= $6.str; - } - ; - - sf_return_type: - RETURN_ORACLE_SYM { LEX *lex= Lex; lex->init_last_field(&lex->sphead->m_return_field_def, @@ -18043,79 +18247,44 @@ sf_return_type: } ; -sf_tail: - opt_if_not_exists - sp_name - { - Lex->sql_command= SQLCOM_CREATE_SPFUNCTION; - if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2, - &sp_handler_function))) - MYSQL_YYABORT; - } - opt_sp_parenthesized_fdparam_list - sf_return_type +sf_c_chistics_and_body_standalone: sp_c_chistics { LEX *lex= thd->lex; - Lex_input_stream *lip= YYLIP; - - lex->sphead->set_chistics(lex->sp_chistics); - lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); + lex->sphead->set_c_chistics(lex->sp_chistics); + lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); } sp_tail_is sp_body { if (unlikely(Lex->sp_body_finalize_function(thd))) MYSQL_YYABORT; - if (unlikely(Lex->sphead->m_flags & sp_head::HAS_AGGREGATE_INSTR)) - { - my_yyabort_error((ER_NOT_AGGREGATE_FUNCTION, MYF(0))); - } - Lex->sphead->set_chistics_agg_type(NOT_AGGREGATE); } ; -sp_tail: - opt_if_not_exists sp_name +sp_tail_standalone: + sp_name { - Lex->sql_command= SQLCOM_CREATE_PROCEDURE; - if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2, - &sp_handler_procedure))) + if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, + &sp_handler_procedure, + DEFAULT_AGGREGATE))) MYSQL_YYABORT; } opt_sp_parenthesized_pdparam_list sp_c_chistics { - Lex->sphead->set_chistics(Lex->sp_chistics); + Lex->sphead->set_c_chistics(Lex->sp_chistics); Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); } sp_tail_is sp_body + opt_sp_name { - if (unlikely(Lex->sp_body_finalize_procedure(thd))) + if (unlikely(Lex->sp_body_finalize_procedure_standalone(thd, $8))) MYSQL_YYABORT; } ; -sf_tail_standalone: - sf_tail opt_sp_name - { - if (unlikely($2 && !$2->eq(Lex->sphead))) - my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0), - ErrConvDQName($2).ptr(), - ErrConvDQName(Lex->sphead).ptr())); - } - ; - -sp_tail_standalone: - sp_tail opt_sp_name - { - if (unlikely($2 && !$2->eq(Lex->sphead))) - my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0), - ErrConvDQName($2).ptr(), - ErrConvDQName(Lex->sphead).ptr())); - } - ; opt_package_routine_end_name: /* Empty */ { $$= null_clex_str; } @@ -18229,35 +18398,27 @@ opt_migrate: ; install: - INSTALL_SYM PLUGIN_SYM ident SONAME_SYM TEXT_STRING_sys + INSTALL_SYM PLUGIN_SYM opt_if_not_exists ident SONAME_SYM TEXT_STRING_sys { - LEX *lex= Lex; - lex->sql_command= SQLCOM_INSTALL_PLUGIN; - lex->comment= $3; - lex->ident= $5; + if (Lex->stmt_install_plugin($3, $4, $6)) + MYSQL_YYABORT; } | INSTALL_SYM SONAME_SYM TEXT_STRING_sys { - LEX *lex= Lex; - lex->sql_command= SQLCOM_INSTALL_PLUGIN; - lex->comment= null_clex_str; - lex->ident= $3; + Lex->stmt_install_plugin($3); } ; uninstall: - UNINSTALL_SYM PLUGIN_SYM ident + UNINSTALL_SYM PLUGIN_SYM opt_if_exists ident { - LEX *lex= Lex; - lex->sql_command= SQLCOM_UNINSTALL_PLUGIN; - lex->comment= $3; + if (Lex->stmt_uninstall_plugin_by_name($3, $4)) + MYSQL_YYABORT; } - | UNINSTALL_SYM SONAME_SYM TEXT_STRING_sys + | UNINSTALL_SYM SONAME_SYM opt_if_exists TEXT_STRING_sys { - LEX *lex= Lex; - lex->sql_command= SQLCOM_UNINSTALL_PLUGIN; - lex->comment= null_clex_str; - lex->ident= $3; + if (Lex->stmt_uninstall_plugin_by_soname($3, $4)) + MYSQL_YYABORT; } ; |