mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge with 4.1
This commit is contained in:
266
sql/sql_db.cc
266
sql/sql_db.cc
@ -40,6 +40,197 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
|
||||
const char *db, const char *path,
|
||||
uint level);
|
||||
|
||||
/* Database options hash */
|
||||
static HASH dboptions;
|
||||
static my_bool dboptions_init= 0;
|
||||
static rw_lock_t LOCK_dboptions;
|
||||
|
||||
/* Structure for database options */
|
||||
typedef struct my_dbopt_st
|
||||
{
|
||||
char *name; /* Database name */
|
||||
uint name_length; /* Database length name */
|
||||
CHARSET_INFO *charset; /* Database default character set */
|
||||
} my_dbopt_t;
|
||||
|
||||
|
||||
/*
|
||||
Function we use in the creation of our hash to get key.
|
||||
*/
|
||||
static byte* dboptions_get_key(my_dbopt_t *opt, uint *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
{
|
||||
*length= opt->name_length;
|
||||
return (byte*) opt->name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Function to free dboptions hash element
|
||||
*/
|
||||
|
||||
static void free_dbopt(void *dbopt)
|
||||
{
|
||||
my_free((gptr) dbopt, MYF(0));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initialize database option hash
|
||||
|
||||
SYNOPSIS
|
||||
my_dbopt_init()
|
||||
|
||||
NOTES
|
||||
Must be called before any other database function is called.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 Fatal error
|
||||
*/
|
||||
|
||||
bool my_dbopt_init(void)
|
||||
{
|
||||
bool error= 0;
|
||||
(void) my_rwlock_init(&LOCK_dboptions, NULL);
|
||||
if (!dboptions_init)
|
||||
{
|
||||
dboptions_init= 1;
|
||||
error= hash_init(&dboptions, lower_case_table_names ?
|
||||
&my_charset_bin : system_charset_info,
|
||||
32, 0, 0, (hash_get_key) dboptions_get_key,
|
||||
free_dbopt,0);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Free database option hash.
|
||||
*/
|
||||
|
||||
void my_dbopt_free(void)
|
||||
{
|
||||
if (dboptions_init)
|
||||
{
|
||||
dboptions_init= 0;
|
||||
hash_free(&dboptions);
|
||||
(void) rwlock_destroy(&LOCK_dboptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void my_dbopt_cleanup(void)
|
||||
{
|
||||
rw_wrlock(&LOCK_dboptions);
|
||||
hash_free(&dboptions);
|
||||
hash_init(&dboptions, lower_case_table_names ?
|
||||
&my_charset_bin : system_charset_info,
|
||||
32, 0, 0, (hash_get_key) dboptions_get_key,
|
||||
free_dbopt,0);
|
||||
rw_unlock(&LOCK_dboptions);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find database options in the hash.
|
||||
|
||||
DESCRIPTION
|
||||
Search a database options in the hash, usings its path.
|
||||
Fills "create" on success.
|
||||
|
||||
RETURN VALUES
|
||||
0 on success.
|
||||
1 on error.
|
||||
*/
|
||||
|
||||
static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
|
||||
{
|
||||
my_dbopt_t *opt;
|
||||
uint length;
|
||||
my_bool error= 1;
|
||||
|
||||
length= (uint) strlen(dbname);
|
||||
|
||||
rw_rdlock(&LOCK_dboptions);
|
||||
if ((opt= (my_dbopt_t*) hash_search(&dboptions, (byte*) dbname, length)))
|
||||
{
|
||||
create->default_table_charset= opt->charset;
|
||||
error= 0;
|
||||
}
|
||||
rw_unlock(&LOCK_dboptions);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Writes database options into the hash.
|
||||
|
||||
DESCRIPTION
|
||||
Inserts database options into the hash, or updates
|
||||
options if they are already in the hash.
|
||||
|
||||
RETURN VALUES
|
||||
0 on success.
|
||||
1 on error.
|
||||
*/
|
||||
|
||||
static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
|
||||
{
|
||||
my_dbopt_t *opt;
|
||||
uint length;
|
||||
my_bool error= 0;
|
||||
DBUG_ENTER("put_dbopt");
|
||||
|
||||
length= (uint) strlen(dbname);
|
||||
|
||||
rw_wrlock(&LOCK_dboptions);
|
||||
if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (byte*) dbname, length)))
|
||||
{
|
||||
/* Options are not in the hash, insert them */
|
||||
char *tmp_name;
|
||||
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
|
||||
&opt, (uint) sizeof(*opt), &tmp_name, length+1,
|
||||
NullS))
|
||||
{
|
||||
error= 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
opt->name= tmp_name;
|
||||
strmov(opt->name, dbname);
|
||||
opt->name_length= length;
|
||||
|
||||
if ((error= my_hash_insert(&dboptions, (byte*) opt)))
|
||||
{
|
||||
my_free((gptr) opt, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update / write options in hash */
|
||||
opt->charset= create->default_table_charset;
|
||||
|
||||
end:
|
||||
rw_unlock(&LOCK_dboptions);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Deletes database options from the hash.
|
||||
*/
|
||||
|
||||
void del_dbopt(const char *path)
|
||||
{
|
||||
my_dbopt_t *opt;
|
||||
rw_wrlock(&LOCK_dboptions);
|
||||
if ((opt= (my_dbopt_t *)hash_search(&dboptions, path, strlen(path))))
|
||||
hash_delete(&dboptions, (byte*) opt);
|
||||
rw_unlock(&LOCK_dboptions);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create database options file:
|
||||
|
||||
@ -57,15 +248,20 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
|
||||
char buf[256]; // Should be enough for one option
|
||||
bool error=1;
|
||||
|
||||
if (!create->default_table_charset)
|
||||
create->default_table_charset= thd->variables.collation_server;
|
||||
|
||||
if (put_dbopt(path, create))
|
||||
return 1;
|
||||
|
||||
if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
|
||||
{
|
||||
ulong length;
|
||||
CHARSET_INFO *cs= ((create && create->default_table_charset) ?
|
||||
create->default_table_charset :
|
||||
thd->variables.collation_server);
|
||||
length= my_sprintf(buf,(buf,
|
||||
"default-character-set=%s\ndefault-collation=%s\n",
|
||||
cs->csname,cs->name));
|
||||
length= (ulong) (strxnmov(buf, sizeof(buf), "default-character-set=",
|
||||
create->default_table_charset->csname,
|
||||
"\ndefault-collation=",
|
||||
create->default_table_charset->name,
|
||||
"\n", NullS) - buf);
|
||||
|
||||
/* Error is written by my_write */
|
||||
if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME)))
|
||||
@ -102,6 +298,12 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
|
||||
|
||||
bzero((char*) create,sizeof(*create));
|
||||
create->default_table_charset= thd->variables.collation_server;
|
||||
|
||||
/* Check if options for this database are already in the hash */
|
||||
if (!get_dbopt(path, create))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
/* Otherwise, load options from the .opt file */
|
||||
if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
|
||||
{
|
||||
IO_CACHE cache;
|
||||
@ -138,9 +340,16 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
|
||||
}
|
||||
}
|
||||
}
|
||||
error=0;
|
||||
end_io_cache(&cache);
|
||||
my_close(file,MYF(0));
|
||||
/*
|
||||
Put the loaded value into the hash.
|
||||
Note that another thread could've added the same
|
||||
entry to the hash after we called get_dbopt(),
|
||||
but it's not an error, as put_dbopt() takes this
|
||||
possibility into account.
|
||||
*/
|
||||
error= put_dbopt(path, create);
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -168,10 +377,11 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
|
||||
bool silent)
|
||||
{
|
||||
char path[FN_REFLEN+16];
|
||||
long result=1;
|
||||
int error = 0;
|
||||
long result= 1;
|
||||
int error= 0;
|
||||
MY_STAT stat_info;
|
||||
uint create_options = create_info ? create_info->options : 0;
|
||||
uint create_options= create_info ? create_info->options : 0;
|
||||
uint path_len;
|
||||
DBUG_ENTER("mysql_create_db");
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
|
||||
@ -185,17 +395,18 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
|
||||
|
||||
/* Check directory */
|
||||
strxmov(path, mysql_data_home, "/", db, NullS);
|
||||
unpack_dirname(path,path); // Convert if not unix
|
||||
path_len= unpack_dirname(path,path); // Convert if not unix
|
||||
path[path_len-1]= 0; // Remove last '/' from path
|
||||
|
||||
if (my_stat(path,&stat_info,MYF(0)))
|
||||
{
|
||||
if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
|
||||
{
|
||||
my_error(ER_DB_CREATE_EXISTS,MYF(0),db);
|
||||
error = -1;
|
||||
error= -1;
|
||||
goto exit;
|
||||
}
|
||||
result = 0;
|
||||
result= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -204,23 +415,23 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
|
||||
my_error(EE_STAT, MYF(0),path,my_errno);
|
||||
goto exit;
|
||||
}
|
||||
strend(path)[-1]=0; // Remove last '/' from path
|
||||
if (my_mkdir(path,0777,MYF(0)) < 0)
|
||||
{
|
||||
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
|
||||
error = -1;
|
||||
error= -1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
unpack_dirname(path, path);
|
||||
strcat(path,MY_DB_OPT_FILE);
|
||||
path[path_len-1]= FN_LIBCHAR;
|
||||
strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
|
||||
if (write_db_opt(thd, path, create_info))
|
||||
{
|
||||
/*
|
||||
Could not create options file.
|
||||
Restore things to beginning.
|
||||
*/
|
||||
path[path_len]= 0;
|
||||
if (rmdir(path) >= 0)
|
||||
{
|
||||
error= -1;
|
||||
@ -271,7 +482,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
|
||||
{
|
||||
char path[FN_REFLEN+16];
|
||||
long result=1;
|
||||
int error = 0;
|
||||
int error= 0;
|
||||
DBUG_ENTER("mysql_alter_db");
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
|
||||
@ -281,7 +492,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
|
||||
goto exit2;
|
||||
|
||||
/* Check directory */
|
||||
(void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE);
|
||||
strxmov(path, mysql_data_home, "/", db, "/", MY_DB_OPT_FILE, NullS);
|
||||
fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
|
||||
if ((error=write_db_opt(thd, path, create_info)))
|
||||
goto exit;
|
||||
@ -334,9 +545,11 @@ exit2:
|
||||
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
||||
{
|
||||
long deleted=0;
|
||||
int error = 0;
|
||||
int error= 0;
|
||||
char path[FN_REFLEN+16], tmp_db[NAME_LEN+1];
|
||||
MY_DIR *dirp;
|
||||
uint length;
|
||||
my_dbopt_t *dbopt;
|
||||
DBUG_ENTER("mysql_rm_db");
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
|
||||
@ -349,9 +562,13 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
||||
}
|
||||
|
||||
(void) sprintf(path,"%s/%s",mysql_data_home,db);
|
||||
unpack_dirname(path,path); // Convert if not unix
|
||||
length= unpack_dirname(path,path); // Convert if not unix
|
||||
strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
|
||||
del_dbopt(path); // Remove dboption hash entry
|
||||
path[length]= '\0'; // Remove file name
|
||||
|
||||
/* See if the directory exists */
|
||||
if (!(dirp = my_dir(path,MYF(MY_DONT_SORT))))
|
||||
if (!(dirp= my_dir(path,MYF(MY_DONT_SORT))))
|
||||
{
|
||||
if (!if_exists)
|
||||
{
|
||||
@ -635,8 +852,10 @@ bool mysql_change_db(THD *thd, const char *name)
|
||||
int length, db_length;
|
||||
char *dbname=my_strdup((char*) name,MYF(MY_WME));
|
||||
char path[FN_REFLEN];
|
||||
ulong db_access;
|
||||
HA_CREATE_INFO create;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
ulong db_access;
|
||||
#endif
|
||||
DBUG_ENTER("mysql_change_db");
|
||||
|
||||
if (!dbname || !(db_length= strlen(dbname)))
|
||||
@ -697,4 +916,3 @@ bool mysql_change_db(THD *thd, const char *name)
|
||||
thd->variables.collation_database= thd->db_charset;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user