From 4e6e122061b71f9378a161793367ae5120310ed4 Mon Sep 17 00:00:00 2001
From: unknown <igor@olga.mysql.com>
Date: Sun, 5 Aug 2007 14:16:49 -0700
Subject: [PATCH] Fix bug #30219. This bug manifested itself for queries with
 grouping by columns of the BIT type. It led to wrong comparisons of bit-field
 values and wrong result sets. Bit-field values never cannot be compared as
 binary values. Yet the class Field_bit had an implementation of the cmp
 method that compared bit-fields values as binary values. Also the get_image
 and set_image methods of the base class Field cannot be used for objects of
 the Field_bit class. Now these methods are declared as virtual and specific
 implementations of the methods are provided for the class Field_bit.

mysql-test/r/type_bit.result:
  Added a test case for bug #30219.
mysql-test/t/type_bit.test:
  Added a test case for bug #30219.
sql/field.h:
  Fix bug #30219.
  This bug manifested itself for queries with grouping by columns of
  the BIT type. It led to wrong comparisons of bit-field values and
  wrong result sets.
  Bit-field values never cannot be compared as binary values. Yet
  the class Field_bit had an implementation of the cmp method that
  compared bit-fields values as binary values.
  Also the get_image and set_image methods of the base class Field
  cannot be used for objects of the Field_bit class.
  Now these methods are declared as virtual and specific implementations
  of these methods are provided for the class Field_bit.
---
 mysql-test/r/type_bit.result | 32 ++++++++++++++++++++++++++++++++
 mysql-test/t/type_bit.test   | 24 ++++++++++++++++++++++++
 sql/field.h                  | 13 ++++++++++---
 3 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result
index fad0e1f797..324dcc2775 100644
--- a/mysql-test/r/type_bit.result
+++ b/mysql-test/r/type_bit.result
@@ -618,4 +618,36 @@ bit_field	int_field
 	2
 handler t1 close;
 drop table t1;
+CREATE TABLE t1 (b BIT(2));
+INSERT INTO t1 (b) VALUES (1), (3), (0), (3);
+SELECT b+0, COUNT(DISTINCT b) FROM t1 GROUP BY b;
+b+0	COUNT(DISTINCT b)
+0	1
+1	1
+3	1
+DROP TABLE t1;
+CREATE TABLE t1 (b BIT(2), a VARCHAR(5));
+INSERT INTO t1 (b, a) VALUES (1, "x"), (3, "zz"), (0, "y"), (3, "z");
+SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b;
+b+0	COUNT(DISTINCT a)
+0	1
+1	1
+3	2
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(5), b BIT(2));
+INSERT INTO t1 (b, a) VALUES (1, "x"), (3, "zz"), (0, "y"), (3, "z");
+SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b;
+b+0	COUNT(DISTINCT a)
+0	1
+1	1
+3	2
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b BIT(2));
+INSERT INTO t1 (b, a) VALUES (1, 1), (3, 2), (0, 3), (3, 4);
+SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b;
+b+0	COUNT(DISTINCT a)
+0	1
+1	1
+3	2
+DROP TABLE t1;
 End of 5.0 tests
diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test
index 48ad24ff6b..2c7f87f342 100644
--- a/mysql-test/t/type_bit.test
+++ b/mysql-test/t/type_bit.test
@@ -272,4 +272,28 @@ handler t1 read a=(1);
 handler t1 close;
 drop table t1;
 
+#
+# Bug #30219: GROUP BY a column of the BIT type
+#
+
+CREATE TABLE t1 (b BIT(2));
+INSERT INTO t1 (b) VALUES (1), (3), (0), (3);
+SELECT b+0, COUNT(DISTINCT b) FROM t1 GROUP BY b;
+DROP TABLE t1;
+
+CREATE TABLE t1 (b BIT(2), a VARCHAR(5));
+INSERT INTO t1 (b, a) VALUES (1, "x"), (3, "zz"), (0, "y"), (3, "z");
+SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a CHAR(5), b BIT(2));
+INSERT INTO t1 (b, a) VALUES (1, "x"), (3, "zz"), (0, "y"), (3, "z");
+SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT, b BIT(2));
+INSERT INTO t1 (b, a) VALUES (1, 1), (3, 2), (0, 3), (3, 4);
+SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b;
+DROP TABLE t1;
+
 --echo End of 5.0 tests
diff --git a/sql/field.h b/sql/field.h
index fbf402ab5c..92705b9aac 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -231,9 +231,9 @@ public:
     if (null_ptr)
       null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*);
   }
-  inline void get_image(char *buff,uint length, CHARSET_INFO *cs)
+  virtual void get_image(char *buff, uint length, CHARSET_INFO *cs)
     { memcpy(buff,ptr,length); }
-  inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
+  virtual void set_image(char *buff,uint length, CHARSET_INFO *cs)
     { memcpy(ptr,buff,length); }
 
 
@@ -1430,13 +1430,20 @@ public:
   String *val_str(String*, String *);
   my_decimal *val_decimal(my_decimal *);
   int cmp(const char *a, const char *b)
-  { return cmp_binary(a, b); }
+  { 
+    DBUG_ASSERT(ptr == a);
+    return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
+  }
   int key_cmp(const byte *a, const byte *b)
   { return cmp_binary((char *) a, (char *) b); }
   int key_cmp(const byte *str, uint length);
   int cmp_offset(uint row_offset);
   int cmp_binary_offset(uint row_offset)
   { return cmp_offset(row_offset); }
+  void get_image(char *buff, uint length, CHARSET_INFO *cs)
+  { get_key_image(buff, length, itRAW); }   
+  void set_image(char *buff,uint length, CHARSET_INFO *cs)
+  { Field_bit::store(buff, length, cs); }
   uint get_key_image(char *buff, uint length, imagetype type);
   void set_key_image(char *buff, uint length)
   { Field_bit::store(buff, length, &my_charset_bin); }
-- 
2.30.9