diff options
author | unknown <pem@mysql.com> | 2006-01-26 13:29:46 +0100 |
---|---|---|
committer | unknown <pem@mysql.com> | 2006-01-26 13:29:46 +0100 |
commit | cce719fba8e143c6a94f5c4048e1b72d005b1dd2 (patch) | |
tree | 42db978805a90eab556fb5ed7c87e15209b14d6b /sql | |
parent | e43170419c97f5432e90016bc89e0910f39f1487 (diff) | |
download | mariadb-git-cce719fba8e143c6a94f5c4048e1b72d005b1dd2.tar.gz |
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sp.cc | 55 | ||||
-rw-r--r-- | sql/sp.h | 5 | ||||
-rw-r--r-- | sql/sql_acl.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 18 |
4 files changed, 59 insertions, 21 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index 37a9c02124e..d2aaa5646a8 100644 --- a/sql/sp.cc +++ b/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) { @@ -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); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7bc5aac270b..c67ce383398 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -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); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1cbc616f63f..2b76024105e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -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; |