diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 53d65549574..8ea0b19c378 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -5168,6 +5168,19 @@ err: } +bool +sp_head::check_standalone_routine_end_name(const sp_name *end_name) const +{ + if (end_name && !end_name->eq(this)) + { + my_error(ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0), + ErrConvDQName(end_name).ptr(), ErrConvDQName(this).ptr()); + return true; + } + return false; +} + + ulong sp_head::sp_cache_version() const { return m_parent ? m_parent->sp_cache_version() : m_sp_cache_version; diff --git a/sql/sp_head.h b/sql/sp_head.h index f59da93d8aa..cec9347d6f1 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -412,6 +412,7 @@ public: const LEX_CSTRING *field_name, Item *val, LEX *lex); bool check_package_routine_end_name(const LEX_CSTRING &end_name) const; + bool check_standalone_routine_end_name(const sp_name *end_name) const; private: /** Generate a code to set a single cursor parameter variable. diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 792a196c5a8..aaa34d29c70 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6532,6 +6532,14 @@ bool LEX::sp_body_finalize_procedure(THD *thd) } +bool LEX::sp_body_finalize_procedure_standalone(THD *thd, + const sp_name *end_name) +{ + return sp_body_finalize_procedure(thd) || + sphead->check_standalone_routine_end_name(end_name); +} + + bool LEX::sp_body_finalize_function(THD *thd) { if (sphead->is_not_allowed_in_function("function")) @@ -6548,6 +6556,14 @@ bool LEX::sp_body_finalize_function(THD *thd) } +bool LEX::sp_body_finalize_function_standalone(THD *thd, + const sp_name *end_name) +{ + return sp_body_finalize_function(thd) || + sphead->check_standalone_routine_end_name(end_name); +} + + bool LEX::sp_block_with_exceptions_finalize_declarations(THD *thd) { /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ca72770e13b..70272e83e08 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3737,16 +3737,10 @@ public: sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph); sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name, const Sp_handler *sph); - sp_head *make_sp_head_no_recursive(THD *thd, - DDL_options_st options, sp_name *name, - const Sp_handler *sph) - { - if (add_create_options_with_check(options)) - return NULL; - return make_sp_head_no_recursive(thd, name, sph); - } bool sp_body_finalize_function(THD *); bool sp_body_finalize_procedure(THD *); + bool sp_body_finalize_function_standalone(THD *, const sp_name *end_name); + bool sp_body_finalize_procedure_standalone(THD *, const sp_name *end_name); sp_package *create_package_start(THD *thd, enum_sql_command command, const Sp_handler *sph, @@ -4486,6 +4480,28 @@ public: void stmt_purge_to(const LEX_CSTRING &to); bool stmt_purge_before(Item *item); + +private: + bool stmt_create_routine_start(const DDL_options_st &options) + { + create_info.set(options); + return main_select_push() || check_create_options(options); + } +public: + bool stmt_create_function_start(const DDL_options_st &options) + { + sql_command= SQLCOM_CREATE_SPFUNCTION; + return stmt_create_routine_start(options); + } + bool stmt_create_procedure_start(const DDL_options_st &options) + { + sql_command= SQLCOM_CREATE_PROCEDURE; + return stmt_create_routine_start(options); + } + void stmt_create_routine_finalize() + { + pop_select(); // main select + } }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2135227fda8..d17e92b6c22 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2841,15 +2841,14 @@ create: { Lex->pop_select(); //main select } - | create_or_replace definer_opt PROCEDURE_SYM + | create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_procedure_start($1 | $4)) MYSQL_YYABORT; - Lex->create_info.set($1); } sp_tail { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } | create_or_replace definer_opt EVENT_SYM { @@ -2861,45 +2860,41 @@ create: { Lex->pop_select(); //main select } - | create_or_replace definer FUNCTION_SYM + | create_or_replace definer FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $4)) MYSQL_YYABORT; - Lex->create_info.set($1); } sf_tail { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } - | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM + | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $5)) MYSQL_YYABORT; - Lex->create_info.set($1); } sf_tail_aggregate { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } - | create_or_replace no_definer FUNCTION_SYM + | create_or_replace no_definer FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $4)) MYSQL_YYABORT; - Lex->create_info.set($1); } create_function_tail { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } - | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM + | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $5)) MYSQL_YYABORT; - Lex->create_info.set($1); } create_aggregate_function_tail { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } | 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 @@ -17744,18 +17739,15 @@ trigger_tail: **************************************************************************/ udf_tail: - opt_if_not_exists ident - RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys + 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)); + if (unlikely(is_native_function(thd, & $1))) + my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $1.str)); lex->sql_command= SQLCOM_CREATE_FUNCTION; - lex->udf.name= $2; - lex->udf.returns= (Item_result) $4; - lex->udf.dl= $6.str; + lex->udf.name= $1; + lex->udf.returns= (Item_result) $3; + lex->udf.dl= $5.str; } ; @@ -17777,11 +17769,9 @@ 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, + if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, &sp_handler_function))) MYSQL_YYABORT; } @@ -17803,10 +17793,9 @@ 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, + if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, &sp_handler_procedure))) MYSQL_YYABORT; } diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index bb80616c755..0f7bbdcff5e 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1564,7 +1564,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); 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 + trigger_tail event_tail udf_tail create_function_tail_standalone create_aggregate_function_tail_standalone @@ -2362,15 +2362,14 @@ create: { Lex->pop_select(); //main select } - | create_or_replace definer_opt PROCEDURE_SYM + | create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_procedure_start($1 | $4)) MYSQL_YYABORT; - Lex->create_info.set($1); } sp_tail_standalone { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } | create_or_replace definer_opt EVENT_SYM { @@ -2382,45 +2381,41 @@ create: { Lex->pop_select(); //main select } - | create_or_replace definer FUNCTION_SYM + | create_or_replace definer FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $4)) MYSQL_YYABORT; - Lex->create_info.set($1); } sf_tail_standalone { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } - | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM + | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $5)) MYSQL_YYABORT; - Lex->create_info.set($1); } sf_tail_aggregate_standalone { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } - | create_or_replace no_definer FUNCTION_SYM + | create_or_replace no_definer FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $4)) MYSQL_YYABORT; - Lex->create_info.set($1); } create_function_tail_standalone { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } - | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM + | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists { - if (Lex->main_select_push()) + if (Lex->stmt_create_function_start($1 | $5)) MYSQL_YYABORT; - Lex->create_info.set($1); } create_aggregate_function_tail_standalone { - Lex->pop_select(); //main select + Lex->stmt_create_routine_finalize(); } | 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 @@ -17952,18 +17947,15 @@ trigger_tail: **************************************************************************/ udf_tail: - opt_if_not_exists ident - RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys + 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)); + if (unlikely(is_native_function(thd, & $1))) + my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $1.str)); lex->sql_command= SQLCOM_CREATE_FUNCTION; - lex->udf.name= $2; - lex->udf.returns= (Item_result) $4; - lex->udf.dl= $6.str; + lex->udf.name= $1; + lex->udf.returns= (Item_result) $3; + lex->udf.dl= $5.str; } ; @@ -17984,12 +17976,10 @@ sf_return_type: } ; -sf_tail: - opt_if_not_exists +sf_tail_standalone: sp_name { - Lex->sql_command= SQLCOM_CREATE_SPFUNCTION; - if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2, + if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, &sp_handler_function))) MYSQL_YYABORT; } @@ -18005,17 +17995,17 @@ sf_tail: } sp_tail_is sp_body + opt_sp_name { - if (unlikely(Lex->sp_body_finalize_function(thd))) + if (unlikely(Lex->sp_body_finalize_function_standalone(thd, $9))) MYSQL_YYABORT; } ; -sp_tail: - opt_if_not_exists sp_name +sp_tail_standalone: + sp_name { - Lex->sql_command= SQLCOM_CREATE_PROCEDURE; - if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2, + if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, &sp_handler_procedure))) MYSQL_YYABORT; } @@ -18027,31 +18017,13 @@ sp_tail: } sp_tail_is sp_body + opt_sp_name { - if (unlikely(Lex->sp_body_finalize_procedure(thd))) + if (unlikely(Lex->sp_body_finalize_procedure_standalone(thd, $8))) MYSQL_YYABORT; } ; -sf_tail_standalone: - sf_tail opt_sp_name - { - if (unlikely($2 && !$2->eq(Lex->sphead))) - my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0), - ErrConvDQName($2).ptr(), - ErrConvDQName(Lex->sphead).ptr())); - } - ; - -sp_tail_standalone: - sp_tail opt_sp_name - { - if (unlikely($2 && !$2->eq(Lex->sphead))) - my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0), - ErrConvDQName($2).ptr(), - ErrConvDQName(Lex->sphead).ptr())); - } - ; opt_package_routine_end_name: /* Empty */ { $$= null_clex_str; }