Commit 2c53f109 authored by Gleb Shchepa's avatar Gleb Shchepa

Bug #37799: SELECT with a BIT column in WHERE clause

            returns unexpected result

If:
  1. a table has a not nullable BIT column c1 with a length
     shorter than 8 bits and some additional not nullable
     columns c2 etc, and
  2. the WHERE clause is like: (c1 = constant) AND c2 ...,
the SELECT query returns unexpected result set.


The server stores BIT columns in a tricky way to save disk
space: if column's bit length is not divisible by 8, the
server places reminder bits among the null bits at the start
of a record. The rest bytes are stored in the record itself,
and Field::ptr points to these rest bytes.

However if a bit length of the whole column is less than 8,
there are no remaining bytes, and there is nothing to store in
the record at its regular place. In this case Field::ptr points
to bytes actually occupied by the next column in a record.
If both columns (BIT and the next column) are NOT NULL,
the Field::eq function incorrectly deduces that this is the
same column, so query transformation/equal item elimination
code (see build_equal_items_for_cond) may mix these columns
and damage conditions containing references to them.
parent 1f28ee88
...@@ -684,4 +684,28 @@ SELECT 1 FROM t1 GROUP BY a; ...@@ -684,4 +684,28 @@ SELECT 1 FROM t1 GROUP BY a;
1 1
1 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (b BIT NOT NULL, i2 INTEGER NOT NULL, s VARCHAR(255) NOT NULL);
INSERT INTO t1 VALUES(0x01,100,''), (0x00,300,''), (0x01,200,''), (0x00,100,'');
SELECT HEX(b), i2 FROM t1 WHERE (i2>=100 AND i2<201) AND b=TRUE;
HEX(b) i2
1 100
1 200
CREATE TABLE t2 (b1 BIT NOT NULL, b2 BIT NOT NULL, i2 INTEGER NOT NULL,
s VARCHAR(255) NOT NULL);
INSERT INTO t2 VALUES (0x01,0x00,100,''), (0x00,0x01,300,''),
(0x01,0x00,200,''), (0x00,0x01,100,'');
SELECT HEX(b1), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b1=TRUE;
HEX(b1) i2
1 100
1 200
SELECT HEX(b2), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b2=FALSE;
HEX(b2) i2
0 100
0 200
SELECT HEX(b1), HEX(b2), i2 FROM t2
WHERE (i2>=100 AND i2<201) AND b1=TRUE AND b2=FALSE;
HEX(b1) HEX(b2) i2
1 0 100
1 0 200
DROP TABLE t1, t2;
End of 5.0 tests End of 5.0 tests
...@@ -333,4 +333,23 @@ SELECT 1 FROM t1 GROUP BY a; ...@@ -333,4 +333,23 @@ SELECT 1 FROM t1 GROUP BY a;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#37799 SELECT with a BIT column in WHERE clause returns unexpected result
#
CREATE TABLE t1 (b BIT NOT NULL, i2 INTEGER NOT NULL, s VARCHAR(255) NOT NULL);
INSERT INTO t1 VALUES(0x01,100,''), (0x00,300,''), (0x01,200,''), (0x00,100,'');
SELECT HEX(b), i2 FROM t1 WHERE (i2>=100 AND i2<201) AND b=TRUE;
CREATE TABLE t2 (b1 BIT NOT NULL, b2 BIT NOT NULL, i2 INTEGER NOT NULL,
s VARCHAR(255) NOT NULL);
INSERT INTO t2 VALUES (0x01,0x00,100,''), (0x00,0x01,300,''),
(0x01,0x00,200,''), (0x00,0x01,100,'');
SELECT HEX(b1), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b1=TRUE;
SELECT HEX(b2), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b2=FALSE;
SELECT HEX(b1), HEX(b2), i2 FROM t2
WHERE (i2>=100 AND i2<201) AND b1=TRUE AND b2=FALSE;
DROP TABLE t1, t2;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -138,7 +138,7 @@ public: ...@@ -138,7 +138,7 @@ public:
virtual bool eq(Field *field) virtual bool eq(Field *field)
{ {
return (ptr == field->ptr && null_ptr == field->null_ptr && return (ptr == field->ptr && null_ptr == field->null_ptr &&
null_bit == field->null_bit); null_bit == field->null_bit && field->type() == type());
} }
virtual bool eq_def(Field *field); virtual bool eq_def(Field *field);
...@@ -1489,7 +1489,6 @@ public: ...@@ -1489,7 +1489,6 @@ public:
bool eq(Field *field) bool eq(Field *field)
{ {
return (Field::eq(field) && return (Field::eq(field) &&
field->type() == type() &&
bit_ptr == ((Field_bit *)field)->bit_ptr && bit_ptr == ((Field_bit *)field)->bit_ptr &&
bit_ofs == ((Field_bit *)field)->bit_ofs); bit_ofs == ((Field_bit *)field)->bit_ofs);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment