diff options
Diffstat (limited to 'sql/sp.cc')
-rw-r--r-- | sql/sp.cc | 148 |
1 files changed, 42 insertions, 106 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index 8655e520041..e910bd6443d 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -519,9 +519,10 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, { LEX *old_lex= thd->lex, newlex; String defstr; - char old_db_buf[NAME_LEN+1]; - LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; - bool dbchanged; + char saved_cur_db_name_buf[NAME_LEN+1]; + LEX_STRING saved_cur_db_name= + { saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) }; + bool cur_db_changed; ulong old_sql_mode= thd->variables.sql_mode; ha_rows old_select_limit= thd->variables.select_limit; sp_rcontext *old_spcont= thd->spcont; @@ -566,16 +567,16 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, } /* - Change current database if needed. + Change the current database (if needed). - collation_database will be updated here. However, it can be wrong, - because it will contain the current value of the database collation. - We need collation_database to be fixed at the creation time -- so - we'll update it later in switch_query_ctx(). + TODO: why do we force switch here? */ - if ((ret= sp_use_new_db(thd, name->m_db, &old_db, TRUE, &dbchanged))) + if (mysql_opt_change_db(thd, &name->m_db, &saved_cur_db_name, TRUE, + &cur_db_changed)) + { goto end; + } thd->spcont= NULL; @@ -584,34 +585,42 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, lex_start(thd); - if (parse_sql(thd, &lip, creation_ctx) || newlex.sphead == NULL) - { - sp_head *sp= newlex.sphead; + ret= parse_sql(thd, &lip, creation_ctx) || newlex.sphead == NULL; - if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE))) - goto end; - delete sp; - ret= SP_PARSE_ERROR; + /* + Force switching back to the saved current database (if changed), + because it may be NULL. In this case, mysql_change_db() would + generate an error. + */ + + if (cur_db_changed && mysql_change_db(thd, &saved_cur_db_name, TRUE)) + { + delete newlex.sphead; + ret= -1; + goto end; } - else + + if (ret) { - if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE))) - goto end; - *sphp= newlex.sphead; - (*sphp)->set_definer(&definer_user_name, &definer_host_name); - (*sphp)->set_info(created, modified, &chistics, sql_mode); - (*sphp)->set_creation_ctx(creation_ctx); - (*sphp)->optimize(); - /* - Not strictly necessary to invoke this method here, since we know - that we've parsed CREATE PROCEDURE/FUNCTION and not an - UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to - maintain the invariant that this method is called for each - distinct statement, in case its logic is extended with other - types of analyses in future. - */ - newlex.set_trg_event_type_for_tables(); + delete newlex.sphead; + ret= SP_PARSE_ERROR; + goto end; } + + *sphp= newlex.sphead; + (*sphp)->set_definer(&definer_user_name, &definer_host_name); + (*sphp)->set_info(created, modified, &chistics, sql_mode); + (*sphp)->set_creation_ctx(creation_ctx); + (*sphp)->optimize(); + /* + Not strictly necessary to invoke this method here, since we know + that we've parsed CREATE PROCEDURE/FUNCTION and not an + UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to + maintain the invariant that this method is called for each + distinct statement, in case its logic is extended with other + types of analyses in future. + */ + newlex.set_trg_event_type_for_tables(); } end: @@ -2024,76 +2033,3 @@ create_string(THD *thd, String *buf, buf->append(body, bodylen); return TRUE; } - - - -/** - Change the current database if needed. - - @param[in] thd thread handle - @param[in] new_db new database name - @param[in, out] old_db IN: str points to a buffer where to store - the old database, length contains the - size of the buffer - OUT: if old db was not NULL, its name is - copied to the buffer pointed at by str - and length is updated accordingly. - Otherwise str[0] is set to '\0' and - length is set to 0. The out parameter - should be used only if the database name - has been changed (see dbchangedp). - @param[in] force_switch Flag to mysql_change_db(). For more information, - see mysql_change_db() comment. - @param[out] dbchangedp is set to TRUE if the current database is - changed, FALSE otherwise. The current - database is not changed if the old name - is equal to the new one, both names are - empty, or an error has occurred. - - @return Operation status. - @retval 0 on success - @retval 1 access denied or out of memory - (the error message is set in THD) -*/ - -int -sp_use_new_db(THD *thd, - LEX_STRING new_db, - LEX_STRING *old_db, - bool force_switch, - bool *dbchangedp) -{ - int ret; - DBUG_ENTER("sp_use_new_db"); - DBUG_PRINT("enter", ("newdb: %s", new_db.str)); - - /* - A stored routine always belongs to some database. The - old database (old_db) might be NULL, but to restore the - old database we will use mysql_change_db. - */ - DBUG_ASSERT(new_db.str && new_db.length); - - if (thd->db) - { - old_db->length= (strmake(old_db->str, thd->db, old_db->length) - - old_db->str); - } - else - { - old_db->str[0]= '\0'; - old_db->length= 0; - } - - /* Don't change the database if the new name is the same as the old one. */ - if (my_strcasecmp(system_charset_info, old_db->str, new_db.str) == 0) - { - *dbchangedp= FALSE; - DBUG_RETURN(0); - } - - ret= mysql_change_db(thd, &new_db, force_switch); - - *dbchangedp= ret == 0; - DBUG_RETURN(ret); -} |