Commit 4de7e18b authored by ingo@mysql.com's avatar ingo@mysql.com

Hand-resolved auto merge

parents 61fd95d1 376f2526
...@@ -250,6 +250,7 @@ client/thimble ...@@ -250,6 +250,7 @@ client/thimble
client/thread_test client/thread_test
client_test client_test
cmd-line-utils/libedit/common.h cmd-line-utils/libedit/common.h
cmd-line-utils/libedit/makelist
comon.h comon.h
config.cache config.cache
config.h config.h
...@@ -300,6 +301,7 @@ innobase/ib_config.h ...@@ -300,6 +301,7 @@ innobase/ib_config.h
innobase/ib_config.h.in innobase/ib_config.h.in
innobase/stamp-h1 innobase/stamp-h1
insert_test insert_test
install
isam/isamchk isam/isamchk
isam/isamlog isam/isamlog
isam/pack_isam isam/pack_isam
...@@ -504,6 +506,7 @@ mysys/main.cc ...@@ -504,6 +506,7 @@ mysys/main.cc
mysys/ste5KbMa mysys/ste5KbMa
mysys/test_charset mysys/test_charset
mysys/test_dir mysys/test_dir
mysys/test_gethwaddr
mysys/test_io_cache mysys/test_io_cache
mysys/test_thr_alarm mysys/test_thr_alarm
mysys/test_thr_lock mysys/test_thr_lock
...@@ -646,5 +649,3 @@ vio/test-ssl ...@@ -646,5 +649,3 @@ vio/test-ssl
vio/test-sslclient vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
mysys/test_gethwaddr
cmd-line-utils/libedit/makelist
...@@ -90,6 +90,20 @@ ...@@ -90,6 +90,20 @@
#define HA_NOT_READ_PREFIX_LAST 32 /* No support for index_read_last() */ #define HA_NOT_READ_PREFIX_LAST 32 /* No support for index_read_last() */
#define HA_KEY_READ_ONLY 64 /* Support HA_EXTRA_KEYREAD */ #define HA_KEY_READ_ONLY 64 /* Support HA_EXTRA_KEYREAD */
/*
Bits in index_ddl_flags(KEY *wanted_index)
for what ddl you can do with index
If none is set, the wanted type of index is not supported
by the handler at all. See WorkLog 1563.
*/
#define HA_DDL_SUPPORT 1 /* Supported by handler */
#define HA_DDL_WITH_LOCK 2 /* Can create/drop with locked table */
#define HA_DDL_ONLINE 4 /* Can create/drop without lock */
/* Return value for ddl methods */
#define HA_DDL_NOT_IMPLEMENTED -1
/* /*
Parameters for open() (in register form->filestat) Parameters for open() (in register form->filestat)
HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
...@@ -355,6 +369,20 @@ public: ...@@ -355,6 +369,20 @@ public:
{ {
return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEY_READ_ONLY); return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEY_READ_ONLY);
} }
virtual ulong index_ddl_flags(KEY *wanted_index) const
{
return (HA_DDL_SUPPORT);
}
virtual int add_index(TABLE *table, KEY *key_info, uint num_of_keys)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online add index");
return (HA_DDL_NOT_IMPLEMENTED);
}
virtual int drop_index(TABLE *table, uint *key_num, uint num_of_keys)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online drop index");
return (HA_DDL_NOT_IMPLEMENTED);
}
virtual uint max_record_length() const =0; virtual uint max_record_length() const =0;
virtual uint max_keys() const =0; virtual uint max_keys() const =0;
virtual uint max_key_parts() const =0; virtual uint max_key_parts() const =0;
......
...@@ -488,6 +488,11 @@ int mysql_handle_derived(LEX *lex); ...@@ -488,6 +488,11 @@ int mysql_handle_derived(LEX *lex);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field, Item ***copy_func, Field **from_field,
bool group,bool modify_item); bool group,bool modify_item);
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
List<create_field> &fields,
List<Key> &keys, uint &db_options,
handler *file, KEY *&key_info_buffer,
uint &key_count, int select_field_count);
int mysql_create_table(THD *thd,const char *db, const char *table_name, int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<Key> &keys, List<create_field> &fields, List<Key> &keys,
...@@ -504,7 +509,19 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, ...@@ -504,7 +509,19 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
uint order_num, ORDER *order, uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
bool simple_alter=0);
int real_alter_table(THD *thd, char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
TABLE *table,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP, enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
...@@ -520,6 +537,10 @@ bool mysql_rename_table(enum db_type base, ...@@ -520,6 +537,10 @@ bool mysql_rename_table(enum db_type base,
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys); int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list); List<Alter_drop> &drop_list);
int mysql_add_column(THD *thd, TABLE_LIST *table_list,
List<create_field> &fields);
int mysql_drop_column(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
uint order_num, ORDER *order, ha_rows limit, uint order_num, ORDER *order, ha_rows limit,
...@@ -923,6 +944,9 @@ void unlock_table_names(THD *thd, TABLE_LIST *table_list, ...@@ -923,6 +944,9 @@ void unlock_table_names(THD *thd, TABLE_LIST *table_list,
void unireg_init(ulong options); void unireg_init(ulong options);
void unireg_end(void); void unireg_end(void);
int mysql_create_frm(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
uint key_count,KEY *key_info,handler *db_type);
int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info, int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field, List<create_field> &create_field,
uint key_count,KEY *key_info); uint key_count,KEY *key_info);
......
...@@ -2604,45 +2604,6 @@ static void mysql_rm_tmp_tables(void) ...@@ -2604,45 +2604,6 @@ static void mysql_rm_tmp_tables(void)
} }
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
List<Alter_drop> drop;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0,
DUP_ERROR));
}
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
{
List<create_field> fields;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0,
DUP_ERROR));
}
/***************************************************************************** /*****************************************************************************
unireg support functions unireg support functions
......
...@@ -509,6 +509,14 @@ public: ...@@ -509,6 +509,14 @@ public:
}; };
typedef class st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
#define ALTER_ADD_COLUMN 1
#define ALTER_DROP_COLUMN 2
#define ALTER_CHANGE_COLUMN 4
#define ALTER_ADD_INDEX 8
#define ALTER_DROP_INDEX 16
#define ALTER_RENAME 32
#define ALTER_ORDER 64
#define ALTER_OPTIONS 128
/* The state of the lex parsing. This is saved in the THD struct */ /* The state of the lex parsing. This is saved in the THD struct */
...@@ -578,6 +586,7 @@ typedef struct st_lex ...@@ -578,6 +586,7 @@ typedef struct st_lex
uint grant, grant_tot_col, which_columns; uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option; uint fk_delete_opt, fk_update_opt, fk_match_option;
uint slave_thd_opt; uint slave_thd_opt;
uint alter_flags;
uint8 describe; uint8 describe;
bool drop_if_exists, drop_temporary, local_file; bool drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog; bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog;
......
...@@ -2391,6 +2391,7 @@ unsent_create_error: ...@@ -2391,6 +2391,7 @@ unsent_create_error:
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements, select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
lex->alter_flags,
lex->duplicates, lex->duplicates,
lex->alter_keys_onoff, lex->alter_keys_onoff,
lex->tablespace_op, lex->tablespace_op,
...@@ -2541,7 +2542,7 @@ unsent_create_error: ...@@ -2541,7 +2542,7 @@ unsent_create_error:
res= mysql_alter_table(thd, NullS, NullS, &create_info, res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
0, (ORDER *) 0, 0, (ORDER *) 0, 0,
DUP_ERROR); DUP_ERROR);
} }
else else
......
...@@ -289,11 +289,15 @@ int quick_rm_table(enum db_type base,const char *db, ...@@ -289,11 +289,15 @@ int quick_rm_table(enum db_type base,const char *db,
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
int error=0; int error=0;
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table_name,reg_ext); if (snprintf(path, sizeof(path), "%s/%s/%s%s",
mysql_data_home, db, table_name, reg_ext)>= (int)sizeof(path))
return 1;
unpack_filename(path,path); unpack_filename(path,path);
if (my_delete(path,MYF(0))) if (my_delete(path,MYF(0)))
error=1; /* purecov: inspected */ error=1; /* purecov: inspected */
sprintf(path,"%s/%s/%s",mysql_data_home,db,table_name); if (snprintf(path, sizeof(path), "%s/%s/%s",
mysql_data_home, db, table_name)>= (int)sizeof(path))
return 1;
unpack_filename(path,path); unpack_filename(path,path);
return ha_delete_table(base,path) || error; return ha_delete_table(base,path) || error;
} }
...@@ -385,85 +389,45 @@ void check_duplicates_in_interval(const char *set_or_name, ...@@ -385,85 +389,45 @@ void check_duplicates_in_interval(const char *set_or_name,
} }
/* /*
Create a table Preparation for table creation
SYNOPSIS SYNOPSIS
mysql_create_table() mysql_prepare_table()
thd Thread object thd Thread object
db Database
table_name Table name
create_info Create information (like MAX_ROWS) create_info Create information (like MAX_ROWS)
fields List of fields to create fields List of fields to create
keys List of keys to create keys List of keys to create
tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
no_log Don't log the query to binary log.
DESCRIPTION DESCRIPTION
If one creates a temporary table, this is automaticly opened Prepares the table and key structures for table creation.
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
select_field_count is also used for CREATE ... SELECT,
and must be zero for standard create of table.
RETURN VALUES RETURN VALUES
0 ok 0 ok
-1 error -1 error
*/ */
int mysql_create_table(THD *thd,const char *db, const char *table_name, int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
HA_CREATE_INFO *create_info,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,bool tmp_table,bool no_log, List<Key> &keys, bool tmp_table, uint &db_options,
uint select_field_count) handler *file, KEY *&key_info_buffer,
uint &key_count, int select_field_count)
{ {
char path[FN_REFLEN]; const char *key_name;
const char *key_name, *alias;
create_field *sql_field,*dup_field; create_field *sql_field,*dup_field;
int error= -1; uint field,null_fields,blob_columns;
uint db_options,field,null_fields,blob_columns;
ulong pos; ulong pos;
KEY *key_info,*key_info_buffer; KEY *key_info;
KEY_PART_INFO *key_part_info; KEY_PART_INFO *key_part_info;
int auto_increment=0; int auto_increment=0;
int timestamps= 0, timestamps_with_niladic= 0; int timestamps= 0, timestamps_with_niladic= 0;
handler *file; handler *file;
int field_no,dup_no; int field_no,dup_no;
enum db_type new_db_type; int select_field_pos,auto_increment=0;
DBUG_ENTER("mysql_create_table"); DBUG_ENTER("mysql_prepare_table");
/* Check for duplicate fields and check type of table to create */
if (!fields.elements)
{
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
DBUG_RETURN(-1);
}
List_iterator<create_field> it(fields),it2(fields); List_iterator<create_field> it(fields),it2(fields);
int select_field_pos=fields.elements - select_field_count; select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0; null_fields=blob_columns=0;
if ((new_db_type= ha_checktype(create_info->db_type)) !=
create_info->db_type)
{
create_info->db_type= new_db_type;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER),
ha_get_storage_engine(new_db_type),
table_name);
}
db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
alias= table_case_name(create_info, table_name);
file=get_new_handler((TABLE*) 0, create_info->db_type);
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
(file->table_flags() & HA_NO_TEMP_TABLES))
{
my_error(ER_ILLEGAL_HA,MYF(0),table_name);
DBUG_RETURN(-1);
}
for (field_no=0; (sql_field=it++) ; field_no++) for (field_no=0; (sql_field=it++) ; field_no++)
{ {
...@@ -681,13 +645,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -681,13 +645,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Create keys */ /* Create keys */
List_iterator<Key> key_iterator(keys); List_iterator<Key> key_iterator(keys);
uint key_parts=0, key_count=0, fk_key_count=0; uint key_parts=0, fk_key_count=0;
List<Key> keys_in_order; // Add new keys here List<Key> keys_in_order; // Add new keys here
bool primary_key=0,unique_key=0; bool primary_key=0,unique_key=0;
Key *key; Key *key;
uint tmp, key_number; uint tmp, key_number;
/* Calculate number of key segements */ /* Calculate number of key segements */
key_count=0;
while ((key=key_iterator++)) while ((key=key_iterator++))
{ {
...@@ -944,7 +909,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -944,7 +909,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{ {
/* not a critical problem */ /* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length); if (snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
length)>= (int)sizeof(warn_buff))
DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff); ER_TOO_LONG_KEY, warn_buff);
} }
...@@ -981,7 +948,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -981,7 +948,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{ {
/* not a critical problem */ /* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length); if (snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
length)>= (int)sizeof(warn_buff))
DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff); ER_TOO_LONG_KEY, warn_buff);
} }
...@@ -1061,15 +1030,100 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -1061,15 +1030,100 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Sort keys in optimized order */ /* Sort keys in optimized order */
qsort((gptr) key_info_buffer, key_count, sizeof(KEY), (qsort_cmp) sort_keys); qsort((gptr) key_info_buffer, key_count, sizeof(KEY), (qsort_cmp) sort_keys);
DBUG_RETURN(0);
}
/*
Create a table
SYNOPSIS
mysql_create_table()
thd Thread object
db Database
table_name Table name
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
no_log Don't log the query to binary log.
DESCRIPTION
If one creates a temporary table, this is automaticly opened
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
select_field_count is also used for CREATE ... SELECT,
and must be zero for standard create of table.
RETURN VALUES
0 ok
-1 error
*/
int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
List<create_field> &fields,
List<Key> &keys,bool tmp_table,bool no_log,
uint select_field_count)
{
char path[FN_REFLEN];
const char *alias;
int error= -1;
uint db_options, key_count;
KEY *key_info_buffer;
handler *file;
enum db_type new_db_type;
DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */
if (!fields.elements)
{
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
DBUG_RETURN(-1);
}
if ((new_db_type= ha_checktype(create_info->db_type)) !=
create_info->db_type)
{
create_info->db_type= new_db_type;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER),
ha_get_storage_engine(new_db_type),
table_name);
}
db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
alias= table_case_name(create_info, table_name);
file=get_new_handler((TABLE*) 0, create_info->db_type);
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
(file->table_flags() & HA_NO_TEMP_TABLES))
{
my_error(ER_ILLEGAL_HA,MYF(0),table_name);
DBUG_RETURN(-1);
}
if (mysql_prepare_table(thd, create_info, fields,
keys, tmp_table, db_options, file,
key_info_buffer, key_count,
select_field_count))
DBUG_RETURN(-1);
/* Check if table exists */ /* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{ {
sprintf(path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix, if (snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s",
current_pid, thd->thread_id, thd->tmp_table++,reg_ext); mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id,
thd->tmp_table++, reg_ext)>= (int)sizeof(path))
DBUG_RETURN(-1);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
} }
else else
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,alias,reg_ext); if (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home, db,
alias, reg_ext)>= (int)sizeof(path))
DBUG_RETURN(-1);
unpack_filename(path,path); unpack_filename(path,path);
/* Check if table already exists */ /* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
...@@ -1163,17 +1217,23 @@ static char * ...@@ -1163,17 +1217,23 @@ static char *
make_unique_key_name(const char *field_name,KEY *start,KEY *end) make_unique_key_name(const char *field_name,KEY *start,KEY *end)
{ {
char buff[MAX_FIELD_NAME],*buff_end; char buff[MAX_FIELD_NAME],*buff_end;
int remain;
if (!check_if_keyname_exists(field_name,start,end) && if (!check_if_keyname_exists(field_name,start,end) &&
my_strcasecmp(system_charset_info,field_name,primary_key_name)) my_strcasecmp(system_charset_info,field_name,primary_key_name))
return (char*) field_name; // Use fieldname return (char*) field_name; // Use fieldname
buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4); buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4);
for (uint i=2 ; ; i++) /*ingo 2004-04-07 only 3 chars + '\0' left, so need to limit to 2 digit*/
for (uint i=2 ; i< 100; i++)
{ {
sprintf(buff_end,"_%d",i); remain= (int)sizeof(buff)- (buff_end- buff);
if (snprintf(buff_end, remain, "_%d", i)>= remain)
return NULL;
if (!check_if_keyname_exists(buff,start,end)) if (!check_if_keyname_exists(buff,start,end))
return sql_strdup(buff); return sql_strdup(buff);
} }
/*ingo 2004-04-07 dedicated return is inevitable*/
return NULL;
} }
/**************************************************************************** /****************************************************************************
...@@ -1271,8 +1331,12 @@ mysql_rename_table(enum db_type base, ...@@ -1271,8 +1331,12 @@ mysql_rename_table(enum db_type base,
my_casedn_str(system_charset_info, tmp_to); my_casedn_str(system_charset_info, tmp_to);
new_name= tmp_to; new_name= tmp_to;
} }
(void) sprintf(from,"%s/%s/%s",mysql_data_home,old_db,old_name); if (snprintf(from, sizeof(from), "%s/%s/%s",
(void) sprintf(to,"%s/%s/%s",mysql_data_home,new_db,new_name); mysql_data_home, old_db, old_name)>= (int)sizeof(from))
DBUG_RETURN(1);
if (snprintf(to, sizeof(to), "%s/%s/%s",
mysql_data_home, new_db, new_name)>= (int)sizeof(to))
DBUG_RETURN(1);
fn_format(from,from,"","",4); fn_format(from,from,"","",4);
fn_format(to,to, "","",4); fn_format(to,to, "","",4);
...@@ -1407,7 +1471,9 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, ...@@ -1407,7 +1471,9 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
reg_ext)) reg_ext))
DBUG_RETURN(-1); // protect buffer overflow DBUG_RETURN(-1); // protect buffer overflow
sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name); if (snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
mysql_real_data_home, db, table_name)>= (int)sizeof(dst_path))
DBUG_RETURN(-1);
if (lock_and_wait_for_table_name(thd,table)) if (lock_and_wait_for_table_name(thd,table))
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -1491,7 +1557,12 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1491,7 +1557,12 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
if (!my_stat(from, &stat_info, MYF(0))) if (!my_stat(from, &stat_info, MYF(0)))
goto end; // Can't use USE_FRM flag goto end; // Can't use USE_FRM flag
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); if (snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
from, current_pid, thd->thread_id)>= (int)sizeof(tmp))
{
error= -1;
goto end;
}
/* If we could open the table, close it */ /* If we could open the table, close it */
if (table_list->table) if (table_list->table)
...@@ -1626,7 +1697,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1626,7 +1697,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store(table_name, system_charset_info); protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info); protocol->store(operator_name, system_charset_info);
protocol->store("error", 5, system_charset_info); protocol->store("error", 5, system_charset_info);
sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name); if (snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name)>= (int)sizeof(buff))
goto err;
protocol->store(buff, system_charset_info); protocol->store(buff, system_charset_info);
close_thread_tables(thd); close_thread_tables(thd);
table->table=0; // For query cache table->table=0; // For query cache
...@@ -1948,8 +2021,11 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -1948,8 +2021,11 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
{ {
if (find_temporary_table(thd, db, table_name)) if (find_temporary_table(thd, db, table_name))
goto table_exists; goto table_exists;
sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix, if (snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s",
current_pid, thd->thread_id, thd->tmp_table++,reg_ext); mysql_tmpdir, tmp_file_prefix, current_pid,
thd->thread_id, thd->tmp_table++, reg_ext)>=
(int)sizeof(dst_path))
DBUG_RETURN(-1);
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE; create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
} }
else else
...@@ -2007,7 +2083,9 @@ table_exists: ...@@ -2007,7 +2083,9 @@ table_exists:
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{ {
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name); if (snprintf(warn_buff, sizeof(warn_buff),
ER(ER_TABLE_EXISTS_ERROR), table_name)>= (int)sizeof(warn_buff))
DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,warn_buff); ER_TABLE_EXISTS_ERROR,warn_buff);
res= 0; res= 0;
...@@ -2118,19 +2196,307 @@ err: ...@@ -2118,19 +2196,307 @@ err:
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
List<Alter_drop> drop;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
int rc;
uint idx;
uint db_options;
uint key_count;
TABLE *table;
Field **f_ptr;
KEY *key_info_buffer;
char path[FN_REFLEN];
DBUG_ENTER("mysql_create_index");
/*
Try to use online generation of index.
This requires that all indexes can be created online.
Otherwise, the old alter table procedure is executed.
Open the table to have access to the correct table handler.
*/
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/*
The add_index method takes an array of KEY structs for the new indexes.
Preparing a new table structure generates this array.
It needs a list with all fields of the table, which does not need to
be correct in every respect. The field names are important.
*/
for (f_ptr= table->field; *f_ptr; f_ptr++)
{
create_field *c_fld= new create_field(*f_ptr, *f_ptr);
c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
fields.push_back(c_fld);
}
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
db_options= 0;
if (mysql_prepare_table(thd, &create_info, fields,
keys, /*tmp_table*/ 0, db_options, table->file,
key_info_buffer, key_count,
/*select_field_count*/ 0))
DBUG_RETURN(-1);
/*
Check if all keys can be generated with the add_index method.
If anyone cannot, then take the old way.
*/
for (idx=0; idx< key_count; idx++)
{
DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ;
}
if ((idx < key_count)|| !key_count)
{
/* Re-initialize the create_info, which was changed by prepare table. */
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
/* Cleanup the fields list. We do not want to create existing fields. */
fields.delete_elements();
if (real_alter_table(thd, table_list->db, table_list->real_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_INDEX, DUP_ERROR))
/*don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(-1);
}
else
{
if (table->file->add_index(table, key_info_buffer, key_count)||
(snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
table_list->db, (lower_case_table_names == 2)?
table_list->alias: table_list->real_name, reg_ext)>=
(int)sizeof(path))||
! unpack_filename(path, path)||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/*don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(-1);
}
/*don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(0);
}
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
{
List<create_field> fields;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
uint idx;
uint db_options;
uint key_count;
uint *key_numbers;
TABLE *table;
Field **f_ptr;
KEY *key_info;
KEY *key_info_buffer;
char path[FN_REFLEN];
DBUG_ENTER("mysql_drop_index");
/*
Try to use online generation of index.
This requires that all indexes can be created online.
Otherwise, the old alter table procedure is executed.
Open the table to have access to the correct table handler.
*/
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/*
The drop_index method takes an array of key numbers.
It cannot get more entries than keys in the table.
*/
key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
key_count= 0;
/*
Get the number of each key and check if it can be created online.
*/
List_iterator<Alter_drop> drop_it(drop);
Alter_drop *drop_key;
while ((drop_key= drop_it++))
{
/* Find the key in the table. */
key_info=table->key_info;
for (idx=0; idx< table->keys; idx++, key_info++)
{
if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
break;
}
if (idx>= table->keys)
{
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
/*
Check if the key can be generated with the add_index method.
If anyone cannot, then take the old way.
*/
DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
if (!(table->file->index_ddl_flags(table->key_info+idx)&
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ;
key_numbers[key_count++]= idx;
}
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
if ((drop_key)|| (drop.elements<= 0))
{
if (real_alter_table(thd, table_list->db, table_list->real_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_INDEX, DUP_ERROR))
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
else
{
db_options= 0;
if (table->file->drop_index(table, key_numbers, key_count)||
mysql_prepare_table(thd, &create_info, fields,
keys, /*tmp_table*/ 0, db_options, table->file,
key_info_buffer, key_count,
/*select_field_count*/ 0)||
(snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
table_list->db, (lower_case_table_names == 2)?
table_list->alias: table_list->real_name, reg_ext)>=
(int)sizeof(path))||
! unpack_filename(path, path)||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(0);
}
int mysql_add_column(THD *thd, TABLE_LIST *table_list,
List<create_field> &fields)
{
List<Alter_drop> drop;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_add_column");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
TABLE *table;
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
DBUG_RETURN(real_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_COLUMN, DUP_ERROR));
}
int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
{
List<create_field> fields;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_drop_column");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
TABLE *table;
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
DBUG_RETURN(real_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_COLUMN, DUP_ERROR));
}
int mysql_alter_table(THD *thd,char *new_db, char *new_name, int mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
TABLE_LIST *table_list, TABLE_LIST *table_list,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
uint order_num, ORDER *order, uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff,
enum tablespace_op_type tablespace_op,
bool simple_alter)
{
DBUG_ENTER("mysql_alter_table");
mysql_ha_closeall(thd, table_list);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
tablespace_op));
if (alter_flags == ALTER_ADD_INDEX)
DBUG_RETURN(mysql_create_index(thd, table_list, keys));
if (alter_flags == ALTER_DROP_INDEX)
DBUG_RETURN(mysql_drop_index(thd, table_list, drop_list));
if (alter_flags == ALTER_ADD_COLUMN)
DBUG_RETURN(mysql_add_column(thd, table_list, fields));
if (alter_flags == ALTER_DROP_COLUMN)
DBUG_RETURN(mysql_drop_column(thd, table_list, drop_list));
TABLE *table;
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
DBUG_RETURN(real_alter_table(thd, new_db, new_name,
create_info, table_list, table, fields,
keys, drop_list, alter_list,
order_num, order, alter_flags,
handle_duplicates, keys_onoff,
tablespace_op, simple_alter));
}
int real_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
TABLE *table,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
enum tablespace_op_type tablespace_op, enum tablespace_op_type tablespace_op,
bool simple_alter) bool simple_alter)
{ {
TABLE *table,*new_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];
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias; char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
...@@ -2139,7 +2505,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2139,7 +2505,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
ulonglong next_insert_id; ulonglong next_insert_id;
uint db_create_options, used_fields; uint db_create_options, used_fields;
enum db_type old_db_type,new_db_type; enum db_type old_db_type,new_db_type;
DBUG_ENTER("mysql_alter_table"); DBUG_ENTER("real_alter_table");
thd->proc_info="init"; thd->proc_info="init";
table_name=table_list->real_name; table_name=table_list->real_name;
...@@ -2152,15 +2518,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2152,15 +2518,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
used_fields=create_info->used_fields; used_fields=create_info->used_fields;
mysql_ha_closeall(thd, table_list);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
tablespace_op));
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/* Check that we are not trying to rename to an existing table */ /* Check that we are not trying to rename to an existing table */
if (new_name) if (new_name)
{ {
...@@ -2355,6 +2712,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2355,6 +2712,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (def) if (def)
{ // Field is changed { // Field is changed
def->field=field; def->field=field;
if (def->sql_type == FIELD_TYPE_TIMESTAMP)
use_timestamp=1;
if (!def->after) if (!def->after)
{ {
create_list.push_back(def); create_list.push_back(def);
...@@ -2364,6 +2723,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2364,6 +2723,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else else
{ // Use old field value { // Use old field value
create_list.push_back(def=new create_field(field,field)); create_list.push_back(def=new create_field(field,field));
if (def->sql_type == FIELD_TYPE_TIMESTAMP)
use_timestamp=1;
alter_it.rewind(); // Change default if ALTER alter_it.rewind(); // Change default if ALTER
Alter_column *alter; Alter_column *alter;
while ((alter=alter_it++)) while ((alter=alter_it++))
...@@ -2526,8 +2887,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2526,8 +2887,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD); db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
(void) sprintf(tmp_name,"%s-%lx_%lx", tmp_file_prefix, current_pid, if (snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
thd->thread_id); current_pid, thd->thread_id)>= (int)sizeof(tmp_name))
goto err;
create_info->db_type=new_db_type; create_info->db_type=new_db_type;
if (!create_info->comment) if (!create_info->comment)
create_info->comment=table->comment; create_info->comment=table->comment;
...@@ -2606,7 +2968,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2606,7 +2968,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else else
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
(void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,tmp_name); if (snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
new_db, tmp_name)>= (int)sizeof(path))
goto err;
fn_format(path,path,"","",4); fn_format(path,path,"","",4);
new_table=open_temporary_table(thd, path, new_db, tmp_name,0); new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
} }
...@@ -2689,8 +3053,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2689,8 +3053,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/ */
thd->proc_info="rename result table"; thd->proc_info="rename result table";
sprintf(old_name,"%s2-%lx-%lx", tmp_file_prefix, current_pid, if (snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
thd->thread_id); current_pid, thd->thread_id)>= (int)sizeof(old_name))
goto err;
if (new_name != table_name || new_db != db) if (new_name != table_name || new_db != db)
{ {
if (!access(new_name_buff,F_OK)) if (!access(new_name_buff,F_OK))
...@@ -2813,7 +3178,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2813,7 +3178,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
shutdown. shutdown.
*/ */
char path[FN_REFLEN]; char path[FN_REFLEN];
(void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,table_name); if (snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
new_db, table_name)>= (int)sizeof(path))
goto err;
fn_format(path,path,"","",4); fn_format(path,path,"","",4);
table=open_temporary_table(thd, path, new_db, tmp_name,0); table=open_temporary_table(thd, path, new_db, tmp_name,0);
if (table) if (table)
...@@ -2831,8 +3198,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2831,8 +3198,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
query_cache_invalidate3(thd, table_list, 0); query_cache_invalidate3(thd, table_list, 0);
end_temporary: end_temporary:
sprintf(tmp_name, ER(ER_INSERT_INFO), (ulong) (copied + deleted), if (snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) deleted, (ulong) thd->cuted_fields); (ulong) (copied + deleted), (ulong) deleted,
(ulong) thd->cuted_fields)>= (int)sizeof(tmp_name))
goto err;
send_ok(thd,copied+deleted,0L,tmp_name); send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0; thd->some_tables_deleted=0;
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -1439,10 +1439,29 @@ attribute: ...@@ -1439,10 +1439,29 @@ attribute:
{ Lex->on_update_value= new Item_func_now_local(); } { Lex->on_update_value= new Item_func_now_local(); }
| AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
| SERIAL_SYM DEFAULT VALUE_SYM | SERIAL_SYM DEFAULT VALUE_SYM
{ Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; } {
| opt_primary KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; } LEX *lex=Lex;
| UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; } lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
| UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } lex->alter_flags|= ALTER_ADD_INDEX;
}
| opt_primary KEY_SYM
{
LEX *lex=Lex;
lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
lex->alter_flags|= ALTER_ADD_INDEX;
}
| UNIQUE_SYM
{
LEX *lex=Lex;
lex->type|= UNIQUE_FLAG;
lex->alter_flags|= ALTER_ADD_INDEX;
}
| UNIQUE_SYM KEY_SYM
{
LEX *lex=Lex;
lex->type|= UNIQUE_KEY_FLAG;
lex->alter_flags|= ALTER_ADD_INDEX;
}
| COMMENT_SYM TEXT_STRING_sys { Lex->comment= &$2; } | COMMENT_SYM TEXT_STRING_sys { Lex->comment= &$2; }
| BINARY { Lex->type|= BINCMP_FLAG; } | BINARY { Lex->type|= BINCMP_FLAG; }
| COLLATE_SYM collation_name | COLLATE_SYM collation_name
...@@ -1700,6 +1719,7 @@ alter: ...@@ -1700,6 +1719,7 @@ alter:
lex->alter_keys_onoff=LEAVE_AS_IS; lex->alter_keys_onoff=LEAVE_AS_IS;
lex->tablespace_op=NO_TABLESPACE_OP; lex->tablespace_op=NO_TABLESPACE_OP;
lex->simple_alter=1; lex->simple_alter=1;
lex->alter_flags=0;
} }
alter_list alter_list
{} {}
...@@ -1718,16 +1738,28 @@ alter_list: ...@@ -1718,16 +1738,28 @@ alter_list:
| alter_list ',' alter_list_item; | alter_list ',' alter_list_item;
add_column: add_column:
ADD opt_column { Lex->change=0; }; ADD opt_column
{
LEX *lex=Lex;
lex->change=0;
lex->alter_flags|= ALTER_ADD_COLUMN;
};
alter_list_item: alter_list_item:
add_column column_def opt_place { Lex->simple_alter=0; } add_column column_def opt_place { Lex->simple_alter=0; }
| ADD key_def { Lex->simple_alter=0; } | ADD key_def
{
LEX *lex=Lex;
lex->simple_alter=0;
lex->alter_flags|= ALTER_ADD_INDEX;
}
| add_column '(' field_list ')' { Lex->simple_alter=0; } | add_column '(' field_list ')' { Lex->simple_alter=0; }
| CHANGE opt_column field_ident | CHANGE opt_column field_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->change= $3.str; lex->simple_alter=0; lex->change= $3.str;
lex->simple_alter=0;
lex->alter_flags|= ALTER_CHANGE_COLUMN;
} }
field_spec opt_place field_spec opt_place
| MODIFY_SYM opt_column field_ident | MODIFY_SYM opt_column field_ident
...@@ -1738,6 +1770,7 @@ alter_list_item: ...@@ -1738,6 +1770,7 @@ alter_list_item:
lex->comment=0; lex->comment=0;
lex->charset= NULL; lex->charset= NULL;
lex->simple_alter=0; lex->simple_alter=0;
lex->alter_flags|= ALTER_CHANGE_COLUMN;
} }
type opt_attribute type opt_attribute
{ {
...@@ -1756,7 +1789,9 @@ alter_list_item: ...@@ -1756,7 +1789,9 @@ alter_list_item:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN, lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
$3.str)); lex->simple_alter=0; $3.str));
lex->simple_alter=0;
lex->alter_flags|= ALTER_DROP_COLUMN;
} }
| DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; } | DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; }
| DROP PRIMARY_SYM KEY_SYM | DROP PRIMARY_SYM KEY_SYM
...@@ -1765,6 +1800,7 @@ alter_list_item: ...@@ -1765,6 +1800,7 @@ alter_list_item:
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
primary_key_name)); primary_key_name));
lex->simple_alter=0; lex->simple_alter=0;
lex->alter_flags|= ALTER_DROP_INDEX;
} }
| DROP key_or_index field_ident | DROP key_or_index field_ident
{ {
...@@ -1772,6 +1808,7 @@ alter_list_item: ...@@ -1772,6 +1808,7 @@ alter_list_item:
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str)); $3.str));
lex->simple_alter=0; lex->simple_alter=0;
lex->alter_flags|= ALTER_DROP_INDEX;
} }
| DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; } | DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; }
| ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; } | ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; }
...@@ -1780,18 +1817,21 @@ alter_list_item: ...@@ -1780,18 +1817,21 @@ alter_list_item:
LEX *lex=Lex; LEX *lex=Lex;
lex->alter_list.push_back(new Alter_column($3.str,$6)); lex->alter_list.push_back(new Alter_column($3.str,$6));
lex->simple_alter=0; lex->simple_alter=0;
lex->alter_flags|= ALTER_CHANGE_COLUMN;
} }
| ALTER opt_column field_ident DROP DEFAULT | ALTER opt_column field_ident DROP DEFAULT
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0)); lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0));
lex->simple_alter=0; lex->simple_alter=0;
lex->alter_flags|= ALTER_CHANGE_COLUMN;
} }
| RENAME opt_to table_ident | RENAME opt_to table_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->select_lex.db=$3->db.str; lex->select_lex.db=$3->db.str;
lex->name= $3->table.str; lex->name= $3->table.str;
lex->alter_flags|= ALTER_RENAME;
} }
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate | CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
{ {
...@@ -1814,8 +1854,18 @@ alter_list_item: ...@@ -1814,8 +1854,18 @@ alter_list_item:
HA_CREATE_USED_DEFAULT_CHARSET); HA_CREATE_USED_DEFAULT_CHARSET);
lex->simple_alter= 0; lex->simple_alter= 0;
} }
| create_table_options_space_separated { Lex->simple_alter=0; } | create_table_options_space_separated
| order_clause { Lex->simple_alter=0; }; {
LEX *lex=Lex;
lex->simple_alter=0;
lex->alter_flags|= ALTER_OPTIONS;
}
| order_clause
{
LEX *lex=Lex;
lex->simple_alter=0;
lex->alter_flags|= ALTER_ORDER;
};
opt_column: opt_column:
/* empty */ {} /* empty */ {}
......
...@@ -47,10 +47,11 @@ static bool make_empty_rec(int file, enum db_type table_type, ...@@ -47,10 +47,11 @@ static bool make_empty_rec(int file, enum db_type table_type,
uint reclength,uint null_fields); uint reclength,uint null_fields);
int rea_create_table(THD *thd, my_string file_name, int mysql_create_frm(THD *thd, my_string file_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<create_field> &create_fields, List<create_field> &create_fields,
uint keys, KEY *key_info) uint keys, KEY *key_info,
handler *db_file)
{ {
uint reclength,info_length,screens,key_info_length,maxlength,null_fields; uint reclength,info_length,screens,key_info_length,maxlength,null_fields;
File file; File file;
...@@ -58,12 +59,12 @@ int rea_create_table(THD *thd, my_string file_name, ...@@ -58,12 +59,12 @@ int rea_create_table(THD *thd, my_string file_name,
uchar fileinfo[64],forminfo[288],*keybuff; uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames; TYPELIB formnames;
uchar *screen_buff; uchar *screen_buff;
handler *db_file;
DBUG_ENTER("rea_create_table"); DBUG_ENTER("rea_create_table");
formnames.type_names=0; formnames.type_names=0;
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0))) if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
DBUG_RETURN(1); DBUG_RETURN(1);
if (db_file == NULL)
db_file=get_new_handler((TABLE*) 0, create_info->db_type); db_file=get_new_handler((TABLE*) 0, create_info->db_type);
if (pack_header(forminfo, create_info->db_type,create_fields,info_length, if (pack_header(forminfo, create_info->db_type,create_fields,info_length,
screens, create_info->table_options, db_file)) screens, create_info->table_options, db_file))
...@@ -155,8 +156,7 @@ int rea_create_table(THD *thd, my_string file_name, ...@@ -155,8 +156,7 @@ int rea_create_table(THD *thd, my_string file_name,
if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) && if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
my_sync(file, MYF(MY_WME))) my_sync(file, MYF(MY_WME)))
goto err2; goto err2;
if (my_close(file,MYF(MY_WME)) || if (my_close(file,MYF(MY_WME)))
ha_create_table(file_name,create_info,0))
goto err3; goto err3;
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -166,6 +166,23 @@ err: ...@@ -166,6 +166,23 @@ err:
err2: err2:
VOID(my_close(file,MYF(MY_WME))); VOID(my_close(file,MYF(MY_WME)));
err3: err3:
DBUG_RETURN(1);
} /* mysql_create_frm */
int rea_create_table(THD *thd, my_string file_name,
HA_CREATE_INFO *create_info,
List<create_field> &create_fields,
uint keys, KEY *key_info)
{
DBUG_ENTER("rea_create_table");
if (mysql_create_frm(thd, file_name, create_info,
create_fields, keys, key_info, NULL) ||
ha_create_table(file_name,create_info,0))
goto err;
DBUG_RETURN(0);
err:
my_delete(file_name,MYF(0)); my_delete(file_name,MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} /* rea_create_table */ } /* rea_create_table */
......
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