Commit 10f9b7fb authored by unknown's avatar unknown

Fixed memory leaks in SP

Some code cleanup


mysql-test/r/sp.result:
  Update results after adding quotes around function/procedure names
sql/sp.cc:
  Moved DBUG_ENTER after all variable declarations
  Eliminated some variables.
  Added more DBUG_ENTER commands.
  Added memory allocation checking in create_string()
  Fixed memory leak in sp_show_create_function()
  Removed usage of sprintf
sql/sql_parse.cc:
  Simple cleanup
  Fixed memory leaks for mailformed SP definitions
parent 3c40a281
...@@ -732,7 +732,7 @@ delete from t1| ...@@ -732,7 +732,7 @@ delete from t1|
alter procedure chistics sql security invoker name chistics2| alter procedure chistics sql security invoker name chistics2|
show create procedure chistics2| show create procedure chistics2|
Procedure Create Procedure Procedure Create Procedure
chistics2 CREATE PROCEDURE chistics2() chistics2 CREATE PROCEDURE `chistics2`()
SQL SECURITY INVOKER SQL SECURITY INVOKER
COMMENT 'Characteristics procedure test' COMMENT 'Characteristics procedure test'
insert into t1 values ("chistics", 1) insert into t1 values ("chistics", 1)
...@@ -749,7 +749,7 @@ chistics() ...@@ -749,7 +749,7 @@ chistics()
alter function chistics name chistics2 comment 'Characteristics function test'| alter function chistics name chistics2 comment 'Characteristics function test'|
show create function chistics2| show create function chistics2|
Function Create Function Function Create Function
chistics2 CREATE FUNCTION chistics2() RETURNS int chistics2 CREATE FUNCTION `chistics2`() RETURNS int
DETERMINISTIC DETERMINISTIC
SQL SECURITY INVOKER SQL SECURITY INVOKER
COMMENT 'Characteristics function test' COMMENT 'Characteristics function test'
...@@ -999,7 +999,7 @@ end while; ...@@ -999,7 +999,7 @@ end while;
end| end|
show create procedure opp| show create procedure opp|
Procedure Create Procedure Procedure Create Procedure
opp CREATE PROCEDURE opp(n bigint unsigned, out pp bool) opp CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
begin begin
declare r double; declare r double;
declare b, s bigint unsigned default 0; declare b, s bigint unsigned default 0;
...@@ -1096,7 +1096,7 @@ alter procedure bar2 name bar comment "3333333333"| ...@@ -1096,7 +1096,7 @@ alter procedure bar2 name bar comment "3333333333"|
alter procedure bar| alter procedure bar|
show create procedure bar| show create procedure bar|
Procedure Create Procedure Procedure Create Procedure
bar CREATE PROCEDURE bar(x char(16), y int) bar CREATE PROCEDURE `bar`(x char(16), y int)
COMMENT '3333333333' COMMENT '3333333333'
insert into test.t1 values (x, y) insert into test.t1 values (x, y)
show procedure status like 'bar'| show procedure status like 'bar'|
......
...@@ -61,13 +61,13 @@ static int ...@@ -61,13 +61,13 @@ static int
db_find_routine_aux(THD *thd, int type, char *name, uint namelen, db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
enum thr_lock_type ltype, TABLE **tablep, bool *opened) enum thr_lock_type ltype, TABLE **tablep, bool *opened)
{ {
DBUG_ENTER("db_find_routine_aux");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
TABLE *table; TABLE *table;
byte key[64+64+1]; // db, name, type byte key[64+64+1]; // db, name, type
uint keylen; uint keylen;
DBUG_ENTER("db_find_routine_aux");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
// Put the key together // Put the key used to read the row together
memset(key, (int)' ', 64); // QQ Empty db for now memset(key, (int)' ', 64); // QQ Empty db for now
keylen= namelen; keylen= namelen;
if (keylen > 64) if (keylen > 64)
...@@ -110,11 +110,10 @@ db_find_routine_aux(THD *thd, int type, char *name, uint namelen, ...@@ -110,11 +110,10 @@ db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
DBUG_RETURN(SP_OK); DBUG_RETURN(SP_OK);
} }
static int static int
db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
{ {
DBUG_ENTER("db_find_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
extern int yyparse(void *thd); extern int yyparse(void *thd);
TABLE *table; TABLE *table;
const char *params, *returns, *body; const char *params, *returns, *body;
...@@ -129,6 +128,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -129,6 +128,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
char buff[65]; char buff[65];
String str(buff, sizeof(buff), &my_charset_bin); String str(buff, sizeof(buff), &my_charset_bin);
ulong sql_mode; ulong sql_mode;
DBUG_ENTER("db_find_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
ret= db_find_routine_aux(thd, type, name, namelen, TL_READ, &table, &opened); ret= db_find_routine_aux(thd, type, name, namelen, TL_READ, &table, &opened);
if (ret != SP_OK) if (ret != SP_OK)
...@@ -202,8 +203,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -202,8 +203,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
if (opened) if (opened)
{ {
close_thread_tables(thd, 0, 1);
opened= FALSE; opened= FALSE;
close_thread_tables(thd, 0, 1);
} }
{ {
...@@ -217,13 +218,18 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -217,13 +218,18 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
thd->variables.sql_mode= sql_mode; thd->variables.sql_mode= sql_mode;
thd->variables.select_limit= HA_POS_ERROR; thd->variables.select_limit= HA_POS_ERROR;
defstr= create_string(thd, &deflen, if (!(defstr= create_string(thd, &deflen,
type, type,
name, namelen, name, namelen,
params, strlen(params), params, strlen(params),
returns, strlen(returns), returns, strlen(returns),
body, strlen(body), body, strlen(body),
&chistics); &chistics)))
{
ret= SP_INTERNAL_ERROR;
goto done;
}
lex_start(thd, (uchar*)defstr, deflen); lex_start(thd, (uchar*)defstr, deflen);
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL) if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
{ {
...@@ -256,15 +262,16 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -256,15 +262,16 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
static int static int
db_create_routine(THD *thd, int type, sp_head *sp) db_create_routine(THD *thd, int type, sp_head *sp)
{ {
DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %*s",type,sp->m_name.length,sp->m_name.str));
int ret; int ret;
TABLE *table; TABLE *table;
TABLE_LIST tables; TABLE_LIST tables;
char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %*s",type,sp->m_name.length,sp->m_name.str));
memset(&tables, 0, sizeof(tables)); memset(&tables, 0, sizeof(tables));
tables.db= (char*)"mysql"; tables.db= (char*)"mysql";
...@@ -310,10 +317,9 @@ db_create_routine(THD *thd, int type, sp_head *sp) ...@@ -310,10 +317,9 @@ db_create_routine(THD *thd, int type, sp_head *sp)
store(sp->m_chistics->comment.str, sp->m_chistics->comment.length, store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
system_charset_info); system_charset_info);
ret= SP_OK;
if (table->file->write_row(table->record[0])) if (table->file->write_row(table->record[0]))
ret= SP_WRITE_ROW_FAILED; ret= SP_WRITE_ROW_FAILED;
else
ret= SP_OK;
} }
done: done:
...@@ -321,14 +327,15 @@ db_create_routine(THD *thd, int type, sp_head *sp) ...@@ -321,14 +327,15 @@ db_create_routine(THD *thd, int type, sp_head *sp)
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
static int static int
db_drop_routine(THD *thd, int type, char *name, uint namelen) db_drop_routine(THD *thd, int type, char *name, uint namelen)
{ {
DBUG_ENTER("db_drop_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
TABLE *table; TABLE *table;
int ret; int ret;
bool opened; bool opened;
DBUG_ENTER("db_drop_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened); ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened);
if (ret == SP_OK) if (ret == SP_OK)
...@@ -342,16 +349,17 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen) ...@@ -342,16 +349,17 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen)
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
static int static int
db_update_routine(THD *thd, int type, char *name, uint namelen, db_update_routine(THD *thd, int type, char *name, uint namelen,
char *newname, uint newnamelen, char *newname, uint newnamelen,
st_sp_chistics *chistics) st_sp_chistics *chistics)
{ {
DBUG_ENTER("db_update_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
TABLE *table; TABLE *table;
int ret; int ret;
bool opened; bool opened;
DBUG_ENTER("db_update_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened); ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened);
if (ret == SP_OK) if (ret == SP_OK)
...@@ -376,6 +384,7 @@ db_update_routine(THD *thd, int type, char *name, uint namelen, ...@@ -376,6 +384,7 @@ db_update_routine(THD *thd, int type, char *name, uint namelen,
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
struct st_used_field struct st_used_field
{ {
const char *field_name; const char *field_name;
...@@ -396,6 +405,7 @@ static struct st_used_field init_fields[]= ...@@ -396,6 +405,7 @@ static struct st_used_field init_fields[]=
{ 0, 0, MYSQL_TYPE_STRING, 0} { 0, 0, MYSQL_TYPE_STRING, 0}
}; };
static int static int
print_field_values(THD *thd, TABLE *table, print_field_values(THD *thd, TABLE *table,
struct st_used_field *used_fields, struct st_used_field *used_fields,
...@@ -444,14 +454,14 @@ print_field_values(THD *thd, TABLE *table, ...@@ -444,14 +454,14 @@ print_field_values(THD *thd, TABLE *table,
return SP_OK; return SP_OK;
} }
static int static int
db_show_routine_status(THD *thd, int type, const char *wild) db_show_routine_status(THD *thd, int type, const char *wild)
{ {
DBUG_ENTER("db_show_routine_status");
TABLE *table; TABLE *table;
TABLE_LIST tables; TABLE_LIST tables;
int res; int res;
DBUG_ENTER("db_show_routine_status");
memset(&tables, 0, sizeof(tables)); memset(&tables, 0, sizeof(tables));
tables.db= (char*)"mysql"; tables.db= (char*)"mysql";
...@@ -513,10 +523,7 @@ db_show_routine_status(THD *thd, int type, const char *wild) ...@@ -513,10 +523,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
table->file->index_init(0); table->file->index_init(0);
if ((res= table->file->index_first(table->record[0]))) if ((res= table->file->index_first(table->record[0])))
{ {
if (res == HA_ERR_END_OF_FILE) res= (res == HA_ERR_END_OF_FILE) ? 0 : SP_INTERNAL_ERROR;
res= 0;
else
res= SP_INTERNAL_ERROR;
goto err_case1; goto err_case1;
} }
if ((res= print_field_values(thd, table, used_fields, type, wild))) if ((res= print_field_values(thd, table, used_fields, type, wild)))
...@@ -529,67 +536,57 @@ db_show_routine_status(THD *thd, int type, const char *wild) ...@@ -529,67 +536,57 @@ db_show_routine_status(THD *thd, int type, const char *wild)
res= SP_OK; res= SP_OK;
} }
err_case1: err_case1:
send_eof(thd); send_eof(thd);
err_case: err_case:
close_thread_tables(thd); close_thread_tables(thd);
done: done:
DBUG_RETURN(res); DBUG_RETURN(res);
} }
/* /*****************************************************************************
* PROCEDURE
* PROCEDURE ******************************************************************************/
*
*/
sp_head * sp_head *
sp_find_procedure(THD *thd, LEX_STRING *name) sp_find_procedure(THD *thd, LEX_STRING *name)
{ {
DBUG_ENTER("sp_find_procedure");
sp_head *sp; sp_head *sp;
DBUG_ENTER("sp_find_procedure");
DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
sp= sp_cache_lookup(&thd->sp_proc_cache, name->str, name->length); if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name->str, name->length)))
if (! sp)
{ {
if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, if (db_find_routine(thd, TYPE_ENUM_PROCEDURE,
name->str, name->length, &sp) == SP_OK) name->str, name->length, &sp) == SP_OK)
{
sp_cache_insert(&thd->sp_proc_cache, sp); sp_cache_insert(&thd->sp_proc_cache, sp);
}
} }
DBUG_RETURN(sp); DBUG_RETURN(sp);
} }
int int
sp_create_procedure(THD *thd, sp_head *sp) sp_create_procedure(THD *thd, sp_head *sp)
{ {
DBUG_ENTER("sp_create_procedure"); DBUG_ENTER("sp_create_procedure");
DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str)); DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str));
int ret; DBUG_RETURN(db_create_routine(thd, TYPE_ENUM_PROCEDURE, sp));
ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, sp);
DBUG_RETURN(ret);
} }
int int
sp_drop_procedure(THD *thd, char *name, uint namelen) sp_drop_procedure(THD *thd, char *name, uint namelen)
{ {
DBUG_ENTER("sp_drop_procedure"); DBUG_ENTER("sp_drop_procedure");
DBUG_PRINT("enter", ("name: %*s", namelen, name)); DBUG_PRINT("enter", ("name: %*s", namelen, name));
int ret;
sp_cache_remove(&thd->sp_proc_cache, name, namelen); sp_cache_remove(&thd->sp_proc_cache, name, namelen);
ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen); DBUG_RETURN(db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen));
DBUG_RETURN(ret);
} }
int int
sp_update_procedure(THD *thd, char *name, uint namelen, sp_update_procedure(THD *thd, char *name, uint namelen,
char *newname, uint newnamelen, char *newname, uint newnamelen,
...@@ -597,30 +594,27 @@ sp_update_procedure(THD *thd, char *name, uint namelen, ...@@ -597,30 +594,27 @@ sp_update_procedure(THD *thd, char *name, uint namelen,
{ {
DBUG_ENTER("sp_update_procedure"); DBUG_ENTER("sp_update_procedure");
DBUG_PRINT("enter", ("name: %*s", namelen, name)); DBUG_PRINT("enter", ("name: %*s", namelen, name));
int ret;
sp_cache_remove(&thd->sp_proc_cache, name, namelen); sp_cache_remove(&thd->sp_proc_cache, name, namelen);
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen, DBUG_RETURN(db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen,
newname, newnamelen, newname, newnamelen, chistics));
chistics);
DBUG_RETURN(ret);
} }
int int
sp_show_create_procedure(THD *thd, LEX_STRING *name) sp_show_create_procedure(THD *thd, LEX_STRING *name)
{ {
sp_head *sp;
DBUG_ENTER("sp_show_create_procedure"); DBUG_ENTER("sp_show_create_procedure");
DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
sp_head *sp;
sp= sp_find_procedure(thd, name); if ((sp= sp_find_procedure(thd, name)))
if (sp) DBUG_RETURN(sp->show_create_procedure(thd));
DBUG_RETURN(sp->show_create_procedure(thd));
DBUG_RETURN(SP_KEY_NOT_FOUND); DBUG_RETURN(SP_KEY_NOT_FOUND);
} }
int int
sp_show_status_procedure(THD *thd, const char *wild) sp_show_status_procedure(THD *thd, const char *wild)
{ {
...@@ -628,55 +622,51 @@ sp_show_status_procedure(THD *thd, const char *wild) ...@@ -628,55 +622,51 @@ sp_show_status_procedure(THD *thd, const char *wild)
DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild)); DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild));
} }
/*
* /*****************************************************************************
* FUNCTION FUNCTION
* ******************************************************************************/
*/
sp_head * sp_head *
sp_find_function(THD *thd, LEX_STRING *name) sp_find_function(THD *thd, LEX_STRING *name)
{ {
DBUG_ENTER("sp_find_function");
sp_head *sp; sp_head *sp;
DBUG_ENTER("sp_find_function");
DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
sp= sp_cache_lookup(&thd->sp_func_cache, name->str, name->length); if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name->str, name->length)))
if (! sp)
{ {
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, if (db_find_routine(thd, TYPE_ENUM_FUNCTION,
name->str, name->length, &sp) != SP_OK) name->str, name->length, &sp) != SP_OK)
sp= NULL; sp= NULL;
else
sp_cache_insert(&thd->sp_func_cache, sp);
} }
DBUG_RETURN(sp); DBUG_RETURN(sp);
} }
int int
sp_create_function(THD *thd, sp_head *sp) sp_create_function(THD *thd, sp_head *sp)
{ {
DBUG_ENTER("sp_create_function"); DBUG_ENTER("sp_create_function");
DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str)); DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str));
int ret;
ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, sp); DBUG_RETURN(db_create_routine(thd, TYPE_ENUM_FUNCTION, sp));
DBUG_RETURN(ret);
} }
int int
sp_drop_function(THD *thd, char *name, uint namelen) sp_drop_function(THD *thd, char *name, uint namelen)
{ {
DBUG_ENTER("sp_drop_function"); DBUG_ENTER("sp_drop_function");
DBUG_PRINT("enter", ("name: %*s", namelen, name)); DBUG_PRINT("enter", ("name: %*s", namelen, name));
int ret;
sp_cache_remove(&thd->sp_func_cache, name, namelen); sp_cache_remove(&thd->sp_func_cache, name, namelen);
ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen); DBUG_RETURN(db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen));
DBUG_RETURN(ret);
} }
int int
sp_update_function(THD *thd, char *name, uint namelen, sp_update_function(THD *thd, char *name, uint namelen,
char *newname, uint newnamelen, char *newname, uint newnamelen,
...@@ -684,30 +674,26 @@ sp_update_function(THD *thd, char *name, uint namelen, ...@@ -684,30 +674,26 @@ sp_update_function(THD *thd, char *name, uint namelen,
{ {
DBUG_ENTER("sp_update_procedure"); DBUG_ENTER("sp_update_procedure");
DBUG_PRINT("enter", ("name: %*s", namelen, name)); DBUG_PRINT("enter", ("name: %*s", namelen, name));
int ret;
sp_cache_remove(&thd->sp_func_cache, name, namelen); sp_cache_remove(&thd->sp_func_cache, name, namelen);
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen, DBUG_RETURN(db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen,
newname, newnamelen, newname, newnamelen, chistics));
chistics);
DBUG_RETURN(ret);
} }
int int
sp_show_create_function(THD *thd, LEX_STRING *name) sp_show_create_function(THD *thd, LEX_STRING *name)
{ {
sp_head *sp;
DBUG_ENTER("sp_show_create_function"); DBUG_ENTER("sp_show_create_function");
DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
sp_head *sp;
sp= sp_find_function(thd, name); if ((sp= sp_find_function(thd, name)))
if (sp)
DBUG_RETURN(sp->show_create_function(thd)); DBUG_RETURN(sp->show_create_function(thd));
DBUG_RETURN(SP_KEY_NOT_FOUND); DBUG_RETURN(SP_KEY_NOT_FOUND);
} }
int int
sp_show_status_function(THD *thd, const char *wild) sp_show_status_function(THD *thd, const char *wild)
{ {
...@@ -715,6 +701,7 @@ sp_show_status_function(THD *thd, const char *wild) ...@@ -715,6 +701,7 @@ sp_show_status_function(THD *thd, const char *wild)
DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild)); DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild));
} }
// QQ Temporary until the function call detection in sql_lex has been reworked. // QQ Temporary until the function call detection in sql_lex has been reworked.
bool bool
sp_function_exists(THD *thd, LEX_STRING *name) sp_function_exists(THD *thd, LEX_STRING *name)
...@@ -722,17 +709,16 @@ sp_function_exists(THD *thd, LEX_STRING *name) ...@@ -722,17 +709,16 @@ sp_function_exists(THD *thd, LEX_STRING *name)
TABLE *table; TABLE *table;
bool ret= FALSE; bool ret= FALSE;
bool opened= 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->str, name->length) ||
db_find_routine_aux(thd, TYPE_ENUM_FUNCTION, db_find_routine_aux(thd, TYPE_ENUM_FUNCTION,
name->str, name->length, TL_READ, name->str, name->length, TL_READ,
&table, &opened) == SP_OK) &table, &opened) == SP_OK)
{
ret= TRUE; ret= TRUE;
}
if (opened) if (opened)
close_thread_tables(thd, 0, 1); close_thread_tables(thd, 0, 1);
return ret; DBUG_RETURN(ret);
} }
...@@ -744,6 +730,7 @@ sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first) ...@@ -744,6 +730,7 @@ sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first)
return (byte *)lsp->str; return (byte *)lsp->str;
} }
void void
sp_add_fun_to_lex(LEX *lex, LEX_STRING fun) sp_add_fun_to_lex(LEX *lex, LEX_STRING fun)
{ {
...@@ -757,6 +744,7 @@ sp_add_fun_to_lex(LEX *lex, LEX_STRING fun) ...@@ -757,6 +744,7 @@ sp_add_fun_to_lex(LEX *lex, LEX_STRING fun)
} }
} }
void void
sp_merge_funs(LEX *dst, LEX *src) sp_merge_funs(LEX *dst, LEX *src)
{ {
...@@ -769,6 +757,7 @@ sp_merge_funs(LEX *dst, LEX *src) ...@@ -769,6 +757,7 @@ sp_merge_funs(LEX *dst, LEX *src)
} }
} }
int int
sp_cache_functions(THD *thd, LEX *lex) sp_cache_functions(THD *thd, LEX *lex)
{ {
...@@ -786,8 +775,7 @@ sp_cache_functions(THD *thd, LEX *lex) ...@@ -786,8 +775,7 @@ sp_cache_functions(THD *thd, LEX *lex)
LEX *newlex= new st_lex; LEX *newlex= new st_lex;
thd->lex= newlex; thd->lex= newlex;
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, ls->str, ls->length, &sp) if (db_find_routine(thd, TYPE_ENUM_FUNCTION, ls->str, ls->length, &sp) == SP_OK)
== SP_OK)
{ {
ret= sp_cache_functions(thd, newlex); ret= sp_cache_functions(thd, newlex);
delete newlex; delete newlex;
...@@ -809,6 +797,7 @@ sp_cache_functions(THD *thd, LEX *lex) ...@@ -809,6 +797,7 @@ sp_cache_functions(THD *thd, LEX *lex)
return ret; return ret;
} }
static char * static char *
create_string(THD *thd, ulong *lenp, create_string(THD *thd, ulong *lenp,
int type, int type,
...@@ -821,23 +810,17 @@ create_string(THD *thd, ulong *lenp, ...@@ -821,23 +810,17 @@ create_string(THD *thd, ulong *lenp,
char *buf, *ptr; char *buf, *ptr;
ulong buflen; ulong buflen;
buflen= 100 + namelen + paramslen + returnslen + bodylen + buflen= 100 + namelen + paramslen + returnslen + bodylen + chistics->comment.length;
chistics->comment.length; if (!(buf= thd->alloc(buflen)))
ptr= buf= thd->alloc(buflen); return 0;
ptr= strxmov(buf, "CREATE ", (type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
" `", name, "`(", params, ")", NullS);
if (type == TYPE_ENUM_FUNCTION) if (type == TYPE_ENUM_FUNCTION)
{ ptr= strxmov(ptr, " RETURNS ", returns, NullS);
ptr+= my_sprintf(buf, *ptr++= '\n';
(buf, (char *)
"CREATE FUNCTION %s(%s) RETURNS %s\n",
name, params, returns));
}
else
{
ptr+= my_sprintf(buf,
(buf, (char *)
"CREATE PROCEDURE %s(%s)\n",
name, params));
}
if (chistics->detistic) if (chistics->detistic)
ptr= strmov(ptr, " DETERMINISTIC\n"); ptr= strmov(ptr, " DETERMINISTIC\n");
if (chistics->suid == IS_NOT_SUID) if (chistics->suid == IS_NOT_SUID)
......
...@@ -3084,23 +3084,23 @@ mysql_execute_command(THD *thd) ...@@ -3084,23 +3084,23 @@ mysql_execute_command(THD *thd)
break; break;
} }
case SQLCOM_CREATE_FUNCTION: // UDF function case SQLCOM_CREATE_FUNCTION: // UDF function
{ {
if (check_access(thd,INSERT_ACL,"mysql",0,1,0)) sp_head *sph;
break; if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
break;
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
sp_head *sph= sp_find_function(thd, &lex->udf.name); if (!(sph= sp_find_function(thd, &lex->udf.name)))
if (sph) {
{ net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str);
net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str); goto error;
goto error; }
} if (!(res = mysql_create_function(thd,&lex->udf)))
if (!(res = mysql_create_function(thd,&lex->udf))) send_ok(thd);
send_ok(thd);
#else #else
res= -1; res= -1;
#endif #endif
break; break;
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_DROP_USER: case SQLCOM_DROP_USER:
{ {
...@@ -3374,62 +3374,62 @@ mysql_execute_command(THD *thd) ...@@ -3374,62 +3374,62 @@ mysql_execute_command(THD *thd)
break; break;
case SQLCOM_CREATE_PROCEDURE: case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION: case SQLCOM_CREATE_SPFUNCTION:
{
if (!lex->sphead) if (!lex->sphead)
{ {
res= -1; // Shouldn't happen res= -1; // Shouldn't happen
break; break;
} }
else uint namelen;
{ char *name= lex->sphead->name(&namelen);
uint namelen;
char *name= lex->sphead->name(&namelen);
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION) if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
{ {
udf_func *udf = find_udf(name, namelen); udf_func *udf = find_udf(name, namelen);
if (udf)
{
net_printf(thd, ER_UDF_EXISTS, name);
goto error;
}
}
#endif
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
!lex->sphead->m_has_return)
{
net_printf(thd, ER_SP_NORETURN, name);
goto error;
}
res= lex->sphead->create(thd);
switch (res) if (udf)
{ {
case SP_OK: net_printf(thd, ER_UDF_EXISTS, name);
send_ok(thd);
delete lex->sphead;
lex->sphead= 0;
break;
case SP_WRITE_ROW_FAILED:
net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
default:
net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name);
delete lex->sphead; delete lex->sphead;
lex->sphead= 0; lex->sphead=0;
goto error; goto error;
} }
}
#endif
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
!lex->sphead->m_has_return)
{
net_printf(thd, ER_SP_NORETURN, name);
delete lex->sphead;
lex->sphead=0;
goto error;
}
res= lex->sphead->create(thd);
switch (res) {
case SP_OK:
send_ok(thd);
delete lex->sphead;
lex->sphead= 0;
break; break;
case SP_WRITE_ROW_FAILED:
net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
default:
net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
} }
break;
}
case SQLCOM_CALL: case SQLCOM_CALL:
{ {
sp_head *sp; sp_head *sp;
sp= sp_find_procedure(thd, &lex->udf.name); if (!(sp= sp_find_procedure(thd, &lex->udf.name)))
if (! sp)
{ {
net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE", lex->udf.name); net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE", lex->udf.name);
goto error; goto error;
...@@ -3611,6 +3611,7 @@ mysql_execute_command(THD *thd) ...@@ -3611,6 +3611,7 @@ mysql_execute_command(THD *thd)
res= 0; res= 0;
goto error; goto error;
} }
res= 0;
break; break;
} }
case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_PROC:
...@@ -4157,6 +4158,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -4157,6 +4158,7 @@ mysql_parse(THD *thd, char *inBuf, uint length)
query_cache_abort(&thd->net); query_cache_abort(&thd->net);
if (thd->lex->sphead) if (thd->lex->sphead)
{ {
/* Clean up after failed stored procedure/function */
if (lex != thd->lex) if (lex != thd->lex)
thd->lex->sphead->restore_lex(thd); thd->lex->sphead->restore_lex(thd);
delete thd->lex->sphead; delete thd->lex->sphead;
......
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