From f5297edcae7167e3c8e4eaa06bfa8353e4c4b81d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 Mar 2004 19:22:14 +0200 Subject: [PATCH 1/3] Worklog#1563 - Support of on-line CREATE/DROP INDEX. This is to enable table handlers to implement online create/drop index. It consists of some parts: - New default handler methods in handler.h - Split of mysql_alter_table. It decides if only one kind of alteration is to be done (e.g. only create indexes or only drop indexes etc.) It then calls the specialized new handler method if the handler implements it. Otherwise it calls real_alter_table. - The parser sets flags for each alter operation detected in a command. These are used by mysql_alter_table for the decision. - mysql_prepare_table is pulled out of mysql_create_table. This is also used by mysql_create_index to prepare the key structure array for the handler. It is also used by mysql_create_index and mysql_drop_index to prepare a call to mysql_create_frm. - mysql_create_frm is pulled out of rea_create_table for use by mysql_create_index and mysql_drop_index after the index is created/dropped. Thanks to Antony who supplied most of the changes. sql/handler.h: Worklog#1563 - Support of on-line CREATE/DROP INDEX. New virtual handler methods with default implementation and return flags. sql/mysql_priv.h: Worklog#1563 - Support of on-line CREATE/DROP INDEX. New function prototypes. mysql_prepare_table is pulled out of mysql_create_table. It prepares a table structure, which is used by mysql_create_table, mysql_create_index and mysql_drop_index. real_alter_table is pulled out of mysql_alter_table. The latter only looks if the requested operation can be done by specialized functions or else calls real_alter_table, which does the real thing. mysql_add_column and mysql_drop_colunm are for future use. They simply call real_alter_table. mysql_create_frm is pulled out of rea_create_table. It is called also from mysql_create_index and mysql_drop_index after successful create/drop index. mysql_alter_table prototype is extended by the new alter_flags argument. sql/sql_base.cc: Worklog#1563 - Support of on-line CREATE/DROP INDEX. mysql_create_index and mysql_drop_index moved to sql_table.cc. sql/sql_lex.h: Worklog#1563 - Support of on-line CREATE/DROP INDEX. Definitions for the new alter_flags. sql/sql_parse.cc: Worklog#1563 - Support of on-line CREATE/DROP INDEX. Extend the calls to mysql_alter_table by the new alter_flags argument. sql/sql_table.cc: Worklog#1563 - Support of on-line CREATE/DROP INDEX. mysql_prepare_table is pulled out of mysql_create_table. mysql_create_index and mysql_drop_index are changed so that they use the new handler functions if the handler implements them. mysql_add_column and mysql_drop_column are for future use. They simply call real_alter_table. mysql_alter_table only decides which function to use for the requested operation. real_alter_table implements most of what mysql_alter_table did before. sql/sql_yacc.yy: Worklog#1563 - Support of on-line CREATE/DROP INDEX. Set the alter_flags where appropriate. sql/unireg.cc: Worklog#1563 - Support of on-line CREATE/DROP INDEX. mysql_create_frm is pulled out of rea_create_table. --- sql/handler.h | 28 +++ sql/mysql_priv.h | 26 ++- sql/sql_base.cc | 39 ---- sql/sql_lex.h | 9 + sql/sql_parse.cc | 3 +- sql/sql_table.cc | 459 ++++++++++++++++++++++++++++++++++++++++------- sql/sql_yacc.yy | 70 ++++++-- sql/unireg.cc | 29 ++- 8 files changed, 538 insertions(+), 125 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index 35a93709e98..97bc8385145 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -89,6 +89,20 @@ #define HA_NOT_READ_PREFIX_LAST 32 /* No support for index_read_last() */ #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) HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED @@ -354,6 +368,20 @@ public: { 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_keys() const =0; virtual uint max_key_parts() const =0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 126675a6e46..986439925d8 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -493,6 +493,11 @@ int mysql_handle_derived(LEX *lex); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, bool group,bool modify_item); +int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, + List &fields, + List &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, HA_CREATE_INFO *create_info, List &fields, List &keys, @@ -509,11 +514,23 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, List &fields, List &keys,List &drop_list, List &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 &fields, + List &keys,List &drop_list, + List &alter_list, + 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 mysql_create_like_table(THD *thd, TABLE_LIST *table, HA_CREATE_INFO *create_info, Table_ident *src_table); @@ -525,6 +542,10 @@ bool mysql_rename_table(enum db_type base, int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys); int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop_list); +int mysql_add_column(THD *thd, TABLE_LIST *table_list, + List &fields); +int mysql_drop_column(THD *thd, TABLE_LIST *table_list, + List &drop_list); int mysql_update(THD *thd,TABLE_LIST *tables,List &fields, List &values,COND *conds, uint order_num, ORDER *order, ha_rows limit, @@ -927,6 +948,9 @@ void unlock_table_names(THD *thd, TABLE_LIST *table_list, void unireg_init(ulong options); void unireg_end(void); +int mysql_create_frm(THD *thd, my_string file_name,HA_CREATE_INFO *create_info, + List &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, List &create_field, uint key_count,KEY *key_info); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1766063c5ec..ef9f568ed92 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2497,45 +2497,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 &keys) -{ - List fields; - List drop; - List 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 &drop) -{ - List fields; - List keys; - List 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 diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ba8fe0d8792..02c56708ec6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -508,6 +508,14 @@ public: }; 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 */ @@ -578,6 +586,7 @@ typedef struct st_lex uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; uint slave_thd_opt; + uint alter_flags; uint8 describe; bool drop_if_exists, drop_temporary, local_file; bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7e6d0ca2434..9951cf06d91 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2355,6 +2355,7 @@ mysql_execute_command(THD *thd) lex->key_list, lex->drop_list, lex->alter_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, + lex->alter_flags, lex->duplicates, lex->alter_keys_onoff, lex->tablespace_op, @@ -2503,7 +2504,7 @@ mysql_execute_command(THD *thd) res= mysql_alter_table(thd, NullS, NullS, &create_info, tables, lex->create_list, lex->key_list, lex->drop_list, lex->alter_list, - 0, (ORDER *) 0, + 0, (ORDER *) 0, 0, DUP_ERROR); } else diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8011809d6ab..eff3393e368 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -385,84 +385,42 @@ void check_duplicates_in_interval(const char *set_or_name, } /* - Create a table + Preparation for table creation SYNOPSIS - mysql_create_table() + mysql_prepare_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. + Prepares the table and key structures for table creation. RETURN VALUES 0 ok -1 error */ -int mysql_create_table(THD *thd,const char *db, const char *table_name, - HA_CREATE_INFO *create_info, +int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, List &fields, - List &keys,bool tmp_table,bool no_log, - uint select_field_count) + List &keys, bool tmp_table, uint &db_options, + handler *file, KEY *&key_info_buffer, + uint &key_count, int select_field_count) { - char path[FN_REFLEN]; - const char *key_name, *alias; + const char *key_name; create_field *sql_field,*dup_field; - int error= -1; - uint db_options,field,null_fields,blob_columns; + uint field,null_fields,blob_columns; ulong pos; - KEY *key_info,*key_info_buffer; + KEY *key_info; KEY_PART_INFO *key_part_info; - int auto_increment=0; - handler *file; int field_no,dup_no; - enum db_type new_db_type; - DBUG_ENTER("mysql_create_table"); + int select_field_pos,auto_increment=0; + 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 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; - 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++) { @@ -649,13 +607,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, /* Create keys */ List_iterator key_iterator(keys); - uint key_parts=0, key_count=0, fk_key_count=0; + uint key_parts=0, fk_key_count=0; List keys_in_order; // Add new keys here bool primary_key=0,unique_key=0; Key *key; uint tmp, key_number; /* Calculate number of key segements */ + key_count=0; while ((key=key_iterator++)) { @@ -1029,6 +988,87 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, /* Sort keys in optimized order */ 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 &fields, + List &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 */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { @@ -2064,19 +2104,311 @@ err: 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 &keys) +{ + List fields; + List drop; + List 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<= 0)) + { + /* 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)|| + ((void) sprintf(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), 0)|| + ! 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 &drop) +{ + List fields; + List keys; + List 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 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)|| + ((void) sprintf(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), 0)|| + ! 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 &fields) +{ + List drop; + List keys; + List 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 &drop) +{ + List fields; + List keys; + List 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, HA_CREATE_INFO *create_info, TABLE_LIST *table_list, List &fields, List &keys,List &drop_list, List &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) { - TABLE *table,*new_table; + DBUG_ENTER("mysql_alter_table"); + + /* !!!!!!!! WARNING: This comment must be removed after a decision !!!!!!!!! + I'm not sure if the next two commands are at the right place here. + I guess that closing all is necessary before table dropping which is + part of alter table, but may be harmful before online DDLs. + So I would put both behind the DDL branches right before open_ltable. + !!!!!!!! WARNING: This comment must be removed after a decision !!!!!! */ + 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 &fields, + List &keys,List &drop_list, + List &alter_list, + 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) +{ + TABLE *new_table; int error; char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN]; char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias; @@ -2086,7 +2418,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ulonglong next_insert_id; uint save_time_stamp,db_create_options, used_fields; enum db_type old_db_type,new_db_type; - DBUG_ENTER("mysql_alter_table"); + DBUG_ENTER("real_alter_table"); thd->proc_info="init"; table_name=table_list->real_name; @@ -2099,15 +2431,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } 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 */ if (new_name) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c87de8a5cd5..61189d1e491 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1441,10 +1441,29 @@ attribute: | DEFAULT signed_literal { Lex->default_value=$2; } | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } | 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; } - | UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; } - | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } + { + LEX *lex=Lex; + lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_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; } | COLLATE_SYM collation_name { @@ -1697,6 +1716,7 @@ alter: lex->alter_keys_onoff=LEAVE_AS_IS; lex->tablespace_op=NO_TABLESPACE_OP; lex->simple_alter=1; + lex->alter_flags=0; } alter_list {} @@ -1715,16 +1735,28 @@ alter_list: | alter_list ',' alter_list_item; 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: 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; } | CHANGE opt_column field_ident { 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 | MODIFY_SYM opt_column field_ident @@ -1735,6 +1767,7 @@ alter_list_item: lex->comment=0; lex->charset= NULL; lex->simple_alter=0; + lex->alter_flags|= ALTER_CHANGE_COLUMN; } type opt_attribute { @@ -1752,7 +1785,9 @@ alter_list_item: { LEX *lex=Lex; 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 PRIMARY_SYM KEY_SYM @@ -1761,6 +1796,7 @@ alter_list_item: lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, primary_key_name)); lex->simple_alter=0; + lex->alter_flags|= ALTER_DROP_INDEX; } | DROP key_or_index field_ident { @@ -1768,6 +1804,7 @@ alter_list_item: lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, $3.str)); lex->simple_alter=0; + lex->alter_flags|= ALTER_DROP_INDEX; } | DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; } | ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; } @@ -1776,21 +1813,34 @@ alter_list_item: LEX *lex=Lex; lex->alter_list.push_back(new Alter_column($3.str,$6)); lex->simple_alter=0; + lex->alter_flags|= ALTER_CHANGE_COLUMN; } | ALTER opt_column field_ident DROP DEFAULT { LEX *lex=Lex; lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0)); lex->simple_alter=0; + lex->alter_flags|= ALTER_CHANGE_COLUMN; } | RENAME opt_to table_ident { LEX *lex=Lex; lex->select_lex.db=$3->db.str; lex->name= $3->table.str; + lex->alter_flags|= ALTER_RENAME; } - | create_table_options_space_separated { Lex->simple_alter=0; } - | order_clause { Lex->simple_alter=0; }; + | create_table_options_space_separated + { + 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: /* empty */ {} diff --git a/sql/unireg.cc b/sql/unireg.cc index 6f127b57f64..350dc7e5a43 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -47,10 +47,11 @@ static bool make_empty_rec(int file, enum db_type table_type, 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, List &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; File file; @@ -58,13 +59,13 @@ int rea_create_table(THD *thd, my_string file_name, uchar fileinfo[64],forminfo[288],*keybuff; TYPELIB formnames; uchar *screen_buff; - handler *db_file; DBUG_ENTER("rea_create_table"); formnames.type_names=0; if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0))) DBUG_RETURN(1); - db_file=get_new_handler((TABLE*) 0, create_info->db_type); + if (db_file == NULL) + db_file=get_new_handler((TABLE*) 0, create_info->db_type); if (pack_header(forminfo, create_info->db_type,create_fields,info_length, screens, create_info->table_options, db_file)) { @@ -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) && my_sync(file, MYF(MY_WME))) goto err2; - if (my_close(file,MYF(MY_WME)) || - ha_create_table(file_name,create_info,0)) + if (my_close(file,MYF(MY_WME))) goto err3; DBUG_RETURN(0); @@ -166,6 +166,23 @@ err: err2: VOID(my_close(file,MYF(MY_WME))); err3: + DBUG_RETURN(1); +} /* mysql_create_frm */ + +int rea_create_table(THD *thd, my_string file_name, + HA_CREATE_INFO *create_info, + List &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)); DBUG_RETURN(1); } /* rea_create_table */ From 3f9a97c1e8597e1e0fb064f366bfbe2413548093 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Apr 2004 13:12:05 +0200 Subject: [PATCH 2/3] Worklog#1563 - Support of on-line CREATE/DROP INDEX. Corrected minor problems of the preceding changeset 1.1705. sql/sql_table.cc: Worklog#1563 - Support of on-line CREATE/DROP INDEX. Replaced all tabs by a proper number of spaces. In the diff list this looks unaligned sometimes. Changed all sprintf to snprintf and checked the return value. Fixed key_count<= 0. key_count is unsigned. Removed an obsolete comment. --- sql/sql_table.cc | 1142 ++++++++++++++++++++++++---------------------- 1 file changed, 591 insertions(+), 551 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index eff3393e368..3da6943e713 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -34,19 +34,19 @@ const char *primary_key_name= "PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); static int copy_data_between_tables(TABLE *from,TABLE *to, - List &create, - enum enum_duplicates handle_duplicates, + List &create, + enum enum_duplicates handle_duplicates, uint order_num, ORDER *order, - ha_rows *copied,ha_rows *deleted); + ha_rows *copied,ha_rows *deleted); /* delete (drop) tables. SYNOPSIS mysql_rm_table() - thd Thread handle - tables List of tables to delete - if_exists If 1, don't give error if one table doesn't exists + thd Thread handle + tables List of tables to delete + if_exists If 1, don't give error if one table doesn't exists NOTES Will delete all tables that can be deleted and give a compact error @@ -57,13 +57,13 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set. RETURN - 0 ok. In this case ok packet is sent to user - -1 Error (Error message given but not sent to user) + 0 ok. In this case ok packet is sent to user + -1 Error (Error message given but not sent to user) */ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, - my_bool drop_temporary) + my_bool drop_temporary) { int error= 0; DBUG_ENTER("mysql_rm_table"); @@ -79,7 +79,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, if (thd->global_read_lock) { my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0), - tables->real_name); + tables->real_name); error= 1; goto err; } @@ -111,23 +111,23 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, SYNOPSIS mysql_rm_table_part2_with_lock() - thd Thread handle - tables List of tables to delete - if_exists If 1, don't give error if one table doesn't exists - dont_log_query Don't write query to log files + thd Thread handle + tables List of tables to delete + if_exists If 1, don't give error if one table doesn't exists + dont_log_query Don't write query to log files NOTES Works like documented in mysql_rm_table(), but don't check global_read_lock and don't send_ok packet to server. RETURN - 0 ok - 1 error + 0 ok + 1 error */ int mysql_rm_table_part2_with_lock(THD *thd, - TABLE_LIST *tables, bool if_exists, - bool drop_temporary, bool dont_log_query) + TABLE_LIST *tables, bool if_exists, + bool drop_temporary, bool dont_log_query) { int error; thd->mysys_var->current_mutex= &LOCK_open; @@ -135,7 +135,7 @@ int mysql_rm_table_part2_with_lock(THD *thd, VOID(pthread_mutex_lock(&LOCK_open)); error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, - dont_log_query); + dont_log_query); pthread_mutex_unlock(&LOCK_open); @@ -152,12 +152,12 @@ int mysql_rm_table_part2_with_lock(THD *thd, SYNOPSIS mysql_rm_table_part2() - thd Thread handler - tables Tables to drop - if_exists If set, don't give an error if table doesn't exists. - In this case we give an warning of level 'NOTE' - drop_temporary Only drop temporary tables - dont_log_query Don't log the query + thd Thread handler + tables Tables to drop + if_exists If set, don't give an error if table doesn't exists. + In this case we give an warning of level 'NOTE' + drop_temporary Only drop temporary tables + dont_log_query Don't log the query TODO: When logging to the binary log, we should log @@ -170,16 +170,16 @@ int mysql_rm_table_part2_with_lock(THD *thd, not all. RETURN - 0 ok - 1 Error - -1 Thread was killed + 0 ok + 1 Error + -1 Thread was killed */ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, - bool drop_temporary, bool dont_log_query) + bool drop_temporary, bool dont_log_query) { TABLE_LIST *table; - char path[FN_REFLEN], *alias; + char path[FN_REFLEN], *alias; String wrong_tables; int error; bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; @@ -195,7 +195,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (!close_temporary_table(thd, db, table->real_name)) { tmp_table_deleted=1; - continue; // removed temporary table + continue; // removed temporary table } error=0; @@ -204,13 +204,13 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, abort_locked_tables(thd,db,table->real_name); while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed) { - dropping_tables++; - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - dropping_tables--; + dropping_tables++; + (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + dropping_tables--; } drop_locked_tables(thd,db,table->real_name); if (thd->killed) - DBUG_RETURN(-1); + DBUG_RETURN(-1); alias= (lower_case_table_names == 2) ? table->alias : table->real_name; /* remove form file and isam files */ strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS); @@ -219,9 +219,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (drop_temporary || access(path,F_OK)) { if (if_exists) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), - table->real_name); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), + table->real_name); else error= 1; } @@ -229,27 +229,27 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { char *end; db_type table_type= get_table_type(path); - *(end=fn_ext(path))=0; // Remove extension for delete + *(end=fn_ext(path))=0; // Remove extension for delete error=ha_delete_table(table_type, path); if (error == ENOENT && if_exists) - error = 0; + error = 0; if (error == HA_ERR_ROW_IS_REFERENCED) { - /* the table is referenced by a foreign key constraint */ + /* the table is referenced by a foreign key constraint */ foreign_key_error=1; } if (!error || error == ENOENT) { - /* Delete the table definition file */ - strmov(end,reg_ext); - if (!(error=my_delete(path,MYF(MY_WME)))) - some_tables_deleted=1; + /* Delete the table definition file */ + strmov(end,reg_ext); + if (!(error=my_delete(path,MYF(MY_WME)))) + some_tables_deleted=1; } } if (error) { if (wrong_tables.length()) - wrong_tables.append(','); + wrong_tables.append(','); wrong_tables.append(String(table->real_name,system_charset_info)); } } @@ -263,9 +263,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, - tmp_table_deleted && !some_tables_deleted); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, thd->query_length, + tmp_table_deleted && !some_tables_deleted); + mysql_bin_log.write(&qinfo); } } } @@ -285,15 +285,19 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, int quick_rm_table(enum db_type base,const char *db, - const char *table_name) + const char *table_name) { char path[FN_REFLEN]; 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); if (my_delete(path,MYF(0))) 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); return ha_delete_table(base,path) || error; } @@ -327,7 +331,7 @@ static int sort_keys(KEY *a, KEY *b) return 1; } else if (b->flags & HA_NOSAME) - return 1; // Prefer b + return 1; // Prefer b if ((a->flags ^ b->flags) & HA_FULLTEXT) { @@ -338,8 +342,8 @@ static int sort_keys(KEY *a, KEY *b) the original key position. */ return ((a->usable_key_parts < b->usable_key_parts) ? -1 : - (a->usable_key_parts > b->usable_key_parts) ? 1 : - 0); + (a->usable_key_parts > b->usable_key_parts) ? 1 : + 0); } /* @@ -360,7 +364,7 @@ static int sort_keys(KEY *a, KEY *b) */ void check_duplicates_in_interval(const char *set_or_name, - const char *name, TYPELIB *typelib) + const char *name, TYPELIB *typelib) { unsigned int old_count= typelib->count; const char **old_type_names= typelib->type_names; @@ -375,9 +379,9 @@ void check_duplicates_in_interval(const char *set_or_name, if (find_type((char*)*cur_value,typelib,1)) { push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_DUPLICATED_VALUE_IN_TYPE, - ER(ER_DUPLICATED_VALUE_IN_TYPE), - name,*cur_value,set_or_name); + ER_DUPLICATED_VALUE_IN_TYPE, + ER(ER_DUPLICATED_VALUE_IN_TYPE), + name,*cur_value,set_or_name); } } typelib->count= old_count; @@ -389,33 +393,33 @@ void check_duplicates_in_interval(const char *set_or_name, SYNOPSIS mysql_prepare_table() - thd Thread object - create_info Create information (like MAX_ROWS) - fields List of fields to create - keys List of keys to create + thd Thread object + create_info Create information (like MAX_ROWS) + fields List of fields to create + keys List of keys to create DESCRIPTION Prepares the table and key structures for table creation. RETURN VALUES - 0 ok - -1 error + 0 ok + -1 error */ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, - List &fields, - List &keys, bool tmp_table, uint &db_options, - handler *file, KEY *&key_info_buffer, - uint &key_count, int select_field_count) + List &fields, + List &keys, bool tmp_table, uint &db_options, + handler *file, KEY *&key_info_buffer, + uint &key_count, int select_field_count) { - const char *key_name; - create_field *sql_field,*dup_field; - uint field,null_fields,blob_columns; - ulong pos; - KEY *key_info; + const char *key_name; + create_field *sql_field,*dup_field; + uint field,null_fields,blob_columns; + ulong pos; + KEY *key_info; KEY_PART_INFO *key_part_info; int field_no,dup_no; - int select_field_pos,auto_increment=0; + int select_field_pos,auto_increment=0; DBUG_ENTER("mysql_prepare_table"); List_iterator it(fields),it2(fields); @@ -438,8 +442,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, /* Don't pack keys in old tables if the user has requested this */ if ((sql_field->flags & BLOB_FLAG) || - sql_field->sql_type == FIELD_TYPE_VAR_STRING && - create_info->row_type != ROW_TYPE_FIXED) + sql_field->sql_type == FIELD_TYPE_VAR_STRING && + create_info->row_type != ROW_TYPE_FIXED) { db_options|=HA_OPTION_PACK_RECORD; } @@ -459,10 +463,10 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->field_name, dup_field->field_name) == 0) { - /* - If this was a CREATE ... SELECT statement, accept a field - redefinition if we are changing a field in the SELECT part - */ + /* + If this was a CREATE ... SELECT statement, accept a field + redefinition if we are changing a field in the SELECT part + */ if (field_no < select_field_pos || dup_no >= select_field_pos) { my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name); @@ -470,20 +474,20 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, } else { - /* Field redefined */ - sql_field->sql_type= dup_field->sql_type; - sql_field->charset= (dup_field->charset ? - dup_field->charset : - create_info->default_table_charset); - sql_field->length= dup_field->length; - sql_field->pack_length= dup_field->pack_length; - sql_field->create_length_to_internal_length(); - sql_field->decimals= dup_field->decimals; - sql_field->flags= dup_field->flags; - sql_field->unireg_check= dup_field->unireg_check; - it2.remove(); // Remove first (create) definition - select_field_pos--; - break; + /* Field redefined */ + sql_field->sql_type= dup_field->sql_type; + sql_field->charset= (dup_field->charset ? + dup_field->charset : + create_info->default_table_charset); + sql_field->length= dup_field->length; + sql_field->pack_length= dup_field->pack_length; + sql_field->create_length_to_internal_length(); + sql_field->decimals= dup_field->decimals; + sql_field->flags= dup_field->flags; + sql_field->unireg_check= dup_field->unireg_check; + it2.remove(); // Remove first (create) definition + select_field_pos--; + break; } } } @@ -505,11 +509,11 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_LONG_BLOB: sql_field->pack_flag=FIELDFLAG_BLOB | - pack_length_to_packflag(sql_field->pack_length - - portable_sizeof_char_ptr); + pack_length_to_packflag(sql_field->pack_length - + portable_sizeof_char_ptr); if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->length=8; // Unireg field length + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->length=8; // Unireg field length sql_field->unireg_check=Field::BLOB_FIELD; blob_columns++; break; @@ -517,49 +521,49 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, #ifdef HAVE_SPATIAL if (!(file->table_flags() & HA_HAS_GEOMETRY)) { - my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), - MYF(0), "GEOMETRY"); - DBUG_RETURN(-1); + my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), + MYF(0), "GEOMETRY"); + DBUG_RETURN(-1); } sql_field->pack_flag=FIELDFLAG_GEOM | - pack_length_to_packflag(sql_field->pack_length - - portable_sizeof_char_ptr); + pack_length_to_packflag(sql_field->pack_length - + portable_sizeof_char_ptr); if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->length=8; // Unireg field length + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->length=8; // Unireg field length sql_field->unireg_check=Field::BLOB_FIELD; blob_columns++; break; #else my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), - sym_group_geom.name, sym_group_geom.needed_define); + sym_group_geom.name, sym_group_geom.needed_define); DBUG_RETURN(-1); #endif /*HAVE_SPATIAL*/ case FIELD_TYPE_VAR_STRING: case FIELD_TYPE_STRING: sql_field->pack_flag=0; if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->pack_flag|=FIELDFLAG_BINARY; break; case FIELD_TYPE_ENUM: sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | - FIELDFLAG_INTERVAL; + FIELDFLAG_INTERVAL; if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->unireg_check=Field::INTERVAL_FIELD; check_duplicates_in_interval("ENUM",sql_field->field_name, - sql_field->interval); + sql_field->interval); break; case FIELD_TYPE_SET: sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | - FIELDFLAG_BITFIELD; + FIELDFLAG_BITFIELD; if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->unireg_check=Field::BIT_FIELD; check_duplicates_in_interval("SET",sql_field->field_name, - sql_field->interval); + sql_field->interval); break; - case FIELD_TYPE_DATE: // Rest of string types + case FIELD_TYPE_DATE: // Rest of string types case FIELD_TYPE_NEWDATE: case FIELD_TYPE_TIME: case FIELD_TYPE_DATETIME: @@ -571,12 +575,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, /* fall through */ default: sql_field->pack_flag=(FIELDFLAG_NUMBER | - (sql_field->flags & UNSIGNED_FLAG ? 0 : - FIELDFLAG_DECIMAL) | - (sql_field->flags & ZEROFILL_FLAG ? - FIELDFLAG_ZEROFILL : 0) | - f_settype((uint) sql_field->sql_type) | - (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); + (sql_field->flags & UNSIGNED_FLAG ? 0 : + FIELDFLAG_DECIMAL) | + (sql_field->flags & ZEROFILL_FLAG ? + FIELDFLAG_ZEROFILL : 0) | + f_settype((uint) sql_field->sql_type) | + (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); break; } if (!(sql_field->flags & NOT_NULL_FLAG)) @@ -608,7 +612,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, List_iterator key_iterator(keys); uint key_parts=0, fk_key_count=0; - List keys_in_order; // Add new keys here + List keys_in_order; // Add new keys here bool primary_key=0,unique_key=0; Key *key; uint tmp, key_number; @@ -623,12 +627,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, fk_key_count++; foreign_key *fk_key= (foreign_key*) key; if (fk_key->ref_columns.elements && - fk_key->ref_columns.elements != fk_key->columns.elements) + fk_key->ref_columns.elements != fk_key->columns.elements) { - my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name : - "foreign key without name", - ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)); - DBUG_RETURN(-1); + my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name : + "foreign key without name", + ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)); + DBUG_RETURN(-1); } continue; } @@ -646,7 +650,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, } key_parts+=key->columns.elements; if (key->name && !tmp_table && - !my_strcasecmp(system_charset_info,key->name,primary_key_name)) + !my_strcasecmp(system_charset_info,key->name,primary_key_name)) { my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); DBUG_RETURN(-1); @@ -662,7 +666,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); if (!key_info_buffer || ! key_part_info) - DBUG_RETURN(-1); // Out of memory + DBUG_RETURN(-1); // Out of memory key_iterator.rewind(); key_number=0; @@ -683,12 +687,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, key_info->flags = HA_SPATIAL; break; #else - my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), - sym_group_geom.name, sym_group_geom.needed_define); - DBUG_RETURN(-1); + my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + DBUG_RETURN(-1); #endif case Key::FOREIGN_KEY: - key_number--; // Skip this key + key_number--; // Skip this key continue; default: key_info->flags = HA_NOSAME; @@ -731,17 +735,17 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, #ifdef HAVE_RTREE_KEYS if ((key_info->key_parts & 1) == 1) { - my_printf_error(ER_WRONG_ARGUMENTS, - ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX"); - DBUG_RETURN(-1); + my_printf_error(ER_WRONG_ARGUMENTS, + ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX"); + DBUG_RETURN(-1); } /* TODO: To be deleted */ my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET), - MYF(0), "RTREE INDEX"); + MYF(0), "RTREE INDEX"); DBUG_RETURN(-1); #else my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), - sym_group_rtree.name, sym_group_rtree.needed_define); + sym_group_rtree.name, sym_group_rtree.needed_define); DBUG_RETURN(-1); #endif } @@ -753,16 +757,16 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, it.rewind(); field=0; while ((sql_field=it++) && - my_strcasecmp(system_charset_info, + my_strcasecmp(system_charset_info, column->field_name, sql_field->field_name)) - field++; + field++; if (!sql_field) { - my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS, - ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0), - column->field_name); - DBUG_RETURN(-1); + my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS, + ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0), + column->field_name); + DBUG_RETURN(-1); } /* for fulltext keys keyseg length is 1 for blobs (it's ignored in ft code anyway, and 0 (set to column width later) for char's. @@ -851,7 +855,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) { if (column_nr == 0 || (file->table_flags() & HA_AUTO_PART_KEY)) - auto_increment--; // Field is used + auto_increment--; // Field is used } } @@ -861,17 +865,19 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, uint length=sql_field->pack_length; if (column->length) { - if (f_is_blob(sql_field->pack_flag)) - { - if ((length=column->length) > file->max_key_length() || - length > file->max_key_part_length()) + if (f_is_blob(sql_field->pack_flag)) + { + if ((length=column->length) > file->max_key_length() || + length > file->max_key_part_length()) { length=min(file->max_key_length(), file->max_key_part_length()); if (key->type == Key::MULTIPLE) { /* not a critical problem */ 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, ER_TOO_LONG_KEY, warn_buff); } @@ -881,8 +887,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(-1); } } - } - else if (!f_is_geom(sql_field->pack_flag) && + } + else if (!f_is_geom(sql_field->pack_flag) && (column->length > length || ((f_is_packed(sql_field->pack_flag) || ((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) && @@ -897,9 +903,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, } else if (length == 0) { - my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0), - column->field_name); - DBUG_RETURN(-1); + my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0), + column->field_name); + DBUG_RETURN(-1); } if (length > file->max_key_part_length()) { @@ -908,7 +914,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { /* not a critical problem */ 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, ER_TOO_LONG_KEY, warn_buff); } @@ -921,15 +929,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, key_part_info->length=(uint16) length; /* Use packed keys for long strings on the first column */ if (!(db_options & HA_OPTION_NO_PACK_KEYS) && - (length >= KEY_DEFAULT_PACK_LENGTH && - (sql_field->sql_type == FIELD_TYPE_STRING || - sql_field->sql_type == FIELD_TYPE_VAR_STRING || - sql_field->pack_flag & FIELDFLAG_BLOB))) + (length >= KEY_DEFAULT_PACK_LENGTH && + (sql_field->sql_type == FIELD_TYPE_STRING || + sql_field->sql_type == FIELD_TYPE_VAR_STRING || + sql_field->pack_flag & FIELDFLAG_BLOB))) { - if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) - key_info->flags|= HA_BINARY_PACK_KEY; - else - key_info->flags|= HA_PACK_KEY; + if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) + key_info->flags|= HA_BINARY_PACK_KEY; + else + key_info->flags|= HA_PACK_KEY; } key_length+=length; key_part_info++; @@ -937,25 +945,25 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, /* Create the key name based on the first column (if not given) */ if (column_nr == 0) { - if (key->type == Key::PRIMARY) - { - if (primary_key) - { - my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); - DBUG_RETURN(-1); - } - key_name=primary_key_name; - primary_key=1; - } - else if (!(key_name = key->name)) - key_name=make_unique_key_name(sql_field->field_name, - key_info_buffer,key_info); - if (check_if_keyname_exists(key_name,key_info_buffer,key_info)) - { - my_error(ER_DUP_KEYNAME,MYF(0),key_name); - DBUG_RETURN(-1); - } - key_info->name=(char*) key_name; + if (key->type == Key::PRIMARY) + { + if (primary_key) + { + my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); + DBUG_RETURN(-1); + } + key_name=primary_key_name; + primary_key=1; + } + else if (!(key_name = key->name)) + key_name=make_unique_key_name(sql_field->field_name, + key_info_buffer,key_info); + if (check_if_keyname_exists(key_name,key_info_buffer,key_info)) + { + my_error(ER_DUP_KEYNAME,MYF(0),key_name); + DBUG_RETURN(-1); + } + key_info->name=(char*) key_name; } } if (!key_info->name || check_column_name(key_info->name)) @@ -996,15 +1004,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, 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. + 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 @@ -1015,23 +1023,23 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, and must be zero for standard create of table. RETURN VALUES - 0 ok - -1 error + 0 ok + -1 error */ int mysql_create_table(THD *thd,const char *db, const char *table_name, - HA_CREATE_INFO *create_info, - List &fields, - List &keys,bool tmp_table,bool no_log, + HA_CREATE_INFO *create_info, + List &fields, + List &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; + 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 */ @@ -1045,10 +1053,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { 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); + 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) @@ -1064,20 +1072,24 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } if (mysql_prepare_table(thd, create_info, fields, - keys, tmp_table, db_options, file, - key_info_buffer, key_count, - select_field_count)) + keys, tmp_table, db_options, file, + key_info_buffer, key_count, + select_field_count)) DBUG_RETURN(-1); /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { - sprintf(path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix, - current_pid, thd->thread_id, thd->tmp_table++,reg_ext); + if (snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s", + 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; } 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); /* Check if table already exists */ if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) @@ -1085,7 +1097,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) { - create_info->table_existed= 1; // Mark that table existed + create_info->table_existed= 1; // Mark that table existed DBUG_RETURN(0); } my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); @@ -1100,8 +1112,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) { - create_info->table_existed= 1; // Mark that table existed - error= 0; + create_info->table_existed= 1; // Mark that table existed + error= 0; } else my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); @@ -1110,14 +1122,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } thd->proc_info="creating table"; - create_info->table_existed= 0; // Mark that table is created + create_info->table_existed= 0; // Mark that table is created if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) create_info->data_file_name= create_info->index_file_name= 0; create_info->table_options=db_options; if (rea_create_table(thd, path, create_info, fields, key_count, - key_info_buffer)) + key_info_buffer)) { /* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */ goto end; @@ -1140,8 +1152,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - test(create_info->options & - HA_LEX_CREATE_TMP_TABLE)); + test(create_info->options & + HA_LEX_CREATE_TMP_TABLE)); mysql_bin_log.write(&qinfo); } } @@ -1171,17 +1183,23 @@ static char * make_unique_key_name(const char *field_name,KEY *start,KEY *end) { char buff[MAX_FIELD_NAME],*buff_end; + int remain; if (!check_if_keyname_exists(field_name,start,end) && 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); - 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)) return sql_strdup(buff); } + /*ingo 2004-04-07 dedicated return is inevitable*/ + return NULL; } /**************************************************************************** @@ -1189,13 +1207,13 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end) ****************************************************************************/ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, - const char *db, const char *name, - List *extra_fields, - List *keys, - List *items, - MYSQL_LOCK **lock) + const char *db, const char *name, + List *extra_fields, + List *keys, + List *items, + MYSQL_LOCK **lock) { - TABLE tmp_table; // Used during 'create_field()' + TABLE tmp_table; // Used during 'create_field()' TABLE *table; tmp_table.table_name=0; uint select_field_count= items->elements; @@ -1209,7 +1227,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, tmp_table.null_row=tmp_table.maybe_null=0; tmp_table.blob_ptr_size=portable_sizeof_char_ptr; tmp_table.db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM || - create_info->db_type == DB_TYPE_HEAP); + create_info->db_type == DB_TYPE_HEAP); while ((item=it++)) { @@ -1219,18 +1237,18 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, field=item->tmp_table_field(&tmp_table); else field=create_tmp_field(thd, &tmp_table, item, item->type(), - (Item ***) 0, &tmp_field,0,0); + (Item ***) 0, &tmp_field,0,0); if (!field || - !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? - ((Item_field *)item)->field : - (Field*) 0)))) + !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? + ((Item_field *)item)->field : + (Field*) 0)))) DBUG_RETURN(0); extra_fields->push_back(cr_field); } /* create and lock table */ /* QQ: This should be done atomic ! */ if (mysql_create_table(thd,db,name,create_info,*extra_fields, - *keys,0,1,select_field_count)) // no logging + *keys,0,1,select_field_count)) // no logging DBUG_RETURN(0); if (!(table=open_table(thd,db,name,name,(bool*) 0))) { @@ -1257,10 +1275,10 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, bool mysql_rename_table(enum db_type base, - const char *old_db, - const char *old_name, - const char *new_db, - const char *new_name) + const char *old_db, + const char *old_name, + const char *new_db, + const char *new_name) { char from[FN_REFLEN], to[FN_REFLEN]; char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1]; @@ -1279,8 +1297,12 @@ mysql_rename_table(enum db_type base, my_casedn_str(system_charset_info, tmp_to); new_name= tmp_to; } - (void) sprintf(from,"%s/%s/%s",mysql_data_home,old_db,old_name); - (void) sprintf(to,"%s/%s/%s",mysql_data_home,new_db,new_name); + if (snprintf(from, sizeof(from), "%s/%s/%s", + 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(to,to, "","",4); @@ -1305,10 +1327,10 @@ mysql_rename_table(enum db_type base, SYNOPSIS wait_while_table_is_used() - thd Thread handler - table Table to remove from cache - function HA_EXTRA_PREPARE_FOR_DELETE if table is to be deleted - HA_EXTRA_FORCE_REOPEN if table is not be used + thd Thread handler + table Table to remove from cache + function HA_EXTRA_PREPARE_FOR_DELETE if table is to be deleted + HA_EXTRA_FORCE_REOPEN if table is not be used NOTES When returning, the table will be unusable for other threads until the table is closed. @@ -1319,7 +1341,7 @@ mysql_rename_table(enum db_type base, */ static void wait_while_table_is_used(THD *thd,TABLE *table, - enum ha_extra_function function) + enum ha_extra_function function) { DBUG_PRINT("enter",("table: %s", table->real_name)); DBUG_ENTER("wait_while_table_is_used"); @@ -1327,11 +1349,11 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, VOID(table->file->extra(function)); /* Mark all tables that are in use as 'old' */ - mysql_lock_abort(thd, table); // end threads waiting on lock + mysql_lock_abort(thd, table); // end threads waiting on lock /* Wait until all there are no other threads that has this table open */ while (remove_table_from_cache(thd,table->table_cache_key, - table->real_name)) + table->real_name)) { dropping_tables++; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); @@ -1345,8 +1367,8 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, SYNOPSIS close_cached_table() - thd Thread handler - table Table to remove from cache + thd Thread handler + table Table to remove from cache NOTES Function ends by signaling threads waiting for the table to try to @@ -1366,7 +1388,7 @@ static bool close_cached_table(THD *thd, TABLE *table) if (thd->lock) { mysql_unlock_tables(thd, thd->lock); - thd->lock=0; // Start locked threads + thd->lock=0; // Start locked threads } /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ thd->open_tables=unlink_open_table(thd,thd->open_tables,table); @@ -1377,7 +1399,7 @@ static bool close_cached_table(THD *thd, TABLE *table) } static int send_check_errmsg(THD *thd, TABLE_LIST* table, - const char* operator_name, const char* errmsg) + const char* operator_name, const char* errmsg) { Protocol *protocol= thd->protocol; @@ -1394,15 +1416,15 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table, static int prepare_for_restore(THD* thd, TABLE_LIST* table, - HA_CHECK_OPT *check_opt) + HA_CHECK_OPT *check_opt) { DBUG_ENTER("prepare_for_restore"); if (table->table) // do not overwrite existing tables on restore { DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "table exists, will not overwrite on restore" - )); + "table exists, will not overwrite on restore" + )); } else { @@ -1412,23 +1434,25 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, char* db = thd->db ? thd->db : table->db; if (fn_format_relative_to_data_home(src_path, table_name, backup_dir, - reg_ext)) + reg_ext)) 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)) DBUG_RETURN(-1); if (my_copy(src_path, - fn_format(dst_path, dst_path,"", reg_ext, 4), - MYF(MY_WME))) + fn_format(dst_path, dst_path,"", reg_ext, 4), + MYF(MY_WME))) { pthread_mutex_lock(&LOCK_open); unlock_table_name(thd, table); pthread_mutex_unlock(&LOCK_open); DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "Failed copying .frm file")); + "Failed copying .frm file")); } if (mysql_truncate(thd, table, 1)) { @@ -1436,7 +1460,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, unlock_table_name(thd, table); pthread_mutex_unlock(&LOCK_open); DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "Failed generating table from .frm file")); + "Failed generating table from .frm file")); } } @@ -1455,7 +1479,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, - HA_CHECK_OPT *check_opt) + HA_CHECK_OPT *check_opt) { int error= 0; TABLE tmp_table, *table; @@ -1464,13 +1488,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, if (!(check_opt->sql_flags & TT_USEFRM)) DBUG_RETURN(0); - if (!(table= table_list->table)) /* if open_ltable failed */ + if (!(table= table_list->table)) /* if open_ltable failed */ { char name[FN_REFLEN]; strxmov(name, mysql_data_home, "/", table_list->db, "/", - table_list->real_name, NullS); + table_list->real_name, NullS); if (openfrm(name, "", 0, 0, 0, &tmp_table)) - DBUG_RETURN(0); // Can't open frm file + DBUG_RETURN(0); // Can't open frm file table= &tmp_table; } @@ -1493,13 +1517,18 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, like ISAM or MyISAM */ if (!ext[0] || !ext[1]) - goto end; // No data file + goto end; // No data file - strxmov(from, table->path, ext[1], NullS); // Name of data file + strxmov(from, table->path, ext[1], NullS); // Name of data file 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 (table_list->table) @@ -1519,7 +1548,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", - "Failed renaming data file"); + "Failed renaming data file"); goto end; } if (mysql_truncate(thd, table_list, 1)) @@ -1528,7 +1557,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", - "Failed generating table from .frm file"); + "Failed generating table from .frm file"); goto end; } if (my_rename(tmp, from, MYF(MY_WME))) @@ -1537,7 +1566,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", - "Failed restoring .MYD file"); + "Failed restoring .MYD file"); goto end; } @@ -1554,21 +1583,21 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, end: if (table == &tmp_table) - closefrm(table); // Free allocated memory + closefrm(table); // Free allocated memory DBUG_RETURN(error); } static int mysql_admin_table(THD* thd, TABLE_LIST* tables, - HA_CHECK_OPT* check_opt, - const char *operator_name, - thr_lock_type lock_type, - bool open_for_modify, - uint extra_open_options, - int (*prepare_func)(THD *, TABLE_LIST *, - HA_CHECK_OPT *), - int (handler::*operator_func) - (THD *, HA_CHECK_OPT *)) + HA_CHECK_OPT* check_opt, + const char *operator_name, + thr_lock_type lock_type, + bool open_for_modify, + uint extra_open_options, + int (*prepare_func)(THD *, TABLE_LIST *, + HA_CHECK_OPT *), + int (handler::*operator_func) + (THD *, HA_CHECK_OPT *)) { TABLE_LIST *table; List field_list; @@ -1619,11 +1648,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->store(operator_name, system_charset_info); protocol->store("error",5, system_charset_info); if (!(err_msg=thd->net.last_error)) - err_msg=ER(ER_CHECK_NO_SUCH_TABLE); + err_msg=ER(ER_CHECK_NO_SUCH_TABLE); protocol->store(err_msg, system_charset_info); thd->net.last_error[0]=0; if (protocol->write()) - goto err; + goto err; continue; } table->table->pos_in_table_list= table; @@ -1634,12 +1663,14 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->store(table_name, system_charset_info); protocol->store(operator_name, 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); close_thread_tables(thd); - table->table=0; // For query cache + table->table=0; // For query cache if (protocol->write()) - goto err; + goto err; continue; } @@ -1648,20 +1679,20 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, { pthread_mutex_lock(&LOCK_open); const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open, - "Waiting to get writelock"); + "Waiting to get writelock"); mysql_lock_abort(thd,table->table); while (remove_table_from_cache(thd, table->table->table_cache_key, - table->table->real_name) && - ! thd->killed) + table->table->real_name) && + ! thd->killed) { - dropping_tables++; - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - dropping_tables--; + dropping_tables++; + (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + dropping_tables--; } thd->exit_cond(old_message); pthread_mutex_unlock(&LOCK_open); if (thd->killed) - goto err; + goto err; open_for_modify=0; } @@ -1678,7 +1709,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, { char buf[ERRMSGSIZE+20]; uint length=my_snprintf(buf, ERRMSGSIZE, - ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); + ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); protocol->store("error", 5, system_charset_info); protocol->store(buf, length, system_charset_info); } @@ -1710,26 +1741,26 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->store("Invalid argument",16, system_charset_info); break; - default: // Probably HA_ADMIN_INTERNAL_ERROR + default: // Probably HA_ADMIN_INTERNAL_ERROR protocol->store("error", 5, system_charset_info); protocol->store("Unknown - internal error during operation", 41 - , system_charset_info); + , system_charset_info); fatal_error=1; break; } if (fatal_error) - table->table->version=0; // Force close of table + table->table->version=0; // Force close of table else if (open_for_modify) { pthread_mutex_lock(&LOCK_open); remove_table_from_cache(thd, table->table->table_cache_key, - table->table->real_name); + table->table->real_name); pthread_mutex_unlock(&LOCK_open); /* May be something modified consequently we have to invalidate cache */ query_cache_invalidate3(thd, table->table, 0); } close_thread_tables(thd); - table->table=0; // For query cache + table->table=0; // For query cache if (protocol->write()) goto err; } @@ -1737,7 +1768,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, send_eof(thd); DBUG_RETURN(0); err: - close_thread_tables(thd); // Shouldn't be needed + close_thread_tables(thd); // Shouldn't be needed if (table) table->table=0; DBUG_RETURN(-1); @@ -1748,8 +1779,8 @@ int mysql_backup_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("mysql_backup_table"); DBUG_RETURN(mysql_admin_table(thd, table_list, 0, - "backup", TL_READ, 0, 0, 0, - &handler::backup)); + "backup", TL_READ, 0, 0, 0, + &handler::backup)); } @@ -1757,9 +1788,9 @@ int mysql_restore_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("mysql_restore_table"); DBUG_RETURN(mysql_admin_table(thd, table_list, 0, - "restore", TL_WRITE, 1, 0, + "restore", TL_WRITE, 1, 0, &prepare_for_restore, - &handler::restore)); + &handler::restore)); } @@ -1767,9 +1798,9 @@ int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) { DBUG_ENTER("mysql_repair_table"); DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, - "repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR, + "repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR, &prepare_for_repair, - &handler::repair)); + &handler::repair)); } @@ -1777,8 +1808,8 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) { DBUG_ENTER("mysql_optimize_table"); DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, - "optimize", TL_WRITE, 1,0,0, - &handler::optimize)); + "optimize", TL_WRITE, 1,0,0, + &handler::optimize)); } @@ -1787,16 +1818,16 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) SYNOPSIS mysql_assign_to_keycache() - thd Thread object + thd Thread object tables Table list (one table only) RETURN VALUES - 0 ok - -1 error + 0 ok + -1 error */ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, - LEX_STRING *key_cache_name) + LEX_STRING *key_cache_name) { HA_CHECK_OPT check_opt; KEY_CACHE *key_cache; @@ -1813,7 +1844,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, pthread_mutex_unlock(&LOCK_global_system_variables); check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, - "assign_to_keycache", TL_READ_NO_INSERT, 0, + "assign_to_keycache", TL_READ_NO_INSERT, 0, 0, 0, &handler::assign_to_keycache)); } @@ -1823,7 +1854,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, SYNOPSIS reassign_keycache_tables() - thd Thread object + thd Thread object src_cache Reference to the key cache to clean up dest_cache New key cache @@ -1840,7 +1871,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, to it for a while after this function returns. RETURN VALUES - 0 ok + 0 ok */ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, @@ -1850,7 +1881,7 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, DBUG_ASSERT(src_cache != dst_cache); DBUG_ASSERT(src_cache->in_init); - src_cache->param_buff_size= 0; // Free key cache + src_cache->param_buff_size= 0; // Free key cache ha_resize_key_cache(src_cache); ha_change_key_cache(src_cache, dst_cache); DBUG_RETURN(0); @@ -1862,20 +1893,20 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, SYNOPSIS mysql_preload_keys() - thd Thread object + thd Thread object tables Table list (one table only) RETURN VALUES - 0 ok - -1 error + 0 ok + -1 error */ int mysql_preload_keys(THD* thd, TABLE_LIST* tables) { DBUG_ENTER("mysql_preload_keys"); DBUG_RETURN(mysql_admin_table(thd, tables, 0, - "preload_keys", TL_READ, 0, 0, 0, - &handler::preload_keys)); + "preload_keys", TL_READ, 0, 0, 0, + &handler::preload_keys)); } @@ -1884,14 +1915,14 @@ int mysql_preload_keys(THD* thd, TABLE_LIST* tables) SYNOPSIS mysql_create_like_table() - thd Thread object + thd Thread object table Table list (one table only) create_info Create info table_ident Src table_ident RETURN VALUES - 0 ok - -1 error + 0 ok + -1 error */ int mysql_create_like_table(THD* thd, TABLE_LIST* table, @@ -1942,8 +1973,11 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, { if (find_temporary_table(thd, db, table_name)) goto table_exists; - sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix, - current_pid, thd->thread_id, thd->tmp_table++,reg_ext); + if (snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s", + 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; } else @@ -1990,8 +2024,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, { thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - test(create_info->options & - HA_LEX_CREATE_TMP_TABLE)); + test(create_info->options & + HA_LEX_CREATE_TMP_TABLE)); mysql_bin_log.write(&qinfo); } DBUG_RETURN(0); @@ -2000,7 +2034,9 @@ table_exists: if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) { 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, ER_TABLE_EXISTS_ERROR,warn_buff); DBUG_RETURN(0); @@ -2020,8 +2056,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) DBUG_ENTER("mysql_analyze_table"); DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, - "analyze", lock_type, 1,0,0, - &handler::analyze)); + "analyze", lock_type, 1,0,0, + &handler::analyze)); } @@ -2035,15 +2071,15 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt) DBUG_ENTER("mysql_check_table"); DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, - "check", lock_type, - 0, HA_OPEN_FOR_REPAIR, 0, - &handler::check)); + "check", lock_type, + 0, HA_OPEN_FOR_REPAIR, 0, + &handler::check)); } /* table_list should contain just one table */ int mysql_discard_or_import_tablespace(THD *thd, - TABLE_LIST *table_list, - enum tablespace_op_type tablespace_op) + TABLE_LIST *table_list, + enum tablespace_op_type tablespace_op) { TABLE *table; my_bool discard; @@ -2061,8 +2097,8 @@ int mysql_discard_or_import_tablespace(THD *thd, discard = FALSE; thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open - and ::external_lock() do not complain when we - lock the table */ + and ::external_lock() do not complain when we + lock the table */ mysql_ha_closeall(thd, table_list); if (!(table=open_ltable(thd,table_list,TL_WRITE))) @@ -2119,12 +2155,12 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) HA_CREATE_INFO create_info; int rc; uint idx; - uint db_options; + uint db_options; uint key_count; TABLE *table; Field **f_ptr; KEY *key_info_buffer; - char path[FN_REFLEN]; + char path[FN_REFLEN]; DBUG_ENTER("mysql_create_index"); /* @@ -2154,9 +2190,9 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) 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)) + keys, /*tmp_table*/ 0, db_options, table->file, + key_info_buffer, key_count, + /*select_field_count*/ 0)) DBUG_RETURN(-1); /* @@ -2170,7 +2206,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) (HA_DDL_ONLINE| HA_DDL_WITH_LOCK))) break ; } - if ((idx < key_count)|| (key_count<= 0)) + if ((idx < key_count)|| !key_count) { /* Re-initialize the create_info, which was changed by prepare table. */ bzero((char*) &create_info,sizeof(create_info)); @@ -2188,9 +2224,10 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) else { if (table->file->add_index(table, key_info_buffer, key_count)|| - ((void) sprintf(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), 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)) @@ -2210,14 +2247,14 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop) List alter; HA_CREATE_INFO create_info; uint idx; - uint db_options; + 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]; + char path[FN_REFLEN]; DBUG_ENTER("mysql_drop_index"); /* @@ -2249,7 +2286,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop) for (idx=0; idx< table->keys; idx++, key_info++) { if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name)) - break; + break; } if (idx>= table->keys) { @@ -2289,9 +2326,10 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop) keys, /*tmp_table*/ 0, db_options, table->file, key_info_buffer, key_count, /*select_field_count*/ 0)|| - ((void) sprintf(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), 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)) @@ -2304,7 +2342,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop) } int mysql_add_column(THD *thd, TABLE_LIST *table_list, - List &fields) + List &fields) { List drop; List keys; @@ -2319,9 +2357,9 @@ int mysql_add_column(THD *thd, TABLE_LIST *table_list, 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)); + &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 &drop) @@ -2339,37 +2377,31 @@ int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List &drop) 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)); + &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, - HA_CREATE_INFO *create_info, - TABLE_LIST *table_list, - List &fields, - List &keys,List &drop_list, - List &alter_list, + HA_CREATE_INFO *create_info, + TABLE_LIST *table_list, + List &fields, + List &keys,List &drop_list, + List &alter_list, 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, + 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"); - /* !!!!!!!! WARNING: This comment must be removed after a decision !!!!!!!!! - I'm not sure if the next two commands are at the right place here. - I guess that closing all is necessary before table dropping which is - part of alter table, but may be harmful before online DDLs. - So I would put both behind the DDL branches right before open_ltable. - !!!!!!!! WARNING: This comment must be removed after a decision !!!!!! */ 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)); + tablespace_op)); if (alter_flags == ALTER_ADD_INDEX) DBUG_RETURN(mysql_create_index(thd, table_list, keys)); @@ -2388,24 +2420,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, 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)); + 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, + HA_CREATE_INFO *create_info, + TABLE_LIST *table_list, TABLE *table, - List &fields, - List &keys,List &drop_list, - List &alter_list, + List &fields, + List &keys,List &drop_list, + List &alter_list, 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, + enum enum_duplicates handle_duplicates, + enum enum_enable_or_disable keys_onoff, + enum tablespace_op_type tablespace_op, bool simple_alter) { TABLE *new_table; @@ -2440,13 +2472,13 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { if (lower_case_table_names != 2) { - my_casedn_str(system_charset_info, new_name_buff); - new_alias= new_name; // Create lower case table name + my_casedn_str(system_charset_info, new_name_buff); + new_alias= new_name; // Create lower case table name } my_casedn_str(system_charset_info, new_name); } if (new_db == db && - !my_strcasecmp(table_alias_charset, new_name_buff, table_name)) + !my_strcasecmp(table_alias_charset, new_name_buff, table_name)) { /* Source and destination table names are equal: make later check @@ -2458,21 +2490,21 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { if (table->tmp_table) { - if (find_temporary_table(thd,new_db,new_name_buff)) - { - my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff); - DBUG_RETURN(-1); - } + if (find_temporary_table(thd,new_db,new_name_buff)) + { + my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff); + DBUG_RETURN(-1); + } } else { - if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0), - F_OK)) - { - /* Table will be closed in do_command() */ - my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias); - DBUG_RETURN(-1); - } + if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0), + F_OK)) + { + /* Table will be closed in do_command() */ + my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias); + DBUG_RETURN(-1); + } } } } @@ -2487,10 +2519,10 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { 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), - new_name); + ER_WARN_USING_OTHER_HANDLER, + ER(ER_WARN_USING_OTHER_HANDLER), + ha_get_storage_engine(new_db_type), + new_name); } if (create_info->row_type == ROW_TYPE_NOT_USED) create_info->row_type=table->row_type; @@ -2515,7 +2547,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, *fn_ext(new_name)=0; close_cached_table(thd, table); if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias)) - error= -1; + error= -1; } VOID(pthread_mutex_unlock(&LOCK_open)); } @@ -2524,28 +2556,28 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { switch (keys_onoff) { case LEAVE_AS_IS: - break; + break; case ENABLE: - VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); - error= table->file->activate_all_index(thd); - /* COND_refresh will be signaled in close_thread_tables() */ - break; + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + VOID(pthread_mutex_unlock(&LOCK_open)); + error= table->file->activate_all_index(thd); + /* COND_refresh will be signaled in close_thread_tables() */ + break; case DISABLE: - if (table->db_type == DB_TYPE_MYISAM) - { - VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); - table->file->deactivate_non_unique_index(HA_POS_ERROR); - /* COND_refresh will be signaled in close_thread_tables() */ - } - else - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA, - ER(ER_ILLEGAL_HA), table->table_name); - break; + if (table->db_type == DB_TYPE_MYISAM) + { + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + VOID(pthread_mutex_unlock(&LOCK_open)); + table->file->deactivate_non_unique_index(HA_POS_ERROR); + /* COND_refresh will be signaled in close_thread_tables() */ + } + else + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA, + ER(ER_ILLEGAL_HA), table->table_name); + break; } } if (!error) @@ -2554,12 +2586,12 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); } send_ok(thd); } - table_list->table=0; // For query cache + table_list->table=0; // For query cache query_cache_invalidate3(thd, table_list, 0); DBUG_RETURN(error); } @@ -2576,12 +2608,12 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) create_info->default_table_charset= table->table_charset; - restore_record(table,default_values); // Empty record for DEFAULT + restore_record(table,default_values); // Empty record for DEFAULT List_iterator drop_it(drop_list); List_iterator def_it(fields); List_iterator alter_it(alter_list); - List create_list; // Add new fields here - List key_list; // Add new keys here + List create_list; // Add new fields here + List key_list; // Add new keys here create_field *def; /* @@ -2597,16 +2629,16 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, while ((drop=drop_it++)) { if (drop->type == Alter_drop::COLUMN && - !my_strcasecmp(system_charset_info,field->field_name, drop->name)) + !my_strcasecmp(system_charset_info,field->field_name, drop->name)) { - /* Reset auto_increment value if it was dropped */ - if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && - !(used_fields & HA_CREATE_USED_AUTO)) - { - create_info->auto_increment_value=0; - create_info->used_fields|=HA_CREATE_USED_AUTO; - } - break; + /* Reset auto_increment value if it was dropped */ + if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && + !(used_fields & HA_CREATE_USED_AUTO)) + { + create_info->auto_increment_value=0; + create_info->used_fields|=HA_CREATE_USED_AUTO; + } + break; } } if (drop) @@ -2620,31 +2652,31 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { if (def->change && !my_strcasecmp(system_charset_info,field->field_name, def->change)) - break; + break; } if (def) - { // Field is changed + { // Field is changed def->field=field; if (def->sql_type == FIELD_TYPE_TIMESTAMP) - use_timestamp=1; + use_timestamp=1; if (!def->after) { - create_list.push_back(def); - def_it.remove(); + create_list.push_back(def); + def_it.remove(); } } else - { // Use old field value + { // Use old field value create_list.push_back(def=new create_field(field,field)); if (def->sql_type == FIELD_TYPE_TIMESTAMP) - use_timestamp=1; + use_timestamp=1; - alter_it.rewind(); // Change default if ALTER + alter_it.rewind(); // Change default if ALTER Alter_column *alter; while ((alter=alter_it++)) { - if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) - break; + if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) + break; } if (alter) { @@ -2653,14 +2685,14 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change); DBUG_RETURN(-1); } - def->def=alter->def; // Use new default - alter_it.remove(); + def->def=alter->def; // Use new default + alter_it.remove(); } } } def_it.rewind(); List_iterator find_it(create_list); - while ((def=def_it++)) // Add new columns + while ((def=def_it++)) // Add new columns { if (def->change && ! def->field) { @@ -2675,17 +2707,17 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { create_field *find; find_it.rewind(); - while ((find=find_it++)) // Add new columns + while ((find=find_it++)) // Add new columns { - if (!my_strcasecmp(system_charset_info,def->after, find->field_name)) - break; + if (!my_strcasecmp(system_charset_info,def->after, find->field_name)) + break; } if (!find) { - my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name); - DBUG_RETURN(-1); + my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name); + DBUG_RETURN(-1); } - find_it.after(def); // Put element after this + find_it.after(def); // Put element after this } } if (alter_list.elements) @@ -2717,8 +2749,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, while ((drop=drop_it++)) { if (drop->type == Alter_drop::KEY && - !my_strcasecmp(system_charset_info,key_name, drop->name)) - break; + !my_strcasecmp(system_charset_info,key_name, drop->name)) + break; } if (drop) { @@ -2731,60 +2763,60 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) { if (!key_part->field) - continue; // Wrong field (from UNIREG) + continue; // Wrong field (from UNIREG) const char *key_part_name=key_part->field->field_name; create_field *cfield; field_it.rewind(); while ((cfield=field_it++)) { - if (cfield->change) - { - if (!my_strcasecmp(system_charset_info, key_part_name, - cfield->change)) - break; - } - else if (!my_strcasecmp(system_charset_info, + if (cfield->change) + { + if (!my_strcasecmp(system_charset_info, key_part_name, + cfield->change)) + break; + } + else if (!my_strcasecmp(system_charset_info, key_part_name, cfield->field_name)) - break; + break; } if (!cfield) - continue; // Field is removed + continue; // Field is removed uint key_part_length=key_part->length; - if (cfield->field) // Not new field - { // Check if sub key - if (cfield->field->type() != FIELD_TYPE_BLOB && - (cfield->field->pack_length() == key_part_length || - cfield->length <= key_part_length / - key_part->field->charset()->mbmaxlen)) - key_part_length=0; // Use whole field + if (cfield->field) // Not new field + { // Check if sub key + if (cfield->field->type() != FIELD_TYPE_BLOB && + (cfield->field->pack_length() == key_part_length || + cfield->length <= key_part_length / + key_part->field->charset()->mbmaxlen)) + key_part_length=0; // Use whole field } key_part_length /= key_part->field->charset()->mbmaxlen; key_parts.push_back(new key_part_spec(cfield->field_name, - key_part_length)); + key_part_length)); } if (key_parts.elements) key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL : (key_info->flags & HA_NOSAME ? - (!my_strcasecmp(system_charset_info, + (!my_strcasecmp(system_charset_info, key_name, primary_key_name) ? - Key::PRIMARY : Key::UNIQUE) : - (key_info->flags & HA_FULLTEXT ? - Key::FULLTEXT : Key::MULTIPLE)), - key_name, + Key::PRIMARY : Key::UNIQUE) : + (key_info->flags & HA_FULLTEXT ? + Key::FULLTEXT : Key::MULTIPLE)), + key_name, key_info->algorithm, - key_parts)); + key_parts)); } { Key *key; - while ((key=key_it++)) // Add new keys + while ((key=key_it++)) // Add new keys { if (key->type != Key::FOREIGN_KEY) - key_list.push_back(key); + key_list.push_back(key); if (key->name && - !my_strcasecmp(system_charset_info,key->name,primary_key_name)) + !my_strcasecmp(system_charset_info,key->name,primary_key_name)) { - my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); - DBUG_RETURN(-1); + my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); + DBUG_RETURN(-1); } } } @@ -2801,8 +2833,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, } db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD); - (void) sprintf(tmp_name,"%s-%lx_%lx", tmp_file_prefix, current_pid, - thd->thread_id); + if (snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix, + current_pid, thd->thread_id)>= (int)sizeof(tmp_name)) + goto err; create_info->db_type=new_db_type; if (!create_info->comment) create_info->comment=table->comment; @@ -2818,7 +2851,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, if (create_info->table_options & (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE)) db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE | - HA_OPTION_NO_DELAY_KEY_WRITE); + HA_OPTION_NO_DELAY_KEY_WRITE); create_info->table_options|= db_create_options; if (table->tmp_table) @@ -2849,31 +2882,31 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, Remove old table and symlinks. */ - if (!strcmp(db, new_db)) // Ignore symlink if db changed + 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); + 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); + create_info->data_file_name, + 1); } } else create_info->data_file_name=create_info->index_file_name=0; if ((error=mysql_create_table(thd, new_db, tmp_name, - create_info, - create_list,key_list,1,1,0))) // no logging + create_info, + create_list,key_list,1,1,0))) // no logging DBUG_RETURN(error); if (table->tmp_table) @@ -2881,7 +2914,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, else { 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); new_table=open_temporary_table(thd, path, new_db, tmp_name,0); } @@ -2895,16 +2930,16 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, if (use_timestamp) new_table->time_stamp=0; new_table->next_number_field=new_table->found_next_number_field; - thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields + thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0L; thd->proc_info="copy to tmp table"; - next_insert_id=thd->next_insert_id; // Remember for loggin + next_insert_id=thd->next_insert_id; // Remember for loggin copied=deleted=0; if (!new_table->is_view) error=copy_data_between_tables(table,new_table,create_list, - handle_duplicates, - order_num, order, &copied, &deleted); - thd->last_insert_id=next_insert_id; // Needed for correct log + handle_duplicates, + order_num, order, &copied, &deleted); + thd->last_insert_id=next_insert_id; // Needed for correct log thd->count_cuted_fields= CHECK_FIELD_IGNORE; new_table->time_stamp=save_time_stamp; @@ -2914,8 +2949,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, if (error) { /* - The following function call will free the new_table pointer, - in close_temporary_table(), so we can safely directly jump to err + The following function call will free the new_table pointer, + in close_temporary_table(), so we can safely directly jump to err */ close_temporary_table(thd,new_db,tmp_name); goto err; @@ -2929,7 +2964,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, /* Remove link to old table and rename the new one */ close_temporary_table(thd,table->table_cache_key,table_name); if (rename_temporary_table(thd, new_table, new_db, new_alias)) - { // Fatal error + { // Fatal error close_temporary_table(thd,new_db,tmp_name); my_free((gptr) new_table,MYF(0)); goto err; @@ -2944,7 +2979,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, goto end_temporary; } - intern_close_table(new_table); /* close temporary table */ + intern_close_table(new_table); /* close temporary table */ my_free((gptr) new_table,MYF(0)); VOID(pthread_mutex_lock(&LOCK_open)); if (error) @@ -2961,8 +2996,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, */ thd->proc_info="rename result table"; - sprintf(old_name,"%s2-%lx-%lx", tmp_file_prefix, current_pid, - thd->thread_id); + if (snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix, + current_pid, thd->thread_id)>= (int)sizeof(old_name)) + goto err; if (new_name != table_name || new_db != db) { if (!access(new_name_buff,F_OK)) @@ -2983,18 +3019,18 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, Win32 and InnoDB can't drop a table that is in use, so we must close the original table at before doing the rename */ - table_name=thd->strdup(table_name); // must be saved + table_name=thd->strdup(table_name); // must be saved if (close_cached_table(thd, table)) - { // Aborted + { // Aborted VOID(quick_rm_table(new_db_type,new_db,tmp_name)); VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } - table=0; // Marker that table is closed + table=0; // Marker that table is closed } #if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2)) else - table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore + table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore #endif @@ -3005,8 +3041,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, VOID(quick_rm_table(new_db_type,new_db,tmp_name)); } else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db, - new_alias)) - { // Try to get everything back + new_alias)) + { // Try to get everything back error=1; VOID(quick_rm_table(new_db_type,new_db,new_alias)); VOID(quick_rm_table(new_db_type,new_db,tmp_name)); @@ -3023,7 +3059,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } - if (thd->lock || new_name != table_name) // True if WIN32 + if (thd->lock || new_name != table_name) // True if WIN32 { /* Not table locking or alter table with rename @@ -3044,14 +3080,14 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, { VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file remove_table_from_cache(thd,db,table_name); // Mark all in-use copies old - mysql_lock_abort(thd,table); // end threads waiting on lock + mysql_lock_abort(thd,table); // end threads waiting on lock } VOID(quick_rm_table(old_db_type,db,old_name)); if (close_data_tables(thd,db,table_name) || - reopen_tables(thd,1,0)) - { // This shouldn't happen + reopen_tables(thd,1,0)) + { // This shouldn't happen if (table) - close_cached_table(thd,table); // Remove lock for table + close_cached_table(thd,table); // Remove lock for table VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } @@ -3085,7 +3121,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, shutdown. */ 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); table=open_temporary_table(thd, path, new_db, tmp_name,0); if (table) @@ -3095,16 +3133,18 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, } else sql_print_error("Warning: Could not open BDB table %s.%s after rename\n", - new_db,table_name); + new_db,table_name); (void) berkeley_flush_logs(); } #endif - table_list->table=0; // For query cache + table_list->table=0; // For query cache query_cache_invalidate3(thd, table_list, 0); end_temporary: - sprintf(tmp_name, ER(ER_INSERT_INFO), (ulong) (copied + deleted), - (ulong) deleted, (ulong) thd->cuted_fields); + if (snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), + (ulong) (copied + deleted), (ulong) deleted, + (ulong) thd->cuted_fields)>= (int)sizeof(tmp_name)) + goto err; send_ok(thd,copied+deleted,0L,tmp_name); thd->some_tables_deleted=0; DBUG_RETURN(0); @@ -3117,9 +3157,9 @@ end_temporary: static int copy_data_between_tables(TABLE *from,TABLE *to, List &create, - enum enum_duplicates handle_duplicates, + enum enum_duplicates handle_duplicates, uint order_num, ORDER *order, - ha_rows *copied, + ha_rows *copied, ha_rows *deleted) { int error; @@ -3137,7 +3177,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, DBUG_ENTER("copy_data_between_tables"); if (!(copy= new Copy_field[to->fields])) - DBUG_RETURN(-1); /* purecov: inspected */ + DBUG_RETURN(-1); /* purecov: inspected */ to->file->external_lock(thd,F_WRLCK); to->file->extra(HA_EXTRA_WRITE_CACHE); @@ -3163,12 +3203,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, bzero((char*) &tables,sizeof(tables)); tables.table = from; tables.alias = tables.real_name= from->real_name; - tables.db = from->table_cache_key; + tables.db = from->table_cache_key; error=1; if (thd->lex->select_lex.setup_ref_array(thd, order_num) || - setup_order(thd, thd->lex->select_lex.ref_pointer_array, - &tables, fields, all_fields, order) || + setup_order(thd, thd->lex->select_lex.ref_pointer_array, + &tables, fields, all_fields, order) || !(sortorder=make_unireg_sortorder(order, &length)) || (from->sort.found_records = filesort(thd, from, sortorder, length, (SQL_SELECT *) 0, HA_POS_ERROR, @@ -3209,12 +3249,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, if ((error=to->file->write_row((byte*) to->record[0]))) { if ((handle_duplicates != DUP_IGNORE && - handle_duplicates != DUP_REPLACE) || - (error != HA_ERR_FOUND_DUPP_KEY && - error != HA_ERR_FOUND_DUPP_UNIQUE)) + handle_duplicates != DUP_REPLACE) || + (error != HA_ERR_FOUND_DUPP_KEY && + error != HA_ERR_FOUND_DUPP_UNIQUE)) { - to->file->print_error(error,MYF(0)); - break; + to->file->print_error(error,MYF(0)); + break; } delete_count++; } @@ -3223,7 +3263,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, } end_read_record(&info); free_io_cache(from); - delete [] copy; // This is never 0 + delete [] copy; // This is never 0 uint tmp_error; if ((tmp_error=to->file->extra(HA_EXTRA_NO_CACHE))) { @@ -3276,7 +3316,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) strxmov(table_name, table->db ,".", table->real_name, NullS); t= table->table= open_ltable(thd, table, TL_READ_NO_INSERT); - thd->clear_error(); // these errors shouldn't get client + thd->clear_error(); // these errors shouldn't get client protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); @@ -3295,7 +3335,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) !(check_opt->flags & T_EXTEND)) protocol->store((ulonglong)t->file->checksum()); else if (!(t->file->table_flags() & HA_HAS_CHECKSUM) && - (check_opt->flags & T_QUICK)) + (check_opt->flags & T_QUICK)) protocol->store_null(); else { @@ -3316,7 +3356,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) ha_checksum row_crc= 0; if (t->record[0] != (byte*) t->field[0]->ptr) row_crc= my_checksum(row_crc, t->record[0], - ((byte*) t->field[0]->ptr) - t->record[0]); + ((byte*) t->field[0]->ptr) - t->record[0]); for (uint i= 0; i < t->fields; i++ ) { @@ -3329,7 +3369,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) } else row_crc= my_checksum(row_crc, (byte*) f->ptr, - f->pack_length()); + f->pack_length()); } crc+= row_crc; @@ -3339,7 +3379,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) } thd->clear_error(); close_thread_tables(thd); - table->table=0; // For query cache + table->table=0; // For query cache } if (protocol->write()) goto err; @@ -3349,7 +3389,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) DBUG_RETURN(0); err: - close_thread_tables(thd); // Shouldn't be needed + close_thread_tables(thd); // Shouldn't be needed if (table) table->table=0; DBUG_RETURN(-1); From 03044fe20463f44c64b3ff8580972b3dbe874301 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Apr 2004 13:57:09 +0200 Subject: [PATCH 3/3] ignore: added install BitKeeper/etc/ignore: added install --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 541e854b188..5d14e0c080e 100644 --- a/.bzrignore +++ b/.bzrignore @@ -647,3 +647,4 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl mysys/test_gethwaddr +install