Commit 2f0b1d65 authored by unknown's avatar unknown

Bug#22043 MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS"

- Refactoring of duplicate code
- Modified bad test cases
- Changed expected error when operating on information_schema.


mysql-test/r/information_schema.result:
  - updated result file with new error code.
mysql-test/r/rpl_sp.result:
  - Modified test case
mysql-test/t/information_schema.test:
  - Changed error code for operations on information_schema
mysql-test/t/rpl_sp.test:
  - Modified test case
sql/sql_parse.cc:
  - Cleaned up code:
    * replace tab with space
    * simplified if/switch statements
    * refactored duplicated code
parent 9a87702b
...@@ -1027,7 +1027,7 @@ CREATE PROCEDURE p1 () ...@@ -1027,7 +1027,7 @@ CREATE PROCEDURE p1 ()
BEGIN BEGIN
SELECT 'foo' FROM DUAL; SELECT 'foo' FROM DUAL;
END | END |
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' ERROR 42000: Unknown database 'information_schema'
select ROUTINE_NAME from routines; select ROUTINE_NAME from routines;
ROUTINE_NAME ROUTINE_NAME
grant all on information_schema.* to 'user1'@'localhost'; grant all on information_schema.* to 'user1'@'localhost';
......
...@@ -465,6 +465,7 @@ RETURN 0 ...@@ -465,6 +465,7 @@ RETURN 0
DROP PROCEDURE p1; DROP PROCEDURE p1;
DROP FUNCTION f1; DROP FUNCTION f1;
drop table t1; drop table t1;
reset master;
drop database if exists mysqltest; drop database if exists mysqltest;
drop database if exists mysqltest2; drop database if exists mysqltest2;
create database mysqltest; create database mysqltest;
...@@ -473,19 +474,15 @@ use mysqltest2; ...@@ -473,19 +474,15 @@ use mysqltest2;
create table t ( t integer ); create table t ( t integer );
create procedure mysqltest.test() begin end; create procedure mysqltest.test() begin end;
insert into t values ( 1 ); 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 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 98 Query 1 199 drop database if exists mysqltest
master-bin.000001 8317 Query 1 8397 use `test`; DROP PROCEDURE p1 master-bin.000001 199 Query 1 302 drop database if exists mysqltest2
master-bin.000001 8397 Query 1 8476 use `test`; DROP FUNCTION f1 master-bin.000001 302 Query 1 395 create database mysqltest
master-bin.000001 8476 Query 1 8552 use `test`; drop table t1 master-bin.000001 395 Query 1 490 create database mysqltest2
master-bin.000001 8552 Query 1 8653 drop database if exists mysqltest master-bin.000001 490 Query 1 587 use `mysqltest2`; create table t ( t integer )
master-bin.000001 8653 Query 1 8756 drop database if exists mysqltest2 master-bin.000001 587 Query 1 726 use `mysqltest2`; CREATE DEFINER=`root`@`localhost` procedure mysqltest.test() begin end
master-bin.000001 8756 Query 1 8849 create database mysqltest master-bin.000001 726 Query 1 821 use `mysqltest2`; insert into t values ( 1 )
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 )
create procedure `\\`.test() begin end; create procedure `\\`.test() begin end;
ERROR 42000: Incorrect database name '\\' ERROR 42000: Incorrect database name '\\'
drop database mysqltest; drop database mysqltest;
......
...@@ -715,7 +715,7 @@ create temporary table schemata(f1 char(10)); ...@@ -715,7 +715,7 @@ create temporary table schemata(f1 char(10));
# Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA # Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA
# #
delimiter |; delimiter |;
--error 1044 --error ER_BAD_DB_ERROR
CREATE PROCEDURE p1 () CREATE PROCEDURE p1 ()
BEGIN BEGIN
SELECT 'foo' FROM DUAL; SELECT 'foo' FROM DUAL;
......
...@@ -524,6 +524,7 @@ sync_slave_with_master; ...@@ -524,6 +524,7 @@ sync_slave_with_master;
# Bug22043: MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS" # Bug22043: MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS"
# #
connection master; connection master;
reset master;
--disable_warnings --disable_warnings
drop database if exists mysqltest; drop database if exists mysqltest;
drop database if exists mysqltest2; drop database if exists mysqltest2;
...@@ -534,7 +535,7 @@ use mysqltest2; ...@@ -534,7 +535,7 @@ use mysqltest2;
create table t ( t integer ); create table t ( t integer );
create procedure mysqltest.test() begin end; create procedure mysqltest.test() begin end;
insert into t values ( 1 ); 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 --error ER_WRONG_DB_NAME
create procedure `\\`.test() begin end; create procedure `\\`.test() begin end;
# Clean up # Clean up
......
...@@ -4221,11 +4221,10 @@ mysql_execute_command(THD *thd) ...@@ -4221,11 +4221,10 @@ mysql_execute_command(THD *thd)
{ {
uint namelen; uint namelen;
char *name; char *name;
int result; int result= SP_INTERNAL_ERROR;
DBUG_ASSERT(lex->sphead != 0); DBUG_ASSERT(lex->sphead != 0);
DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
/* /*
Verify that the database name is allowed, optionally Verify that the database name is allowed, optionally
lowercase it. lowercase it.
...@@ -4233,37 +4232,26 @@ mysql_execute_command(THD *thd) ...@@ -4233,37 +4232,26 @@ mysql_execute_command(THD *thd)
if (check_db_name(lex->sphead->m_db.str)) if (check_db_name(lex->sphead->m_db.str))
{ {
my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str); my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
delete lex->sphead; goto create_sp_error;
lex->sphead= 0;
goto error;
} }
/* /*
Check that a database with this name Check that a database directory with this name
exists. exists. Design note: This won't work on virtual databases
like information_schema.
*/ */
if (check_db_dir_existence(lex->sphead->m_db.str)) if (check_db_dir_existence(lex->sphead->m_db.str))
{ {
my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
delete lex->sphead; goto create_sp_error;
lex->sphead= 0;
goto error;
} }
if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
is_schema_db(lex->sphead->m_db.str))) is_schema_db(lex->sphead->m_db.str)))
{ goto create_sp_error;
delete lex->sphead;
lex->sphead= 0;
goto error;
}
if (end_active_trans(thd)) if (end_active_trans(thd))
{ goto create_sp_error;
delete lex->sphead;
lex->sphead= 0;
goto error;
}
name= lex->sphead->name(&namelen); name= lex->sphead->name(&namelen);
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
...@@ -4273,10 +4261,8 @@ mysql_execute_command(THD *thd) ...@@ -4273,10 +4261,8 @@ mysql_execute_command(THD *thd)
if (udf) if (udf)
{ {
my_error(ER_UDF_EXISTS, MYF(0), name); my_error(ER_UDF_EXISTS, MYF(0), name);
delete lex->sphead; goto create_sp_error;
lex->sphead= 0;
goto error;
} }
} }
#endif #endif
...@@ -4284,7 +4270,7 @@ mysql_execute_command(THD *thd) ...@@ -4284,7 +4270,7 @@ mysql_execute_command(THD *thd)
/* /*
If the definer is not specified, this means that CREATE-statement missed If the definer is not specified, this means that CREATE-statement missed
DEFINER-clause. DEFINER-clause can be missed in two cases: DEFINER-clause. DEFINER-clause can be missed in two cases:
- The user submitted a statement w/o the clause. This is a normal - The user submitted a statement w/o the clause. This is a normal
case, we should assign CURRENT_USER as definer. case, we should assign CURRENT_USER as definer.
...@@ -4293,7 +4279,7 @@ mysql_execute_command(THD *thd) ...@@ -4293,7 +4279,7 @@ mysql_execute_command(THD *thd)
CURRENT_USER as definer here, but also we should mark this routine CURRENT_USER as definer here, but also we should mark this routine
as NON-SUID. This is essential for the sake of backward as NON-SUID. This is essential for the sake of backward
compatibility. compatibility.
The problem is the slave thread is running under "special" user (@), The problem is the slave thread is running under "special" user (@),
that actually does not exist. In the older versions we do not fail 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 execution of a stored routine if its definer does not exist and
...@@ -4318,13 +4304,9 @@ mysql_execute_command(THD *thd) ...@@ -4318,13 +4304,9 @@ mysql_execute_command(THD *thd)
if (ps_arena) if (ps_arena)
thd->restore_active_arena(ps_arena, &original_arena); thd->restore_active_arena(ps_arena, &original_arena);
/* Error has been already reported. */
if (res) if (res)
{ goto create_sp_error;
/* Error has been already reported. */
delete lex->sphead;
lex->sphead= 0;
goto error;
}
if (thd->slave_thread) if (thd->slave_thread)
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
...@@ -4335,7 +4317,7 @@ mysql_execute_command(THD *thd) ...@@ -4335,7 +4317,7 @@ mysql_execute_command(THD *thd)
that the current user has SUPER privilege (in order to create a stored that the current user has SUPER privilege (in order to create a stored
routine under another user one must have SUPER privilege). routine under another user one must have SUPER privilege).
*/ */
else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info, my_strcasecmp(system_charset_info,
lex->definer->host.str, lex->definer->host.str,
...@@ -4344,9 +4326,7 @@ mysql_execute_command(THD *thd) ...@@ -4344,9 +4326,7 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL)) if (check_global_access(thd, SUPER_ACL))
{ {
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
delete lex->sphead; goto create_sp_error;
lex->sphead= 0;
goto error;
} }
} }
...@@ -4366,54 +4346,51 @@ mysql_execute_command(THD *thd) ...@@ -4366,54 +4346,51 @@ mysql_execute_command(THD *thd)
#endif /* NO_EMBEDDED_ACCESS_CHECKS */ #endif /* NO_EMBEDDED_ACCESS_CHECKS */
res= (result= lex->sphead->create(thd)); res= (result= lex->sphead->create(thd));
if (result == SP_OK) switch (result) {
{ case SP_OK:
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
/* only add privileges if really neccessary */ /* only add privileges if really neccessary */
if (sp_automatic_privileges && !opt_noacl && if (sp_automatic_privileges && !opt_noacl &&
check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS, 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)) lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
{ {
close_thread_tables(thd);
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name, if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE)) lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_PROC_AUTO_GRANT_FAIL, ER_PROC_AUTO_GRANT_FAIL,
ER(ER_PROC_AUTO_GRANT_FAIL)); ER(ER_PROC_AUTO_GRANT_FAIL));
close_thread_tables(thd);
} }
#endif #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; 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: case SQLCOM_CALL:
{ {
sp_head *sp; sp_head *sp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment