1/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
15
16/*
17 Rename a table
18*/
19
20#include "ma_fulltext.h"
21#include "trnman_public.h"
22
23/**
24 @brief renames a table
25
26 @param old_name current name of table
27 @param new_name table should be renamed to this name
28
29 @return Operation status
30 @retval 0 OK
31 @retval !=0 Error
32*/
33
34int maria_rename(const char *old_name, const char *new_name)
35{
36 char from[FN_REFLEN],to[FN_REFLEN];
37 int data_file_rename_error;
38#ifdef USE_RAID
39 uint raid_type=0,raid_chunks=0;
40#endif
41 MARIA_HA *info;
42 MARIA_SHARE *share;
43 myf sync_dir;
44 DBUG_ENTER("maria_rename");
45
46#ifdef EXTRA_DEBUG
47 _ma_check_table_is_closed(old_name,"rename old_table");
48 _ma_check_table_is_closed(new_name,"rename new table2");
49#endif
50 /** @todo LOCK take X-lock on table */
51 if (!(info= maria_open(old_name, O_RDWR, HA_OPEN_FOR_REPAIR)))
52 DBUG_RETURN(my_errno);
53 share= info->s;
54#ifdef USE_RAID
55 raid_type = share->base.raid_type;
56 raid_chunks = share->base.raid_chunks;
57#endif
58
59 /*
60 the renaming of an internal table to the final table (like in ALTER TABLE)
61 is the moment when this table receives its correct create_rename_lsn and
62 this is important; make sure transactionality has been re-enabled.
63 */
64 DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
65 sync_dir= (share->now_transactional && !share->temporary &&
66 !maria_in_recovery) ? MY_SYNC_DIR : 0;
67 if (sync_dir)
68 {
69 LSN lsn;
70 LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
71 size_t old_name_len= strlen(old_name)+1, new_name_len= strlen(new_name)+1;
72 log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (uchar*)old_name;
73 log_array[TRANSLOG_INTERNAL_PARTS + 0].length= old_name_len;
74 log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (uchar*)new_name;
75 log_array[TRANSLOG_INTERNAL_PARTS + 1].length= new_name_len;
76 /*
77 For this record to be of any use for Recovery, we need the upper
78 MySQL layer to be crash-safe, which it is not now (that would require
79 work using the ddl_log of sql/sql_table.cc); when it is, we should
80 reconsider the moment of writing this log record (before or after op,
81 under THR_LOCK_maria or not...), how to use it in Recovery.
82 For now it can serve to apply logs to a backup so we sync it.
83 */
84 if (unlikely(translog_write_record(&lsn, LOGREC_REDO_RENAME_TABLE,
85 &dummy_transaction_object, NULL,
86 (translog_size_t)(old_name_len + new_name_len),
87 sizeof(log_array)/sizeof(log_array[0]),
88 log_array, NULL, NULL) ||
89 translog_flush(lsn)))
90 {
91 maria_close(info);
92 DBUG_RETURN(1);
93 }
94 /*
95 store LSN into file, needed for Recovery to not be confused if a
96 RENAME happened (applying REDOs to the wrong table).
97 */
98 if (_ma_update_state_lsns(share, lsn, share->state.create_trid, TRUE,
99 TRUE))
100 {
101 maria_close(info);
102 DBUG_RETURN(1);
103 }
104 }
105
106 _ma_reset_state(info);
107 maria_close(info);
108
109 fn_format(from,old_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
110 fn_format(to,new_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
111 if (mysql_file_rename_with_symlink(key_file_kfile, from, to,
112 MYF(MY_WME | sync_dir)))
113 DBUG_RETURN(my_errno);
114 fn_format(from,old_name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
115 fn_format(to,new_name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
116 data_file_rename_error=
117 mysql_file_rename_with_symlink(key_file_dfile, from, to,
118 MYF(MY_WME | sync_dir));
119 if (data_file_rename_error)
120 {
121 /*
122 now we have a renamed index file and a non-renamed data file, try to
123 undo the rename of the index file.
124 */
125 data_file_rename_error= my_errno;
126 fn_format(from, old_name, "", MARIA_NAME_IEXT, MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
127 fn_format(to, new_name, "", MARIA_NAME_IEXT, MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
128 mysql_file_rename_with_symlink(key_file_kfile, to, from,
129 MYF(MY_WME | sync_dir));
130 }
131 DBUG_RETURN(data_file_rename_error);
132
133}
134