Commit c92b5349 authored by unknown's avatar unknown

Fixed BUG#5000: SPs can be created with no default database.

  Easy to prevent crash, but the question was how to treat this case?
  We ended up implementing the "global" SPs (i.e. with no associated
  db), which were planned but left unresolved when SPs moved into dbs.
  So now things like "call .p()" work too.


mysql-test/r/sp-error.result:
  New test case for BUG#5000, and "global" SPs in general.
mysql-test/t/sp-error.test:
  New test case for BUG#5000, and "global" SPs in general.
sql/sp.cc:
  Prevent crash when the new db is null.
sql/sp_head.cc:
  Don't set the db part of the name to thd->db, we have already set it correctly
  in the provided name struct.
  Also, don't attempt to change "no-db" when executing an SP.
sql/sql_yacc.yy:
  Added support for the "global SP" syntax, e.g ".p()".
parent 1bf3ce01
delete from mysql.proc; delete from mysql.proc;
create function .f1() returns int return 1;
create procedure .p1() select 1, database();
create procedure p1() select 2, database();
alter procedure .p1 sql security invoker;
select .f1();
.f1()
1
call .p1();
1 database()
1 test
call p1();
2 database()
2 test
select f1();
ERROR 42000: FUNCTION test.f1 does not exist
select db,name,type,security_type from mysql.proc;
db name type security_type
f1 FUNCTION DEFINER
p1 PROCEDURE INVOKER
test p1 PROCEDURE DEFINER
drop function .f1;
drop procedure .p1;
drop procedure p1;
create procedure syntaxerror(t int)| create procedure syntaxerror(t int)|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
create procedure syntaxerror(t int)| create procedure syntaxerror(t int)|
......
...@@ -5,6 +5,29 @@ ...@@ -5,6 +5,29 @@
# Make sure we don't have any procedures left. # Make sure we don't have any procedures left.
delete from mysql.proc; delete from mysql.proc;
# A test "global" procedures, i.e. not belonging to any database.
create function .f1() returns int return 1;
create procedure .p1() select 1, database();
create procedure p1() select 2, database();
alter procedure .p1 sql security invoker;
# This is ok:
select .f1();
call .p1();
call p1();
# This is not ok:
--error 1304
select f1();
select db,name,type,security_type from mysql.proc;
drop function .f1;
drop procedure .p1;
drop procedure p1;
delimiter |; delimiter |;
# This should give three syntax errors (sometimes crashed; bug #643) # This should give three syntax errors (sometimes crashed; bug #643)
......
...@@ -1054,6 +1054,8 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen, ...@@ -1054,6 +1054,8 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
DBUG_ENTER("sp_use_new_db"); DBUG_ENTER("sp_use_new_db");
DBUG_PRINT("enter", ("newdb: %s", newdb)); DBUG_PRINT("enter", ("newdb: %s", newdb));
if (! newdb)
newdb= (char *)"";
if (thd->db && thd->db[0]) if (thd->db && thd->db[0])
{ {
if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0) if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0)
......
...@@ -296,16 +296,11 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -296,16 +296,11 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
name->m_db.length, name->m_db.str, name->m_db.length, name->m_db.str,
name->m_name.length, name->m_name.str)); name->m_name.length, name->m_name.str));
/* We have to copy strings to get them into the right memroot */ /* We have to copy strings to get them into the right memroot */
m_db.length= name->m_db.length;
if (name->m_db.length == 0) if (name->m_db.length == 0)
{ m_db.str= NULL;
m_db.length= (thd->db ? strlen(thd->db) : 0);
m_db.str= strmake_root(root, (thd->db ? thd->db : ""), m_db.length);
}
else else
{
m_db.length= name->m_db.length;
m_db.str= strmake_root(root, name->m_db.str, 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.length= name->m_name.length;
m_name.str= strmake_root(root, name->m_name.str, name->m_name.length); m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
...@@ -453,7 +448,8 @@ sp_head::execute(THD *thd) ...@@ -453,7 +448,8 @@ sp_head::execute(THD *thd)
#endif #endif
dbchanged= FALSE; dbchanged= FALSE;
if ((ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged))) if (m_db.length &&
(ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
goto done; goto done;
if ((ctx= thd->spcont)) if ((ctx= thd->spcont))
......
...@@ -1207,7 +1207,12 @@ create: ...@@ -1207,7 +1207,12 @@ create:
; ;
sp_name: sp_name:
IDENT_sys '.' IDENT_sys '.' IDENT_sys
{
$$= new sp_name($2);
$$->init_qname(YYTHD);
}
| IDENT_sys '.' IDENT_sys
{ {
$$= new sp_name($1, $3); $$= new sp_name($1, $3);
$$->init_qname(YYTHD); $$->init_qname(YYTHD);
...@@ -4312,6 +4317,18 @@ simple_expr: ...@@ -4312,6 +4317,18 @@ simple_expr:
{ $$= new Item_func_round($3,$5,1); } { $$= new Item_func_round($3,$5,1); }
| TRUE_SYM | TRUE_SYM
{ $$= new Item_int((char*) "TRUE",1,1); } { $$= new Item_int((char*) "TRUE",1,1); }
| '.' ident '(' udf_expr_list ')'
{
LEX *lex= Lex;
sp_name *name= new sp_name($2);
name->init_qname(YYTHD);
sp_add_fun_to_lex(Lex, name);
if ($4)
$$= new Item_func_sp(name, *$4);
else
$$= new Item_func_sp(name);
}
| ident '.' ident '(' udf_expr_list ')' | ident '.' ident '(' udf_expr_list ')'
{ {
LEX *lex= Lex; LEX *lex= Lex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment