From: Date: October 15 2008 5:09pm Subject: bzr commit into mysql-5.1 branch (ramil:2771) Bug#23113 List-Archive: http://lists.mysql.com/commits/56278 X-Bug: 23113 Message-Id: <200810151509.m9FF9wf8009604@ram.home> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/ram/mysql/b23113.5.1/ 2771 Ramil Kalimullin 2008-10-15 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. modified: mysql-test/r/alter_table.result mysql-test/t/alter_table.test sql/field.cc sql/field.h per-file messages: mysql-test/r/alter_table.result Fix for bug#23113: Different behavior on altering ENUM fields between 5.0 and 5.1 - test result. mysql-test/t/alter_table.test Fix for bug#23113: Different behavior on altering ENUM fields between 5.0 and 5.1 - test case. sql/field.cc Fix for bug#23113: Different behavior on altering ENUM fields between 5.0 and 5.1 - Field_enum::is_equal() introduced, which is called to detect that a field is changing by 'ALTER TABLE'. sql/field.h Fix for bug#23113: Different behavior on altering ENUM fields between 5.0 and 5.1 - Field_enum::is_equal() introduced, which is called to detect that a field is changing by 'ALTER TABLE'. === modified file 'mysql-test/r/alter_table.result' --- a/mysql-test/r/alter_table.result 2008-06-17 14:12:21 +0000 +++ b/mysql-test/r/alter_table.result 2008-10-15 15:09:48 +0000 @@ -1222,4 +1222,16 @@ ALTER TABLE t1 CHANGE d c varchar(10); affected rows: 0 info: Records: 0 Duplicates: 0 Warnings: 0 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 === modified file 'mysql-test/t/alter_table.test' --- a/mysql-test/t/alter_table.test 2008-06-17 14:12:21 +0000 +++ b/mysql-test/t/alter_table.test 2008-10-15 15:09:48 +0000 @@ -947,4 +947,16 @@ ALTER TABLE t1 CHANGE d c varchar(10); --disable_info 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 === modified file 'sql/field.cc' --- a/sql/field.cc 2008-09-20 14:52:34 +0000 +++ b/sql/field.cc 2008-10-15 15:09:48 +0000 @@ -8783,28 +8783,43 @@ bool Field::eq_def(Field *field) return 1; } + /** @return returns 1 if the fields are equally defined */ + bool Field_enum::eq_def(Field *field) { if (!Field::eq_def(field)) 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; - for (uint i=0 ; i < from_lib->count ; i++) + +bool Field_enum::compare_enum_values(TYPELIB *values) +{ + if (typelib->count != values->count) + return FALSE; + for (uint i= 0; i < typelib->count; i++) if (my_strnncoll(field_charset, - (const uchar*)typelib->type_names[i], - strlen(typelib->type_names[i]), - (const uchar*)from_lib->type_names[i], - strlen(from_lib->type_names[i]))) - return 0; - return 1; + (const uchar*) typelib->type_names[i], + typelib->type_lengths[i], + (const uchar*) values->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 compare_enum_values(new_field->interval); +} + + /** @return returns 1 if the fields are equally defined === modified file 'sql/field.h' --- a/sql/field.h 2008-09-20 14:52:34 +0000 +++ b/sql/field.h 2008-10-15 15:09:48 +0000 @@ -1853,6 +1853,8 @@ public: CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } private: int do_save_field_metadata(uchar *first_byte); + bool compare_enum_values(TYPELIB *values); + uint is_equal(Create_field *new_field); };