Bug#43508: Renaming timestamp or date column triggers table copy

We set up DATE and TIMESTAMP differently in field-creation than we
did in field-MD creation (for CREATE). Admirably, ALTER TABLE
detected this and didn't damage any data, but it did initiate a
full copy/conversion, which we don't really need to do.

Now we describe Field and Create_field the same for those types.
As a result, ALTER TABLE that only changes meta-data (like a
field's name) no longer forces a data-copy when there needn't
be one.


mysql-test/r/alter_table.result:
  0 rows should be affected when a meta-data change is enough ALTER TABLE.
mysql-test/t/alter_table.test:
  add test-case: show that we don't do a full data-copy on ALTER TABLE
  when we don't need to.
sql/field.cc:
  Remove Field_str::compare_str_field_flags() (now in Field/Create_field as
  field_flags_are_binary().
  
  Correct some field-lengths!
sql/field.h:
  Clean-up: use defined constants rather than numeric literals for certain
  field-lengths.
  
  Add enquiry-functions binaryp() to classes Field and Create_field.
  This replaces field.cc's Field_str::compare_str_field_flags().
This commit is contained in:
Tatiana A. Nurnberg 2009-10-09 14:41:04 +02:00
commit 798ce98340
4 changed files with 56 additions and 24 deletions

View file

@ -1,4 +1,4 @@
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -6470,20 +6470,9 @@ uint Field::is_equal(Create_field *new_field)
}
/* If one of the fields is binary and the other one isn't return 1 else 0 */
bool Field_str::compare_str_field_flags(Create_field *new_field, uint32 flag_arg)
{
return (((new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
!(flag_arg & (BINCMP_FLAG | BINARY_FLAG))) ||
(!(new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
(flag_arg & (BINCMP_FLAG | BINARY_FLAG))));
}
uint Field_str::is_equal(Create_field *new_field)
{
if (compare_str_field_flags(new_field, flags))
if (field_flags_are_binary() != new_field->field_flags_are_binary())
return 0;
return ((new_field->sql_type == real_type()) &&
@ -8249,7 +8238,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
uint Field_blob::is_equal(Create_field *new_field)
{
if (compare_str_field_flags(new_field, flags))
if (field_flags_are_binary() != new_field->field_flags_are_binary())
return 0;
return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
@ -9535,7 +9524,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
if (length == 0)
fld_length= 0; /* purecov: inspected */
fld_length= NULL; /* purecov: inspected */
}
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
@ -9687,8 +9676,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_TIMESTAMP:
if (fld_length == NULL)
{
/* Compressed date YYYYMMDDHHMMSS */
length= MAX_DATETIME_COMPRESSED_WIDTH;
length= MAX_DATETIME_WIDTH;
}
else if (length != MAX_DATETIME_WIDTH)
{
@ -9753,7 +9741,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
sql_type= MYSQL_TYPE_NEWDATE;
/* fall trough */
case MYSQL_TYPE_NEWDATE:
length= 10;
length= MAX_DATE_WIDTH;
break;
case MYSQL_TYPE_TIME:
length= 10;
@ -9834,6 +9822,17 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
DBUG_RETURN(TRUE);
}
switch (fld_type) {
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
charset= &my_charset_bin;
flags|= BINCMP_FLAG;
default: break;
}
DBUG_RETURN(FALSE); /* success */
}