Fixed the old kludge for pre-loading functions and made it more efficient
using a hash table instead (and made it work with lex pointers). Some additional code cleanup too. sql/sp.cc: Fixed the old kludge for pre-loading functions and made it more efficient using a hash table instead (and made it work with lex pointers). Some additional cleanup of comments too. sql/sp_head.h: Some additional code cleanup. sql/sql_lex.cc: Use hash table for function pre-loading (isntead of list). sql/sql_lex.h: Use hash table for function pre-loading (isntead of list).
This commit is contained in:
parent
d17a3ae1f4
commit
a6b9cbd65c
76
sql/sp.cc
76
sql/sp.cc
@ -26,7 +26,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// *openeed=true means we opened ourselves
|
||||
// *opened=true means we opened ourselves
|
||||
static int
|
||||
db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
|
||||
enum thr_lock_type ltype, TABLE **tablep, bool *opened)
|
||||
@ -99,7 +99,6 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
|
||||
char buff[65];
|
||||
String str(buff, sizeof(buff), &my_charset_bin);
|
||||
|
||||
// QQ Set up our own mem_root here???
|
||||
ret= db_find_routine_aux(thd, type, name, namelen, TL_READ, &table, &opened);
|
||||
if (ret != SP_OK)
|
||||
goto done;
|
||||
@ -109,7 +108,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
|
||||
goto done;
|
||||
}
|
||||
|
||||
//Get additional information
|
||||
// Get additional information
|
||||
if ((creator= get_field(&thd->mem_root, table->field[3])) == NULL)
|
||||
{
|
||||
ret= SP_GET_FIELD_FAILED;
|
||||
@ -377,74 +376,75 @@ sp_function_exists(THD *thd, LEX_STRING *name)
|
||||
}
|
||||
|
||||
|
||||
byte *
|
||||
sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first)
|
||||
{
|
||||
LEX_STRING *lsp= (LEX_STRING *)ptr;
|
||||
*plen= lsp->length;
|
||||
return (byte *)lsp->str;
|
||||
}
|
||||
|
||||
void
|
||||
sp_add_fun_to_lex(LEX *lex, LEX_STRING fun)
|
||||
{
|
||||
List_iterator_fast<char> li(lex->spfuns);
|
||||
char *fn;
|
||||
|
||||
while ((fn= li++))
|
||||
if (! hash_search(&lex->spfuns, (byte *)fun.str, fun.length))
|
||||
{
|
||||
uint len= strlen(fn);
|
||||
LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING));
|
||||
ls->str= sql_strmake(fun.str, fun.length);
|
||||
ls->length= fun.length;
|
||||
|
||||
if (my_strnncoll(system_charset_info,
|
||||
(const uchar *)fn, len,
|
||||
(const uchar *)fun.str, fun.length) == 0)
|
||||
break;
|
||||
}
|
||||
if (! fn)
|
||||
{
|
||||
char *s= sql_strmake(fun.str, fun.length);
|
||||
lex->spfuns.push_back(s);
|
||||
hash_insert(&lex->spfuns, (byte *)ls);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sp_merge_funs(LEX *dst, LEX *src)
|
||||
{
|
||||
List_iterator_fast<char> li(src->spfuns);
|
||||
char *fn;
|
||||
|
||||
while ((fn= li++))
|
||||
for (uint i=0 ; i < src->spfuns.records ; i++)
|
||||
{
|
||||
LEX_STRING lx;
|
||||
LEX_STRING *ls= (LEX_STRING *)hash_element(&src->spfuns, i);
|
||||
|
||||
lx.str= fn; lx.length= strlen(fn);
|
||||
sp_add_fun_to_lex(dst, lx);
|
||||
if (! hash_search(&dst->spfuns, (byte *)ls->str, ls->length))
|
||||
hash_insert(&dst->spfuns, (byte *)ls);
|
||||
}
|
||||
}
|
||||
|
||||
/* QQ Not terribly efficient right now, but it'll do for starters.
|
||||
We should actually open the mysql.proc table just once. */
|
||||
int
|
||||
sp_cache_functions(THD *thd, LEX *lex)
|
||||
{
|
||||
List_iterator<char> li(lex->spfuns);
|
||||
char *fn;
|
||||
enum_sql_command cmd= lex->sql_command;
|
||||
HASH *h= &lex->spfuns;
|
||||
int ret= 0;
|
||||
|
||||
while ((fn= li++))
|
||||
for (uint i=0 ; i < h->records ; i++)
|
||||
{
|
||||
LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
|
||||
|
||||
if (! thd->sp_func_cache->lookup(ls->str, ls->length))
|
||||
{
|
||||
sp_head *sp;
|
||||
int len= strlen(fn);
|
||||
LEX *oldlex= thd->lex;
|
||||
LEX *newlex= new st_lex;
|
||||
|
||||
if (thd->sp_func_cache->lookup(fn, len))
|
||||
continue;
|
||||
|
||||
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, fn, len, &sp) == SP_OK)
|
||||
thd->lex= newlex;
|
||||
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, ls->str, ls->length, &sp)
|
||||
== SP_OK)
|
||||
{
|
||||
ret= sp_cache_functions(thd, thd->lex);
|
||||
ret= sp_cache_functions(thd, newlex);
|
||||
delete newlex;
|
||||
thd->lex= oldlex;
|
||||
if (ret)
|
||||
break;
|
||||
thd->sp_func_cache->insert(sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_error(thd, ER_SP_DOES_NOT_EXIST);
|
||||
delete newlex;
|
||||
thd->lex= oldlex;
|
||||
net_printf(thd, ER_SP_DOES_NOT_EXIST, "FUNCTION", ls->str);
|
||||
ret= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lex->sql_command= cmd;
|
||||
return ret;
|
||||
}
|
||||
|
@ -99,7 +99,6 @@ public:
|
||||
|
||||
// Restores lex in 'thd' from our copy, but keeps some status from the
|
||||
// one in 'thd', like ptr, tables, fields, etc.
|
||||
// If 'delete_lex' is true, we delete the current lex.
|
||||
void
|
||||
restore_lex(THD *thd);
|
||||
|
||||
@ -162,6 +161,7 @@ private:
|
||||
MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
|
||||
Item *m_free_list; // Where the items go
|
||||
THD *m_thd; // Set if we have reset mem_root
|
||||
|
||||
LEX_STRING m_name;
|
||||
LEX_STRING m_defstr;
|
||||
LEX_STRING m_comment;
|
||||
|
@ -126,7 +126,12 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
|
||||
lex->sql_command=SQLCOM_END;
|
||||
lex->sphead= NULL;
|
||||
lex->spcont= NULL;
|
||||
lex->spfuns.empty();
|
||||
|
||||
extern byte *sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first);
|
||||
hash_free(&lex->spfuns);
|
||||
hash_init(&lex->spfuns, system_charset_info, 0, 0, 0,
|
||||
sp_lex_spfuns_key, 0, 0);
|
||||
|
||||
return lex;
|
||||
}
|
||||
|
||||
|
@ -497,9 +497,19 @@ typedef struct st_lex
|
||||
sp_head *sphead;
|
||||
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
|
||||
sp_pcontext *spcont;
|
||||
List<char> spfuns; /* Called functions */
|
||||
HASH spfuns; /* Called functions */
|
||||
|
||||
st_lex()
|
||||
{
|
||||
bzero((char *)&spfuns, sizeof(spfuns));
|
||||
}
|
||||
|
||||
~st_lex()
|
||||
{
|
||||
if (spfuns.array.buffer)
|
||||
hash_free(&spfuns);
|
||||
}
|
||||
|
||||
st_lex() {}
|
||||
inline void uncacheable()
|
||||
{
|
||||
safe_to_cache_query= 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user