WL#1366: Use the schema (db) associated with an SP.
Phase 4 (final): Remove associated stored procedures when a database is dropped. mysql-test/r/sp-security.result: drop database now deletes associated SPs. mysql-test/r/sp.result: drop database now deletes associated SPs. mysql-test/t/sp-security.test: drop database now deletes associated SPs. mysql-test/t/sp.test: drop database now deletes associated SPs. sql/sp.cc: New function for deleting all SPs associated with a database. sql/sp.h: New function for deleting all SPs associated with a database. sql/sp_cache.cc: New function for just invalidating all SP caches (when dropping a database). sql/sp_cache.h: New function for just invalidating all SP caches (when dropping a database). sql/sql_db.cc: When dropping a database, also delete all associated SPs.
This commit is contained in:
parent
d2ad3cff19
commit
645d19f694
@ -97,11 +97,15 @@ s1
|
||||
0
|
||||
2
|
||||
2
|
||||
drop procedure db1_secret.stamp;
|
||||
drop function db1_secret.db;
|
||||
drop procedure db2.p;
|
||||
drop procedure db2.q;
|
||||
use test;
|
||||
select type,db,name from mysql.proc;
|
||||
type db name
|
||||
FUNCTION db1_secret db
|
||||
PROCEDURE db1_secret stamp
|
||||
PROCEDURE db2 p
|
||||
PROCEDURE db2 q
|
||||
drop database db1_secret;
|
||||
drop database db2;
|
||||
select type,db,name from mysql.proc;
|
||||
type db name
|
||||
delete from mysql.user where user='user1' or user='user2';
|
||||
|
@ -786,6 +786,22 @@ select @c1, @c2|
|
||||
12 3
|
||||
delete from t1|
|
||||
drop procedure modes|
|
||||
create database sp_db1|
|
||||
drop database sp_db1|
|
||||
create database sp_db2|
|
||||
use sp_db2|
|
||||
create table t3 ( s char(4), t int )|
|
||||
insert into t3 values ("abcd", 42), ("dcba", 666)|
|
||||
use test|
|
||||
drop database sp_db2|
|
||||
create database sp_db3|
|
||||
use sp_db3|
|
||||
create procedure dummy(out x int)
|
||||
set x = 42|
|
||||
use test|
|
||||
drop database sp_db3|
|
||||
select type,db,name from mysql.proc where db = 'sp_db3'|
|
||||
type db name
|
||||
create procedure bug822(a_id char(16), a_data int)
|
||||
begin
|
||||
declare n int;
|
||||
|
@ -163,11 +163,11 @@ select * from t2;
|
||||
|
||||
# Clean up
|
||||
connection con1root;
|
||||
drop procedure db1_secret.stamp;
|
||||
drop function db1_secret.db;
|
||||
drop procedure db2.p;
|
||||
drop procedure db2.q;
|
||||
use test;
|
||||
select type,db,name from mysql.proc;
|
||||
drop database db1_secret;
|
||||
drop database db2;
|
||||
# Make sure the routines are gone
|
||||
select type,db,name from mysql.proc;
|
||||
# Get rid of the users
|
||||
delete from mysql.user where user='user1' or user='user2';
|
||||
|
@ -905,6 +905,32 @@ delete from t1|
|
||||
drop procedure modes|
|
||||
|
||||
|
||||
# Check that dropping a database without routines works.
|
||||
# (Dropping with routines is tested in sp-security.test)
|
||||
# First an empty db.
|
||||
create database sp_db1|
|
||||
drop database sp_db1|
|
||||
|
||||
# Again, with a table.
|
||||
create database sp_db2|
|
||||
use sp_db2|
|
||||
# Just put something in here...
|
||||
create table t3 ( s char(4), t int )|
|
||||
insert into t3 values ("abcd", 42), ("dcba", 666)|
|
||||
use test|
|
||||
drop database sp_db2|
|
||||
|
||||
# And yet again, with just a procedure.
|
||||
create database sp_db3|
|
||||
use sp_db3|
|
||||
create procedure dummy(out x int)
|
||||
set x = 42|
|
||||
use test|
|
||||
drop database sp_db3|
|
||||
# Check that it's gone
|
||||
select type,db,name from mysql.proc where db = 'sp_db3'|
|
||||
|
||||
|
||||
#
|
||||
# Test cases for old bugs
|
||||
#
|
||||
|
64
sql/sp.cc
64
sql/sp.cc
@ -589,6 +589,70 @@ done:
|
||||
}
|
||||
|
||||
|
||||
/* Drop all routines in database 'db' */
|
||||
int
|
||||
sp_drop_db_routines(THD *thd, char *db)
|
||||
{
|
||||
TABLE *table;
|
||||
byte key[64]; // db
|
||||
uint keylen;
|
||||
int ret;
|
||||
DBUG_ENTER("sp_drop_db_routines");
|
||||
DBUG_PRINT("enter", ("db: %s", db));
|
||||
|
||||
// Put the key used to read the row together
|
||||
keylen= strlen(db);
|
||||
if (keylen > 64)
|
||||
keylen= 64;
|
||||
memcpy(key, db, keylen);
|
||||
memset(key+keylen, (int)' ', 64-keylen); // Pad with space
|
||||
keylen= sizeof(key);
|
||||
|
||||
for (table= thd->open_tables ; table ; table= table->next)
|
||||
if (strcmp(table->table_cache_key, "mysql") == 0 &&
|
||||
strcmp(table->real_name, "proc") == 0)
|
||||
break;
|
||||
if (! table)
|
||||
{
|
||||
TABLE_LIST tables;
|
||||
|
||||
memset(&tables, 0, sizeof(tables));
|
||||
tables.db= (char*)"mysql";
|
||||
tables.real_name= tables.alias= (char*)"proc";
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE)))
|
||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||
}
|
||||
|
||||
ret= SP_OK;
|
||||
table->file->index_init(0);
|
||||
if (! table->file->index_read(table->record[0],
|
||||
key, keylen, HA_READ_KEY_EXACT))
|
||||
{
|
||||
int nxtres;
|
||||
bool deleted= FALSE;
|
||||
|
||||
do {
|
||||
if (! table->file->delete_row(table->record[0]))
|
||||
deleted= TRUE; /* We deleted something */
|
||||
else
|
||||
{
|
||||
ret= SP_DELETE_ROW_FAILED;
|
||||
break;
|
||||
}
|
||||
} while (! (nxtres= table->file->index_next_same(table->record[0],
|
||||
key, keylen)));
|
||||
if (nxtres != HA_ERR_END_OF_FILE)
|
||||
ret= SP_KEY_NOT_FOUND;
|
||||
if (deleted)
|
||||
sp_cache_invalidate();
|
||||
}
|
||||
|
||||
close_thread_tables(thd);
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
PROCEDURE
|
||||
******************************************************************************/
|
||||
|
4
sql/sp.h
4
sql/sp.h
@ -28,6 +28,10 @@
|
||||
#define SP_PARSE_ERROR -6
|
||||
#define SP_INTERNAL_ERROR -7
|
||||
|
||||
/* Drop all routines in database 'db' */
|
||||
int
|
||||
sp_drop_db_routines(THD *thd, char *db);
|
||||
|
||||
sp_head *
|
||||
sp_find_procedure(THD *thd, sp_name *name);
|
||||
|
||||
|
@ -115,6 +115,13 @@ sp_cache_remove(sp_cache **cp, sp_name *name)
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
sp_cache_invalidate()
|
||||
{
|
||||
pthread_mutex_lock(&Cversion_lock); // LOCK
|
||||
Cversion++;
|
||||
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
||||
}
|
||||
|
||||
static byte *
|
||||
hash_get_key_for_sp_head(const byte *ptr, uint *plen,
|
||||
|
@ -40,6 +40,9 @@ sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
|
||||
/* Remove an SP from cache. Returns true if something was removed */
|
||||
bool sp_cache_remove(sp_cache **cp, sp_name *name);
|
||||
|
||||
/* Invalidate a cache */
|
||||
void sp_cache_invalidate();
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "mysql_priv.h"
|
||||
#include "sql_acl.h"
|
||||
#include "sp.h"
|
||||
#include <my_dir.h>
|
||||
#include <m_ctype.h>
|
||||
#ifdef __WIN__
|
||||
@ -386,6 +387,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
||||
}
|
||||
|
||||
exit:
|
||||
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
||||
start_waiting_global_read_lock(thd);
|
||||
/*
|
||||
If this database was the client's selected database, we silently change the
|
||||
|
Loading…
x
Reference in New Issue
Block a user