Commit 6892cf08 authored by unknown's avatar unknown

Getting rid of lots of memory leaks (but not quite all of them yet,

some will go away when temporary code is replaced).


mysql-test/r/sp.result:
  Drop db before creating.
mysql-test/t/sp.test:
  Drop db before creating.
parent 36598365
...@@ -20,6 +20,7 @@ delete from t1; ...@@ -20,6 +20,7 @@ delete from t1;
drop procedure foo42; drop procedure foo42;
create procedure u() create procedure u()
use sptmp; use sptmp;
drop database if exists sptmp;
create database sptmp; create database sptmp;
use test; use test;
call u(); call u();
......
...@@ -35,6 +35,9 @@ drop procedure foo42; ...@@ -35,6 +35,9 @@ drop procedure foo42;
create procedure u() create procedure u()
use sptmp; use sptmp;
--disable_warnings
drop database if exists sptmp;
--enable_warnings
create database sptmp; create database sptmp;
use test; use test;
call u(); call u();
......
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
#include "sp.h" #include "sp.h"
#include "sp_head.h" #include "sp_head.h"
static sp_head * static sp_head *
sp_find_cached_function(THD *thd, char *name, uint namelen); sp_find_cached_function(THD *thd, char *name, uint namelen);
/* /*
* *
...@@ -373,6 +373,13 @@ sp_cache_functions(THD *thd, LEX *lex) ...@@ -373,6 +373,13 @@ sp_cache_functions(THD *thd, LEX *lex)
void void
sp_clear_function_cache(THD *thd) sp_clear_function_cache(THD *thd)
{ {
//QQ This doesn't work for some completely mysterious reason, but since this
//QQ is tempoarary code anyway, we just ignore it for now.
//QQ List_iterator_fast<sp_head> li(thd->spfuns);
//QQ sp_head *sp;
//QQ while ((sp= li++))
//QQ sp->destroy();
thd->spfuns.empty(); thd->spfuns.empty();
} }
......
...@@ -92,7 +92,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type) ...@@ -92,7 +92,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type)
} }
sp_head::sp_head(LEX_STRING *name, LEX *lex) sp_head::sp_head(LEX_STRING *name, LEX *lex)
: m_simple_case(FALSE) : Sql_alloc(), m_simple_case(FALSE)
{ {
const char *dstr = (const char*)lex->buf; const char *dstr = (const char*)lex->buf;
...@@ -126,19 +126,34 @@ sp_head::create(THD *thd) ...@@ -126,19 +126,34 @@ sp_head::create(THD *thd)
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
void
sp_head::destroy()
{
delete_dynamic(&m_instr);
m_pcont->destroy();
}
int int
sp_head::execute(THD *thd) sp_head::execute(THD *thd)
{ {
DBUG_ENTER("sp_head::execute"); DBUG_ENTER("sp_head::execute");
char *olddbname; char olddbname[128];
char *olddbptr= thd->db; char *olddbptr= thd->db;
int ret= 0; int ret= 0;
uint ip= 0; uint ip= 0;
LINT_INIT(olddbname);
if (olddbptr) if (olddbptr)
olddbname= my_strdup(olddbptr, MYF(MY_WME)); {
uint i= 0;
char *p= olddbptr;
/* Fast inline strncpy without padding... */
while (*p && i < sizeof(olddbname))
olddbname[i++]= *p++;
if (i == sizeof(olddbname))
i-= 1; // QQ Error or warning for truncate?
olddbname[i]= '\0';
}
do do
{ {
...@@ -156,13 +171,12 @@ sp_head::execute(THD *thd) ...@@ -156,13 +171,12 @@ sp_head::execute(THD *thd)
ret= -1; ret= -1;
/* If the DB has changed, the pointer has changed too, but the /* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */ original thd->db will then have been freed */
if (olddbptr && olddbptr != thd->db && olddbname) if (olddbptr && olddbptr != thd->db)
{ {
/* QQ Maybe we should issue some special error message or warning here, /* QQ Maybe we should issue some special error message or warning here,
if this fails?? */ if this fails?? */
if (! thd->killed) if (! thd->killed)
ret= mysql_change_db(thd, olddbname); ret= mysql_change_db(thd, olddbname);
my_free(olddbname, MYF(0));
} }
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -399,7 +413,7 @@ sp_head::restore_lex(THD *thd) ...@@ -399,7 +413,7 @@ sp_head::restore_lex(THD *thd)
void void
sp_head::push_backpatch(sp_instr *i, sp_label_t *lab) sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
{ {
bp_t *bp= (bp_t *)my_malloc(sizeof(bp_t), MYF(MY_WME)); bp_t *bp= (bp_t *)sql_alloc(sizeof(bp_t));
if (bp) if (bp)
{ {
......
...@@ -52,21 +52,15 @@ class sp_head : public Sql_alloc ...@@ -52,21 +52,15 @@ class sp_head : public Sql_alloc
List<char *> m_tables; // Used tables. List<char *> m_tables; // Used tables.
#endif #endif
static void *operator new(size_t size)
{
return (void*) sql_alloc((uint) size);
}
static void operator delete(void *ptr, size_t size)
{
/* Empty */
}
sp_head(LEX_STRING *name, LEX *lex); sp_head(LEX_STRING *name, LEX *lex);
int int
create(THD *thd); create(THD *thd);
// Free memory
void
destroy();
int int
execute_function(THD *thd, Item **args, uint argcount, Item **resp); execute_function(THD *thd, Item **args, uint argcount, Item **resp);
...@@ -134,11 +128,13 @@ class sp_head : public Sql_alloc ...@@ -134,11 +128,13 @@ class sp_head : public Sql_alloc
inline sp_instr * inline sp_instr *
get_instr(uint i) get_instr(uint i)
{ {
sp_instr *in= NULL; sp_instr *ip;
if (i < m_instr.elements) if (i < m_instr.elements)
get_dynamic(&m_instr, (gptr)&in, i); get_dynamic(&m_instr, (gptr)&ip, i);
return in; else
ip= NULL;
return ip;
} }
int int
......
...@@ -27,30 +27,20 @@ ...@@ -27,30 +27,20 @@
#include "sp_head.h" #include "sp_head.h"
sp_pcontext::sp_pcontext() sp_pcontext::sp_pcontext()
: m_params(0), m_framesize(0), m_i(0), m_genlab(0) : Sql_alloc(), m_params(0), m_framesize(0), m_genlab(0)
{ {
m_pvar_size = 16; VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
m_pvar = (sp_pvar_t *)my_malloc(m_pvar_size * sizeof(sp_pvar_t), MYF(MY_WME));
if (m_pvar)
memset(m_pvar, 0, m_pvar_size * sizeof(sp_pvar_t));
m_label.empty(); m_label.empty();
} }
void void
sp_pcontext::grow() sp_pcontext::destroy()
{ {
uint sz = m_pvar_size + 8; delete_dynamic(&m_pvar);
sp_pvar_t *a = (sp_pvar_t *)my_realloc((char *)m_pvar, m_label.empty();
sz * sizeof(sp_pvar_t),
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
if (a)
{
m_pvar_size = sz;
m_pvar = a;
}
} }
/* This does a linear search (from newer to older variables, in case /* This does a linear search (from newer to older variables, in case
** we have shadowed names). ** we have shadowed names).
** It's possible to have a more efficient allocation and search method, ** It's possible to have a more efficient allocation and search method,
...@@ -61,19 +51,20 @@ sp_pcontext::grow() ...@@ -61,19 +51,20 @@ sp_pcontext::grow()
sp_pvar_t * sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name) sp_pcontext::find_pvar(LEX_STRING *name)
{ {
uint i = m_i; uint i = m_pvar.elements;
while (i-- > 0) while (i-- > 0)
{ {
uint len= (m_pvar[i].name.length > name->length ? sp_pvar_t *p= find_pvar(i);
m_pvar[i].name.length : name->length); uint len= (p->name.length > name->length ?
p->name.length : name->length);
if (my_strncasecmp(system_charset_info, if (my_strncasecmp(system_charset_info,
name->str, name->str,
m_pvar[i].name.str, p->name.str,
len) == 0) len) == 0)
{ {
return m_pvar + i; return p;
} }
} }
return NULL; return NULL;
...@@ -83,26 +74,26 @@ void ...@@ -83,26 +74,26 @@ void
sp_pcontext::push(LEX_STRING *name, enum enum_field_types type, sp_pcontext::push(LEX_STRING *name, enum enum_field_types type,
sp_param_mode_t mode) sp_param_mode_t mode)
{ {
if (m_i >= m_pvar_size) sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t));
grow();
if (m_i < m_pvar_size) if (p)
{ {
if (m_i == m_framesize) if (m_pvar.elements == m_framesize)
m_framesize += 1; m_framesize += 1;
m_pvar[m_i].name.str= name->str; p->name.str= name->str;
m_pvar[m_i].name.length= name->length, p->name.length= name->length;
m_pvar[m_i].type= type; p->type= type;
m_pvar[m_i].mode= mode; p->mode= mode;
m_pvar[m_i].offset= m_i; p->offset= m_pvar.elements;
m_pvar[m_i].isset= (mode == sp_param_out ? FALSE : TRUE); p->isset= (mode == sp_param_out ? FALSE : TRUE);
m_i += 1; insert_dynamic(&m_pvar, (gptr)&p);
} }
} }
sp_label_t * sp_label_t *
sp_pcontext::push_label(char *name, uint ip) sp_pcontext::push_label(char *name, uint ip)
{ {
sp_label_t *lab = (sp_label_t *)my_malloc(sizeof(sp_label_t), MYF(MY_WME)); sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
if (lab) if (lab)
{ {
......
...@@ -53,6 +53,10 @@ class sp_pcontext : public Sql_alloc ...@@ -53,6 +53,10 @@ class sp_pcontext : public Sql_alloc
sp_pcontext(); sp_pcontext();
// Free memory
void
destroy();
inline uint inline uint
max_framesize() max_framesize()
{ {
...@@ -62,7 +66,7 @@ class sp_pcontext : public Sql_alloc ...@@ -62,7 +66,7 @@ class sp_pcontext : public Sql_alloc
inline uint inline uint
current_framesize() current_framesize()
{ {
return m_i; return m_pvar.elements;
} }
inline uint inline uint
...@@ -75,21 +79,25 @@ class sp_pcontext : public Sql_alloc ...@@ -75,21 +79,25 @@ class sp_pcontext : public Sql_alloc
inline void inline void
set_params() set_params()
{ {
m_params= m_i; m_params= m_pvar.elements;
} }
inline void inline void
set_type(uint i, enum enum_field_types type) set_type(uint i, enum enum_field_types type)
{ {
if (i < m_i) sp_pvar_t *p= find_pvar(i);
m_pvar[i].type= type;
if (p)
p->type= type;
} }
inline void inline void
set_isset(uint i, my_bool val) set_isset(uint i, my_bool val)
{ {
if (i < m_i) sp_pvar_t *p= find_pvar(i);
m_pvar[i].isset= val;
if (p)
p->isset= val;
} }
void void
...@@ -99,8 +107,8 @@ class sp_pcontext : public Sql_alloc ...@@ -99,8 +107,8 @@ class sp_pcontext : public Sql_alloc
inline void inline void
pop(uint num = 1) pop(uint num = 1)
{ {
if (num < m_i) while (num--)
m_i -= num; pop_dynamic(&m_pvar);
} }
// Find by name // Find by name
...@@ -111,9 +119,13 @@ class sp_pcontext : public Sql_alloc ...@@ -111,9 +119,13 @@ class sp_pcontext : public Sql_alloc
sp_pvar_t * sp_pvar_t *
find_pvar(uint i) find_pvar(uint i)
{ {
if (i >= m_i) sp_pvar_t *p;
return NULL;
return m_pvar+i; if (i < m_pvar.elements)
get_dynamic(&m_pvar, (gptr)&p, i);
else
p= NULL;
return p;
} }
sp_label_t * sp_label_t *
...@@ -138,13 +150,8 @@ class sp_pcontext : public Sql_alloc ...@@ -138,13 +150,8 @@ class sp_pcontext : public Sql_alloc
uint m_params; // The number of parameters uint m_params; // The number of parameters
uint m_framesize; // The maximum framesize uint m_framesize; // The maximum framesize
uint m_i; // The current index (during parsing)
sp_pvar_t *m_pvar;
uint m_pvar_size; // Current size of m_pvar.
void DYNAMIC_ARRAY m_pvar;
grow();
List<sp_label_t> m_label; // The label list List<sp_label_t> m_label; // The label list
uint m_genlab; // Gen. label counter uint m_genlab; // Gen. label counter
......
...@@ -191,6 +191,9 @@ THD::THD():user_time(0), is_fatal_error(0), ...@@ -191,6 +191,9 @@ THD::THD():user_time(0), is_fatal_error(0),
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id); randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
} }
/* QQ init the temporary function cache */
spfuns.empty();
} }
...@@ -282,6 +285,10 @@ void THD::cleanup(void) ...@@ -282,6 +285,10 @@ void THD::cleanup(void)
pthread_mutex_unlock(&LOCK_user_locks); pthread_mutex_unlock(&LOCK_user_locks);
ull= 0; ull= 0;
} }
// extern void sp_clear_function_cache(THD *);
// sp_clear_function_cache(this);
cleanup_done=1; cleanup_done=1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -2810,6 +2810,7 @@ mysql_execute_command(THD *thd) ...@@ -2810,6 +2810,7 @@ mysql_execute_command(THD *thd)
sp_head *sph= sp_find_function(thd, &lex->udf.name); sp_head *sph= sp_find_function(thd, &lex->udf.name);
if (sph) if (sph)
{ {
sph->destroy(); // QQ Free memory. Remove this when caching!!!
net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str); net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str);
goto error; goto error;
} }
...@@ -3050,6 +3051,8 @@ mysql_execute_command(THD *thd) ...@@ -3050,6 +3051,8 @@ mysql_execute_command(THD *thd)
thd->net.no_send_ok= nsok; thd->net.no_send_ok= nsok;
#endif #endif
sp->destroy(); // QQ Free memory. Remove this when caching!!!
if (res == 0) if (res == 0)
send_ok(thd); send_ok(thd);
else else
...@@ -3075,6 +3078,7 @@ mysql_execute_command(THD *thd) ...@@ -3075,6 +3078,7 @@ mysql_execute_command(THD *thd)
{ {
/* QQ This is an no-op right now, since we haven't /* QQ This is an no-op right now, since we haven't
put the characteristics in yet. */ put the characteristics in yet. */
sp->destroy(); // QQ Free memory. Remove this when caching!!!
send_ok(thd); send_ok(thd);
} }
} }
......
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