summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc389
1 files changed, 283 insertions, 106 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3b593e57d82..4b0ca67a549 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -179,11 +179,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool drop_temporary, bool dont_log_query)
{
TABLE_LIST *table;
- char path[FN_REFLEN];
+ char path[FN_REFLEN], *alias;
String wrong_tables;
- db_type table_type;
int error;
- bool some_tables_deleted=0, tmp_table_deleted=0;
+ bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
DBUG_ENTER("mysql_rm_table_part2");
if (lock_table_names(thd, tables))
@@ -212,13 +211,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
drop_locked_tables(thd,db,table->real_name);
if (thd->killed)
DBUG_RETURN(-1);
-
+ alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
/* remove form file and isam files */
- strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
- NullS);
+ strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS);
(void) unpack_filename(path,path);
-
- table_type=get_table_type(path);
}
if (drop_temporary || access(path,F_OK))
{
@@ -232,10 +228,16 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
else
{
char *end;
- *(end=fn_ext(path))=0; // Remove extension
+ db_type table_type= get_table_type(path);
+ *(end=fn_ext(path))=0; // Remove extension for delete
error=ha_delete_table(table_type, path);
if (error == ENOENT && if_exists)
error = 0;
+ if (error == HA_ERR_ROW_IS_REFERENCED)
+ {
+ /* the table is referenced by a foreign key constraint */
+ foreign_key_error=1;
+ }
if (!error || error == ENOENT)
{
/* Delete the table definition file */
@@ -268,7 +270,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
error= 0;
if (wrong_tables.length())
{
- my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
+ if (!foreign_key_error)
+ my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
+ else
+ my_error(ER_ROW_IS_REFERENCED,MYF(0));
error= 1;
}
DBUG_RETURN(error);
@@ -333,6 +338,47 @@ static int sort_keys(KEY *a, KEY *b)
0);
}
+/*
+ Check TYPELIB (set or enum) for duplicates
+
+ SYNOPSIS
+ check_duplicates_in_interval()
+ set_or_name "SET" or "ENUM" string for warning message
+ name name of the checked column
+ typelib list of values for the column
+
+ DESCRIPTION
+ This function prints an warning for each value in list
+ which has some duplicates on its right
+
+ RETURN VALUES
+ void
+*/
+
+void check_duplicates_in_interval(const char *set_or_name,
+ const char *name, TYPELIB *typelib)
+{
+ unsigned int old_count= typelib->count;
+ const char **old_type_names= typelib->type_names;
+
+ old_count= typelib->count;
+ old_type_names= typelib->type_names;
+ const char **cur_value= typelib->type_names;
+ for ( ; typelib->count > 1; cur_value++)
+ {
+ typelib->type_names++;
+ typelib->count--;
+ if (find_type((char*)*cur_value,typelib,1))
+ {
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_DUPLICATED_VALUE_IN_TYPE,
+ ER(ER_DUPLICATED_VALUE_IN_TYPE),
+ name,*cur_value,set_or_name);
+ }
+ }
+ typelib->count= old_count;
+ typelib->type_names= old_type_names;
+}
/*
Create a table
@@ -369,7 +415,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
uint select_field_count)
{
char path[FN_REFLEN];
- const char *key_name;
+ const char *key_name, *alias;
create_field *sql_field,*dup_field;
int error= -1;
uint db_options,field,null_fields,blob_columns;
@@ -377,15 +423,13 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
KEY *key_info,*key_info_buffer;
KEY_PART_INFO *key_part_info;
int auto_increment=0;
+ int timestamps= 0, timestamps_with_niladic= 0;
handler *file;
int field_no,dup_no;
enum db_type new_db_type;
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 */
if (!fields.elements)
{
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
@@ -407,6 +451,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
+ alias= table_case_name(create_info, table_name);
file=get_new_handler((TABLE*) 0, create_info->db_type);
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
@@ -422,10 +467,24 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
sql_field->charset= create_info->default_table_charset;
/*
table_charset is set in ALTER TABLE if we want change character set
- for all varchar/char columns
+ for all varchar/char columns.
+ But the table charset must not affect the BLOB fields, so don't
+ allow to change my_charset_bin to somethig else.
*/
- if (create_info->table_charset)
+ if (create_info->table_charset && sql_field->charset != &my_charset_bin)
sql_field->charset= create_info->table_charset;
+
+ CHARSET_INFO *savecs= sql_field->charset;
+ if ((sql_field->flags & BINCMP_FLAG) &&
+ !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
+ MY_CS_BINSORT,MYF(0))))
+ {
+ char tmp[64];
+ strmake(strmake(tmp, savecs->csname, sizeof(tmp)-4), "_bin", 4);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
+ DBUG_RETURN(-1);
+ }
+
sql_field->create_length_to_internal_length();
/* Don't pack keys in old tables if the user has requested this */
@@ -539,6 +598,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD;
+ check_duplicates_in_interval("ENUM",sql_field->field_name,
+ sql_field->interval);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -546,6 +607,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD;
+ check_duplicates_in_interval("SET",sql_field->field_name,
+ sql_field->interval);
break;
case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
@@ -555,8 +618,22 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
break;
case FIELD_TYPE_TIMESTAMP:
- sql_field->unireg_check=Field::TIMESTAMP_FIELD;
- /* fall through */
+ /* We should replace old TIMESTAMP fields with their newer analogs */
+ if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
+ {
+ if (!timestamps)
+ {
+ sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
+ timestamps_with_niladic++;
+ }
+ else
+ sql_field->unireg_check= Field::NONE;
+ }
+ else if (sql_field->unireg_check != Field::NONE)
+ timestamps_with_niladic++;
+
+ timestamps++;
+ /* fall-through */
default:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
(sql_field->flags & UNSIGNED_FLAG ? 0 :
@@ -574,6 +651,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
auto_increment++;
pos+=sql_field->pack_length;
}
+ if (timestamps_with_niladic > 1)
+ {
+ my_error(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,MYF(0));
+ DBUG_RETURN(-1);
+ }
if (auto_increment > 1)
{
my_error(ER_WRONG_AUTO_KEY,MYF(0));
@@ -632,6 +714,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
key_parts+=key->columns.elements;
+ if (key->name && !tmp_table &&
+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ DBUG_RETURN(-1);
+ }
}
tmp=min(file->max_keys(), MAX_KEY);
if (key_count > tmp)
@@ -846,26 +934,35 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if ((length=column->length) > file->max_key_length() ||
length > file->max_key_part_length())
- {
- my_error(ER_WRONG_SUB_KEY,MYF(0));
- DBUG_RETURN(-1);
- }
- }
- /* TODO HF What's this for??? */
- else if (f_is_geom(sql_field->pack_flag))
- {
- }
- else if (column->length > length ||
- ((f_is_packed(sql_field->pack_flag) ||
- ((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
- (key_info->flags & HA_NOSAME))) &&
- column->length != length))
- {
- my_error(ER_WRONG_SUB_KEY,MYF(0));
- DBUG_RETURN(-1);
+ {
+ length=min(file->max_key_length(), file->max_key_part_length());
+ if (key->type == Key::MULTIPLE)
+ {
+ /* not a critical problem */
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TOO_LONG_KEY, warn_buff);
+ }
+ else
+ {
+ my_error(ER_TOO_LONG_KEY,MYF(0),length);
+ DBUG_RETURN(-1);
+ }
+ }
}
- if (!(file->table_flags() & HA_NO_PREFIX_CHAR_KEYS))
- length=column->length;
+ else if (!f_is_geom(sql_field->pack_flag) &&
+ (column->length > length ||
+ ((f_is_packed(sql_field->pack_flag) ||
+ ((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
+ (key_info->flags & HA_NOSAME))) &&
+ column->length != length)))
+ {
+ my_error(ER_WRONG_SUB_KEY,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ else if (!(file->table_flags() & HA_NO_PREFIX_CHAR_KEYS))
+ length=column->length;
}
else if (length == 0)
{
@@ -875,8 +972,20 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
if (length > file->max_key_part_length())
{
- my_error(ER_WRONG_SUB_KEY,MYF(0));
- DBUG_RETURN(-1);
+ length=file->max_key_part_length();
+ if (key->type == Key::MULTIPLE)
+ {
+ /* not a critical problem */
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TOO_LONG_KEY, warn_buff);
+ }
+ else
+ {
+ my_error(ER_TOO_LONG_KEY,MYF(0),length);
+ DBUG_RETURN(-1);
+ }
}
key_part_info->length=(uint16) length;
/* Use packed keys for long strings on the first column */
@@ -956,7 +1065,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
}
else
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table_name,reg_ext);
+ (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,alias,reg_ext);
unpack_filename(path,path);
/* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -967,7 +1076,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
create_info->table_existed= 1; // Mark that table existed
DBUG_RETURN(0);
}
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
DBUG_RETURN(-1);
}
if (wait_if_global_read_lock(thd, 0))
@@ -1046,7 +1155,8 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
{
char buff[MAX_FIELD_NAME],*buff_end;
- 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))
return (char*) field_name; // Use fieldname
buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4);
for (uint i=2 ; ; i++)
@@ -1107,7 +1217,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(0);
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
{
- quick_rm_table(create_info->db_type,db,name);
+ quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
DBUG_RETURN(0);
}
table->reginfo.lock_type=TL_WRITE;
@@ -1116,7 +1226,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
VOID(pthread_mutex_lock(&LOCK_open));
hash_delete(&open_cache,(byte*) table);
VOID(pthread_mutex_unlock(&LOCK_open));
- quick_rm_table(create_info->db_type,db,name);
+ quick_rm_table(create_info->db_type,db,table_case_name(create_info, name));
DBUG_RETURN(0);
}
table->file->extra(HA_EXTRA_WRITE_CACHE);
@@ -1131,18 +1241,32 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
bool
mysql_rename_table(enum db_type base,
const char *old_db,
- const char * old_name,
+ const char *old_name,
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];
handler *file=get_new_handler((TABLE*) 0, base);
int error=0;
DBUG_ENTER("mysql_rename_table");
+
+ if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
+ {
+ /* Table handler expects to get all file names as lower case */
+ strmov(tmp_from, old_name);
+ my_casedn_str(system_charset_info, tmp_from);
+ old_name= tmp_from;
+
+ strmov(tmp_to, new_name);
+ my_casedn_str(system_charset_info, tmp_to);
+ new_name= tmp_to;
+ }
(void) sprintf(from,"%s/%s/%s",mysql_data_home,old_db,old_name);
(void) sprintf(to,"%s/%s/%s",mysql_data_home,new_db,new_name);
fn_format(from,from,"","",4);
fn_format(to,to, "","",4);
+
if (!(error=file->rename_table((const char*) from,(const char *) to)))
{
if (rename_file_ext(from,to,reg_ext))
@@ -1158,6 +1282,7 @@ mysql_rename_table(enum db_type base,
DBUG_RETURN(error != 0);
}
+
/*
Force all other threads to stop using the table
@@ -1202,7 +1327,7 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
Close a cached table
SYNOPSIS
- clsoe_cached_table()
+ close_cached_table()
thd Thread handler
table Table to remove from cache
@@ -1552,6 +1677,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store("Operation failed",16, system_charset_info);
break;
+ case HA_ADMIN_REJECT:
+ protocol->store("status", 6, system_charset_info);
+ protocol->store("Operation need committed state",30, system_charset_info);
+ open_for_modify= FALSE;
+ break;
+
case HA_ADMIN_ALREADY_DONE:
protocol->store("status", 6, system_charset_info);
protocol->store("Table is already up to date", 27, system_charset_info);
@@ -1762,7 +1893,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
char *table_name= table->real_name;
char *src_db= thd->db;
char *src_table= table_ident->table.str;
- int err;
+ int err, res= -1;
+ TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
/*
@@ -1776,6 +1908,13 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
DBUG_RETURN(-1);
}
+
+ src_tables_list.db= table_ident->db.str ? table_ident->db.str : thd->db;
+ src_tables_list.real_name= table_ident->table.str;
+ src_tables_list.next= 0;
+
+ if (lock_and_wait_for_table_name(thd, &src_tables_list))
+ goto err;
if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
@@ -1786,7 +1925,7 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (access(src_path, F_OK))
{
my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
- DBUG_RETURN(-1);
+ goto err;
}
}
@@ -1814,9 +1953,9 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
/*
Create a new table by copying from source table
- */
- if (my_copy(src_path, dst_path, MYF(MY_WME)))
- DBUG_RETURN(-1);
+ */
+ if (my_copy(src_path, dst_path, MYF(MY_WME|MY_DONT_OVERWRITE_FILE)))
+ goto err;
/*
As mysql_truncate don't work on a new table at this stage of
@@ -1832,16 +1971,28 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
(void) rm_temporary_table(create_info->db_type,
dst_path); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
}
else if (err)
{
(void) quick_rm_table(create_info->db_type, db,
table_name); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
- DBUG_RETURN(0);
+
+ // Must be written before unlock
+ mysql_update_log.write(thd,thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE));
+ mysql_bin_log.write(&qinfo);
+ }
+ res= 0;
+ goto err;
table_exists:
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
@@ -1850,10 +2001,16 @@ table_exists:
sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,warn_buff);
- DBUG_RETURN(0);
+ res= 0;
}
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
- DBUG_RETURN(-1);
+ else
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+
+err:
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, &src_tables_list);
+ pthread_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(res);
}
@@ -1943,9 +2100,10 @@ int mysql_discard_or_import_tablespace(THD *thd,
err:
close_thread_tables(thd);
thd->tablespace_op=FALSE;
- if (error == 0) {
+ if (error == 0)
+ {
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(0);
}
DBUG_RETURN(error);
}
@@ -1964,21 +2122,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
TABLE *table,*new_table;
int error;
- char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN],
- *table_name,*db;
+ char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
+ char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
char index_file[FN_REFLEN], data_file[FN_REFLEN];
- bool use_timestamp=0;
ha_rows copied,deleted;
ulonglong next_insert_id;
- uint save_time_stamp,db_create_options, used_fields;
+ uint db_create_options, used_fields;
enum db_type old_db_type,new_db_type;
DBUG_ENTER("mysql_alter_table");
thd->proc_info="init";
table_name=table_list->real_name;
+ alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
+
db=table_list->db;
- if (!new_db || !strcmp(new_db,db))
- new_db=db;
+ if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
+ {
+ new_db= db;
+ }
used_fields=create_info->used_fields;
mysql_ha_closeall(thd, table_list);
@@ -1986,7 +2147,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
- tablespace_op));
+ tablespace_op));
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
@@ -1994,18 +2155,32 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (new_name)
{
strmov(new_name_buff,new_name);
- fn_same(new_name_buff,table_name,3);
+ strmov(new_alias= new_alias_buff, new_name);
if (lower_case_table_names)
- my_casedn_str(system_charset_info,new_name);
- if (!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
- new_name=table_name; // No. Make later check easier
+ {
+ if (lower_case_table_names != 2)
+ {
+ my_casedn_str(system_charset_info, new_name_buff);
+ new_alias= new_name; // Create lower case table name
+ }
+ my_casedn_str(system_charset_info, new_name);
+ }
+ if (new_db == db &&
+ !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
+ {
+ /*
+ Source and destination table names are equal: make later check
+ easier.
+ */
+ new_alias= new_name= table_name;
+ }
else
{
if (table->tmp_table)
{
if (find_temporary_table(thd,new_db,new_name_buff))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
DBUG_RETURN(-1);
}
}
@@ -2015,14 +2190,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
F_OK))
{
/* Table will be closed in do_command() */
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
DBUG_RETURN(-1);
}
}
}
}
else
- new_name=table_name;
+ new_alias= new_name= table_name;
old_db_type=table->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
@@ -2059,7 +2234,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
*fn_ext(new_name)=0;
close_cached_table(thd, table);
- if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
+ if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias))
error= -1;
}
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -2084,14 +2259,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR);
+ /* COND_refresh will be signaled in close_thread_tables() */
}
else
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA,
ER(ER_ILLEGAL_HA), table->table_name);
- break;
-
- /* COND_refresh will be signaled in close_thread_tables() */
break;
}
}
@@ -2122,7 +2295,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
create_info->default_table_charset= table->table_charset;
- restore_record(table,default_values); // Empty record for DEFAULT
+ restore_record(table,default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(drop_list);
List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_list);
@@ -2171,8 +2344,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (def)
{ // Field is changed
def->field=field;
- if (def->sql_type == FIELD_TYPE_TIMESTAMP)
- use_timestamp=1;
if (!def->after)
{
create_list.push_back(def);
@@ -2182,9 +2353,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{ // Use old field value
create_list.push_back(def=new create_field(field,field));
- if (def->sql_type == FIELD_TYPE_TIMESTAMP)
- use_timestamp=1;
-
alter_it.rewind(); // Change default if ALTER
Alter_column *alter;
while ((alter=alter_it++))
@@ -2326,6 +2494,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (key->type != Key::FOREIGN_KEY)
key_list.push_back(key);
+ if (key->name &&
+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ DBUG_RETURN(-1);
+ }
}
}
@@ -2431,9 +2605,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
- save_time_stamp=new_table->time_stamp;
- if (use_timestamp)
- new_table->time_stamp=0;
+
+ /*
+ We don't want update TIMESTAMP fields during ALTER TABLE
+ and copy_data_between_tables uses only write_row() for new_table so
+ don't need to set up timestamp_on_update_now member.
+ */
+ new_table->timestamp_default_now= 0;
new_table->next_number_field=new_table->found_next_number_field;
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L;
@@ -2446,7 +2624,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
- new_table->time_stamp=save_time_stamp;
if (table->tmp_table)
{
@@ -2468,7 +2645,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
/* Remove link to old table and rename the new one */
close_temporary_table(thd,table->table_cache_key,table_name);
- if (rename_temporary_table(thd, new_table, new_db, new_name))
+ if (rename_temporary_table(thd, new_table, new_db, new_alias))
{ // Fatal error
close_temporary_table(thd,new_db,tmp_name);
my_free((gptr) new_table,MYF(0));
@@ -2492,6 +2669,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
+
/*
Data is copied. Now we rename the old table to a temp name,
rename the new one to the old name, remove all entries from the old table
@@ -2543,12 +2721,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
}
else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db,
- new_name))
+ new_alias))
{ // Try to get everything back
error=1;
- VOID(quick_rm_table(new_db_type,new_db,new_name));
+ VOID(quick_rm_table(new_db_type,new_db,new_alias));
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- VOID(mysql_rename_table(old_db_type,db,old_name,db,table_name));
+ VOID(mysql_rename_table(old_db_type,db,old_name,db,alias));
}
if (error)
{
@@ -2714,13 +2892,14 @@ copy_data_between_tables(TABLE *from,TABLE *to,
goto err;
};
- /* Turn off recovery logging since rollback of an
- alter table is to delete the new table so there
- is no need to log the changes to it. */
- error = ha_recovery_logging(thd,FALSE);
+ /*
+ Turn off recovery logging since rollback of an alter table is to
+ delete the new table so there is no need to log the changes to it.
+ */
+ error= ha_recovery_logging(thd,FALSE);
if (error)
{
- error = 1;
+ error= 1;
goto err;
}
@@ -2796,7 +2975,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
List<Item> field_list;
Item *item;
Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysql_admin_table");
+ DBUG_ENTER("mysql_checksum_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
item->maybe_null= 1;
@@ -2839,12 +3018,10 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
/* calculating table's checksum */
ha_checksum crc= 0;
- if (t->db_type == DB_TYPE_INNODB) {
- /* InnoDB must be told explicitly to retrieve all columns, because
- this function does not set field->query_id in the columns to the
- current query id */
- t->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- }
+ /* InnoDB must be told explicitly to retrieve all columns, because
+ this function does not set field->query_id in the columns to the
+ current query id */
+ t->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (t->file->rnd_init(1))
protocol->store_null();