Commit adf630dc authored by Ramil Kalimullin's avatar Ramil Kalimullin

Fix for bug#23113: Different behavior on altering ENUM fields between 5.0 and 5.1

Problem: mysqld doesn't detect that enum data must be reinserted performing
'ALTER TABLE' in some cases.

Fix: reinsert data altering an enum field if enum values are changed.
parent a4890f89
...@@ -1222,4 +1222,16 @@ ALTER TABLE t1 CHANGE d c varchar(10); ...@@ -1222,4 +1222,16 @@ ALTER TABLE t1 CHANGE d c varchar(10);
affected rows: 0 affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0 info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY,
b ENUM('a', 'b', 'c') NOT NULL);
INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a');
ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
SELECT * FROM t1;
a b
1 a
2 c
3 b
4 b
5 a
DROP TABLE t1;
End of 5.1 tests End of 5.1 tests
...@@ -947,4 +947,16 @@ ALTER TABLE t1 CHANGE d c varchar(10); ...@@ -947,4 +947,16 @@ ALTER TABLE t1 CHANGE d c varchar(10);
--disable_info --disable_info
DROP TABLE t1; DROP TABLE t1;
#
# Bug #23113: Different behavior on altering ENUM fields between 5.0 and 5.1
#
CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY,
b ENUM('a', 'b', 'c') NOT NULL);
INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a');
ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
SELECT * FROM t1;
DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -8783,28 +8783,43 @@ bool Field::eq_def(Field *field) ...@@ -8783,28 +8783,43 @@ bool Field::eq_def(Field *field)
return 1; return 1;
} }
/** /**
@return @return
returns 1 if the fields are equally defined returns 1 if the fields are equally defined
*/ */
bool Field_enum::eq_def(Field *field) bool Field_enum::eq_def(Field *field)
{ {
if (!Field::eq_def(field)) if (!Field::eq_def(field))
return 0; return 0;
TYPELIB *from_lib=((Field_enum*) field)->typelib; return compare_enum_values(((Field_enum*) field)->typelib);
}
if (typelib->count < from_lib->count)
return 0; bool Field_enum::compare_enum_values(TYPELIB *values)
for (uint i=0 ; i < from_lib->count ; i++) {
if (typelib->count != values->count)
return FALSE;
for (uint i= 0; i < typelib->count; i++)
if (my_strnncoll(field_charset, if (my_strnncoll(field_charset,
(const uchar*)typelib->type_names[i], (const uchar*) typelib->type_names[i],
strlen(typelib->type_names[i]), typelib->type_lengths[i],
(const uchar*)from_lib->type_names[i], (const uchar*) values->type_names[i],
strlen(from_lib->type_names[i]))) values->type_lengths[i]))
return FALSE;
return TRUE;
}
uint Field_enum::is_equal(Create_field *new_field)
{
if (!Field_str::is_equal(new_field))
return 0; return 0;
return 1; return compare_enum_values(new_field->interval);
} }
/** /**
@return @return
returns 1 if the fields are equally defined returns 1 if the fields are equally defined
......
...@@ -1853,6 +1853,8 @@ public: ...@@ -1853,6 +1853,8 @@ public:
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
private: private:
int do_save_field_metadata(uchar *first_byte); int do_save_field_metadata(uchar *first_byte);
bool compare_enum_values(TYPELIB *values);
uint is_equal(Create_field *new_field);
}; };
......
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