Commit c908b555 authored by pem@mysql.com's avatar pem@mysql.com

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.
parent 38c459e6
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
*/ */
// *openeed=true means we opened ourselves // *opened=true means we opened ourselves
static int static int
db_find_routine_aux(THD *thd, int type, char *name, uint namelen, db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
enum thr_lock_type ltype, TABLE **tablep, bool *opened) 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) ...@@ -99,7 +99,6 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
char buff[65]; char buff[65];
String str(buff, sizeof(buff), &my_charset_bin); 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); ret= db_find_routine_aux(thd, type, name, namelen, TL_READ, &table, &opened);
if (ret != SP_OK) if (ret != SP_OK)
goto done; goto done;
...@@ -109,7 +108,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -109,7 +108,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
goto done; goto done;
} }
//Get additional information // Get additional information
if ((creator= get_field(&thd->mem_root, table->field[3])) == NULL) if ((creator= get_field(&thd->mem_root, table->field[3])) == NULL)
{ {
ret= SP_GET_FIELD_FAILED; ret= SP_GET_FIELD_FAILED;
...@@ -377,74 +376,75 @@ sp_function_exists(THD *thd, LEX_STRING *name) ...@@ -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 void
sp_add_fun_to_lex(LEX *lex, LEX_STRING fun) sp_add_fun_to_lex(LEX *lex, LEX_STRING fun)
{ {
List_iterator_fast<char> li(lex->spfuns); if (! hash_search(&lex->spfuns, (byte *)fun.str, fun.length))
char *fn;
while ((fn= li++))
{ {
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, hash_insert(&lex->spfuns, (byte *)ls);
(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);
} }
} }
void void
sp_merge_funs(LEX *dst, LEX *src) sp_merge_funs(LEX *dst, LEX *src)
{ {
List_iterator_fast<char> li(src->spfuns); for (uint i=0 ; i < src->spfuns.records ; i++)
char *fn;
while ((fn= li++))
{ {
LEX_STRING lx; LEX_STRING *ls= (LEX_STRING *)hash_element(&src->spfuns, i);
lx.str= fn; lx.length= strlen(fn); if (! hash_search(&dst->spfuns, (byte *)ls->str, ls->length))
sp_add_fun_to_lex(dst, lx); 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 int
sp_cache_functions(THD *thd, LEX *lex) sp_cache_functions(THD *thd, LEX *lex)
{ {
List_iterator<char> li(lex->spfuns); HASH *h= &lex->spfuns;
char *fn;
enum_sql_command cmd= lex->sql_command;
int ret= 0; int ret= 0;
while ((fn= li++)) for (uint i=0 ; i < h->records ; i++)
{ {
sp_head *sp; LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
int len= strlen(fn);
if (thd->sp_func_cache->lookup(fn, len)) if (! thd->sp_func_cache->lookup(ls->str, ls->length))
continue; {
sp_head *sp;
LEX *oldlex= thd->lex;
LEX *newlex= new st_lex;
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) if (ret)
break; break;
thd->sp_func_cache->insert(sp); thd->sp_func_cache->insert(sp);
} }
else 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; ret= 1;
break;
}
} }
} }
lex->sql_command= cmd;
return ret; return ret;
} }
...@@ -99,7 +99,6 @@ public: ...@@ -99,7 +99,6 @@ public:
// Restores lex in 'thd' from our copy, but keeps some status from the // Restores lex in 'thd' from our copy, but keeps some status from the
// one in 'thd', like ptr, tables, fields, etc. // one in 'thd', like ptr, tables, fields, etc.
// If 'delete_lex' is true, we delete the current lex.
void void
restore_lex(THD *thd); restore_lex(THD *thd);
...@@ -162,6 +161,7 @@ private: ...@@ -162,6 +161,7 @@ private:
MEM_ROOT m_thd_root; // Temp. store for thd's mem_root MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
Item *m_free_list; // Where the items go Item *m_free_list; // Where the items go
THD *m_thd; // Set if we have reset mem_root THD *m_thd; // Set if we have reset mem_root
LEX_STRING m_name; LEX_STRING m_name;
LEX_STRING m_defstr; LEX_STRING m_defstr;
LEX_STRING m_comment; LEX_STRING m_comment;
......
...@@ -126,7 +126,12 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) ...@@ -126,7 +126,12 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->sql_command=SQLCOM_END; lex->sql_command=SQLCOM_END;
lex->sphead= NULL; lex->sphead= NULL;
lex->spcont= 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; return lex;
} }
......
...@@ -497,9 +497,19 @@ typedef struct st_lex ...@@ -497,9 +497,19 @@ typedef struct st_lex
sp_head *sphead; sp_head *sphead;
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */ bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
sp_pcontext *spcont; 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() inline void uncacheable()
{ {
safe_to_cache_query= 0; safe_to_cache_query= 0;
......
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