Commit 798ce983 authored by Tatiana A. Nurnberg's avatar Tatiana A. Nurnberg

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().
parents fce4fa36 74deaae9
...@@ -1268,4 +1268,12 @@ a b ...@@ -1268,4 +1268,12 @@ a b
4 b 4 b
5 a 5 a
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL,
f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2);
this should affect no rows as there is no real change
ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t1;
End of 5.1 tests End of 5.1 tests
...@@ -1000,4 +1000,19 @@ ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL; ...@@ -1000,4 +1000,19 @@ ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#43508: Renaming timestamp or date column triggers table copy
#
CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL,
f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2);
--echo this should affect no rows as there is no real change
--enable_info
ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL;
--disable_info
DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
/* 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 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 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) ...@@ -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) 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 0;
return ((new_field->sql_type == real_type()) && return ((new_field->sql_type == real_type()) &&
...@@ -8249,7 +8238,7 @@ uint Field_blob::max_packed_col_length(uint max_length) ...@@ -8249,7 +8238,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
uint Field_blob::is_equal(Create_field *new_field) 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 0;
return ((new_field->sql_type == get_blob_type_from_length(max_data_length())) 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, ...@@ -9535,7 +9524,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
} }
if (length == 0) if (length == 0)
fld_length= 0; /* purecov: inspected */ fld_length= NULL; /* purecov: inspected */
} }
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1; 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, ...@@ -9687,8 +9676,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_TIMESTAMP:
if (fld_length == NULL) if (fld_length == NULL)
{ {
/* Compressed date YYYYMMDDHHMMSS */ length= MAX_DATETIME_WIDTH;
length= MAX_DATETIME_COMPRESSED_WIDTH;
} }
else if (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, ...@@ -9753,7 +9741,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
sql_type= MYSQL_TYPE_NEWDATE; sql_type= MYSQL_TYPE_NEWDATE;
/* fall trough */ /* fall trough */
case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_NEWDATE:
length= 10; length= MAX_DATE_WIDTH;
break; break;
case MYSQL_TYPE_TIME: case MYSQL_TYPE_TIME:
length= 10; length= 10;
...@@ -9834,6 +9822,17 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, ...@@ -9834,6 +9822,17 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
DBUG_RETURN(TRUE); 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 */ DBUG_RETURN(FALSE); /* success */
} }
......
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -603,6 +603,12 @@ class Field ...@@ -603,6 +603,12 @@ class Field
handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first); handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first);
return from + sizeof(int64); return from + sizeof(int64);
} }
bool field_flags_are_binary()
{
return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
}
}; };
...@@ -658,7 +664,6 @@ class Field_str :public Field { ...@@ -658,7 +664,6 @@ class Field_str :public Field {
friend class Create_field; friend class Create_field;
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
virtual bool str_needs_quotes() { return TRUE; } virtual bool str_needs_quotes() { return TRUE; }
bool compare_str_field_flags(Create_field *new_field, uint32 flags);
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
}; };
...@@ -1268,12 +1273,12 @@ class Field_date :public Field_str { ...@@ -1268,12 +1273,12 @@ class Field_date :public Field_str {
Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
CHARSET_INFO *cs) CHARSET_INFO *cs)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, :Field_str(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, cs) unireg_check_arg, field_name_arg, cs)
{} {}
Field_date(bool maybe_null_arg, const char *field_name_arg, Field_date(bool maybe_null_arg, const char *field_name_arg,
CHARSET_INFO *cs) CHARSET_INFO *cs)
:Field_str((uchar*) 0,10, maybe_null_arg ? (uchar*) "": 0,0, :Field_str((uchar*) 0, MAX_DATE_WIDTH, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, cs) {} NONE, field_name_arg, cs) {}
enum_field_types type() const { return MYSQL_TYPE_DATE;} enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
...@@ -1383,12 +1388,12 @@ class Field_datetime :public Field_str { ...@@ -1383,12 +1388,12 @@ class Field_datetime :public Field_str {
Field_datetime(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_datetime(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
CHARSET_INFO *cs) CHARSET_INFO *cs)
:Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, cs) unireg_check_arg, field_name_arg, cs)
{} {}
Field_datetime(bool maybe_null_arg, const char *field_name_arg, Field_datetime(bool maybe_null_arg, const char *field_name_arg,
CHARSET_INFO *cs) CHARSET_INFO *cs)
:Field_str((uchar*) 0,19, maybe_null_arg ? (uchar*) "": 0,0, :Field_str((uchar*) 0, MAX_DATETIME_WIDTH, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, cs) {} NONE, field_name_arg, cs) {}
enum_field_types type() const { return MYSQL_TYPE_DATETIME;} enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
#ifdef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG
...@@ -2061,6 +2066,11 @@ class Create_field :public Sql_alloc ...@@ -2061,6 +2066,11 @@ class Create_field :public Sql_alloc
Item *on_update_value, LEX_STRING *comment, char *change, Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs, List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type); uint uint_geom_type);
bool field_flags_are_binary()
{
return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
}
}; };
......
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