From c92b5349701ba68fa7ab97abf14933de8d6352fe Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Sep 2004 14:23:14 +0200 Subject: [PATCH] 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()". --- mysql-test/r/sp-error.result | 23 +++++++++++++++++++++++ mysql-test/t/sp-error.test | 23 +++++++++++++++++++++++ sql/sp.cc | 2 ++ sql/sp_head.cc | 12 ++++-------- sql/sql_yacc.yy | 19 ++++++++++++++++++- 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 6b36b3bb2bf..6426e078894 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1,4 +1,27 @@ 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)| 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)| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index f8abab0e7e3..d946ba7afbc 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -5,6 +5,29 @@ # Make sure we don't have any procedures left. 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 |; # This should give three syntax errors (sometimes crashed; bug #643) diff --git a/sql/sp.cc b/sql/sp.cc index 41d07bb9d40..6475b64eb18 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1054,6 +1054,8 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen, DBUG_ENTER("sp_use_new_db"); DBUG_PRINT("enter", ("newdb: %s", newdb)); + if (! newdb) + newdb= (char *)""; if (thd->db && thd->db[0]) { if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 4bb06fd8172..5222f8e6fbe 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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_name.length, name->m_name.str)); /* 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) - { - m_db.length= (thd->db ? strlen(thd->db) : 0); - m_db.str= strmake_root(root, (thd->db ? thd->db : ""), m_db.length); - } + m_db.str= NULL; 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); @@ -453,7 +448,8 @@ sp_head::execute(THD *thd) #endif 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; if ((ctx= thd->spcont)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ba3a36f2c34..17cc3b7d12c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1207,7 +1207,12 @@ create: ; sp_name: - IDENT_sys '.' IDENT_sys + '.' IDENT_sys + { + $$= new sp_name($2); + $$->init_qname(YYTHD); + } + | IDENT_sys '.' IDENT_sys { $$= new sp_name($1, $3); $$->init_qname(YYTHD); @@ -4312,6 +4317,18 @@ simple_expr: { $$= new Item_func_round($3,$5,1); } | TRUE_SYM { $$= 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 ')' { LEX *lex= Lex;