diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/sql_db.cc | 122 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 26 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 32 |
6 files changed, 68 insertions, 119 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 47a42354423..6a7e3e00f6f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -923,7 +923,7 @@ void end_connection(THD *thd); bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); -bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db); +bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db); void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags); void mysql_client_binlog_statement(THD *thd); bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, diff --git a/sql/sql_db.cc b/sql/sql_db.cc index cd7ad048802..abbf2131957 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1727,41 +1727,21 @@ lock_databases(THD *thd, const char *db1, uint length1, } -/* - Rename database. - - SYNOPSIS - mysql_rename_db() - thd Thread handler - olddb Old database name - newdb New database name - - DESCRIPTION - This function is invoked whenever a RENAME DATABASE query is executed: - - RENAME DATABASE 'olddb' TO 'newdb'. - - NOTES - - If we have managed to rename (move) tables to the new database - but something failed on a later step, then we store the - RENAME DATABASE event in the log. mysql_rename_db() is atomic in - the sense that it will rename all or none of the tables. - - TODO: - - Better trigger, stored procedure, event, grant handling, - see the comments below. - NOTE: It's probably a good idea to call wait_if_global_read_lock() - once in mysql_rename_db(), instead of locking inside all - the required functions for renaming triggerts, SP, events, grants, etc. - - RETURN VALUES - 0 ok - 1 error +/** + Upgrade a 5.0 database. + This function is invoked whenever an ALTER DATABASE UPGRADE query is executed: + ALTER DATABASE 'olddb' UPGRADE DATA DIRECTORY NAME. + + If we have managed to rename (move) tables to the new database + but something failed on a later step, then we store the + RENAME DATABASE event in the log. mysql_rename_db() is atomic in + the sense that it will rename all or none of the tables. + + @param thd Current thread + @param old_db 5.0 database name, in #mysql50#name format + @return 0 on success, 1 on error */ - - -bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) +bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) { int error= 0, change_to_newdb= 0; char path[FN_REFLEN+16]; @@ -1770,11 +1750,27 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) MY_DIR *dirp; TABLE_LIST *table_list; SELECT_LEX *sl= thd->lex->current_select; - DBUG_ENTER("mysql_rename_db"); + LEX_STRING new_db; + DBUG_ENTER("mysql_upgrade_db"); + + if ((old_db->length <= MYSQL50_TABLE_NAME_PREFIX_LENGTH) || + (strncmp(old_db->str, + MYSQL50_TABLE_NAME_PREFIX, + MYSQL50_TABLE_NAME_PREFIX_LENGTH) != 0)) + { + my_error(ER_WRONG_USAGE, MYF(0), + "ALTER DATABASE UPGRADE DATA DIRECTORY NAME", + "name"); + DBUG_RETURN(1); + } + + /* `#mysql50#<name>` converted to encoded `<name>` */ + new_db.str= old_db->str + MYSQL50_TABLE_NAME_PREFIX_LENGTH; + new_db.length= old_db->length - MYSQL50_TABLE_NAME_PREFIX_LENGTH; if (lock_databases(thd, old_db->str, old_db->length, - new_db->str, new_db->length)) - return 1; + new_db.str, new_db.length)) + DBUG_RETURN(1); /* Let's remember if we should do "USE newdb" afterwards. @@ -1798,7 +1794,7 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) } /* Step1: Create the new database */ - if ((error= mysql_create_db(thd, new_db->str, &create_info, 1))) + if ((error= mysql_create_db(thd, new_db.str, &create_info, 1))) goto exit; /* Step2: Move tables to the new database */ @@ -1819,12 +1815,12 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) /* A frm file found, add the table info rename list */ *extension= '\0'; - + table_str.length= filename_to_tablename(file->name, tname, sizeof(tname)-1); table_str.str= (char*) sql_memdup(tname, table_str.length + 1); Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0); - Table_ident *new_ident= new Table_ident(thd, *new_db, table_str, 0); + Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0); if (!old_ident || !new_ident || !sl->add_table_to_list(thd, old_ident, NULL, TL_OPTION_UPDATING, TL_IGNORE) || @@ -1854,9 +1850,9 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) It garantees we never loose any tables. */ build_table_filename(path, sizeof(path)-1, - new_db->str,"",MY_DB_OPT_FILE, 0); + new_db.str,"",MY_DB_OPT_FILE, 0); my_delete(path, MYF(MY_WME)); - length= build_table_filename(path, sizeof(path)-1, new_db->str, "", "", 0); + length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' rmdir(path); @@ -1910,47 +1906,13 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) build_table_filename(oldname, sizeof(oldname)-1, old_db->str, "", file->name, 0); build_table_filename(newname, sizeof(newname)-1, - new_db->str, "", file->name, 0); + new_db.str, "", file->name, 0); my_rename(oldname, newname, MYF(MY_WME)); } - my_dirend(dirp); + my_dirend(dirp); } /* - Step4: TODO: moving stored procedures in the 'proc' system table - We need a new function: sp_move_db_routines(thd, olddb, newdb) - Which will basically have the same effect with: - UPDATE proc SET db='newdb' WHERE db='olddb' - Note, for 5.0 to 5.1 upgrade purposes we don't really need it. - - The biggest problem here is that we can't have a lock on LOCK_open() while - calling open_table() for 'proc'. - - Two solutions: - - Start by opening the 'event' and 'proc' (and other) tables for write - even before creating the 'to' database. (This will have the nice - effect of blocking another 'rename database' while the lock is active). - - Use the solution "Disable create of new tables during lock table" - - For an example of how to read through all rows, see: - sql_help.cc::search_topics() - */ - - /* - Step5: TODO: moving events in the 'event' system table - We need a new function evex_move_db_events(thd, olddb, newdb) - Which will have the same effect with: - UPDATE event SET db='newdb' WHERE db='olddb' - Note, for 5.0 to 5.1 upgrade purposes we don't really need it. - */ - - /* - Step6: TODO: moving grants in the 'db', 'tables_priv', 'columns_priv'. - Update each grant table, doing the same with: - UPDATE system_table SET db='newdb' WHERE db='olddb' - */ - - /* Step7: drop the old database. remove_db_from_cache(olddb) and query_cache_invalidate(olddb) are done inside mysql_rm_db(), no needs to execute them again. @@ -1968,13 +1930,13 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) /* Step9: Let's do "use newdb" if we renamed the current database */ if (change_to_newdb) - error|= mysql_change_db(thd, new_db, FALSE); + error|= mysql_change_db(thd, & new_db, FALSE); exit: pthread_mutex_lock(&LOCK_lock_db); /* Remove the databases from db lock cache */ lock_db_delete(old_db->str, old_db->length); - lock_db_delete(new_db->str, new_db->length); + lock_db_delete(new_db.str, new_db.length); creating_database--; /* Signal waiting CREATE TABLE's to continue */ pthread_cond_signal(&COND_refresh); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index da0134a7f72..ae689be263e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -78,7 +78,6 @@ enum enum_sql_command { SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, - SQLCOM_RENAME_DB, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, @@ -117,6 +116,7 @@ enum enum_sql_command { SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT, SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS, SQLCOM_SHOW_CREATE_TRIGGER, + SQLCOM_ALTER_DB_UPGRADE, /* This should be the last !!! */ @@ -1550,7 +1550,6 @@ typedef struct st_lex : public Query_tables_list required a local context, the parser pops the top-most context. */ List<Name_resolution_context> context_stack; - List<LEX_STRING> db_list; SQL_LIST proc_list, auxiliary_table_list, save_list; Create_field *last_field; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bbd6cb16d11..6002d7545ba 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3175,12 +3175,9 @@ end_with_restore_list: res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0); break; } - case SQLCOM_RENAME_DB: + case SQLCOM_ALTER_DB_UPGRADE: { - LEX_STRING *olddb, *newdb; - List_iterator <LEX_STRING> db_list(lex->db_list); - olddb= db_list++; - newdb= db_list++; + LEX_STRING *db= & lex->name; if (end_active_trans(thd)) { res= 1; @@ -3188,24 +3185,22 @@ end_with_restore_list: } #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(olddb->str) || - !rpl_filter->db_ok(newdb->str) || - !rpl_filter->db_ok_with_wild_table(olddb->str) || - !rpl_filter->db_ok_with_wild_table(newdb->str))) + (!rpl_filter->db_ok(db->str) || + !rpl_filter->db_ok_with_wild_table(db->str))) { res= 1; my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_db_name(newdb)) + if (check_db_name(db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), newdb->str); + my_error(ER_WRONG_DB_NAME, MYF(0), db->str); break; } - if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || - check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || - check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str))) + if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) || + check_access(thd, DROP_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) || + check_access(thd, CREATE_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) { res= 1; break; @@ -3217,7 +3212,8 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_rename_db(thd, olddb, newdb); + + res= mysql_upgrade_db(thd, db); if (!res) send_ok(thd); break; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9337a2aa329..c576a9dba1d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1799,7 +1799,7 @@ static bool check_prepared_statement(Prepared_statement *stmt, case SQLCOM_UNINSTALL_PLUGIN: case SQLCOM_CREATE_DB: case SQLCOM_DROP_DB: - case SQLCOM_RENAME_DB: + case SQLCOM_ALTER_DB_UPGRADE: case SQLCOM_CHECKSUM: case SQLCOM_CREATE_USER: case SQLCOM_RENAME_USER: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index efd8c20e6d7..864d838c183 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1260,7 +1260,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); clear_privileges flush_options flush_option equal optional_braces opt_mi_check_type opt_to mi_check_types normal_join - db_to_db table_to_table_list table_to_table opt_table_list opt_as + table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild union_clause union_list @@ -5400,6 +5400,17 @@ alter: lex->copy_db_to(&lex->name.str, &lex->name.length)) MYSQL_YYABORT; } + | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM + { + LEX *lex= Lex; + if (lex->sphead) + { + my_error(ER_SP_NO_DROP_SP, MYF(0), "DATABASE"); + MYSQL_YYABORT; + } + lex->sql_command= SQLCOM_ALTER_DB_UPGRADE; + lex->name= $3; + } | ALTER PROCEDURE sp_name { LEX *lex= Lex; @@ -6184,13 +6195,6 @@ rename: } table_to_table_list {} - | RENAME DATABASE - { - Lex->db_list.empty(); - Lex->sql_command= SQLCOM_RENAME_DB; - } - db_to_db - {} | RENAME USER clear_privileges rename_list { Lex->sql_command = SQLCOM_RENAME_USER; @@ -6228,18 +6232,6 @@ table_to_table: } ; -db_to_db: - ident TO_SYM ident - { - LEX *lex=Lex; - if (lex->db_list.push_back((LEX_STRING*) - sql_memdup(&$1, sizeof(LEX_STRING))) || - lex->db_list.push_back((LEX_STRING*) - sql_memdup(&$3, sizeof(LEX_STRING)))) - MYSQL_YYABORT; - } - ; - keycache: CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name { |