Commit 1d3c703d authored by pem@mysql.com's avatar pem@mysql.com

SP cache (WL#730). (Mostly by vva, additions by pem.)

parent 4006e958
......@@ -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));
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)
sp= NULL;
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_ */
......@@ -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
......@@ -156,6 +158,11 @@ THD::THD():user_time(0), is_fatal_error(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)
my_init_dynamic_array(&user_var_events,
......@@ -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;
}
......
......@@ -551,7 +551,7 @@ class THD :public ilink
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
......
......@@ -1527,13 +1527,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
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;
......
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