List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:September 22 2009 3:06pm
Subject:bzr commit into mysql-5.1-bugteam branch (davi:3118) Bug#45567
View as plain text  
# At a local mysql-5.1-bugteam repository of davi

 3118 Davi Arnaut	2009-09-22
      Bug#45567: Fast ALTER TABLE broken for enum and set
      
      The problem was that appending values to the end of an existing
      ENUM or SET column was being treated as table data modification,
      preventing a immediately (fast) table alteration that occurs when
      only table metadata is being modified.
      
      The cause was twofold: adding a enumeration or set members to the 
      end of the list of valid member values was not being considered
      a "compatible" table alteration, and for SET columns, the check
      was being done upon the max display length and not the underlying
      (pack) length of the field.
      
      The solution is to augment the function that checks wether two ENUM
      or SET fields are compatible -- by comparing the pack lengths and
      performing a limited comparison of the member values.
     @ mysql-test/r/alter_table.result
        Add test case result for Bug#45567
     @ mysql-test/t/alter_table.test
        Add test case for Bug#45567
     @ sql/field.cc
        Check whether two fields can be considered 'equal' for table
        alteration purposes. Fields are equal if they retain the same
        pack length and if new members are added to the end of the list.

    modified:
      mysql-test/r/alter_table.result
      mysql-test/t/alter_table.test
      sql/field.cc
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	2008-12-09 13:31:22 +0000
+++ b/mysql-test/r/alter_table.result	2009-09-22 15:06:52 +0000
@@ -1268,4 +1268,66 @@ a	b
 4	b
 5	a
 DROP TABLE t1;
+#
+# Bug#45567: Fast ALTER TABLE broken for enum and set
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a ENUM('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+# No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2');
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+# No copy: Add new enumeration to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3');
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+# Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+# Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+# Copy: Add new enumeration
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+# No copy: Add new enumerations to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6');
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+DROP TABLE t1;
+CREATE TABLE t1 (a SET('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+# No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2');
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+# No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3');
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+# Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+# Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+# Copy: Add new member
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+# No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6');
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+# Copy: Numerical incrase (pack lenght)
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10');
+affected rows: 2
+info: Records: 2  Duplicates: 0  Warnings: 0
+DROP TABLE t1;
 End of 5.1 tests

=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test	2008-12-09 13:31:22 +0000
+++ b/mysql-test/t/alter_table.test	2009-09-22 15:06:52 +0000
@@ -1000,4 +1000,50 @@ ALTER TABLE t1 MODIFY b ENUM('a', 'z', '
 SELECT * FROM t1;
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#45567: Fast ALTER TABLE broken for enum and set
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a ENUM('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+--enable_info
+--echo # No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2');
+--echo # No copy: Add new enumeration to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3');
+--echo # Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5');
+--echo # Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx');
+--echo # Copy: Add new enumeration
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx');
+--echo # No copy: Add new enumerations to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6');
+--disable_info
+DROP TABLE t1;
+
+CREATE TABLE t1 (a SET('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+--enable_info
+--echo # No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2');
+--echo # No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3');
+--echo # Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5');
+--echo # Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx');
+--echo # Copy: Add new member
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx');
+--echo # No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6');
+--echo # Copy: Numerical incrase (pack lenght)
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10');
+--disable_info
+DROP TABLE t1;
+
 --echo End of 5.1 tests

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2009-08-28 16:21:54 +0000
+++ b/sql/field.cc	2009-09-22 15:06:52 +0000
@@ -8862,9 +8862,36 @@ bool Field_enum::compare_enum_values(TYP
 
 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);
+  TYPELIB *values= new_field->interval;
+
+  /*
+    The fields are compatible if they have the same flags,
+    type, charset and have the same underlying length.
+  */
+  if (compare_str_field_flags(new_field, flags) ||
+      new_field->sql_type != real_type() ||
+      new_field->charset != field_charset ||
+      new_field->pack_length != pack_length())
+    return IS_EQUAL_NO;
+
+  /*
+    Changing the definition of an ENUM or SET column by adding a new
+    enumeration or set members to the end of the list of valid member
+    values only alters table metadata and not table data.
+  */
+  if (typelib->count > values->count)
+    return IS_EQUAL_NO;
+
+  /* Check whether there are modification before the end. */
+  for (uint i= 0; i < typelib->count; i++)
+    if (my_strnncoll(field_charset,
+                     (const uchar*) typelib->type_names[i],
+                     typelib->type_lengths[i],
+                     (const uchar*) values->type_names[i],
+                     values->type_lengths[i]))
+      return IS_EQUAL_NO;
+
+  return IS_EQUAL_YES;
 }
 
 


Attachment: [text/bzr-bundle] bzr/davi.arnaut@sun.com-20090922150652-b0cuwsgnwt51uzpn.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (davi:3118) Bug#45567Davi Arnaut22 Sep