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.
This commit is contained in:
parent
60e7ad754f
commit
2eebaf7bd3
@ -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;
|
|||||||
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();
|
||||||
|
@ -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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@ public:
|
|||||||
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 @@ private:
|
|||||||
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,29 +27,19 @@
|
|||||||
#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).
|
||||||
@ -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
|
|||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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 @@ private:
|
|||||||
|
|
||||||
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;
|
DYNAMIC_ARRAY m_pvar;
|
||||||
uint m_pvar_size; // Current size of m_pvar.
|
|
||||||
|
|
||||||
void
|
|
||||||
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),
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
/* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user