diff options
author | unknown <dlenev@mysql.com> | 2005-03-04 17:46:45 +0300 |
---|---|---|
committer | unknown <dlenev@mysql.com> | 2005-03-04 17:46:45 +0300 |
commit | b1095fb0cd0b42158f6ca3d8f157df5d23bec423 (patch) | |
tree | bff7a84c42deaf288f2aee7fdb2011a47b92ba6c /sql/sp.cc | |
parent | d6949b3e9f8164e28bb24b7c1d948cdce12db005 (diff) | |
parent | ac9f68b9fac716ebc09b9f31b4348b0db135519b (diff) | |
download | mariadb-git-b1095fb0cd0b42158f6ca3d8f157df5d23bec423.tar.gz |
Manual merge SP-locking improvements patch with current tree.
mysql-test/r/mysqldump.result:
Auto merged
mysql-test/r/sp.result:
Auto merged
mysql-test/t/mysqldump.test:
Auto merged
mysql-test/t/sp.test:
Auto merged
sql/item_func.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sp.cc:
Auto merged
sql/sp_rcontext.cc:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/sql_view.cc:
Auto merged
sql/table.h:
Auto merged
sql/sp_head.cc:
Manual merge.
sql/sql_class.cc:
Manual merge.
sql/sql_parse.cc:
Manual merge.
sql/sql_yacc.yy:
Manual merge.
Diffstat (limited to 'sql/sp.cc')
-rw-r--r-- | sql/sp.cc | 189 |
1 files changed, 135 insertions, 54 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index a57d90dbf7a..8b8e8897180 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -720,8 +720,29 @@ sp_drop_db_routines(THD *thd, char *db) PROCEDURE ******************************************************************************/ +/* + Obtain object representing stored procedure by its name from + stored procedures cache and looking into mysql.proc if needed. + + SYNOPSIS + sp_find_procedure() + thd - thread context + name - name of procedure + cache_only - if true perform cache-only lookup + (Don't look in mysql.proc). + + TODO + We should consider merging of sp_find_procedure() and + sp_find_function() into one sp_find_routine() function + (the same applies to other similarly paired functions). + + RETURN VALUE + Non-0 pointer to sp_head object for the procedure, or + 0 - in case of error. +*/ + sp_head * -sp_find_procedure(THD *thd, sp_name *name) +sp_find_procedure(THD *thd, sp_name *name, bool cache_only) { sp_head *sp; DBUG_ENTER("sp_find_procedure"); @@ -729,7 +750,7 @@ sp_find_procedure(THD *thd, sp_name *name) name->m_db.length, name->m_db.str, name->m_name.length, name->m_name.str)); - if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name))) + if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)) && !cache_only) { if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK) sp_cache_insert(&thd->sp_proc_cache, sp); @@ -855,6 +876,25 @@ sp_show_status_procedure(THD *thd, const char *wild) FUNCTION ******************************************************************************/ +/* + Obtain object representing stored function by its name from + stored functions cache and looking into mysql.proc if needed. + + SYNOPSIS + sp_find_function() + thd - thread context + name - name of function + cache_only - if true perform cache-only lookup + (Don't look in mysql.proc). + + NOTE + See TODO section for sp_find_procedure(). + + RETURN VALUE + Non-0 pointer to sp_head object for the function, or + 0 - in case of error. +*/ + sp_head * sp_find_function(THD *thd, sp_name *name, bool cache_only) { @@ -988,79 +1028,120 @@ sp_add_to_hash(HASH *h, sp_name *fun) } -void +/* + Merge contents of two hashes containing LEX_STRING's + + SYNOPSIS + sp_merge_hash() + dst - hash to which elements should be added + src - hash from which elements merged + + RETURN VALUE + TRUE - if we have added some new elements to destination hash. + FALSE - there were no new elements in src. +*/ + +bool sp_merge_hash(HASH *dst, HASH *src) { + bool res= FALSE; for (uint i=0 ; i < src->records ; i++) { LEX_STRING *ls= (LEX_STRING *)hash_element(src, i); if (! hash_search(dst, (byte *)ls->str, ls->length)) + { my_hash_insert(dst, (byte *)ls); + res= TRUE; + } } + return res; } -int -sp_cache_routines(THD *thd, LEX *lex, int type) +/* + Cache all routines implicitly or explicitly used by query + (or whatever object is represented by LEX). + + SYNOPSIS + sp_cache_routines() + thd - thread context + lex - LEX representing query + + NOTE + If some function is missing this won't be reported here. + Instead this fact will be discovered during query execution. + + TODO + Currently if after passing through routine hashes we discover + that we have added something to them, we do one more pass to + process all routines which were missed on previous pass because + of these additions. We can avoid this if along with hashes + we use lists holding routine names and iterate other these + lists instead of hashes (since addition to the end of list + does not reorder elements in it). +*/ + +void +sp_cache_routines(THD *thd, LEX *lex) { - HASH *h= (type == TYPE_ENUM_FUNCTION ? &lex->spfuns : &lex->spprocs); - int ret= 0; + bool routines_added= TRUE; - for (uint i=0 ; i < h->records ; i++) + DBUG_ENTER("sp_cache_routines"); + + while (routines_added) { - LEX_STRING *ls= (LEX_STRING *)hash_element(h, i); - sp_name name(*ls); + routines_added= FALSE; - name.m_qname= *ls; - if (! sp_cache_lookup((type == TYPE_ENUM_FUNCTION ? - &thd->sp_func_cache : &thd->sp_proc_cache), - &name)) + for (int type= TYPE_ENUM_FUNCTION; type < TYPE_ENUM_TRIGGER; type++) { - sp_head *sp; - LEX *oldlex= thd->lex; - LEX *newlex= new st_lex; - - thd->lex= newlex; - newlex->proc_table= oldlex->proc_table; // hint if mysql.oper is opened - newlex->current_select= NULL; - name.m_name.str= strchr(name.m_qname.str, '.'); - name.m_db.length= name.m_name.str - name.m_qname.str; - name.m_db.str= strmake_root(thd->mem_root, - name.m_qname.str, name.m_db.length); - name.m_name.str+= 1; - name.m_name.length= name.m_qname.length - name.m_db.length - 1; - - if (db_find_routine(thd, type, &name, &sp) == SP_OK) - { - if (type == TYPE_ENUM_FUNCTION) - sp_cache_insert(&thd->sp_func_cache, sp); - else - sp_cache_insert(&thd->sp_proc_cache, sp); - ret= sp_cache_routines(thd, newlex, TYPE_ENUM_FUNCTION); - if (!ret) - { - sp_merge_hash(&lex->spfuns, &newlex->spfuns); - ret= sp_cache_routines(thd, newlex, TYPE_ENUM_PROCEDURE); - } - if (!ret) - { - sp_merge_hash(&lex->spprocs, &newlex->spprocs); - sp_merge_table_hash(&lex->sptabs, &sp->m_sptabs); - } - delete newlex; - thd->lex= oldlex; - if (ret) - break; - } - else + HASH *h= (type == TYPE_ENUM_FUNCTION ? &lex->spfuns : &lex->spprocs); + + for (uint i=0 ; i < h->records ; i++) { - delete newlex; - thd->lex= oldlex; + LEX_STRING *ls= (LEX_STRING *)hash_element(h, i); + sp_name name(*ls); + sp_head *sp; + + name.m_qname= *ls; + if (!(sp= sp_cache_lookup((type == TYPE_ENUM_FUNCTION ? + &thd->sp_func_cache : &thd->sp_proc_cache), + &name))) + { + LEX *oldlex= thd->lex; + LEX *newlex= new st_lex; + + thd->lex= newlex; + /* Pass hint pointer to mysql.proc table */ + newlex->proc_table= oldlex->proc_table; + newlex->current_select= NULL; + name.m_name.str= strchr(name.m_qname.str, '.'); + name.m_db.length= name.m_name.str - name.m_qname.str; + name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str, + name.m_db.length); + name.m_name.str+= 1; + name.m_name.length= name.m_qname.length - name.m_db.length - 1; + + if (db_find_routine(thd, type, &name, &sp) == SP_OK) + { + if (type == TYPE_ENUM_FUNCTION) + sp_cache_insert(&thd->sp_func_cache, sp); + else + sp_cache_insert(&thd->sp_proc_cache, sp); + } + delete newlex; + thd->lex= oldlex; + } + + if (sp) + { + routines_added|= sp_merge_hash(&lex->spfuns, &sp->m_spfuns); + routines_added|= sp_merge_hash(&lex->spprocs, &sp->m_spprocs); + } } } } - return ret; + DBUG_VOID_RETURN; } /* |