summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp-security.result12
-rw-r--r--mysql-test/r/sp.result16
-rw-r--r--mysql-test/t/sp-security.test8
-rw-r--r--mysql-test/t/sp.test26
-rw-r--r--sql/sp.cc64
-rw-r--r--sql/sp.h4
-rw-r--r--sql/sp_cache.cc7
-rw-r--r--sql/sp_cache.h3
-rw-r--r--sql/sql_db.cc2
9 files changed, 134 insertions, 8 deletions
diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result
index 25bceb0f54f..60adad0181c 100644
--- a/mysql-test/r/sp-security.result
+++ b/mysql-test/r/sp-security.result
@@ -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';
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index f1fa1735ead..620f22aca68 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -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;
diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test
index ae977684129..8fc51357bc4 100644
--- a/mysql-test/t/sp-security.test
+++ b/mysql-test/t/sp-security.test
@@ -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';
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 5dae97b371e..943e150ce1f 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -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
#
diff --git a/sql/sp.cc b/sql/sp.cc
index 389c627f5f3..ede6cfeb84b 100644
--- a/sql/sp.cc
+++ b/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
******************************************************************************/
diff --git a/sql/sp.h b/sql/sp.h
index ffe3f31c157..a4fec50aca2 100644
--- a/sql/sp.h
+++ b/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);
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index e13fb2695e7..056ac6d7e96 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -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,
diff --git a/sql/sp_cache.h b/sql/sp_cache.h
index 253e9b11588..754a987090e 100644
--- a/sql/sp_cache.h
+++ b/sql/sp_cache.h
@@ -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();
+
/*
*
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index bc6b30040d6..54265b58bd4 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -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