summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysqld_error.h3
-rw-r--r--include/sql_state.h1
-rw-r--r--mysql-test/r/show_check.result1
-rw-r--r--mysql-test/r/sp-error.result4
-rw-r--r--mysql-test/r/sp-security.result22
-rw-r--r--mysql-test/r/sp.result59
-rw-r--r--mysql-test/r/status.result2
-rw-r--r--mysql-test/t/sp-error.test6
-rw-r--r--mysql-test/t/sp-security.test18
-rw-r--r--mysql-test/t/sp.test31
-rw-r--r--sql/item_func.cc27
-rw-r--r--sql/item_func.h16
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/share/czech/errmsg.txt1
-rw-r--r--sql/share/danish/errmsg.txt1
-rw-r--r--sql/share/dutch/errmsg.txt1
-rw-r--r--sql/share/english/errmsg.txt1
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt1
-rw-r--r--sql/share/german/errmsg.txt1
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt1
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt1
-rw-r--r--sql/share/norwegian/errmsg.txt1
-rw-r--r--sql/share/polish/errmsg.txt1
-rw-r--r--sql/share/portuguese/errmsg.txt1
-rw-r--r--sql/share/romanian/errmsg.txt1
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt1
-rw-r--r--sql/share/slovak/errmsg.txt1
-rw-r--r--sql/share/spanish/errmsg.txt1
-rw-r--r--sql/share/swedish/errmsg.txt1
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/sp.cc245
-rw-r--r--sql/sp.h36
-rw-r--r--sql/sp_cache.cc13
-rw-r--r--sql/sp_cache.h4
-rw-r--r--sql/sp_head.cc144
-rw-r--r--sql/sp_head.h60
-rw-r--r--sql/sql_db.cc95
-rw-r--r--sql/sql_lex.cc32
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc50
-rw-r--r--sql/sql_yacc.yy207
47 files changed, 683 insertions, 421 deletions
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index a3e063d4ed7..113eb07ed66 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -339,4 +339,5 @@
#define ER_SP_DUP_CURS 1320
#define ER_SP_CANT_ALTER 1321
#define ER_SP_SUBSELECT_NYI 1322
-#define ER_ERROR_MESSAGES 323
+#define ER_SP_NO_USE 1323
+#define ER_ERROR_MESSAGES 324
diff --git a/include/sql_state.h b/include/sql_state.h
index f4fbe434490..c5a71daceb9 100644
--- a/include/sql_state.h
+++ b/include/sql_state.h
@@ -196,3 +196,4 @@ ER_SP_DUP_COND, "42000", "",
ER_SP_DUP_CURS, "42000", "",
/*ER_SP_CANT_ALTER*/
ER_SP_SUBSELECT_NYI, "0A000", "",
+ER_SP_NO_USE, "42000", "",
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 3fa700ccf26..4645e7d9b9c 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -144,7 +144,6 @@ insert into t1 values (1);
show open tables;
Database Table In_use Name_locked
test t1 0 0
-mysql proc 0 0
drop table t1;
create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" ENGINE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed;
show create table t1;
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index f965cf90eb4..1877789e2b0 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -251,6 +251,10 @@ declare c cursor for select * from t1;
declare c cursor for select field from t1;
end|
ERROR 42000: Duplicate cursor: c
+create procedure u()
+use sptmp;
+#|
+ERROR 42000: USE is not allowed in a stored procedure
create procedure bug1965()
begin
declare c cursor for select val from t1 order by valname;
diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result
index c4fbece9d72..51439e08782 100644
--- a/mysql-test/r/sp-security.result
+++ b/mysql-test/r/sp-security.result
@@ -8,16 +8,16 @@ create table t1 ( u varchar(64), i int );
create procedure stamp(i int)
insert into db1_secret.t1 values (user(), i);
show procedure status like 'stamp';
-Name Type Definer Modified Created Security_type Comment
-stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+Db Name Type Definer Modified Created Security_type Comment
+db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call stamp(1);
select * from t1;
u i
root@localhost 1
-call stamp(2);
+call db1_secret.stamp(2);
select * from db1_secret.t1;
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
-call stamp(3);
+call db1_secret.stamp(3);
select * from db1_secret.t1;
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
select * from t1;
@@ -27,8 +27,8 @@ user1@localhost 2
anon@localhost 3
alter procedure stamp sql security invoker;
show procedure status like 'stamp';
-Name Type Definer Modified Created Security_type Comment
-stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
+Db Name Type Definer Modified Created Security_type Comment
+db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
call stamp(4);
select * from t1;
u i
@@ -36,9 +36,9 @@ root@localhost 1
user1@localhost 2
anon@localhost 3
root@localhost 4
-call stamp(5);
+call db1_secret.stamp(5);
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
-call stamp(6);
+call db1_secret.stamp(6);
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
drop database if exists db2;
create database db2;
@@ -73,9 +73,9 @@ s1
0
2
2
-drop procedure stamp;
-drop procedure p;
-drop procedure q;
+drop procedure db1_secret.stamp;
+drop procedure db2.p;
+drop procedure db2.q;
use test;
drop database db1_secret;
drop database db2;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 2b91e8de270..f1fa1735ead 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -18,17 +18,6 @@ id data
foo 42
delete from t1;
drop procedure foo42;
-create procedure u()
-use sptmp;
-drop database if exists sptmp;
-create database sptmp;
-use test;
-call u();
-select database();
-database()
-test
-drop database sptmp;
-drop procedure u;
create procedure bar(x char(16), y int)
insert into test.t1 values (x, y);
call bar("bar", 666);
@@ -746,7 +735,7 @@ delete from t1|
alter procedure chistics sql security invoker name chistics2|
show create procedure chistics2|
Procedure Create Procedure
-chistics2 CREATE PROCEDURE `chistics2`()
+chistics2 CREATE PROCEDURE `test`.`chistics2`()
SQL SECURITY INVOKER
COMMENT 'Characteristics procedure test'
insert into t1 values ("chistics", 1)
@@ -763,7 +752,7 @@ chistics()
alter function chistics name chistics2 comment 'Characteristics function test'|
show create function chistics2|
Function Create Function
-chistics2 CREATE FUNCTION `chistics2`() RETURNS int
+chistics2 CREATE FUNCTION `test`.`chistics2`() RETURNS int
DETERMINISTIC
SQL SECURITY INVOKER
COMMENT 'Characteristics function test'
@@ -939,23 +928,23 @@ begin
show create function fac;
end|
call bug2267_1()|
-Name Type Definer Modified Created Security_type Comment
-bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
-bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
-bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
-bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+Db Name Type Definer Modified Created Security_type Comment
+test bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call bug2267_2()|
-Name Type Definer Modified Created Security_type Comment
-fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+Db Name Type Definer Modified Created Security_type Comment
+test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call bug2267_3()|
Procedure Create Procedure
-bug2267_1 CREATE PROCEDURE `bug2267_1`()
+bug2267_1 CREATE PROCEDURE `test`.`bug2267_1`()
begin
show procedure status;
end
call bug2267_4()|
Function Create Function
-fac CREATE FUNCTION `fac`(n int unsigned) RETURNS bigint unsigned
+fac CREATE FUNCTION `test`.`fac`(n int unsigned) RETURNS bigint unsigned
begin
declare f bigint unsigned default 1;
while n > 1 do
@@ -1035,12 +1024,12 @@ n f
20 2432902008176640000
drop table fac|
show function status like '%f%'|
-Name Type Definer Modified Created Security_type Comment
-fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+Db Name Type Definer Modified Created Security_type Comment
+test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
drop procedure ifac|
drop function fac|
show function status like '%f%'|
-Name Type Definer Modified Created Security_type Comment
+Db Name Type Definer Modified Created Security_type Comment
drop table if exists primes|
create table primes (
i int unsigned not null primary key,
@@ -1101,7 +1090,7 @@ end while;
end|
show create procedure opp|
Procedure Create Procedure
-opp CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
+opp CREATE PROCEDURE `test`.`opp`(n bigint unsigned, out pp bool)
begin
declare r double;
declare b, s bigint unsigned default 0;
@@ -1128,9 +1117,9 @@ end if;
end loop;
end
show procedure status like '%p%'|
-Name Type Definer Modified Created Security_type Comment
-ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
-opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+Db Name Type Definer Modified Created Security_type Comment
+test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call ip(200)|
select * from primes where i=45 or i=100 or i=199|
i p
@@ -1141,7 +1130,7 @@ drop table primes|
drop procedure opp|
drop procedure ip|
show procedure status like '%p%'|
-Name Type Definer Modified Created Security_type Comment
+Db Name Type Definer Modified Created Security_type Comment
drop table if exists fib|
create table fib ( f bigint unsigned not null )|
insert into fib values (1), (1)|
@@ -1191,19 +1180,19 @@ create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
insert into test.t1 values (x, y)|
show procedure status like 'bar'|
-Name Type Definer Modified Created Security_type Comment
-bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111
+Db Name Type Definer Modified Created Security_type Comment
+test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111
alter procedure bar name bar2 comment "2222222222" sql security definer|
alter procedure bar2 name bar comment "3333333333"|
alter procedure bar|
show create procedure bar|
Procedure Create Procedure
-bar CREATE PROCEDURE `bar`(x char(16), y int)
+bar CREATE PROCEDURE `test`.`bar`(x char(16), y int)
COMMENT '3333333333'
insert into test.t1 values (x, y)
show procedure status like 'bar'|
-Name Type Definer Modified Created Security_type Comment
-bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER 3333333333
+Db Name Type Definer Modified Created Security_type Comment
+test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER 3333333333
drop procedure bar|
drop table t1;
drop table t2;
diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result
index 3134fdcf5ee..e9616232fa1 100644
--- a/mysql-test/r/status.result
+++ b/mysql-test/r/status.result
@@ -14,6 +14,6 @@ update t1 set n = 3;
unlock tables;
show status like 'Table_lock%';
Variable_name Value
-Table_locks_immediate 4
+Table_locks_immediate 3
Table_locks_waited 1
drop table t1;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 68a5ccdbe42..43b5c04766a 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -330,6 +330,12 @@ begin
declare c cursor for select field from t1;
end|
+# USE is not allowed
+--error 1323
+create procedure u()
+ use sptmp;
+
+
#
# BUG#1965
#
diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test
index ac7477869a1..2d089e72d0b 100644
--- a/mysql-test/t/sp-security.test
+++ b/mysql-test/t/sp-security.test
@@ -24,7 +24,7 @@ create table t1 ( u varchar(64), i int );
# Our test procedure
create procedure stamp(i int)
insert into db1_secret.t1 values (user(), i);
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'stamp';
# root can, of course
@@ -40,7 +40,7 @@ connect (con3anon,localhost,anon,,);
connection con2user1;
# This should work...
-call stamp(2);
+call db1_secret.stamp(2);
# ...but not this
--error 1044
@@ -52,7 +52,7 @@ select * from db1_secret.t1;
connection con3anon;
# This should work...
-call stamp(3);
+call db1_secret.stamp(3);
# ...but not this
--error 1044
@@ -68,7 +68,7 @@ select * from t1;
# Change to invoker's rights
#
alter procedure stamp sql security invoker;
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'stamp';
# root still can
@@ -82,7 +82,7 @@ connection con2user1;
# This should not work
--error 1044
-call stamp(5);
+call db1_secret.stamp(5);
#
# Anonymous cannot
@@ -91,7 +91,7 @@ connection con3anon;
# This should not work
--error 1044
-call stamp(6);
+call db1_secret.stamp(6);
#
@@ -148,9 +148,9 @@ select * from t2;
# Clean up
connection con1root;
-drop procedure stamp;
-drop procedure p;
-drop procedure q;
+drop procedure db1_secret.stamp;
+drop procedure db2.p;
+drop procedure db2.q;
use test;
drop database db1_secret;
drop database db2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index fd6cb4a300a..5dae97b371e 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -31,21 +31,6 @@ delete from t1;
drop procedure foo42;
-# USE test: Make sure we remain in the same DB.
-create procedure u()
- use sptmp;
-
---disable_warnings
-drop database if exists sptmp;
---enable_warnings
-create database sptmp;
-use test;
-call u();
-select database();
-drop database sptmp;
-drop procedure u;
-
-
# Single statement, two IN params.
create procedure bar(x char(16), y int)
insert into test.t1 values (x, y);
@@ -1094,9 +1079,9 @@ begin
show create function fac;
end|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
call bug2267_1()|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
call bug2267_2()|
call bug2267_3()|
call bug2267_4()|
@@ -1178,11 +1163,11 @@ end|
call ifac(20)|
select * from fac|
drop table fac|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like '%f%'|
drop procedure ifac|
drop function fac|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like '%f%'|
@@ -1259,7 +1244,7 @@ begin
end while;
end|
show create procedure opp|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like '%p%'|
# This isn't the fastest way in the world to compute prime numbers, so
@@ -1271,7 +1256,7 @@ select * from primes where i=45 or i=100 or i=199|
drop table primes|
drop procedure opp|
drop procedure ip|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like '%p%'|
@@ -1318,13 +1303,13 @@ drop procedure fib|
create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
insert into test.t1 values (x, y)|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'bar'|
alter procedure bar name bar2 comment "2222222222" sql security definer|
alter procedure bar2 name bar comment "3333333333"|
alter procedure bar|
show create procedure bar|
---replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status like 'bar'|
drop procedure bar|
delimiter ;|
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d1d03b21eed..fdb0a5e5240 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3088,6 +3088,25 @@ longlong Item_func_is_used_lock::val_int()
return ull->thread_id;
}
+
+Item_func_sp::Item_func_sp(sp_name *name)
+ :Item_func(), m_name(name), m_sp(NULL)
+{
+ m_name->init_qname(current_thd);
+}
+
+Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
+ :Item_func(list), m_name(name), m_sp(NULL)
+{
+ m_name->init_qname(current_thd);
+}
+
+const char *
+Item_func_sp::func_name() const
+{
+ return m_name->m_name.str;
+}
+
int
Item_func_sp::execute(Item **itp)
{
@@ -3099,7 +3118,7 @@ Item_func_sp::execute(Item **itp)
#endif
if (! m_sp)
- m_sp= sp_find_function(thd, &m_name);
+ m_sp= sp_find_function(thd, m_name);
if (! m_sp)
DBUG_RETURN(-1);
@@ -3122,7 +3141,7 @@ Item_func_sp::field_type() const
DBUG_ENTER("Item_func_sp::field_type");
if (! m_sp)
- m_sp= sp_find_function(current_thd, const_cast<LEX_STRING*>(&m_name));
+ m_sp= sp_find_function(current_thd, m_name);
if (m_sp)
{
DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns));
@@ -3138,7 +3157,7 @@ Item_func_sp::result_type() const
DBUG_PRINT("info", ("m_sp = %p", m_sp));
if (! m_sp)
- m_sp= sp_find_function(current_thd, const_cast<LEX_STRING*>(&m_name));
+ m_sp= sp_find_function(current_thd, m_name);
if (m_sp)
{
DBUG_RETURN(m_sp->result());
@@ -3152,7 +3171,7 @@ Item_func_sp::fix_length_and_dec()
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
if (! m_sp)
- m_sp= sp_find_function(current_thd, &m_name);
+ m_sp= sp_find_function(current_thd, m_name);
if (m_sp)
{
switch (m_sp->result()) {
diff --git a/sql/item_func.h b/sql/item_func.h
index 75c8b348347..e68826ca56e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1072,32 +1072,26 @@ enum Cast_target
*/
class sp_head;
+class sp_name;
class Item_func_sp :public Item_func
{
private:
- LEX_STRING m_name;
+ sp_name *m_name;
mutable sp_head *m_sp;
int execute(Item **itp);
public:
- Item_func_sp(LEX_STRING name)
- :Item_func(), m_name(name), m_sp(NULL)
- {}
+ Item_func_sp(sp_name *name);
- Item_func_sp(LEX_STRING name, List<Item> &list)
- :Item_func(list), m_name(name), m_sp(NULL)
- {}
+ Item_func_sp(sp_name *name, List<Item> &list);
virtual ~Item_func_sp()
{}
- const char *func_name() const
- {
- return m_name.str;
- }
+ const char *func_name() const;
enum enum_field_types field_type() const;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e17847ebe24..21822e02d29 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -445,7 +445,8 @@ int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
int quick_rm_table(enum db_type base,const char *db,
const char *table_name);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
-bool mysql_change_db(THD *thd,const char *name);
+bool mysql_change_db(THD *thd,const char *name,
+ bool empty_is_ok=0, bool no_access_check=0);
void mysql_parse(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command);
void free_items(Item *item);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 117bf4b37d4..eea5912cbdf 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -335,3 +335,4 @@ character-set=latin2
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index ba012e0eea3..2c2782d4cf0 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -329,3 +329,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 0349929f0d3..84bd5781ffb 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -337,3 +337,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 6bf4bde9b22..2c88e1b445f 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -326,3 +326,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 03e2d4d6c90..d72d7f94309 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -331,3 +331,4 @@ character-set=latin7
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index dab2ab9f51d..227b5138e98 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -326,3 +326,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 5b2378dde22..d4e42ed5d58 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -338,3 +338,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index a840e95de97..44e072bb20e 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -326,3 +326,4 @@ character-set=greek
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 0b24ca6afb8..72fdf4f8c51 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -328,3 +328,4 @@ character-set=latin2
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index a298baa7682..6694f220848 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -326,3 +326,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index a25357ae079..896146749a9 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -328,3 +328,4 @@ character-set=ujis
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index d3799d881ed..3a92c060c67 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -326,3 +326,4 @@ character-set=euckr
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index d69d52408ff..ada0435b52a 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -328,3 +328,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 5fbbaf19480..d0688b2858c 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -328,3 +328,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 92572db5fdc..d0c96146441 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -330,3 +330,4 @@ character-set=latin2
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 580fec472b6..71be50ba262 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -327,3 +327,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 3e6bff75591..d800906e663 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -330,3 +330,4 @@ character-set=latin2
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index b04cda84efd..633e29e8c48 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -328,3 +328,4 @@ character-set=koi8r
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 2737ce26873..efda5bb12cc 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -321,3 +321,4 @@ character-set=cp1250
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index bf9fe6d3519..8fa84320a8f 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -334,3 +334,4 @@ character-set=latin2
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index fec6bbb4342..75a6d42bec8 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -328,3 +328,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 8b2892172ba..9b743acb930 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -326,3 +326,4 @@ character-set=latin1
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 393c765a8ca..2b3587e2028 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -331,3 +331,4 @@ character-set=koi8u
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
"Subselect value not supported"
+"USE is not allowed in a stored procedure"
diff --git a/sql/sp.cc b/sql/sp.cc
index f517504e1f5..1b58c709e4e 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -23,7 +23,7 @@
static char *
create_string(THD *thd, ulong *lenp,
int sp_type,
- char *name, ulong namelen,
+ sp_name *name,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
@@ -58,21 +58,26 @@ enum
/* *opened=true means we opened ourselves */
static int
-db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
+db_find_routine_aux(THD *thd, int type, sp_name *name,
enum thr_lock_type ltype, TABLE **tablep, bool *opened)
{
TABLE *table;
byte key[64+64+1]; // db, name, type
uint keylen;
DBUG_ENTER("db_find_routine_aux");
- DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
// Put the key used to read the row together
- memset(key, (int)' ', 64); // QQ Empty db for now
- keylen= namelen;
+ keylen= name->m_db.length;
if (keylen > 64)
keylen= 64;
- memcpy(key+64, name, keylen);
+ memcpy(key, name->m_db.str, keylen);
+ memset(key+keylen, (int)' ', 64-keylen); // Pad with space
+ keylen= name->m_name.length;
+ if (keylen > 64)
+ keylen= 64;
+ memcpy(key+64, name->m_name.str, keylen);
memset(key+64+keylen, (int)' ', 64-keylen); // Pad with space
key[128]= type;
keylen= sizeof(key);
@@ -112,7 +117,7 @@ db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
static int
-db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
+db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
{
extern int yyparse(void *thd);
TABLE *table;
@@ -129,9 +134,10 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
String str(buff, sizeof(buff), &my_charset_bin);
ulong sql_mode;
DBUG_ENTER("db_find_routine");
- DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
- ret= db_find_routine_aux(thd, type, name, namelen, TL_READ, &table, &opened);
+ ret= db_find_routine_aux(thd, type, name, TL_READ, &table, &opened);
if (ret != SP_OK)
goto done;
@@ -211,6 +217,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
char *defstr;
ulong deflen;
LEX *oldlex= thd->lex;
+ char olddb[128];
+ char *olddbptr;
enum enum_sql_command oldcmd= thd->lex->sql_command;
ulong old_sql_mode= thd->variables.sql_mode;
ha_rows select_limit= thd->variables.select_limit;
@@ -219,17 +227,21 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
thd->variables.select_limit= HA_POS_ERROR;
if (!(defstr= create_string(thd, &deflen,
- type,
- name, namelen,
- params, strlen(params),
- returns, strlen(returns),
- body, strlen(body),
+ type,
+ name,
+ params, strlen(params),
+ returns, strlen(returns),
+ body, strlen(body),
&chistics)))
{
ret= SP_INTERNAL_ERROR;
goto done;
}
+ olddbptr= thd->db;
+ if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb), 1)))
+ goto done;
+
{
/* This is something of a kludge. We need to initialize some fields
* in thd->lex (the unit and master stuff), and the easiest way to
@@ -249,6 +261,9 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
LEX *newlex= thd->lex;
sp_head *sp= newlex->sphead;
+ if (olddbptr != thd->db &&
+ (ret= sp_change_db(thd, olddb, 1)))
+ goto done;
if (sp)
{
if (oldlex != newlex)
@@ -260,6 +275,9 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
}
else
{
+ if (olddbptr != thd->db &&
+ (ret= sp_change_db(thd, olddb, 1)))
+ goto done;
*sphp= thd->lex->sphead;
(*sphp)->set_info((char *)definer, (uint)strlen(definer),
created, modified, &chistics);
@@ -270,6 +288,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
}
done:
+
if (opened)
close_thread_tables(thd);
DBUG_RETURN(ret);
@@ -302,6 +321,8 @@ db_create_routine(THD *thd, int type, sp_head *sp)
ret= SP_GET_FIELD_FAILED;
goto done;
}
+ table->field[MYSQL_PROC_FIELD_DB]->
+ store(sp->m_db.str, sp->m_db.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_NAME]->
store(sp->m_name.str, sp->m_name.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_TYPE]->
@@ -342,15 +363,16 @@ done:
static int
-db_drop_routine(THD *thd, int type, char *name, uint namelen)
+db_drop_routine(THD *thd, int type, sp_name *name)
{
TABLE *table;
int ret;
bool opened;
DBUG_ENTER("db_drop_routine");
- DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
- ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened);
+ ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened);
if (ret == SP_OK)
{
if (table->file->delete_row(table->record[0]))
@@ -364,7 +386,7 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen)
static int
-db_update_routine(THD *thd, int type, char *name, uint namelen,
+db_update_routine(THD *thd, int type, sp_name *name,
char *newname, uint newnamelen,
st_sp_chistics *chistics)
{
@@ -372,9 +394,10 @@ db_update_routine(THD *thd, int type, char *name, uint namelen,
int ret;
bool opened;
DBUG_ENTER("db_update_routine");
- DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
- ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened);
+ ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened);
if (ret == SP_OK)
{
store_record(table,record[1]);
@@ -408,6 +431,7 @@ struct st_used_field
static struct st_used_field init_fields[]=
{
+ { "Db", NAME_LEN, MYSQL_TYPE_STRING, 0},
{ "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
{ "Type", 9, MYSQL_TYPE_STRING, 0},
{ "Definer", 77, MYSQL_TYPE_STRING, 0},
@@ -428,14 +452,20 @@ print_field_values(THD *thd, TABLE *table,
if (table->field[MYSQL_PROC_FIELD_TYPE]->val_int() == type)
{
- String *tmp_string= new String();
+ String db_string;
+ String name_string;
struct st_used_field *used_field= used_fields;
- get_field(&thd->mem_root, used_field->field, tmp_string);
- if (!wild || !wild[0] || !wild_compare(tmp_string->ptr(), wild, 0))
+ if (get_field(&thd->mem_root, used_field->field, &db_string))
+ db_string.set_ascii("", 0);
+ used_field+= 1;
+ get_field(&thd->mem_root, used_field->field, &name_string);
+
+ if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
{
protocol->prepare_for_resend();
- protocol->store(tmp_string);
+ protocol->store(&db_string);
+ protocol->store(&name_string);
for (used_field++;
used_field->field_name;
used_field++)
@@ -452,10 +482,10 @@ print_field_values(THD *thd, TABLE *table,
break;
default:
{
- String *tmp_string1= new String();
+ String tmp_string;
- get_field(&thd->mem_root, used_field->field, tmp_string1);
- protocol->store(tmp_string1);
+ get_field(&thd->mem_root, used_field->field, &tmp_string);
+ protocol->store(&tmp_string);
}
break;
}
@@ -563,16 +593,17 @@ done:
******************************************************************************/
sp_head *
-sp_find_procedure(THD *thd, LEX_STRING *name)
+sp_find_procedure(THD *thd, sp_name *name)
{
sp_head *sp;
DBUG_ENTER("sp_find_procedure");
- DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
+ DBUG_PRINT("enter", ("name: %*s.%*s",
+ name->m_db.length, name->m_db.str,
+ name->m_name.length, name->m_name.str));
- if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name->str, name->length)))
+ if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)))
{
- if (db_find_routine(thd, TYPE_ENUM_PROCEDURE,
- name->str, name->length, &sp) == SP_OK)
+ if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK)
sp_cache_insert(&thd->sp_proc_cache, sp);
}
@@ -593,40 +624,40 @@ sp_create_procedure(THD *thd, sp_head *sp)
int
-sp_drop_procedure(THD *thd, char *name, uint namelen)
+sp_drop_procedure(THD *thd, sp_name *name)
{
int ret;
DBUG_ENTER("sp_drop_procedure");
- DBUG_PRINT("enter", ("name: %*s", namelen, name));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
- sp_cache_remove(&thd->sp_proc_cache, name, namelen);
- ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen);
+ sp_cache_remove(&thd->sp_proc_cache, name);
+ ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name);
DBUG_RETURN(ret);
}
int
-sp_update_procedure(THD *thd, char *name, uint namelen,
+sp_update_procedure(THD *thd, sp_name *name,
char *newname, uint newnamelen,
st_sp_chistics *chistics)
{
int ret;
DBUG_ENTER("sp_update_procedure");
- DBUG_PRINT("enter", ("name: %*s", namelen, name));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
- sp_cache_remove(&thd->sp_proc_cache, name, namelen);
- ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen,
+ sp_cache_remove(&thd->sp_proc_cache, name);
+ ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name,
newname, newnamelen, chistics);
DBUG_RETURN(ret);
}
int
-sp_show_create_procedure(THD *thd, LEX_STRING *name)
+sp_show_create_procedure(THD *thd, sp_name *name)
{
sp_head *sp;
DBUG_ENTER("sp_show_create_procedure");
- DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
if ((sp= sp_find_procedure(thd, name)))
{
@@ -655,16 +686,15 @@ sp_show_status_procedure(THD *thd, const char *wild)
******************************************************************************/
sp_head *
-sp_find_function(THD *thd, LEX_STRING *name)
+sp_find_function(THD *thd, sp_name *name)
{
sp_head *sp;
DBUG_ENTER("sp_find_function");
- DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
- if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name->str, name->length)))
+ if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)))
{
- if (db_find_routine(thd, TYPE_ENUM_FUNCTION,
- name->str, name->length, &sp) != SP_OK)
+ if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) != SP_OK)
sp= NULL;
else
sp_cache_insert(&thd->sp_func_cache, sp);
@@ -686,40 +716,40 @@ sp_create_function(THD *thd, sp_head *sp)
int
-sp_drop_function(THD *thd, char *name, uint namelen)
+sp_drop_function(THD *thd, sp_name *name)
{
int ret;
DBUG_ENTER("sp_drop_function");
- DBUG_PRINT("enter", ("name: %*s", namelen, name));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
- sp_cache_remove(&thd->sp_func_cache, name, namelen);
- ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen);
+ sp_cache_remove(&thd->sp_func_cache, name);
+ ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name);
DBUG_RETURN(ret);
}
int
-sp_update_function(THD *thd, char *name, uint namelen,
+sp_update_function(THD *thd, sp_name *name,
char *newname, uint newnamelen,
st_sp_chistics *chistics)
{
int ret;
DBUG_ENTER("sp_update_procedure");
- DBUG_PRINT("enter", ("name: %*s", namelen, name));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
- sp_cache_remove(&thd->sp_func_cache, name, namelen);
- ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen,
+ sp_cache_remove(&thd->sp_func_cache, name);
+ ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name,
newname, newnamelen, chistics);
DBUG_RETURN(ret);
}
int
-sp_show_create_function(THD *thd, LEX_STRING *name)
+sp_show_create_function(THD *thd, sp_name *name)
{
sp_head *sp;
DBUG_ENTER("sp_show_create_function");
- DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
if ((sp= sp_find_function(thd, name)))
{
@@ -741,18 +771,17 @@ sp_show_status_function(THD *thd, const char *wild)
}
-// QQ Temporary until the function call detection in sql_lex has been reworked.
bool
-sp_function_exists(THD *thd, LEX_STRING *name)
+sp_function_exists(THD *thd, sp_name *name)
{
TABLE *table;
bool ret= FALSE;
bool opened= FALSE;
DBUG_ENTER("sp_function_exists");
- if (sp_cache_lookup(&thd->sp_func_cache, name->str, name->length) ||
+ if (sp_cache_lookup(&thd->sp_func_cache, name) ||
db_find_routine_aux(thd, TYPE_ENUM_FUNCTION,
- name->str, name->length, TL_READ,
+ name, TL_READ,
&table, &opened) == SP_OK)
ret= TRUE;
if (opened)
@@ -771,13 +800,14 @@ sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first)
void
-sp_add_fun_to_lex(LEX *lex, LEX_STRING fun)
+sp_add_fun_to_lex(LEX *lex, sp_name *fun)
{
- if (! hash_search(&lex->spfuns, (byte *)fun.str, fun.length))
+ if (! hash_search(&lex->spfuns,
+ (byte *)fun->m_qname.str, fun->m_qname.length))
{
LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING));
- ls->str= sql_strmake(fun.str, fun.length);
- ls->length= fun.length;
+ ls->str= sql_strmake(fun->m_qname.str, fun->m_qname.length);
+ ls->length= fun->m_qname.length;
my_hash_insert(&lex->spfuns, (byte *)ls);
}
@@ -806,15 +836,25 @@ sp_cache_functions(THD *thd, LEX *lex)
for (uint i=0 ; i < h->records ; i++)
{
LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
+ sp_name name(*ls);
- if (! sp_cache_lookup(&thd->sp_func_cache, ls->str, ls->length))
+ name.m_qname= *ls;
+ if (! sp_cache_lookup(&thd->sp_func_cache, &name))
{
sp_head *sp;
LEX *oldlex= thd->lex;
LEX *newlex= new st_lex;
thd->lex= newlex;
- if (db_find_routine(thd, TYPE_ENUM_FUNCTION, ls->str, ls->length, &sp) == SP_OK)
+ name.m_name.str= strchr(name.m_qname.str, '.');
+ name.m_db.length= name.m_name.str - name.m_qname.str;
+ name.m_db.str= strmake_root(&thd->mem_root,
+ name.m_qname.str, name.m_db.length);
+ name.m_name.str+= 1;
+ name.m_name.length= name.m_qname.length - name.m_db.length - 1;
+
+ if (db_find_routine(thd, TYPE_ENUM_FUNCTION, &name, &sp)
+ == SP_OK)
{
ret= sp_cache_functions(thd, newlex);
delete newlex;
@@ -840,7 +880,7 @@ sp_cache_functions(THD *thd, LEX *lex)
static char *
create_string(THD *thd, ulong *lenp,
int type,
- char *name, ulong namelen,
+ sp_name *name,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
@@ -849,12 +889,15 @@ create_string(THD *thd, ulong *lenp,
char *buf, *ptr;
ulong buflen;
- buflen= 100 + namelen + paramslen + returnslen + bodylen + chistics->comment.length;
+ buflen= 100 + name->m_qname.length + paramslen + returnslen + bodylen +
+ chistics->comment.length;
if (!(buf= thd->alloc(buflen)))
return 0;
- ptr= strxmov(buf, "CREATE ", (type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
- " `", name, "`(", params, ")", NullS);
+ ptr= strxmov(buf, "CREATE ",
+ (type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
+ " `", name->m_db.str, "`.`", name->m_name.str, "`(", params, ")",
+ NullS);
if (type == TYPE_ENUM_FUNCTION)
ptr= strxmov(ptr, " RETURNS ", returns, NullS);
@@ -873,3 +916,63 @@ create_string(THD *thd, ulong *lenp,
*lenp= (ptr-buf);
return buf;
}
+
+
+//
+// Utilities...
+//
+
+int
+sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
+ bool no_access_check)
+{
+ bool changeit;
+ DBUG_ENTER("sp_use_new_db");
+ DBUG_PRINT("enter", ("newdb: %s", newdb));
+
+ if (thd->db && thd->db[0])
+ {
+ if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0)
+ changeit= 0;
+ else
+ {
+ changeit= 1;
+ strnmov(olddb, thd->db, olddblen);
+ }
+ }
+ else
+ { // thd->db empty
+ if (newdb[0])
+ changeit= 1;
+ else
+ changeit= 0;
+ olddb[0] = '\0';
+ }
+ if (!changeit)
+ {
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ int ret= sp_change_db(thd, newdb, no_access_check);
+
+ DBUG_RETURN(ret);
+ }
+}
+
+int
+sp_change_db(THD *thd, char *db, bool no_access_check)
+{
+ int ret;
+ ulong dbaccess= thd->db_access; /* mysql_change_db() changes this */
+ my_bool nsok= thd->net.no_send_ok; /* mysql_change_db() does send_ok() */
+ thd->net.no_send_ok= TRUE;
+ DBUG_ENTER("sp_change_db");
+ DBUG_PRINT("enter", ("db: %s, no_access_check: %d", db, no_access_check));
+
+ ret= mysql_change_db(thd, db, 1, no_access_check);
+
+ thd->net.no_send_ok= nsok;
+ thd->db_access= dbaccess;
+ DBUG_RETURN(ret);
+}
diff --git a/sql/sp.h b/sql/sp.h
index b9f29138de2..ffe3f31c157 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -29,58 +29,72 @@
#define SP_INTERNAL_ERROR -7
sp_head *
-sp_find_procedure(THD *thd, LEX_STRING *name);
+sp_find_procedure(THD *thd, sp_name *name);
int
sp_create_procedure(THD *thd, sp_head *sp);
int
-sp_drop_procedure(THD *thd, char *name, uint namelen);
+sp_drop_procedure(THD *thd, sp_name *name);
int
-sp_update_procedure(THD *thd, char *name, uint namelen,
+sp_update_procedure(THD *thd, sp_name *name,
char *newname, uint newnamelen,
st_sp_chistics *chistics);
int
-sp_show_create_procedure(THD *thd, LEX_STRING *name);
+sp_show_create_procedure(THD *thd, sp_name *name);
int
sp_show_status_procedure(THD *thd, const char *wild);
sp_head *
-sp_find_function(THD *thd, LEX_STRING *name);
+sp_find_function(THD *thd, sp_name *name);
int
sp_create_function(THD *thd, sp_head *sp);
int
-sp_drop_function(THD *thd, char *name, uint namelen);
+sp_drop_function(THD *thd, sp_name *name);
int
-sp_update_function(THD *thd, char *name, uint namelen,
+sp_update_function(THD *thd, sp_name *name,
char *newname, uint newnamelen,
st_sp_chistics *chistics);
int
-sp_show_create_function(THD *thd, LEX_STRING *name);
+sp_show_create_function(THD *thd, sp_name *name);
int
sp_show_status_function(THD *thd, const char *wild);
-// QQ Temporary until the function call detection in sql_lex has been reworked.
bool
-sp_function_exists(THD *thd, LEX_STRING *name);
+sp_function_exists(THD *thd, sp_name *name);
// This is needed since we have to read the functions before we
// do anything else.
void
-sp_add_fun_to_lex(LEX *lex, LEX_STRING fun);
+sp_add_fun_to_lex(LEX *lex, sp_name *fun);
void
sp_merge_funs(LEX *dst, LEX *src);
int
sp_cache_functions(THD *thd, LEX *lex);
+
+//
+// Utilities...
+//
+
+// Do a "use newdb". The current db is stored at olddb.
+// If newdb is the same as the current one, nothing is changed.
+int
+sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddbmax,
+ bool no_access_check);
+
+// Like mysql_change_db() but handles empty db name and the send_ok() problem.
+int
+sp_change_db(THD *thd, char *db, bool no_access_check);
+
#endif /* _SP_H_ */
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index 657a96ec33d..e13fb2695e7 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -71,7 +71,7 @@ sp_cache_insert(sp_cache **cp, sp_head *sp)
}
sp_head *
-sp_cache_lookup(sp_cache **cp, char *name, uint namelen)
+sp_cache_lookup(sp_cache **cp, sp_name *name)
{
ulong v;
sp_cache *c= *cp;
@@ -89,11 +89,11 @@ sp_cache_lookup(sp_cache **cp, char *name, uint namelen)
c->version= v;
return NULL;
}
- return c->lookup(name, namelen);
+ return c->lookup(name->m_qname.str, name->m_qname.length);
}
bool
-sp_cache_remove(sp_cache **cp, char *name, uint namelen)
+sp_cache_remove(sp_cache **cp, sp_name *name)
{
sp_cache *c= *cp;
bool found= FALSE;
@@ -109,7 +109,7 @@ sp_cache_remove(sp_cache **cp, char *name, uint namelen)
if (c->version < v)
c->remove_all();
else
- found= c->remove(name, namelen);
+ found= c->remove(name->m_qname.str, name->m_qname.length);
c->version= v+1;
}
return found;
@@ -120,7 +120,10 @@ static byte *
hash_get_key_for_sp_head(const byte *ptr, uint *plen,
my_bool first)
{
- return (byte*) ((sp_head*)ptr)->name(plen);
+ sp_head *sp= (sp_head *)ptr;
+
+ *plen= sp->m_qname.length;
+ return (byte*) sp->m_qname.str;
}
static void
diff --git a/sql/sp_cache.h b/sql/sp_cache.h
index da25227303b..253e9b11588 100644
--- a/sql/sp_cache.h
+++ b/sql/sp_cache.h
@@ -35,10 +35,10 @@ void sp_cache_clear(sp_cache **cp);
void sp_cache_insert(sp_cache **cp, sp_head *sp);
/* Lookup an SP in cache */
-sp_head *sp_cache_lookup(sp_cache **cp, char *name, uint namelen);
+sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
/* Remove an SP from cache. Returns true if something was removed */
-bool sp_cache_remove(sp_cache **cp, char *name, uint namelen);
+bool sp_cache_remove(sp_cache **cp, sp_name *name);
/*
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index bfd7ad259f6..ebf74e25bbe 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -130,6 +130,52 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
DBUG_RETURN(it);
}
+
+/*
+ *
+ * sp_name
+ *
+ */
+
+void
+sp_name::init_qname(THD *thd)
+{
+ m_qname.length= m_db.length+m_name.length+1;
+ m_qname.str= alloc_root(&thd->mem_root, m_qname.length+1);
+ sprintf(m_qname.str, "%*s.%*s",
+ m_db.length, (m_db.length ? m_db.str : ""),
+ m_name.length, m_name.str);
+}
+
+sp_name *
+sp_name_current_db_new(THD *thd, LEX_STRING name)
+{
+ sp_name *qname;
+
+ if (! thd->db)
+ qname= new sp_name(name);
+ else
+ {
+ LEX_STRING db;
+
+ db.length= strlen(thd->db);
+ db.str= thd->strmake(thd->db, db.length);
+ qname= new sp_name(db, name);
+ }
+ qname->init_qname(thd);
+ return qname;
+}
+
+
+/* ------------------------------------------------------------------ */
+
+
+/*
+ *
+ * sp_head
+ *
+ */
+
void *
sp_head::operator new(size_t size)
{
@@ -178,22 +224,42 @@ sp_head::init(LEX *lex)
lex->spcont= m_pcont= new sp_pcontext();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
- m_name.str= m_params.str= m_retstr.str= m_body.str= m_defstr.str= 0;
- m_name.length= m_params.length= m_retstr.length= m_body.length=
- m_defstr.length= 0;
+ m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
+ m_body.str= m_defstr.str= 0;
+ m_qname.length= m_db.length= m_name.length= m_params.length=
+ m_retstr.length= m_body.length= m_defstr.length= 0;
DBUG_VOID_RETURN;
}
void
-sp_head::init_strings(THD *thd, LEX *lex, LEX_STRING *name)
+sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
{
DBUG_ENTER("sp_head::init_strings");
/* During parsing, we must use thd->mem_root */
MEM_ROOT *root= &thd->mem_root;
- DBUG_PRINT("info", ("name: %*s", name->length, name->str));
- m_name.length= name->length;
- m_name.str= strmake_root(root, name->str, name->length);
+ DBUG_PRINT("info", ("name: %*.s%*s",
+ name->m_db.length, name->m_db.str,
+ name->m_name.length, name->m_name.str));
+ /* We have to copy strings to get them into the right memroot */
+ if (name->m_db.length == 0)
+ {
+ m_db.length= (thd->db ? strlen(thd->db) : 0);
+ m_db.str= strmake_root(root, (thd->db ? thd->db : ""), m_db.length);
+ }
+ else
+ {
+ m_db.length= name->m_db.length;
+ m_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
+ }
+ m_name.length= name->m_name.length;
+ m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
+
+ if (name->m_qname.length == 0)
+ name->init_qname(thd);
+ m_qname.length= name->m_qname.length;
+ m_qname.str= strmake_root(root, name->m_qname.str, m_qname.length);
+
m_params.length= m_param_end- m_param_begin;
m_params.str= strmake_root(root,
(char *)m_param_begin, m_params.length);
@@ -271,30 +337,22 @@ int
sp_head::execute(THD *thd)
{
DBUG_ENTER("sp_head::execute");
- char olddbname[128];
- char *olddbptr= thd->db;
+ char olddb[128];
+ char *olddbptr;
sp_rcontext *ctx= thd->spcont;
int ret= 0;
uint ip= 0;
#ifndef EMBEDDED_LIBRARY
- if (check_stack_overrun(thd, olddbptr))
+ if (check_stack_overrun(thd, olddb))
{
DBUG_RETURN(-1);
}
#endif
- if (olddbptr)
- {
- uint i= 0;
- char *p= olddbptr;
-
- /* Fast inline strncpy without padding... */
- while (*p && i < sizeof(olddbname))
- olddbname[i++]= *p++;
- if (i == sizeof(olddbname))
- i-= 1; // QQ Error or warning for truncate?
- olddbname[i]= '\0';
- }
+
+ olddbptr= thd->db;
+ if ((ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0)))
+ goto done;
if (ctx)
ctx->clear_handler();
@@ -333,18 +391,17 @@ sp_head::execute(THD *thd)
}
} while (ret == 0 && !thd->killed && !thd->query_error);
+ done:
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
ret, thd->killed, thd->query_error));
if (thd->killed || thd->query_error)
ret= -1;
/* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */
- if (olddbptr && olddbptr != thd->db)
+ if (olddbptr != thd->db)
{
- /* QQ Maybe we should issue some special error message or warning here,
- if this fails?? */
if (! thd->killed)
- ret= mysql_change_db(thd, olddbname);
+ ret= sp_change_db(thd, olddb, 0);
}
DBUG_RETURN(ret);
}
@@ -711,6 +768,32 @@ sp_head::set_info(char *definer, uint definerlen,
m_chistics->comment.length);
}
+void
+sp_head::reset_thd_mem_root(THD *thd)
+{
+ m_thd_root= thd->mem_root;
+ thd->mem_root= m_mem_root;
+ m_free_list= thd->free_list; // Keep the old list
+ thd->free_list= NULL; // Start a new one
+ /* Copy the db, since substatements will point to it */
+ m_thd_db= thd->db;
+ thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length);
+ m_thd= thd;
+}
+
+void
+sp_head::restore_thd_mem_root(THD *thd)
+{
+ Item *flist= m_free_list; // The old list
+ m_free_list= thd->free_list; // Get the new one
+ thd->free_list= flist; // Restore the old one
+ thd->db= m_thd_db; // Restore the original db pointer
+ m_mem_root= thd->mem_root;
+ thd->mem_root= m_thd_root;
+ m_thd= NULL;
+}
+
+
int
sp_head::show_create_procedure(THD *thd)
{
@@ -1092,10 +1175,13 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
DBUG_RETURN(res);
}
+/* ------------------------------------------------------------------ */
+
//
// Security context swapping
//
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
void
sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
@@ -1108,8 +1194,6 @@ sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
{
ctxp->master_access= thd->master_access;
ctxp->db_access= thd->db_access;
- ctxp->db= thd->db;
- ctxp->db_length= thd->db_length;
ctxp->priv_user= thd->priv_user;
strncpy(ctxp->priv_host, thd->priv_host, sizeof(ctxp->priv_host));
ctxp->user= thd->user;
@@ -1125,8 +1209,6 @@ sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
ctxp->changed= FALSE;
thd->master_access= ctxp->master_access;
thd->db_access= ctxp->db_access;
- thd->db= ctxp->db;
- thd->db_length= ctxp->db_length;
thd->priv_user= ctxp->priv_user;
strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
}
@@ -1146,8 +1228,6 @@ sp_restore_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
ctxp->changed= FALSE;
thd->master_access= ctxp->master_access;
thd->db_access= ctxp->db_access;
- thd->db= ctxp->db;
- thd->db_length= ctxp->db_length;
thd->priv_user= ctxp->priv_user;
strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index b2dee5204bb..791c6697693 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -37,6 +37,39 @@ class sp_instr;
struct sp_cond_type;
struct sp_pvar;
+class sp_name : public Sql_alloc
+{
+public:
+
+ LEX_STRING m_db;
+ LEX_STRING m_name;
+ LEX_STRING m_qname;
+
+ sp_name(LEX_STRING name)
+ : m_name(name)
+ {
+ m_db.str= m_qname.str= 0;
+ m_db.length= m_qname.length= 0;
+ }
+
+ sp_name(LEX_STRING db, LEX_STRING name)
+ : m_db(db), m_name(name)
+ {
+ m_qname.str= 0;
+ m_qname.length= 0;
+ }
+
+ // Init. the qualified name from the db and name.
+ void init_qname(THD *thd); // thd for memroot allocation
+
+ ~sp_name()
+ {}
+};
+
+sp_name *
+sp_name_current_db_new(THD *thd, LEX_STRING name);
+
+
class sp_head : public Sql_alloc
{
sp_head(const sp_head &); /* Prevent use of these */
@@ -56,6 +89,8 @@ public:
List<char *> m_calls; // Called procedures.
List<char *> m_tables; // Used tables.
#endif
+ LEX_STRING m_qname; // db.name
+ LEX_STRING m_db;
LEX_STRING m_name;
LEX_STRING m_params;
LEX_STRING m_retstr; // For FUNCTIONs only
@@ -83,7 +118,7 @@ public:
// Initialize strings after parsing header
void
- init_strings(THD *thd, LEX *lex, LEX_STRING *name);
+ init_strings(THD *thd, LEX *lex, sp_name *name);
int
create(THD *thd);
@@ -163,24 +198,10 @@ public:
longlong created, longlong modified,
st_sp_chistics *chistics);
- inline void reset_thd_mem_root(THD *thd)
- {
- m_thd_root= thd->mem_root;
- thd->mem_root= m_mem_root;
- m_free_list= thd->free_list; // Keep the old list
- thd->free_list= NULL; // Start a new one
- m_thd= thd;
- }
+ void reset_thd_mem_root(THD *thd);
+
+ void restore_thd_mem_root(THD *thd);
- inline void restore_thd_mem_root(THD *thd)
- {
- Item *flist= m_free_list; // The old list
- m_free_list= thd->free_list; // Get the new one
- thd->free_list= flist; // Restore the old one
- m_mem_root= thd->mem_root;
- thd->mem_root= m_thd_root;
- m_thd= NULL;
- }
private:
@@ -188,6 +209,7 @@ private:
MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
Item *m_free_list; // Where the items go
THD *m_thd; // Set if we have reset mem_root
+ char *m_thd_db; // Original thd->db pointer
sp_pcontext *m_pcont; // Parse context
List<LEX> m_lex; // Temp. store for the other lex
@@ -640,8 +662,6 @@ struct st_sp_security_context
bool changed;
uint master_access;
uint db_access;
- char *db;
- uint db_length;
char *priv_user;
char priv_host[MAX_HOSTNAME];
char *user;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index bc6b30040d6..3ea6821ef80 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -595,7 +595,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
1 error
*/
-bool mysql_change_db(THD *thd, const char *name)
+bool mysql_change_db(THD *thd, const char *name,
+ bool empty_is_ok, bool no_access_check)
{
int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME));
@@ -604,62 +605,76 @@ bool mysql_change_db(THD *thd, const char *name)
HA_CREATE_INFO create;
DBUG_ENTER("mysql_change_db");
- if (!dbname || !(db_length=strip_sp(dbname)))
+ if ((!dbname || !(db_length=strip_sp(dbname))) && !empty_is_ok)
{
x_free(dbname); /* purecov: inspected */
send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
- if ((db_length > NAME_LEN) || check_db_name(dbname))
+ if (!empty_is_ok || (dbname && db_length))
{
- net_printf(thd, ER_WRONG_DB_NAME, dbname);
- x_free(dbname);
- DBUG_RETURN(1);
+ if ((db_length > NAME_LEN) || check_db_name(dbname))
+ {
+ net_printf(thd, ER_WRONG_DB_NAME, dbname);
+ x_free(dbname);
+ DBUG_RETURN(1);
+ }
}
DBUG_PRINT("info",("Use database: %s", dbname));
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (test_all_bits(thd->master_access,DB_ACLS))
- db_access=DB_ACLS;
- else
- db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
- thd->master_access);
- if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
+ if (!empty_is_ok || (dbname && db_length))
{
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- dbname);
- mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
- thd->priv_user,
- thd->priv_host,
- dbname);
- my_free(dbname,MYF(0));
- DBUG_RETURN(1);
- }
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (! no_access_check)
+ {
+ if (test_all_bits(thd->master_access,DB_ACLS))
+ db_access=DB_ACLS;
+ else
+ db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
+ thd->master_access);
+ if (!(db_access & DB_ACLS) &&
+ (!grant_option || check_grant_db(thd,dbname)))
+ {
+ net_printf(thd,ER_DBACCESS_DENIED_ERROR,
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
+ mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
+ my_free(dbname,MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
#endif
- (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
- length=unpack_dirname(path,path); // Convert if not unix
- if (length && path[length-1] == FN_LIBCHAR)
- path[length-1]=0; // remove ending '\'
- if (access(path,F_OK))
- {
- net_printf(thd,ER_BAD_DB_ERROR,dbname);
- my_free(dbname,MYF(0));
- DBUG_RETURN(1);
+ (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
+ length=unpack_dirname(path,path); // Convert if not unix
+ if (length && path[length-1] == FN_LIBCHAR)
+ path[length-1]=0; // remove ending '\'
+ if (access(path,F_OK))
+ {
+ net_printf(thd,ER_BAD_DB_ERROR,dbname);
+ my_free(dbname,MYF(0));
+ DBUG_RETURN(1);
+ }
}
send_ok(thd);
x_free(thd->db);
thd->db=dbname; // THD::~THD will free this
thd->db_length=db_length;
+ if (!empty_is_ok || (dbname && db_length))
+ {
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- thd->db_access=db_access;
+ if (! no_access_check)
+ thd->db_access=db_access;
#endif
- strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
- load_db_opt(thd, path, &create);
- thd->db_charset= create.default_table_charset ?
- create.default_table_charset :
- thd->variables.collation_server;
- thd->variables.collation_database= thd->db_charset;
+ strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
+ thd->db_charset= create.default_table_charset ?
+ create.default_table_charset :
+ thd->variables.collation_server;
+ thd->variables.collation_database= thd->db_charset;
+ }
DBUG_RETURN(0);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index f37f133f105..6f6a8925412 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -168,38 +168,6 @@ static int find_keyword(LEX *lex, uint len, bool function)
lex->yylval->symbol.length=len;
return symbol->tok;
}
-
- LEX_STRING ls;
- ls.str = (char *)tok; ls.length= len;
- if (function && sp_function_exists(current_thd, &ls)) // QQ temp fix
- {
- lex->safe_to_cache_query= 0;
- lex->yylval->lex_str.str= lex->thd->strmake((char*)lex->tok_start, len);
- lex->yylval->lex_str.length= len;
- return SP_FUNC;
- }
-
-#ifdef HAVE_DLOPEN
- udf_func *udf;
- if (function && using_udf_functions && (udf=find_udf((char*) tok, len)))
- {
- lex->safe_to_cache_query=0;
- lex->yylval->udf=udf;
- switch (udf->returns) {
- case STRING_RESULT:
- return (udf->type == UDFTYPE_FUNCTION) ? UDF_CHAR_FUNC : UDA_CHAR_SUM;
- case REAL_RESULT:
- return (udf->type == UDFTYPE_FUNCTION) ? UDF_FLOAT_FUNC : UDA_FLOAT_SUM;
- case INT_RESULT:
- return (udf->type == UDFTYPE_FUNCTION) ? UDF_INT_FUNC : UDA_INT_SUM;
- case ROW_RESULT:
- default:
- // This case should never be choosen
- DBUG_ASSERT(0);
- return 0;
- }
- }
-#endif
return 0;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 50b8f322731..221f864db81 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -22,6 +22,7 @@ class Table_ident;
class sql_exchange;
class LEX_COLUMN;
class sp_head;
+class sp_name;
class sp_instr;
class sp_pcontext;
@@ -604,6 +605,7 @@ typedef struct st_lex
bool derived_tables;
bool safe_to_cache_query;
sp_head *sphead;
+ sp_name *spname;
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
sp_pcontext *spcont;
HASH spfuns; /* Called functions */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d332b6985cb..273e994189f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3105,9 +3105,9 @@ mysql_execute_command(THD *thd)
if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
break;
#ifdef HAVE_DLOPEN
- if ((sph= sp_find_function(thd, &lex->udf.name)))
+ if ((sph= sp_find_function(thd, lex->spname)))
{
- net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str);
+ net_printf(thd, ER_UDF_EXISTS, lex->spname->m_name.str);
goto error;
}
if (!(res = mysql_create_function(thd,&lex->udf)))
@@ -3445,9 +3445,10 @@ mysql_execute_command(THD *thd)
{
sp_head *sp;
- if (!(sp= sp_find_procedure(thd, &lex->udf.name)))
+ if (!(sp= sp_find_procedure(thd, lex->spname)))
{
- net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE", lex->udf.name);
+ net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE",
+ lex->spname->m_name.str);
goto error;
}
else
@@ -3525,10 +3526,10 @@ mysql_execute_command(THD *thd)
goto error;
}
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
- res= sp_update_procedure(thd, lex->udf.name.str, lex->udf.name.length,
+ res= sp_update_procedure(thd, lex->spname,
lex->name, newname_len, &lex->sp_chistics);
else
- res= sp_update_function(thd, lex->udf.name.str, lex->udf.name.length,
+ res= sp_update_function(thd, lex->spname,
lex->name, newname_len, &lex->sp_chistics);
switch (res)
{
@@ -3536,10 +3537,12 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
- net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),lex->udf.name);
+ net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
+ lex->spname->m_name.str);
goto error;
default:
- net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex),lex->udf.name);
+ net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex),
+ lex->spname->m_name.str);
goto error;
}
break;
@@ -3548,19 +3551,20 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_FUNCTION:
{
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- res= sp_drop_procedure(thd, lex->udf.name.str, lex->udf.name.length);
+ res= sp_drop_procedure(thd, lex->spname);
else
{
- res= sp_drop_function(thd, lex->udf.name.str, lex->udf.name.length);
+ res= sp_drop_function(thd, lex->spname);
#ifdef HAVE_DLOPEN
if (res == SP_KEY_NOT_FOUND)
{
- udf_func *udf = find_udf(lex->udf.name.str, lex->udf.name.length);
+ udf_func *udf = find_udf(lex->spname->m_name.str,
+ lex->spname->m_name.length);
if (udf)
{
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0))
goto error;
- if (!(res = mysql_drop_function(thd,&lex->udf.name)))
+ if (!(res = mysql_drop_function(thd,&lex->spname->m_name)))
{
send_ok(thd);
break;
@@ -3579,17 +3583,17 @@ mysql_execute_command(THD *thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
- SP_COM_STRING(lex), lex->udf.name.str);
+ SP_COM_STRING(lex), lex->spname->m_name.str);
res= 0;
send_ok(thd);
break;
}
net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
- lex->udf.name.str);
+ lex->spname->m_name.str);
goto error;
default:
net_printf(thd, ER_SP_DROP_FAILED, SP_COM_STRING(lex),
- lex->udf.name.str);
+ lex->spname->m_name.str);
goto error;
}
break;
@@ -3597,16 +3601,16 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_CREATE_PROC:
{
res= -1;
- if (lex->udf.name.length > NAME_LEN)
+ if (lex->spname->m_name.length > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT, lex->udf.name.str);
+ net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str);
goto error;
}
- res= sp_show_create_procedure(thd, &lex->udf.name);
+ res= sp_show_create_procedure(thd, lex->spname);
if (res != SP_OK)
{ /* We don't distinguish between errors for now */
net_printf(thd, ER_SP_DOES_NOT_EXIST,
- SP_COM_STRING(lex), lex->udf.name.str);
+ SP_COM_STRING(lex), lex->spname->m_name.str);
res= 0;
goto error;
}
@@ -3614,16 +3618,16 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_CREATE_FUNC:
{
- if (lex->udf.name.length > NAME_LEN)
+ if (lex->spname->m_name.length > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT, lex->udf.name.str);
+ net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str);
goto error;
}
- res= sp_show_create_function(thd, &lex->udf.name);
+ res= sp_show_create_function(thd, lex->spname);
if (res != SP_OK)
{ /* We don't distinguish between errors for now */
net_printf(thd, ER_SP_DOES_NOT_EXIST,
- SP_COM_STRING(lex), lex->udf.name.str);
+ SP_COM_STRING(lex), lex->spname->m_name.str);
res= 0;
goto error;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 4c217b325ec..50f475eb68c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -92,6 +92,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
chooser_compare_func_creator boolfunc2creator;
struct sp_cond_type *spcondtype;
struct { int vars, conds, hndlrs, curs; } spblock;
+ sp_name *spname;
struct st_lex *lex;
}
@@ -568,17 +569,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SECOND_SYM
%token SECOND_MICROSECOND_SYM
%token SHARE_SYM
-%token SP_FUNC
%token SUBDATE_SYM
%token SUBSTRING
%token SUBSTRING_INDEX
%token TRIM
-%token UDA_CHAR_SUM
-%token UDA_FLOAT_SUM
-%token UDA_INT_SUM
-%token UDF_CHAR_FUNC
-%token UDF_FLOAT_FUNC
-%token UDF_INT_FUNC
%token UNIQUE_USERS
%token UNIX_TIMESTAMP
%token USER
@@ -640,7 +634,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
- SP_FUNC ident_or_spfunc sp_opt_label
+ sp_opt_label
%type <lex_str_ptr>
opt_table_alias
@@ -683,7 +677,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
simple_ident_nospvar simple_ident_q
%type <item_list>
- expr_list sp_expr_list udf_expr_list udf_expr_list2 when_list
+ expr_list udf_expr_list udf_expr_list2 when_list
ident_list ident_list_arg
%type <key_type>
@@ -701,10 +695,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <table_list>
join_table_list join_table
-%type <udf>
- UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC
- UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM
-
%type <date_time_type> date_time_type;
%type <interval> interval
@@ -782,6 +772,7 @@ END_OF_INPUT
%type <spcondtype> sp_cond sp_hcond
%type <spblock> sp_decls sp_decl
%type <lex> sp_cursor_stmt
+%type <spname> sp_name
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
@@ -1030,15 +1021,15 @@ create:
lex->name=$4.str;
lex->create_info.options=$3;
}
- | CREATE udf_func_type FUNCTION_SYM ident_or_spfunc
+ | CREATE udf_func_type FUNCTION_SYM sp_name
{
LEX *lex=Lex;
- lex->udf.name = $4;
+ lex->spname= $4;
lex->udf.type= $2;
}
create_function_tail
{}
- | CREATE PROCEDURE ident
+ | CREATE PROCEDURE sp_name
{
LEX *lex= Lex;
sp_head *sp;
@@ -1089,7 +1080,7 @@ create:
{
LEX *lex= Lex;
- lex->sphead->init_strings(YYTHD, lex, &$3);
+ lex->sphead->init_strings(YYTHD, lex, $3);
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
/* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq)
@@ -1098,9 +1089,16 @@ create:
}
;
-ident_or_spfunc:
- IDENT_sys { $$= $1; }
- | SP_FUNC { $$= $1; }
+sp_name:
+ IDENT_sys '.' IDENT_sys
+ {
+ $$= new sp_name($1, $3);
+ $$->init_qname(YYTHD);
+ }
+ | IDENT_sys
+ {
+ $$= sp_name_current_db_new(YYTHD, $1);
+ }
;
create_function_tail:
@@ -1108,6 +1106,7 @@ create_function_tail:
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_CREATE_FUNCTION;
+ lex->udf.name = lex->spname->m_name;
lex->udf.returns=(Item_result) $2;
lex->udf.dl=$4.str;
}
@@ -1169,7 +1168,7 @@ create_function_tail:
sp_head *sp= lex->sphead;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
- sp->init_strings(YYTHD, lex, &lex->udf.name);
+ sp->init_strings(YYTHD, lex, lex->spname);
/* Restore flag if it was cleared above */
if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
@@ -1219,12 +1218,12 @@ sp_suid:
;
call:
- CALL_SYM ident_or_spfunc
+ CALL_SYM sp_name
{
LEX *lex = Lex;
lex->sql_command= SQLCOM_CALL;
- lex->udf.name= $2;
+ lex->spname= $2;
lex->value_list.empty();
}
'(' sp_cparam_list ')' {}
@@ -1584,6 +1583,11 @@ sp_proc_stmt:
/* We maybe have one or more SELECT without INTO */
lex->sphead->m_multi_results= TRUE;
}
+ if (lex->sql_command == SQLCOM_CHANGE_DB)
+ { /* "USE db" doesn't work in a procedure */
+ send_error(YYTHD, ER_SP_NO_USE);
+ YYABORT;
+ }
/* Don't add an instruction for empty SET statements.
** (This happens if the SET only contained local variables,
** which get their set instructions generated separately.)
@@ -2739,7 +2743,7 @@ alter:
lex->sql_command=SQLCOM_ALTER_DB;
lex->name=$3.str;
}
- | ALTER PROCEDURE ident
+ | ALTER PROCEDURE sp_name
{
LEX *lex= Lex;
@@ -2752,9 +2756,9 @@ alter:
LEX *lex=Lex;
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
- lex->udf.name= $3;
+ lex->spname= $3;
}
- | ALTER FUNCTION_SYM ident
+ | ALTER FUNCTION_SYM sp_name
{
LEX *lex= Lex;
@@ -2767,7 +2771,7 @@ alter:
LEX *lex=Lex;
lex->sql_command= SQLCOM_ALTER_FUNCTION;
- lex->udf.name= $3;
+ lex->spname= $3;
}
;
@@ -3919,55 +3923,82 @@ simple_expr:
{ $$= new Item_func_round($3,$5,1); }
| TRUE_SYM
{ $$= new Item_int((char*) "TRUE",1,1); }
- | SP_FUNC '(' sp_expr_list ')'
- {
- sp_add_fun_to_lex(Lex, $1);
- if ($3)
- $$= new Item_func_sp($1, *$3);
- else
- $$= new Item_func_sp($1);
- }
- | UDA_CHAR_SUM '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_sum_udf_str($1, *$3);
- else
- $$ = new Item_sum_udf_str($1);
- }
- | UDA_FLOAT_SUM '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_sum_udf_float($1, *$3);
- else
- $$ = new Item_sum_udf_float($1);
- }
- | UDA_INT_SUM '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_sum_udf_int($1, *$3);
- else
- $$ = new Item_sum_udf_int($1);
- }
- | UDF_CHAR_FUNC '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_func_udf_str($1, *$3);
- else
- $$ = new Item_func_udf_str($1);
- }
- | UDF_FLOAT_FUNC '(' udf_expr_list ')'
+ | IDENT_sys '(' udf_expr_list ')'
{
- if ($3 != NULL)
- $$ = new Item_func_udf_float($1, *$3);
- else
- $$ = new Item_func_udf_float($1);
- }
- | UDF_INT_FUNC '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_func_udf_int($1, *$3);
+ sp_name *name= sp_name_current_db_new(YYTHD, $1);
+
+ if (sp_function_exists(YYTHD, name))
+ {
+ LEX *lex= Lex;
+
+ sp_add_fun_to_lex(lex, name);
+ if ($3)
+ $$= new Item_func_sp(name, *$3);
+ else
+ $$= new Item_func_sp(name);
+ }
else
- $$ = new Item_func_udf_int($1);
+ {
+#ifdef HAVE_DLOPEN
+ udf_func *udf;
+
+ if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
+ {
+ switch (udf->returns) {
+ case STRING_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_str(udf, *$3);
+ else
+ $$ = new Item_func_udf_str(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_str(udf, *$3);
+ else
+ $$ = new Item_sum_udf_str(udf);
+ }
+ break;
+ case REAL_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_float(udf, *$3);
+ else
+ $$ = new Item_func_udf_float(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_float(udf, *$3);
+ else
+ $$ = new Item_sum_udf_float(udf);
+ }
+ break;
+ case INT_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_int(udf, *$3);
+ else
+ $$ = new Item_func_udf_int(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_int(udf, *$3);
+ else
+ $$ = new Item_sum_udf_int(udf);
+ }
+ break;
+ default:
+ YYABORT;
+ }
+ }
+#endif /* HAVE_DLOPEN */
+ }
}
| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
{
@@ -4075,10 +4106,6 @@ fulltext_options:
| IN_SYM BOOLEAN_SYM MODE_SYM { $$= FT_BOOL; }
;
-sp_expr_list:
- /* empty */ { $$= NULL; }
- | expr_list { $$= $1;};
-
udf_expr_list:
/* empty */ { $$= NULL; }
| udf_expr_list2 { $$= $1;}
@@ -4825,19 +4852,19 @@ drop:
lex->drop_if_exists=$3;
lex->name=$4.str;
}
- | DROP FUNCTION_SYM if_exists IDENT_sys opt_restrict
+ | DROP FUNCTION_SYM if_exists sp_name opt_restrict
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->drop_if_exists= $3;
- lex->udf.name= $4;
+ lex->spname= $4;
}
- | DROP PROCEDURE if_exists IDENT_sys opt_restrict
+ | DROP PROCEDURE if_exists sp_name opt_restrict
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_PROCEDURE;
lex->drop_if_exists= $3;
- lex->udf.name= $4;
+ lex->spname= $4;
}
| DROP USER
{
@@ -5316,15 +5343,19 @@ show_param:
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
}
- | CREATE PROCEDURE ident
+ | CREATE PROCEDURE sp_name
{
- Lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
- Lex->udf.name= $3;
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
+ lex->spname= $3;
}
- | CREATE FUNCTION_SYM ident
+ | CREATE FUNCTION_SYM sp_name
{
- Lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
- Lex->udf.name= $3;
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
+ lex->spname= $3;
}
| PROCEDURE STATUS_SYM wild
{