diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 43eedc19f12..21d7bfb1b21 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1027,7 +1027,7 @@ CREATE PROCEDURE p1 () BEGIN SELECT 'foo' FROM DUAL; END | -ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +ERROR 42000: Unknown database 'information_schema' select ROUTINE_NAME from routines; ROUTINE_NAME grant all on information_schema.* to 'user1'@'localhost'; diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index 95191282bc4..a0464e97e28 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -467,6 +467,7 @@ DROP FUNCTION f1; drop table t1; set global log_bin_trust_function_creators=0; set global log_bin_trust_function_creators=0; +reset master; drop database if exists mysqltest; drop database if exists mysqltest2; create database mysqltest; @@ -475,19 +476,15 @@ use mysqltest2; create table t ( t integer ); create procedure mysqltest.test() begin end; insert into t values ( 1 ); -show binlog events in 'master-bin.000001' from 8186; +show binlog events in 'master-bin.000001' from 98; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 8186 Query 1 8317 use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION f1() RETURNS INT RETURN 0 -master-bin.000001 8317 Query 1 8397 use `test`; DROP PROCEDURE p1 -master-bin.000001 8397 Query 1 8476 use `test`; DROP FUNCTION f1 -master-bin.000001 8476 Query 1 8552 use `test`; drop table t1 -master-bin.000001 8552 Query 1 8653 drop database if exists mysqltest -master-bin.000001 8653 Query 1 8756 drop database if exists mysqltest2 -master-bin.000001 8756 Query 1 8849 create database mysqltest -master-bin.000001 8849 Query 1 8944 create database mysqltest2 -master-bin.000001 8944 Query 1 9041 use `mysqltest2`; create table t ( t integer ) -master-bin.000001 9041 Query 1 9180 use `mysqltest2`; CREATE DEFINER=`root`@`localhost` procedure mysqltest.test() begin end -master-bin.000001 9180 Query 1 9275 use `mysqltest2`; insert into t values ( 1 ) +master-bin.000001 98 Query 1 199 drop database if exists mysqltest +master-bin.000001 199 Query 1 302 drop database if exists mysqltest2 +master-bin.000001 302 Query 1 395 create database mysqltest +master-bin.000001 395 Query 1 490 create database mysqltest2 +master-bin.000001 490 Query 1 587 use `mysqltest2`; create table t ( t integer ) +master-bin.000001 587 Query 1 726 use `mysqltest2`; CREATE DEFINER=`root`@`localhost` procedure mysqltest.test() begin end +master-bin.000001 726 Query 1 821 use `mysqltest2`; insert into t values ( 1 ) create procedure `\\`.test() begin end; ERROR 42000: Incorrect database name '\\' drop database mysqltest; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index dd203add344..623ccee49e4 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -715,7 +715,7 @@ create temporary table schemata(f1 char(10)); # Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA # delimiter |; ---error 1044 +--error ER_BAD_DB_ERROR CREATE PROCEDURE p1 () BEGIN SELECT 'foo' FROM DUAL; diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index fdc04edf7bd..373b895a7c1 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -528,6 +528,7 @@ set global log_bin_trust_function_creators=0; # Bug22043: MySQL don't add "USE " before "DROP PROCEDURE IF EXISTS" # connection master; +reset master; --disable_warnings drop database if exists mysqltest; drop database if exists mysqltest2; @@ -538,7 +539,7 @@ use mysqltest2; create table t ( t integer ); create procedure mysqltest.test() begin end; insert into t values ( 1 ); -show binlog events in 'master-bin.000001' from 8186; +show binlog events in 'master-bin.000001' from 98; --error ER_WRONG_DB_NAME create procedure `\\`.test() begin end; # Clean up diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4d1d36a5dd7..65257c06d69 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4244,11 +4244,10 @@ end_with_restore_list: { uint namelen; char *name; - int result; + int result= SP_INTERNAL_ERROR; DBUG_ASSERT(lex->sphead != 0); DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ - /* Verify that the database name is allowed, optionally lowercase it. @@ -4256,37 +4255,26 @@ end_with_restore_list: if (check_db_name(lex->sphead->m_db.str)) { my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str); - delete lex->sphead; - lex->sphead= 0; - goto error; + goto create_sp_error; } /* - Check that a database with this name - exists. + Check that a database directory with this name + exists. Design note: This won't work on virtual databases + like information_schema. */ if (check_db_dir_existence(lex->sphead->m_db.str)) { my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); - delete lex->sphead; - lex->sphead= 0; - goto error; + goto create_sp_error; } if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, is_schema_db(lex->sphead->m_db.str))) - { - delete lex->sphead; - lex->sphead= 0; - goto error; - } + goto create_sp_error; - if (end_active_trans(thd)) - { - delete lex->sphead; - lex->sphead= 0; - goto error; - } + if (end_active_trans(thd)) + goto create_sp_error; name= lex->sphead->name(&namelen); #ifdef HAVE_DLOPEN @@ -4296,10 +4284,8 @@ end_with_restore_list: if (udf) { - my_error(ER_UDF_EXISTS, MYF(0), name); - delete lex->sphead; - lex->sphead= 0; - goto error; + my_error(ER_UDF_EXISTS, MYF(0), name); + goto create_sp_error; } } #endif @@ -4307,7 +4293,7 @@ end_with_restore_list: /* If the definer is not specified, this means that CREATE-statement missed DEFINER-clause. DEFINER-clause can be missed in two cases: - + - The user submitted a statement w/o the clause. This is a normal case, we should assign CURRENT_USER as definer. @@ -4316,7 +4302,7 @@ end_with_restore_list: CURRENT_USER as definer here, but also we should mark this routine as NON-SUID. This is essential for the sake of backward compatibility. - + The problem is the slave thread is running under "special" user (@), that actually does not exist. In the older versions we do not fail execution of a stored routine if its definer does not exist and @@ -4341,13 +4327,9 @@ end_with_restore_list: if (ps_arena) thd->restore_active_arena(ps_arena, &original_arena); + /* Error has been already reported. */ if (res) - { - /* Error has been already reported. */ - delete lex->sphead; - lex->sphead= 0; - goto error; - } + goto create_sp_error; if (thd->slave_thread) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; @@ -4358,7 +4340,7 @@ end_with_restore_list: that the current user has SUPER privilege (in order to create a stored routine under another user one must have SUPER privilege). */ - + else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || my_strcasecmp(system_charset_info, lex->definer->host.str, @@ -4367,9 +4349,7 @@ end_with_restore_list: if (check_global_access(thd, SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - delete lex->sphead; - lex->sphead= 0; - goto error; + goto create_sp_error; } } @@ -4389,54 +4369,51 @@ end_with_restore_list: #endif /* NO_EMBEDDED_ACCESS_CHECKS */ res= (result= lex->sphead->create(thd)); - if (result == SP_OK) - { + switch (result) { + case SP_OK: #ifndef NO_EMBEDDED_ACCESS_CHECKS /* only add privileges if really neccessary */ if (sp_automatic_privileges && !opt_noacl && check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS, - lex->sphead->m_db.str, name, + lex->sphead->m_db.str, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1)) { - close_thread_tables(thd); if (sp_grant_privileges(thd, lex->sphead->m_db.str, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE)) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_PROC_AUTO_GRANT_FAIL, - ER(ER_PROC_AUTO_GRANT_FAIL)); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_PROC_AUTO_GRANT_FAIL, + ER(ER_PROC_AUTO_GRANT_FAIL)); + close_thread_tables(thd); } #endif - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - send_ok(thd); - } - else - { - switch (result) { - case SP_WRITE_ROW_FAILED: - my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); - break; - case SP_NO_DB_ERROR: - my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); - break; - case SP_BAD_IDENTIFIER: - my_error(ER_TOO_LONG_IDENT, MYF(0), name); - break; - case SP_BODY_TOO_LONG: - my_error(ER_TOO_LONG_BODY, MYF(0), name); - break; - default: - my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); - break; - } - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - goto error; - } break; - } + case SP_WRITE_ROW_FAILED: + my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); + break; + case SP_BAD_IDENTIFIER: + my_error(ER_TOO_LONG_IDENT, MYF(0), name); + break; + case SP_BODY_TOO_LONG: + my_error(ER_TOO_LONG_BODY, MYF(0), name); + break; + default: + my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); + break; + } /* end switch */ + + /* + Capture all errors within this CASE and + clean up the environment. + */ +create_sp_error: + lex->unit.cleanup(); + delete lex->sphead; + lex->sphead= 0; + if (result != SP_OK ) + goto error; + send_ok(thd); + break; /* break super switch */ + } /* end case group bracket */ case SQLCOM_CALL: { sp_head *sp;