Commit 5b1fdbec authored by pem@mysql.com's avatar pem@mysql.com

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.
parent 865d8f8e
...@@ -72,6 +72,12 @@ drop trigger t1_ai; ...@@ -72,6 +72,12 @@ drop trigger t1_ai;
create trigger t1_ai after insert on t1 for each row call bug14233_3(); create trigger t1_ai after insert on t1 for each row call bug14233_3();
insert into t1 values (0); 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) 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 trigger t1_ai;
drop table t1; 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(); ...@@ -119,6 +119,15 @@ create trigger t1_ai after insert on t1 for each row call bug14233_3();
insert into t1 values (0); insert into t1 values (0);
# Clean-up # Clean-up
delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai; drop trigger t1_ai;
drop table t1; 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;
...@@ -1002,22 +1002,26 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, ...@@ -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 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; bool result= 0;
DBUG_ENTER("sp_exists_routine"); DBUG_ENTER("sp_exists_routine");
for (table= tables; table; table= table->next_global) for (routine= routines; routine; routine= routine->next_global)
{ {
sp_name *name; sp_name *name;
LEX_STRING lex_db; LEX_STRING lex_db;
LEX_STRING lex_name; LEX_STRING lex_name;
lex_db.length= strlen(table->db); lex_db.length= strlen(routine->db);
lex_name.length= strlen(table->table_name); lex_name.length= strlen(routine->table_name);
lex_db.str= thd->strmake(table->db, lex_db.length); lex_db.str= thd->strmake(routine->db, lex_db.length);
lex_name.str= thd->strmake(table->table_name, lex_name.length); lex_name.str= thd->strmake(routine->table_name, lex_name.length);
name= new sp_name(lex_db, lex_name); name= new sp_name(lex_db, lex_name);
name->init_qname(thd); name->init_qname(thd);
if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, 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) ...@@ -1034,7 +1038,7 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
if (!no_error) if (!no_error)
{ {
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE", my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE",
table->table_name); routine->table_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -1044,6 +1048,41 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error) ...@@ -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 int
sp_create_procedure(THD *thd, sp_head *sp) sp_create_procedure(THD *thd, sp_head *sp)
{ {
......
...@@ -40,7 +40,10 @@ sp_find_routine(THD *thd, int type, sp_name *name, ...@@ -40,7 +40,10 @@ sp_find_routine(THD *thd, int type, sp_name *name,
sp_cache **cp, bool cache_only); sp_cache **cp, bool cache_only);
int 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 int
sp_create_procedure(THD *thd, sp_head *sp); 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, ...@@ -3030,7 +3030,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
if (!revoke_grant) 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); DBUG_RETURN(TRUE);
} }
......
...@@ -4445,21 +4445,17 @@ mysql_execute_command(THD *thd) ...@@ -4445,21 +4445,17 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_PROCEDURE: case SQLCOM_DROP_PROCEDURE:
case SQLCOM_DROP_FUNCTION: case SQLCOM_DROP_FUNCTION:
{ {
sp_head *sp;
int result; 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) result= sp_routine_exists_in_table(thd, type, lex->spname);
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);
mysql_reset_errors(thd, 0); mysql_reset_errors(thd, 0);
if (sp) if (result == SP_OK)
{ {
db= thd->strdup(sp->m_db.str); char *db= lex->spname->m_db.str;
name= thd->strdup(sp->m_name.str); char *name= lex->spname->m_name.str;
if (check_routine_access(thd, ALTER_PROC_ACL, db, name, if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
goto error; goto error;
......
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