List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:September 3 2008 12:23pm
Subject:bzr commit into mysql-6.0 branch (bar:2820) Bug#26180
View as plain text  
#At file:///home/bar/mysql-bzr/mysql-6.0.b26180/

 2820 Alexander Barkov	2008-09-03
       Bug#26180 Can't add columns to tables created with utf8 (regular) text indexes
            Problem: On ALTER TABLE, maximum possible key part length for TEXT
            variants was calculated similar to VARCHAR datatype, which was wrong
            because TEXT columns are limited in bytes, while VARCHAR columns
            are limited in characters.
            Fix: adding a special code for TEXT variants.
            
            mysql-test/r/ctype_utf8.result
            mysql-test/t/ctype_utf8.test
              Adding test case
            
            sql/sql_table.cc
              Adding special code for TEXT variants.
modified:
  mysql-test/r/ctype_utf8.result
  mysql-test/t/ctype_utf8.test
  sql/sql_table.cc

=== modified file 'mysql-test/r/ctype_utf8.result'
--- a/mysql-test/r/ctype_utf8.result	2008-07-25 17:21:55 +0000
+++ b/mysql-test/r/ctype_utf8.result	2008-09-03 12:22:55 +0000
@@ -2402,6 +2402,23 @@ b
 c
 drop table t1;
 set max_sort_length=default;
+CREATE TABLE t1 (
+clipid INT NOT NULL,
+Tape TINYTEXT,
+PRIMARY KEY (clipid),
+KEY tape(Tape(255))
+) CHARACTER SET=utf8;
+ALTER TABLE t1 ADD mos TINYINT DEFAULT 0 AFTER clipid;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `clipid` int(11) NOT NULL,
+  `mos` tinyint(4) DEFAULT '0',
+  `Tape` tinytext,
+  PRIMARY KEY (`clipid`),
+  KEY `tape` (`Tape`(255))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+DROP TABLE t1;
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 (
 predicted_order int NOT NULL,

=== modified file 'mysql-test/t/ctype_utf8.test'
--- a/mysql-test/t/ctype_utf8.test	2008-07-23 09:43:50 +0000
+++ b/mysql-test/t/ctype_utf8.test	2008-09-03 12:22:55 +0000
@@ -1524,6 +1524,19 @@ drop table t1;
 set max_sort_length=default;
 
 #
+# Bug#26180: Can't add columns to tables created with utf8 text indexes
+#
+CREATE TABLE t1 (
+  clipid INT NOT NULL,
+  Tape TINYTEXT,
+  PRIMARY KEY (clipid),
+  KEY tape(Tape(255))
+) CHARACTER SET=utf8;
+ALTER TABLE t1 ADD mos TINYINT DEFAULT 0 AFTER clipid;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+#
 # Bug#26474: Add Sinhala script (Sri Lanka) collation to MySQL
 #
 --disable_warnings

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2008-08-27 15:48:32 +0000
+++ b/sql/sql_table.cc	2008-09-03 12:22:55 +0000
@@ -5905,6 +5905,35 @@ mysql_fast_or_online_alter_table(THD *th
 
 
 /**
+  maximum possible length for certain blob types.
+
+  @param[in]      type        Blob type (e.g. MYSQL_TYPE_TINY_BLOB)
+
+  @return
+    length
+*/
+
+static uint
+blob_length_by_type(enum_field_types type)
+{
+  switch (type)
+  {
+  case MYSQL_TYPE_TINY_BLOB:
+    return 255;
+  case MYSQL_TYPE_BLOB:
+    return 65535;
+  case MYSQL_TYPE_MEDIUM_BLOB:
+    return 16777215;
+  case MYSQL_TYPE_LONG_BLOB:
+    return 4294967295U;
+  default:
+    DBUG_ASSERT(0); // we should never go here
+    return 0;
+  }
+}
+
+
+/**
   Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
 
   This function transforms parse output of ALTER TABLE - lists of
@@ -6209,6 +6238,14 @@ mysql_prepare_alter_table(THD *thd, TABL
 
           BLOBs may have cfield->length == 0, which is why we test it before
           checking whether cfield->length < key_part_length (in chars).
+          
+          In case of TEXTs we check the data type maximum length *in bytes*
+          to key part length measured *in characters* (i.e. key_part_length
+          devided to mbmaxlen). This is because it's OK to have:
+          CREATE TABLE t1 (a tinytext, key(a(254)) character set utf8);
+          In case of this example:
+          - data type maximum length is 255.
+          - key_part_length is 1016 (=254*4, where 4 is mbmaxlen)
          */
         if (!Field::type_can_have_key_part(cfield->field->type()) ||
             !Field::type_can_have_key_part(cfield->sql_type) ||
@@ -6216,8 +6253,10 @@ mysql_prepare_alter_table(THD *thd, TABL
             (key_info->flags & HA_SPATIAL) ||
             (cfield->field->field_length == key_part_length &&
              !f_is_blob(key_part->key_type)) ||
-	    (cfield->length && (cfield->length < key_part_length /
-                                key_part->field->charset()->mbmaxlen)))
+            (cfield->length && ((f_is_blob(key_part->key_type) ? 
+                                blob_length_by_type(cfield->sql_type) :
+                                cfield->length) <
+	     key_part_length / key_part->field->charset()->mbmaxlen)))
 	  key_part_length= 0;			// Use whole field
       }
       key_part_length /= key_part->field->charset()->mbmaxlen;

Thread
bzr commit into mysql-6.0 branch (bar:2820) Bug#26180Alexander Barkov3 Sep