Commit 483efba2 authored by pem@mysql.com's avatar pem@mysql.com

Fixed save/restore of current database when calling a procedure.

parent 25785647
...@@ -243,6 +243,23 @@ ...@@ -243,6 +243,23 @@
5) On success, set the new values of the OUT and INOUT parameters in 5) On success, set the new values of the OUT and INOUT parameters in
the caller's frame. the caller's frame.
- USE database
Before executing the instruction we also keeps the current default
database (if any). If this was changed during execution (i.e. a "USE"
statement has been executed), we restore the current database to the
original.
This is the most useful way to handle USE in procedures. If we didn't,
the caller would find himself in a different database after calling
a function, which can be confusing.
Restoring the database also gives full freedom to the procedure writer:
- It's possible to write "general" procedures that are independent of
the actual database name.
- It's possible to write procedures that work on a particular database
by calling USE, without having to use fully qualified table names
everywhere (which doesn't help if you want to call other, "general",
procedures anyway).
- Evaluating Items - Evaluating Items
...@@ -340,6 +357,9 @@ ...@@ -340,6 +357,9 @@
Dropping is done by simply getting the procedure with the sp_find() Dropping is done by simply getting the procedure with the sp_find()
function and calling sp_drop() (both in sp.{cc,h}). function and calling sp_drop() (both in sp.{cc,h}).
DROP PROCEDURE/FUNCTION also supports the non-standard "IF EXISTS",
analogous to other DROP statements in MySQL.
- Class and function APIs - Class and function APIs
......
...@@ -18,6 +18,16 @@ id data ...@@ -18,6 +18,16 @@ id data
foo 42 foo 42
delete from t1; delete from t1;
drop procedure foo42; drop procedure foo42;
create procedure u()
use sptmp;
create database sptmp;
use test;
call u();
select database();
database()
test
drop database sptmp;
drop procedure u;
create procedure bar(x char(16), y int) create procedure bar(x char(16), y int)
insert into test.t1 values (x, y); insert into test.t1 values (x, y);
call bar("bar", 666); call bar("bar", 666);
......
...@@ -31,6 +31,18 @@ delete from t1; ...@@ -31,6 +31,18 @@ delete from t1;
drop procedure foo42; drop procedure foo42;
# USE test: Make sure we remain in the same DB.
create procedure u()
use sptmp;
create database sptmp;
use test;
call u();
select database();
drop database sptmp;
drop procedure u;
# Single statement, two IN params. # Single statement, two IN params.
create procedure bar(x char(16), y int) create procedure bar(x char(16), y int)
insert into test.t1 values (x, y); insert into test.t1 values (x, y);
......
...@@ -131,9 +131,14 @@ int ...@@ -131,9 +131,14 @@ int
sp_head::execute(THD *thd) sp_head::execute(THD *thd)
{ {
DBUG_ENTER("sp_head::execute"); DBUG_ENTER("sp_head::execute");
char *olddbname;
char *olddbptr= thd->db;
int ret= 0; int ret= 0;
uint ip= 0; uint ip= 0;
if (olddbptr)
olddbname= my_strdup(olddbptr, MYF(MY_WME));
do do
{ {
sp_instr *i; sp_instr *i;
...@@ -144,6 +149,16 @@ sp_head::execute(THD *thd) ...@@ -144,6 +149,16 @@ sp_head::execute(THD *thd)
DBUG_PRINT("execute", ("Instruction %u", ip)); DBUG_PRINT("execute", ("Instruction %u", ip));
ret= i->execute(thd, &ip); ret= i->execute(thd, &ip);
} while (ret == 0); } while (ret == 0);
/* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */
if (olddbptr && olddbptr != thd->db && olddbname)
{
/* QQ Maybe we should issue some special error message or warning here,
if this fails?? */
ret= mysql_change_db(thd, olddbname);
my_free(olddbname, MYF(0));
}
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
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