diff options
-rw-r--r-- | sql/sp.cc | 95 | ||||
-rw-r--r-- | sql/sp.h | 6 | ||||
-rw-r--r-- | sql/sql_class.cc | 19 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 19 |
5 files changed, 69 insertions, 72 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index 79beb78e3e5..ecbe0ff3955 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -22,6 +22,9 @@ static sp_head * sp_find_cached_function(THD *thd, char *name, uint namelen); +static sp_head * +sp_find_cached_procedure(THD *thd, char *name, uint namelen); + /* * * DB storage of Stored PROCEDUREs and FUNCTIONs @@ -254,9 +257,17 @@ sp_find_procedure(THD *thd, LEX_STRING *name) DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); - if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, - name->str, name->length, &sp) != SP_OK) - sp= NULL; + sp= sp_find_cached_procedure(thd, name->str, name->length); + if (! sp) + { + if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, + name->str, name->length, &sp) == SP_OK) + { + HASH *phash= thd->sp_hash+TYPE_ENUM_PROCEDURE-1; + + hash_insert(phash, (const byte*)sp); + } + } DBUG_RETURN(sp); } @@ -280,8 +291,17 @@ sp_drop_procedure(THD *thd, char *name, uint namelen) { DBUG_ENTER("sp_drop_procedure"); DBUG_PRINT("enter", ("name: %*s", namelen, name)); + sp_head *sp; int ret; + sp= sp_find_cached_procedure(thd, name, namelen); + if (sp) + { + HASH *phash= thd->sp_hash+TYPE_ENUM_PROCEDURE-1; + + hash_delete(phash, (byte*)sp); + delete sp; + } ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen); DBUG_RETURN(ret); @@ -331,8 +351,17 @@ sp_drop_function(THD *thd, char *name, uint namelen) { DBUG_ENTER("sp_drop_function"); DBUG_PRINT("enter", ("name: %*s", namelen, name)); + sp_head *sp; int ret; + sp= sp_find_cached_function(thd, name, namelen); + if (sp) + { + HASH *fhash= thd->sp_hash+TYPE_ENUM_FUNCTION-1; + + hash_delete(fhash, (byte*)sp); + delete sp; + } ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen); DBUG_RETURN(ret); @@ -344,9 +373,10 @@ sp_function_exists(THD *thd, LEX_STRING *name) { TABLE *table; bool ret= FALSE; - bool opened; + bool opened= FALSE; - if (db_find_routine_aux(thd, TYPE_ENUM_FUNCTION, + if (sp_find_cached_function(thd, name->str, name->length) || + db_find_routine_aux(thd, TYPE_ENUM_FUNCTION, name->str, name->length, TL_READ, &table, &opened) == SP_OK) { @@ -358,13 +388,6 @@ sp_function_exists(THD *thd, LEX_STRING *name) } -/* - * - * The temporary FUNCTION cache. (QQ This will be rehacked later, but - * it's needed now to make functions work at all.) - * - */ - void sp_add_fun_to_lex(LEX *lex, LEX_STRING fun) { @@ -411,25 +434,22 @@ sp_cache_functions(THD *thd, LEX *lex) char *fn; enum_sql_command cmd= lex->sql_command; int ret= 0; + HASH *fhash= thd->sp_hash+TYPE_ENUM_FUNCTION-1; while ((fn= li++)) { - List_iterator_fast<sp_head> lisp(thd->spfuns); sp_head *sp; + int len= strlen(fn); - while ((sp= lisp++)) - { - if (my_strcasecmp(system_charset_info, fn, sp->name()) == 0) - break; - } - if (sp) + if (hash_search(fhash,(const byte*)fn,len)) continue; - if (db_find_routine(thd, TYPE_ENUM_FUNCTION, fn, strlen(fn), &sp) == SP_OK) + + if (db_find_routine(thd, TYPE_ENUM_FUNCTION, fn, len, &sp) == SP_OK) { ret= sp_cache_functions(thd, thd->lex); if (ret) break; - thd->spfuns.push_back(sp); + hash_insert(fhash,(const byte*)sp); } else { @@ -441,32 +461,23 @@ sp_cache_functions(THD *thd, LEX *lex) return ret; } -void -sp_clear_function_cache(THD *thd) +byte * +hash_get_key_for_sp_head(const byte *ptr, uint *plen, + my_bool first) { - List_iterator_fast<sp_head> li(thd->spfuns); - sp_head *sp; - - while ((sp= li++)) - delete sp; - thd->spfuns.empty(); + return ((sp_head*)ptr)->name(plen); } static sp_head * sp_find_cached_function(THD *thd, char *name, uint namelen) { - List_iterator_fast<sp_head> li(thd->spfuns); - sp_head *sp; - - while ((sp= li++)) - { - uint len; - const uchar *n= (const uchar *)sp->name(&len); + return (sp_head*)hash_search(thd->sp_hash+TYPE_ENUM_FUNCTION-1, + (const byte*)name,namelen); +} - if (my_strnncoll(system_charset_info, - (const uchar *)name, namelen, - n, len) == 0) - break; - } - return sp; +static sp_head * +sp_find_cached_procedure(THD *thd, char *name, uint namelen) +{ + return (sp_head*)hash_search(thd->sp_hash+TYPE_ENUM_PROCEDURE-1, + (const byte*)name,namelen); } @@ -53,15 +53,13 @@ bool sp_function_exists(THD *thd, LEX_STRING *name); -// QQ More temporary stuff until the real cache is implemented. This is -// needed since we have to read the functions before we do anything else. +// This is needed since we have to read the functions before we +// do anything else. void sp_add_fun_to_lex(LEX *lex, LEX_STRING fun); void sp_merge_funs(LEX *dst, LEX *src); int sp_cache_functions(THD *thd, LEX *lex); -void -sp_clear_function_cache(THD *thd); #endif /* _SP_H_ */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c64bb7ff8fa..5ab096b91e4 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -38,6 +38,8 @@ #include <sp_rcontext.h> +byte *hash_get_key_for_sp_head(const byte*,uint*,my_bool); + /* The following is used to initialise Table_ident with a internal table name @@ -155,6 +157,11 @@ THD::THD():user_time(0), is_fatal_error(0), hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, (hash_free_key) free_user_var, 0); + + hash_init(sp_hash,system_charset_info,0,0,0, + hash_get_key_for_sp_head,0,0); + hash_init(sp_hash+1,system_charset_info,0,0,0, + hash_get_key_for_sp_head,0,0); /* For user vars replication*/ if (opt_bin_log) @@ -200,9 +207,6 @@ 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(); } @@ -261,6 +265,10 @@ void THD::change_user(void) hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, (hash_free_key) free_user_var, 0); + hash_init(sp_hash,system_charset_info,0,0,0, + hash_get_key_for_sp_head,0,0); + hash_init(sp_hash+1,system_charset_info,0,0,0, + hash_get_key_for_sp_head,0,0); } @@ -284,6 +292,8 @@ void THD::cleanup(void) close_temporary_tables(this); delete_dynamic(&user_var_events); hash_free(&user_vars); + hash_free(sp_hash); + hash_free(sp_hash+1); if (global_read_lock) unlock_global_read_lock(this); if (ull) @@ -294,9 +304,6 @@ void THD::cleanup(void) 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_class.h b/sql/sql_class.h index 3bb0f348024..cebcdf68391 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -551,7 +551,7 @@ public: bool prepare_command; bool tmp_table_used; sp_rcontext *spcont; // SP runtime context - List<sp_head> spfuns; // SP FUNCTIONs + HASH sp_hash[2]; // hash for SP PROCEDURES and FUNCTIONS /* If we do a purge of binary logs, log index info of the threads diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b29e1734302..6a02383e984 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1527,13 +1527,6 @@ restore_user: VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory - /* - Clear the SP function cache after each statement (QQ this is a temporary - solution; caching will be rehacked later). - Note: Must do this before we free_root. - */ - sp_clear_function_cache(thd); - free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); DBUG_RETURN(error); } @@ -2829,7 +2822,6 @@ mysql_execute_command(THD *thd) sp_head *sph= sp_find_function(thd, &lex->udf.name); if (sph) { - delete sph; // QQ Free memory. Remove this when caching!!! net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str); goto error; } @@ -3033,18 +3025,12 @@ mysql_execute_command(THD *thd) { case SP_OK: send_ok(thd); - delete lex->sphead; // QQ Free memory. Remove this when caching!!! - lex->sphead= NULL; break; case SP_WRITE_ROW_FAILED: net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name); - delete lex->sphead; // QQ Free memory. Remove this when caching!!! - lex->sphead= NULL; goto error; default: net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name); - delete lex->sphead; // QQ Free memory. Remove this when caching!!! - lex->sphead= NULL; goto error; } break; @@ -3068,7 +3054,6 @@ mysql_execute_command(THD *thd) if (tables && ((res= check_table_access(thd, SELECT_ACL, tables)) || (res= open_and_lock_tables(thd, tables)))) { - delete sp; // Free memory. Remove this when caching!!! break; } fix_tables_pointers(lex->all_selects_list); @@ -3087,7 +3072,6 @@ mysql_execute_command(THD *thd) #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; #endif - delete sp; // QQ Free memory. Remove this when caching!!! goto error; } smrx= thd->server_status & SERVER_MORE_RESULTS_EXISTS; @@ -3105,8 +3089,6 @@ mysql_execute_command(THD *thd) thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS; } - delete sp; // QQ Free memory. Remove this when caching!!! - if (res == 0) send_ok(thd); else @@ -3132,7 +3114,6 @@ mysql_execute_command(THD *thd) { /* QQ This is an no-op right now, since we haven't put the characteristics in yet. */ - delete sp; // QQ Free memory. Remove this when caching!!! send_ok(thd); } break; |