diff options
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 2937 |
1 files changed, 1368 insertions, 1569 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e844c500b77..183a2504b70 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -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 @@ -491,96 +492,6 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, } /** - @brief Creates a new SELECT_LEX for a UNION branch. - - Sets up and initializes a SELECT_LEX structure for a query once the parser - discovers a UNION token. The current SELECT_LEX is pushed on the stack and - the new SELECT_LEX becomes the current one. - - @param lex The parser state. - - @param is_union_distinct True if the union preceding the new select - statement uses UNION DISTINCT. - - @param is_top_level This should be @c TRUE if the newly created SELECT_LEX - is a non-nested statement. - - @return <code>false</code> if successful, <code>true</code> if an error was - reported. In the latter case parsing should stop. - */ -bool LEX::add_select_to_union_list(bool is_union_distinct, - enum sub_select_type type, - bool is_top_level) -{ - const char *type_name= (type == INTERSECT_TYPE ? "INTERSECT" : - (type == EXCEPT_TYPE ? "EXCEPT" : "UNION")); - /* - Only the last SELECT can have INTO. Since the grammar won't allow INTO in - a nested SELECT, we make this check only when creating a top-level SELECT. - */ - if (is_top_level && result) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "INTO"); - return TRUE; - } - if (current_select->order_list.first && !current_select->braces) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "ORDER BY"); - return TRUE; - } - - if (current_select->explicit_limit && !current_select->braces) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "LIMIT"); - return TRUE; - } - if (current_select->linkage == GLOBAL_OPTIONS_TYPE) - { - thd->parse_error(); - return TRUE; - } - if (!is_union_distinct && (type == INTERSECT_TYPE || type == EXCEPT_TYPE)) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "ALL"); - return TRUE; - } - /* - Priority implementation, but also trying to keep things as flat - as possible */ - if (type == INTERSECT_TYPE && - (current_select->linkage != INTERSECT_TYPE && - current_select != current_select->master_unit()->first_select()) - && !(thd->variables.sql_mode & MODE_ORACLE)) - { - /* - This and previous SELECTs should go one level down because of - priority - */ - SELECT_LEX *prev= exclude_last_select(); - if (add_unit_in_brackets(prev)) - return TRUE; - return add_select_to_union_list(is_union_distinct, type, 0); - } - else - { - check_automatic_up(type); - } - /* This counter shouldn't be incremented for UNION parts */ - nest_level--; - if (mysql_new_select(this, 0, NULL)) - return TRUE; - mysql_init_select(this); - current_select->linkage= type; - current_select->with_all_modifier= !is_union_distinct; - if (is_union_distinct) /* UNION DISTINCT - remember position */ - current_select->master_unit()->union_distinct= current_select; - else - DBUG_ASSERT(type == UNION_TYPE); - return FALSE; -} - - -/** Create a separate LEX for each assignment if in SP. If we are in SP we want have own LEX for each assignment. @@ -621,6 +532,7 @@ void sp_create_assignment_lex(THD *thd, bool no_lookahead) lex->sphead->m_tmp_query= lip->get_tok_end(); /* Inherit from outer lex. */ lex->option_type= old_lex->option_type; + lex->main_select_push(); } } @@ -642,8 +554,6 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead) if (lex->sphead) { - sp_head *sp= lex->sphead; - if (!lex->var_list.is_empty()) { /* @@ -651,35 +561,38 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead) option setting, so we should construct sp_instr_stmt for it. */ - LEX_STRING qbuff; - sp_instr_stmt *i; Lex_input_stream *lip= &thd->m_parser_state->m_lip; - if (!(i= new (thd->mem_root) - sp_instr_stmt(sp->instructions(), lex->spcont, lex))) - return true; - /* Extract the query statement from the tokenizer. The end is either lip->ptr, if there was no lookahead, lip->tok_end otherwise. */ - if (no_lookahead) - qbuff.length= lip->get_ptr() - sp->m_tmp_query; - else - qbuff.length= lip->get_tok_end() - sp->m_tmp_query; - - if (!(qbuff.str= (char*) alloc_root(thd->mem_root, - qbuff.length + 5))) - return true; - - strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query, - qbuff.length); - qbuff.length+= 4; - i->m_query= qbuff; - if (sp->add_instr(i)) + static const LEX_CSTRING setsp= { STRING_WITH_LEN("SET ") }; + const char *qend= no_lookahead ? lip->get_ptr() : lip->get_tok_end(); + Lex_cstring qbuf(lex->sphead->m_tmp_query, qend); + if (lex->new_sp_instr_stmt(thd, setsp, qbuf)) return true; } + lex->pop_select(); + if (lex->check_main_unit_semantics()) + { + /* + "lex" can be referrenced by: + - sp_instr_set SET a= expr; + - sp_instr_set_row_field SET r.a= expr; + - sp_instr_stmt (just generated above) SET @a= expr; + In this case, "lex" is fully owned by sp_instr_xxx and it will + be deleted by the destructor ~sp_instr_xxx(). + So we should remove "lex" from the stack sp_head::m_lex, + to avoid double free. + Note, in case "lex" is not owned by any sp_instr_xxx, + it's also safe to remove it from the stack right now. + So we can remove it unconditionally, without testing lex->sp_lex_in_use. + */ + lex->sphead->restore_lex(thd); + return true; + } enum_var_type inner_option_type= lex->option_type; if (lex->sphead->restore_lex(thd)) return true; @@ -767,6 +680,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) return v; } + %} %union { int num; @@ -791,6 +705,20 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) 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; @@ -811,6 +739,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) 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; @@ -836,6 +765,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) 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; @@ -843,8 +773,9 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) st_trg_execution_order trg_execution_order; /* 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; @@ -877,6 +808,8 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) } %{ +/* avoid unintentional %union size increases, it's what a parser stack made of */ +static_assert(sizeof(YYSTYPE) == sizeof(void*)*2+8, "%union size check"); bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %} @@ -884,10 +817,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 52 shift/reduce conflicts. + Currently there are 48 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 52 +%expect 48 /* Comments for TOKENS. @@ -1044,6 +977,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 @@ -1106,6 +1042,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 */ @@ -1234,6 +1171,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 */ @@ -1351,6 +1289,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 @@ -1466,6 +1405,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 */ @@ -1589,6 +1529,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 @@ -1817,7 +1758,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 @@ -1882,7 +1824,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 @@ -1891,7 +1833,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 @@ -1931,7 +1873,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <item> literal insert_ident order_ident temporal_literal - simple_ident expr sum_expr in_sum_expr + simple_ident expr expr_no_subselect sum_expr in_sum_expr variable variable_aux bool_pri predicate bit_expr parenthesized_expr table_wild simple_expr column_default_non_parenthesized_expr udf_expr @@ -1972,6 +1914,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 @@ -2004,12 +1948,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 @@ -2030,6 +1973,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 @@ -2043,14 +1988,19 @@ 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_primary + query_primary_parens + select_into_query_specification + + +%type <select_lex_unit> + query_specification_start + query_expression_body + query_expression + query_expression_unit %type <boolfunc2creator> comp_op @@ -2062,11 +2012,28 @@ 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 + order_or_limit + 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 @@ -2082,7 +2049,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 @@ -2106,18 +2073,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 - statement sp_suid + 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 create_aggregate_function_tail + trigger_tail sp_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 @@ -2126,6 +2091,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 @@ -2158,6 +2124,8 @@ END_OF_INPUT %type <view_suid> view_suid opt_view_suid %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 @@ -2243,8 +2211,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; @@ -2298,6 +2266,7 @@ statement: alter | analyze | analyze_stmt_command + | backup | binlog_base64_event | call | change @@ -2340,6 +2309,7 @@ statement: | rollback | savepoint | select + | select_into | set | signal_stmt | show @@ -2357,9 +2327,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); } ; @@ -2369,72 +2337,59 @@ deallocate_or_drop: ; prepare: - PREPARE_SYM ident FROM prepare_src + PREPARE_SYM ident FROM expr_no_subselect { - 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; + if (Lex->stmt_prepare($2, $4)) + MYSQL_YYABORT; } ; -prepare_src: +expr_no_subselect: { Lex->expr_allows_subselect= false; } expr { - Lex->prepared_stmt_code= $2; Lex->expr_allows_subselect= true; + $$= $2; } ; 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_using - {} - | EXECUTE_SYM IMMEDIATE_SYM prepare_src + | EXECUTE_SYM IMMEDIATE_SYM expr_no_subselect execute_using { - 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($3, $4)) + MYSQL_YYABORT; } - execute_using - {} ; execute_using: - /* nothing */ + /* nothing */ { $$= NULL; } | USING { Lex->expr_allows_subselect= false; } - execute_var_list + execute_params { - if (unlikely(Lex->table_or_sp_used())) - my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), - "EXECUTE..USING")); + $$= $3; Lex->expr_allows_subselect= true; } ; -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: @@ -2693,19 +2648,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(); /* @@ -2720,12 +2680,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(); @@ -2733,10 +2695,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; /* @@ -2759,8 +2720,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; } @@ -2773,46 +2735,70 @@ 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; Lex->create_info.used_fields= 0; + if (Lex->main_select_push()) + MYSQL_YYABORT; } opt_create_database_options { @@ -2821,61 +2807,95 @@ create: $1 | $3))) MYSQL_YYABORT; lex->name= $4; + Lex->pop_select(); //main select } | create_or_replace definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident { - if (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))) MYSQL_YYABORT; + if (Lex->main_select_push()) + 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 - { } + { + 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 { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->create_info.set($1); } - sf_tail_not_aggregate - { } - | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM + event_tail { - Lex->create_info.set($1); + Lex->pop_select(); //main select } - sf_tail_aggregate - { } - | create_or_replace no_definer FUNCTION_SYM - { Lex->create_info.set($1); } - create_function_tail - { } - | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM + | create_or_replace definer opt_aggregate FUNCTION_SYM opt_if_not_exists + sp_name '(' { - Lex->create_info.set($1); + if (Lex->stmt_create_stored_function_start($1 | $5, $3, $6)) + MYSQL_YYABORT; } - create_aggregate_function_tail - { } - | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list - opt_require_clause opt_resource_options + sp_fdparam_list ')' + sf_return_type + sf_c_chistics_and_body + { + Lex->stmt_create_routine_finalize(); + } + | 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 ')' + sf_return_type + sf_c_chistics_and_body + { + Lex->stmt_create_routine_finalize(); + } + | 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))) @@ -2901,36 +2921,6 @@ create: { } ; -sf_tail_not_aggregate: - sf_tail - { - 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); - } - -sf_tail_aggregate: - sf_tail - { - if (unlikely(!(Lex->sphead->m_flags & sp_head::HAS_AGGREGATE_INSTR))) - { - my_yyabort_error((ER_INVALID_AGGREGATE_FUNCTION, MYF(0))); - } - Lex->sphead->set_chistics_agg_type(GROUP_AGGREGATE); - } - -create_function_tail: - sf_tail_not_aggregate { } - | udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; } - ; - -create_aggregate_function_tail: - sf_tail_aggregate - { } - | udf_tail { Lex->udf.type= UDFTYPE_AGGREGATE; } - ; opt_sequence: /* empty */ { } | sequence_defs @@ -3251,20 +3241,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; } ; @@ -3276,13 +3263,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 { @@ -3321,7 +3311,7 @@ sp_chistic: | MODIFIES_SYM SQL_SYM DATA_SYM { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; } | sp_suid - {} + { Lex->sp_chistics.suid= $1; } ; /* Create characteristics */ @@ -3331,14 +3321,8 @@ sp_c_chistic: ; sp_suid: - SQL_SYM SECURITY_SYM DEFINER_SYM - { - Lex->sp_chistics.suid= SP_IS_SUID; - } - | SQL_SYM SECURITY_SYM INVOKER_SYM - { - Lex->sp_chistics.suid= SP_IS_NOT_SUID; - } + SQL_SYM SECURITY_SYM DEFINER_SYM { $$= SP_IS_SUID; } + | SQL_SYM SECURITY_SYM INVOKER_SYM { $$= SP_IS_NOT_SUID; } ; call: @@ -3375,7 +3359,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: @@ -3449,18 +3444,6 @@ sp_opt_inout: | INOUT_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: '(' { @@ -3528,12 +3511,8 @@ optionally_qualified_column_ident: row_field_name: ident { - 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); } ; @@ -3544,17 +3523,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; } ; @@ -3801,7 +3775,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; } ; @@ -3987,6 +3961,7 @@ statement_information_item: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + ; simple_target_specification: ident_cli @@ -4043,6 +4018,7 @@ condition_information_item: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + ; condition_information_item_name: CLASS_ORIGIN_SYM @@ -4172,44 +4148,8 @@ sp_proc_stmt_statement: } 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; } ; @@ -4343,7 +4283,7 @@ 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))) + if ($$->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4352,6 +4292,7 @@ for_loop_bound_expr: assignment_source_lex { Lex->sphead->reset_lex(thd, $1); + Lex->current_select->parsing_place= FOR_LOOP_BOUND; } expr { @@ -4361,6 +4302,7 @@ for_loop_bound_expr: $$->set_item_and_free_list($3, NULL); if (unlikely($$->sphead->restore_lex(thd))) MYSQL_YYABORT; + Lex->current_select->parsing_place= NO_MATTER; } ; @@ -4413,15 +4355,8 @@ sp_proc_stmt_fetch: sp_proc_stmt_fetch_head sp_fetch_list { } | FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - lex->sphead->m_flags|= sp_head::HAS_AGGREGATE_INSTR; - sp_instr_agg_cfetch *i= - new (thd->mem_root) sp_instr_agg_cfetch(sp->instructions(), - lex->spcont); - if (unlikely(i == NULL) || - unlikely(sp->add_instr(i))) - MYSQL_YYABORT; + if (unlikely(Lex->sp_add_agg_cfetch())) + MYSQL_YYABORT; } ; @@ -4594,7 +4529,8 @@ case_stmt_body: { if (unlikely(Lex->case_stmt_action_expr($2))) MYSQL_YYABORT; - if (unlikely(Lex->sphead->restore_lex(thd))) + + if (Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } simple_when_clause_list @@ -4793,7 +4729,7 @@ while_body: LEX *lex= Lex; if (unlikely(lex->sp_while_loop_expression(thd, $1))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } sp_proc_stmts1 END WHILE_SYM @@ -4816,7 +4752,7 @@ repeat_body: if (unlikely(i == NULL) || unlikely(lex->sphead->add_instr(i))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; /* We can shortcut the cont_backpatch here */ i->m_cont_dest= ip+1; @@ -5296,26 +5232,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. */ @@ -5325,7 +5251,7 @@ create_body: create_like: LIKE table_ident { $$= $2; } - | '(' LIKE table_ident ')' { $$= $3; } + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; } ; opt_create_select: @@ -5334,23 +5260,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_body ')' { - 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: @@ -5433,13 +5355,17 @@ partition_entry: thd->parse_error(ER_PARTITION_ENTRY_ERROR); MYSQL_YYABORT; } - DBUG_ASSERT(Lex->part_info->table); + if (Lex->main_select_push()) + MYSQL_YYABORT; /* We enter here when opening the frm file to translate partition info string into part_info data structure. */ } - partition {} + partition + { + Lex->pop_select(); //main select + } ; partition: @@ -6088,56 +6014,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 {} @@ -6365,7 +6241,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 ')' { @@ -6374,8 +6250,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 @@ -6478,7 +6354,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; } } @@ -6565,6 +6441,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 @@ -6575,6 +6458,7 @@ field_list_item: | key_def | constraint_def | period_for_system_time + | PERIOD_SYM period_for_application_time { } ; column_def: @@ -6671,7 +6555,7 @@ key_def: constraint_def: opt_constraint check_constraint { - Lex->add_constraint(&$1, $2, FALSE); + Lex->add_constraint($1, $2, FALSE); } ; @@ -6680,7 +6564,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; } ; @@ -6867,6 +6759,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 { @@ -6874,14 +6768,15 @@ parse_vcol_expr: if (unlikely(!v)) MYSQL_YYABORT; Lex->last_field->vcol_info= v; + Lex->pop_select(); //main select } ; parenthesized_expr: - subselect + remember_tok_start + query_expression { - $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1); - if (unlikely($$ == NULL)) + if (!($$= Lex->create_item_query_expression(thd, $1, $2))) MYSQL_YYABORT; } | expr @@ -7135,7 +7030,7 @@ field_type_lob: | JSON_SYM opt_compressed { Lex->charset= &my_charset_utf8mb4_bin; - $$.set(&type_handler_long_blob); + $$.set(&type_handler_json_longtext); } ; @@ -7236,10 +7131,12 @@ field_length: opt_field_length: /* empty */ { $$= (char*) 0; /* use default length */ } | field_length { $$= $1; } + ; opt_field_length_default_1: /* empty */ { $$= (char*) "1"; } | field_length { $$= $1; } + ; opt_precision: /* empty */ { $$.set(0, 0); } @@ -7725,12 +7622,14 @@ fulltext_key_opts: opt_USING_key_algorithm: /* Empty*/ { $$= HA_KEY_ALG_UNDEF; } | USING btree_or_rtree { $$= $2; } + ; /* TYPE is a valid identifier, so it's handled differently than USING */ opt_key_algorithm_clause: /* Empty*/ { $$= HA_KEY_ALG_UNDEF; } | USING btree_or_rtree { $$= $2; } | TYPE_SYM btree_or_rtree { $$= $2; } + ; key_using_alg: USING btree_or_rtree @@ -7853,23 +7752,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(); } alter_commands @@ -7881,11 +7782,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()) + MYSQL_YYABORT; } create_database_options { @@ -7895,6 +7799,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 { @@ -7910,6 +7815,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 @@ -7918,6 +7825,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 { @@ -7925,6 +7835,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 @@ -7933,14 +7845,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 @@ -7948,14 +7869,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 @@ -7987,6 +7916,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 { @@ -8016,7 +7947,7 @@ alter: } OPTIONS_SYM '(' server_options_list ')' { } /* ALTER USER foo is allowed for MySQL compatibility. */ | ALTER opt_if_exists USER_SYM 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($2); Lex->sql_command= SQLCOM_ALTER_USER; @@ -8030,16 +7961,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 @@ -8048,6 +7980,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)); } ; @@ -8196,22 +8164,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; } ; @@ -8335,6 +8288,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; @@ -8349,7 +8309,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 @@ -8445,9 +8405,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)) || @@ -8468,7 +8428,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 { @@ -8499,6 +8459,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: @@ -8507,6 +8475,7 @@ opt_index_lock_algorithm: | alter_algorithm_option | alter_lock_option alter_algorithm_option | alter_algorithm_option alter_lock_option + ; alter_algorithm_option: ALGORITHM_SYM opt_equal DEFAULT @@ -8565,7 +8534,7 @@ alter_option: Lex->alter_info.requested_lock= Alter_info::ALTER_TABLE_LOCK_NONE; } - + ; opt_restrict: /* empty */ { Lex->drop_mode= DROP_DEFAULT; } @@ -8832,6 +8801,7 @@ persistent_stat_spec: {} | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec {} + ; persistent_column_stat_spec: ALL {} @@ -9146,8 +9116,8 @@ adm_partition: cache_keys_spec: { - Lex->select_lex.alloc_index_hints(thd); - Select->set_index_hint_type(INDEX_HINT_USE, + Lex->first_select_lex()->alloc_index_hints(thd); + Select->set_index_hint_type(INDEX_HINT_USE, INDEX_HINT_MASK_ALL); } cache_key_list_or_empty @@ -9168,227 +9138,213 @@ opt_ignore_leaves: Select : retrieve data from table */ - select: - opt_with_clause select_init + query_expression_body { - LEX *lex= Lex; - lex->sql_command= SQLCOM_SELECT; - lex->current_select->set_with_clause($1); - } - ; - -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: - { - Lex->current_select->set_braces(true); + if (Lex->push_select($1->fake_select_lex ? + $1->fake_select_lex : + $1->first_select())) + MYSQL_YYABORT; } - table_value_constructor select_part3 + opt_procedure_or_into { - DBUG_ASSERT(Lex->current_select->braces); + Lex->pop_select(); + if (Lex->select_finalize($1, $3)) + MYSQL_YYABORT; } - | + | with_clause query_expression_body { - /* - 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->fake_select_lex ? + $2->fake_select_lex : + $2->first_select())) + MYSQL_YYABORT; } - SELECT_SYM select_options_and_item_list select_part3 - opt_select_lock_type + opt_procedure_or_into { - DBUG_ASSERT(Lex->current_select->braces); + Lex->pop_select(); + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + if (Lex->select_finalize($2, $4)) + 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 - ; -select_paren_union_query_term: +select_into: + 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($1)) + MYSQL_YYABORT; } - select_parent_union_query_term_proper + opt_order_limit_lock { - DBUG_ASSERT(Lex->current_select->braces); - } - | '(' select_paren_union_query_term ')' - ; + st_select_lex_unit *unit; + if (!(unit= Lex->parsed_body_select($1, $3))) + MYSQL_YYABORT; + if (Lex->select_finalize(unit)) + MYSQL_YYABORT; + } + ; -select_parent_view_proper: - SELECT_SYM select_options_and_item_list select_part3_view - opt_select_lock_type - | table_value_constructor select_part3_view + +simple_table: + query_specification { $$= $1; } + | table_value_constructor { $$= $1; } ; -select_paren_view: +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_view_proper + select_options { - DBUG_ASSERT(Lex->current_select->braces); + Select->parsing_place= SELECT_LIST; } - | '(' select_paren_view ')' - ; + select_item_list + { + Select->parsing_place= NO_MATTER; + } + ; -/* The equivalent of select_paren for nested queries. */ -select_paren_derived: +query_specification: + query_specification_start + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_window_clause { - Lex->current_select->set_braces(true); + $$= Lex->pop_select(); } - table_value_constructor + ; + +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->current_select->master_unit()->first_select(); + $$= Lex->pop_select(); } - | + ; + +opt_from_clause: + /* Empty */ + | from_clause + ; + + +query_primary: + simple_table + { $$= $1; } + | query_primary_parens + { $$= $1; } + ; + +query_primary_parens: + '(' query_expression_unit { - Lex->current_select->set_braces(true); + if (Lex->parsed_unit_in_brackets($2)) + MYSQL_YYABORT; } - SELECT_SYM select_part2_derived - opt_table_expression - opt_order_clause - opt_limit_clause - opt_select_lock_type + query_expression_tail ')' { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + $$= Lex->parsed_unit_in_brackets_tail($2, $4); } - | '(' select_paren_derived ')' { $$= $2; } - ; - -select_init3: - opt_table_expression - opt_select_lock_type + | '(' query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + Lex->push_select($2); } - union_clause - | select_part3_union_not_ready - opt_select_lock_type + query_expression_tail ')' { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_in_brackets($2, $4))) + YYABORT; } ; - -select_init3_union_query_term: - opt_table_expression - opt_select_lock_type +query_expression_unit: + query_primary + unit_type_decl + query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type, + $2.distinct))) + YYABORT; } - union_clause - | select_part3_union_not_ready_noproc - opt_select_lock_type + | query_expression_unit + unit_type_decl + query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type, + $2.distinct, FALSE))) + YYABORT; } ; - -select_init3_view: - opt_table_expression opt_select_lock_type +query_expression_body: + query_primary { - Lex->current_select->set_braces(false); + Lex->push_select($1); } - | opt_table_expression opt_select_lock_type + query_expression_tail { - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_body_select($1, $3))) + MYSQL_YYABORT; } - union_list_view - | order_or_limit opt_select_lock_type + | query_expression_unit { - Lex->current_select->set_braces(false); + if (Lex->parsed_body_unit($1)) + MYSQL_YYABORT; } - | table_expression order_or_limit opt_select_lock_type + query_expression_tail { - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_body_unit_tail($1, $3))) + MYSQL_YYABORT; } ; -/* - The SELECT parts after select_item_list that cannot be followed by UNION. -*/ - -select_part3: - opt_table_expression - | select_part3_union_not_ready - ; - -select_part3_union_query_term: - opt_table_expression - | select_part3_union_not_ready_noproc - ; - -select_part3_view: - opt_table_expression - | order_or_limit - | table_expression order_or_limit - ; - -select_part3_union_not_ready: - select_part3_union_not_ready_noproc - | table_expression procedure_clause - | table_expression order_or_limit procedure_clause - ; - -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 - ; - -select_options_and_item_list: +query_expression: + opt_with_clause + query_expression_body { - 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) + { + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + } + $$= $2; } - select_options select_item_list + ; + +subselect: + remember_tok_start + query_expression { - Select->parsing_place= NO_MATTER; + if (!($$= Lex->parsed_subselect($2, $1))) + YYABORT; } ; @@ -9396,18 +9352,6 @@ select_options_and_item_list: /** <table expression>, as in the SQL standard. */ -table_expression: - from_clause - opt_where_clause - opt_group_clause - opt_having_clause - opt_window_clause - ; - -opt_table_expression: - /* Empty */ - | table_expression - ; from_clause: FROM table_reference_list @@ -9456,8 +9400,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_datetime.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true))) MYSQL_YYABORT; $$= Vers_history_point(VERS_TIMESTAMP, item); } @@ -9471,6 +9416,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 */ { @@ -9510,59 +9482,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 @@ -9641,13 +9622,13 @@ select_alias: opt_default_time_precision: /* empty */ { $$= NOT_FIXED_DEC; } | '(' ')' { $$= NOT_FIXED_DEC; } - | '(' real_ulong_num ')' { $$= $2; }; + | '(' real_ulong_num ')' { $$= $2; } ; opt_time_precision: /* empty */ { $$= 0; } | '(' ')' { $$= 0; } - | '(' real_ulong_num ')' { $$= $2; }; + | '(' real_ulong_num ')' { $$= $2; } ; optional_braces: @@ -10152,6 +10133,7 @@ dyncall_create_element: else $$->len= 0; } + ; dyncall_create_list: dyncall_create_element @@ -10234,7 +10216,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 ')' { @@ -10413,7 +10409,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; } @@ -11392,6 +11388,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: @@ -11632,7 +11643,7 @@ opt_gconcat_separator: opt_gorder_clause: /* empty */ - | ORDER_SYM BY gorder_list; + | ORDER_SYM BY gorder_list ; gorder_list: @@ -11746,6 +11757,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: @@ -11756,9 +11771,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 @@ -11870,10 +11883,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); } ; @@ -11892,11 +11910,18 @@ join_table: left-associative joins. */ table_ref normal_join table_ref %prec TABLE_REF_PRIORITY - { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; } + { + MYSQL_YYABORT_UNLESS($1 && ($$=$3)); + Select->add_joined_table($1); + Select->add_joined_table($3); + $3->straight=$2; + } | table_ref normal_join table_ref ON { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $3))) MYSQL_YYABORT; @@ -11913,6 +11938,8 @@ join_table: USING { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); } '(' using_list ')' { @@ -11923,6 +11950,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); } @@ -11932,6 +11961,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; @@ -11948,6 +11979,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 ')' { @@ -11958,6 +11991,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; @@ -11968,6 +12003,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; @@ -11985,6 +12022,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 ')' { @@ -11996,6 +12035,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()))) @@ -12028,241 +12069,59 @@ 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_opt_parens { $$= $1; } + | table_primary_derived_opt_parens { $$= $1; } + | join_table_parens { $$= $1; } + | table_reference_list_parens { $$= $1; } ; -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; - TABLE_LIST *tl= $$; - Select->add_joined_table(tl); - if ($4) - tl->vers_conditions= Lex->vers_conditions; - } +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; @@ -12270,83 +12129,54 @@ 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: - { - LEX *lex= Lex; - lex->derived_tables|= DERIVED_SUBQUERY; - if (unlikely(!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE)) - { - thd->parse_error(); - 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 - ; +/* + 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> -get_select_lex: - /* Empty */ { $$= Select; } - ; + <derived table> ::= <table subquery> + <table subquery> ::= <subquery> + <subquery> ::= <left paren> <query expression> <right paren> + <query expression> ::= [ <with clause> ] <query expression body> -get_select_lex_derived: - get_select_lex + 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: + query_primary_parens opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - if (unlikely($1->init_nested_join(lex->thd))) - MYSQL_YYABORT; + if (!($$= Lex->parsed_derived_select($1, $2, $3))) + YYABORT; } - ; - -select_derived_init: + | '(' + query_expression + ')' opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - - TABLE_LIST *embedding= lex->current_select->embedding; - $$= embedding && - !embedding->nested_join->join_list.elements; - /* return true if we are deeply nested */ + if (!($$= Lex->parsed_derived_unit($2, $4, $5))) + YYABORT; } ; @@ -12480,9 +12310,14 @@ 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)) @@ -12578,7 +12413,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; @@ -12595,7 +12430,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; @@ -12647,6 +12482,7 @@ opt_window_ref: if (unlikely(thd->lex->win_ref == NULL)) MYSQL_YYABORT; } + ; opt_window_partition_clause: /* empty */ { } @@ -12655,7 +12491,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: @@ -12781,70 +12617,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: @@ -12854,63 +12655,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= 0; 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; } ; @@ -12955,6 +12755,7 @@ limit_rows_option: LEX *lex=Lex; lex->limit_rows_examined= $1; } + ; delete_limit_clause: /* empty */ @@ -12973,6 +12774,77 @@ delete_limit_clause: | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; } ; +opt_order_limit_lock: + /* empty */ + { $$= NULL; } + | 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; + } + ; +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 */ | '+' @@ -12981,6 +12853,7 @@ opt_plus: int_num: opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); } | '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); } + ; ulong_num: opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } @@ -13004,7 +12877,7 @@ longlong_num: | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); } | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); } | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); } - + ; ulonglong_num: opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); } @@ -13041,15 +12914,13 @@ bool: ulong_num { $$= $1 != 0; } | TRUE_SYM { $$= 1; } | FALSE_SYM { $$= 0; } - + ; procedure_clause: PROCEDURE_SYM ident /* Procedure name */ { 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; @@ -13069,6 +12940,7 @@ procedure_clause: parameters are reduced. */ Lex->expr_allows_subselect= false; + Select->options|= OPTION_PROCEDURE_CLAUSE; } '(' procedure_list ')' { @@ -13152,6 +13024,7 @@ select_outvar: into: INTO into_destination + {} ; into_destination: @@ -13345,10 +13218,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; } ; @@ -13421,17 +13295,24 @@ 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; + } ; replace: @@ -13440,15 +13321,22 @@ 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; + } ; insert_lock_option: @@ -13488,18 +13376,21 @@ 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; - }; + } + ; insert_field_spec: insert_values {} - | '(' ')' insert_values {} - | '(' fields ')' insert_values {} + | insert_field_list insert_values {} | SET { LEX *lex=Lex; @@ -13507,20 +13398,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: @@ -13664,23 +13568,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), @@ -13694,7 +13618,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: @@ -13738,12 +13669,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 ; @@ -13764,6 +13696,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 } ; @@ -13782,12 +13715,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); @@ -13798,6 +13744,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 { @@ -13809,6 +13758,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; } ; @@ -13877,9 +13829,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; } @@ -13964,6 +13916,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(); @@ -13971,6 +13925,7 @@ show: show_param { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } ; @@ -13986,40 +13941,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 @@ -14068,12 +14023,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; @@ -14115,13 +14071,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; @@ -14183,7 +14139,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; } @@ -14191,7 +14147,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; } @@ -14199,7 +14155,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; } @@ -14416,7 +14372,7 @@ describe: 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; @@ -14430,12 +14386,13 @@ describe: 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 @@ -14456,6 +14413,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 {} ; @@ -14498,8 +14457,7 @@ flush: lex->type= 0; lex->no_write_to_binlog= $2; } - flush_options - {} + flush_options {} ; flush_options: @@ -14516,6 +14474,7 @@ flush_options: opt_table_list opt_flush_lock {} | flush_options_list + {} ; opt_flush_lock: @@ -14601,6 +14560,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; @@ -14622,6 +14583,37 @@ 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 table_ident + { + if (unlikely(!Select->add_table_to_list(thd, $2, NULL, 0, + TL_READ, MDL_SHARED_HIGH_PRIO))) + MYSQL_YYABORT; + Lex->sql_command= SQLCOM_BACKUP_LOCK; + } + | 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 ')' @@ -14652,6 +14644,7 @@ delete_domain_id: optional_flush_tables_arguments: /* empty */ {$$= 0;} | AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; } + ; reset: RESET_SYM @@ -14695,34 +14688,18 @@ 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 expr_no_subselect { - LEX *lex= Lex; - lex->value_list.empty(); - lex->value_list.push_front($2, thd->mem_root); - lex->sql_command= SQLCOM_PURGE_BEFORE; + if (Lex->stmt_purge_before($5)) + MYSQL_YYABORT; } ; + /* kill threads */ kill: @@ -14744,6 +14721,7 @@ kill_type: /* Empty */ { $$= (int) KILL_HARD_BIT; } | HARD_SYM { $$= (int) KILL_HARD_BIT; } | SOFT_SYM { $$= 0; } + ; kill_option: /* empty */ { $$= (int) KILL_CONNECTION; } @@ -14771,6 +14749,15 @@ 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 */ @@ -14780,7 +14767,7 @@ use: { LEX *lex=Lex; lex->sql_command=SQLCOM_CHANGE_DB; - lex->select_lex.db= $2; + lex->first_select_lex()->db= $2; } ; @@ -14790,7 +14777,6 @@ load: LOAD data_or_xml { LEX *lex= thd->lex; - mysql_init_select(lex); if (unlikely(lex->sphead)) { @@ -14798,6 +14784,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 { @@ -14828,7 +14817,11 @@ load: opt_xml_rows_identified_by opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec opt_load_data_set_spec - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; data_or_xml: @@ -15026,11 +15019,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 @@ -15039,7 +15027,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | BIN_NUM @@ -15052,7 +15039,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); } ; @@ -15201,26 +15187,23 @@ 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_datetime.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } ; @@ -15236,17 +15219,21 @@ opt_with_clause: with_clause: - WITH opt_recursive + WITH opt_recursive { + LEX *lex= Lex; With_clause *with_clause= new With_clause($2, Lex->curr_with_clause); if (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(); @@ -15275,15 +15262,14 @@ with_list_element: MYSQL_YYABORT; Lex->with_column_list.empty(); } - AS '(' remember_tok_start subselect remember_tok_end ')' + AS '(' remember_tok_start query_expression remember_tok_end ')' { 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))) + With_element *elem= new With_element($1, *$2, $7); + if (elem == NULL || Lex->curr_with_clause->add_with_element(elem)) MYSQL_YYABORT; if (elem->set_unparsed_spec(thd, spec_start, $8, spec_start - query_start)) @@ -15597,11 +15583,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, @@ -15610,10 +15594,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, @@ -15643,8 +15626,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(); } ; @@ -15930,6 +15912,7 @@ keyword_data_type: */ keyword_sp_var_and_label: ACTION + | ACCOUNT_SYM | ADDDATE_SYM | ADMIN_SYM | AFTER_SYM @@ -16013,6 +15996,7 @@ keyword_sp_var_and_label: | EXCEPTION_MARIADB_SYM | EXCHANGE_SYM | EXPANSION_SYM + | EXPIRE_SYM | EXPORT_SYM | EXTENDED_SYM | EXTENT_SIZE_SYM @@ -16103,6 +16087,7 @@ keyword_sp_var_and_label: | MYSQL_SYM | MYSQL_ERRNO_SYM | NAME_SYM + | NEVER_SYM | NEXT_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2 | NEXTVAL_SYM | NEW_SYM @@ -16191,6 +16176,7 @@ keyword_sp_var_and_label: | SQL_BUFFER_RESULT | SQL_NO_CACHE_SYM | SQL_THREAD + | STAGE_SYM | STARTS_SYM | STATEMENT_SYM | STATUS_SYM @@ -16259,14 +16245,22 @@ set: SET { LEX *lex=Lex; + if (lex->main_select_push()) + MYSQL_YYABORT; lex->set_stmt_init(); lex->var_list.empty(); sp_create_assignment_lex(thd, yychar == YYEMPTY); } start_option_value_list - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | SET STATEMENT_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->set_stmt_init(); } set_stmt_option_value_following_option_type_list @@ -16276,6 +16270,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 {} @@ -16615,21 +16612,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; } ; @@ -16699,7 +16704,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); @@ -16747,27 +16752,37 @@ 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)) @@ -16781,15 +16796,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->expr_allows_subselect= TRUE; + if (!lex->current_select->explicit_limit) + { + Item *one= new (thd->mem_root) Item_int(thd, (int32) 1); + if (one == NULL) + MYSQL_YYABORT; + lex->current_select->select_limit= one; + lex->current_select->offset_limit= 0; + lex->limit_rows_examined= 0; + } /* Stored functions are not supported for HANDLER READ. */ - if (unlikely(Lex->uses_stored_routines())) + if (lex->uses_stored_routines()) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "stored functions in HANDLER ... READ"); @@ -16959,12 +16983,14 @@ grant_command: ; opt_with_admin: - /* nothing */ { Lex->definer = 0; } - | WITH ADMIN_SYM user_or_role { Lex->definer = $3; } + /* nothing */ { Lex->definer = 0; } + | WITH ADMIN_SYM user_or_role { Lex->definer = $3; } + ; opt_with_admin_option: - /* nothing */ { Lex->with_admin_option= false; } - | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; } + /* nothing */ { Lex->with_admin_option= false; } + | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; } + ; role_list: grant_role @@ -16985,7 +17011,7 @@ current_role: if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_role; - $$->reset_auth(); + $$->auth= NULL; } ; @@ -17002,7 +17028,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, @@ -17092,23 +17118,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; } ; @@ -17199,31 +17225,67 @@ 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; - $1->plugin= $4; - $1->auth= $6; } - | user_or_role - { $$= $1; } ; +auth_expression: + auth_token OR_SYM auth_expression + { + $$= $1; + DBUG_ASSERT($$->next == NULL); + $$->next= $3; + } + | auth_token + { + $$= $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: /* empty */ { @@ -17271,52 +17333,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; } ; @@ -17365,8 +17422,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; } ; @@ -17453,214 +17510,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; @@ -17668,18 +17538,8 @@ query_expression_option: | DISTINCT { 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; } ; @@ -17712,9 +17572,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(); } ; @@ -17767,35 +17625,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; } @@ -17872,7 +17709,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()); @@ -17880,13 +17718,9 @@ trigger_tail: sp_proc_stmt /* $19 */ { /* $20 */ LEX *lex= Lex; - sp_head *sp= lex->sphead; 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; /* @@ -17894,11 +17728,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; } ; @@ -17909,22 +17742,6 @@ 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: RETURNS_SYM @@ -17942,24 +17759,12 @@ 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; - } - sp_parenthesized_fdparam_list - sf_return_type +sf_c_chistics_and_body: 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_proc_stmt_in_returns_clause { @@ -17968,18 +17773,19 @@ sf_tail: } ; + sp_tail: - opt_if_not_exists sp_name + 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; } 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_proc_stmt @@ -18091,44 +17897,37 @@ 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; } ; /* Avoid compiler warning from sql_yacc.cc where yyerrlab1 is not used */ keep_gcc_happy: - IMPOSSIBLE_ACTION - { - YYERROR; - } + IMPOSSIBLE_ACTION + { + YYERROR; + } + ; /** @} (end of group Parser) |