From 62933c50df1dd97940f4b46c1376ba80e6a8368c Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 12 Feb 2010 16:30:04 +0400 Subject: [PATCH] BUG#49628 - corrupt table after legal SQL, LONGTEXT column Bulk REPLACE or bulk INSERT ... ON DUPLICATE KEY UPDATE may break dynamic record MyISAM table. The problem is limited to bulk REPLACE and INSERT ... ON DUPLICATE KEY UPDATE, because only these operations may be done via UPDATE internally and may request write cache. When flushing write cache, MyISAM may write remaining cached data at wrong position. Fixed by requesting write cache to seek to a correct position. mysql-test/r/myisam.result: A test case for BUG#49628. mysql-test/t/myisam.test: A test case for BUG#49628. storage/myisam/mi_dynrec.c: delete_dynamic_record() may change data file position. IO cache must be notified as it may still have cached data, which has to be flushed later. --- mysql-test/r/myisam.result | 13 +++++++++++++ mysql-test/t/myisam.test | 13 +++++++++++++ storage/myisam/mi_dynrec.c | 8 ++++++++ 3 files changed, 34 insertions(+) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index c68bc91aa41..15fce66cff1 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2313,4 +2313,17 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; +# +# BUG#49628 - corrupt table after legal SQL, LONGTEXT column +# +CREATE TABLE t1(a INT, b LONGTEXT, UNIQUE(a)); +REPLACE INTO t1 VALUES +(1, REPEAT('a', 129015)),(1, NULL), +(2, NULL),(3, NULL),(4, NULL),(5, NULL),(6, NULL),(7, NULL), +(1, REPEAT('b', 129016)),(1, NULL), +(1, REPEAT('c', 129015)),(1, REPEAT('d', 129015)); +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 351027ab246..568eadb5e39 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1563,5 +1563,18 @@ SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; CHECK TABLE t1; DROP TABLE t1; + +--echo # +--echo # BUG#49628 - corrupt table after legal SQL, LONGTEXT column +--echo # +CREATE TABLE t1(a INT, b LONGTEXT, UNIQUE(a)); +REPLACE INTO t1 VALUES +(1, REPEAT('a', 129015)),(1, NULL), +(2, NULL),(3, NULL),(4, NULL),(5, NULL),(6, NULL),(7, NULL), +(1, REPEAT('b', 129016)),(1, NULL), +(1, REPEAT('c', 129015)),(1, REPEAT('d', 129015)); +CHECK TABLE t1; +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 696b9ff93df..6518d874f4f 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -933,8 +933,16 @@ static int update_dynamic_record(MI_INFO *info, my_off_t filepos, uchar *record, } if (block_info.next_filepos != HA_OFFSET_ERROR) + { + /* + delete_dynamic_record() may change data file position. + IO cache must be notified as it may still have cached + data, which has to be flushed later. + */ + info->rec_cache.seek_not_done= 1; if (delete_dynamic_record(info,block_info.next_filepos,1)) goto err; + } DBUG_RETURN(0); err: DBUG_RETURN(1);