Fixed BUG#16303: erroneus stored procedures and functions should be droppable
Use a special lookup function for DROP, which doesn't attempt to parse the definition. mysql-test/r/sp-destruct.result: Updated test result for BUG#16303. mysql-test/t/sp-destruct.test: Added test case for BUG#16303. sql/sp.cc: New function sp_routine_exists_in_table() for DROP PROCEDURE/FUNCTION; which doesn't want to parse the definition, only know if it exists. Renamed sp_exists_routine to sp_exist_routines and added comment, and changed the misnamed parameter/variable 'tables'/'table' to 'routines'/'routine'. sql/sp.h: New function sp_routine_exists_in_table() for DROP PROCEDURE/FUNCTION. Renamed sp_exists_routine to sp_exist_routines, and changed the misnamed parameter 'tables' to 'routines'. sql/sql_acl.cc: Call to sp_exists_routine() renamed to sp_exist_routines(). sql/sql_parse.cc: Use the new sp_routine_exists_in_table() instead of sp_find_routine(), since we don't want the routine definition parsed when doing DROP PROCEDURE/FUNCTION.
This commit is contained in:
parent
e43170419c
commit
cce719fba8
@ -72,6 +72,12 @@ drop trigger t1_ai;
|
||||
create trigger t1_ai after insert on t1 for each row call bug14233_3();
|
||||
insert into t1 values (0);
|
||||
ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
|
||||
delete from mysql.proc where name like 'bug14233%';
|
||||
drop trigger t1_ai;
|
||||
drop table t1;
|
||||
drop function bug14233_1;
|
||||
drop function bug14233_2;
|
||||
drop procedure bug14233_3;
|
||||
show procedure status;
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
show function status;
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
|
@ -119,6 +119,15 @@ create trigger t1_ai after insert on t1 for each row call bug14233_3();
|
||||
insert into t1 values (0);
|
||||
|
||||
# Clean-up
|
||||
delete from mysql.proc where name like 'bug14233%';
|
||||
drop trigger t1_ai;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#16303: erroneus stored procedures and functions should be droppable
|
||||
#
|
||||
drop function bug14233_1;
|
||||
drop function bug14233_2;
|
||||
drop procedure bug14233_3;
|
||||
# Assert: These should show nothing.
|
||||
show procedure status;
|
||||
show function status;
|
||||
|
55
sql/sp.cc
55
sql/sp.cc
@ -1002,22 +1002,26 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This is used by sql_acl.cc:mysql_routine_grant() and is used to find
|
||||
the routines in 'routines'.
|
||||
*/
|
||||
|
||||
int
|
||||
sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
|
||||
sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any, bool no_error)
|
||||
{
|
||||
TABLE_LIST *table;
|
||||
TABLE_LIST *routine;
|
||||
bool result= 0;
|
||||
DBUG_ENTER("sp_exists_routine");
|
||||
for (table= tables; table; table= table->next_global)
|
||||
for (routine= routines; routine; routine= routine->next_global)
|
||||
{
|
||||
sp_name *name;
|
||||
LEX_STRING lex_db;
|
||||
LEX_STRING lex_name;
|
||||
lex_db.length= strlen(table->db);
|
||||
lex_name.length= strlen(table->table_name);
|
||||
lex_db.str= thd->strmake(table->db, lex_db.length);
|
||||
lex_name.str= thd->strmake(table->table_name, lex_name.length);
|
||||
lex_db.length= strlen(routine->db);
|
||||
lex_name.length= strlen(routine->table_name);
|
||||
lex_db.str= thd->strmake(routine->db, lex_db.length);
|
||||
lex_name.str= thd->strmake(routine->table_name, lex_name.length);
|
||||
name= new sp_name(lex_db, lex_name);
|
||||
name->init_qname(thd);
|
||||
if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
|
||||
@ -1034,7 +1038,7 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
|
||||
if (!no_error)
|
||||
{
|
||||
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE",
|
||||
table->table_name);
|
||||
routine->table_name);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
@ -1044,6 +1048,41 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if a routine exists in the mysql.proc table, without actually
|
||||
parsing the definition. (Used for dropping)
|
||||
|
||||
SYNOPSIS
|
||||
sp_routine_exists_in_table()
|
||||
thd - thread context
|
||||
name - name of procedure
|
||||
|
||||
RETURN VALUE
|
||||
0 - Success
|
||||
non-0 - Error; SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND
|
||||
*/
|
||||
|
||||
int
|
||||
sp_routine_exists_in_table(THD *thd, int type, sp_name *name)
|
||||
{
|
||||
TABLE *table;
|
||||
int ret;
|
||||
Open_tables_state open_tables_state_backup;
|
||||
|
||||
if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup)))
|
||||
ret= SP_OPEN_TABLE_FAILED;
|
||||
else
|
||||
{
|
||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
||||
ret= SP_OK;
|
||||
else
|
||||
ret= SP_KEY_NOT_FOUND;
|
||||
close_proc_table(thd, &open_tables_state_backup);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sp_create_procedure(THD *thd, sp_head *sp)
|
||||
{
|
||||
|
5
sql/sp.h
5
sql/sp.h
@ -40,7 +40,10 @@ sp_find_routine(THD *thd, int type, sp_name *name,
|
||||
sp_cache **cp, bool cache_only);
|
||||
|
||||
int
|
||||
sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
|
||||
sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
|
||||
|
||||
int
|
||||
sp_routine_exists_in_table(THD *thd, int type, sp_name *name);
|
||||
|
||||
int
|
||||
sp_create_procedure(THD *thd, sp_head *sp);
|
||||
|
@ -3030,7 +3030,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
|
||||
|
||||
if (!revoke_grant)
|
||||
{
|
||||
if (sp_exists_routine(thd, table_list, is_proc, no_error)<0)
|
||||
if (sp_exist_routines(thd, table_list, is_proc, no_error)<0)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
|
@ -4445,21 +4445,17 @@ end_with_restore_list:
|
||||
case SQLCOM_DROP_PROCEDURE:
|
||||
case SQLCOM_DROP_FUNCTION:
|
||||
{
|
||||
sp_head *sp;
|
||||
int result;
|
||||
char *db, *name;
|
||||
int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
|
||||
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
|
||||
|
||||
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
|
||||
sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
|
||||
&thd->sp_proc_cache, FALSE);
|
||||
else
|
||||
sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
|
||||
&thd->sp_func_cache, FALSE);
|
||||
result= sp_routine_exists_in_table(thd, type, lex->spname);
|
||||
mysql_reset_errors(thd, 0);
|
||||
if (sp)
|
||||
if (result == SP_OK)
|
||||
{
|
||||
db= thd->strdup(sp->m_db.str);
|
||||
name= thd->strdup(sp->m_name.str);
|
||||
char *db= lex->spname->m_db.str;
|
||||
char *name= lex->spname->m_name.str;
|
||||
|
||||
if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
|
||||
lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
|
||||
goto error;
|
||||
|
Loading…
x
Reference in New Issue
Block a user