mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
WL#1366: Use the schema (db) associated with an SP.
Phase 2: Make SPs belong to a DB, and use qualified names. As a side effect, using USE in an SP is no longer allowed. (It just doesn't work otherwise.) include/mysqld_error.h: New error code (USE is no longer allowed in a stored procedure). include/sql_state.h: New error state (USE is no longer allowed in a stored procedure). mysql-test/r/sp-error.result: Updated result for test of USE in SP (not allowed now). mysql-test/r/sp-security.result: Updated test results for new db column and qualified procedured names. mysql-test/r/sp.result: Updated results for USE in SP (as it's no longer allowed), and for new db column in status result. mysql-test/t/sp-error.test: Moved test of USE in SP from sp.test (as it's no longer allowed). mysql-test/t/sp-security.test: Ajusted tests for new db column and qualified procedured names. mysql-test/t/sp.test: Moved test of USE in SP to sp-error.test (as it's no longer allowed). Adjusted tests for new db column in status result. sql/mysql_priv.h: mysql_change_db() now has optional arguments for use by SP with qualified names. sql/share/czech/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/danish/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/dutch/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/english/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/estonian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/french/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/german/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/greek/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/hungarian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/italian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/japanese/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/korean/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/norwegian-ny/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/norwegian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/polish/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/portuguese/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/romanian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/russian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/serbian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/slovak/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/spanish/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/swedish/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/share/ukrainian/errmsg.txt: New error message: USE is not allowed in a stored procedure. sql/sp.cc: SPs are now "belong" to a DB and may have qualified names. New functions for changing DB ("use") when parsing and invoking SPs. sql/sp.h: New functions for changing DB ("use") when parsing and invoking SPs. sql/sp_cache.cc: Use the qualified name in the SP cache. sql/sp_head.cc: New function for allocating a qualified SP name (used in sql_yacc.yy). Change DB when executing an SP (if needed). Moved thd_mem_root swap functions from sp_head.h. sql/sp_head.h: New function for allocating a qualified SP name (used in sql_yacc.yy). Moved thd_mem_root swap functions to sp_head.cc. sql/sql_db.cc: mysql_change_db() now has optional arguments for use by SP with qualified names (for use when reading an SP from database and executing it); also allow "unusing" a database, i.e. setting thd->thd to "". sql/sql_yacc.yy: Initialize qualfied SP names correctly. USE is no longer allowed in an SP.
This commit is contained in:
@ -339,4 +339,5 @@
|
|||||||
#define ER_SP_DUP_CURS 1320
|
#define ER_SP_DUP_CURS 1320
|
||||||
#define ER_SP_CANT_ALTER 1321
|
#define ER_SP_CANT_ALTER 1321
|
||||||
#define ER_SP_SUBSELECT_NYI 1322
|
#define ER_SP_SUBSELECT_NYI 1322
|
||||||
#define ER_ERROR_MESSAGES 323
|
#define ER_SP_NO_USE 1323
|
||||||
|
#define ER_ERROR_MESSAGES 324
|
||||||
|
@ -196,3 +196,4 @@ ER_SP_DUP_COND, "42000", "",
|
|||||||
ER_SP_DUP_CURS, "42000", "",
|
ER_SP_DUP_CURS, "42000", "",
|
||||||
/*ER_SP_CANT_ALTER*/
|
/*ER_SP_CANT_ALTER*/
|
||||||
ER_SP_SUBSELECT_NYI, "0A000", "",
|
ER_SP_SUBSELECT_NYI, "0A000", "",
|
||||||
|
ER_SP_NO_USE, "42000", "",
|
||||||
|
@ -251,6 +251,10 @@ declare c cursor for select * from t1;
|
|||||||
declare c cursor for select field from t1;
|
declare c cursor for select field from t1;
|
||||||
end|
|
end|
|
||||||
ERROR 42000: Duplicate cursor: c
|
ERROR 42000: Duplicate cursor: c
|
||||||
|
create procedure u()
|
||||||
|
use sptmp;
|
||||||
|
#|
|
||||||
|
ERROR 42000: USE is not allowed in a stored procedure
|
||||||
create procedure bug1965()
|
create procedure bug1965()
|
||||||
begin
|
begin
|
||||||
declare c cursor for select val from t1 order by valname;
|
declare c cursor for select val from t1 order by valname;
|
||||||
|
@ -8,16 +8,16 @@ create table t1 ( u varchar(64), i int );
|
|||||||
create procedure stamp(i int)
|
create procedure stamp(i int)
|
||||||
insert into db1_secret.t1 values (user(), i);
|
insert into db1_secret.t1 values (user(), i);
|
||||||
show procedure status like 'stamp';
|
show procedure status like 'stamp';
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
call stamp(1);
|
call stamp(1);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
u i
|
u i
|
||||||
root@localhost 1
|
root@localhost 1
|
||||||
call stamp(2);
|
call db1_secret.stamp(2);
|
||||||
select * from db1_secret.t1;
|
select * from db1_secret.t1;
|
||||||
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
|
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
|
||||||
call stamp(3);
|
call db1_secret.stamp(3);
|
||||||
select * from db1_secret.t1;
|
select * from db1_secret.t1;
|
||||||
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
|
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
|
||||||
select * from t1;
|
select * from t1;
|
||||||
@ -27,8 +27,8 @@ user1@localhost 2
|
|||||||
anon@localhost 3
|
anon@localhost 3
|
||||||
alter procedure stamp sql security invoker;
|
alter procedure stamp sql security invoker;
|
||||||
show procedure status like 'stamp';
|
show procedure status like 'stamp';
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
|
db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
|
||||||
call stamp(4);
|
call stamp(4);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
u i
|
u i
|
||||||
@ -36,9 +36,9 @@ root@localhost 1
|
|||||||
user1@localhost 2
|
user1@localhost 2
|
||||||
anon@localhost 3
|
anon@localhost 3
|
||||||
root@localhost 4
|
root@localhost 4
|
||||||
call stamp(5);
|
call db1_secret.stamp(5);
|
||||||
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
|
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
|
||||||
call stamp(6);
|
call db1_secret.stamp(6);
|
||||||
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
|
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
|
||||||
drop database if exists db2;
|
drop database if exists db2;
|
||||||
create database db2;
|
create database db2;
|
||||||
@ -73,9 +73,9 @@ s1
|
|||||||
0
|
0
|
||||||
2
|
2
|
||||||
2
|
2
|
||||||
drop procedure stamp;
|
drop procedure db1_secret.stamp;
|
||||||
drop procedure p;
|
drop procedure db2.p;
|
||||||
drop procedure q;
|
drop procedure db2.q;
|
||||||
use test;
|
use test;
|
||||||
drop database db1_secret;
|
drop database db1_secret;
|
||||||
drop database db2;
|
drop database db2;
|
||||||
|
@ -18,17 +18,6 @@ id data
|
|||||||
foo 42
|
foo 42
|
||||||
delete from t1;
|
delete from t1;
|
||||||
drop procedure foo42;
|
drop procedure foo42;
|
||||||
create procedure u()
|
|
||||||
use sptmp;
|
|
||||||
drop database if exists 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);
|
||||||
@ -746,7 +735,7 @@ delete from t1|
|
|||||||
alter procedure chistics sql security invoker name chistics2|
|
alter procedure chistics sql security invoker name chistics2|
|
||||||
show create procedure chistics2|
|
show create procedure chistics2|
|
||||||
Procedure Create Procedure
|
Procedure Create Procedure
|
||||||
chistics2 CREATE PROCEDURE `chistics2`()
|
chistics2 CREATE PROCEDURE `test`.`chistics2`()
|
||||||
SQL SECURITY INVOKER
|
SQL SECURITY INVOKER
|
||||||
COMMENT 'Characteristics procedure test'
|
COMMENT 'Characteristics procedure test'
|
||||||
insert into t1 values ("chistics", 1)
|
insert into t1 values ("chistics", 1)
|
||||||
@ -763,7 +752,7 @@ chistics()
|
|||||||
alter function chistics name chistics2 comment 'Characteristics function test'|
|
alter function chistics name chistics2 comment 'Characteristics function test'|
|
||||||
show create function chistics2|
|
show create function chistics2|
|
||||||
Function Create Function
|
Function Create Function
|
||||||
chistics2 CREATE FUNCTION `chistics2`() RETURNS int
|
chistics2 CREATE FUNCTION `test`.`chistics2`() RETURNS int
|
||||||
DETERMINISTIC
|
DETERMINISTIC
|
||||||
SQL SECURITY INVOKER
|
SQL SECURITY INVOKER
|
||||||
COMMENT 'Characteristics function test'
|
COMMENT 'Characteristics function test'
|
||||||
@ -939,23 +928,23 @@ begin
|
|||||||
show create function fac;
|
show create function fac;
|
||||||
end|
|
end|
|
||||||
call bug2267_1()|
|
call bug2267_1()|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
call bug2267_2()|
|
call bug2267_2()|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
call bug2267_3()|
|
call bug2267_3()|
|
||||||
Procedure Create Procedure
|
Procedure Create Procedure
|
||||||
bug2267_1 CREATE PROCEDURE `bug2267_1`()
|
bug2267_1 CREATE PROCEDURE `test`.`bug2267_1`()
|
||||||
begin
|
begin
|
||||||
show procedure status;
|
show procedure status;
|
||||||
end
|
end
|
||||||
call bug2267_4()|
|
call bug2267_4()|
|
||||||
Function Create Function
|
Function Create Function
|
||||||
fac CREATE FUNCTION `fac`(n int unsigned) RETURNS bigint unsigned
|
fac CREATE FUNCTION `test`.`fac`(n int unsigned) RETURNS bigint unsigned
|
||||||
begin
|
begin
|
||||||
declare f bigint unsigned default 1;
|
declare f bigint unsigned default 1;
|
||||||
while n > 1 do
|
while n > 1 do
|
||||||
@ -1029,12 +1018,12 @@ n f
|
|||||||
20 2432902008176640000
|
20 2432902008176640000
|
||||||
drop table fac|
|
drop table fac|
|
||||||
show function status like '%f%'|
|
show function status like '%f%'|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
drop procedure ifac|
|
drop procedure ifac|
|
||||||
drop function fac|
|
drop function fac|
|
||||||
show function status like '%f%'|
|
show function status like '%f%'|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
drop table if exists primes|
|
drop table if exists primes|
|
||||||
create table primes (
|
create table primes (
|
||||||
i int unsigned not null primary key,
|
i int unsigned not null primary key,
|
||||||
@ -1095,7 +1084,7 @@ end while;
|
|||||||
end|
|
end|
|
||||||
show create procedure opp|
|
show create procedure opp|
|
||||||
Procedure Create Procedure
|
Procedure Create Procedure
|
||||||
opp CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
|
opp CREATE PROCEDURE `test`.`opp`(n bigint unsigned, out pp bool)
|
||||||
begin
|
begin
|
||||||
declare r double;
|
declare r double;
|
||||||
declare b, s bigint unsigned default 0;
|
declare b, s bigint unsigned default 0;
|
||||||
@ -1122,9 +1111,9 @@ end if;
|
|||||||
end loop;
|
end loop;
|
||||||
end
|
end
|
||||||
show procedure status like '%p%'|
|
show procedure status like '%p%'|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||||
call ip(200)|
|
call ip(200)|
|
||||||
select * from primes where i=45 or i=100 or i=199|
|
select * from primes where i=45 or i=100 or i=199|
|
||||||
i p
|
i p
|
||||||
@ -1135,7 +1124,7 @@ drop table primes|
|
|||||||
drop procedure opp|
|
drop procedure opp|
|
||||||
drop procedure ip|
|
drop procedure ip|
|
||||||
show procedure status like '%p%'|
|
show procedure status like '%p%'|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
drop table if exists fib|
|
drop table if exists fib|
|
||||||
create table fib ( f bigint unsigned not null )|
|
create table fib ( f bigint unsigned not null )|
|
||||||
insert into fib values (1), (1)|
|
insert into fib values (1), (1)|
|
||||||
@ -1185,19 +1174,19 @@ create procedure bar(x char(16), y int)
|
|||||||
comment "111111111111" sql security invoker
|
comment "111111111111" sql security invoker
|
||||||
insert into test.t1 values (x, y)|
|
insert into test.t1 values (x, y)|
|
||||||
show procedure status like 'bar'|
|
show procedure status like 'bar'|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111
|
test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111
|
||||||
alter procedure bar name bar2 comment "2222222222" sql security definer|
|
alter procedure bar name bar2 comment "2222222222" sql security definer|
|
||||||
alter procedure bar2 name bar comment "3333333333"|
|
alter procedure bar2 name bar comment "3333333333"|
|
||||||
alter procedure bar|
|
alter procedure bar|
|
||||||
show create procedure bar|
|
show create procedure bar|
|
||||||
Procedure Create Procedure
|
Procedure Create Procedure
|
||||||
bar CREATE PROCEDURE `bar`(x char(16), y int)
|
bar CREATE PROCEDURE `test`.`bar`(x char(16), y int)
|
||||||
COMMENT '3333333333'
|
COMMENT '3333333333'
|
||||||
insert into test.t1 values (x, y)
|
insert into test.t1 values (x, y)
|
||||||
show procedure status like 'bar'|
|
show procedure status like 'bar'|
|
||||||
Name Type Definer Modified Created Security_type Comment
|
Db Name Type Definer Modified Created Security_type Comment
|
||||||
bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER 3333333333
|
test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER 3333333333
|
||||||
drop procedure bar|
|
drop procedure bar|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
@ -330,6 +330,12 @@ begin
|
|||||||
declare c cursor for select field from t1;
|
declare c cursor for select field from t1;
|
||||||
end|
|
end|
|
||||||
|
|
||||||
|
# USE is not allowed
|
||||||
|
--error 1323
|
||||||
|
create procedure u()
|
||||||
|
use sptmp;
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#1965
|
# BUG#1965
|
||||||
#
|
#
|
||||||
|
@ -24,7 +24,7 @@ create table t1 ( u varchar(64), i int );
|
|||||||
# Our test procedure
|
# Our test procedure
|
||||||
create procedure stamp(i int)
|
create procedure stamp(i int)
|
||||||
insert into db1_secret.t1 values (user(), i);
|
insert into db1_secret.t1 values (user(), i);
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show procedure status like 'stamp';
|
show procedure status like 'stamp';
|
||||||
|
|
||||||
# root can, of course
|
# root can, of course
|
||||||
@ -40,7 +40,7 @@ connect (con3anon,localhost,anon,,);
|
|||||||
connection con2user1;
|
connection con2user1;
|
||||||
|
|
||||||
# This should work...
|
# This should work...
|
||||||
call stamp(2);
|
call db1_secret.stamp(2);
|
||||||
|
|
||||||
# ...but not this
|
# ...but not this
|
||||||
--error 1044
|
--error 1044
|
||||||
@ -52,7 +52,7 @@ select * from db1_secret.t1;
|
|||||||
connection con3anon;
|
connection con3anon;
|
||||||
|
|
||||||
# This should work...
|
# This should work...
|
||||||
call stamp(3);
|
call db1_secret.stamp(3);
|
||||||
|
|
||||||
# ...but not this
|
# ...but not this
|
||||||
--error 1044
|
--error 1044
|
||||||
@ -68,7 +68,7 @@ select * from t1;
|
|||||||
# Change to invoker's rights
|
# Change to invoker's rights
|
||||||
#
|
#
|
||||||
alter procedure stamp sql security invoker;
|
alter procedure stamp sql security invoker;
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show procedure status like 'stamp';
|
show procedure status like 'stamp';
|
||||||
|
|
||||||
# root still can
|
# root still can
|
||||||
@ -82,7 +82,7 @@ connection con2user1;
|
|||||||
|
|
||||||
# This should not work
|
# This should not work
|
||||||
--error 1044
|
--error 1044
|
||||||
call stamp(5);
|
call db1_secret.stamp(5);
|
||||||
|
|
||||||
#
|
#
|
||||||
# Anonymous cannot
|
# Anonymous cannot
|
||||||
@ -91,7 +91,7 @@ connection con3anon;
|
|||||||
|
|
||||||
# This should not work
|
# This should not work
|
||||||
--error 1044
|
--error 1044
|
||||||
call stamp(6);
|
call db1_secret.stamp(6);
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -148,9 +148,9 @@ select * from t2;
|
|||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
connection con1root;
|
connection con1root;
|
||||||
drop procedure stamp;
|
drop procedure db1_secret.stamp;
|
||||||
drop procedure p;
|
drop procedure db2.p;
|
||||||
drop procedure q;
|
drop procedure db2.q;
|
||||||
use test;
|
use test;
|
||||||
drop database db1_secret;
|
drop database db1_secret;
|
||||||
drop database db2;
|
drop database db2;
|
||||||
|
@ -31,21 +31,6 @@ delete from t1;
|
|||||||
drop procedure foo42;
|
drop procedure foo42;
|
||||||
|
|
||||||
|
|
||||||
# USE test: Make sure we remain in the same DB.
|
|
||||||
create procedure u()
|
|
||||||
use sptmp;
|
|
||||||
|
|
||||||
--disable_warnings
|
|
||||||
drop database if exists sptmp;
|
|
||||||
--enable_warnings
|
|
||||||
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);
|
||||||
@ -1094,9 +1079,9 @@ begin
|
|||||||
show create function fac;
|
show create function fac;
|
||||||
end|
|
end|
|
||||||
|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
call bug2267_1()|
|
call bug2267_1()|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
call bug2267_2()|
|
call bug2267_2()|
|
||||||
call bug2267_3()|
|
call bug2267_3()|
|
||||||
call bug2267_4()|
|
call bug2267_4()|
|
||||||
@ -1168,11 +1153,11 @@ end|
|
|||||||
call ifac(20)|
|
call ifac(20)|
|
||||||
select * from fac|
|
select * from fac|
|
||||||
drop table fac|
|
drop table fac|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show function status like '%f%'|
|
show function status like '%f%'|
|
||||||
drop procedure ifac|
|
drop procedure ifac|
|
||||||
drop function fac|
|
drop function fac|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show function status like '%f%'|
|
show function status like '%f%'|
|
||||||
|
|
||||||
|
|
||||||
@ -1249,7 +1234,7 @@ begin
|
|||||||
end while;
|
end while;
|
||||||
end|
|
end|
|
||||||
show create procedure opp|
|
show create procedure opp|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show procedure status like '%p%'|
|
show procedure status like '%p%'|
|
||||||
|
|
||||||
# This isn't the fastest way in the world to compute prime numbers, so
|
# This isn't the fastest way in the world to compute prime numbers, so
|
||||||
@ -1261,7 +1246,7 @@ select * from primes where i=45 or i=100 or i=199|
|
|||||||
drop table primes|
|
drop table primes|
|
||||||
drop procedure opp|
|
drop procedure opp|
|
||||||
drop procedure ip|
|
drop procedure ip|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show procedure status like '%p%'|
|
show procedure status like '%p%'|
|
||||||
|
|
||||||
|
|
||||||
@ -1308,13 +1293,13 @@ drop procedure fib|
|
|||||||
create procedure bar(x char(16), y int)
|
create procedure bar(x char(16), y int)
|
||||||
comment "111111111111" sql security invoker
|
comment "111111111111" sql security invoker
|
||||||
insert into test.t1 values (x, y)|
|
insert into test.t1 values (x, y)|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show procedure status like 'bar'|
|
show procedure status like 'bar'|
|
||||||
alter procedure bar name bar2 comment "2222222222" sql security definer|
|
alter procedure bar name bar2 comment "2222222222" sql security definer|
|
||||||
alter procedure bar2 name bar comment "3333333333"|
|
alter procedure bar2 name bar comment "3333333333"|
|
||||||
alter procedure bar|
|
alter procedure bar|
|
||||||
show create procedure bar|
|
show create procedure bar|
|
||||||
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||||
show procedure status like 'bar'|
|
show procedure status like 'bar'|
|
||||||
drop procedure bar|
|
drop procedure bar|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
@ -445,7 +445,8 @@ int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
|
|||||||
int quick_rm_table(enum db_type base,const char *db,
|
int quick_rm_table(enum db_type base,const char *db,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
|
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
|
||||||
bool mysql_change_db(THD *thd,const char *name);
|
bool mysql_change_db(THD *thd,const char *name,
|
||||||
|
bool empty_is_ok=0, bool no_access_check=0);
|
||||||
void mysql_parse(THD *thd,char *inBuf,uint length);
|
void mysql_parse(THD *thd,char *inBuf,uint length);
|
||||||
bool is_update_query(enum enum_sql_command command);
|
bool is_update_query(enum enum_sql_command command);
|
||||||
void free_items(Item *item);
|
void free_items(Item *item);
|
||||||
|
@ -335,3 +335,4 @@ character-set=latin2
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -329,3 +329,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -337,3 +337,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -326,3 +326,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -331,3 +331,4 @@ character-set=latin7
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -326,3 +326,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -338,3 +338,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -326,3 +326,4 @@ character-set=greek
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -328,3 +328,4 @@ character-set=latin2
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -326,3 +326,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -328,3 +328,4 @@ character-set=ujis
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -326,3 +326,4 @@ character-set=euckr
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -328,3 +328,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -328,3 +328,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -330,3 +330,4 @@ character-set=latin2
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -327,3 +327,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -330,3 +330,4 @@ character-set=latin2
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -328,3 +328,4 @@ character-set=koi8r
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -321,3 +321,4 @@ character-set=cp1250
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -334,3 +334,4 @@ character-set=latin2
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -328,3 +328,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -326,3 +326,4 @@ character-set=latin1
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
@ -331,3 +331,4 @@ character-set=koi8u
|
|||||||
"Duplicate cursor: %s"
|
"Duplicate cursor: %s"
|
||||||
"Failed to ALTER %s %s"
|
"Failed to ALTER %s %s"
|
||||||
"Subselect value not supported"
|
"Subselect value not supported"
|
||||||
|
"USE is not allowed in a stored procedure"
|
||||||
|
147
sql/sp.cc
147
sql/sp.cc
@ -23,7 +23,7 @@
|
|||||||
static char *
|
static char *
|
||||||
create_string(THD *thd, ulong *lenp,
|
create_string(THD *thd, ulong *lenp,
|
||||||
int sp_type,
|
int sp_type,
|
||||||
char *name, ulong namelen,
|
sp_name *name,
|
||||||
const char *params, ulong paramslen,
|
const char *params, ulong paramslen,
|
||||||
const char *returns, ulong returnslen,
|
const char *returns, ulong returnslen,
|
||||||
const char *body, ulong bodylen,
|
const char *body, ulong bodylen,
|
||||||
@ -69,7 +69,11 @@ db_find_routine_aux(THD *thd, int type, sp_name *name,
|
|||||||
type, name->m_name.length, name->m_name.str));
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
// Put the key used to read the row together
|
// Put the key used to read the row together
|
||||||
memset(key, (int)' ', 64); // QQ Empty db for now
|
keylen= name->m_db.length;
|
||||||
|
if (keylen > 64)
|
||||||
|
keylen= 64;
|
||||||
|
memcpy(key, name->m_db.str, keylen);
|
||||||
|
memset(key+keylen, (int)' ', 64-keylen); // Pad with space
|
||||||
keylen= name->m_name.length;
|
keylen= name->m_name.length;
|
||||||
if (keylen > 64)
|
if (keylen > 64)
|
||||||
keylen= 64;
|
keylen= 64;
|
||||||
@ -213,6 +217,8 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||||||
char *defstr;
|
char *defstr;
|
||||||
ulong deflen;
|
ulong deflen;
|
||||||
LEX *oldlex= thd->lex;
|
LEX *oldlex= thd->lex;
|
||||||
|
char olddb[128];
|
||||||
|
char *olddbptr;
|
||||||
enum enum_sql_command oldcmd= thd->lex->sql_command;
|
enum enum_sql_command oldcmd= thd->lex->sql_command;
|
||||||
ulong old_sql_mode= thd->variables.sql_mode;
|
ulong old_sql_mode= thd->variables.sql_mode;
|
||||||
ha_rows select_limit= thd->variables.select_limit;
|
ha_rows select_limit= thd->variables.select_limit;
|
||||||
@ -221,23 +227,30 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||||||
thd->variables.select_limit= HA_POS_ERROR;
|
thd->variables.select_limit= HA_POS_ERROR;
|
||||||
|
|
||||||
if (!(defstr= create_string(thd, &deflen,
|
if (!(defstr= create_string(thd, &deflen,
|
||||||
type,
|
type,
|
||||||
name->m_name.str, name->m_name.length,
|
name,
|
||||||
params, strlen(params),
|
params, strlen(params),
|
||||||
returns, strlen(returns),
|
returns, strlen(returns),
|
||||||
body, strlen(body),
|
body, strlen(body),
|
||||||
&chistics)))
|
&chistics)))
|
||||||
{
|
{
|
||||||
ret= SP_INTERNAL_ERROR;
|
ret= SP_INTERNAL_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
olddbptr= thd->db;
|
||||||
|
if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb), 1)))
|
||||||
|
goto done;
|
||||||
|
|
||||||
lex_start(thd, (uchar*)defstr, deflen);
|
lex_start(thd, (uchar*)defstr, deflen);
|
||||||
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
|
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
|
||||||
{
|
{
|
||||||
LEX *newlex= thd->lex;
|
LEX *newlex= thd->lex;
|
||||||
sp_head *sp= newlex->sphead;
|
sp_head *sp= newlex->sphead;
|
||||||
|
|
||||||
|
if (olddbptr != thd->db &&
|
||||||
|
(ret= sp_change_db(thd, olddb, 1)))
|
||||||
|
goto done;
|
||||||
if (sp)
|
if (sp)
|
||||||
{
|
{
|
||||||
if (oldlex != newlex)
|
if (oldlex != newlex)
|
||||||
@ -249,6 +262,9 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (olddbptr != thd->db &&
|
||||||
|
(ret= sp_change_db(thd, olddb, 1)))
|
||||||
|
goto done;
|
||||||
*sphp= thd->lex->sphead;
|
*sphp= thd->lex->sphead;
|
||||||
(*sphp)->set_info((char *)definer, (uint)strlen(definer),
|
(*sphp)->set_info((char *)definer, (uint)strlen(definer),
|
||||||
created, modified, &chistics);
|
created, modified, &chistics);
|
||||||
@ -259,6 +275,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
if (opened)
|
if (opened)
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
@ -291,9 +308,8 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
|||||||
ret= SP_GET_FIELD_FAILED;
|
ret= SP_GET_FIELD_FAILED;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
// QQ Not yet
|
table->field[MYSQL_PROC_FIELD_DB]->
|
||||||
// table->field[MYSQL_PROC_FIELD_DB]->
|
store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
||||||
// store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
|
||||||
table->field[MYSQL_PROC_FIELD_NAME]->
|
table->field[MYSQL_PROC_FIELD_NAME]->
|
||||||
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
||||||
table->field[MYSQL_PROC_FIELD_TYPE]->
|
table->field[MYSQL_PROC_FIELD_TYPE]->
|
||||||
@ -402,8 +418,7 @@ struct st_used_field
|
|||||||
|
|
||||||
static struct st_used_field init_fields[]=
|
static struct st_used_field init_fields[]=
|
||||||
{
|
{
|
||||||
// QQ Not yet
|
{ "Db", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
||||||
// { "Db", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
|
||||||
{ "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
{ "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
||||||
{ "Type", 9, MYSQL_TYPE_STRING, 0},
|
{ "Type", 9, MYSQL_TYPE_STRING, 0},
|
||||||
{ "Definer", 77, MYSQL_TYPE_STRING, 0},
|
{ "Definer", 77, MYSQL_TYPE_STRING, 0},
|
||||||
@ -424,14 +439,20 @@ print_field_values(THD *thd, TABLE *table,
|
|||||||
|
|
||||||
if (table->field[MYSQL_PROC_FIELD_TYPE]->val_int() == type)
|
if (table->field[MYSQL_PROC_FIELD_TYPE]->val_int() == type)
|
||||||
{
|
{
|
||||||
String *tmp_string= new String();
|
String db_string;
|
||||||
|
String name_string;
|
||||||
struct st_used_field *used_field= used_fields;
|
struct st_used_field *used_field= used_fields;
|
||||||
|
|
||||||
get_field(&thd->mem_root, used_field->field, tmp_string);
|
if (get_field(&thd->mem_root, used_field->field, &db_string))
|
||||||
if (!wild || !wild[0] || !wild_compare(tmp_string->ptr(), wild, 0))
|
db_string.set_ascii("", 0);
|
||||||
|
used_field+= 1;
|
||||||
|
get_field(&thd->mem_root, used_field->field, &name_string);
|
||||||
|
|
||||||
|
if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
|
||||||
{
|
{
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(tmp_string);
|
protocol->store(&db_string);
|
||||||
|
protocol->store(&name_string);
|
||||||
for (used_field++;
|
for (used_field++;
|
||||||
used_field->field_name;
|
used_field->field_name;
|
||||||
used_field++)
|
used_field++)
|
||||||
@ -448,10 +469,10 @@ print_field_values(THD *thd, TABLE *table,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
String *tmp_string1= new String();
|
String tmp_string;
|
||||||
|
|
||||||
get_field(&thd->mem_root, used_field->field, tmp_string1);
|
get_field(&thd->mem_root, used_field->field, &tmp_string);
|
||||||
protocol->store(tmp_string1);
|
protocol->store(&tmp_string);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -738,17 +759,16 @@ sp_show_status_function(THD *thd, const char *wild)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sp_function_exists(THD *thd, LEX_STRING *name)
|
sp_function_exists(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
bool ret= FALSE;
|
bool ret= FALSE;
|
||||||
bool opened= FALSE;
|
bool opened= FALSE;
|
||||||
sp_name n(*name);
|
|
||||||
DBUG_ENTER("sp_function_exists");
|
DBUG_ENTER("sp_function_exists");
|
||||||
|
|
||||||
if (sp_cache_lookup(&thd->sp_func_cache, &n) ||
|
if (sp_cache_lookup(&thd->sp_func_cache, name) ||
|
||||||
db_find_routine_aux(thd, TYPE_ENUM_FUNCTION,
|
db_find_routine_aux(thd, TYPE_ENUM_FUNCTION,
|
||||||
&n, TL_READ,
|
name, TL_READ,
|
||||||
&table, &opened) == SP_OK)
|
&table, &opened) == SP_OK)
|
||||||
ret= TRUE;
|
ret= TRUE;
|
||||||
if (opened)
|
if (opened)
|
||||||
@ -770,11 +790,11 @@ void
|
|||||||
sp_add_fun_to_lex(LEX *lex, sp_name *fun)
|
sp_add_fun_to_lex(LEX *lex, sp_name *fun)
|
||||||
{
|
{
|
||||||
if (! hash_search(&lex->spfuns,
|
if (! hash_search(&lex->spfuns,
|
||||||
(byte *)fun->m_name.str, fun->m_name.length))
|
(byte *)fun->m_qname.str, fun->m_qname.length))
|
||||||
{
|
{
|
||||||
LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING));
|
LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING));
|
||||||
ls->str= sql_strmake(fun->m_name.str, fun->m_name.length);
|
ls->str= sql_strmake(fun->m_qname.str, fun->m_qname.length);
|
||||||
ls->length= fun->m_name.length;
|
ls->length= fun->m_qname.length;
|
||||||
|
|
||||||
my_hash_insert(&lex->spfuns, (byte *)ls);
|
my_hash_insert(&lex->spfuns, (byte *)ls);
|
||||||
}
|
}
|
||||||
@ -805,6 +825,7 @@ sp_cache_functions(THD *thd, LEX *lex)
|
|||||||
LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
|
LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
|
||||||
sp_name name(*ls);
|
sp_name name(*ls);
|
||||||
|
|
||||||
|
name.m_qname= *ls;
|
||||||
if (! sp_cache_lookup(&thd->sp_func_cache, &name))
|
if (! sp_cache_lookup(&thd->sp_func_cache, &name))
|
||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
@ -812,6 +833,13 @@ sp_cache_functions(THD *thd, LEX *lex)
|
|||||||
LEX *newlex= new st_lex;
|
LEX *newlex= new st_lex;
|
||||||
|
|
||||||
thd->lex= newlex;
|
thd->lex= newlex;
|
||||||
|
name.m_name.str= strchr(name.m_qname.str, '.');
|
||||||
|
name.m_db.length= name.m_name.str - name.m_qname.str;
|
||||||
|
name.m_db.str= strmake_root(&thd->mem_root,
|
||||||
|
name.m_qname.str, name.m_db.length);
|
||||||
|
name.m_name.str+= 1;
|
||||||
|
name.m_name.length= name.m_qname.length - name.m_db.length - 1;
|
||||||
|
|
||||||
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, &name, &sp)
|
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, &name, &sp)
|
||||||
== SP_OK)
|
== SP_OK)
|
||||||
{
|
{
|
||||||
@ -839,7 +867,7 @@ sp_cache_functions(THD *thd, LEX *lex)
|
|||||||
static char *
|
static char *
|
||||||
create_string(THD *thd, ulong *lenp,
|
create_string(THD *thd, ulong *lenp,
|
||||||
int type,
|
int type,
|
||||||
char *name, ulong namelen,
|
sp_name *name,
|
||||||
const char *params, ulong paramslen,
|
const char *params, ulong paramslen,
|
||||||
const char *returns, ulong returnslen,
|
const char *returns, ulong returnslen,
|
||||||
const char *body, ulong bodylen,
|
const char *body, ulong bodylen,
|
||||||
@ -848,14 +876,15 @@ create_string(THD *thd, ulong *lenp,
|
|||||||
char *buf, *ptr;
|
char *buf, *ptr;
|
||||||
ulong buflen;
|
ulong buflen;
|
||||||
|
|
||||||
buflen= 100 + namelen + paramslen + returnslen + bodylen +
|
buflen= 100 + name->m_qname.length + paramslen + returnslen + bodylen +
|
||||||
chistics->comment.length;
|
chistics->comment.length;
|
||||||
if (!(buf= thd->alloc(buflen)))
|
if (!(buf= thd->alloc(buflen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ptr= strxmov(buf, "CREATE ",
|
ptr= strxmov(buf, "CREATE ",
|
||||||
(type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
|
(type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
|
||||||
" `", name, "`(", params, ")", NullS);
|
" `", name->m_db.str, "`.`", name->m_name.str, "`(", params, ")",
|
||||||
|
NullS);
|
||||||
|
|
||||||
if (type == TYPE_ENUM_FUNCTION)
|
if (type == TYPE_ENUM_FUNCTION)
|
||||||
ptr= strxmov(ptr, " RETURNS ", returns, NullS);
|
ptr= strxmov(ptr, " RETURNS ", returns, NullS);
|
||||||
@ -874,3 +903,63 @@ create_string(THD *thd, ulong *lenp,
|
|||||||
*lenp= (ptr-buf);
|
*lenp= (ptr-buf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Utilities...
|
||||||
|
//
|
||||||
|
|
||||||
|
int
|
||||||
|
sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
|
||||||
|
bool no_access_check)
|
||||||
|
{
|
||||||
|
bool changeit;
|
||||||
|
DBUG_ENTER("sp_use_new_db");
|
||||||
|
DBUG_PRINT("enter", ("newdb: %s", newdb));
|
||||||
|
|
||||||
|
if (thd->db && thd->db[0])
|
||||||
|
{
|
||||||
|
if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0)
|
||||||
|
changeit= 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
changeit= 1;
|
||||||
|
strnmov(olddb, thd->db, olddblen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // thd->db empty
|
||||||
|
if (newdb[0])
|
||||||
|
changeit= 1;
|
||||||
|
else
|
||||||
|
changeit= 0;
|
||||||
|
olddb[0] = '\0';
|
||||||
|
}
|
||||||
|
if (!changeit)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ret= sp_change_db(thd, newdb, no_access_check);
|
||||||
|
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sp_change_db(THD *thd, char *db, bool no_access_check)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ulong dbaccess= thd->db_access; /* mysql_change_db() changes this */
|
||||||
|
my_bool nsok= thd->net.no_send_ok; /* mysql_change_db() does send_ok() */
|
||||||
|
thd->net.no_send_ok= TRUE;
|
||||||
|
DBUG_ENTER("sp_change_db");
|
||||||
|
DBUG_PRINT("enter", ("db: %s, no_access_check: %d", db, no_access_check));
|
||||||
|
|
||||||
|
ret= mysql_change_db(thd, db, 1, no_access_check);
|
||||||
|
|
||||||
|
thd->net.no_send_ok= nsok;
|
||||||
|
thd->db_access= dbaccess;
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
}
|
||||||
|
17
sql/sp.h
17
sql/sp.h
@ -70,7 +70,7 @@ int
|
|||||||
sp_show_status_function(THD *thd, const char *wild);
|
sp_show_status_function(THD *thd, const char *wild);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sp_function_exists(THD *thd, LEX_STRING *name);
|
sp_function_exists(THD *thd, sp_name *name);
|
||||||
|
|
||||||
|
|
||||||
// This is needed since we have to read the functions before we
|
// This is needed since we have to read the functions before we
|
||||||
@ -82,4 +82,19 @@ sp_merge_funs(LEX *dst, LEX *src);
|
|||||||
int
|
int
|
||||||
sp_cache_functions(THD *thd, LEX *lex);
|
sp_cache_functions(THD *thd, LEX *lex);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Utilities...
|
||||||
|
//
|
||||||
|
|
||||||
|
// Do a "use newdb". The current db is stored at olddb.
|
||||||
|
// If newdb is the same as the current one, nothing is changed.
|
||||||
|
int
|
||||||
|
sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddbmax,
|
||||||
|
bool no_access_check);
|
||||||
|
|
||||||
|
// Like mysql_change_db() but handles empty db name and the send_ok() problem.
|
||||||
|
int
|
||||||
|
sp_change_db(THD *thd, char *db, bool no_access_check);
|
||||||
|
|
||||||
#endif /* _SP_H_ */
|
#endif /* _SP_H_ */
|
||||||
|
@ -89,7 +89,7 @@ sp_cache_lookup(sp_cache **cp, sp_name *name)
|
|||||||
c->version= v;
|
c->version= v;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return c->lookup(name->m_name.str, name->m_name.length);
|
return c->lookup(name->m_qname.str, name->m_qname.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -109,7 +109,7 @@ sp_cache_remove(sp_cache **cp, sp_name *name)
|
|||||||
if (c->version < v)
|
if (c->version < v)
|
||||||
c->remove_all();
|
c->remove_all();
|
||||||
else
|
else
|
||||||
found= c->remove(name->m_name.str, name->m_name.length);
|
found= c->remove(name->m_qname.str, name->m_qname.length);
|
||||||
c->version= v+1;
|
c->version= v+1;
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
@ -120,7 +120,10 @@ static byte *
|
|||||||
hash_get_key_for_sp_head(const byte *ptr, uint *plen,
|
hash_get_key_for_sp_head(const byte *ptr, uint *plen,
|
||||||
my_bool first)
|
my_bool first)
|
||||||
{
|
{
|
||||||
return (byte*) ((sp_head*)ptr)->name(plen);
|
sp_head *sp= (sp_head *)ptr;
|
||||||
|
|
||||||
|
*plen= sp->m_qname.length;
|
||||||
|
return (byte*) sp->m_qname.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -147,6 +147,26 @@ sp_name::init_qname(THD *thd)
|
|||||||
m_name.length, m_name.str);
|
m_name.length, m_name.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp_name *
|
||||||
|
sp_name_current_db_new(THD *thd, LEX_STRING name)
|
||||||
|
{
|
||||||
|
sp_name *qname;
|
||||||
|
|
||||||
|
if (! thd->db)
|
||||||
|
qname= new sp_name(name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LEX_STRING db;
|
||||||
|
|
||||||
|
db.length= strlen(thd->db);
|
||||||
|
db.str= thd->strmake(thd->db, db.length);
|
||||||
|
qname= new sp_name(db, name);
|
||||||
|
}
|
||||||
|
qname->init_qname(thd);
|
||||||
|
return qname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
@ -224,8 +244,8 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
|
|||||||
/* We have to copy strings to get them into the right memroot */
|
/* We have to copy strings to get them into the right memroot */
|
||||||
if (name->m_db.length == 0)
|
if (name->m_db.length == 0)
|
||||||
{
|
{
|
||||||
m_db.length= strlen(thd->db);
|
m_db.length= (thd->db ? strlen(thd->db) : 0);
|
||||||
m_db.str= strmake_root(root, thd->db, m_db.length);
|
m_db.str= strmake_root(root, (thd->db ? thd->db : ""), m_db.length);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -317,30 +337,22 @@ int
|
|||||||
sp_head::execute(THD *thd)
|
sp_head::execute(THD *thd)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("sp_head::execute");
|
DBUG_ENTER("sp_head::execute");
|
||||||
char olddbname[128];
|
char olddb[128];
|
||||||
char *olddbptr= thd->db;
|
char *olddbptr;
|
||||||
sp_rcontext *ctx= thd->spcont;
|
sp_rcontext *ctx= thd->spcont;
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
uint ip= 0;
|
uint ip= 0;
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (check_stack_overrun(thd, olddbptr))
|
if (check_stack_overrun(thd, olddb))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (olddbptr)
|
|
||||||
{
|
|
||||||
uint i= 0;
|
|
||||||
char *p= olddbptr;
|
|
||||||
|
|
||||||
/* Fast inline strncpy without padding... */
|
olddbptr= thd->db;
|
||||||
while (*p && i < sizeof(olddbname))
|
if ((ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0)))
|
||||||
olddbname[i++]= *p++;
|
goto done;
|
||||||
if (i == sizeof(olddbname))
|
|
||||||
i-= 1; // QQ Error or warning for truncate?
|
|
||||||
olddbname[i]= '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx)
|
if (ctx)
|
||||||
ctx->clear_handler();
|
ctx->clear_handler();
|
||||||
@ -379,18 +391,17 @@ sp_head::execute(THD *thd)
|
|||||||
}
|
}
|
||||||
} while (ret == 0 && !thd->killed && !thd->query_error);
|
} while (ret == 0 && !thd->killed && !thd->query_error);
|
||||||
|
|
||||||
|
done:
|
||||||
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
|
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
|
||||||
ret, thd->killed, thd->query_error));
|
ret, thd->killed, thd->query_error));
|
||||||
if (thd->killed || thd->query_error)
|
if (thd->killed || thd->query_error)
|
||||||
ret= -1;
|
ret= -1;
|
||||||
/* If the DB has changed, the pointer has changed too, but the
|
/* If the DB has changed, the pointer has changed too, but the
|
||||||
original thd->db will then have been freed */
|
original thd->db will then have been freed */
|
||||||
if (olddbptr && olddbptr != thd->db)
|
if (olddbptr != thd->db)
|
||||||
{
|
{
|
||||||
/* QQ Maybe we should issue some special error message or warning here,
|
|
||||||
if this fails?? */
|
|
||||||
if (! thd->killed)
|
if (! thd->killed)
|
||||||
ret= mysql_change_db(thd, olddbname);
|
ret= sp_change_db(thd, olddb, 0);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
@ -757,6 +768,32 @@ sp_head::set_info(char *definer, uint definerlen,
|
|||||||
m_chistics->comment.length);
|
m_chistics->comment.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sp_head::reset_thd_mem_root(THD *thd)
|
||||||
|
{
|
||||||
|
m_thd_root= thd->mem_root;
|
||||||
|
thd->mem_root= m_mem_root;
|
||||||
|
m_free_list= thd->free_list; // Keep the old list
|
||||||
|
thd->free_list= NULL; // Start a new one
|
||||||
|
/* Copy the db, since substatements will point to it */
|
||||||
|
m_thd_db= thd->db;
|
||||||
|
thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length);
|
||||||
|
m_thd= thd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sp_head::restore_thd_mem_root(THD *thd)
|
||||||
|
{
|
||||||
|
Item *flist= m_free_list; // The old list
|
||||||
|
m_free_list= thd->free_list; // Get the new one
|
||||||
|
thd->free_list= flist; // Restore the old one
|
||||||
|
thd->db= m_thd_db; // Restore the original db pointer
|
||||||
|
m_mem_root= thd->mem_root;
|
||||||
|
thd->mem_root= m_thd_root;
|
||||||
|
m_thd= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_head::show_create_procedure(THD *thd)
|
sp_head::show_create_procedure(THD *thd)
|
||||||
{
|
{
|
||||||
@ -1157,8 +1194,6 @@ sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
|
|||||||
{
|
{
|
||||||
ctxp->master_access= thd->master_access;
|
ctxp->master_access= thd->master_access;
|
||||||
ctxp->db_access= thd->db_access;
|
ctxp->db_access= thd->db_access;
|
||||||
ctxp->db= thd->db;
|
|
||||||
ctxp->db_length= thd->db_length;
|
|
||||||
ctxp->priv_user= thd->priv_user;
|
ctxp->priv_user= thd->priv_user;
|
||||||
strncpy(ctxp->priv_host, thd->priv_host, sizeof(ctxp->priv_host));
|
strncpy(ctxp->priv_host, thd->priv_host, sizeof(ctxp->priv_host));
|
||||||
ctxp->user= thd->user;
|
ctxp->user= thd->user;
|
||||||
@ -1174,8 +1209,6 @@ sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
|
|||||||
ctxp->changed= FALSE;
|
ctxp->changed= FALSE;
|
||||||
thd->master_access= ctxp->master_access;
|
thd->master_access= ctxp->master_access;
|
||||||
thd->db_access= ctxp->db_access;
|
thd->db_access= ctxp->db_access;
|
||||||
thd->db= ctxp->db;
|
|
||||||
thd->db_length= ctxp->db_length;
|
|
||||||
thd->priv_user= ctxp->priv_user;
|
thd->priv_user= ctxp->priv_user;
|
||||||
strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
|
strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
|
||||||
}
|
}
|
||||||
@ -1195,8 +1228,6 @@ sp_restore_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
|
|||||||
ctxp->changed= FALSE;
|
ctxp->changed= FALSE;
|
||||||
thd->master_access= ctxp->master_access;
|
thd->master_access= ctxp->master_access;
|
||||||
thd->db_access= ctxp->db_access;
|
thd->db_access= ctxp->db_access;
|
||||||
thd->db= ctxp->db;
|
|
||||||
thd->db_length= ctxp->db_length;
|
|
||||||
thd->priv_user= ctxp->priv_user;
|
thd->priv_user= ctxp->priv_user;
|
||||||
strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
|
strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,10 @@ public:
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sp_name *
|
||||||
|
sp_name_current_db_new(THD *thd, LEX_STRING name);
|
||||||
|
|
||||||
|
|
||||||
class sp_head : public Sql_alloc
|
class sp_head : public Sql_alloc
|
||||||
{
|
{
|
||||||
sp_head(const sp_head &); /* Prevent use of these */
|
sp_head(const sp_head &); /* Prevent use of these */
|
||||||
@ -194,24 +198,10 @@ public:
|
|||||||
longlong created, longlong modified,
|
longlong created, longlong modified,
|
||||||
st_sp_chistics *chistics);
|
st_sp_chistics *chistics);
|
||||||
|
|
||||||
inline void reset_thd_mem_root(THD *thd)
|
void reset_thd_mem_root(THD *thd);
|
||||||
{
|
|
||||||
m_thd_root= thd->mem_root;
|
void restore_thd_mem_root(THD *thd);
|
||||||
thd->mem_root= m_mem_root;
|
|
||||||
m_free_list= thd->free_list; // Keep the old list
|
|
||||||
thd->free_list= NULL; // Start a new one
|
|
||||||
m_thd= thd;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void restore_thd_mem_root(THD *thd)
|
|
||||||
{
|
|
||||||
Item *flist= m_free_list; // The old list
|
|
||||||
m_free_list= thd->free_list; // Get the new one
|
|
||||||
thd->free_list= flist; // Restore the old one
|
|
||||||
m_mem_root= thd->mem_root;
|
|
||||||
thd->mem_root= m_thd_root;
|
|
||||||
m_thd= NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -219,6 +209,7 @@ private:
|
|||||||
MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
|
MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
|
||||||
Item *m_free_list; // Where the items go
|
Item *m_free_list; // Where the items go
|
||||||
THD *m_thd; // Set if we have reset mem_root
|
THD *m_thd; // Set if we have reset mem_root
|
||||||
|
char *m_thd_db; // Original thd->db pointer
|
||||||
|
|
||||||
sp_pcontext *m_pcont; // Parse context
|
sp_pcontext *m_pcont; // Parse context
|
||||||
List<LEX> m_lex; // Temp. store for the other lex
|
List<LEX> m_lex; // Temp. store for the other lex
|
||||||
@ -671,8 +662,6 @@ struct st_sp_security_context
|
|||||||
bool changed;
|
bool changed;
|
||||||
uint master_access;
|
uint master_access;
|
||||||
uint db_access;
|
uint db_access;
|
||||||
char *db;
|
|
||||||
uint db_length;
|
|
||||||
char *priv_user;
|
char *priv_user;
|
||||||
char priv_host[MAX_HOSTNAME];
|
char priv_host[MAX_HOSTNAME];
|
||||||
char *user;
|
char *user;
|
||||||
|
@ -595,7 +595,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
|
|||||||
1 error
|
1 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool mysql_change_db(THD *thd, const char *name)
|
bool mysql_change_db(THD *thd, const char *name,
|
||||||
|
bool empty_is_ok, bool no_access_check)
|
||||||
{
|
{
|
||||||
int length, db_length;
|
int length, db_length;
|
||||||
char *dbname=my_strdup((char*) name,MYF(MY_WME));
|
char *dbname=my_strdup((char*) name,MYF(MY_WME));
|
||||||
@ -604,62 +605,76 @@ bool mysql_change_db(THD *thd, const char *name)
|
|||||||
HA_CREATE_INFO create;
|
HA_CREATE_INFO create;
|
||||||
DBUG_ENTER("mysql_change_db");
|
DBUG_ENTER("mysql_change_db");
|
||||||
|
|
||||||
if (!dbname || !(db_length=strip_sp(dbname)))
|
if ((!dbname || !(db_length=strip_sp(dbname))) && !empty_is_ok)
|
||||||
{
|
{
|
||||||
x_free(dbname); /* purecov: inspected */
|
x_free(dbname); /* purecov: inspected */
|
||||||
send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
|
send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
}
|
}
|
||||||
if ((db_length > NAME_LEN) || check_db_name(dbname))
|
if (!empty_is_ok || (dbname && db_length))
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_WRONG_DB_NAME, dbname);
|
if ((db_length > NAME_LEN) || check_db_name(dbname))
|
||||||
x_free(dbname);
|
{
|
||||||
DBUG_RETURN(1);
|
net_printf(thd, ER_WRONG_DB_NAME, dbname);
|
||||||
|
x_free(dbname);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info",("Use database: %s", dbname));
|
DBUG_PRINT("info",("Use database: %s", dbname));
|
||||||
|
if (!empty_is_ok || (dbname && db_length))
|
||||||
|
{
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (test_all_bits(thd->master_access,DB_ACLS))
|
if (! no_access_check)
|
||||||
db_access=DB_ACLS;
|
{
|
||||||
else
|
if (test_all_bits(thd->master_access,DB_ACLS))
|
||||||
db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
|
db_access=DB_ACLS;
|
||||||
thd->master_access);
|
else
|
||||||
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
|
db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
|
||||||
{
|
thd->master_access);
|
||||||
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
|
if (!(db_access & DB_ACLS) &&
|
||||||
thd->priv_user,
|
(!grant_option || check_grant_db(thd,dbname)))
|
||||||
thd->priv_host,
|
{
|
||||||
dbname);
|
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
|
||||||
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
|
thd->priv_user,
|
||||||
thd->priv_user,
|
thd->priv_host,
|
||||||
thd->priv_host,
|
dbname);
|
||||||
dbname);
|
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
|
||||||
my_free(dbname,MYF(0));
|
thd->priv_user,
|
||||||
DBUG_RETURN(1);
|
thd->priv_host,
|
||||||
}
|
dbname);
|
||||||
|
my_free(dbname,MYF(0));
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
(void) sprintf(path,"%s/%s",mysql_data_home,dbname);
|
(void) sprintf(path,"%s/%s",mysql_data_home,dbname);
|
||||||
length=unpack_dirname(path,path); // Convert if not unix
|
length=unpack_dirname(path,path); // Convert if not unix
|
||||||
if (length && path[length-1] == FN_LIBCHAR)
|
if (length && path[length-1] == FN_LIBCHAR)
|
||||||
path[length-1]=0; // remove ending '\'
|
path[length-1]=0; // remove ending '\'
|
||||||
if (access(path,F_OK))
|
if (access(path,F_OK))
|
||||||
{
|
{
|
||||||
net_printf(thd,ER_BAD_DB_ERROR,dbname);
|
net_printf(thd,ER_BAD_DB_ERROR,dbname);
|
||||||
my_free(dbname,MYF(0));
|
my_free(dbname,MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
x_free(thd->db);
|
x_free(thd->db);
|
||||||
thd->db=dbname; // THD::~THD will free this
|
thd->db=dbname; // THD::~THD will free this
|
||||||
thd->db_length=db_length;
|
thd->db_length=db_length;
|
||||||
|
if (!empty_is_ok || (dbname && db_length))
|
||||||
|
{
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
thd->db_access=db_access;
|
if (! no_access_check)
|
||||||
|
thd->db_access=db_access;
|
||||||
#endif
|
#endif
|
||||||
strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
|
strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
|
||||||
load_db_opt(thd, path, &create);
|
load_db_opt(thd, path, &create);
|
||||||
thd->db_charset= create.default_table_charset ?
|
thd->db_charset= create.default_table_charset ?
|
||||||
create.default_table_charset :
|
create.default_table_charset :
|
||||||
thd->variables.collation_server;
|
thd->variables.collation_server;
|
||||||
thd->variables.collation_database= thd->db_charset;
|
thd->variables.collation_database= thd->db_charset;
|
||||||
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,8 +1090,15 @@ create:
|
|||||||
;
|
;
|
||||||
|
|
||||||
sp_name:
|
sp_name:
|
||||||
IDENT_sys '.' IDENT_sys { $$= new sp_name($1, $3); }
|
IDENT_sys '.' IDENT_sys
|
||||||
| IDENT_sys { $$= new sp_name($1); }
|
{
|
||||||
|
$$= new sp_name($1, $3);
|
||||||
|
$$->init_qname(YYTHD);
|
||||||
|
}
|
||||||
|
| IDENT_sys
|
||||||
|
{
|
||||||
|
$$= sp_name_current_db_new(YYTHD, $1);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
create_function_tail:
|
create_function_tail:
|
||||||
@ -1576,6 +1583,11 @@ sp_proc_stmt:
|
|||||||
/* We maybe have one or more SELECT without INTO */
|
/* We maybe have one or more SELECT without INTO */
|
||||||
lex->sphead->m_multi_results= TRUE;
|
lex->sphead->m_multi_results= TRUE;
|
||||||
}
|
}
|
||||||
|
if (lex->sql_command == SQLCOM_CHANGE_DB)
|
||||||
|
{ /* "USE db" doesn't work in a procedure */
|
||||||
|
send_error(YYTHD, ER_SP_NO_USE);
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
/* Don't add an instruction for empty SET statements.
|
/* Don't add an instruction for empty SET statements.
|
||||||
** (This happens if the SET only contained local variables,
|
** (This happens if the SET only contained local variables,
|
||||||
** which get their set instructions generated separately.)
|
** which get their set instructions generated separately.)
|
||||||
@ -3913,10 +3925,11 @@ simple_expr:
|
|||||||
{ $$= new Item_int((char*) "TRUE",1,1); }
|
{ $$= new Item_int((char*) "TRUE",1,1); }
|
||||||
| IDENT_sys '(' udf_expr_list ')'
|
| IDENT_sys '(' udf_expr_list ')'
|
||||||
{
|
{
|
||||||
if (sp_function_exists(YYTHD, &$1))
|
sp_name *name= sp_name_current_db_new(YYTHD, $1);
|
||||||
|
|
||||||
|
if (sp_function_exists(YYTHD, name))
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_name *name= new sp_name($1);
|
|
||||||
|
|
||||||
sp_add_fun_to_lex(lex, name);
|
sp_add_fun_to_lex(lex, name);
|
||||||
if ($3)
|
if ($3)
|
||||||
|
Reference in New Issue
Block a user