ALTER DATABASE DEFAULT CHARACTER SET latin1;

parent a3d8e086
...@@ -289,7 +289,8 @@ inline THD *_current_thd(void) ...@@ -289,7 +289,8 @@ inline THD *_current_thd(void)
#define prepare_execute(A) ((A)->command == COM_EXECUTE) #define prepare_execute(A) ((A)->command == COM_EXECUTE)
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent); int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
......
...@@ -31,6 +31,96 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, ...@@ -31,6 +31,96 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path, const char *db, const char *path,
uint level); uint level);
/*
Create database options file:
Currently databse default charset is only stored there.
*/
static int write_db_opt(THD *thd, char *db, HA_CREATE_INFO *create, char *fn)
{
register File file;
char buf[256]; // Should be enough
int error=0;
if ((file=my_create(fn,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
sprintf(buf,"default-character-set=%s\n",
(create && create->table_charset) ?
create->table_charset->name : "DEFAULT");
if (my_write(file,(byte*)buf,strlen(buf),MYF(MY_NABP+MY_WME)))
{
// QQ : should we send more suitable error message?
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
error = -1;
goto exit;
}
my_close(file,MYF(0));
}
else
{
// QQ : should we send more suitable error message?
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
error = -1;
goto exit;
}
exit:
return error;
}
/*
Load database options file:
*/
static int load_db_opt(THD *thd,char *fn)
{
register File file;
char buf[256]="";
if ((file=my_open(fn,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0)
{
int nbytes=my_read(file,(byte*)buf,sizeof(buf)-1,MYF(0));
if ( nbytes >= 0 )
{
char *ln=buf;
char *pe=buf+nbytes;
buf[nbytes]='\0';
for ( ln=buf; ln<pe; )
{
char *le,*val;
for ( le=ln, val=0 ; le<pe ; le++ )
{
switch(le[0])
{
case '=':
le[0]='\0';
val=le+1;
le++;
break;
case '\r':
case '\n':
le[0]='\0';
le++;
for( ; (le[0]=='\r' || le[0]=='\n') ; le++);
if (!strcmp(ln,"default-character-set") && val && val[0])
{
thd->db_charset=get_charset_by_name(val, MYF(0));
}
goto cnt;
break;
}
}
cnt:
ln=le;
}
}
my_close(file,MYF(0));
}
return 0;
}
/* db-name is already validated when we come here */ /* db-name is already validated when we come here */
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
...@@ -39,10 +129,10 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent ...@@ -39,10 +129,10 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent
MY_DIR *dirp; MY_DIR *dirp;
long result=1; long result=1;
int error = 0; int error = 0;
DBUG_ENTER("mysql_create_db");
register File file;
uint create_options = create_info ? create_info->options : 0; uint create_options = create_info ? create_info->options : 0;
DBUG_ENTER("mysql_create_db");
VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
// do not create database if another thread is holding read lock // do not create database if another thread is holding read lock
...@@ -77,43 +167,81 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent ...@@ -77,43 +167,81 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent
} }
} }
/*
Create database options file:
Currently databse default charset is only stored there.
*/
strcat(path,"/"); strcat(path,"/");
unpack_dirname(path,path); unpack_dirname(path,path);
strcat(path,MY_DB_OPT_FILE); strcat(path,MY_DB_OPT_FILE);
if ((file=my_create(path,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) if ((error=write_db_opt(thd,db,create_info,path)))
{ goto exit;
sprintf(path,"default-character-set=%s\n",
(create_info && create_info->table_charset) ?
create_info->table_charset->name : "DEFAULT");
if (my_write(file,(byte*) path,strlen(path),MYF(MY_NABP+MY_WME))) if (!silent)
{ {
// QQ : should we send more suitable error message? if (!thd->query)
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); {
error = -1; thd->query = path;
goto exit; thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
path);
} }
my_close(file,MYF(0)); {
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
} }
else }
if (thd->query == path)
{ {
// QQ : should we send more suitable error message? thd->query = 0; // just in case
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); thd->query_length = 0;
error = -1; }
goto exit; send_ok(&thd->net, result);
} }
exit:
start_waiting_global_read_lock(thd);
exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
DBUG_RETURN(error);
}
/* db-name is already validated when we come here */
int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
{
char path[FN_REFLEN+16];
MY_DIR *dirp;
long result=1;
int error = 0;
DBUG_ENTER("mysql_create_db");
register File file;
uint create_options = create_info ? create_info->options : 0;
printf("alter database\n");
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
// do not alter database if another thread is holding read lock
if (wait_if_global_read_lock(thd,0))
{
error= -1;
goto exit2;
}
/* Check directory */
(void)sprintf(path,"%s/%s", mysql_data_home, db);
strcat(path,"/");
unpack_dirname(path,path); // Convert if not unix
strcat(path,MY_DB_OPT_FILE);
if ((error=write_db_opt(thd,db,create_info,path)))
goto exit;
if (!silent) if (!silent)
{ {
if (!thd->query) if (!thd->query)
{ {
thd->query = path; thd->query = path;
thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- thd->query_length = (uint) (strxmov(path,"alter database ", db, NullS)-
path); path);
} }
{ {
...@@ -139,6 +267,10 @@ exit2: ...@@ -139,6 +267,10 @@ exit2:
DBUG_RETURN(error); DBUG_RETURN(error);
} }
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
static TYPELIB deletable_extentions= static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts}; {array_elements(del_exts)-1,"del_exts", del_exts};
...@@ -368,7 +500,6 @@ bool mysql_change_db(THD *thd,const char *name) ...@@ -368,7 +500,6 @@ bool mysql_change_db(THD *thd,const char *name)
char path[FN_REFLEN]; char path[FN_REFLEN];
uint db_access; uint db_access;
DBUG_ENTER("mysql_change_db"); DBUG_ENTER("mysql_change_db");
register File file;
if (!dbname || !(db_length=strip_sp(dbname))) if (!dbname || !(db_length=strip_sp(dbname)))
{ {
...@@ -419,53 +550,11 @@ bool mysql_change_db(THD *thd,const char *name) ...@@ -419,53 +550,11 @@ bool mysql_change_db(THD *thd,const char *name)
thd->db_length=db_length; thd->db_length=db_length;
thd->db_access=db_access; thd->db_access=db_access;
/*
Load database options file:
*/
strcat(path,"/"); strcat(path,"/");
unpack_dirname(path,path); unpack_dirname(path,path);
strcat(path,MY_DB_OPT_FILE); strcat(path,MY_DB_OPT_FILE);
if ((file=my_open(path,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) load_db_opt(thd,path);
{
int nbytes=my_read(file,(byte*) path,sizeof(path),MYF(0));
if ( nbytes >= 0 )
{
char *ln=path;
char *pe=path+nbytes;
path[nbytes]='\0';
for ( ln=path; ln<pe; )
{
char *le,*val;
for ( le=ln, val=0 ; le<pe ; le++ )
{
switch(le[0])
{
case '=':
le[0]='\0';
val=le+1;
le++;
break;
case '\r':
case '\n':
le[0]='\0';
le++;
for( ; (le[0]=='\r' || le[0]=='\n') ; le++);
if (!strcmp(ln,"default-character-set") && val && val[0])
{
thd->db_charset=get_charset_by_name(val, MYF(0));
}
goto cnt;
break;
}
}
cnt:
ln=le;
}
}
my_close(file,MYF(0));
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -44,7 +44,8 @@ enum enum_sql_command { ...@@ -44,7 +44,8 @@ enum enum_sql_command {
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
......
...@@ -2328,6 +2328,23 @@ mysql_execute_command(void) ...@@ -2328,6 +2328,23 @@ mysql_execute_command(void)
res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0); res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0);
break; break;
} }
case SQLCOM_ALTER_DB:
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
if (check_access(thd,DROP_ACL,lex->name,0,1))
break;
if (thd->locked_tables || thd->active_transaction())
{
send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
goto error;
}
res=mysql_alter_db(thd,lex->name,&lex->create_info,0);
break;
}
case SQLCOM_CREATE_FUNCTION: case SQLCOM_CREATE_FUNCTION:
if (check_access(thd,INSERT_ACL,"mysql",0,1)) if (check_access(thd,INSERT_ACL,"mysql",0,1))
break; break;
......
...@@ -885,12 +885,7 @@ create_table_option: ...@@ -885,12 +885,7 @@ 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;
} }
| CHARSET EQ DEFAULT | CHARSET EQ charset_or_nocharset
{
Lex->create_info.table_charset=NULL;
Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
}
| CHARSET EQ charset
{ {
Lex->create_info.table_charset=Lex->charset; Lex->create_info.table_charset=Lex->charset;
Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
...@@ -1139,6 +1134,10 @@ charset: ...@@ -1139,6 +1134,10 @@ charset:
} }
}; };
charset_or_nocharset:
charset
| DEFAULT {Lex->charset=NULL; }
opt_binary: opt_binary:
/* empty */ { Lex->charset=NULL; } /* empty */ { Lex->charset=NULL; }
| BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; } | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; }
...@@ -1146,7 +1145,7 @@ opt_binary: ...@@ -1146,7 +1145,7 @@ opt_binary:
default_charset: default_charset:
/* empty */ { Lex->charset=NULL; } /* empty */ { Lex->charset=NULL; }
| DEFAULT CHAR_SYM SET charset ; | DEFAULT CHAR_SYM SET charset_or_nocharset ;
references: references:
REFERENCES table_ident REFERENCES table_ident
...@@ -1271,6 +1270,15 @@ alter: ...@@ -1271,6 +1270,15 @@ alter:
} }
alter_list; alter_list;
| ALTER DATABASE ident default_charset
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_ALTER_DB;
lex->name=$3.str;
lex->create_info.table_charset=lex->charset;
}
alter_list: alter_list:
| alter_list_item | alter_list_item
| alter_list ',' alter_list_item; | alter_list ',' alter_list_item;
......
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