/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; version 2 of the License .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/*
Rename a table
*/
#include "ma_fulltext.h"
#include "trnman_public.h"
/**
@ brief renames a table
@ param old_name current name of table
@ param new_name table should be renamed to this name
@ return Operation status
@ retval 0 OK
@ retval ! = 0 Error
*/
int maria_rename(const char *old_name, const char *new_name)
{
char from[FN_REFLEN],to[FN_REFLEN];
int data_file_rename_error= 0 , index_file_rename_error= 0 ;
#ifdef USE_RAID
uint raid_type=0 ,raid_chunks=0 ;
#endif
MARIA_HA *info;
MARIA_SHARE *share;
myf sync_dir= 0 ;
my_bool ddl_recovery= 0 ;
DBUG_ENTER("maria_rename" );
#ifdef EXTRA_DEBUG
_ma_check_table_is_closed(old_name,"rename old_table" );
_ma_check_table_is_closed(new_name,"rename new table2" );
#endif
/** @todo LOCK take X-lock on table */
if (!(info= maria_open(old_name, O_RDWR, HA_OPEN_FOR_REPAIR, 0 )))
{
int error= my_errno;
/*
Check if we are in recovery from a rename that failed in the middle
and we are now renaming things back .
*/
if (error == ENOENT)
{
char *index_file= from;
char *data_file= to;
fn_format(index_file, old_name, "" , MARIA_NAME_IEXT,
MY_UNPACK_FILENAME | MY_APPEND_EXT);
fn_format(data_file, old_name, "" , MARIA_NAME_DEXT,
MY_UNPACK_FILENAME | MY_APPEND_EXT);
if (!access(data_file, F_OK) && access(index_file, F_OK))
{
ddl_recovery= 1 ;
goto forced_rename;
}
}
DBUG_RETURN(error);
}
share= info->s;
#ifdef USE_RAID
raid_type = share->base.raid_type;
raid_chunks = share->base.raid_chunks;
#endif
/*
the renaming of an internal table to the final table ( like in ALTER TABLE )
is the moment when this table receives its correct create_rename_lsn and
this is important ; make sure transactionality has been re - enabled .
*/
DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
if (share->now_transactional && !share->temporary && !maria_in_recovery)
{
LSN lsn;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2 ];
size_t old_name_len= strlen(old_name)+1 , new_name_len= strlen(new_name)+1 ;
sync_dir= MY_SYNC_DIR;
log_array[TRANSLOG_INTERNAL_PARTS + 0 ].str= (uchar*)old_name;
log_array[TRANSLOG_INTERNAL_PARTS + 0 ].length= old_name_len;
log_array[TRANSLOG_INTERNAL_PARTS + 1 ].str= (uchar*)new_name;
log_array[TRANSLOG_INTERNAL_PARTS + 1 ].length= new_name_len;
/*
For this record to be of any use for Recovery , we need the upper
MySQL layer to be crash - safe , which it is not now ( that would require
work using the ddl_log of sql / sql_table . cc ) ; when it is , we should
reconsider the moment of writing this log record ( before or after op ,
under THR_LOCK_maria or not . . . ) , how to use it in Recovery .
For now it can serve to apply logs to a backup so we sync it .
*/
if (unlikely(translog_write_record(&lsn, LOGREC_REDO_RENAME_TABLE,
&dummy_transaction_object, NULL,
(translog_size_t)(old_name_len + new_name_len),
sizeof (log_array)/sizeof (log_array[0 ]),
log_array, NULL, NULL) ||
translog_flush(lsn)))
{
maria_close(info);
DBUG_RETURN(1 );
}
/*
store LSN into file , needed for Recovery to not be confused if a
RENAME happened ( applying REDOs to the wrong table ) .
*/
if (_ma_update_state_lsns(share, lsn, share->state.create_trid, TRUE ,
TRUE ))
{
maria_close(info);
DBUG_RETURN(1 );
}
}
_ma_reset_state(info);
maria_close(info);
forced_rename:
/*
This code is written so that it should be possible to re - run a
failed rename ( even if there is a server crash in between the
renames ) and complete it .
*/
fn_format(from,old_name,"" ,MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
fn_format(to,new_name,"" ,MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (mysql_file_rename_with_symlink(key_file_kfile, from, to,
MYF(MY_WME | sync_dir)))
index_file_rename_error= my_errno;
fn_format(from,old_name,"" ,MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
fn_format(to,new_name,"" ,MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (mysql_file_rename_with_symlink(key_file_dfile, from, to,
MYF(MY_WME | sync_dir)))
data_file_rename_error= my_errno;
if (data_file_rename_error && data_file_rename_error != ENOENT &&
!ddl_recovery)
{
/*
Now we have a renamed index file and a non - renamed data file , try to
undo a successful rename of the index file .
*/
if (!index_file_rename_error)
{
fn_format(from, old_name, "" , MARIA_NAME_IEXT,
MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
fn_format(to, new_name, "" , MARIA_NAME_IEXT,
MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
mysql_file_rename_with_symlink(key_file_kfile, to, from,
MYF(MY_WME | sync_dir));
}
}
DBUG_RETURN(data_file_rename_error ? data_file_rename_error:
index_file_rename_error);
}
Messung V0.5 in Prozent C=95 H=92 G=93
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland