summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/mysqldump.c48
-rw-r--r--mysql-test/r/gis.result2
-rw-r--r--mysql-test/r/information_schema.result4
-rw-r--r--mysql-test/r/mysqldump.result14
-rw-r--r--mysql-test/r/rpl_ddl.result4
-rw-r--r--mysql-test/r/rpl_sp.result30
-rw-r--r--mysql-test/r/rpl_trigger.result2
-rw-r--r--mysql-test/r/sp-security.result52
-rw-r--r--mysql-test/r/sp.result28
-rw-r--r--mysql-test/r/sql_mode.result8
-rw-r--r--mysql-test/t/sp-security.test101
-rw-r--r--sql/sp.cc55
-rw-r--r--sql/sp_head.cc28
-rw-r--r--sql/sp_head.h1
-rw-r--r--sql/sql_lex.h14
-rw-r--r--sql/sql_parse.cc84
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_yacc.yy202
18 files changed, 521 insertions, 158 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 161197821d6..e0469e00031 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -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 */
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 049ba784dc9..13e2d56d83e 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -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())
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index d3576e24a44..1c845c73e4b 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -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;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index d156e711167..e6ac9fbc740 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -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;
diff --git a/mysql-test/r/rpl_ddl.result b/mysql-test/r/rpl_ddl.result
index c56c9f20cf8..92e91b31459 100644
--- a/mysql-test/r/rpl_ddl.result
+++ b/mysql-test/r/rpl_ddl.result
@@ -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
diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result
index a42c33ce333..5dfda16c763 100644
--- a/mysql-test/r/rpl_sp.result
+++ b/mysql-test/r/rpl_sp.result
@@ -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);
diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result
index 185862097bc..b9b20b82acd 100644
--- a/mysql-test/r/rpl_trigger.result
+++ b/mysql-test/r/rpl_trigger.result
@@ -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
diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result
index d8abc387677..90466bfcfc4 100644
--- a/mysql-test/r/sp-security.result
+++ b/mysql-test/r/sp-security.result
@@ -323,3 +323,55 @@ 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;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index a4c920f8e15..3e7c51e9394 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -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
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 66df424919b..b05680f9c54 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -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='';
diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test
index 19f94a32d9c..b466d2125d4 100644
--- a/mysql-test/t/sp-security.test
+++ b/mysql-test/t/sp-security.test
@@ -547,4 +547,105 @@ 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;
+
+
# End of 5.0 bugs.
diff --git a/sql/sp.cc b/sql/sp.cc
index ce0282bf810..e4489af1fdd 100644
--- a/sql/sp.cc
+++ b/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
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index f7572a374f1..b8b7ee2f78b 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -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;
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index a4dd68ee4a3..64d9167fb17 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -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);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 7b2ea359fb2..8db059ae2fa 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 13d814bdf42..527a6a67811 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4146,6 +4146,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
been deleted.
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 9ccc70d8ccd..1fe5bf63756 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -275,7 +275,7 @@ end:
append_definer(thd, &log_query, &definer_user, &definer_host);
}
- log_query.append(thd->lex->trigger_definition_begin);
+ log_query.append(thd->lex->stmt_definition_begin);
}
/* Such a statement can always go directly to binlog, no trans cache. */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 7e93b9c8e73..36a684f1d4a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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
{
@@ -8959,6 +8892,34 @@ subselect_end:
lex->nest_level--;
};
+/**************************************************************************
+
+ CREATE VIEW | TRIGGER | PROCEDURE statements.
+
+**************************************************************************/
+
+view_or_trigger_or_sp:
+ definer view_or_trigger_or_sp_tail
+ {}
+ | view_replace_or_algorithm definer view_tail
+ {}
+ ;
+
+view_or_trigger_or_sp_tail:
+ view_tail
+ {}
+ | trigger_tail
+ {}
+ | sp_tail
+ {}
+ ;
+
+/**************************************************************************
+
+ DEFINER clause support.
+
+**************************************************************************/
+
definer:
/* empty */
{
@@ -8985,7 +8946,7 @@ definer:
/**************************************************************************
- CREATE VIEW statement options.
+ CREATE VIEW statement parts.
**************************************************************************/
@@ -9019,20 +8980,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; }
@@ -9131,7 +9078,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= $9 - $7;
@@ -9180,6 +9127,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