diff options
Diffstat (limited to 'sql/sp.cc')
-rw-r--r-- | sql/sp.cc | 168 |
1 files changed, 31 insertions, 137 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index e45a360e85b..4485019be4a 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -68,13 +68,16 @@ bool mysql_proc_table_exists= 1; SYNOPSIS close_proc_table() - thd Thread context + thd Thread context + backup Pointer to Open_tables_state instance which holds + information about tables which were open before we + decided to access mysql.proc. */ -static void close_proc_table(THD *thd) +void close_proc_table(THD *thd, Open_tables_state *backup) { close_thread_tables(thd); - thd->pop_open_tables_state(); + thd->restore_backup_open_tables_state(backup); } @@ -83,7 +86,10 @@ static void close_proc_table(THD *thd) SYNOPSIS open_proc_table_for_read() - thd Thread context + thd Thread context + backup Pointer to Open_tables_state instance where information about + currently open tables will be saved, and from which will be + restored when we will end work with mysql.proc. NOTES Thanks to restrictions which we put on opening and locking of @@ -97,11 +103,10 @@ static void close_proc_table(THD *thd) # Pointer to TABLE object of mysql.proc */ -static TABLE *open_proc_table_for_read(THD *thd) +TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) { TABLE_LIST tables; TABLE *table; - bool old_open_tables= thd->open_tables != 0; bool refresh; DBUG_ENTER("open_proc_table"); @@ -112,8 +117,7 @@ static TABLE *open_proc_table_for_read(THD *thd) if (!mysql_proc_table_exists) DBUG_RETURN(0); - if (thd->push_open_tables_state()) - DBUG_RETURN(0); + thd->reset_n_backup_open_tables_state(backup); bzero((char*) &tables, sizeof(tables)); tables.db= (char*) "mysql"; @@ -121,7 +125,7 @@ static TABLE *open_proc_table_for_read(THD *thd) if (!(table= open_table(thd, &tables, thd->mem_root, &refresh, MYSQL_LOCK_IGNORE_FLUSH))) { - thd->pop_open_tables_state(); + thd->restore_backup_open_tables_state(backup); mysql_proc_table_exists= 0; DBUG_RETURN(0); } @@ -130,15 +134,13 @@ static TABLE *open_proc_table_for_read(THD *thd) table->reginfo.lock_type= TL_READ; /* - If we have other tables opened, we have to ensure we are not blocked - by a flush tables or global read lock, as this could lead to a deadlock + We have to ensure we are not blocked by a flush tables, as this + could lead to a deadlock if we have other tables opened. */ if (!(thd->lock= mysql_lock_tables(thd, &table, 1, - old_open_tables ? - (MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK | - MYSQL_LOCK_IGNORE_FLUSH) : 0))) + MYSQL_LOCK_IGNORE_FLUSH))) { - close_proc_table(thd); + close_proc_table(thd, backup); DBUG_RETURN(0); } DBUG_RETURN(table); @@ -271,12 +273,13 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) char buff[65]; String str(buff, sizeof(buff), &my_charset_bin); ulong sql_mode; + Open_tables_state open_tables_state_backup; DBUG_ENTER("db_find_routine"); DBUG_PRINT("enter", ("type: %d name: %*s", type, name->m_name.length, name->m_name.str)); *sphp= 0; // In case of errors - if (!(table= open_proc_table_for_read(thd))) + if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup))) DBUG_RETURN(SP_OPEN_TABLE_FAILED); if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK) @@ -371,7 +374,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) chistics.comment.str= ptr; chistics.comment.length= length; - close_proc_table(thd); + close_proc_table(thd, &open_tables_state_backup); table= 0; { @@ -424,7 +427,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) LEX *newlex= thd->lex; sp_head *sp= newlex->sphead; - if (dbchanged && (ret= sp_change_db(thd, olddb, 1))) + if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) goto done; if (sp) { @@ -435,7 +438,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) } else { - if (dbchanged && (ret= sp_change_db(thd, olddb, 1))) + if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) goto done; *sphp= thd->lex->sphead; (*sphp)->set_info((char *)definer, (uint)strlen(definer), @@ -449,7 +452,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) done: if (table) - close_proc_table(thd); + close_proc_table(thd, &open_tables_state_backup); DBUG_RETURN(ret); } @@ -591,7 +594,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) done: close_thread_tables(thd); if (dbchanged) - (void)sp_change_db(thd, olddb, 1); + (void)mysql_change_db(thd, olddb, 1); DBUG_RETURN(ret); } @@ -786,6 +789,7 @@ db_show_routine_status(THD *thd, int type, const char *wild) */ thd->lex->select_lex.context.resolve_in_table_list_only(&tables); setup_tables(thd, &thd->lex->select_lex.context, + &thd->lex->select_lex.top_join_list, &tables, 0, &leaves, FALSE); for (used_field= &used_fields[0]; used_field->field_name; @@ -795,7 +799,7 @@ db_show_routine_status(THD *thd, int type, const char *wild) "mysql", "proc", used_field->field_name); if (!field || - !(used_field->field= find_field_in_tables(thd, field, &tables, + !(used_field->field= find_field_in_tables(thd, field, &tables, NULL, 0, REPORT_ALL_ERRORS, 1, TRUE))) { @@ -986,13 +990,11 @@ int sp_drop_procedure(THD *thd, sp_name *name) { int ret; - bool found; DBUG_ENTER("sp_drop_procedure"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_proc_cache, name); ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1002,13 +1004,11 @@ int sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics) { int ret; - bool found; DBUG_ENTER("sp_update_procedure"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_proc_cache, name); ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1099,13 +1099,11 @@ int sp_drop_function(THD *thd, sp_name *name) { int ret; - bool found; DBUG_ENTER("sp_drop_function"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_func_cache, name); ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1115,13 +1113,11 @@ int sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics) { int ret; - bool found; DBUG_ENTER("sp_update_procedure"); DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); - found= sp_cache_remove(&thd->sp_func_cache, name); ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics); - if (!found && !ret) + if (!ret) sp_cache_invalidate(); DBUG_RETURN(ret); } @@ -1617,112 +1613,10 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen, } else { - int ret= sp_change_db(thd, newdb, no_access_check); + int ret= mysql_change_db(thd, newdb, no_access_check); if (! ret) *dbchangedp= TRUE; DBUG_RETURN(ret); } } - -/* - Change database. - - SYNOPSIS - sp_change_db() - thd Thread handler - name Database name - empty_is_ok True= it's ok with "" as name - no_access_check True= don't do access check - - DESCRIPTION - This is the same as mysql_change_db(), but with some extra - arguments for Stored Procedure usage; doing implicit "use" - when executing an SP in a different database. - We also use different error routines, since this might be - invoked from a function when executing a query or statement. - Note: We would have prefered to reuse mysql_change_db(), but - the error handling in particular made that too awkward, so - we (reluctantly) have a "copy" here. - - RETURN VALUES - 0 ok - 1 error -*/ - -int -sp_change_db(THD *thd, char *name, bool no_access_check) -{ - int length, db_length; - char *dbname=my_strdup((char*) name,MYF(MY_WME)); - char path[FN_REFLEN]; - HA_CREATE_INFO create; - DBUG_ENTER("sp_change_db"); - DBUG_PRINT("enter", ("db: %s, no_access_check: %d", name, no_access_check)); - - db_length= (!dbname ? 0 : strip_sp(dbname)); - if (dbname && db_length) - { - if ((db_length > NAME_LEN) || check_db_name(dbname)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), dbname); - x_free(dbname); - DBUG_RETURN(1); - } - } - - if (dbname && db_length) - { -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (! no_access_check) - { - ulong db_access; - - if (test_all_bits(thd->master_access,DB_ACLS)) - db_access=DB_ACLS; - else - db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | - thd->master_access); - if (!(db_access & DB_ACLS) && - (!grant_option || check_grant_db(thd,dbname))) - { - my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, - thd->priv_host, - dbname); - mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), - thd->priv_user, - thd->priv_host, - dbname); - my_free(dbname,MYF(0)); - DBUG_RETURN(1); - } - } -#endif - (void) sprintf(path,"%s/%s",mysql_data_home,dbname); - length=unpack_dirname(path,path); // Convert if not unix - if (length && path[length-1] == FN_LIBCHAR) - path[length-1]=0; // remove ending '\' - if (access(path,F_OK)) - { - my_error(ER_BAD_DB_ERROR, MYF(0), dbname); - my_free(dbname,MYF(0)); - DBUG_RETURN(1); - } - } - - x_free(thd->db); - thd->db=dbname; // THD::~THD will free this - thd->db_length=db_length; - - if (dbname && db_length) - { - strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE); - load_db_opt(thd, path, &create); - thd->db_charset= create.default_table_charset ? - create.default_table_charset : - thd->variables.collation_server; - thd->variables.collation_database= thd->db_charset; - } - DBUG_RETURN(0); -} |