Commit 45e58963 authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

Fixed various memory leaks.

parent 07541b6a
...@@ -583,12 +583,9 @@ sp_drop_procedure(THD *thd, char *name, uint namelen) ...@@ -583,12 +583,9 @@ 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));
sp_head *sp;
int ret; int ret;
sp= sp_cache_remove(&thd->sp_proc_cache, name, namelen); sp_cache_remove(&thd->sp_proc_cache, name, namelen);
if (sp)
delete sp;
ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen); ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen);
DBUG_RETURN(ret); DBUG_RETURN(ret);
...@@ -601,12 +598,9 @@ sp_update_procedure(THD *thd, char *name, uint namelen, ...@@ -601,12 +598,9 @@ 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));
sp_head *sp;
int ret; int ret;
sp= sp_cache_remove(&thd->sp_proc_cache, name, namelen); sp_cache_remove(&thd->sp_proc_cache, name, namelen);
if (sp)
delete sp;
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen, ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen,
newname, newnamelen, newname, newnamelen,
chistics); chistics);
...@@ -676,12 +670,9 @@ sp_drop_function(THD *thd, char *name, uint namelen) ...@@ -676,12 +670,9 @@ 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));
sp_head *sp;
int ret; int ret;
sp= sp_cache_remove(&thd->sp_func_cache, name, namelen); sp_cache_remove(&thd->sp_func_cache, name, namelen);
if (sp)
delete sp;
ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen); ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen);
DBUG_RETURN(ret); DBUG_RETURN(ret);
...@@ -694,12 +685,9 @@ sp_update_function(THD *thd, char *name, uint namelen, ...@@ -694,12 +685,9 @@ 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));
sp_head *sp;
int ret; int ret;
sp= sp_cache_remove(&thd->sp_func_cache, name, namelen); sp_cache_remove(&thd->sp_func_cache, name, namelen);
if (sp)
delete sp;
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen, ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen,
newname, newnamelen, newname, newnamelen,
chistics); chistics);
......
...@@ -92,11 +92,11 @@ sp_cache_lookup(sp_cache **cp, char *name, uint namelen) ...@@ -92,11 +92,11 @@ sp_cache_lookup(sp_cache **cp, char *name, uint namelen)
return c->lookup(name, namelen); return c->lookup(name, namelen);
} }
sp_head * bool
sp_cache_remove(sp_cache **cp, char *name, uint namelen) sp_cache_remove(sp_cache **cp, char *name, uint namelen)
{ {
sp_cache *c= *cp; sp_cache *c= *cp;
sp_head *sp= NULL; bool found= FALSE;
if (c) if (c)
{ {
...@@ -109,10 +109,10 @@ sp_cache_remove(sp_cache **cp, char *name, uint namelen) ...@@ -109,10 +109,10 @@ sp_cache_remove(sp_cache **cp, char *name, uint namelen)
if (c->version < v) if (c->version < v)
c->remove_all(); c->remove_all();
else else
sp= c->remove(name, namelen); found= c->remove(name, namelen);
c->version= v+1; c->version= v+1;
} }
return sp; return found;
} }
...@@ -123,6 +123,14 @@ hash_get_key_for_sp_head(const byte *ptr, uint *plen, ...@@ -123,6 +123,14 @@ hash_get_key_for_sp_head(const byte *ptr, uint *plen,
return ((sp_head*)ptr)->name(plen); return ((sp_head*)ptr)->name(plen);
} }
static void
hash_free_sp_head(void *p)
{
sp_head *sp= (sp_head *)p;
delete sp;
}
sp_cache::sp_cache() sp_cache::sp_cache()
{ {
init(); init();
...@@ -137,7 +145,7 @@ void ...@@ -137,7 +145,7 @@ void
sp_cache::init() sp_cache::init()
{ {
hash_init(&m_hashtable, system_charset_info, 0, 0, 0, hash_init(&m_hashtable, system_charset_info, 0, 0, 0,
hash_get_key_for_sp_head, 0, 0); hash_get_key_for_sp_head, hash_free_sp_head, 0);
version= 0; version= 0;
} }
......
...@@ -37,8 +37,8 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp); ...@@ -37,8 +37,8 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp);
/* Lookup an SP in cache */ /* 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, char *name, uint namelen);
/* Remove an SP from cache */ /* Remove an SP from cache. Returns true if something was removed */
sp_head *sp_cache_remove(sp_cache **cp, char *name, uint namelen); bool sp_cache_remove(sp_cache **cp, char *name, uint namelen);
/* /*
...@@ -75,14 +75,17 @@ class sp_cache ...@@ -75,14 +75,17 @@ class sp_cache
return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen); return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen);
} }
inline sp_head * inline bool
remove(char *name, uint namelen) remove(char *name, uint namelen)
{ {
sp_head *sp= lookup(name, namelen); sp_head *sp= lookup(name, namelen);
if (sp) if (sp)
{
hash_delete(&m_hashtable, (byte *)sp); hash_delete(&m_hashtable, (byte *)sp);
return sp; return TRUE;
}
return FALSE;
} }
inline void inline void
......
...@@ -146,6 +146,7 @@ sp_head::operator delete(void *ptr, size_t size) ...@@ -146,6 +146,7 @@ sp_head::operator delete(void *ptr, size_t size)
MEM_ROOT own_root; MEM_ROOT own_root;
sp_head *sp= (sp_head *)ptr; sp_head *sp= (sp_head *)ptr;
DBUG_PRINT("info", ("root: %lx", &sp->m_mem_root));
memcpy(&own_root, (const void *)&sp->m_mem_root, sizeof(MEM_ROOT)); memcpy(&own_root, (const void *)&sp->m_mem_root, sizeof(MEM_ROOT));
free_root(&own_root, MYF(0)); free_root(&own_root, MYF(0));
...@@ -178,15 +179,17 @@ sp_head::init(LEX *lex) ...@@ -178,15 +179,17 @@ sp_head::init(LEX *lex)
} }
void void
sp_head::init_strings(LEX_STRING *name, LEX *lex) sp_head::init_strings(THD *thd, LEX *lex, LEX_STRING *name)
{ {
DBUG_ENTER("sp_head::init_strings"); 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)); DBUG_PRINT("info", ("name: %*s", name->length, name->str));
m_name.length= name->length; m_name.length= name->length;
m_name.str= strmake_root(&m_mem_root, name->str, name->length); m_name.str= strmake_root(root, name->str, name->length);
m_params.length= m_param_end- m_param_begin; m_params.length= m_param_end- m_param_begin;
m_params.str= strmake_root(&m_mem_root, m_params.str= strmake_root(root,
(char *)m_param_begin, m_params.length); (char *)m_param_begin, m_params.length);
if (m_returns_begin && m_returns_end) if (m_returns_begin && m_returns_end)
{ {
...@@ -204,13 +207,13 @@ sp_head::init_strings(LEX_STRING *name, LEX *lex) ...@@ -204,13 +207,13 @@ sp_head::init_strings(LEX_STRING *name, LEX *lex)
p-= 1; p-= 1;
m_returns_end= (uchar *)p+1; m_returns_end= (uchar *)p+1;
m_retstr.length= m_returns_end - m_returns_begin; m_retstr.length= m_returns_end - m_returns_begin;
m_retstr.str= strmake_root(&m_mem_root, m_retstr.str= strmake_root(root,
(char *)m_returns_begin, m_retstr.length); (char *)m_returns_begin, m_retstr.length);
} }
m_body.length= lex->end_of_query - m_body_begin; m_body.length= lex->end_of_query - m_body_begin;
m_body.str= strmake_root(&m_mem_root, (char *)m_body_begin, m_body.length); m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
m_defstr.length= lex->end_of_query - lex->buf; m_defstr.length= lex->end_of_query - lex->buf;
m_defstr.str= strmake_root(&m_mem_root, (char *)lex->buf, m_defstr.length); m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -83,7 +83,7 @@ class sp_head : public Sql_alloc ...@@ -83,7 +83,7 @@ class sp_head : public Sql_alloc
// Initialize strings after parsing header // Initialize strings after parsing header
void void
init_strings(LEX_STRING *name, LEX *lex); init_strings(THD *thd, LEX *lex, LEX_STRING *name);
int int
create(THD *thd); create(THD *thd);
......
...@@ -3473,12 +3473,18 @@ mysql_execute_command(THD *thd) ...@@ -3473,12 +3473,18 @@ mysql_execute_command(THD *thd)
{ {
case SP_OK: case SP_OK:
send_ok(thd); send_ok(thd);
delete lex->sphead;
lex->sphead= 0;
break; break;
case SP_WRITE_ROW_FAILED: case SP_WRITE_ROW_FAILED:
net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name); net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name);
delete lex->sphead;
lex->sphead= 0;
goto error; goto error;
default: default:
net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name); net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name);
delete lex->sphead;
lex->sphead= 0;
goto error; goto error;
} }
break; break;
......
...@@ -1078,7 +1078,7 @@ create: ...@@ -1078,7 +1078,7 @@ create:
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->init_strings(&$3, lex); lex->sphead->init_strings(YYTHD, lex, &$3);
lex->sql_command= SQLCOM_CREATE_PROCEDURE; lex->sql_command= SQLCOM_CREATE_PROCEDURE;
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq) if (lex->sphead->m_old_cmq)
...@@ -1158,7 +1158,7 @@ create_function_tail: ...@@ -1158,7 +1158,7 @@ create_function_tail:
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION; lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(&lex->udf.name, lex); sp->init_strings(YYTHD, lex, &lex->udf.name);
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (sp->m_old_cmq) if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
......
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