From c579a5878830909e07ba9c45778defe351d6672b Mon Sep 17 00:00:00 2001 From: amrSherif12 Date: Sun, 10 May 2026 12:44:25 +0300 Subject: [PATCH] ALTER PREC DEF no whitespaces --- .../main/alter_procedure_definer.result | 17 ++++++++++++++++ mysql-test/main/alter_procedure_definer.test | 20 +++++++++++++++++++ sql/sp.cc | 16 ++++++++++++++- sql/sp.h | 2 +- sql/sql_parse.cc | 9 ++++++++- sql/sql_yacc.yy | 9 +++++++-- 6 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 mysql-test/main/alter_procedure_definer.result create mode 100644 mysql-test/main/alter_procedure_definer.test diff --git a/mysql-test/main/alter_procedure_definer.result b/mysql-test/main/alter_procedure_definer.result new file mode 100644 index 0000000000000..c9d60b39254ab --- /dev/null +++ b/mysql-test/main/alter_procedure_definer.result @@ -0,0 +1,17 @@ +# ALTER PROCEDURE DEFINER +CREATE USER 'user1'@'localhost'; +GRANT ALL PRIVILEGES ON test.* TO 'user1'@'localhost'; +connect con1, localhost, user1, , test; +CREATE PROCEDURE p1() SELECT 1; +ALTER PROCEDURE p1 DEFINER = 'user1'@'localhost'; +ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; +ERROR 42000: Access denied; you need (at least one of) the SUPER, SET USER privilege(s) for this operation +connection default; +ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; +SELECT definer FROM mysql.proc WHERE name = 'p1'; +definer +root@localhost +DROP PROCEDURE p1; +DROP USER 'user1'@'localhost'; +Warnings: +Note 4227 Dropped users 'user1'@'localhost' have active connections. Use KILL CONNECTION if they should not be used anymore. diff --git a/mysql-test/main/alter_procedure_definer.test b/mysql-test/main/alter_procedure_definer.test new file mode 100644 index 0000000000000..76d9db2d7063f --- /dev/null +++ b/mysql-test/main/alter_procedure_definer.test @@ -0,0 +1,20 @@ +--echo # ALTER PROCEDURE DEFINER + +CREATE USER 'user1'@'localhost'; +GRANT ALL PRIVILEGES ON test.* TO 'user1'@'localhost'; + +--connect (con1, localhost, user1, , test) +CREATE PROCEDURE p1() SELECT 1; + +ALTER PROCEDURE p1 DEFINER = 'user1'@'localhost'; + +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; + +--connection default +ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; + +SELECT definer FROM mysql.proc WHERE name = 'p1'; + +DROP PROCEDURE p1; +DROP USER 'user1'@'localhost'; diff --git a/sql/sp.cc b/sql/sp.cc index cbaf72b939814..ac351a7605e5a 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1711,7 +1711,7 @@ Sp_handler::sp_drop_routine(THD *thd, int Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name, - const st_sp_chistics *chistics) const + const st_sp_chistics *chistics, LEX_USER *definer) const { TABLE *table; int ret; @@ -1768,6 +1768,20 @@ Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name, if (chistics->agg_type != DEFAULT_AGGREGATE) table->field[MYSQL_PROC_FIELD_AGGREGATE]-> store((longlong)chistics->agg_type, TRUE); + if (definer) + { + if (definer->user.str && definer->host.str) + { + char definer_str[USER_HOST_BUFF_SIZE]; + uint definer_len= strxmov(definer_str, definer->user.str, "@", + definer->host.str, NullS) - + definer_str; + table->field[MYSQL_PROC_FIELD_DEFINER]->set_notnull(); + table->field[MYSQL_PROC_FIELD_DEFINER]->store(definer_str, definer_len, + system_charset_info); + sp_cache_invalidate(); + } + } if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) && ret != HA_ERR_RECORD_IS_THE_SAME) ret= SP_WRITE_ROW_FAILED; diff --git a/sql/sp.h b/sql/sp.h index 47f2495db3e26..fda7301298810 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -218,7 +218,7 @@ class Sp_handler bool sp_create_routine(THD *thd, const sp_head *sp) const; int sp_update_routine(THD *thd, const Database_qualified_name *name, - const st_sp_chistics *chistics) const; + const st_sp_chistics *chistics, LEX_USER *definer = nullptr) const; int sp_drop_routine(THD *thd, const Database_qualified_name *name) const; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index efa23a3007ee2..ab480fbd058db 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6448,6 +6448,13 @@ alter_routine(THD *thd, LEX *lex) if (check_routine_access(thd, ALTER_PROC_ACL, &lex->spname->m_db, &lex->spname->m_name, sph, 0)) return 1; + if (lex->definer) + { + if ((!lex_string_eq(&lex->definer->user, thd->security_ctx->priv_user, strlen(thd->security_ctx->priv_user)) || + !lex_string_eq(&lex->definer->host, thd->security_ctx->priv_host, strlen(thd->security_ctx->priv_host))) && + check_global_access(thd, SET_USER_ACL | SUPER_ACL)) + return 1; + } /* Note that if you implement the capability of ALTER FUNCTION to alter the body of the function, this command should be made to @@ -6455,7 +6462,7 @@ alter_routine(THD *thd, LEX *lex) already puts on CREATE FUNCTION. */ /* Conditionally writes to binlog */ - sp_result= sph->sp_update_routine(thd, lex->spname, &lex->sp_chistics); + sp_result= sph->sp_update_routine(thd, lex->spname, &lex->sp_chistics, lex->definer); switch (sp_result) { case SP_OK: my_ok(thd); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 269d497058c2f..720ce10899b4f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1777,7 +1777,7 @@ rule: %type user grant_user grant_role user_or_role current_role admin_option_for_role user_maybe_role role_name - user_name + user_name sp_a_chistic %type opt_auth_str auth_expression auth_token text_or_password @@ -3395,7 +3395,12 @@ sp_name: sp_a_chistics: /* Empty */ {} - | sp_a_chistics sp_chistic {} + | sp_a_chistics sp_a_chistic {} + ; + +sp_a_chistic: + sp_chistic {} + | definer {} ; sp_c_chistics: