Commit cce719fb authored by unknown's avatar unknown

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.
parent e4317041
......@@ -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;
......@@ -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)
{
......
......@@ -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;
......
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