diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4833b152f07a621909cdc65764fbd34f618e9b3d..1ff6d1552f4d36f25aae43dfa06dd6d36717b6d4 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -20,6 +20,7 @@ delete from t1; drop procedure foo42; create procedure u() use sptmp; +drop database if exists sptmp; create database sptmp; use test; call u(); diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 95b3e4732a9d0e57ada4136ed5df4bf43ed39e55..a12e06f24b1694a4a12687ceb1cbcf6ec181b521 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -35,6 +35,9 @@ drop procedure foo42; create procedure u() use sptmp; +--disable_warnings +drop database if exists sptmp; +--enable_warnings create database sptmp; use test; call u(); diff --git a/sql/sp.cc b/sql/sp.cc index 5eb12c9fae5f5e2656182fb9aabe65379fa8e253..c8dc328ced147373ca5eb1a253ef5097713d5580 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -19,8 +19,8 @@ #include "sp.h" #include "sp_head.h" - static sp_head * - sp_find_cached_function(THD *thd, char *name, uint namelen); +static sp_head * +sp_find_cached_function(THD *thd, char *name, uint namelen); /* * @@ -373,6 +373,13 @@ sp_cache_functions(THD *thd, LEX *lex) void 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(); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 61cf322876030f90761cd4b4649634fa778e4536..036207796c36dc650a4de8fcaacb65e722399554 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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) - : m_simple_case(FALSE) + : Sql_alloc(), m_simple_case(FALSE) { const char *dstr = (const char*)lex->buf; @@ -126,19 +126,34 @@ sp_head::create(THD *thd) DBUG_RETURN(ret); } +void +sp_head::destroy() +{ + delete_dynamic(&m_instr); + m_pcont->destroy(); +} int sp_head::execute(THD *thd) { DBUG_ENTER("sp_head::execute"); - char *olddbname; + char olddbname[128]; char *olddbptr= thd->db; int ret= 0; uint ip= 0; - LINT_INIT(olddbname); 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 { @@ -156,13 +171,12 @@ sp_head::execute(THD *thd) ret= -1; /* If the DB has changed, the pointer has changed too, but the 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, if this fails?? */ if (! thd->killed) ret= mysql_change_db(thd, olddbname); - my_free(olddbname, MYF(0)); } DBUG_RETURN(ret); } @@ -399,7 +413,7 @@ sp_head::restore_lex(THD *thd) void 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) { diff --git a/sql/sp_head.h b/sql/sp_head.h index 52cbdc560932c5e8d0617e30f0aef7c0b9d74ef1..840276681a561a0fca3f351b9d76088d3f786a5f 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -52,21 +52,15 @@ class sp_head : public Sql_alloc List<char *> m_tables; // Used tables. #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); int create(THD *thd); + // Free memory + void + destroy(); + int execute_function(THD *thd, Item **args, uint argcount, Item **resp); @@ -134,11 +128,13 @@ class sp_head : public Sql_alloc inline sp_instr * get_instr(uint i) { - sp_instr *in= NULL; + sp_instr *ip; if (i < m_instr.elements) - get_dynamic(&m_instr, (gptr)&in, i); - return in; + get_dynamic(&m_instr, (gptr)&ip, i); + else + ip= NULL; + return ip; } int diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index d59db9b449b4b488f4ca018f92207d00dfe84f65..4d3cf80cd34104c5d3ed7dd79df2a8800cd0a41c 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -27,30 +27,20 @@ #include "sp_head.h" 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; - 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)); + VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); m_label.empty(); } void -sp_pcontext::grow() +sp_pcontext::destroy() { - uint sz = m_pvar_size + 8; - sp_pvar_t *a = (sp_pvar_t *)my_realloc((char *)m_pvar, - sz * sizeof(sp_pvar_t), - MYF(MY_WME | MY_ALLOW_ZERO_PTR)); - - if (a) - { - m_pvar_size = sz; - m_pvar = a; - } + delete_dynamic(&m_pvar); + m_label.empty(); } + /* This does a linear search (from newer to older variables, in case ** we have shadowed names). ** It's possible to have a more efficient allocation and search method, @@ -61,19 +51,20 @@ sp_pcontext::grow() sp_pvar_t * sp_pcontext::find_pvar(LEX_STRING *name) { - uint i = m_i; + uint i = m_pvar.elements; while (i-- > 0) { - uint len= (m_pvar[i].name.length > name->length ? - m_pvar[i].name.length : name->length); + sp_pvar_t *p= find_pvar(i); + uint len= (p->name.length > name->length ? + p->name.length : name->length); if (my_strncasecmp(system_charset_info, name->str, - m_pvar[i].name.str, + p->name.str, len) == 0) { - return m_pvar + i; + return p; } } return NULL; @@ -83,26 +74,26 @@ void sp_pcontext::push(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode) { - if (m_i >= m_pvar_size) - grow(); - if (m_i < m_pvar_size) + sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t)); + + if (p) { - if (m_i == m_framesize) + if (m_pvar.elements == m_framesize) m_framesize += 1; - m_pvar[m_i].name.str= name->str; - m_pvar[m_i].name.length= name->length, - m_pvar[m_i].type= type; - m_pvar[m_i].mode= mode; - m_pvar[m_i].offset= m_i; - m_pvar[m_i].isset= (mode == sp_param_out ? FALSE : TRUE); - m_i += 1; + p->name.str= name->str; + p->name.length= name->length; + p->type= type; + p->mode= mode; + p->offset= m_pvar.elements; + p->isset= (mode == sp_param_out ? FALSE : TRUE); + insert_dynamic(&m_pvar, (gptr)&p); } } sp_label_t * 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) { diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index c5b0f1d410b53e50cfb62347edd07c9d35bccc02..6900e18aa93b01565ae82db4bfd185bf04620fa0 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -53,6 +53,10 @@ class sp_pcontext : public Sql_alloc sp_pcontext(); + // Free memory + void + destroy(); + inline uint max_framesize() { @@ -62,7 +66,7 @@ class sp_pcontext : public Sql_alloc inline uint current_framesize() { - return m_i; + return m_pvar.elements; } inline uint @@ -75,21 +79,25 @@ class sp_pcontext : public Sql_alloc inline void set_params() { - m_params= m_i; + m_params= m_pvar.elements; } inline void set_type(uint i, enum enum_field_types type) { - if (i < m_i) - m_pvar[i].type= type; + sp_pvar_t *p= find_pvar(i); + + if (p) + p->type= type; } inline void set_isset(uint i, my_bool val) { - if (i < m_i) - m_pvar[i].isset= val; + sp_pvar_t *p= find_pvar(i); + + if (p) + p->isset= val; } void @@ -99,8 +107,8 @@ class sp_pcontext : public Sql_alloc inline void pop(uint num = 1) { - if (num < m_i) - m_i -= num; + while (num--) + pop_dynamic(&m_pvar); } // Find by name @@ -111,9 +119,13 @@ class sp_pcontext : public Sql_alloc sp_pvar_t * find_pvar(uint i) { - if (i >= m_i) - return NULL; - return m_pvar+i; + sp_pvar_t *p; + + if (i < m_pvar.elements) + get_dynamic(&m_pvar, (gptr)&p, i); + else + p= NULL; + return p; } sp_label_t * @@ -138,13 +150,8 @@ class sp_pcontext : public Sql_alloc uint m_params; // The number of parameters 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 - grow(); + DYNAMIC_ARRAY m_pvar; List<sp_label_t> m_label; // The label list uint m_genlab; // Gen. label counter diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d5197b6507193ea4aa4948499af5dab7c7c194cb..7247d5bc3d092b3096d8d5b90f4e482598af27d0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -191,6 +191,9 @@ THD::THD():user_time(0), is_fatal_error(0), pthread_mutex_unlock(&LOCK_thread_count); 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); ull= 0; } + + // extern void sp_clear_function_cache(THD *); + // sp_clear_function_cache(this); + cleanup_done=1; DBUG_VOID_RETURN; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cc9c2decf5b8719f5ff9caa98fa7383bd16080e8..4d9cb0729324c1d351e68403b6a9c573ebbef2ad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2810,6 +2810,7 @@ mysql_execute_command(THD *thd) sp_head *sph= sp_find_function(thd, &lex->udf.name); if (sph) { + sph->destroy(); // QQ Free memory. Remove this when caching!!! net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str); goto error; } @@ -3046,6 +3047,8 @@ mysql_execute_command(THD *thd) thd->net.no_send_ok= nsok; #endif + sp->destroy(); // QQ Free memory. Remove this when caching!!! + if (res == 0) send_ok(thd); else @@ -3071,6 +3074,7 @@ mysql_execute_command(THD *thd) { /* QQ This is an no-op right now, since we haven't put the characteristics in yet. */ + sp->destroy(); // QQ Free memory. Remove this when caching!!! send_ok(thd); } }