Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/alik/Documents/AllProgs/MySQL/devel/5.0-rt mysql-test/r/sp.result: Auto merged sql/sql_trigger.cc: Auto merged sql/sql_yacc.yy: Auto merged mysql-test/r/skip_grants.result: Merge 5.0 and 5.0-runtime. mysql-test/t/skip_grants.test: Merge 5.0 and 5.0-runtime.
This commit is contained in:
commit
99515a3ac8
@ -80,6 +80,7 @@ static char *add_load_option(char *ptr, const char *object,
|
||||
const char *statement);
|
||||
static ulong find_set(TYPELIB *lib, const char *x, uint length,
|
||||
char **err_pos, uint *err_len);
|
||||
static char *alloc_query_str(ulong size);
|
||||
|
||||
static char *field_escape(char *to,const char *from,uint length);
|
||||
static my_bool verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
|
||||
@ -1304,19 +1305,64 @@ static uint dump_routines_for_db(char *db)
|
||||
routine_name, row[2], strlen(row[2])));
|
||||
if (strlen(row[2]))
|
||||
{
|
||||
char *query_str= NULL;
|
||||
char *definer_begin;
|
||||
|
||||
if (opt_drop)
|
||||
fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
|
||||
routine_type[i], routine_name);
|
||||
|
||||
/*
|
||||
Cover DEFINER-clause in version-specific comments.
|
||||
|
||||
TODO: this is definitely a BAD IDEA to parse SHOW CREATE output.
|
||||
We should user INFORMATION_SCHEMA instead. The only problem is
|
||||
that now INFORMATION_SCHEMA does not provide information about
|
||||
routine parameters.
|
||||
*/
|
||||
|
||||
definer_begin= strstr(row[2], " DEFINER");
|
||||
|
||||
if (definer_begin)
|
||||
{
|
||||
char *definer_end= strstr(definer_begin, " PROCEDURE");
|
||||
|
||||
if (!definer_end)
|
||||
definer_end= strstr(definer_begin, " FUNCTION");
|
||||
|
||||
if (definer_end)
|
||||
{
|
||||
char *query_str_tail;
|
||||
|
||||
/*
|
||||
Allocate memory for new query string: original string
|
||||
from SHOW statement and version-specific comments.
|
||||
*/
|
||||
query_str= alloc_query_str(strlen(row[2]) + 23);
|
||||
|
||||
query_str_tail= strnmov(query_str, row[2],
|
||||
definer_begin - row[2]);
|
||||
query_str_tail= strmov(query_str_tail, "*/ /*!50019");
|
||||
query_str_tail= strnmov(query_str_tail, definer_begin,
|
||||
definer_end - definer_begin);
|
||||
query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
|
||||
definer_end, NullS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
we need to change sql_mode only for the CREATE
|
||||
PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
|
||||
*/;
|
||||
fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
|
||||
row[1] /* sql_mode */);
|
||||
fprintf(sql_file, "/*!50003 %s */;;\n", row[2]);
|
||||
fprintf(sql_file, "/*!50003 %s */;;\n",
|
||||
(query_str != NULL ? query_str : row[2]));
|
||||
fprintf(sql_file,
|
||||
"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
|
||||
";;\n");
|
||||
|
||||
my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
} /* end of routine printing */
|
||||
} /* end of list of routines */
|
||||
|
@ -680,7 +680,7 @@ drop procedure if exists fn3;
|
||||
create function fn3 () returns point return GeomFromText("point(1 1)");
|
||||
show create function fn3;
|
||||
Function sql_mode Create Function
|
||||
fn3 CREATE FUNCTION `fn3`() RETURNS point
|
||||
fn3 CREATE DEFINER=`root`@`localhost` FUNCTION `fn3`() RETURNS point
|
||||
return GeomFromText("point(1 1)")
|
||||
select astext(fn3());
|
||||
astext(fn3())
|
||||
|
@ -309,7 +309,7 @@ Function sql_mode Create Function
|
||||
sub1
|
||||
show create function sub2;
|
||||
Function sql_mode Create Function
|
||||
sub2 CREATE FUNCTION `sub2`(i int) RETURNS int(11)
|
||||
sub2 CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11)
|
||||
return i+1
|
||||
show function status like "sub2";
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
@ -317,7 +317,7 @@ test sub2 FUNCTION mysqltest_1@localhost # # DEFINER
|
||||
drop function sub2;
|
||||
show create procedure sel2;
|
||||
Procedure sql_mode Create Procedure
|
||||
sel2 CREATE PROCEDURE `sel2`()
|
||||
sel2 CREATE DEFINER=`root`@`localhost` PROCEDURE `sel2`()
|
||||
begin
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
|
@ -2210,12 +2210,12 @@ UNLOCK TABLES;
|
||||
DELIMITER ;;
|
||||
/*!50003 DROP FUNCTION IF EXISTS `bug9056_func1` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
|
||||
RETURN a+b */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP FUNCTION IF EXISTS `bug9056_func2` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
|
||||
begin
|
||||
set f1= concat( 'hello', f1 );
|
||||
return f1;
|
||||
@ -2223,17 +2223,17 @@ end */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `a'b` */;;
|
||||
/*!50003 SET SESSION SQL_MODE="REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI"*/;;
|
||||
/*!50003 CREATE PROCEDURE "a'b"()
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER="root"@"localhost"*/ /*!50003 PROCEDURE "a'b"()
|
||||
select 1 */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc1` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
|
||||
BEGIN SELECT a+b INTO c; end */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE PROCEDURE `bug9056_proc2`(OUT a INT)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc2`(OUT a INT)
|
||||
BEGIN
|
||||
select sum(id) from t1 into a;
|
||||
END */;;
|
||||
@ -2685,11 +2685,11 @@ return 42 */|
|
||||
select 42 */|
|
||||
show create function f;
|
||||
Function sql_mode Create Function
|
||||
f CREATE FUNCTION `f`() RETURNS bigint(20)
|
||||
f CREATE DEFINER=`root`@`localhost` FUNCTION `f`() RETURNS bigint(20)
|
||||
return 42
|
||||
show create procedure p;
|
||||
Procedure sql_mode Create Procedure
|
||||
p CREATE PROCEDURE `p`()
|
||||
p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()
|
||||
select 42
|
||||
drop function f;
|
||||
drop procedure p;
|
||||
|
@ -1133,7 +1133,7 @@ SHOW PROCEDURE STATUS LIKE 'p1';
|
||||
Db mysqltest1
|
||||
Name p1
|
||||
Type PROCEDURE
|
||||
Definer @
|
||||
Definer root@localhost
|
||||
Modified #
|
||||
Created #
|
||||
Security_type DEFINER
|
||||
@ -1199,7 +1199,7 @@ SHOW PROCEDURE STATUS LIKE 'p1';
|
||||
Db mysqltest1
|
||||
Name p1
|
||||
Type PROCEDURE
|
||||
Definer @
|
||||
Definer root@localhost
|
||||
Modified #
|
||||
Created #
|
||||
Security_type DEFINER
|
||||
|
@ -31,7 +31,7 @@ declare b int;
|
||||
set b = 8;
|
||||
insert into t1 values (b);
|
||||
insert into t1 values (unix_timestamp());
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
set timestamp=1000000000;
|
||||
call foo();
|
||||
select * from t1;
|
||||
@ -118,7 +118,7 @@ select * from mysql.proc where name="foo4" and db='mysqltest1';
|
||||
db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
|
||||
mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES DEFINER begin
|
||||
insert into t2 values(20),(20);
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
drop procedure foo4;
|
||||
select * from mysql.proc where name="foo4" and db='mysqltest1';
|
||||
db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
|
||||
@ -223,13 +223,13 @@ select * from mysql.proc where db='mysqltest1';
|
||||
db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
|
||||
mysqltest1 fn1 FUNCTION fn1 SQL NO_SQL NO DEFINER int(11) begin
|
||||
return unix_timestamp();
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
mysqltest1 fn2 FUNCTION fn2 SQL NO_SQL NO DEFINER int(11) begin
|
||||
return unix_timestamp();
|
||||
end @ # #
|
||||
end zedjzlcsjhd@localhost # #
|
||||
mysqltest1 fn3 FUNCTION fn3 SQL READS_SQL_DATA NO DEFINER int(11) begin
|
||||
return 0;
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
delete from t2;
|
||||
alter table t2 add unique (a);
|
||||
drop function fn1;
|
||||
@ -274,7 +274,7 @@ Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query 1 # drop database if exists mysqltest1
|
||||
master-bin.000001 # Query 1 # create database mysqltest1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a varchar(100))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
|
||||
begin
|
||||
declare b int;
|
||||
set b = 8;
|
||||
@ -284,19 +284,19 @@ end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp())
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2()
|
||||
select * from mysqltest1.t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo2 contains sql
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo3()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo3()
|
||||
deterministic
|
||||
insert into t1 values (15)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` procedure foo4()
|
||||
deterministic
|
||||
begin
|
||||
insert into t2 values(3);
|
||||
@ -311,7 +311,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (5)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t2 add unique (a)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo4
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4()
|
||||
deterministic
|
||||
begin
|
||||
insert into t2 values(20),(20);
|
||||
@ -321,7 +321,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo4
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo3
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1(x int)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1(x int)
|
||||
returns int
|
||||
deterministic
|
||||
begin
|
||||
@ -332,7 +332,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; delete t1,t2 from t1,t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `fn1`(20)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(fn1(21))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1()
|
||||
returns int
|
||||
no sql
|
||||
begin
|
||||
@ -340,13 +340,13 @@ return unix_timestamp();
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(fn1())
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn2()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` function fn2()
|
||||
returns int
|
||||
no sql
|
||||
begin
|
||||
return unix_timestamp();
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn3()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn3()
|
||||
returns int
|
||||
not deterministic
|
||||
reads sql data
|
||||
@ -356,7 +356,7 @@ end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t2 add unique (a)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1(x int)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1(x int)
|
||||
returns int
|
||||
begin
|
||||
insert into t2 values(x),(x);
|
||||
|
@ -102,7 +102,7 @@ t1_first root@localhost
|
||||
SELECT routine_name, definer
|
||||
FROM information_schema.routines;
|
||||
routine_name definer
|
||||
bug12480 @
|
||||
bug12480 root@localhost
|
||||
SELECT trigger_name, definer
|
||||
FROM information_schema.triggers;
|
||||
trigger_name definer
|
||||
@ -855,3 +855,44 @@ f3
|
||||
drop trigger trg11;
|
||||
drop table t21,t31;
|
||||
drop table t11;
|
||||
STOP SLAVE;
|
||||
FLUSH LOGS;
|
||||
RESET SLAVE;
|
||||
START SLAVE;
|
||||
SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
|
||||
MASTER_POS_WAIT('master-bin.000001', 513) >= 0
|
||||
1
|
||||
SHOW TABLES;
|
||||
Tables_in_test
|
||||
t1
|
||||
t2
|
||||
SHOW TRIGGERS;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
trg1 INSERT t1 INSERT INTO t2 VALUES(CURRENT_USER()) AFTER NULL
|
||||
SELECT * FROM t1;
|
||||
c
|
||||
1
|
||||
SELECT * FROM t2;
|
||||
s
|
||||
@
|
||||
INSERT INTO t1 VALUES(2);
|
||||
SELECT * FROM t1;
|
||||
c
|
||||
1
|
||||
2
|
||||
SELECT * FROM t2;
|
||||
s
|
||||
@
|
||||
root@localhost
|
||||
DROP TRIGGER trg1;
|
||||
Warnings:
|
||||
Warning 1454 No definer attribute for trigger 'test'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
SHOW TABLES;
|
||||
Tables_in_test
|
||||
SHOW TRIGGERS;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
RESET MASTER;
|
||||
|
@ -2,10 +2,6 @@ drop table if exists t1,v1;
|
||||
drop view if exists t1,v1;
|
||||
drop procedure if exists f1;
|
||||
use test;
|
||||
create table t1 (field1 INT);
|
||||
CREATE VIEW v1 AS SELECT field1 FROM t1;
|
||||
ERROR HY000: Definer is not fully qualified
|
||||
drop table t1;
|
||||
create procedure f1() select 1;
|
||||
drop procedure f1;
|
||||
create table t1 (a int);
|
||||
@ -15,3 +11,20 @@ drop table t1;
|
||||
drop function if exists f1;
|
||||
Warnings:
|
||||
Note 1305 FUNCTION f1 does not exist
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP VIEW IF EXISTS v2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(c INT);
|
||||
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @a = 1;
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @b = 1;
|
||||
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
|
||||
DROP TRIGGER t1_bi;
|
||||
DROP TRIGGER ti_ai;
|
||||
DROP VIEW v1;
|
||||
DROP VIEW v2;
|
||||
DROP TABLE t1;
|
||||
|
@ -323,3 +323,99 @@ Warning 1287 'SHOW INNODB STATUS' is deprecated; use 'SHOW ENGINE INNODB STATUS'
|
||||
GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
|
||||
DROP DATABASE db_bug7787;
|
||||
use test;
|
||||
|
||||
---> connection: root
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
CREATE DATABASE mysqltest;
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT SUPER ON *.* TO mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CREATE PROCEDURE wl2897_p1() SELECT 1;
|
||||
CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1;
|
||||
|
||||
---> connection: mysqltest_1_con
|
||||
use mysqltest;
|
||||
CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2;
|
||||
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
||||
CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2;
|
||||
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3;
|
||||
Warnings:
|
||||
Note 1449 There is no 'a @ b @ c'@'localhost' registered
|
||||
CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3;
|
||||
Warnings:
|
||||
Note 1449 There is no 'a @ b @ c'@'localhost' registered
|
||||
|
||||
---> connection: con1root
|
||||
use mysqltest;
|
||||
SHOW CREATE PROCEDURE wl2897_p1;
|
||||
Procedure sql_mode Create Procedure
|
||||
wl2897_p1 CREATE DEFINER=`mysqltest_2`@`localhost` PROCEDURE `wl2897_p1`()
|
||||
SELECT 1
|
||||
SHOW CREATE PROCEDURE wl2897_p3;
|
||||
Procedure sql_mode Create Procedure
|
||||
wl2897_p3 CREATE DEFINER=`a @ b @ c`@`localhost` PROCEDURE `wl2897_p3`()
|
||||
SELECT 3
|
||||
SHOW CREATE FUNCTION wl2897_f1;
|
||||
Function sql_mode Create Function
|
||||
wl2897_f1 CREATE DEFINER=`mysqltest_2`@`localhost` FUNCTION `wl2897_f1`() RETURNS int(11)
|
||||
RETURN 1
|
||||
SHOW CREATE FUNCTION wl2897_f3;
|
||||
Function sql_mode Create Function
|
||||
wl2897_f3 CREATE DEFINER=`a @ b @ c`@`localhost` FUNCTION `wl2897_f3`() RETURNS int(11)
|
||||
RETURN 3
|
||||
DROP USER mysqltest_1@localhost;
|
||||
DROP USER mysqltest_2@localhost;
|
||||
DROP DATABASE mysqltest;
|
||||
|
||||
---> connection: root
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
CREATE DATABASE mysqltest;
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
---> connection: mysqltest_1_con
|
||||
use mysqltest;
|
||||
CREATE PROCEDURE bug13198_p1()
|
||||
SELECT 1;
|
||||
CREATE FUNCTION bug13198_f1() RETURNS INT
|
||||
RETURN 1;
|
||||
CALL bug13198_p1();
|
||||
1
|
||||
1
|
||||
SELECT bug13198_f1();
|
||||
bug13198_f1()
|
||||
1
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CALL bug13198_p1();
|
||||
1
|
||||
1
|
||||
SELECT bug13198_f1();
|
||||
bug13198_f1()
|
||||
1
|
||||
|
||||
---> connection: root
|
||||
DROP USER mysqltest_1@localhost;
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CALL bug13198_p1();
|
||||
ERROR HY000: There is no 'mysqltest_1'@'localhost' registered
|
||||
SELECT bug13198_f1();
|
||||
ERROR HY000: There is no 'mysqltest_1'@'localhost' registered
|
||||
|
||||
---> connection: root
|
||||
DROP USER mysqltest_2@localhost;
|
||||
DROP DATABASE mysqltest;
|
||||
|
@ -788,7 +788,7 @@ comment 'Characteristics procedure test'
|
||||
insert into t1 values ("chistics", 1)|
|
||||
show create procedure chistics|
|
||||
Procedure sql_mode Create Procedure
|
||||
chistics CREATE PROCEDURE `chistics`()
|
||||
chistics CREATE DEFINER=`root`@`localhost` PROCEDURE `chistics`()
|
||||
MODIFIES SQL DATA
|
||||
COMMENT 'Characteristics procedure test'
|
||||
insert into t1 values ("chistics", 1)
|
||||
@ -800,7 +800,7 @@ delete from t1|
|
||||
alter procedure chistics sql security invoker|
|
||||
show create procedure chistics|
|
||||
Procedure sql_mode Create Procedure
|
||||
chistics CREATE PROCEDURE `chistics`()
|
||||
chistics CREATE DEFINER=`root`@`localhost` PROCEDURE `chistics`()
|
||||
MODIFIES SQL DATA
|
||||
SQL SECURITY INVOKER
|
||||
COMMENT 'Characteristics procedure test'
|
||||
@ -815,7 +815,7 @@ comment 'Characteristics procedure test'
|
||||
return 42|
|
||||
show create function chistics|
|
||||
Function sql_mode Create Function
|
||||
chistics CREATE FUNCTION `chistics`() RETURNS int(11)
|
||||
chistics CREATE DEFINER=`root`@`localhost` FUNCTION `chistics`() RETURNS int(11)
|
||||
DETERMINISTIC
|
||||
SQL SECURITY INVOKER
|
||||
COMMENT 'Characteristics procedure test'
|
||||
@ -828,7 +828,7 @@ no sql
|
||||
comment 'Characteristics function test'|
|
||||
show create function chistics|
|
||||
Function sql_mode Create Function
|
||||
chistics CREATE FUNCTION `chistics`() RETURNS int(11)
|
||||
chistics CREATE DEFINER=`root`@`localhost` FUNCTION `chistics`() RETURNS int(11)
|
||||
NO SQL
|
||||
DETERMINISTIC
|
||||
SQL SECURITY INVOKER
|
||||
@ -1287,7 +1287,7 @@ end while;
|
||||
end|
|
||||
show create procedure opp|
|
||||
Procedure sql_mode Create Procedure
|
||||
opp CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
|
||||
opp CREATE DEFINER=`root`@`localhost` PROCEDURE `opp`(n bigint unsigned, out pp bool)
|
||||
begin
|
||||
declare r double;
|
||||
declare b, s bigint unsigned default 0;
|
||||
@ -1386,7 +1386,7 @@ alter procedure bar comment "3333333333"|
|
||||
alter procedure bar|
|
||||
show create procedure bar|
|
||||
Procedure sql_mode Create Procedure
|
||||
bar CREATE PROCEDURE `bar`(x char(16), y int)
|
||||
bar CREATE DEFINER=`root`@`localhost` PROCEDURE `bar`(x char(16), y int)
|
||||
COMMENT '3333333333'
|
||||
insert into test.t1 values (x, y)
|
||||
show procedure status like 'bar'|
|
||||
@ -1966,13 +1966,13 @@ Db Name Type Definer Modified Created Security_type Comment
|
||||
test bug2267_4 FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
call bug2267_3()|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2267_1 CREATE PROCEDURE `bug2267_1`()
|
||||
bug2267_1 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug2267_1`()
|
||||
begin
|
||||
show procedure status;
|
||||
end
|
||||
call bug2267_4()|
|
||||
Function sql_mode Create Function
|
||||
bug2267_4 CREATE FUNCTION `bug2267_4`() RETURNS int(11)
|
||||
bug2267_4 CREATE DEFINER=`root`@`localhost` FUNCTION `bug2267_4`() RETURNS int(11)
|
||||
return 100
|
||||
drop procedure bug2267_1|
|
||||
drop procedure bug2267_2|
|
||||
@ -2333,20 +2333,20 @@ return x || y$
|
||||
set @@sql_mode = ''|
|
||||
show create procedure bug2564_1|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2564_1 CREATE PROCEDURE `bug2564_1`()
|
||||
bug2564_1 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug2564_1`()
|
||||
COMMENT 'Joe''s procedure'
|
||||
insert into `t1` values ("foo", 1)
|
||||
show create procedure bug2564_2|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2564_2 ANSI_QUOTES CREATE PROCEDURE "bug2564_2"()
|
||||
bug2564_2 ANSI_QUOTES CREATE DEFINER="root"@"localhost" PROCEDURE "bug2564_2"()
|
||||
insert into "t1" values ('foo', 1)
|
||||
show create function bug2564_3|
|
||||
Function sql_mode Create Function
|
||||
bug2564_3 CREATE FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
|
||||
bug2564_3 CREATE DEFINER=`root`@`localhost` FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
|
||||
return x || y
|
||||
show create function bug2564_4|
|
||||
Function sql_mode Create Function
|
||||
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI CREATE FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
|
||||
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI CREATE DEFINER="root"@"localhost" FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
|
||||
return x || y
|
||||
drop procedure bug2564_1|
|
||||
drop procedure bug2564_2|
|
||||
@ -4056,7 +4056,7 @@ return 42;
|
||||
end */;;
|
||||
show create function bug14723;;
|
||||
Function sql_mode Create Function
|
||||
bug14723 CREATE FUNCTION `bug14723`() RETURNS bigint(20)
|
||||
bug14723 CREATE DEFINER=`root`@`localhost` FUNCTION `bug14723`() RETURNS bigint(20)
|
||||
main_loop: begin
|
||||
return 42;
|
||||
end
|
||||
@ -4069,7 +4069,7 @@ select 42;
|
||||
end */;;
|
||||
show create procedure bug14723;;
|
||||
Procedure sql_mode Create Procedure
|
||||
bug14723 CREATE PROCEDURE `bug14723`()
|
||||
bug14723 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug14723`()
|
||||
main_loop: begin
|
||||
select 42;
|
||||
end
|
||||
|
@ -445,23 +445,23 @@ SET @@SQL_MODE='';
|
||||
create function `foo` () returns int return 5;
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo CREATE FUNCTION `foo`() RETURNS int(11)
|
||||
foo CREATE DEFINER=`root`@`localhost` FUNCTION `foo`() RETURNS int(11)
|
||||
return 5
|
||||
SET @@SQL_MODE='ANSI_QUOTES';
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo CREATE FUNCTION `foo`() RETURNS int(11)
|
||||
foo CREATE DEFINER=`root`@`localhost` FUNCTION `foo`() RETURNS int(11)
|
||||
return 5
|
||||
drop function `foo`;
|
||||
create function `foo` () returns int return 5;
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo ANSI_QUOTES CREATE FUNCTION "foo"() RETURNS int(11)
|
||||
foo ANSI_QUOTES CREATE DEFINER="root"@"localhost" FUNCTION "foo"() RETURNS int(11)
|
||||
return 5
|
||||
SET @@SQL_MODE='';
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo ANSI_QUOTES CREATE FUNCTION "foo"() RETURNS int(11)
|
||||
foo ANSI_QUOTES CREATE DEFINER="root"@"localhost" FUNCTION "foo"() RETURNS int(11)
|
||||
return 5
|
||||
drop function `foo`;
|
||||
SET @@SQL_MODE='';
|
||||
|
BIN
mysql-test/std_data/bug16266.000001
Normal file
BIN
mysql-test/std_data/bug16266.000001
Normal file
Binary file not shown.
@ -162,6 +162,7 @@ use test;
|
||||
drop table t1,t2;
|
||||
drop database other;
|
||||
|
||||
|
||||
#
|
||||
# Test specific triggers including SELECT into var with replication
|
||||
# BUG#13227:
|
||||
@ -257,6 +258,79 @@ while ($rnd)
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# BUG#16266: Definer is not fully qualified error during replication.
|
||||
#
|
||||
# The idea of this test is to emulate replication of a trigger from the old
|
||||
# master (master w/o "DEFINER in triggers" support) to the new slave and check
|
||||
# that:
|
||||
# 1. the trigger on the slave will be replicated w/o errors;
|
||||
# 2. the trigger on the slave will be non-SUID (will have no DEFINER);
|
||||
# 3. the trigger can be activated later on the slave w/o errors.
|
||||
#
|
||||
# In order to emulate this kind of replication, we make the slave playing the binlog,
|
||||
# recorded by 5.0.16 master. This binlog contains the following statements:
|
||||
# CREATE TABLE t1(c INT);
|
||||
# CREATE TABLE t2(s CHAR(200));
|
||||
# CREATE TRIGGER trg1 AFTER INSERT ON t1
|
||||
# FOR EACH ROW
|
||||
# INSERT INTO t2 VALUES(CURRENT_USER());
|
||||
# INSERT INTO t1 VALUES(1);
|
||||
#
|
||||
|
||||
# 1. Check that the trigger's replication is succeeded.
|
||||
|
||||
# Stop the slave.
|
||||
|
||||
connection slave;
|
||||
STOP SLAVE;
|
||||
|
||||
# Replace master's binlog.
|
||||
|
||||
connection master;
|
||||
FLUSH LOGS;
|
||||
exec cp $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLTEST_VARDIR/log/master-bin.000001;
|
||||
|
||||
# Make the slave to replay the new binlog.
|
||||
|
||||
connection slave;
|
||||
RESET SLAVE;
|
||||
START SLAVE;
|
||||
|
||||
SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
|
||||
|
||||
# Check that the replication succeeded.
|
||||
|
||||
SHOW TABLES;
|
||||
SHOW TRIGGERS;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
# 2. Check that the trigger is non-SUID on the slave;
|
||||
# 3. Check that the trigger can be activated on the slave.
|
||||
|
||||
INSERT INTO t1 VALUES(2);
|
||||
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
# That's all, cleanup.
|
||||
|
||||
DROP TRIGGER trg1;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
|
||||
# The master should be clean.
|
||||
|
||||
connection master;
|
||||
SHOW TABLES;
|
||||
SHOW TRIGGERS;
|
||||
|
||||
RESET MASTER;
|
||||
|
||||
|
||||
#
|
||||
# End of tests
|
||||
|
@ -8,14 +8,6 @@ drop procedure if exists f1;
|
||||
--enable_warnings
|
||||
use test;
|
||||
|
||||
#
|
||||
# test that we can create VIEW if privileges check switched off
|
||||
#
|
||||
create table t1 (field1 INT);
|
||||
-- error ER_MALFORMED_DEFINER
|
||||
CREATE VIEW v1 AS SELECT field1 FROM t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test that we can create and drop procedure without warnings
|
||||
# see bug#9993
|
||||
@ -33,3 +25,48 @@ drop table t1;
|
||||
|
||||
# BUG#17595: DROP FUNCTION IF EXISTS f1 crashes server
|
||||
drop function if exists f1;
|
||||
|
||||
#
|
||||
# BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables
|
||||
# specified
|
||||
#
|
||||
# Also, a test that we can create VIEW if privileges check switched off has
|
||||
# been moved here.
|
||||
#
|
||||
|
||||
# Prepare.
|
||||
|
||||
--disable_warnings
|
||||
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP VIEW IF EXISTS v2;
|
||||
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
||||
--enable_warnings
|
||||
|
||||
# Test case.
|
||||
|
||||
CREATE TABLE t1(c INT);
|
||||
|
||||
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @a = 1;
|
||||
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
|
||||
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @b = 1;
|
||||
|
||||
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
|
||||
|
||||
# Cleanup.
|
||||
|
||||
DROP TRIGGER t1_bi;
|
||||
DROP TRIGGER ti_ai;
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP VIEW v2;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
@ -547,4 +547,200 @@ GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
|
||||
DROP DATABASE db_bug7787;
|
||||
use test;
|
||||
|
||||
|
||||
#
|
||||
# WL#2897: Complete definer support in the stored routines.
|
||||
#
|
||||
# The following cases are tested:
|
||||
# 1. check that if DEFINER-clause is not explicitly specified, stored routines
|
||||
# are created with CURRENT_USER privileges;
|
||||
# 2. check that if DEFINER-clause specifies non-current user, SUPER privilege
|
||||
# is required to create a stored routine;
|
||||
# 3. check that if DEFINER-clause specifies non-existent user, a warning is
|
||||
# emitted.
|
||||
# 4. check that SHOW CREATE PROCEDURE | FUNCTION works correctly;
|
||||
#
|
||||
# The following cases are tested in other test suites:
|
||||
# - check that mysqldump dumps new attribute correctly;
|
||||
# - check that slave replicates CREATE-statements with explicitly specified
|
||||
# DEFINER correctly.
|
||||
#
|
||||
|
||||
# Setup the environment.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE mysqltest;
|
||||
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT SUPER ON *.* TO mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
--connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest)
|
||||
--connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest)
|
||||
|
||||
# test case (1).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CREATE PROCEDURE wl2897_p1() SELECT 1;
|
||||
|
||||
CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1;
|
||||
|
||||
# test case (2).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_1_con
|
||||
--connection mysqltest_1_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2;
|
||||
|
||||
# test case (3).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3;
|
||||
|
||||
CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3;
|
||||
|
||||
# test case (4).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: con1root
|
||||
--connection con1root
|
||||
|
||||
use mysqltest;
|
||||
|
||||
SHOW CREATE PROCEDURE wl2897_p1;
|
||||
SHOW CREATE PROCEDURE wl2897_p3;
|
||||
|
||||
SHOW CREATE FUNCTION wl2897_f1;
|
||||
SHOW CREATE FUNCTION wl2897_f3;
|
||||
|
||||
# Cleanup.
|
||||
|
||||
DROP USER mysqltest_1@localhost;
|
||||
DROP USER mysqltest_2@localhost;
|
||||
|
||||
DROP DATABASE mysqltest;
|
||||
|
||||
--disconnect mysqltest_1_con
|
||||
--disconnect mysqltest_2_con
|
||||
|
||||
|
||||
#
|
||||
# BUG#13198: SP executes if definer does not exist
|
||||
#
|
||||
|
||||
# Prepare environment.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE mysqltest;
|
||||
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
--connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest)
|
||||
--connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest)
|
||||
|
||||
# Create a procedure/function under u1.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_1_con
|
||||
--connection mysqltest_1_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CREATE PROCEDURE bug13198_p1()
|
||||
SELECT 1;
|
||||
|
||||
CREATE FUNCTION bug13198_f1() RETURNS INT
|
||||
RETURN 1;
|
||||
|
||||
CALL bug13198_p1();
|
||||
|
||||
SELECT bug13198_f1();
|
||||
|
||||
# Check that u2 can call the procedure/function.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CALL bug13198_p1();
|
||||
|
||||
SELECT bug13198_f1();
|
||||
|
||||
# Drop user u1 (definer of the object);
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disconnect mysqltest_1_con
|
||||
|
||||
DROP USER mysqltest_1@localhost;
|
||||
|
||||
# Check that u2 can not call the procedure/function.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
--error ER_NO_SUCH_USER
|
||||
CALL bug13198_p1();
|
||||
|
||||
--error ER_NO_SUCH_USER
|
||||
SELECT bug13198_f1();
|
||||
|
||||
# Cleanup.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disconnect mysqltest_2_con
|
||||
|
||||
DROP USER mysqltest_2@localhost;
|
||||
|
||||
DROP DATABASE mysqltest;
|
||||
|
||||
|
||||
# End of 5.0 bugs.
|
||||
|
@ -530,7 +530,8 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables);
|
||||
bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
TABLE_LIST *create_table);
|
||||
|
||||
bool get_default_definer(THD *thd, LEX_USER *definer);
|
||||
void get_default_definer(THD *thd, LEX_USER *definer);
|
||||
LEX_USER *create_default_definer(THD *thd);
|
||||
LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
|
||||
|
||||
enum enum_mysql_completiontype {
|
||||
|
55
sql/sp.cc
55
sql/sp.cc
@ -21,6 +21,8 @@
|
||||
#include "sp_cache.h"
|
||||
#include "sql_trigger.h"
|
||||
|
||||
#include <my_user.h>
|
||||
|
||||
static bool
|
||||
create_string(THD *thd, String *buf,
|
||||
int sp_type,
|
||||
@ -28,7 +30,9 @@ create_string(THD *thd, String *buf,
|
||||
const char *params, ulong paramslen,
|
||||
const char *returns, ulong returnslen,
|
||||
const char *body, ulong bodylen,
|
||||
st_sp_chistics *chistics);
|
||||
st_sp_chistics *chistics,
|
||||
const LEX_STRING *definer_user,
|
||||
const LEX_STRING *definer_host);
|
||||
static int
|
||||
db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
||||
ulong sql_mode, const char *params, const char *returns,
|
||||
@ -406,6 +410,15 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
||||
ulong old_sql_mode= thd->variables.sql_mode;
|
||||
ha_rows old_select_limit= thd->variables.select_limit;
|
||||
sp_rcontext *old_spcont= thd->spcont;
|
||||
|
||||
char definer_user_name_holder[USERNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder,
|
||||
USERNAME_LENGTH);
|
||||
|
||||
char definer_host_name_holder[HOSTNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder,
|
||||
HOSTNAME_LENGTH);
|
||||
|
||||
int ret;
|
||||
|
||||
thd->variables.sql_mode= sql_mode;
|
||||
@ -414,14 +427,25 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
||||
thd->lex= &newlex;
|
||||
newlex.current_select= NULL;
|
||||
|
||||
parse_user(definer, strlen(definer),
|
||||
definer_user_name.str, &definer_user_name.length,
|
||||
definer_host_name.str, &definer_host_name.length);
|
||||
|
||||
defstr.set_charset(system_charset_info);
|
||||
|
||||
/*
|
||||
We have to add DEFINER clause and provide proper routine characterstics in
|
||||
routine definition statement that we build here to be able to use this
|
||||
definition for SHOW CREATE PROCEDURE later.
|
||||
*/
|
||||
|
||||
if (!create_string(thd, &defstr,
|
||||
type,
|
||||
name,
|
||||
params, strlen(params),
|
||||
returns, strlen(returns),
|
||||
body, strlen(body),
|
||||
&chistics))
|
||||
&chistics, &definer_user_name, &definer_host_name))
|
||||
{
|
||||
ret= SP_INTERNAL_ERROR;
|
||||
goto end;
|
||||
@ -449,7 +473,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
||||
if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
|
||||
goto end;
|
||||
*sphp= newlex.sphead;
|
||||
(*sphp)->set_definer((char*) definer, (uint) strlen(definer));
|
||||
(*sphp)->set_definer(&definer_user_name, &definer_host_name);
|
||||
(*sphp)->set_info(created, modified, &chistics, sql_mode);
|
||||
(*sphp)->optimize();
|
||||
}
|
||||
@ -500,8 +524,10 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
||||
else
|
||||
{
|
||||
restore_record(table, s->default_values); // Get default values for fields
|
||||
strxmov(definer, thd->security_ctx->priv_user, "@",
|
||||
thd->security_ctx->priv_host, NullS);
|
||||
|
||||
/* NOTE: all needed privilege checks have been already done. */
|
||||
strxmov(definer, thd->lex->definer->user.str, "@",
|
||||
thd->lex->definer->host.str, NullS);
|
||||
|
||||
if (table->s->fields != MYSQL_PROC_FIELD_COUNT)
|
||||
{
|
||||
@ -592,8 +618,17 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
||||
else if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
|
||||
String log_query;
|
||||
log_query.set_charset(system_charset_info);
|
||||
log_query.append(STRING_WITH_LEN("CREATE "));
|
||||
append_definer(thd, &log_query, &thd->lex->definer->user,
|
||||
&thd->lex->definer->host);
|
||||
log_query.append(thd->lex->stmt_definition_begin);
|
||||
|
||||
/* Such a statement can always go directly to binlog, no trans cache */
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
Query_log_event qinfo(thd, log_query.c_ptr(), log_query.length(), 0,
|
||||
FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
|
||||
@ -1723,14 +1758,18 @@ create_string(THD *thd, String *buf,
|
||||
const char *params, ulong paramslen,
|
||||
const char *returns, ulong returnslen,
|
||||
const char *body, ulong bodylen,
|
||||
st_sp_chistics *chistics)
|
||||
st_sp_chistics *chistics,
|
||||
const LEX_STRING *definer_user,
|
||||
const LEX_STRING *definer_host)
|
||||
{
|
||||
/* Make some room to begin with */
|
||||
if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen +
|
||||
chistics->comment.length))
|
||||
chistics->comment.length + 10 /* length of " DEFINER= "*/ +
|
||||
USER_HOST_BUFF_SIZE))
|
||||
return FALSE;
|
||||
|
||||
buf->append(STRING_WITH_LEN("CREATE "));
|
||||
append_definer(thd, buf, definer_user, definer_host);
|
||||
if (type == TYPE_ENUM_FUNCTION)
|
||||
buf->append(STRING_WITH_LEN("FUNCTION "));
|
||||
else
|
||||
|
@ -1810,19 +1810,27 @@ sp_head::set_info(longlong created, longlong modified,
|
||||
void
|
||||
sp_head::set_definer(const char *definer, uint definerlen)
|
||||
{
|
||||
uint user_name_len;
|
||||
char user_name_str[USERNAME_LENGTH + 1];
|
||||
uint host_name_len;
|
||||
char host_name_str[HOSTNAME_LENGTH + 1];
|
||||
char user_name_holder[USERNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH);
|
||||
|
||||
parse_user(definer, definerlen, user_name_str, &user_name_len,
|
||||
host_name_str, &host_name_len);
|
||||
char host_name_holder[HOSTNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH);
|
||||
|
||||
m_definer_user.str= strmake_root(mem_root, user_name_str, user_name_len);
|
||||
m_definer_user.length= user_name_len;
|
||||
parse_user(definer, definerlen, user_name.str, &user_name.length,
|
||||
host_name.str, &host_name.length);
|
||||
|
||||
m_definer_host.str= strmake_root(mem_root, host_name_str, host_name_len);
|
||||
m_definer_host.length= host_name_len;
|
||||
set_definer(&user_name, &host_name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sp_head::set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name)
|
||||
{
|
||||
m_definer_user.str= strmake_root(mem_root, user_name->str, user_name->length);
|
||||
m_definer_user.length= user_name->length;
|
||||
|
||||
m_definer_host.str= strmake_root(mem_root, host_name->str, host_name->length);
|
||||
m_definer_host.length= host_name->length;
|
||||
}
|
||||
|
||||
|
||||
@ -3163,24 +3171,9 @@ sp_change_security_context(THD *thd, sp_head *sp, Security_context **backup)
|
||||
sp->m_definer_host.str,
|
||||
sp->m_db.str))
|
||||
{
|
||||
#ifdef NOT_YET_REPLICATION_SAFE
|
||||
/*
|
||||
Until we don't properly replicate information about stored routine
|
||||
definer with stored routine creation statement all stored routines
|
||||
on slave are created under ''@'' definer. Therefore we won't be able
|
||||
to run any routine which was replicated from master on slave server
|
||||
if we emit error here. This will cause big problems for users
|
||||
who use slave for fail-over. So until we fully implement WL#2897
|
||||
"Complete definer support in the stored routines" we run suid
|
||||
stored routines for which we were unable to find definer under
|
||||
invoker security context.
|
||||
*/
|
||||
my_error(ER_NO_SUCH_USER, MYF(0), sp->m_definer_user.str,
|
||||
sp->m_definer_host.str);
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
*backup= thd->security_ctx;
|
||||
thd->security_ctx= &sp->m_security_ctx;
|
||||
|
@ -302,6 +302,7 @@ public:
|
||||
st_sp_chistics *chistics, ulong sql_mode);
|
||||
|
||||
void set_definer(const char *definer, uint definerlen);
|
||||
void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
|
||||
|
||||
void reset_thd_mem_root(THD *thd);
|
||||
|
||||
|
@ -909,12 +909,16 @@ typedef struct st_lex
|
||||
SQL_LIST trg_table_fields;
|
||||
|
||||
/*
|
||||
trigger_definition_begin points to the beginning of the word "TRIGGER" in
|
||||
CREATE TRIGGER statement. This is used to add possibly omitted DEFINER
|
||||
clause to the trigger definition statement before dumping it to the
|
||||
binlog.
|
||||
stmt_definition_begin is intended to point to the next word after
|
||||
DEFINER-clause in the following statements:
|
||||
- CREATE TRIGGER (points to "TRIGGER");
|
||||
- CREATE PROCEDURE (points to "PROCEDURE");
|
||||
- CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE");
|
||||
|
||||
This pointer is required to add possibly omitted DEFINER-clause to the
|
||||
DDL-statement before dumping it to the binlog.
|
||||
*/
|
||||
const char *trigger_definition_begin;
|
||||
const char *stmt_definition_begin;
|
||||
|
||||
/*
|
||||
If non-0 then indicates that query requires prelocking and points to
|
||||
|
132
sql/sql_parse.cc
132
sql/sql_parse.cc
@ -4145,6 +4145,90 @@ end_with_restore_list:
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
If the definer is not specified, this means that CREATE-statement missed
|
||||
DEFINER-clause. DEFINER-clause can be missed in two cases:
|
||||
|
||||
- The user submitted a statement w/o the clause. This is a normal
|
||||
case, we should assign CURRENT_USER as definer.
|
||||
|
||||
- Our slave received an updated from the master, that does not
|
||||
replicate definer for stored rountines. We should also assign
|
||||
CURRENT_USER as definer here, but also we should mark this routine
|
||||
as NON-SUID. This is essential for the sake of backward
|
||||
compatibility.
|
||||
|
||||
The problem is the slave thread is running under "special" user (@),
|
||||
that actually does not exist. In the older versions we do not fail
|
||||
execution of a stored routine if its definer does not exist and
|
||||
continue the execution under the authorization of the invoker
|
||||
(BUG#13198). And now if we try to switch to slave-current-user (@),
|
||||
we will fail.
|
||||
|
||||
Actually, this leads to the inconsistent state of master and
|
||||
slave (different definers, different SUID behaviour), but it seems,
|
||||
this is the best we can do.
|
||||
*/
|
||||
|
||||
if (!lex->definer)
|
||||
{
|
||||
bool res= FALSE;
|
||||
Query_arena original_arena;
|
||||
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
|
||||
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
res= TRUE;
|
||||
|
||||
if (ps_arena)
|
||||
thd->restore_active_arena(ps_arena, &original_arena);
|
||||
|
||||
if (res)
|
||||
{
|
||||
/* Error has been already reported. */
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (thd->slave_thread)
|
||||
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
|
||||
}
|
||||
|
||||
/*
|
||||
If the specified definer differs from the current user, we should check
|
||||
that the current user has SUPER privilege (in order to create a stored
|
||||
routine under another user one must have SUPER privilege).
|
||||
*/
|
||||
|
||||
else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info,
|
||||
lex->definer->host.str,
|
||||
thd->security_ctx->priv_host))
|
||||
{
|
||||
if (check_global_access(thd, SUPER_ACL))
|
||||
{
|
||||
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the specified definer exists. Emit a warning if not. */
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (!is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_NO_SUCH_USER,
|
||||
ER(ER_NO_SUCH_USER),
|
||||
lex->definer->user.str,
|
||||
lex->definer->host.str);
|
||||
}
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
|
||||
/*
|
||||
We need to copy name and db in order to use them for
|
||||
check_routine_access which is called after lex->sphead has
|
||||
@ -7168,41 +7252,49 @@ Item *negate_expression(THD *thd, Item *expr)
|
||||
|
||||
/*
|
||||
Set the specified definer to the default value, which is the current user in
|
||||
the thread. Also check that the current user satisfies to the definers
|
||||
requirements.
|
||||
the thread.
|
||||
|
||||
SYNOPSIS
|
||||
get_default_definer()
|
||||
thd [in] thread handler
|
||||
definer [out] definer
|
||||
|
||||
RETURN
|
||||
error status, that is:
|
||||
- FALSE -- on success;
|
||||
- TRUE -- on error (current user can not be a definer).
|
||||
*/
|
||||
|
||||
bool get_default_definer(THD *thd, LEX_USER *definer)
|
||||
void get_default_definer(THD *thd, LEX_USER *definer)
|
||||
{
|
||||
/* Check that current user has non-empty host name. */
|
||||
|
||||
const Security_context *sctx= thd->security_ctx;
|
||||
|
||||
if (sctx->priv_host[0] == 0)
|
||||
{
|
||||
my_error(ER_MALFORMED_DEFINER, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fill in. */
|
||||
|
||||
definer->user.str= (char *) sctx->priv_user;
|
||||
definer->user.length= strlen(definer->user.str);
|
||||
|
||||
definer->host.str= (char *) sctx->priv_host;
|
||||
definer->host.length= strlen(definer->host.str);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
Create default definer for the specified THD.
|
||||
|
||||
SYNOPSIS
|
||||
create_default_definer()
|
||||
thd [in] thread handler
|
||||
|
||||
RETURN
|
||||
On success, return a valid pointer to the created and initialized
|
||||
LEX_USER, which contains definer information.
|
||||
On error, return 0.
|
||||
*/
|
||||
|
||||
LEX_USER *create_default_definer(THD *thd)
|
||||
{
|
||||
LEX_USER *definer;
|
||||
|
||||
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
|
||||
return 0;
|
||||
|
||||
get_default_definer(thd, definer);
|
||||
|
||||
return definer;
|
||||
}
|
||||
|
||||
|
||||
@ -7218,7 +7310,7 @@ bool get_default_definer(THD *thd, LEX_USER *definer)
|
||||
|
||||
RETURN
|
||||
On success, return a valid pointer to the created and initialized
|
||||
LEX_STRING, which contains definer information.
|
||||
LEX_USER, which contains definer information.
|
||||
On error, return 0.
|
||||
*/
|
||||
|
||||
|
@ -264,8 +264,18 @@ end:
|
||||
log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */
|
||||
|
||||
log_query.append(STRING_WITH_LEN("CREATE "));
|
||||
append_definer(thd, &log_query, &definer_user, &definer_host);
|
||||
log_query.append(thd->lex->trigger_definition_begin);
|
||||
|
||||
if (definer_user.str && definer_host.str)
|
||||
{
|
||||
/*
|
||||
Append definer-clause if the trigger is SUID (a usual trigger in
|
||||
new MySQL versions).
|
||||
*/
|
||||
|
||||
append_definer(thd, &log_query, &definer_user, &definer_host);
|
||||
}
|
||||
|
||||
log_query.append(thd->lex->stmt_definition_begin);
|
||||
}
|
||||
|
||||
/* Such a statement can always go directly to binlog, no trans cache. */
|
||||
@ -289,17 +299,30 @@ end:
|
||||
LEX)
|
||||
tables - table list containing one open table for which the
|
||||
trigger is created.
|
||||
definer_user - [out] after a call it points to 0-terminated string,
|
||||
which contains user name part of the actual trigger
|
||||
definer. The caller is responsible to provide memory for
|
||||
definer_user - [out] after a call it points to 0-terminated string or
|
||||
contains the NULL-string:
|
||||
- 0-terminated is returned if the trigger is SUID. The
|
||||
string contains user name part of the actual trigger
|
||||
definer.
|
||||
- NULL-string is returned if the trigger is non-SUID.
|
||||
Anyway, the caller is responsible to provide memory for
|
||||
storing LEX_STRING object.
|
||||
definer_host - [out] after a call it points to 0-terminated string,
|
||||
which contains host name part of the actual trigger
|
||||
definer. The caller is responsible to provide memory for
|
||||
definer_host - [out] after a call it points to 0-terminated string or
|
||||
contains the NULL-string:
|
||||
- 0-terminated string is returned if the trigger is
|
||||
SUID. The string contains host name part of the
|
||||
actual trigger definer.
|
||||
- NULL-string is returned if the trigger is non-SUID.
|
||||
Anyway, the caller is responsible to provide memory for
|
||||
storing LEX_STRING object.
|
||||
|
||||
NOTE
|
||||
Assumes that trigger name is fully qualified.
|
||||
- Assumes that trigger name is fully qualified.
|
||||
- NULL-string means the following LEX_STRING instance:
|
||||
{ str = 0; length = 0 }.
|
||||
- In other words, definer_user and definer_host should contain
|
||||
simultaneously NULL-strings (non-SUID/old trigger) or valid strings
|
||||
(SUID/new trigger).
|
||||
|
||||
RETURN VALUE
|
||||
False - success
|
||||
@ -336,12 +359,30 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Definer attribute of the Lex instance is always set in sql_yacc.yy when
|
||||
trigger is created.
|
||||
*/
|
||||
if (!lex->definer)
|
||||
{
|
||||
/*
|
||||
DEFINER-clause is missing.
|
||||
|
||||
DBUG_ASSERT(lex->definer);
|
||||
If we are in slave thread, this means that we received CREATE TRIGGER
|
||||
from the master, that does not support definer in triggers. So, we
|
||||
should mark this trigger as non-SUID. Note that this does not happen
|
||||
when we parse triggers' definitions during opening .TRG file.
|
||||
LEX::definer is ignored in that case.
|
||||
|
||||
Otherwise, we should use CURRENT_USER() as definer.
|
||||
|
||||
NOTE: when CREATE TRIGGER statement is allowed to be executed in PS/SP,
|
||||
it will be required to create the definer below in persistent MEM_ROOT
|
||||
of PS/SP.
|
||||
*/
|
||||
|
||||
if (!thd->slave_thread)
|
||||
{
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If the specified definer differs from the current user, we should check
|
||||
@ -349,10 +390,11 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
under another user one must have SUPER privilege).
|
||||
*/
|
||||
|
||||
if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info,
|
||||
lex->definer->host.str,
|
||||
thd->security_ctx->priv_host))
|
||||
if (lex->definer &&
|
||||
(strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info,
|
||||
lex->definer->host.str,
|
||||
thd->security_ctx->priv_host)))
|
||||
{
|
||||
if (check_global_access(thd, SUPER_ACL))
|
||||
{
|
||||
@ -446,8 +488,8 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
*trg_sql_mode= thd->variables.sql_mode;
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (!is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
if (lex->definer && !is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
@ -458,12 +500,30 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
|
||||
*definer_user= lex->definer->user;
|
||||
*definer_host= lex->definer->host;
|
||||
if (lex->definer)
|
||||
{
|
||||
/* SUID trigger. */
|
||||
|
||||
trg_definer->str= trg_definer_holder;
|
||||
trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
|
||||
definer_host->str, NullS) - trg_definer->str;
|
||||
*definer_user= lex->definer->user;
|
||||
*definer_host= lex->definer->host;
|
||||
|
||||
trg_definer->str= trg_definer_holder;
|
||||
trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
|
||||
definer_host->str, NullS) - trg_definer->str;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* non-SUID trigger. */
|
||||
|
||||
definer_user->str= 0;
|
||||
definer_user->length= 0;
|
||||
|
||||
definer_host->str= 0;
|
||||
definer_host->length= 0;
|
||||
|
||||
trg_definer->str= (char*) "";
|
||||
trg_definer->length= 0;
|
||||
}
|
||||
|
||||
if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
|
||||
(gptr)this, triggers_file_parameters, 0))
|
||||
|
@ -208,6 +208,26 @@ bool mysql_create_view(THD *thd,
|
||||
if (mode != VIEW_CREATE_NEW)
|
||||
sp_cache_invalidate();
|
||||
|
||||
if (!lex->definer)
|
||||
{
|
||||
/*
|
||||
DEFINER-clause is missing; we have to create default definer in
|
||||
persistent arena to be PS/SP friendly.
|
||||
*/
|
||||
|
||||
Query_arena original_arena;
|
||||
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
|
||||
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
res= TRUE;
|
||||
|
||||
if (ps_arena)
|
||||
thd->restore_active_arena(ps_arena, &original_arena);
|
||||
|
||||
if (res)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/*
|
||||
check definer of view:
|
||||
@ -815,8 +835,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
|
||||
table->db, table->table_name);
|
||||
if (get_default_definer(thd, &table->definer))
|
||||
goto err;
|
||||
get_default_definer(thd, &table->definer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
256
sql/sql_yacc.yy
256
sql/sql_yacc.yy
@ -778,7 +778,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
|
||||
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
|
||||
|
||||
%type <lex_user> user grant_user get_definer
|
||||
%type <lex_user> user grant_user
|
||||
|
||||
%type <charset>
|
||||
opt_collate
|
||||
@ -833,8 +833,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
||||
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
||||
definer view_replace_or_algorithm view_replace view_algorithm_opt
|
||||
view_algorithm view_or_trigger_tail view_suid view_tail view_list_opt
|
||||
view_list view_select view_check_option trigger_tail
|
||||
view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
|
||||
view_suid view_tail view_list_opt view_list view_select
|
||||
view_check_option trigger_tail sp_tail
|
||||
END_OF_INPUT
|
||||
|
||||
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
|
||||
@ -1189,81 +1190,13 @@ create:
|
||||
lex->name=$4.str;
|
||||
lex->create_info.options=$3;
|
||||
}
|
||||
| CREATE udf_func_type FUNCTION_SYM sp_name
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->spname= $4;
|
||||
lex->udf.type= $2;
|
||||
}
|
||||
create_function_tail
|
||||
{}
|
||||
| CREATE PROCEDURE sp_name
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
|
||||
YYABORT;
|
||||
}
|
||||
/* Order is important here: new - reset - init */
|
||||
sp= new sp_head();
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->init(lex);
|
||||
|
||||
sp->m_type= TYPE_ENUM_PROCEDURE;
|
||||
lex->sphead= sp;
|
||||
/*
|
||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||
* stored procedure, otherwise yylex will chop it into pieces
|
||||
* at each ';'.
|
||||
*/
|
||||
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
|
||||
}
|
||||
'('
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||
}
|
||||
sp_pdparam_list
|
||||
')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_end= lex->tok_start;
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
}
|
||||
sp_c_chistics
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->tok_start;
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
if (sp->check_backpatch(YYTHD))
|
||||
YYABORT;
|
||||
sp->init_strings(YYTHD, lex, $3);
|
||||
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||
/* Restore flag if it was cleared above */
|
||||
if (sp->m_old_cmq)
|
||||
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
||||
sp->restore_thd_mem_root(YYTHD);
|
||||
}
|
||||
| CREATE
|
||||
{
|
||||
Lex->create_view_mode= VIEW_CREATE_NEW;
|
||||
Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
|
||||
Lex->create_view_suid= TRUE;
|
||||
}
|
||||
view_or_trigger
|
||||
view_or_trigger_or_sp
|
||||
{}
|
||||
| CREATE USER clear_privileges grant_list
|
||||
{
|
||||
@ -8957,45 +8890,61 @@ subselect_end:
|
||||
lex->nest_level--;
|
||||
};
|
||||
|
||||
definer:
|
||||
get_definer
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
|
||||
if (! (thd->lex->definer= create_definer(thd, &$1->user, &$1->host)))
|
||||
YYABORT;
|
||||
}
|
||||
/**************************************************************************
|
||||
|
||||
CREATE VIEW | TRIGGER | PROCEDURE statements.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
view_or_trigger_or_sp:
|
||||
definer view_or_trigger_or_sp_tail
|
||||
{}
|
||||
| view_replace_or_algorithm definer view_tail
|
||||
{}
|
||||
;
|
||||
|
||||
get_definer:
|
||||
opt_current_definer
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
|
||||
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
|
||||
YYABORT;
|
||||
|
||||
if (get_default_definer(thd, $$))
|
||||
YYABORT;
|
||||
}
|
||||
| DEFINER_SYM EQ ident_or_text '@' ident_or_text
|
||||
{
|
||||
if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
|
||||
YYABORT;
|
||||
|
||||
$$->user= $3;
|
||||
$$->host= $5;
|
||||
}
|
||||
;
|
||||
|
||||
opt_current_definer:
|
||||
/* empty */
|
||||
| DEFINER_SYM EQ CURRENT_USER optional_braces
|
||||
view_or_trigger_or_sp_tail:
|
||||
view_tail
|
||||
{}
|
||||
| trigger_tail
|
||||
{}
|
||||
| sp_tail
|
||||
{}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
CREATE VIEW statement options.
|
||||
DEFINER clause support.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
definer:
|
||||
/* empty */
|
||||
{
|
||||
/*
|
||||
We have to distinguish missing DEFINER-clause from case when
|
||||
CURRENT_USER specified as definer explicitly in order to properly
|
||||
handle CREATE TRIGGER statements which come to replication thread
|
||||
from older master servers (i.e. to create non-suid trigger in this
|
||||
case).
|
||||
*/
|
||||
YYTHD->lex->definer= 0;
|
||||
}
|
||||
| DEFINER_SYM EQ CURRENT_USER optional_braces
|
||||
{
|
||||
if (! (YYTHD->lex->definer= create_default_definer(YYTHD)))
|
||||
YYABORT;
|
||||
}
|
||||
| DEFINER_SYM EQ ident_or_text '@' ident_or_text
|
||||
{
|
||||
if (!(YYTHD->lex->definer= create_definer(YYTHD, &$3, &$5)))
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
CREATE VIEW statement parts.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
@ -9029,20 +8978,6 @@ view_algorithm_opt:
|
||||
{}
|
||||
;
|
||||
|
||||
view_or_trigger:
|
||||
definer view_or_trigger_tail
|
||||
{}
|
||||
| view_replace_or_algorithm definer view_tail
|
||||
{}
|
||||
;
|
||||
|
||||
view_or_trigger_tail:
|
||||
view_tail
|
||||
{}
|
||||
| trigger_tail
|
||||
{}
|
||||
;
|
||||
|
||||
view_suid:
|
||||
/* empty */
|
||||
{ Lex->create_view_suid= TRUE; }
|
||||
@ -9141,7 +9076,7 @@ trigger_tail:
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->init(lex);
|
||||
|
||||
lex->trigger_definition_begin= $2;
|
||||
lex->stmt_definition_begin= $2;
|
||||
lex->ident.str= $7;
|
||||
lex->ident.length= $10 - $7;
|
||||
|
||||
@ -9190,6 +9125,87 @@ trigger_tail:
|
||||
}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
CREATE FUNCTION | PROCEDURE statements parts.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
sp_tail:
|
||||
udf_func_type remember_name FUNCTION_SYM sp_name
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->udf.type= $1;
|
||||
lex->stmt_definition_begin= $2;
|
||||
lex->spname= $4;
|
||||
}
|
||||
create_function_tail
|
||||
{}
|
||||
| PROCEDURE remember_name sp_name
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
lex->stmt_definition_begin= $2;
|
||||
|
||||
/* Order is important here: new - reset - init */
|
||||
sp= new sp_head();
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->init(lex);
|
||||
|
||||
sp->m_type= TYPE_ENUM_PROCEDURE;
|
||||
lex->sphead= sp;
|
||||
/*
|
||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||
* stored procedure, otherwise yylex will chop it into pieces
|
||||
* at each ';'.
|
||||
*/
|
||||
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
|
||||
}
|
||||
'('
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||
}
|
||||
sp_pdparam_list
|
||||
')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_end= lex->tok_start;
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
}
|
||||
sp_c_chistics
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->tok_start;
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
if (sp->check_backpatch(YYTHD))
|
||||
YYABORT;
|
||||
sp->init_strings(YYTHD, lex, $3);
|
||||
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||
/* Restore flag if it was cleared above */
|
||||
if (sp->m_old_cmq)
|
||||
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
||||
sp->restore_thd_mem_root(YYTHD);
|
||||
}
|
||||
;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
xa: XA_SYM begin_or_start xid opt_join_or_resume
|
||||
|
Loading…
x
Reference in New Issue
Block a user