List:Commits« Previous MessageNext Message »
From:Ian Greenhoe Date:September 13 2006 8:18am
Subject:bk commit into 5.0 tree (igreenhoe:1.2272) BUG#19342
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of greenman. When greenman 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, 2006-09-12 23:17:58-07:00, igreenhoe@stripped +4 -0
  Fix for bug #19342 (IN works incorrectly for BIGINT UNSIGNED values)
  
  Problem: the in function extracts and stores the integer portion of
  an integer-valued Item prior to comparison for speed.  However, this
  extraction did not keep track if the value was unsigned in certian
  circumstances, and assumed that the stored value was signed.
  
  Solution: add the extra information so that we can make the
  determination at comparison time if the origional values were
  signed or not.  Note that this may appear to be an inefficent packing
  of the data; however, it ensures that the long longs are
  word-aligned, and also keeps the signedness bit near the value so
  that we can efficently sort.

  mysql-test/r/func_in.result@stripped, 2006-09-12 23:17:53-07:00,
igreenhoe@stripped +32 -0
    New tests for the "in" function

  mysql-test/t/func_in.test@stripped, 2006-09-12 23:17:53-07:00,
igreenhoe@stripped +18 -0
    New tests for the "in" function

  sql/item_cmpfunc.cc@stripped, 2006-09-12 23:17:53-07:00,
igreenhoe@stripped +14 -4
    Added unsigned_flag to the information that we keep (and check) when
    comparing integers in the "in" function.

  sql/item_cmpfunc.h@stripped, 2006-09-12 23:17:53-07:00,
igreenhoe@stripped +12 -3
    Added unsigned_flag to the information that we keep (and check) when
    comparing integers in the "in" function.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	igreenhoe
# Host:	anubis.greendragongames.com
# Root:	/home/greenman/workspace-mysql/mysql/bug-5.0-19342

--- 1.217/sql/item_cmpfunc.cc	2006-09-12 23:18:06 -07:00
+++ 1.218/sql/item_cmpfunc.cc	2006-09-12 23:18:06 -07:00
@@ -2058,6 +2058,10 @@
 
 static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b)
 {
+  /* extra bit (unsigned_flag) is stored immediately after a and b */
+  if (*(a+1) != *(b+1))
+    return *(a+1) ? 1 : -1;
+
   return *a < *b ? -1 : *a == *b ? 0 : 1;
 }
 
@@ -2183,20 +2187,26 @@
 }
 
 in_longlong::in_longlong(uint elements)
-  :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0)
+  :in_vector(elements,sizeof(longlong) * 2,(qsort2_cmp) cmp_longlong, 0)
 {}
 
 void in_longlong::set(uint pos,Item *item)
 {
-  ((longlong*) base)[pos]=item->val_int();
+  longlong *temp= (longlong *) base;
+  temp[pos * 2]= item->val_int();
+
+  /* record unsigned flag only if val_int would read as < 0 */
+  temp[pos * 2 + 1]= item->unsigned_flag && temp[pos * 2] < 0;
 }
 
 byte *in_longlong::get_value(Item *item)
 {
-  tmp= item->val_int();
+  tmp[0]= item->val_int();
+  /* record unsigned flag only if val_int would read as < 0 */
+  tmp[1]= item->unsigned_flag && tmp[0] < 0;
   if (item->null_value)
     return 0;
-  return (byte*) &tmp;
+  return (byte*) tmp;
 }
 
 in_double::in_double(uint elements)

--- 1.129/sql/item_cmpfunc.h	2006-09-12 23:18:06 -07:00
+++ 1.130/sql/item_cmpfunc.h	2006-09-12 23:18:06 -07:00
@@ -703,7 +703,8 @@
 
 class in_longlong :public in_vector
 {
-  longlong tmp;
+  /* used by get_value, tmp[0] is val_int, tmp[1] is unsigned_flag */
+  longlong tmp[2];
 public:
   in_longlong(uint elements);
   void set(uint pos,Item *item);
@@ -719,7 +720,8 @@
   }
   void value_to_item(uint pos, Item *item)
   {
-    ((Item_int*)item)->value= ((longlong*)base)[pos];
+    ((Item_int*)item)->value= ((longlong*)base)[pos * 2];
+    ((Item_int*)item)->unsigned_flag= ((longlong*)base)[pos * 2 + 1];
   }
 };
 
@@ -825,19 +827,26 @@
 class cmp_item_int :public cmp_item
 {
   longlong value;
+  my_bool unsigned_flag;
 public:
   cmp_item_int() {}                           /* Remove gcc warning */
   void store_value(Item *item)
   {
     value= item->val_int();
+    /* record unsigned flag only if val_int would read as < 0 */
+    unsigned_flag= item->unsigned_flag && value < 0;
   }
   int cmp(Item *arg)
   {
-    return value != arg->val_int();
+    return (value != arg->val_int()) || (unsigned_flag != arg->unsigned_flag);
   }
   int compare(cmp_item *c)
   {
     cmp_item_int *cmp= (cmp_item_int *)c;
+
+    if (unsigned_flag != cmp->unsigned_flag)
+      return unsigned_flag ? 1 : -1;
+
     return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1);
   }
   cmp_item *make_same();

--- 1.28/mysql-test/r/func_in.result	2006-09-12 23:18:06 -07:00
+++ 1.29/mysql-test/r/func_in.result	2006-09-12 23:18:06 -07:00
@@ -343,3 +343,35 @@
 1
 2
 drop table t1;
+create table t1 (c1 bigint unsigned);
+insert into t1 values (0xFFFFFFFFFFFFFFFF);
+select * from t1 where c1=-1 or c1=-2;
+c1
+select * from t1 where c1 in (-1, -2);
+c1
+drop table t1;
+create table t1 (c1 smallint(5));
+insert into t1 values (1),(2),(3),(4),(5),(-1),(-2);
+select * from t1 where c1 in (18446744073709551615,18446744073709551612);
+c1
+select * from t1 where c1 not in (18446744073709551615,18446744073709551612);
+c1
+1
+2
+3
+4
+5
+-1
+-2
+select c1 from t1 where c1 in (1,3);
+c1
+1
+3
+select c1 from t1 where c1 not in (1,3);
+c1
+2
+4
+5
+-1
+-2
+drop table t1;

--- 1.22/mysql-test/t/func_in.test	2006-09-12 23:18:06 -07:00
+++ 1.23/mysql-test/t/func_in.test	2006-09-12 23:18:06 -07:00
@@ -232,3 +232,21 @@
 select some_id from t1 where some_id not in(-4,-1,-4);
 select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
 drop table t1;
+
+# bug 19342: IN works incorrectly for bigint unsigned values
+create table t1 (c1 bigint unsigned);
+insert into t1 values (0xFFFFFFFFFFFFFFFF);
+select * from t1 where c1=-1 or c1=-2;
+select * from t1 where c1 in (-1, -2);
+drop table t1;
+
+create table t1 (c1 smallint(5));
+insert into t1 values (1),(2),(3),(4),(5),(-1),(-2);
+
+select * from t1 where c1 in (18446744073709551615,18446744073709551612);
+select * from t1 where c1 not in (18446744073709551615,18446744073709551612);
+select c1 from t1 where c1 in (1,3);
+select c1 from t1 where c1 not in (1,3);
+
+drop table t1;
+
Thread
bk commit into 5.0 tree (igreenhoe:1.2272) BUG#19342Ian Greenhoe13 Sep
Re: bk commit into 5.0 tree (igreenhoe:1.2272) BUG#19342Ian Greenhoe15 Sep