Fixed save/restore of current database when calling a procedure.
This commit is contained in:
parent
3946b8235c
commit
2c9ef84cc3
@ -243,6 +243,23 @@
|
||||
5) On success, set the new values of the OUT and INOUT parameters in
|
||||
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
|
||||
|
||||
@ -340,6 +357,9 @@
|
||||
Dropping is done by simply getting the procedure with the sp_find()
|
||||
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
|
||||
|
||||
|
@ -18,6 +18,16 @@ id data
|
||||
foo 42
|
||||
delete from t1;
|
||||
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)
|
||||
insert into test.t1 values (x, y);
|
||||
call bar("bar", 666);
|
||||
|
@ -31,6 +31,18 @@ delete from t1;
|
||||
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.
|
||||
create procedure bar(x char(16), y int)
|
||||
insert into test.t1 values (x, y);
|
||||
|
@ -131,9 +131,14 @@ int
|
||||
sp_head::execute(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("sp_head::execute");
|
||||
char *olddbname;
|
||||
char *olddbptr= thd->db;
|
||||
int ret= 0;
|
||||
uint ip= 0;
|
||||
|
||||
if (olddbptr)
|
||||
olddbname= my_strdup(olddbptr, MYF(MY_WME));
|
||||
|
||||
do
|
||||
{
|
||||
sp_instr *i;
|
||||
@ -144,6 +149,16 @@ sp_head::execute(THD *thd)
|
||||
DBUG_PRINT("execute", ("Instruction %u", ip));
|
||||
ret= i->execute(thd, &ip);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user