From 45cbd32697abbc29d793746f58faecef90c15aaa Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Wed, 29 Apr 2009 14:00:34 +0200 Subject: [PATCH] Bug#43737: Select query return bad result A bug in the initialization of key segment information made it point to the wrong bit, since a bit index was used when its int value was needed. This lead to misinterpretation of bit columns read from MyISAM record format when a NULL bit pushed them over a byte boundary. Fixed by using the int value of the bit instead. mysql-test/r/myisam.result: Bug#43737: Test result. mysql-test/t/myisam.test: Bug#43737: Test case. storage/myisam/mi_open.c: Bug#43737: fix. --- mysql-test/r/myisam.result | 26 ++++++++++++++++++++++++++ mysql-test/t/myisam.test | 25 +++++++++++++++++++++++++ storage/myisam/mi_open.c | 3 ++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 6f26135ce45..732b1b260f8 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2226,4 +2226,30 @@ Key Start Len Index Type 1 2 30 multip. varchar 2 33 30 multip. char NULL DROP TABLE t1; +CREATE TABLE t1 ( +c INT, +d bit(1), +e INT, +f VARCHAR(1), +g BIT(1), +h BIT(1), +KEY (h, d, e, g) +); +INSERT INTO t1 VALUES +( 3, 1, 1, 'a', 0, 0 ), +( 3, 1, 5, 'a', 0, 0 ), +( 10, 1, 2, 'a', 0, 1 ), +( 10, 1, 3, 'a', 0, 1 ), +( 10, 1, 4, 'a', 0, 1 ); +SELECT f FROM t1 WHERE d = 1 AND e = 2 AND g = 0 AND h = 1; +f +a +SELECT h+0, d + 0, e, g + 0 FROM t1; +h+0 d + 0 e g + 0 +0 1 1 0 +0 1 5 0 +1 1 2 0 +1 1 3 0 +1 1 4 0 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 6d7e03b1c28..ba6bc05cfea 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1478,5 +1478,30 @@ let $MYSQLD_DATADIR= `select @@datadir`; --exec $MYISAMCHK -d $MYSQLD_DATADIR/test/t1 DROP TABLE t1; +# +# Bug#43737: Select query return bad result +# +CREATE TABLE t1 ( + c INT, + d bit(1), + e INT, + f VARCHAR(1), + g BIT(1), + h BIT(1), + KEY (h, d, e, g) +); +INSERT INTO t1 VALUES + ( 3, 1, 1, 'a', 0, 0 ), + ( 3, 1, 5, 'a', 0, 0 ), + ( 10, 1, 2, 'a', 0, 1 ), + ( 10, 1, 3, 'a', 0, 1 ), + ( 10, 1, 4, 'a', 0, 1 ); + +SELECT f FROM t1 WHERE d = 1 AND e = 2 AND g = 0 AND h = 1; + +SELECT h+0, d + 0, e, g + 0 FROM t1; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 78749d50fe5..328cde20923 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -1160,7 +1160,8 @@ uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg) keyseg->null_pos = mi_uint4korr(ptr); ptr +=4; keyseg->charset=0; /* Will be filled in later */ if (keyseg->null_bit) - keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == 7)); + /* We adjust bit_pos if null_bit is last in the byte */ + keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == (1 << 7))); else { keyseg->bit_pos= (uint16)keyseg->null_pos;