Commit 866a8278 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Added support for symlinked tables.

myisamchk: Don't force a repair if the only problem was that the
open count wasn't correct.
Added missing error messages.
parent 762f423d
...@@ -110,10 +110,7 @@ extern int NEAR my_errno; /* Last error in mysys */ ...@@ -110,10 +110,7 @@ extern int NEAR my_errno; /* Last error in mysys */
/* root_alloc flags */ /* root_alloc flags */
#define MY_KEEP_PREALLOC 1 #define MY_KEEP_PREALLOC 1
#define MY_MARK_BLOCKS_FREE 2 /* do not my_free() blocks, #define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */
just move used into free list
and mark all blocks as fully free
*/
/* defines when allocating data */ /* defines when allocating data */
......
...@@ -54,7 +54,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ ...@@ -54,7 +54,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
mf_pack.lo my_messnc.lo mf_dirname.lo mf_fn_ext.lo\ mf_pack.lo my_messnc.lo mf_dirname.lo mf_fn_ext.lo\
mf_wcomp.lo typelib.lo safemalloc.lo my_alloc.lo \ mf_wcomp.lo typelib.lo safemalloc.lo my_alloc.lo \
mf_format.lo mf_path.lo mf_unixpath.lo my_fopen.lo \ mf_format.lo mf_path.lo mf_unixpath.lo my_fopen.lo \
my_fstream.lo \ my_symlink.lo my_fstream.lo \
mf_loadpath.lo my_pthread.lo my_thr_init.lo \ mf_loadpath.lo my_pthread.lo my_thr_init.lo \
thr_mutex.lo mulalloc.lo string.lo default.lo \ thr_mutex.lo mulalloc.lo string.lo default.lo \
my_compress.lo array.lo my_once.lo list.lo my_net.lo \ my_compress.lo array.lo my_once.lo list.lo my_net.lo \
......
...@@ -1130,7 +1130,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1130,7 +1130,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
if (!rep_quick) if (!rep_quick)
{ {
if ((new_file=my_raid_create(fn_format(param->temp_filename,name,"", /* Get real path for data file */
fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
if ((new_file=my_raid_create(fn_format(param->temp_filename,
param->temp_filename,"",
DATA_TMP_EXT, DATA_TMP_EXT,
2+4), 2+4),
0,param->tmpfile_createflag, 0,param->tmpfile_createflag,
...@@ -1476,8 +1479,10 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name) ...@@ -1476,8 +1479,10 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
printf("- Sorting index for MyISAM-table '%s'\n",name); printf("- Sorting index for MyISAM-table '%s'\n",name);
if ((new_file=my_create(fn_format(param->temp_filename,name,"", /* Get real path for index file */
INDEX_TMP_EXT,2+4), fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
if ((new_file=my_create(fn_format(param->temp_filename,param->temp_filename,
"", INDEX_TMP_EXT,2+4),
0,param->tmpfile_createflag,MYF(0))) <= 0) 0,param->tmpfile_createflag,MYF(0))) <= 0)
{ {
mi_check_print_error(param,"Can't create new tempfile: '%s'", mi_check_print_error(param,"Can't create new tempfile: '%s'",
...@@ -1497,7 +1502,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name) ...@@ -1497,7 +1502,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
if (share->state.key_root[key] != HA_OFFSET_ERROR) if (share->state.key_root[key] != HA_OFFSET_ERROR)
{ {
index_pos[key]=param->new_file_pos; /* Write first block here */ index_pos[key]=param->new_file_pos; /* Write first block here */
if (sort_one_index(param,info,keyinfo,share->state.key_root[key], if (sort_one_index(param,info,keyinfo,share->state.key_root[key],
new_file)) new_file))
goto err; goto err;
...@@ -1618,9 +1623,14 @@ err: ...@@ -1618,9 +1623,14 @@ err:
} /* sort_one_index */ } /* sort_one_index */
/* Change to use new file */ /*
/* Copy stats from old file to new file, deletes orginal and */ Let temporary file replace old file.
/* changes new file name to old file name */ This assumes that the new file was created in the same
directory as given by realpath(filename).
This will ensure that any symlinks that are used will still work.
Copy stats from old file to new file, deletes orignal and
changes new file name to old file name
*/
int change_to_newfile(const char * filename, const char * old_ext, int change_to_newfile(const char * filename, const char * old_ext,
const char * new_ext, const char * new_ext,
...@@ -1635,8 +1645,10 @@ int change_to_newfile(const char * filename, const char * old_ext, ...@@ -1635,8 +1645,10 @@ int change_to_newfile(const char * filename, const char * old_ext,
raid_chunks, raid_chunks,
MYF(MY_WME | MY_LINK_WARNING | MyFlags)); MYF(MY_WME | MY_LINK_WARNING | MyFlags));
#endif #endif
return my_redel(fn_format(old_filename,filename,"",old_ext,2+4), /* Get real path to filename */
fn_format(new_filename,filename,"",new_ext,2+4), (void) fn_format(old_filename,filename,"",old_ext,2+4+32);
return my_redel(old_filename,
fn_format(new_filename,old_filename,"",new_ext,2+4),
MYF(MY_WME | MY_LINK_WARNING | MyFlags)); MYF(MY_WME | MY_LINK_WARNING | MyFlags));
} /* change_to_newfile */ } /* change_to_newfile */
...@@ -1753,7 +1765,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1753,7 +1765,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
} }
if (!rep_quick) if (!rep_quick)
{ {
if ((new_file=my_raid_create(fn_format(param->temp_filename,name,"", /* Get real path for data file */
fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
if ((new_file=my_raid_create(fn_format(param->temp_filename,
param->temp_filename, "",
DATA_TMP_EXT, DATA_TMP_EXT,
2+4), 2+4),
0,param->tmpfile_createflag, 0,param->tmpfile_createflag,
......
...@@ -50,12 +50,12 @@ int mi_delete_table(const char *name) ...@@ -50,12 +50,12 @@ int mi_delete_table(const char *name)
#endif /* USE_RAID */ #endif /* USE_RAID */
fn_format(from,name,"",MI_NAME_IEXT,4); fn_format(from,name,"",MI_NAME_IEXT,4);
if (my_delete(from, MYF(MY_WME))) if (my_delete_with_symlink(from, MYF(MY_WME)))
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
fn_format(from,name,"",MI_NAME_DEXT,4); fn_format(from,name,"",MI_NAME_DEXT,4);
#ifdef USE_RAID #ifdef USE_RAID
if (raid_type) if (raid_type)
DBUG_RETURN(my_raid_delete(from, raid_chunks, MYF(MY_WME)) ? my_errno : 0); DBUG_RETURN(my_raid_delete(from, raid_chunks, MYF(MY_WME)) ? my_errno : 0);
#endif #endif
DBUG_RETURN(my_delete(from, MYF(MY_WME)) ? my_errno : 0); DBUG_RETURN(my_delete_with_symlink(from, MYF(MY_WME)) ? my_errno : 0);
} }
...@@ -132,10 +132,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -132,10 +132,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
} }
/* Don't call realpath() if the name can't be a link */ /* Don't call realpath() if the name can't be a link */
if (strcmp(name_buff, org_name)) if (strcmp(name_buff, org_name))
my_readlink(index_name, org_name, MYF(0)); (void) my_readlink(index_name, org_name, MYF(0));
else else
strmov(index_name, org_name); (void) strmov(index_name, org_name);
fn_format(data_name,org_name,"",MI_NAME_DEXT,4+16); (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,2+4+16);
info_length=mi_uint2korr(share->state.header.header_length); info_length=mi_uint2korr(share->state.header.header_length);
base_pos=mi_uint2korr(share->state.header.base_pos); base_pos=mi_uint2korr(share->state.header.base_pos);
......
...@@ -51,7 +51,7 @@ int mi_rename(const char *old_name, const char *new_name) ...@@ -51,7 +51,7 @@ int mi_rename(const char *old_name, const char *new_name)
fn_format(from,old_name,"",MI_NAME_IEXT,4); fn_format(from,old_name,"",MI_NAME_IEXT,4);
fn_format(to,new_name,"",MI_NAME_IEXT,4); fn_format(to,new_name,"",MI_NAME_IEXT,4);
if (my_rename(from, to, MYF(MY_WME))) if (my_rename_with_symlink(from, to, MYF(MY_WME)))
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
fn_format(from,old_name,"",MI_NAME_DEXT,4); fn_format(from,old_name,"",MI_NAME_DEXT,4);
fn_format(to,new_name,"",MI_NAME_DEXT,4); fn_format(to,new_name,"",MI_NAME_DEXT,4);
...@@ -60,5 +60,5 @@ int mi_rename(const char *old_name, const char *new_name) ...@@ -60,5 +60,5 @@ int mi_rename(const char *old_name, const char *new_name)
DBUG_RETURN(my_raid_rename(from, to, raid_chunks, MYF(MY_WME)) ? my_errno : DBUG_RETURN(my_raid_rename(from, to, raid_chunks, MYF(MY_WME)) ? my_errno :
0); 0);
#endif #endif
DBUG_RETURN(my_rename(from, to,MYF(MY_WME)) ? my_errno : 0); DBUG_RETURN(my_rename_with_symlink(from, to,MYF(MY_WME)) ? my_errno : 0);
} }
...@@ -498,7 +498,6 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -498,7 +498,6 @@ static int myisamchk(MI_CHECK *param, my_string filename)
uint raid_chunks; uint raid_chunks;
MI_INFO *info; MI_INFO *info;
File datafile; File datafile;
char fixed_name[FN_REFLEN];
char llbuff[22],llbuff2[22]; char llbuff[22],llbuff2[22];
my_bool state_updated=0; my_bool state_updated=0;
MYISAM_SHARE *share; MYISAM_SHARE *share;
...@@ -675,9 +674,6 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -675,9 +674,6 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (tmp != share->state.key_map) if (tmp != share->state.key_map)
info->update|=HA_STATE_CHANGED; info->update|=HA_STATE_CHANGED;
} }
VOID(fn_format(fixed_name,filename,"",MI_NAME_IEXT,
4+ (param->opt_follow_links ? 32 : 0)));
if (rep_quick && chk_del(&check_param, info, if (rep_quick && chk_del(&check_param, info,
param->testflag & ~T_VERBOSE)) param->testflag & ~T_VERBOSE))
{ {
...@@ -702,11 +698,11 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -702,11 +698,11 @@ static int myisamchk(MI_CHECK *param, my_string filename)
info->s->state.key_map, info->s->state.key_map,
check_param.force_sort)) check_param.force_sort))
{ {
error=mi_repair_by_sort(&check_param,info,fixed_name,rep_quick); error=mi_repair_by_sort(&check_param,info,filename,rep_quick);
state_updated=1; state_updated=1;
} }
else if (param->testflag & (T_REP | T_REP_BY_SORT)) else if (param->testflag & (T_REP | T_REP_BY_SORT))
error=mi_repair(&check_param, info,fixed_name,rep_quick); error=mi_repair(&check_param, info,filename,rep_quick);
} }
if (!error && param->testflag & T_SORT_RECORDS) if (!error && param->testflag & T_SORT_RECORDS)
{ {
...@@ -718,7 +714,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -718,7 +714,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (param->out_flag & O_NEW_DATA) if (param->out_flag & O_NEW_DATA)
{ /* Change temp file to org file */ { /* Change temp file to org file */
VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */ VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */
error|=change_to_newfile(fixed_name,MI_NAME_DEXT,DATA_TMP_EXT, error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks, raid_chunks,
MYF(0)); MYF(0));
if (mi_open_datafile(info,info->s)) if (mi_open_datafile(info,info->s))
...@@ -739,7 +735,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -739,7 +735,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (share->keyinfo[key].flag & HA_BINARY_PACK_KEY) if (share->keyinfo[key].flag & HA_BINARY_PACK_KEY)
update_index=0; update_index=0;
error=mi_sort_records(param,info,fixed_name,param->opt_sort_key, error=mi_sort_records(param,info,filename,param->opt_sort_key,
(my_bool) !(param->testflag & T_REP), (my_bool) !(param->testflag & T_REP),
update_index); update_index);
datafile=info->dfile; /* This is now locked */ datafile=info->dfile; /* This is now locked */
...@@ -747,12 +743,12 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -747,12 +743,12 @@ static int myisamchk(MI_CHECK *param, my_string filename)
{ {
if (check_param.verbose) if (check_param.verbose)
puts("Table had a compressed index; We must now recreate the index"); puts("Table had a compressed index; We must now recreate the index");
error=mi_repair_by_sort(&check_param,info,fixed_name,1); error=mi_repair_by_sort(&check_param,info,filename,1);
} }
} }
} }
if (!error && param->testflag & T_SORT_INDEX) if (!error && param->testflag & T_SORT_INDEX)
error=mi_sort_index(param,info,fixed_name); error=mi_sort_index(param,info,filename);
if (!error) if (!error)
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
STATE_CRASHED_ON_REPAIR); STATE_CRASHED_ON_REPAIR);
...@@ -849,12 +845,12 @@ end2: ...@@ -849,12 +845,12 @@ end2:
if (error == 0) if (error == 0)
{ {
if (param->out_flag & O_NEW_DATA) if (param->out_flag & O_NEW_DATA)
error|=change_to_newfile(fixed_name,MI_NAME_DEXT,DATA_TMP_EXT, error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks, raid_chunks,
((param->testflag & T_BACKUP_DATA) ? ((param->testflag & T_BACKUP_DATA) ?
MYF(MY_REDEL_MAKE_BACKUP) : MYF(0))); MYF(MY_REDEL_MAKE_BACKUP) : MYF(0)));
if (param->out_flag & O_NEW_INDEX) if (param->out_flag & O_NEW_INDEX)
error|=change_to_newfile(fixed_name,MI_NAME_IEXT,INDEX_TMP_EXT,0, error|=change_to_newfile(filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
MYF(0)); MYF(0));
} }
VOID(fflush(stdout)); VOID(fflush(stderr)); VOID(fflush(stdout)); VOID(fflush(stderr));
...@@ -1212,7 +1208,9 @@ static int mi_sort_records(MI_CHECK *param, ...@@ -1212,7 +1208,9 @@ static int mi_sort_records(MI_CHECK *param,
mi_check_print_error(param,"Not enough memory for record"); mi_check_print_error(param,"Not enough memory for record");
goto err; goto err;
} }
new_file=my_raid_create(fn_format(param->temp_filename,name,"", fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
new_file=my_raid_create(fn_format(param->temp_filename,
param->temp_filename,"",
DATA_TMP_EXT,2+4), DATA_TMP_EXT,2+4),
0,param->tmpfile_createflag, 0,param->tmpfile_createflag,
share->base.raid_type, share->base.raid_type,
......
...@@ -212,7 +212,7 @@ make_tempname (filename) ...@@ -212,7 +212,7 @@ make_tempname (filename)
{ {
tmpname = xmalloc (sizeof (template)); tmpname = xmalloc (sizeof (template));
strcpy (tmpname, template); strcpy (tmpname, template);
mktemp (tmpname); mkstemp (tmpname);
} }
return tmpname; return tmpname;
} }
......
...@@ -813,6 +813,8 @@ void ha_myisam::position(const byte* record) ...@@ -813,6 +813,8 @@ void ha_myisam::position(const byte* record)
void ha_myisam::info(uint flag) void ha_myisam::info(uint flag)
{ {
MI_ISAMINFO info; MI_ISAMINFO info;
char name_buff[FN_REFLEN];
(void) mi_status(file,&info,flag); (void) mi_status(file,&info,flag);
if (flag & HA_STATUS_VARIABLE) if (flag & HA_STATUS_VARIABLE)
{ {
...@@ -842,6 +844,18 @@ void ha_myisam::info(uint flag) ...@@ -842,6 +844,18 @@ void ha_myisam::info(uint flag)
raid_type=info.raid_type; raid_type=info.raid_type;
raid_chunks=info.raid_chunks; raid_chunks=info.raid_chunks;
raid_chunksize=info.raid_chunksize; raid_chunksize=info.raid_chunksize;
/*
Set data_file_name and index_file_name to point at the symlink value
if table is symlinked
*/
data_file_name=index_file_name=0;
fn_format(name_buff, file->filename, "", MI_NAME_IEXT, 4);
if (!strcmp(name_buff, info.data_file_name))
data_file_name=info.data_file_name;
strmov(fn_ext(name_buff),MI_NAME_DEXT);
if (!strcmp(name_buff, info.index_file_name))
index_file_name=info.index_file_name;
} }
if (flag & HA_STATUS_ERRKEY) if (flag & HA_STATUS_ERRKEY)
{ {
...@@ -897,6 +911,7 @@ THR_LOCK_DATA **ha_myisam::store_lock(THD *thd, ...@@ -897,6 +911,7 @@ THR_LOCK_DATA **ha_myisam::store_lock(THD *thd,
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
{ {
MI_ISAMINFO info;
table->file->info(HA_STATUS_AUTO | HA_STATUS_CONST); table->file->info(HA_STATUS_AUTO | HA_STATUS_CONST);
if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
{ {
...@@ -908,6 +923,8 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) ...@@ -908,6 +923,8 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
create_info->raid_chunks= raid_chunks; create_info->raid_chunks= raid_chunks;
create_info->raid_chunksize= raid_chunksize; create_info->raid_chunksize= raid_chunksize;
} }
create_info->data_file_name=data_file_name;
create_info->index_file_name=index_file_name;
} }
...@@ -1079,6 +1096,8 @@ int ha_myisam::create(const char *name, register TABLE *form, ...@@ -1079,6 +1096,8 @@ int ha_myisam::create(const char *name, register TABLE *form,
create_info.raid_type=info->raid_type; create_info.raid_type=info->raid_type;
create_info.raid_chunks=info->raid_chunks ? info->raid_chunks : RAID_DEFAULT_CHUNKS; create_info.raid_chunks=info->raid_chunks ? info->raid_chunks : RAID_DEFAULT_CHUNKS;
create_info.raid_chunksize=info->raid_chunksize ? info->raid_chunksize : RAID_DEFAULT_CHUNKSIZE; create_info.raid_chunksize=info->raid_chunksize ? info->raid_chunksize : RAID_DEFAULT_CHUNKSIZE;
create_info.data_file_name= info->data_file_name;
create_info.index_file_name=info->index_file_name;
error=mi_create(fn_format(buff,name,"","",2+4+16), error=mi_create(fn_format(buff,name,"","",2+4+16),
form->keys,keydef, form->keys,keydef,
......
...@@ -38,6 +38,7 @@ class ha_myisam: public handler ...@@ -38,6 +38,7 @@ class ha_myisam: public handler
{ {
MI_INFO *file; MI_INFO *file;
uint int_option_flag; uint int_option_flag;
char *data_file_name, *index_file_name;
int repair(THD *thd, MI_CHECK &param, bool optimize); int repair(THD *thd, MI_CHECK &param, bool optimize);
public: public:
......
...@@ -232,7 +232,7 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) ...@@ -232,7 +232,7 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
for (table=file->open_tables ; table != file->end_table ; table++) for (table=file->open_tables ; table != file->end_table ; table++)
{ {
char *name=table->table->s->filename; char *name=table->table->filename;
char buff[FN_REFLEN]; char buff[FN_REFLEN];
TABLE_LIST *ptr; TABLE_LIST *ptr;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
...@@ -278,7 +278,7 @@ void ha_myisammrg::append_create_info(String *packet) ...@@ -278,7 +278,7 @@ void ha_myisammrg::append_create_info(String *packet)
for (first=table=file->open_tables ; table != file->end_table ; table++) for (first=table=file->open_tables ; table != file->end_table ; table++)
{ {
char *name=table->table->s->filename; char *name=table->table->filename;
fn_format(buff,name,"","",3); fn_format(buff,name,"","",3);
if (table != first) if (table != first)
packet->append(','); packet->append(',');
......
...@@ -853,5 +853,5 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag) ...@@ -853,5 +853,5 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
{ {
char buff[FN_REFLEN]; char buff[FN_REFLEN];
VOID(fn_format(buff,name,"",ext,extflag | 4)); VOID(fn_format(buff,name,"",ext,extflag | 4));
return(my_delete(buff,MYF(MY_WME))); return(my_delete_with_symlink(buff,MYF(MY_WME)));
} }
...@@ -142,6 +142,7 @@ typedef struct st_ha_create_information ...@@ -142,6 +142,7 @@ typedef struct st_ha_create_information
ulonglong max_rows,min_rows; ulonglong max_rows,min_rows;
ulonglong auto_increment_value; ulonglong auto_increment_value;
char *comment,*password; char *comment,*password;
char *data_file_name, *index_file_name;
uint options; /* OR of HA_CREATE_ options */ uint options; /* OR of HA_CREATE_ options */
uint raid_type,raid_chunks; uint raid_type,raid_chunks;
ulong raid_chunksize; ulong raid_chunksize;
......
...@@ -113,6 +113,7 @@ static SYMBOL symbols[] = { ...@@ -113,6 +113,7 @@ static SYMBOL symbols[] = {
{ "DELETE", SYM(DELETE_SYM),0,0}, { "DELETE", SYM(DELETE_SYM),0,0},
{ "DESC", SYM(DESC),0,0}, { "DESC", SYM(DESC),0,0},
{ "DESCRIBE", SYM(DESCRIBE),0,0}, { "DESCRIBE", SYM(DESCRIBE),0,0},
{ "DIRECTORY", SYM(DIRECTORY_SYM),0,0},
{ "DISABLE", SYM(DISABLE_SYM),0,0}, { "DISABLE", SYM(DISABLE_SYM),0,0},
{ "DISTINCT", SYM(DISTINCT),0,0}, { "DISTINCT", SYM(DISTINCT),0,0},
{ "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */ { "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */
......
...@@ -218,3 +218,5 @@ ...@@ -218,3 +218,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -212,3 +212,5 @@ ...@@ -212,3 +212,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -209,3 +209,5 @@ ...@@ -209,3 +209,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -213,3 +213,5 @@ ...@@ -213,3 +213,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -209,3 +209,5 @@ ...@@ -209,3 +209,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -212,3 +212,5 @@ ...@@ -212,3 +212,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -209,3 +209,5 @@ ...@@ -209,3 +209,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -211,3 +211,5 @@ ...@@ -211,3 +211,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -209,3 +209,5 @@ ...@@ -209,3 +209,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -211,3 +211,5 @@ ...@@ -211,3 +211,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -209,3 +209,5 @@ ...@@ -209,3 +209,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -211,3 +211,5 @@ ...@@ -211,3 +211,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -211,3 +211,5 @@ ...@@ -211,3 +211,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -213,3 +213,5 @@ ...@@ -213,3 +213,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -209,3 +209,5 @@ ...@@ -209,3 +209,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -213,3 +213,5 @@ ...@@ -213,3 +213,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -212,3 +212,5 @@ ...@@ -212,3 +212,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -217,3 +217,5 @@ ...@@ -217,3 +217,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -210,3 +210,5 @@ ...@@ -210,3 +210,5 @@
"Lock wait timeout exceeded", "Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size", "The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
...@@ -206,3 +206,8 @@ ...@@ -206,3 +206,8 @@
"Kunde inte starta en tråd för replikering", "Kunde inte starta en tråd för replikering",
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar", "Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
"Du kan endast använda konstant-uttryck med SET", "Du kan endast använda konstant-uttryck med SET",
"Tiden att få ett lås var för lång",
"Antal lås är större än vad som ryms i lock tabellen",
"Du kan inte låsa tabeller/poster under READ UNCOMMITTED",
"Fick fel vid inloggning till master: %-.128s",
"Fick fel vid exekvering av fråga på master: %-.128s",
...@@ -206,6 +206,8 @@ ...@@ -206,6 +206,8 @@
"Kunde inte starta en tråd för replikering", "Kunde inte starta en tråd för replikering",
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar", "Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
"Du kan endast använda konstant-uttryck med SET", "Du kan endast använda konstant-uttryck med SET",
"Lock wait timeout exceeded", "Tiden att få ett lås var för lång",
"The total number of locks exceeds the lock table size", "Antal lås är större än vad som ryms i lock tabellen",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction", "Du kan inte låsa tabeller/poster under READ UNCOMMITTED",
"Fick fel vid inloggning till master: %-.128s",
"Fick fel vid exekvering av fråga på master: %-.128s",
...@@ -212,7 +212,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path, ...@@ -212,7 +212,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
} }
strxmov(filePath,org_path,"/",file->name,NullS); strxmov(filePath,org_path,"/",file->name,NullS);
unpack_filename(filePath,filePath); unpack_filename(filePath,filePath);
if (my_delete(filePath,MYF(MY_WME))) if (my_delete_with_symlink(filePath,MYF(MY_WME)))
{ {
if(thd) if(thd)
net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error); net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error);
......
...@@ -46,6 +46,7 @@ static bool check_dup(THD *thd,const char *db,const char *name, ...@@ -46,6 +46,7 @@ static bool check_dup(THD *thd,const char *db,const char *name,
static void mysql_init_query(THD *thd); static void mysql_init_query(THD *thd);
static void remove_escape(char *name); static void remove_escape(char *name);
static void refresh_status(void); static void refresh_status(void);
static bool append_file_to_dir(char **filename_ptr, char *table_name);
const char *any_db="*any*"; // Special symbol for check_access const char *any_db="*any*"; // Special symbol for check_access
...@@ -1286,6 +1287,14 @@ mysql_execute_command(void) ...@@ -1286,6 +1287,14 @@ mysql_execute_command(void)
res=0; res=0;
break; break;
} }
/* Fix names if symlinked tables */
if (append_file_to_dir(&lex->create_info.data_file_name, tables->name) ||
append_file_to_dir(&lex->create_info.index_file_name, tables->name))
{
res=-1;
break;
}
if (lex->item_list.elements) // With select if (lex->item_list.elements) // With select
{ {
select_result *result; select_result *result;
...@@ -1404,6 +1413,8 @@ mysql_execute_command(void) ...@@ -1404,6 +1413,8 @@ mysql_execute_command(void)
goto error; goto error;
} }
} }
/* Don't yet allow changing of symlinks with ALTER TABLE */
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */ /* ALTER TABLE ends previous transaction */
if (end_active_trans(thd)) if (end_active_trans(thd))
res= -1; res= -1;
...@@ -2884,3 +2895,31 @@ static void refresh_status(void) ...@@ -2884,3 +2895,31 @@ static void refresh_status(void)
pthread_mutex_unlock(&LOCK_status); pthread_mutex_unlock(&LOCK_status);
pthread_mutex_unlock(&THR_LOCK_keycache); pthread_mutex_unlock(&THR_LOCK_keycache);
} }
/* If pointer is not a null pointer, append filename to it */
static bool append_file_to_dir(char **filename_ptr, char *table_name)
{
char buff[FN_REFLEN],*ptr;
if (!*filename_ptr)
return 0; // nothing to do
/* Check that the filename is not too long and it's a hard path */
if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
!test_if_hard_path(*filename_ptr))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
return 1;
}
/* Fix is using unix filename format on dos */
strmov(buff,*filename_ptr);
convert_dirname(buff);
if (!(ptr=sql_alloc(strlen(buff)+strlen(table_name+1))))
return 1; // End of memory
*filename_ptr=ptr;
ptr=strmov(ptr,buff);
*ptr=FN_LIBCHAR;
strmov(ptr+1,table_name);
return 0;
}
...@@ -1098,7 +1098,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1098,7 +1098,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
TABLE *table,*new_table; TABLE *table,*new_table;
int error; int error;
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN], char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN],
*table_name,*db; *table_name,*db;
char index_file[FN_REFLEN], data_file[FN_REFLEN];
bool use_timestamp=0; bool use_timestamp=0;
ha_rows copied,deleted; ha_rows copied,deleted;
ulonglong next_insert_id; ulonglong next_insert_id;
...@@ -1120,10 +1121,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1120,10 +1121,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{ {
strmov(new_name_buff,new_name); strmov(new_name_buff,new_name);
fn_same(new_name_buff,table_name,3); fn_same(new_name_buff,table_name,3);
// Check if name changed
#ifdef FN_LOWER_CASE #ifdef FN_LOWER_CASE
if (!my_strcasecmp(new_name_buff,table_name))// Check if name changed if (!strcmp(db,new_db) && !my_strcasecmp(new_name_buff,table_name))
#else #else
if (!strcmp(new_name_buff,table_name)) // Check if name changed if (!strcmp(db,new_db) && !strcmp(new_name_buff,table_name))
#endif #endif
new_name=table_name; // No. Make later check easier new_name=table_name; // No. Make later check easier
else else
...@@ -1445,6 +1447,51 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1445,6 +1447,51 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (table->tmp_table) if (table->tmp_table)
create_info->options|=HA_LEX_CREATE_TMP_TABLE; create_info->options|=HA_LEX_CREATE_TMP_TABLE;
/*
Handling of symlinked tables:
If no rename:
Create new data file and index file on the same disk as the
old data and index files.
Copy data.
Rename new data file over old data file and new index file over
old index file.
Symlinks are not changed.
If rename:
Create new data file and index file on the same disk as the
old data and index files. Create also symlinks to point at
the new tables.
Copy data.
At end, rename temporary tables and symlinks to temporary table
to final table name.
Remove old table and old symlinks
If rename is made to another database:
Create new tables in new database.
Copy data.
Remove old table and symlinks.
*/
if (!strcmp(db, new_db)) // Ignore symlink if db changed
{
if (create_info->index_file_name)
{
/* Fix index_file_name to have 'tmp_name' as basename */
strmov(index_file, tmp_name);
create_info->index_file_name=fn_same(index_file,
create_info->index_file_name,
1);
}
if (create_info->data_file_name)
{
/* Fix data_file_name to have 'tmp_name' as basename */
strmov(data_file, tmp_name);
create_info->data_file_name=fn_same(data_file,
create_info->data_file_name,
1);
}
}
if ((error=mysql_create_table(thd, new_db, tmp_name, if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info, create_info,
create_list,key_list,1,1))) // no logging create_list,key_list,1,1))) // no logging
......
...@@ -161,6 +161,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -161,6 +161,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DELAY_KEY_WRITE_SYM %token DELAY_KEY_WRITE_SYM
%token DESC %token DESC
%token DESCRIBE %token DESCRIBE
%token DIRECTORY_SYM
%token DISTINCT %token DISTINCT
%token DISABLE_SYM %token DISABLE_SYM
%token DYNAMIC_SYM %token DYNAMIC_SYM
...@@ -771,6 +772,8 @@ create_table_option: ...@@ -771,6 +772,8 @@ create_table_option:
table_list->next=0; table_list->next=0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION; lex->create_info.used_fields|= HA_CREATE_USED_UNION;
} }
| DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; }
| INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; }
table_types: table_types:
ISAM_SYM { $$= DB_TYPE_ISAM; } ISAM_SYM { $$= DB_TYPE_ISAM; }
...@@ -2383,7 +2386,7 @@ use: USE_SYM ident ...@@ -2383,7 +2386,7 @@ use: USE_SYM ident
/* import, export of files */ /* import, export of files */
load: LOAD DATA_SYM opt_low_priority opt_local INFILE TEXT_STRING load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{ {
Lex->sql_command= SQLCOM_LOAD; Lex->sql_command= SQLCOM_LOAD;
Lex->local_file= $4; Lex->local_file= $4;
...@@ -2584,6 +2587,7 @@ keyword: ...@@ -2584,6 +2587,7 @@ keyword:
| DATETIME {} | DATETIME {}
| DATE_SYM {} | DATE_SYM {}
| DAY_SYM {} | DAY_SYM {}
| DIRECTORY_SYM {}
| DELAY_KEY_WRITE_SYM {} | DELAY_KEY_WRITE_SYM {}
| DISABLE_SYM {} | DISABLE_SYM {}
| DUMPFILE {} | DUMPFILE {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment