Commit 4de5c672 authored by unknown's avatar unknown

bug #28309 First insert violates UNIQUE constraint - was "memory" table empty?

  
If we have lower_case_table_names == 2 (usually on case insensitive file
systems) we sometimes make 'homedir' part of the path sent to the
handler into lowercase. So in this case HEAP engine couldn't properly
find and remove HP_SHARE, what caused the bug.


sql/handler.cc:
  bug #28309 First insert violates UNIQUE constraint - was "memory" table empty?
      
  we don't turn homedirectory part of the path into lowercase
sql/mysql_priv.h:
  bug #28309 First insert violates UNIQUE constraint - was "memory" table empty?
      
  mysql_data_home_len introduced
sql/mysqld.cc:
  bug #28309 First insert violates UNIQUE constraint - was "memory" table empty?
      
  mysql_data_home_len value is set with the mysql_data_home
parent 420508b8
...@@ -1392,6 +1392,25 @@ bool ha_flush_logs(handlerton *db_type) ...@@ -1392,6 +1392,25 @@ bool ha_flush_logs(handlerton *db_type)
return FALSE; return FALSE;
} }
static const char *check_lowercase_names(handler *file, const char *path,
char *tmp_path)
{
if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
return path;
/* Ensure that table handler get path in lower case */
if (tmp_path != path)
strmov(tmp_path, path);
/*
we only should turn into lowercase database/table part
so start the process after homedirectory
*/
my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
return tmp_path;
}
/** @brief /** @brief
This should return ENOENT if the file doesn't exists. This should return ENOENT if the file doesn't exists.
The .frm file will be deleted only if we return 0 or ENOENT The .frm file will be deleted only if we return 0 or ENOENT
...@@ -1415,13 +1434,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, ...@@ -1415,13 +1434,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
DBUG_RETURN(ENOENT); DBUG_RETURN(ENOENT);
if (lower_case_table_names == 2 && !(file->ha_table_flags() & HA_FILE_BASED)) path= check_lowercase_names(file, path, tmp_path);
{
/* Ensure that table handler get path in lower case */
strmov(tmp_path, path);
my_casedn_str(files_charset_info, tmp_path);
path= tmp_path;
}
if ((error= file->delete_table(path)) && generate_warning) if ((error= file->delete_table(path)) && generate_warning)
{ {
/* /*
...@@ -2598,15 +2611,7 @@ int ha_create_table(THD *thd, const char *path, ...@@ -2598,15 +2611,7 @@ int ha_create_table(THD *thd, const char *path,
if (update_create_info) if (update_create_info)
update_create_info_from_table(create_info, &table); update_create_info_from_table(create_info, &table);
name= share.path.str; name= check_lowercase_names(table.file, share.path.str, name_buff);
if (lower_case_table_names == 2 &&
!(table.file->ha_table_flags() & HA_FILE_BASED))
{
/* Ensure that handler gets name in lower case */
strmov(name_buff, name);
my_casedn_str(files_charset_info, name_buff);
name= name_buff;
}
error= table.file->create(name, &table, create_info); error= table.file->create(name, &table, create_info);
VOID(closefrm(&table, 0)); VOID(closefrm(&table, 0));
...@@ -2656,7 +2661,8 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) ...@@ -2656,7 +2661,8 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
frmblob and frmlen are set, write the frm to disk frmblob and frmlen are set, write the frm to disk
*/ */
(void)strxnmov(path,FN_REFLEN-1,mysql_data_home,"/",db,"/",name,NullS); (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,FN_ROOTDIR,
db,FN_ROOTDIR,name,NullS);
// Save the frm file // Save the frm file
error= writefrm(path, frmblob, frmlen); error= writefrm(path, frmblob, frmlen);
my_free(frmblob, MYF(0)); my_free(frmblob, MYF(0));
...@@ -2677,12 +2683,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) ...@@ -2677,12 +2683,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
update_create_info_from_table(&create_info, &table); update_create_info_from_table(&create_info, &table);
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE; create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
if (lower_case_table_names == 2 && check_lowercase_names(table.file, path, path);
!(table.file->ha_table_flags() & HA_FILE_BASED))
{
/* Ensure that handler gets name in lower case */
my_casedn_str(files_charset_info, path);
}
error=table.file->create(path,&table,&create_info); error=table.file->create(path,&table,&create_info);
VOID(closefrm(&table, 1)); VOID(closefrm(&table, 1));
......
...@@ -1601,6 +1601,7 @@ extern int creating_table; // How many mysql_create_table() are running ...@@ -1601,6 +1601,7 @@ extern int creating_table; // How many mysql_create_table() are running
*/ */
extern time_t server_start_time; extern time_t server_start_time;
extern uint mysql_data_home_len;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[],
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
......
...@@ -491,6 +491,7 @@ key_map key_map_full(0); // Will be initialized later ...@@ -491,6 +491,7 @@ key_map key_map_full(0); // Will be initialized later
const char *opt_date_time_formats[3]; const char *opt_date_time_formats[3];
uint mysql_data_home_len;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
char server_version[SERVER_VERSION_LENGTH]; char server_version[SERVER_VERSION_LENGTH];
char *mysqld_unix_port, *opt_mysql_tmpdir; char *mysqld_unix_port, *opt_mysql_tmpdir;
...@@ -3770,6 +3771,7 @@ int main(int argc, char **argv) ...@@ -3770,6 +3771,7 @@ int main(int argc, char **argv)
mysql_data_home= mysql_data_home_buff; mysql_data_home= mysql_data_home_buff;
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
mysql_data_home[1]=0; mysql_data_home[1]=0;
mysql_data_home_len= 2;
if ((user_info= check_user(mysqld_user))) if ((user_info= check_user(mysqld_user)))
{ {
...@@ -7056,6 +7058,7 @@ static void mysql_init_variables(void) ...@@ -7056,6 +7058,7 @@ static void mysql_init_variables(void)
sizeof(mysql_real_data_home)-1); sizeof(mysql_real_data_home)-1);
mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here
mysql_data_home_buff[1]=0; mysql_data_home_buff[1]=0;
mysql_data_home_len= 2;
/* Replication parameters */ /* Replication parameters */
master_user= (char*) "test"; master_user= (char*) "test";
...@@ -7217,6 +7220,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -7217,6 +7220,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1); strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
/* Correct pointer set by my_getopt (for embedded library) */ /* Correct pointer set by my_getopt (for embedded library) */
mysql_data_home= mysql_real_data_home; mysql_data_home= mysql_real_data_home;
mysql_data_home_len= strlen(mysql_data_home);
break; break;
case 'u': case 'u':
if (!mysqld_user || !strcmp(mysqld_user, argument)) if (!mysqld_user || !strcmp(mysqld_user, argument))
......
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