List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:January 14 2008 4:59pm
Subject:bk commit into 5.1 tree (istruewing:1.2641) BUG#33222
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of istruewing. When istruewing does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-01-14 17:59:45+01:00, istruewing@stripped +3 -0
  Bug#33222 - myisam-table drops rows when column is added
             and a char-field > 128 exists
  
  CHECK TABLE (non-QUICK) and any form of repair table did wrongly rate
  records as corrupted under the following conditions:
  1. The table has dynamic row format and
  2. it has a CHAR like column > 127 bytes (but not VARCHAR)
     (for multi-byte character sets this could be less than 127
     characters) and
  3. it has records with > 127 bytes significant length in that column
     (a byte beyond byte position 127 must be non-space).
  Affected were the statements CHECK TABLE, REPAIR TABLE, OPTIMIZE TABLE,
  ALTER TABLE. CHECK TABLE reported and marked the table as crashed if any
  record was present that fulfilled condition 3. The other statements
  deleted these records.
  
  The problem was a signed/unsigned compare in MyISAM code. A
  char to uchar change became necessary after the big byte to uchar
  change.

  mysql-test/r/myisam.result@stripped, 2008-01-14 17:59:44+01:00, istruewing@stripped +162 -0
    Bug#33222 - myisam-table drops rows when column is added
               and a char-field > 128 exists
    Added test result.

  mysql-test/t/myisam.test@stripped, 2008-01-14 17:59:44+01:00, istruewing@stripped +170 -0
    Bug#33222 - myisam-table drops rows when column is added
               and a char-field > 128 exists
    Added test.

  storage/myisam/mi_dynrec.c@stripped, 2008-01-14 17:59:44+01:00, istruewing@stripped +17 -15
    Bug#33222 - myisam-table drops rows when column is added
               and a char-field > 128 exists
    char -> uchar became necessary after big byte -> uchar change.
    Fixed some small coding style violations near the changes.

diff -Nrup a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
--- a/mysql-test/r/myisam.result	2007-11-15 20:25:40 +01:00
+++ b/mysql-test/r/myisam.result	2008-01-14 17:59:44 +01:00
@@ -2001,4 +2001,166 @@ CHECK TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	check	status	OK
 DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(130),
+c2 VARCHAR(1)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(REPEAT("a",128), 'b');
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	status	OK
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(130),
+c2 VARCHAR(1)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(REPEAT("a",128), 'b');
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+REPAIR TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	status	OK
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(130),
+c2 VARCHAR(1)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(REPEAT("a",128), 'b');
+INSERT INTO t1 VALUES('b', 'b');
+INSERT INTO t1 VALUES('c', 'b');
+DELETE FROM t1 WHERE c1='b';
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+2
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	status	OK
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+2
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(130),
+c2 VARCHAR(1),
+KEY (c1)
+) ENGINE=MyISAM;
+# Insert 100 rows. Query log disabled.
+UPDATE t1 SET c1=REPEAT("a",128) LIMIT 90;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+100
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+100
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(50),
+c2 VARCHAR(1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b');
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	status	OK
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(50),
+c2 VARCHAR(1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b');
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+REPAIR TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	status	OK
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+1
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(50),
+c2 VARCHAR(1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b');
+INSERT INTO t1 VALUES('b', 'b');
+INSERT INTO t1 VALUES('c', 'b');
+DELETE FROM t1 WHERE c1='b';
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+2
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	status	OK
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+2
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 CHAR(50),
+c2 VARCHAR(1),
+KEY (c1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+# Insert 100 rows. Query log disabled.
+UPDATE t1 SET c1=REPEAT(_utf8 x'e0ae85',43) LIMIT 90;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+100
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+100
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
 End of 5.1 tests
diff -Nrup a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
--- a/mysql-test/t/myisam.test	2007-11-15 20:25:40 +01:00
+++ b/mysql-test/t/myisam.test	2008-01-14 17:59:44 +01:00
@@ -1261,5 +1261,175 @@ DELETE FROM t1 WHERE c1 >= 10;
 CHECK TABLE t1;
 DROP TABLE t1;
 
+#
+# Bug#33222 - myisam-table drops rows when column is added
+#             and a char-field > 128 exists
+#
+# Test #1 - CHECK TABLE sees wrong record, REPAR TABLE deletes it.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+CREATE TABLE t1 (
+  c1 CHAR(130),
+  c2 VARCHAR(1)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(REPEAT("a",128), 'b');
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1;
+REPAIR TABLE t1;
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1;
+DROP TABLE t1;
+#
+# Test #2 - same as test #1, but using EXTENDED.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+CREATE TABLE t1 (
+  c1 CHAR(130),
+  c2 VARCHAR(1)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(REPEAT("a",128), 'b');
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1 EXTENDED;
+REPAIR TABLE t1 EXTENDED;
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1 EXTENDED;
+DROP TABLE t1;
+#
+# Test #3 - same as test #1, but using OPTIMIZE TABLE.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+CREATE TABLE t1 (
+  c1 CHAR(130),
+  c2 VARCHAR(1)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(REPEAT("a",128), 'b');
+# Insert more rows and delete one in the middle to force optimize.
+INSERT INTO t1 VALUES('b', 'b');
+INSERT INTO t1 VALUES('c', 'b');
+DELETE FROM t1 WHERE c1='b';
+SELECT COUNT(*) FROM t1;
+OPTIMIZE TABLE t1;
+SELECT COUNT(*) FROM t1;
+DROP TABLE t1;
+#
+# Test #4 - ALTER TABLE deletes rows.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+# Using an index which can be disabled during bulk insert.
+CREATE TABLE t1 (
+  c1 CHAR(130),
+  c2 VARCHAR(1),
+  KEY (c1)
+) ENGINE=MyISAM;
+#
+# Insert 100 rows. This turns bulk insert on during the copy phase of
+# ALTER TABLE. Bulk insert disables keys before the insert and re-enables
+# them by repair after the insert.
+--disable_query_log
+let $count= 100;
+--echo # Insert $count rows. Query log disabled.
+while ($count)
+{
+  INSERT INTO t1 VALUES ('a', 'b');
+  dec $count;
+}
+--enable_query_log
+#
+# Change most of the rows into long character values with > 127 characters.
+UPDATE t1 SET c1=REPEAT("a",128) LIMIT 90;
+SELECT COUNT(*) FROM t1;
+ALTER TABLE t1 ENGINE=MyISAM;
+#
+# With bug present, this shows that all long rows are gone.
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1;
+CHECK TABLE t1 EXTENDED;
+DROP TABLE t1;
+#
+# Test #5 - same as test #1 but UTF-8.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+CREATE TABLE t1 (
+  c1 CHAR(50),
+  c2 VARCHAR(1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+# Using Tamil Letter A, Unicode U+0B85
+INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b');
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1;
+REPAIR TABLE t1;
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1;
+DROP TABLE t1;
+#
+# Test #6 - same as test #2, but UTF-8.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+CREATE TABLE t1 (
+  c1 CHAR(50),
+  c2 VARCHAR(1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+# Using Tamil Letter A, Unicode U+0B85
+INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b');
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1 EXTENDED;
+REPAIR TABLE t1 EXTENDED;
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1 EXTENDED;
+DROP TABLE t1;
+#
+# Test #7 - same as test #3, but UTF-8.
+# Using a CHAR column that can have > 127 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+CREATE TABLE t1 (
+  c1 CHAR(50),
+  c2 VARCHAR(1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+# Using Tamil Letter A, Unicode U+0B85
+INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b');
+# Insert more rows and delete one in the middle to force optimize.
+INSERT INTO t1 VALUES('b', 'b');
+INSERT INTO t1 VALUES('c', 'b');
+DELETE FROM t1 WHERE c1='b';
+SELECT COUNT(*) FROM t1;
+OPTIMIZE TABLE t1;
+SELECT COUNT(*) FROM t1;
+DROP TABLE t1;
+#
+# Test #8 - same as test #4, but UTF-8.
+# Using a CHAR column that can have > 42 UTF-8 characters.
+# Using a VARCHAR to create a table with dynamic row format.
+# Using an index which can be disabled during bulk insert.
+CREATE TABLE t1 (
+  c1 CHAR(50),
+  c2 VARCHAR(1),
+  KEY (c1)
+) ENGINE=MyISAM DEFAULT CHARSET UTF8;
+#
+# Insert 100 rows. This turns bulk insert on during the copy phase of
+# ALTER TABLE. Bulk insert disables keys before the insert and re-enables
+# them by repair after the insert.
+--disable_query_log
+let $count= 100;
+--echo # Insert $count rows. Query log disabled.
+while ($count)
+{
+  INSERT INTO t1 VALUES ('a', 'b');
+  dec $count;
+}
+--enable_query_log
+#
+# Change most of the rows into long character values with > 42 characters.
+# Using Tamil Letter A, Unicode U+0B85
+UPDATE t1 SET c1=REPEAT(_utf8 x'e0ae85',43) LIMIT 90;
+SELECT COUNT(*) FROM t1;
+ALTER TABLE t1 ENGINE=MyISAM;
+#
+# With bug present, this shows that all long rows are gone.
+SELECT COUNT(*) FROM t1;
+CHECK TABLE t1;
+CHECK TABLE t1 EXTENDED;
+DROP TABLE t1;
+
 --echo End of 5.1 tests
 
diff -Nrup a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
--- a/storage/myisam/mi_dynrec.c	2007-11-12 10:07:27 +01:00
+++ b/storage/myisam/mi_dynrec.c	2008-01-14 17:59:44 +01:00
@@ -1006,12 +1006,12 @@ uint _mi_rec_pack(MI_INFO *info, registe
 	{
 	  if (rec->length > 255 && new_length > 127)
 	  {
-	    to[0]=(char) ((new_length & 127)+128);
-	    to[1]=(char) (new_length >> 7);
-	    to+=2;
-	  }
-	  else
-	    *to++= (char) new_length;
+            to[0]= (uchar) ((new_length & 127) + 128);
+            to[1]= (uchar) (new_length >> 7);
+            to+=2;
+          }
+          else
+            *to++= (uchar) new_length;
 	  memcpy((uchar*) to,pos,(size_t) new_length); to+=new_length;
 	  flag|=bit;
 	}
@@ -1045,7 +1045,7 @@ uint _mi_rec_pack(MI_INFO *info, registe
       }
       if ((bit= bit << 1) >= 256)
       {
-	*packpos++ = (char) (uchar) flag;
+        *packpos++= (uchar) flag;
 	bit=1; flag=0;
       }
     }
@@ -1055,9 +1055,9 @@ uint _mi_rec_pack(MI_INFO *info, registe
     }
   }
   if (bit != 1)
-    *packpos= (char) (uchar) flag;
+    *packpos= (uchar) flag;
   if (info->s->calc_checksum)
-    *to++=(char) info->checksum;
+    *to++= (uchar) info->checksum;
   DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos)));
   DBUG_RETURN((uint) (to-startpos));
 } /* _mi_rec_pack */
@@ -1128,12 +1128,14 @@ my_bool _mi_rec_check(MI_INFO *info,cons
 	    goto err;
 	  if (rec->length > 255 && new_length > 127)
 	  {
-	    if (to[0] != (char) ((new_length & 127)+128) ||
-		to[1] != (char) (new_length >> 7))
-	      goto err;
-	    to+=2;
-	  }
-	  else if (*to++ != (char) new_length)
+            /* purecov: begin inspected */
+            if (to[0] != (uchar) ((new_length & 127) + 128) ||
+                to[1] != (uchar) (new_length >> 7))
+              goto err;
+            to+=2;
+            /* purecov: end */
+          }
+          else if (*to++ != (uchar) new_length)
 	    goto err;
 	  to+=new_length;
 	}
Thread
bk commit into 5.1 tree (istruewing:1.2641) BUG#33222Ingo Struewing14 Jan