Commit ce816b35 authored by ingo@mysql.com's avatar ingo@mysql.com

Worklog#1563 - Support of on-line CREATE/DROP INDEX.

Corrected minor problems of the preceding changeset 1.1705.
parent 85ec87a0
...@@ -34,19 +34,19 @@ const char *primary_key_name= "PRIMARY"; ...@@ -34,19 +34,19 @@ const char *primary_key_name= "PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); 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 char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to, static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
uint order_num, ORDER *order, uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted); ha_rows *copied,ha_rows *deleted);
/* /*
delete (drop) tables. delete (drop) tables.
SYNOPSIS SYNOPSIS
mysql_rm_table() mysql_rm_table()
thd Thread handle thd Thread handle
tables List of tables to delete tables List of tables to delete
if_exists If 1, don't give error if one table doesn't exists if_exists If 1, don't give error if one table doesn't exists
NOTES NOTES
Will delete all tables that can be deleted and give a compact error 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, ...@@ -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. Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
RETURN RETURN
0 ok. In this case ok packet is sent to user 0 ok. In this case ok packet is sent to user
-1 Error (Error message given but not 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, int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
my_bool drop_temporary) my_bool drop_temporary)
{ {
int error= 0; int error= 0;
DBUG_ENTER("mysql_rm_table"); DBUG_ENTER("mysql_rm_table");
...@@ -79,7 +79,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, ...@@ -79,7 +79,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
if (thd->global_read_lock) if (thd->global_read_lock)
{ {
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0), my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
tables->real_name); tables->real_name);
error= 1; error= 1;
goto err; goto err;
} }
...@@ -111,23 +111,23 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, ...@@ -111,23 +111,23 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
SYNOPSIS SYNOPSIS
mysql_rm_table_part2_with_lock() mysql_rm_table_part2_with_lock()
thd Thread handle thd Thread handle
tables List of tables to delete tables List of tables to delete
if_exists If 1, don't give error if one table doesn't exists if_exists If 1, don't give error if one table doesn't exists
dont_log_query Don't write query to log files dont_log_query Don't write query to log files
NOTES NOTES
Works like documented in mysql_rm_table(), but don't check Works like documented in mysql_rm_table(), but don't check
global_read_lock and don't send_ok packet to server. global_read_lock and don't send_ok packet to server.
RETURN RETURN
0 ok 0 ok
1 error 1 error
*/ */
int mysql_rm_table_part2_with_lock(THD *thd, int mysql_rm_table_part2_with_lock(THD *thd,
TABLE_LIST *tables, bool if_exists, TABLE_LIST *tables, bool if_exists,
bool drop_temporary, bool dont_log_query) bool drop_temporary, bool dont_log_query)
{ {
int error; int error;
thd->mysys_var->current_mutex= &LOCK_open; thd->mysys_var->current_mutex= &LOCK_open;
...@@ -135,7 +135,7 @@ int mysql_rm_table_part2_with_lock(THD *thd, ...@@ -135,7 +135,7 @@ int mysql_rm_table_part2_with_lock(THD *thd,
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
dont_log_query); dont_log_query);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
...@@ -152,12 +152,12 @@ int mysql_rm_table_part2_with_lock(THD *thd, ...@@ -152,12 +152,12 @@ int mysql_rm_table_part2_with_lock(THD *thd,
SYNOPSIS SYNOPSIS
mysql_rm_table_part2() mysql_rm_table_part2()
thd Thread handler thd Thread handler
tables Tables to drop tables Tables to drop
if_exists If set, don't give an error if table doesn't exists. if_exists If set, don't give an error if table doesn't exists.
In this case we give an warning of level 'NOTE' In this case we give an warning of level 'NOTE'
drop_temporary Only drop temporary tables drop_temporary Only drop temporary tables
dont_log_query Don't log the query dont_log_query Don't log the query
TODO: TODO:
When logging to the binary log, we should log When logging to the binary log, we should log
...@@ -170,16 +170,16 @@ int mysql_rm_table_part2_with_lock(THD *thd, ...@@ -170,16 +170,16 @@ int mysql_rm_table_part2_with_lock(THD *thd,
not all. not all.
RETURN RETURN
0 ok 0 ok
1 Error 1 Error
-1 Thread was killed -1 Thread was killed
*/ */
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, 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; TABLE_LIST *table;
char path[FN_REFLEN], *alias; char path[FN_REFLEN], *alias;
String wrong_tables; String wrong_tables;
int error; int error;
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; 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, ...@@ -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)) if (!close_temporary_table(thd, db, table->real_name))
{ {
tmp_table_deleted=1; tmp_table_deleted=1;
continue; // removed temporary table continue; // removed temporary table
} }
error=0; error=0;
...@@ -204,13 +204,13 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -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); abort_locked_tables(thd,db,table->real_name);
while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed) while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed)
{ {
dropping_tables++; dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--; dropping_tables--;
} }
drop_locked_tables(thd,db,table->real_name); drop_locked_tables(thd,db,table->real_name);
if (thd->killed) if (thd->killed)
DBUG_RETURN(-1); DBUG_RETURN(-1);
alias= (lower_case_table_names == 2) ? table->alias : table->real_name; alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
/* remove form file and isam files */ /* remove form file and isam files */
strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS); 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, ...@@ -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 (drop_temporary || access(path,F_OK))
{ {
if (if_exists) if (if_exists)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
table->real_name); table->real_name);
else else
error= 1; error= 1;
} }
...@@ -229,27 +229,27 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -229,27 +229,27 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
{ {
char *end; char *end;
db_type table_type= get_table_type(path); 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); error=ha_delete_table(table_type, path);
if (error == ENOENT && if_exists) if (error == ENOENT && if_exists)
error = 0; error = 0;
if (error == HA_ERR_ROW_IS_REFERENCED) 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; foreign_key_error=1;
} }
if (!error || error == ENOENT) if (!error || error == ENOENT)
{ {
/* Delete the table definition file */ /* Delete the table definition file */
strmov(end,reg_ext); strmov(end,reg_ext);
if (!(error=my_delete(path,MYF(MY_WME)))) if (!(error=my_delete(path,MYF(MY_WME))))
some_tables_deleted=1; some_tables_deleted=1;
} }
} }
if (error) if (error)
{ {
if (wrong_tables.length()) if (wrong_tables.length())
wrong_tables.append(','); wrong_tables.append(',');
wrong_tables.append(String(table->real_name,system_charset_info)); 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, ...@@ -263,9 +263,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
thd->clear_error(); thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
tmp_table_deleted && !some_tables_deleted); tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
} }
} }
...@@ -285,15 +285,19 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -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, int quick_rm_table(enum db_type base,const char *db,
const char *table_name) const char *table_name)
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
int error=0; int error=0;
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table_name,reg_ext); if (snprintf(path, sizeof(path), "%s/%s/%s%s",
mysql_data_home, db, table_name, reg_ext)>= (int)sizeof(path))
return 1;
unpack_filename(path,path); unpack_filename(path,path);
if (my_delete(path,MYF(0))) if (my_delete(path,MYF(0)))
error=1; /* purecov: inspected */ error=1; /* purecov: inspected */
sprintf(path,"%s/%s/%s",mysql_data_home,db,table_name); if (snprintf(path, sizeof(path), "%s/%s/%s",
mysql_data_home, db, table_name)>= (int)sizeof(path))
return 1;
unpack_filename(path,path); unpack_filename(path,path);
return ha_delete_table(base,path) || error; return ha_delete_table(base,path) || error;
} }
...@@ -327,7 +331,7 @@ static int sort_keys(KEY *a, KEY *b) ...@@ -327,7 +331,7 @@ static int sort_keys(KEY *a, KEY *b)
return 1; return 1;
} }
else if (b->flags & HA_NOSAME) else if (b->flags & HA_NOSAME)
return 1; // Prefer b return 1; // Prefer b
if ((a->flags ^ b->flags) & HA_FULLTEXT) if ((a->flags ^ b->flags) & HA_FULLTEXT)
{ {
...@@ -338,8 +342,8 @@ static int sort_keys(KEY *a, KEY *b) ...@@ -338,8 +342,8 @@ static int sort_keys(KEY *a, KEY *b)
the original key position. the original key position.
*/ */
return ((a->usable_key_parts < b->usable_key_parts) ? -1 : return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
(a->usable_key_parts > b->usable_key_parts) ? 1 : (a->usable_key_parts > b->usable_key_parts) ? 1 :
0); 0);
} }
/* /*
...@@ -360,7 +364,7 @@ static int sort_keys(KEY *a, KEY *b) ...@@ -360,7 +364,7 @@ static int sort_keys(KEY *a, KEY *b)
*/ */
void check_duplicates_in_interval(const char *set_or_name, 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; unsigned int old_count= typelib->count;
const char **old_type_names= typelib->type_names; const char **old_type_names= typelib->type_names;
...@@ -375,9 +379,9 @@ void check_duplicates_in_interval(const char *set_or_name, ...@@ -375,9 +379,9 @@ void check_duplicates_in_interval(const char *set_or_name,
if (find_type((char*)*cur_value,typelib,1)) if (find_type((char*)*cur_value,typelib,1))
{ {
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE, push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DUPLICATED_VALUE_IN_TYPE, ER_DUPLICATED_VALUE_IN_TYPE,
ER(ER_DUPLICATED_VALUE_IN_TYPE), ER(ER_DUPLICATED_VALUE_IN_TYPE),
name,*cur_value,set_or_name); name,*cur_value,set_or_name);
} }
} }
typelib->count= old_count; typelib->count= old_count;
...@@ -389,33 +393,33 @@ void check_duplicates_in_interval(const char *set_or_name, ...@@ -389,33 +393,33 @@ void check_duplicates_in_interval(const char *set_or_name,
SYNOPSIS SYNOPSIS
mysql_prepare_table() mysql_prepare_table()
thd Thread object thd Thread object
create_info Create information (like MAX_ROWS) create_info Create information (like MAX_ROWS)
fields List of fields to create fields List of fields to create
keys List of keys to create keys List of keys to create
DESCRIPTION DESCRIPTION
Prepares the table and key structures for table creation. Prepares the table and key structures for table creation.
RETURN VALUES RETURN VALUES
0 ok 0 ok
-1 error -1 error
*/ */
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys, bool tmp_table, uint &db_options, List<Key> &keys, bool tmp_table, uint &db_options,
handler *file, KEY *&key_info_buffer, handler *file, KEY *&key_info_buffer,
uint &key_count, int select_field_count) uint &key_count, int select_field_count)
{ {
const char *key_name; const char *key_name;
create_field *sql_field,*dup_field; create_field *sql_field,*dup_field;
uint field,null_fields,blob_columns; uint field,null_fields,blob_columns;
ulong pos; ulong pos;
KEY *key_info; KEY *key_info;
KEY_PART_INFO *key_part_info; KEY_PART_INFO *key_part_info;
int field_no,dup_no; int field_no,dup_no;
int select_field_pos,auto_increment=0; int select_field_pos,auto_increment=0;
DBUG_ENTER("mysql_prepare_table"); DBUG_ENTER("mysql_prepare_table");
List_iterator<create_field> it(fields),it2(fields); List_iterator<create_field> it(fields),it2(fields);
...@@ -438,8 +442,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -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 */ /* Don't pack keys in old tables if the user has requested this */
if ((sql_field->flags & BLOB_FLAG) || if ((sql_field->flags & BLOB_FLAG) ||
sql_field->sql_type == FIELD_TYPE_VAR_STRING && sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
create_info->row_type != ROW_TYPE_FIXED) create_info->row_type != ROW_TYPE_FIXED)
{ {
db_options|=HA_OPTION_PACK_RECORD; db_options|=HA_OPTION_PACK_RECORD;
} }
...@@ -459,10 +463,10 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -459,10 +463,10 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->field_name, sql_field->field_name,
dup_field->field_name) == 0) dup_field->field_name) == 0)
{ {
/* /*
If this was a CREATE ... SELECT statement, accept a field If this was a CREATE ... SELECT statement, accept a field
redefinition if we are changing a field in the SELECT part redefinition if we are changing a field in the SELECT part
*/ */
if (field_no < select_field_pos || dup_no >= select_field_pos) if (field_no < select_field_pos || dup_no >= select_field_pos)
{ {
my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name); 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, ...@@ -470,20 +474,20 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
} }
else else
{ {
/* Field redefined */ /* Field redefined */
sql_field->sql_type= dup_field->sql_type; sql_field->sql_type= dup_field->sql_type;
sql_field->charset= (dup_field->charset ? sql_field->charset= (dup_field->charset ?
dup_field->charset : dup_field->charset :
create_info->default_table_charset); create_info->default_table_charset);
sql_field->length= dup_field->length; sql_field->length= dup_field->length;
sql_field->pack_length= dup_field->pack_length; sql_field->pack_length= dup_field->pack_length;
sql_field->create_length_to_internal_length(); sql_field->create_length_to_internal_length();
sql_field->decimals= dup_field->decimals; sql_field->decimals= dup_field->decimals;
sql_field->flags= dup_field->flags; sql_field->flags= dup_field->flags;
sql_field->unireg_check= dup_field->unireg_check; sql_field->unireg_check= dup_field->unireg_check;
it2.remove(); // Remove first (create) definition it2.remove(); // Remove first (create) definition
select_field_pos--; select_field_pos--;
break; break;
} }
} }
} }
...@@ -505,11 +509,11 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -505,11 +509,11 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB: case FIELD_TYPE_LONG_BLOB:
sql_field->pack_flag=FIELDFLAG_BLOB | sql_field->pack_flag=FIELDFLAG_BLOB |
pack_length_to_packflag(sql_field->pack_length - pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr); portable_sizeof_char_ptr);
if (sql_field->charset->state & MY_CS_BINSORT) if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD; sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++; blob_columns++;
break; break;
...@@ -517,49 +521,49 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -517,49 +521,49 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
#ifdef HAVE_SPATIAL #ifdef HAVE_SPATIAL
if (!(file->table_flags() & HA_HAS_GEOMETRY)) if (!(file->table_flags() & HA_HAS_GEOMETRY))
{ {
my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
MYF(0), "GEOMETRY"); MYF(0), "GEOMETRY");
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
sql_field->pack_flag=FIELDFLAG_GEOM | sql_field->pack_flag=FIELDFLAG_GEOM |
pack_length_to_packflag(sql_field->pack_length - pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr); portable_sizeof_char_ptr);
if (sql_field->charset->state & MY_CS_BINSORT) if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD; sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++; blob_columns++;
break; break;
#else #else
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), 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); DBUG_RETURN(-1);
#endif /*HAVE_SPATIAL*/ #endif /*HAVE_SPATIAL*/
case FIELD_TYPE_VAR_STRING: case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_STRING: case FIELD_TYPE_STRING:
sql_field->pack_flag=0; sql_field->pack_flag=0;
if (sql_field->charset->state & MY_CS_BINSORT) if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->pack_flag|=FIELDFLAG_BINARY;
break; break;
case FIELD_TYPE_ENUM: case FIELD_TYPE_ENUM:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_INTERVAL; FIELDFLAG_INTERVAL;
if (sql_field->charset->state & MY_CS_BINSORT) 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; sql_field->unireg_check=Field::INTERVAL_FIELD;
check_duplicates_in_interval("ENUM",sql_field->field_name, check_duplicates_in_interval("ENUM",sql_field->field_name,
sql_field->interval); sql_field->interval);
break; break;
case FIELD_TYPE_SET: case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_BITFIELD; FIELDFLAG_BITFIELD;
if (sql_field->charset->state & MY_CS_BINSORT) 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; sql_field->unireg_check=Field::BIT_FIELD;
check_duplicates_in_interval("SET",sql_field->field_name, check_duplicates_in_interval("SET",sql_field->field_name,
sql_field->interval); sql_field->interval);
break; break;
case FIELD_TYPE_DATE: // Rest of string types case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE: case FIELD_TYPE_NEWDATE:
case FIELD_TYPE_TIME: case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME: case FIELD_TYPE_DATETIME:
...@@ -571,12 +575,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -571,12 +575,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/* fall through */ /* fall through */
default: default:
sql_field->pack_flag=(FIELDFLAG_NUMBER | sql_field->pack_flag=(FIELDFLAG_NUMBER |
(sql_field->flags & UNSIGNED_FLAG ? 0 : (sql_field->flags & UNSIGNED_FLAG ? 0 :
FIELDFLAG_DECIMAL) | FIELDFLAG_DECIMAL) |
(sql_field->flags & ZEROFILL_FLAG ? (sql_field->flags & ZEROFILL_FLAG ?
FIELDFLAG_ZEROFILL : 0) | FIELDFLAG_ZEROFILL : 0) |
f_settype((uint) sql_field->sql_type) | f_settype((uint) sql_field->sql_type) |
(sql_field->decimals << FIELDFLAG_DEC_SHIFT)); (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break; break;
} }
if (!(sql_field->flags & NOT_NULL_FLAG)) if (!(sql_field->flags & NOT_NULL_FLAG))
...@@ -608,7 +612,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -608,7 +612,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
List_iterator<Key> key_iterator(keys); List_iterator<Key> key_iterator(keys);
uint key_parts=0, fk_key_count=0; uint key_parts=0, fk_key_count=0;
List<Key> keys_in_order; // Add new keys here List<Key> keys_in_order; // Add new keys here
bool primary_key=0,unique_key=0; bool primary_key=0,unique_key=0;
Key *key; Key *key;
uint tmp, key_number; uint tmp, key_number;
...@@ -623,12 +627,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -623,12 +627,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
fk_key_count++; fk_key_count++;
foreign_key *fk_key= (foreign_key*) key; foreign_key *fk_key= (foreign_key*) key;
if (fk_key->ref_columns.elements && 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 : my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
"foreign key without name", "foreign key without name",
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)); ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
continue; continue;
} }
...@@ -646,7 +650,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -646,7 +650,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
} }
key_parts+=key->columns.elements; key_parts+=key->columns.elements;
if (key->name && !tmp_table && 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); my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -662,7 +666,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -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_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); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
if (!key_info_buffer || ! key_part_info) if (!key_info_buffer || ! key_part_info)
DBUG_RETURN(-1); // Out of memory DBUG_RETURN(-1); // Out of memory
key_iterator.rewind(); key_iterator.rewind();
key_number=0; key_number=0;
...@@ -683,12 +687,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -683,12 +687,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags = HA_SPATIAL; key_info->flags = HA_SPATIAL;
break; break;
#else #else
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), 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); DBUG_RETURN(-1);
#endif #endif
case Key::FOREIGN_KEY: case Key::FOREIGN_KEY:
key_number--; // Skip this key key_number--; // Skip this key
continue; continue;
default: default:
key_info->flags = HA_NOSAME; key_info->flags = HA_NOSAME;
...@@ -731,17 +735,17 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -731,17 +735,17 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
#ifdef HAVE_RTREE_KEYS #ifdef HAVE_RTREE_KEYS
if ((key_info->key_parts & 1) == 1) if ((key_info->key_parts & 1) == 1)
{ {
my_printf_error(ER_WRONG_ARGUMENTS, my_printf_error(ER_WRONG_ARGUMENTS,
ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX"); ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
/* TODO: To be deleted */ /* TODO: To be deleted */
my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET), my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
MYF(0), "RTREE INDEX"); MYF(0), "RTREE INDEX");
DBUG_RETURN(-1); DBUG_RETURN(-1);
#else #else
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0), 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); DBUG_RETURN(-1);
#endif #endif
} }
...@@ -753,16 +757,16 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -753,16 +757,16 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
it.rewind(); it.rewind();
field=0; field=0;
while ((sql_field=it++) && while ((sql_field=it++) &&
my_strcasecmp(system_charset_info, my_strcasecmp(system_charset_info,
column->field_name, column->field_name,
sql_field->field_name)) sql_field->field_name))
field++; field++;
if (!sql_field) if (!sql_field)
{ {
my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS, my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0), ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
column->field_name); column->field_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
/* for fulltext keys keyseg length is 1 for blobs (it's ignored in /* 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. 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, ...@@ -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 (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
{ {
if (column_nr == 0 || (file->table_flags() & HA_AUTO_PART_KEY)) 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, ...@@ -861,17 +865,19 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
uint length=sql_field->pack_length; uint length=sql_field->pack_length;
if (column->length) if (column->length)
{ {
if (f_is_blob(sql_field->pack_flag)) if (f_is_blob(sql_field->pack_flag))
{ {
if ((length=column->length) > file->max_key_length() || if ((length=column->length) > file->max_key_length() ||
length > file->max_key_part_length()) length > file->max_key_part_length())
{ {
length=min(file->max_key_length(), file->max_key_part_length()); length=min(file->max_key_length(), file->max_key_part_length());
if (key->type == Key::MULTIPLE) if (key->type == Key::MULTIPLE)
{ {
/* not a critical problem */ /* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length); if (snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
length)>= (int)sizeof(warn_buff))
DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff); ER_TOO_LONG_KEY, warn_buff);
} }
...@@ -881,8 +887,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -881,8 +887,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
} }
else if (!f_is_geom(sql_field->pack_flag) && else if (!f_is_geom(sql_field->pack_flag) &&
(column->length > length || (column->length > length ||
((f_is_packed(sql_field->pack_flag) || ((f_is_packed(sql_field->pack_flag) ||
((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) && ((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
...@@ -897,9 +903,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -897,9 +903,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
} }
else if (length == 0) else if (length == 0)
{ {
my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0), my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
column->field_name); column->field_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (length > file->max_key_part_length()) if (length > file->max_key_part_length())
{ {
...@@ -908,7 +914,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -908,7 +914,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{ {
/* not a critical problem */ /* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length); if (snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
length)>= (int)sizeof(warn_buff))
DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff); ER_TOO_LONG_KEY, warn_buff);
} }
...@@ -921,15 +929,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -921,15 +929,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_part_info->length=(uint16) length; key_part_info->length=(uint16) length;
/* Use packed keys for long strings on the first column */ /* Use packed keys for long strings on the first column */
if (!(db_options & HA_OPTION_NO_PACK_KEYS) && if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
(length >= KEY_DEFAULT_PACK_LENGTH && (length >= KEY_DEFAULT_PACK_LENGTH &&
(sql_field->sql_type == FIELD_TYPE_STRING || (sql_field->sql_type == FIELD_TYPE_STRING ||
sql_field->sql_type == FIELD_TYPE_VAR_STRING || sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
sql_field->pack_flag & FIELDFLAG_BLOB))) sql_field->pack_flag & FIELDFLAG_BLOB)))
{ {
if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB))
key_info->flags|= HA_BINARY_PACK_KEY; key_info->flags|= HA_BINARY_PACK_KEY;
else else
key_info->flags|= HA_PACK_KEY; key_info->flags|= HA_PACK_KEY;
} }
key_length+=length; key_length+=length;
key_part_info++; key_part_info++;
...@@ -937,25 +945,25 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_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) */ /* Create the key name based on the first column (if not given) */
if (column_nr == 0) if (column_nr == 0)
{ {
if (key->type == Key::PRIMARY) if (key->type == Key::PRIMARY)
{ {
if (primary_key) if (primary_key)
{ {
my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
key_name=primary_key_name; key_name=primary_key_name;
primary_key=1; primary_key=1;
} }
else if (!(key_name = key->name)) else if (!(key_name = key->name))
key_name=make_unique_key_name(sql_field->field_name, key_name=make_unique_key_name(sql_field->field_name,
key_info_buffer,key_info); key_info_buffer,key_info);
if (check_if_keyname_exists(key_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); my_error(ER_DUP_KEYNAME,MYF(0),key_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
key_info->name=(char*) key_name; key_info->name=(char*) key_name;
} }
} }
if (!key_info->name || check_column_name(key_info->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, ...@@ -996,15 +1004,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
SYNOPSIS SYNOPSIS
mysql_create_table() mysql_create_table()
thd Thread object thd Thread object
db Database db Database
table_name Table name table_name Table name
create_info Create information (like MAX_ROWS) create_info Create information (like MAX_ROWS)
fields List of fields to create fields List of fields to create
keys List of keys to create keys List of keys to create
tmp_table Set to 1 if this is an internal temporary table tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE) (From ALTER TABLE)
no_log Don't log the query to binary log. no_log Don't log the query to binary log.
DESCRIPTION DESCRIPTION
If one creates a temporary table, this is automaticly opened 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, ...@@ -1015,23 +1023,23 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
and must be zero for standard create of table. and must be zero for standard create of table.
RETURN VALUES RETURN VALUES
0 ok 0 ok
-1 error -1 error
*/ */
int mysql_create_table(THD *thd,const char *db, const char *table_name, int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,bool tmp_table,bool no_log, List<Key> &keys,bool tmp_table,bool no_log,
uint select_field_count) uint select_field_count)
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
const char *alias; const char *alias;
int error= -1; int error= -1;
uint db_options, key_count; uint db_options, key_count;
KEY *key_info_buffer; KEY *key_info_buffer;
handler *file; handler *file;
enum db_type new_db_type; enum db_type new_db_type;
DBUG_ENTER("mysql_create_table"); DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */ /* 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, ...@@ -1045,10 +1053,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{ {
create_info->db_type= new_db_type; create_info->db_type= new_db_type;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER, ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER), ER(ER_WARN_USING_OTHER_HANDLER),
ha_get_storage_engine(new_db_type), ha_get_storage_engine(new_db_type),
table_name); table_name);
} }
db_options=create_info->table_options; db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC) 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, ...@@ -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, if (mysql_prepare_table(thd, create_info, fields,
keys, tmp_table, db_options, file, keys, tmp_table, db_options, file,
key_info_buffer, key_count, key_info_buffer, key_count,
select_field_count)) select_field_count))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* Check if table exists */ /* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{ {
sprintf(path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix, if (snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s",
current_pid, thd->thread_id, thd->tmp_table++,reg_ext); mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id,
thd->tmp_table++, reg_ext)>= (int)sizeof(path))
DBUG_RETURN(-1);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
} }
else else
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,alias,reg_ext); if (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home, db,
alias, reg_ext)>= (int)sizeof(path))
DBUG_RETURN(-1);
unpack_filename(path,path); unpack_filename(path,path);
/* Check if table already exists */ /* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
...@@ -1085,7 +1097,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -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) 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); DBUG_RETURN(0);
} }
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); 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, ...@@ -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) 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
error= 0; error= 0;
} }
else else
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); 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, ...@@ -1110,14 +1122,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
} }
thd->proc_info="creating table"; 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) if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
create_info->data_file_name= create_info->index_file_name= 0; create_info->data_file_name= create_info->index_file_name= 0;
create_info->table_options=db_options; create_info->table_options=db_options;
if (rea_create_table(thd, path, create_info, fields, key_count, 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); */ /* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
goto end; goto end;
...@@ -1140,8 +1152,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -1140,8 +1152,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{ {
thd->clear_error(); thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
test(create_info->options & test(create_info->options &
HA_LEX_CREATE_TMP_TABLE)); HA_LEX_CREATE_TMP_TABLE));
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
} }
...@@ -1171,17 +1183,23 @@ static char * ...@@ -1171,17 +1183,23 @@ static char *
make_unique_key_name(const char *field_name,KEY *start,KEY *end) make_unique_key_name(const char *field_name,KEY *start,KEY *end)
{ {
char buff[MAX_FIELD_NAME],*buff_end; char buff[MAX_FIELD_NAME],*buff_end;
int remain;
if (!check_if_keyname_exists(field_name,start,end) && if (!check_if_keyname_exists(field_name,start,end) &&
my_strcasecmp(system_charset_info,field_name,primary_key_name)) my_strcasecmp(system_charset_info,field_name,primary_key_name))
return (char*) field_name; // Use fieldname return (char*) field_name; // Use fieldname
buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4); buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4);
for (uint i=2 ; ; i++) /*ingo 2004-04-07 only 3 chars + '\0' left, so need to limit to 2 digit*/
for (uint i=2 ; i< 100; i++)
{ {
sprintf(buff_end,"_%d",i); remain= (int)sizeof(buff)- (buff_end- buff);
if (snprintf(buff_end, remain, "_%d", i)>= remain)
return NULL;
if (!check_if_keyname_exists(buff,start,end)) if (!check_if_keyname_exists(buff,start,end))
return sql_strdup(buff); return sql_strdup(buff);
} }
/*ingo 2004-04-07 dedicated return is inevitable*/
return NULL;
} }
/**************************************************************************** /****************************************************************************
...@@ -1189,13 +1207,13 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end) ...@@ -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, TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
const char *db, const char *name, const char *db, const char *name,
List<create_field> *extra_fields, List<create_field> *extra_fields,
List<Key> *keys, List<Key> *keys,
List<Item> *items, List<Item> *items,
MYSQL_LOCK **lock) MYSQL_LOCK **lock)
{ {
TABLE tmp_table; // Used during 'create_field()' TABLE tmp_table; // Used during 'create_field()'
TABLE *table; TABLE *table;
tmp_table.table_name=0; tmp_table.table_name=0;
uint select_field_count= items->elements; uint select_field_count= items->elements;
...@@ -1209,7 +1227,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -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.null_row=tmp_table.maybe_null=0;
tmp_table.blob_ptr_size=portable_sizeof_char_ptr; tmp_table.blob_ptr_size=portable_sizeof_char_ptr;
tmp_table.db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM || 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++)) while ((item=it++))
{ {
...@@ -1219,18 +1237,18 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1219,18 +1237,18 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
field=item->tmp_table_field(&tmp_table); field=item->tmp_table_field(&tmp_table);
else else
field=create_tmp_field(thd, &tmp_table, item, item->type(), field=create_tmp_field(thd, &tmp_table, item, item->type(),
(Item ***) 0, &tmp_field,0,0); (Item ***) 0, &tmp_field,0,0);
if (!field || if (!field ||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
((Item_field *)item)->field : ((Item_field *)item)->field :
(Field*) 0)))) (Field*) 0))))
DBUG_RETURN(0); DBUG_RETURN(0);
extra_fields->push_back(cr_field); extra_fields->push_back(cr_field);
} }
/* create and lock table */ /* create and lock table */
/* QQ: This should be done atomic ! */ /* QQ: This should be done atomic ! */
if (mysql_create_table(thd,db,name,create_info,*extra_fields, 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); DBUG_RETURN(0);
if (!(table=open_table(thd,db,name,name,(bool*) 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, ...@@ -1257,10 +1275,10 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
bool bool
mysql_rename_table(enum db_type base, mysql_rename_table(enum db_type base,
const char *old_db, const char *old_db,
const char *old_name, const char *old_name,
const char *new_db, const char *new_db,
const char *new_name) const char *new_name)
{ {
char from[FN_REFLEN], to[FN_REFLEN]; char from[FN_REFLEN], to[FN_REFLEN];
char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1]; char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1];
...@@ -1279,8 +1297,12 @@ mysql_rename_table(enum db_type base, ...@@ -1279,8 +1297,12 @@ mysql_rename_table(enum db_type base,
my_casedn_str(system_charset_info, tmp_to); my_casedn_str(system_charset_info, tmp_to);
new_name= tmp_to; new_name= tmp_to;
} }
(void) sprintf(from,"%s/%s/%s",mysql_data_home,old_db,old_name); if (snprintf(from, sizeof(from), "%s/%s/%s",
(void) sprintf(to,"%s/%s/%s",mysql_data_home,new_db,new_name); mysql_data_home, old_db, old_name)>= (int)sizeof(from))
DBUG_RETURN(1);
if (snprintf(to, sizeof(to), "%s/%s/%s",
mysql_data_home, new_db, new_name)>= (int)sizeof(to))
DBUG_RETURN(1);
fn_format(from,from,"","",4); fn_format(from,from,"","",4);
fn_format(to,to, "","",4); fn_format(to,to, "","",4);
...@@ -1305,10 +1327,10 @@ mysql_rename_table(enum db_type base, ...@@ -1305,10 +1327,10 @@ mysql_rename_table(enum db_type base,
SYNOPSIS SYNOPSIS
wait_while_table_is_used() wait_while_table_is_used()
thd Thread handler thd Thread handler
table Table to remove from cache table Table to remove from cache
function HA_EXTRA_PREPARE_FOR_DELETE if table is to be deleted function HA_EXTRA_PREPARE_FOR_DELETE if table is to be deleted
HA_EXTRA_FORCE_REOPEN if table is not be used HA_EXTRA_FORCE_REOPEN if table is not be used
NOTES NOTES
When returning, the table will be unusable for other threads until When returning, the table will be unusable for other threads until
the table is closed. the table is closed.
...@@ -1319,7 +1341,7 @@ mysql_rename_table(enum db_type base, ...@@ -1319,7 +1341,7 @@ mysql_rename_table(enum db_type base,
*/ */
static void wait_while_table_is_used(THD *thd,TABLE *table, 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_PRINT("enter",("table: %s", table->real_name));
DBUG_ENTER("wait_while_table_is_used"); DBUG_ENTER("wait_while_table_is_used");
...@@ -1327,11 +1349,11 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, ...@@ -1327,11 +1349,11 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
VOID(table->file->extra(function)); VOID(table->file->extra(function));
/* Mark all tables that are in use as 'old' */ /* 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 */ /* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key, while (remove_table_from_cache(thd,table->table_cache_key,
table->real_name)) table->real_name))
{ {
dropping_tables++; dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
...@@ -1345,8 +1367,8 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, ...@@ -1345,8 +1367,8 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
SYNOPSIS SYNOPSIS
close_cached_table() close_cached_table()
thd Thread handler thd Thread handler
table Table to remove from cache table Table to remove from cache
NOTES NOTES
Function ends by signaling threads waiting for the table to try to 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) ...@@ -1366,7 +1388,7 @@ static bool close_cached_table(THD *thd, TABLE *table)
if (thd->lock) if (thd->lock)
{ {
mysql_unlock_tables(thd, 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 */ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table); thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
...@@ -1377,7 +1399,7 @@ static bool close_cached_table(THD *thd, TABLE *table) ...@@ -1377,7 +1399,7 @@ static bool close_cached_table(THD *thd, TABLE *table)
} }
static int send_check_errmsg(THD *thd, TABLE_LIST* 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; Protocol *protocol= thd->protocol;
...@@ -1394,15 +1416,15 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table, ...@@ -1394,15 +1416,15 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
static int prepare_for_restore(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"); DBUG_ENTER("prepare_for_restore");
if (table->table) // do not overwrite existing tables on restore if (table->table) // do not overwrite existing tables on restore
{ {
DBUG_RETURN(send_check_errmsg(thd, table, "restore", DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"table exists, will not overwrite on restore" "table exists, will not overwrite on restore"
)); ));
} }
else else
{ {
...@@ -1412,23 +1434,25 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, ...@@ -1412,23 +1434,25 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
char* db = thd->db ? thd->db : table->db; char* db = thd->db ? thd->db : table->db;
if (fn_format_relative_to_data_home(src_path, table_name, backup_dir, if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
reg_ext)) reg_ext))
DBUG_RETURN(-1); // protect buffer overflow DBUG_RETURN(-1); // protect buffer overflow
sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name); if (snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
mysql_real_data_home, db, table_name)>= (int)sizeof(dst_path))
DBUG_RETURN(-1);
if (lock_and_wait_for_table_name(thd,table)) if (lock_and_wait_for_table_name(thd,table))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (my_copy(src_path, if (my_copy(src_path,
fn_format(dst_path, dst_path,"", reg_ext, 4), fn_format(dst_path, dst_path,"", reg_ext, 4),
MYF(MY_WME))) MYF(MY_WME)))
{ {
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table); unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore", DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed copying .frm file")); "Failed copying .frm file"));
} }
if (mysql_truncate(thd, table, 1)) if (mysql_truncate(thd, table, 1))
{ {
...@@ -1436,7 +1460,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, ...@@ -1436,7 +1460,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
unlock_table_name(thd, table); unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore", 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, ...@@ -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, static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
HA_CHECK_OPT *check_opt) HA_CHECK_OPT *check_opt)
{ {
int error= 0; int error= 0;
TABLE tmp_table, *table; TABLE tmp_table, *table;
...@@ -1464,13 +1488,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1464,13 +1488,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
if (!(check_opt->sql_flags & TT_USEFRM)) if (!(check_opt->sql_flags & TT_USEFRM))
DBUG_RETURN(0); 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]; char name[FN_REFLEN];
strxmov(name, mysql_data_home, "/", table_list->db, "/", 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)) 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; table= &tmp_table;
} }
...@@ -1493,13 +1517,18 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1493,13 +1517,18 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
like ISAM or MyISAM like ISAM or MyISAM
*/ */
if (!ext[0] || !ext[1]) 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))) if (!my_stat(from, &stat_info, MYF(0)))
goto end; // Can't use USE_FRM flag goto end; // Can't use USE_FRM flag
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); if (snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
from, current_pid, thd->thread_id)>= (int)sizeof(tmp))
{
error= -1;
goto end;
}
/* If we could open the table, close it */ /* If we could open the table, close it */
if (table_list->table) if (table_list->table)
...@@ -1519,7 +1548,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1519,7 +1548,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
unlock_table_name(thd, table_list); unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair", error= send_check_errmsg(thd, table_list, "repair",
"Failed renaming data file"); "Failed renaming data file");
goto end; goto end;
} }
if (mysql_truncate(thd, table_list, 1)) if (mysql_truncate(thd, table_list, 1))
...@@ -1528,7 +1557,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1528,7 +1557,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
unlock_table_name(thd, table_list); unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair", error= send_check_errmsg(thd, table_list, "repair",
"Failed generating table from .frm file"); "Failed generating table from .frm file");
goto end; goto end;
} }
if (my_rename(tmp, from, MYF(MY_WME))) if (my_rename(tmp, from, MYF(MY_WME)))
...@@ -1537,7 +1566,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1537,7 +1566,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
unlock_table_name(thd, table_list); unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair", error= send_check_errmsg(thd, table_list, "repair",
"Failed restoring .MYD file"); "Failed restoring .MYD file");
goto end; goto end;
} }
...@@ -1554,21 +1583,21 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, ...@@ -1554,21 +1583,21 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
end: end:
if (table == &tmp_table) if (table == &tmp_table)
closefrm(table); // Free allocated memory closefrm(table); // Free allocated memory
DBUG_RETURN(error); DBUG_RETURN(error);
} }
static int mysql_admin_table(THD* thd, TABLE_LIST* tables, static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt, HA_CHECK_OPT* check_opt,
const char *operator_name, const char *operator_name,
thr_lock_type lock_type, thr_lock_type lock_type,
bool open_for_modify, bool open_for_modify,
uint extra_open_options, uint extra_open_options,
int (*prepare_func)(THD *, TABLE_LIST *, int (*prepare_func)(THD *, TABLE_LIST *,
HA_CHECK_OPT *), HA_CHECK_OPT *),
int (handler::*operator_func) int (handler::*operator_func)
(THD *, HA_CHECK_OPT *)) (THD *, HA_CHECK_OPT *))
{ {
TABLE_LIST *table; TABLE_LIST *table;
List<Item> field_list; List<Item> field_list;
...@@ -1619,11 +1648,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1619,11 +1648,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store(operator_name, system_charset_info); protocol->store(operator_name, system_charset_info);
protocol->store("error",5, system_charset_info); protocol->store("error",5, system_charset_info);
if (!(err_msg=thd->net.last_error)) 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); protocol->store(err_msg, system_charset_info);
thd->net.last_error[0]=0; thd->net.last_error[0]=0;
if (protocol->write()) if (protocol->write())
goto err; goto err;
continue; continue;
} }
table->table->pos_in_table_list= table; table->table->pos_in_table_list= table;
...@@ -1634,12 +1663,14 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1634,12 +1663,14 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store(table_name, system_charset_info); protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info); protocol->store(operator_name, system_charset_info);
protocol->store("error", 5, system_charset_info); protocol->store("error", 5, system_charset_info);
sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name); if (snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name)>= (int)sizeof(buff))
goto err;
protocol->store(buff, system_charset_info); protocol->store(buff, system_charset_info);
close_thread_tables(thd); close_thread_tables(thd);
table->table=0; // For query cache table->table=0; // For query cache
if (protocol->write()) if (protocol->write())
goto err; goto err;
continue; continue;
} }
...@@ -1648,20 +1679,20 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1648,20 +1679,20 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
{ {
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &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); mysql_lock_abort(thd,table->table);
while (remove_table_from_cache(thd, table->table->table_cache_key, while (remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name) && table->table->real_name) &&
! thd->killed) ! thd->killed)
{ {
dropping_tables++; dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--; dropping_tables--;
} }
thd->exit_cond(old_message); thd->exit_cond(old_message);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
if (thd->killed) if (thd->killed)
goto err; goto err;
open_for_modify=0; open_for_modify=0;
} }
...@@ -1678,7 +1709,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1678,7 +1709,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
{ {
char buf[ERRMSGSIZE+20]; char buf[ERRMSGSIZE+20];
uint length=my_snprintf(buf, ERRMSGSIZE, 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("error", 5, system_charset_info);
protocol->store(buf, length, system_charset_info); protocol->store(buf, length, system_charset_info);
} }
...@@ -1710,26 +1741,26 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1710,26 +1741,26 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store("Invalid argument",16, system_charset_info); protocol->store("Invalid argument",16, system_charset_info);
break; break;
default: // Probably HA_ADMIN_INTERNAL_ERROR default: // Probably HA_ADMIN_INTERNAL_ERROR
protocol->store("error", 5, system_charset_info); protocol->store("error", 5, system_charset_info);
protocol->store("Unknown - internal error during operation", 41 protocol->store("Unknown - internal error during operation", 41
, system_charset_info); , system_charset_info);
fatal_error=1; fatal_error=1;
break; break;
} }
if (fatal_error) if (fatal_error)
table->table->version=0; // Force close of table table->table->version=0; // Force close of table
else if (open_for_modify) else if (open_for_modify)
{ {
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
remove_table_from_cache(thd, table->table->table_cache_key, remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name); table->table->real_name);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
/* May be something modified consequently we have to invalidate cache */ /* May be something modified consequently we have to invalidate cache */
query_cache_invalidate3(thd, table->table, 0); query_cache_invalidate3(thd, table->table, 0);
} }
close_thread_tables(thd); close_thread_tables(thd);
table->table=0; // For query cache table->table=0; // For query cache
if (protocol->write()) if (protocol->write())
goto err; goto err;
} }
...@@ -1737,7 +1768,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1737,7 +1768,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
send_eof(thd); send_eof(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
close_thread_tables(thd); // Shouldn't be needed close_thread_tables(thd); // Shouldn't be needed
if (table) if (table)
table->table=0; table->table=0;
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -1748,8 +1779,8 @@ int mysql_backup_table(THD* thd, TABLE_LIST* table_list) ...@@ -1748,8 +1779,8 @@ int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
{ {
DBUG_ENTER("mysql_backup_table"); DBUG_ENTER("mysql_backup_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0, DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"backup", TL_READ, 0, 0, 0, "backup", TL_READ, 0, 0, 0,
&handler::backup)); &handler::backup));
} }
...@@ -1757,9 +1788,9 @@ int mysql_restore_table(THD* thd, TABLE_LIST* table_list) ...@@ -1757,9 +1788,9 @@ int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{ {
DBUG_ENTER("mysql_restore_table"); DBUG_ENTER("mysql_restore_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0, DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"restore", TL_WRITE, 1, 0, "restore", TL_WRITE, 1, 0,
&prepare_for_restore, &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) ...@@ -1767,9 +1798,9 @@ int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{ {
DBUG_ENTER("mysql_repair_table"); DBUG_ENTER("mysql_repair_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, 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, &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) ...@@ -1777,8 +1808,8 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{ {
DBUG_ENTER("mysql_optimize_table"); DBUG_ENTER("mysql_optimize_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"optimize", TL_WRITE, 1,0,0, "optimize", TL_WRITE, 1,0,0,
&handler::optimize)); &handler::optimize));
} }
...@@ -1787,16 +1818,16 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) ...@@ -1787,16 +1818,16 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
SYNOPSIS SYNOPSIS
mysql_assign_to_keycache() mysql_assign_to_keycache()
thd Thread object thd Thread object
tables Table list (one table only) tables Table list (one table only)
RETURN VALUES RETURN VALUES
0 ok 0 ok
-1 error -1 error
*/ */
int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, 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; HA_CHECK_OPT check_opt;
KEY_CACHE *key_cache; KEY_CACHE *key_cache;
...@@ -1813,7 +1844,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, ...@@ -1813,7 +1844,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
check_opt.key_cache= key_cache; check_opt.key_cache= key_cache;
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, 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)); 0, 0, &handler::assign_to_keycache));
} }
...@@ -1823,7 +1854,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, ...@@ -1823,7 +1854,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
SYNOPSIS SYNOPSIS
reassign_keycache_tables() reassign_keycache_tables()
thd Thread object thd Thread object
src_cache Reference to the key cache to clean up src_cache Reference to the key cache to clean up
dest_cache New key cache dest_cache New key cache
...@@ -1840,7 +1871,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, ...@@ -1840,7 +1871,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
to it for a while after this function returns. to it for a while after this function returns.
RETURN VALUES RETURN VALUES
0 ok 0 ok
*/ */
int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
...@@ -1850,7 +1881,7 @@ 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 != dst_cache);
DBUG_ASSERT(src_cache->in_init); 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_resize_key_cache(src_cache);
ha_change_key_cache(src_cache, dst_cache); ha_change_key_cache(src_cache, dst_cache);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -1862,20 +1893,20 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, ...@@ -1862,20 +1893,20 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
SYNOPSIS SYNOPSIS
mysql_preload_keys() mysql_preload_keys()
thd Thread object thd Thread object
tables Table list (one table only) tables Table list (one table only)
RETURN VALUES RETURN VALUES
0 ok 0 ok
-1 error -1 error
*/ */
int mysql_preload_keys(THD* thd, TABLE_LIST* tables) int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{ {
DBUG_ENTER("mysql_preload_keys"); DBUG_ENTER("mysql_preload_keys");
DBUG_RETURN(mysql_admin_table(thd, tables, 0, DBUG_RETURN(mysql_admin_table(thd, tables, 0,
"preload_keys", TL_READ, 0, 0, 0, "preload_keys", TL_READ, 0, 0, 0,
&handler::preload_keys)); &handler::preload_keys));
} }
...@@ -1884,14 +1915,14 @@ int mysql_preload_keys(THD* thd, TABLE_LIST* tables) ...@@ -1884,14 +1915,14 @@ int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
SYNOPSIS SYNOPSIS
mysql_create_like_table() mysql_create_like_table()
thd Thread object thd Thread object
table Table list (one table only) table Table list (one table only)
create_info Create info create_info Create info
table_ident Src table_ident table_ident Src table_ident
RETURN VALUES RETURN VALUES
0 ok 0 ok
-1 error -1 error
*/ */
int mysql_create_like_table(THD* thd, TABLE_LIST* table, int mysql_create_like_table(THD* thd, TABLE_LIST* table,
...@@ -1942,8 +1973,11 @@ 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)) if (find_temporary_table(thd, db, table_name))
goto table_exists; goto table_exists;
sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix, if (snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s",
current_pid, thd->thread_id, thd->tmp_table++,reg_ext); mysql_tmpdir, tmp_file_prefix, current_pid,
thd->thread_id, thd->tmp_table++, reg_ext)>=
(int)sizeof(dst_path))
DBUG_RETURN(-1);
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE; create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
} }
else else
...@@ -1990,8 +2024,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -1990,8 +2024,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
{ {
thd->clear_error(); thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
test(create_info->options & test(create_info->options &
HA_LEX_CREATE_TMP_TABLE)); HA_LEX_CREATE_TMP_TABLE));
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -2000,7 +2034,9 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -2000,7 +2034,9 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{ {
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name); if (snprintf(warn_buff, sizeof(warn_buff),
ER(ER_TABLE_EXISTS_ERROR), table_name)>= (int)sizeof(warn_buff))
DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,warn_buff); ER_TABLE_EXISTS_ERROR,warn_buff);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -2020,8 +2056,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) ...@@ -2020,8 +2056,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_analyze_table"); DBUG_ENTER("mysql_analyze_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"analyze", lock_type, 1,0,0, "analyze", lock_type, 1,0,0,
&handler::analyze)); &handler::analyze));
} }
...@@ -2035,15 +2071,15 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt) ...@@ -2035,15 +2071,15 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_check_table"); DBUG_ENTER("mysql_check_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"check", lock_type, "check", lock_type,
0, HA_OPEN_FOR_REPAIR, 0, 0, HA_OPEN_FOR_REPAIR, 0,
&handler::check)); &handler::check));
} }
/* table_list should contain just one table */ /* table_list should contain just one table */
int mysql_discard_or_import_tablespace(THD *thd, int mysql_discard_or_import_tablespace(THD *thd,
TABLE_LIST *table_list, TABLE_LIST *table_list,
enum tablespace_op_type tablespace_op) enum tablespace_op_type tablespace_op)
{ {
TABLE *table; TABLE *table;
my_bool discard; my_bool discard;
...@@ -2061,8 +2097,8 @@ int mysql_discard_or_import_tablespace(THD *thd, ...@@ -2061,8 +2097,8 @@ int mysql_discard_or_import_tablespace(THD *thd,
discard = FALSE; discard = FALSE;
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
and ::external_lock() do not complain when we and ::external_lock() do not complain when we
lock the table */ lock the table */
mysql_ha_closeall(thd, table_list); mysql_ha_closeall(thd, table_list);
if (!(table=open_ltable(thd,table_list,TL_WRITE))) if (!(table=open_ltable(thd,table_list,TL_WRITE)))
...@@ -2119,12 +2155,12 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) ...@@ -2119,12 +2155,12 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
HA_CREATE_INFO create_info; HA_CREATE_INFO create_info;
int rc; int rc;
uint idx; uint idx;
uint db_options; uint db_options;
uint key_count; uint key_count;
TABLE *table; TABLE *table;
Field **f_ptr; Field **f_ptr;
KEY *key_info_buffer; KEY *key_info_buffer;
char path[FN_REFLEN]; char path[FN_REFLEN];
DBUG_ENTER("mysql_create_index"); DBUG_ENTER("mysql_create_index");
/* /*
...@@ -2154,9 +2190,9 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) ...@@ -2154,9 +2190,9 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.default_table_charset= thd->variables.collation_database; create_info.default_table_charset= thd->variables.collation_database;
db_options= 0; db_options= 0;
if (mysql_prepare_table(thd, &create_info, fields, if (mysql_prepare_table(thd, &create_info, fields,
keys, /*tmp_table*/ 0, db_options, table->file, keys, /*tmp_table*/ 0, db_options, table->file,
key_info_buffer, key_count, key_info_buffer, key_count,
/*select_field_count*/ 0)) /*select_field_count*/ 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* /*
...@@ -2170,7 +2206,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) ...@@ -2170,7 +2206,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK))) (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ; 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. */ /* Re-initialize the create_info, which was changed by prepare table. */
bzero((char*) &create_info,sizeof(create_info)); bzero((char*) &create_info,sizeof(create_info));
...@@ -2188,9 +2224,10 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) ...@@ -2188,9 +2224,10 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
else else
{ {
if (table->file->add_index(table, key_info_buffer, key_count)|| if (table->file->add_index(table, key_info_buffer, key_count)||
((void) sprintf(path, "%s/%s/%s%s", mysql_data_home, table_list->db, (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
(lower_case_table_names == 2)? table_list->alias: table_list->db, (lower_case_table_names == 2)?
table_list->real_name, reg_ext), 0)|| table_list->alias: table_list->real_name, reg_ext)>=
(int)sizeof(path))||
! unpack_filename(path, path)|| ! unpack_filename(path, path)||
mysql_create_frm(thd, path, &create_info, mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file)) fields, key_count, key_info_buffer, table->file))
...@@ -2210,14 +2247,14 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2210,14 +2247,14 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
List<Alter_column> alter; List<Alter_column> alter;
HA_CREATE_INFO create_info; HA_CREATE_INFO create_info;
uint idx; uint idx;
uint db_options; uint db_options;
uint key_count; uint key_count;
uint *key_numbers; uint *key_numbers;
TABLE *table; TABLE *table;
Field **f_ptr; Field **f_ptr;
KEY *key_info; KEY *key_info;
KEY *key_info_buffer; KEY *key_info_buffer;
char path[FN_REFLEN]; char path[FN_REFLEN];
DBUG_ENTER("mysql_drop_index"); DBUG_ENTER("mysql_drop_index");
/* /*
...@@ -2249,7 +2286,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2249,7 +2286,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
for (idx=0; idx< table->keys; idx++, key_info++) for (idx=0; idx< table->keys; idx++, key_info++)
{ {
if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name)) if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
break; break;
} }
if (idx>= table->keys) if (idx>= table->keys)
{ {
...@@ -2289,9 +2326,10 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2289,9 +2326,10 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
keys, /*tmp_table*/ 0, db_options, table->file, keys, /*tmp_table*/ 0, db_options, table->file,
key_info_buffer, key_count, key_info_buffer, key_count,
/*select_field_count*/ 0)|| /*select_field_count*/ 0)||
((void) sprintf(path, "%s/%s/%s%s", mysql_data_home, table_list->db, (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
(lower_case_table_names == 2)? table_list->alias: table_list->db, (lower_case_table_names == 2)?
table_list->real_name, reg_ext), 0)|| table_list->alias: table_list->real_name, reg_ext)>=
(int)sizeof(path))||
! unpack_filename(path, path)|| ! unpack_filename(path, path)||
mysql_create_frm(thd, path, &create_info, mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file)) fields, key_count, key_info_buffer, table->file))
...@@ -2304,7 +2342,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2304,7 +2342,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
} }
int mysql_add_column(THD *thd, TABLE_LIST *table_list, int mysql_add_column(THD *thd, TABLE_LIST *table_list,
List<create_field> &fields) List<create_field> &fields)
{ {
List<Alter_drop> drop; List<Alter_drop> drop;
List<Key> keys; List<Key> keys;
...@@ -2319,9 +2357,9 @@ int mysql_add_column(THD *thd, TABLE_LIST *table_list, ...@@ -2319,9 +2357,9 @@ int mysql_add_column(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(real_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(real_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, table, &create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0, fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_COLUMN, DUP_ERROR)); ALTER_ADD_COLUMN, DUP_ERROR));
} }
int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
...@@ -2339,37 +2377,31 @@ int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2339,37 +2377,31 @@ int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(real_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(real_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, table, &create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0, fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_COLUMN, DUP_ERROR)); ALTER_DROP_COLUMN, DUP_ERROR));
} }
int mysql_alter_table(THD *thd,char *new_db, char *new_name, int mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
TABLE_LIST *table_list, TABLE_LIST *table_list,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
uint order_num, ORDER *order, int alter_flags, uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
enum tablespace_op_type tablespace_op, enum tablespace_op_type tablespace_op,
bool simple_alter) bool simple_alter)
{ {
DBUG_ENTER("mysql_alter_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); mysql_ha_closeall(thd, table_list);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (tablespace_op != NO_TABLESPACE_OP) if (tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list, DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
tablespace_op)); tablespace_op));
if (alter_flags == ALTER_ADD_INDEX) if (alter_flags == ALTER_ADD_INDEX)
DBUG_RETURN(mysql_create_index(thd, table_list, keys)); 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, ...@@ -2388,24 +2420,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(real_alter_table(thd, new_db, new_name, DBUG_RETURN(real_alter_table(thd, new_db, new_name,
create_info, table_list, table, fields, create_info, table_list, table, fields,
keys, drop_list, alter_list, keys, drop_list, alter_list,
order_num, order, alter_flags, order_num, order, alter_flags,
handle_duplicates, keys_onoff, handle_duplicates, keys_onoff,
tablespace_op, simple_alter)); tablespace_op, simple_alter));
} }
int real_alter_table(THD *thd,char *new_db, char *new_name, int real_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
TABLE_LIST *table_list, TABLE_LIST *table_list,
TABLE *table, TABLE *table,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
uint order_num, ORDER *order, int alter_flags, uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
enum tablespace_op_type tablespace_op, enum tablespace_op_type tablespace_op,
bool simple_alter) bool simple_alter)
{ {
TABLE *new_table; TABLE *new_table;
...@@ -2440,13 +2472,13 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2440,13 +2472,13 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
{ {
if (lower_case_table_names != 2) if (lower_case_table_names != 2)
{ {
my_casedn_str(system_charset_info, new_name_buff); my_casedn_str(system_charset_info, new_name_buff);
new_alias= new_name; // Create lower case table name new_alias= new_name; // Create lower case table name
} }
my_casedn_str(system_charset_info, new_name); my_casedn_str(system_charset_info, new_name);
} }
if (new_db == db && 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 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, ...@@ -2458,21 +2490,21 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
{ {
if (table->tmp_table) if (table->tmp_table)
{ {
if (find_temporary_table(thd,new_db,new_name_buff)) if (find_temporary_table(thd,new_db,new_name_buff))
{ {
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff); my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
else else
{ {
if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0), if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0),
F_OK)) F_OK))
{ {
/* Table will be closed in do_command() */ /* Table will be closed in do_command() */
my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias); my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
} }
} }
...@@ -2487,10 +2519,10 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2487,10 +2519,10 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
{ {
create_info->db_type= new_db_type; create_info->db_type= new_db_type;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER, ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER), ER(ER_WARN_USING_OTHER_HANDLER),
ha_get_storage_engine(new_db_type), ha_get_storage_engine(new_db_type),
new_name); new_name);
} }
if (create_info->row_type == ROW_TYPE_NOT_USED) if (create_info->row_type == ROW_TYPE_NOT_USED)
create_info->row_type=table->row_type; create_info->row_type=table->row_type;
...@@ -2515,7 +2547,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2515,7 +2547,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
*fn_ext(new_name)=0; *fn_ext(new_name)=0;
close_cached_table(thd, table); close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias)) if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias))
error= -1; error= -1;
} }
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
} }
...@@ -2524,28 +2556,28 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2524,28 +2556,28 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
{ {
switch (keys_onoff) { switch (keys_onoff) {
case LEAVE_AS_IS: case LEAVE_AS_IS:
break; break;
case ENABLE: case ENABLE:
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->activate_all_index(thd); error= table->file->activate_all_index(thd);
/* COND_refresh will be signaled in close_thread_tables() */ /* COND_refresh will be signaled in close_thread_tables() */
break; break;
case DISABLE: case DISABLE:
if (table->db_type == DB_TYPE_MYISAM) if (table->db_type == DB_TYPE_MYISAM)
{ {
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR); table->file->deactivate_non_unique_index(HA_POS_ERROR);
/* COND_refresh will be signaled in close_thread_tables() */ /* COND_refresh will be signaled in close_thread_tables() */
} }
else else
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA, ER_ILLEGAL_HA,
ER(ER_ILLEGAL_HA), table->table_name); ER(ER_ILLEGAL_HA), table->table_name);
break; break;
} }
} }
if (!error) if (!error)
...@@ -2554,12 +2586,12 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2554,12 +2586,12 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
thd->clear_error(); thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0); Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
send_ok(thd); send_ok(thd);
} }
table_list->table=0; // For query cache table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0); query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -2576,12 +2608,12 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2576,12 +2608,12 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
create_info->default_table_charset= table->table_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<Alter_drop> drop_it(drop_list); List_iterator<Alter_drop> drop_it(drop_list);
List_iterator<create_field> def_it(fields); List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_list); List_iterator<Alter_column> alter_it(alter_list);
List<create_field> create_list; // Add new fields here List<create_field> create_list; // Add new fields here
List<Key> key_list; // Add new keys here List<Key> key_list; // Add new keys here
create_field *def; create_field *def;
/* /*
...@@ -2597,16 +2629,16 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2597,16 +2629,16 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
while ((drop=drop_it++)) while ((drop=drop_it++))
{ {
if (drop->type == Alter_drop::COLUMN && 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 */ /* Reset auto_increment value if it was dropped */
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
!(used_fields & HA_CREATE_USED_AUTO)) !(used_fields & HA_CREATE_USED_AUTO))
{ {
create_info->auto_increment_value=0; create_info->auto_increment_value=0;
create_info->used_fields|=HA_CREATE_USED_AUTO; create_info->used_fields|=HA_CREATE_USED_AUTO;
} }
break; break;
} }
} }
if (drop) if (drop)
...@@ -2620,31 +2652,31 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2620,31 +2652,31 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
{ {
if (def->change && if (def->change &&
!my_strcasecmp(system_charset_info,field->field_name, def->change)) !my_strcasecmp(system_charset_info,field->field_name, def->change))
break; break;
} }
if (def) if (def)
{ // Field is changed { // Field is changed
def->field=field; def->field=field;
if (def->sql_type == FIELD_TYPE_TIMESTAMP) if (def->sql_type == FIELD_TYPE_TIMESTAMP)
use_timestamp=1; use_timestamp=1;
if (!def->after) if (!def->after)
{ {
create_list.push_back(def); create_list.push_back(def);
def_it.remove(); def_it.remove();
} }
} }
else else
{ // Use old field value { // Use old field value
create_list.push_back(def=new create_field(field,field)); create_list.push_back(def=new create_field(field,field));
if (def->sql_type == FIELD_TYPE_TIMESTAMP) 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; Alter_column *alter;
while ((alter=alter_it++)) while ((alter=alter_it++))
{ {
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
break; break;
} }
if (alter) if (alter)
{ {
...@@ -2653,14 +2685,14 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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); my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
def->def=alter->def; // Use new default def->def=alter->def; // Use new default
alter_it.remove(); alter_it.remove();
} }
} }
} }
def_it.rewind(); def_it.rewind();
List_iterator<create_field> find_it(create_list); List_iterator<create_field> find_it(create_list);
while ((def=def_it++)) // Add new columns while ((def=def_it++)) // Add new columns
{ {
if (def->change && ! def->field) if (def->change && ! def->field)
{ {
...@@ -2675,17 +2707,17 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2675,17 +2707,17 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
{ {
create_field *find; create_field *find;
find_it.rewind(); 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)) if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
break; break;
} }
if (!find) if (!find)
{ {
my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name); my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
find_it.after(def); // Put element after this find_it.after(def); // Put element after this
} }
} }
if (alter_list.elements) if (alter_list.elements)
...@@ -2717,8 +2749,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2717,8 +2749,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
while ((drop=drop_it++)) while ((drop=drop_it++))
{ {
if (drop->type == Alter_drop::KEY && if (drop->type == Alter_drop::KEY &&
!my_strcasecmp(system_charset_info,key_name, drop->name)) !my_strcasecmp(system_charset_info,key_name, drop->name))
break; break;
} }
if (drop) if (drop)
{ {
...@@ -2731,60 +2763,60 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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++) for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{ {
if (!key_part->field) if (!key_part->field)
continue; // Wrong field (from UNIREG) continue; // Wrong field (from UNIREG)
const char *key_part_name=key_part->field->field_name; const char *key_part_name=key_part->field->field_name;
create_field *cfield; create_field *cfield;
field_it.rewind(); field_it.rewind();
while ((cfield=field_it++)) while ((cfield=field_it++))
{ {
if (cfield->change) if (cfield->change)
{ {
if (!my_strcasecmp(system_charset_info, key_part_name, if (!my_strcasecmp(system_charset_info, key_part_name,
cfield->change)) cfield->change))
break; break;
} }
else if (!my_strcasecmp(system_charset_info, else if (!my_strcasecmp(system_charset_info,
key_part_name, cfield->field_name)) key_part_name, cfield->field_name))
break; break;
} }
if (!cfield) if (!cfield)
continue; // Field is removed continue; // Field is removed
uint key_part_length=key_part->length; uint key_part_length=key_part->length;
if (cfield->field) // Not new field if (cfield->field) // Not new field
{ // Check if sub key { // Check if sub key
if (cfield->field->type() != FIELD_TYPE_BLOB && if (cfield->field->type() != FIELD_TYPE_BLOB &&
(cfield->field->pack_length() == key_part_length || (cfield->field->pack_length() == key_part_length ||
cfield->length <= key_part_length / cfield->length <= key_part_length /
key_part->field->charset()->mbmaxlen)) key_part->field->charset()->mbmaxlen))
key_part_length=0; // Use whole field key_part_length=0; // Use whole field
} }
key_part_length /= key_part->field->charset()->mbmaxlen; key_part_length /= key_part->field->charset()->mbmaxlen;
key_parts.push_back(new key_part_spec(cfield->field_name, key_parts.push_back(new key_part_spec(cfield->field_name,
key_part_length)); key_part_length));
} }
if (key_parts.elements) if (key_parts.elements)
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL : key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
(key_info->flags & HA_NOSAME ? (key_info->flags & HA_NOSAME ?
(!my_strcasecmp(system_charset_info, (!my_strcasecmp(system_charset_info,
key_name, primary_key_name) ? key_name, primary_key_name) ?
Key::PRIMARY : Key::UNIQUE) : Key::PRIMARY : Key::UNIQUE) :
(key_info->flags & HA_FULLTEXT ? (key_info->flags & HA_FULLTEXT ?
Key::FULLTEXT : Key::MULTIPLE)), Key::FULLTEXT : Key::MULTIPLE)),
key_name, key_name,
key_info->algorithm, key_info->algorithm,
key_parts)); key_parts));
} }
{ {
Key *key; Key *key;
while ((key=key_it++)) // Add new keys while ((key=key_it++)) // Add new keys
{ {
if (key->type != Key::FOREIGN_KEY) if (key->type != Key::FOREIGN_KEY)
key_list.push_back(key); key_list.push_back(key);
if (key->name && 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); my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
} }
...@@ -2801,8 +2833,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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); db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
(void) sprintf(tmp_name,"%s-%lx_%lx", tmp_file_prefix, current_pid, if (snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
thd->thread_id); current_pid, thd->thread_id)>= (int)sizeof(tmp_name))
goto err;
create_info->db_type=new_db_type; create_info->db_type=new_db_type;
if (!create_info->comment) if (!create_info->comment)
create_info->comment=table->comment; create_info->comment=table->comment;
...@@ -2818,7 +2851,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2818,7 +2851,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->table_options & if (create_info->table_options &
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE)) (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
db_create_options&= ~(HA_OPTION_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; create_info->table_options|= db_create_options;
if (table->tmp_table) if (table->tmp_table)
...@@ -2849,31 +2882,31 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2849,31 +2882,31 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
Remove old table and symlinks. 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) if (create_info->index_file_name)
{ {
/* Fix index_file_name to have 'tmp_name' as basename */ /* Fix index_file_name to have 'tmp_name' as basename */
strmov(index_file, tmp_name); strmov(index_file, tmp_name);
create_info->index_file_name=fn_same(index_file, create_info->index_file_name=fn_same(index_file,
create_info->index_file_name, create_info->index_file_name,
1); 1);
} }
if (create_info->data_file_name) if (create_info->data_file_name)
{ {
/* Fix data_file_name to have 'tmp_name' as basename */ /* Fix data_file_name to have 'tmp_name' as basename */
strmov(data_file, tmp_name); strmov(data_file, tmp_name);
create_info->data_file_name=fn_same(data_file, create_info->data_file_name=fn_same(data_file,
create_info->data_file_name, create_info->data_file_name,
1); 1);
} }
} }
else else
create_info->data_file_name=create_info->index_file_name=0; create_info->data_file_name=create_info->index_file_name=0;
if ((error=mysql_create_table(thd, new_db, tmp_name, if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info, create_info,
create_list,key_list,1,1,0))) // no logging create_list,key_list,1,1,0))) // no logging
DBUG_RETURN(error); DBUG_RETURN(error);
if (table->tmp_table) if (table->tmp_table)
...@@ -2881,7 +2914,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2881,7 +2914,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
else else
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
(void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,tmp_name); if (snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
new_db, tmp_name)>= (int)sizeof(path))
goto err;
fn_format(path,path,"","",4); fn_format(path,path,"","",4);
new_table=open_temporary_table(thd, path, new_db, tmp_name,0); new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
} }
...@@ -2895,16 +2930,16 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2895,16 +2930,16 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
if (use_timestamp) if (use_timestamp)
new_table->time_stamp=0; new_table->time_stamp=0;
new_table->next_number_field=new_table->found_next_number_field; 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->cuted_fields=0L;
thd->proc_info="copy to tmp table"; 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; copied=deleted=0;
if (!new_table->is_view) if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list, error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates, handle_duplicates,
order_num, order, &copied, &deleted); order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->count_cuted_fields= CHECK_FIELD_IGNORE;
new_table->time_stamp=save_time_stamp; new_table->time_stamp=save_time_stamp;
...@@ -2914,8 +2949,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2914,8 +2949,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
if (error) if (error)
{ {
/* /*
The following function call will free the new_table pointer, The following function call will free the new_table pointer,
in close_temporary_table(), so we can safely directly jump to err in close_temporary_table(), so we can safely directly jump to err
*/ */
close_temporary_table(thd,new_db,tmp_name); close_temporary_table(thd,new_db,tmp_name);
goto err; goto err;
...@@ -2929,7 +2964,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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 */ /* Remove link to old table and rename the new one */
close_temporary_table(thd,table->table_cache_key,table_name); close_temporary_table(thd,table->table_cache_key,table_name);
if (rename_temporary_table(thd, new_table, new_db, new_alias)) if (rename_temporary_table(thd, new_table, new_db, new_alias))
{ // Fatal error { // Fatal error
close_temporary_table(thd,new_db,tmp_name); close_temporary_table(thd,new_db,tmp_name);
my_free((gptr) new_table,MYF(0)); my_free((gptr) new_table,MYF(0));
goto err; goto err;
...@@ -2944,7 +2979,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2944,7 +2979,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
goto end_temporary; 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)); my_free((gptr) new_table,MYF(0));
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
if (error) if (error)
...@@ -2961,8 +2996,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2961,8 +2996,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
*/ */
thd->proc_info="rename result table"; thd->proc_info="rename result table";
sprintf(old_name,"%s2-%lx-%lx", tmp_file_prefix, current_pid, if (snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
thd->thread_id); current_pid, thd->thread_id)>= (int)sizeof(old_name))
goto err;
if (new_name != table_name || new_db != db) if (new_name != table_name || new_db != db)
{ {
if (!access(new_name_buff,F_OK)) if (!access(new_name_buff,F_OK))
...@@ -2983,18 +3019,18 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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 Win32 and InnoDB can't drop a table that is in use, so we must
close the original table at before doing the rename 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)) if (close_cached_table(thd, table))
{ // Aborted { // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name)); VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; goto err;
} }
table=0; // Marker that table is closed table=0; // Marker that table is closed
} }
#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2)) #if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
else 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 #endif
...@@ -3005,8 +3041,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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)); 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, else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db,
new_alias)) new_alias))
{ // Try to get everything back { // Try to get everything back
error=1; error=1;
VOID(quick_rm_table(new_db_type,new_db,new_alias)); VOID(quick_rm_table(new_db_type,new_db,new_alias));
VOID(quick_rm_table(new_db_type,new_db,tmp_name)); 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, ...@@ -3023,7 +3059,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; 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 Not table locking or alter table with rename
...@@ -3044,14 +3080,14 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -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 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 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)); VOID(quick_rm_table(old_db_type,db,old_name));
if (close_data_tables(thd,db,table_name) || if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0)) reopen_tables(thd,1,0))
{ // This shouldn't happen { // This shouldn't happen
if (table) 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)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; goto err;
} }
...@@ -3085,7 +3121,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3085,7 +3121,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
shutdown. shutdown.
*/ */
char path[FN_REFLEN]; char path[FN_REFLEN];
(void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,table_name); if (snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
new_db, table_name)>= (int)sizeof(path))
goto err;
fn_format(path,path,"","",4); fn_format(path,path,"","",4);
table=open_temporary_table(thd, path, new_db, tmp_name,0); table=open_temporary_table(thd, path, new_db, tmp_name,0);
if (table) if (table)
...@@ -3095,16 +3133,18 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3095,16 +3133,18 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
} }
else else
sql_print_error("Warning: Could not open BDB table %s.%s after rename\n", 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(); (void) berkeley_flush_logs();
} }
#endif #endif
table_list->table=0; // For query cache table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0); query_cache_invalidate3(thd, table_list, 0);
end_temporary: end_temporary:
sprintf(tmp_name, ER(ER_INSERT_INFO), (ulong) (copied + deleted), if (snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) deleted, (ulong) thd->cuted_fields); (ulong) (copied + deleted), (ulong) deleted,
(ulong) thd->cuted_fields)>= (int)sizeof(tmp_name))
goto err;
send_ok(thd,copied+deleted,0L,tmp_name); send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0; thd->some_tables_deleted=0;
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -3117,9 +3157,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3117,9 +3157,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
static int static int
copy_data_between_tables(TABLE *from,TABLE *to, copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
uint order_num, ORDER *order, uint order_num, ORDER *order,
ha_rows *copied, ha_rows *copied,
ha_rows *deleted) ha_rows *deleted)
{ {
int error; int error;
...@@ -3137,7 +3177,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -3137,7 +3177,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
DBUG_ENTER("copy_data_between_tables"); DBUG_ENTER("copy_data_between_tables");
if (!(copy= new Copy_field[to->fields])) 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->external_lock(thd,F_WRLCK);
to->file->extra(HA_EXTRA_WRITE_CACHE); to->file->extra(HA_EXTRA_WRITE_CACHE);
...@@ -3163,12 +3203,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -3163,12 +3203,12 @@ copy_data_between_tables(TABLE *from,TABLE *to,
bzero((char*) &tables,sizeof(tables)); bzero((char*) &tables,sizeof(tables));
tables.table = from; tables.table = from;
tables.alias = tables.real_name= from->real_name; tables.alias = tables.real_name= from->real_name;
tables.db = from->table_cache_key; tables.db = from->table_cache_key;
error=1; error=1;
if (thd->lex->select_lex.setup_ref_array(thd, order_num) || if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array, setup_order(thd, thd->lex->select_lex.ref_pointer_array,
&tables, fields, all_fields, order) || &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length, (from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,
...@@ -3209,12 +3249,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -3209,12 +3249,12 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if ((error=to->file->write_row((byte*) to->record[0]))) if ((error=to->file->write_row((byte*) to->record[0])))
{ {
if ((handle_duplicates != DUP_IGNORE && if ((handle_duplicates != DUP_IGNORE &&
handle_duplicates != DUP_REPLACE) || handle_duplicates != DUP_REPLACE) ||
(error != HA_ERR_FOUND_DUPP_KEY && (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)) error != HA_ERR_FOUND_DUPP_UNIQUE))
{ {
to->file->print_error(error,MYF(0)); to->file->print_error(error,MYF(0));
break; break;
} }
delete_count++; delete_count++;
} }
...@@ -3223,7 +3263,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -3223,7 +3263,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
} }
end_read_record(&info); end_read_record(&info);
free_io_cache(from); free_io_cache(from);
delete [] copy; // This is never 0 delete [] copy; // This is never 0
uint tmp_error; uint tmp_error;
if ((tmp_error=to->file->extra(HA_EXTRA_NO_CACHE))) 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) ...@@ -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); strxmov(table_name, table->db ,".", table->real_name, NullS);
t= table->table= open_ltable(thd, table, TL_READ_NO_INSERT); 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->prepare_for_resend();
protocol->store(table_name, system_charset_info); 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) ...@@ -3295,7 +3335,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
!(check_opt->flags & T_EXTEND)) !(check_opt->flags & T_EXTEND))
protocol->store((ulonglong)t->file->checksum()); protocol->store((ulonglong)t->file->checksum());
else if (!(t->file->table_flags() & HA_HAS_CHECKSUM) && else if (!(t->file->table_flags() & HA_HAS_CHECKSUM) &&
(check_opt->flags & T_QUICK)) (check_opt->flags & T_QUICK))
protocol->store_null(); protocol->store_null();
else else
{ {
...@@ -3316,7 +3356,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) ...@@ -3316,7 +3356,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
ha_checksum row_crc= 0; ha_checksum row_crc= 0;
if (t->record[0] != (byte*) t->field[0]->ptr) if (t->record[0] != (byte*) t->field[0]->ptr)
row_crc= my_checksum(row_crc, t->record[0], 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++ ) 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) ...@@ -3329,7 +3369,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
} }
else else
row_crc= my_checksum(row_crc, (byte*) f->ptr, row_crc= my_checksum(row_crc, (byte*) f->ptr,
f->pack_length()); f->pack_length());
} }
crc+= row_crc; crc+= row_crc;
...@@ -3339,7 +3379,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) ...@@ -3339,7 +3379,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
} }
thd->clear_error(); thd->clear_error();
close_thread_tables(thd); close_thread_tables(thd);
table->table=0; // For query cache table->table=0; // For query cache
} }
if (protocol->write()) if (protocol->write())
goto err; goto err;
...@@ -3349,7 +3389,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) ...@@ -3349,7 +3389,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
close_thread_tables(thd); // Shouldn't be needed close_thread_tables(thd); // Shouldn't be needed
if (table) if (table)
table->table=0; table->table=0;
DBUG_RETURN(-1); DBUG_RETURN(-1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment