mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -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()
|
|||||||
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;
|
|||||||
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"|
|
|||||||
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'|
|
||||||
|
189
sql/sp.cc
189
sql/sp.cc
@ -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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@ done:
|
|||||||
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)
|
|||||||
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,
|
|||||||
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[]=
|
|||||||
{ 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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
||||||
|
110
sql/sql_parse.cc
110
sql/sql_parse.cc
@ -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)
|
|||||||
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)
|
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);
|
net_printf(thd, ER_UDF_EXISTS, name);
|
||||||
|
delete lex->sphead;
|
||||||
|
lex->sphead=0;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
res= lex->sphead->create(thd);
|
|
||||||
|
|
||||||
switch (res)
|
|
||||||
{
|
|
||||||
case SP_OK:
|
|
||||||
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;
|
|
||||||
lex->sphead= 0;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
#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;
|
||||||
|
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user