From 3f9a97c1e8597e1e0fb064f366bfbe2413548093 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Apr 2004 13:12:05 +0200 Subject: [PATCH] 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);