List:Commits« Previous MessageNext Message »
From:lars-erik.bjork Date:March 23 2009 5:30pm
Subject:bzr commit into mysql-6.0-falcon-team branch (lars-erik.bjork:3069) Bug#40950
View as plain text  
#At file:///home/lb200670/mysql/40950/ based on revid:hky@stripped

 3069 lars-erik.bjork@stripped	2009-03-23
      This is a patch for bug#40950 Falcon indexes broken for unsigned bigint
      
      As explained in the bug report, the problem is that Falcon does not find the value in the index if the sign bit is set. This is because the value is intepreted as negative.
      
      The way I have fixed this is by encoding unsigned bigint (MYSQL_TYPE_LONGLONG) using BigInt instead of int64. I have also changed StorageDatabase::getSegmentValue accordingly to create working index values.
      added:
        mysql-test/suite/falcon/r/falcon_bug_40950.result
        mysql-test/suite/falcon/t/falcon_bug_40950.test
      modified:
        storage/falcon/BigInt.cpp
        storage/falcon/BigInt.h
        storage/falcon/StorageDatabase.cpp
        storage/falcon/Value.cpp
        storage/falcon/ha_falcon.cpp

per-file messages:
  mysql-test/suite/falcon/r/falcon_bug_40950.result
    The expected result of the test
  mysql-test/suite/falcon/t/falcon_bug_40950.test
    A test file testing the patch
  storage/falcon/BigInt.cpp
    Added a method for setting the value of a BigInt from an uint64, changed a call to BigInt::set accordingly
  storage/falcon/BigInt.h
    Added a method for setting the value of a BigInt from an uint64
  storage/falcon/StorageDatabase.cpp
    Altered StorageDatabase::getSegment value to use BigInt in the case of KEY_FORMAT_ULONGLONG
  storage/falcon/Value.cpp
    Specified int64, to use the correct method
  storage/falcon/ha_falcon.cpp
    Changed StorageInterface::encodeRecord to encode unsigned bigint (MYSQL_TYPE_LONGLONG) using BigInt instead of int64. Changed StorageInterface::decodeRecord accoringly.
=== added file 'mysql-test/suite/falcon/r/falcon_bug_40950.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_40950.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_40950.result	2009-03-23 17:30:40 +0000
@@ -0,0 +1,98 @@
+*** Bug #40950 ***
+SET @@storage_engine = 'Falcon';
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (s1 bigint unsigned, key (s1));
+INSERT INTO t1 VALUES (9),(10),(11),(12),(13),(14);
+SELECT * FROM t1;
+s1
+9
+10
+11
+12
+13
+14
+SELECT * FROM t1 WHERE s1 < 1.65025801745927e+19;
+s1
+9
+10
+11
+12
+13
+14
+INSERT INTO t1 VALUES (0x7FFFFFFFFFFFFFFF), (0x8FFFFFFFFFFFFFFF),
+(0xCFFFFFFFFFFFFFFF), (0xFFFFFFFFFFFFFFFF);
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 1;
+hex(s1)
+9
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 2;
+hex(s1)
+9
+A
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 3;
+hex(s1)
+9
+A
+B
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 4;
+hex(s1)
+9
+A
+B
+C
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 5;
+hex(s1)
+9
+A
+B
+C
+D
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 6;
+hex(s1)
+9
+A
+B
+C
+D
+E
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 7;
+hex(s1)
+9
+A
+B
+C
+D
+E
+7FFFFFFFFFFFFFFF
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 8;
+hex(s1)
+9
+A
+B
+C
+D
+E
+7FFFFFFFFFFFFFFF
+8FFFFFFFFFFFFFFF
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 9;
+hex(s1)
+9
+A
+B
+C
+D
+E
+7FFFFFFFFFFFFFFF
+8FFFFFFFFFFFFFFF
+CFFFFFFFFFFFFFFF
+SELECT hex(s1) FROM t1 WHERE s1 > 12;
+hex(s1)
+D
+E
+7FFFFFFFFFFFFFFF
+8FFFFFFFFFFFFFFF
+CFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF
+SELECT count(*) FROM t1;
+count(*)
+10
+DROP TABLE t1;

=== added file 'mysql-test/suite/falcon/t/falcon_bug_40950.test'
--- a/mysql-test/suite/falcon/t/falcon_bug_40950.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_40950.test	2009-03-23 17:30:40 +0000
@@ -0,0 +1,47 @@
+--source include/have_falcon.inc
+
+#
+# Bug #40950: Falcon indexes broken for unsigned bigint
+#
+--echo *** Bug #40950 ***
+
+# ----------------------------------------------------- #
+# --- Initialisation                                --- #
+# ----------------------------------------------------- #
+let $engine = 'Falcon';
+eval SET @@storage_engine = $engine;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+# ----------------------------------------------------- #
+# --- Test                                          --- #
+# ----------------------------------------------------- #
+
+CREATE TABLE t1 (s1 bigint unsigned, key (s1));
+INSERT INTO t1 VALUES (9),(10),(11),(12),(13),(14);
+SELECT * FROM t1;
+SELECT * FROM t1 WHERE s1 < 1.65025801745927e+19;
+INSERT INTO t1 VALUES (0x7FFFFFFFFFFFFFFF), (0x8FFFFFFFFFFFFFFF),
+(0xCFFFFFFFFFFFFFFF), (0xFFFFFFFFFFFFFFFF);
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 1;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 2;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 3;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 4;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 5;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 6;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 7;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 8;
+SELECT hex(s1) FROM t1 ORDER BY s1 LIMIT 9;
+SELECT hex(s1) FROM t1 WHERE s1 > 12;
+
+# ----------------------------------------------------- #
+# --- Check                                         --- #
+# ----------------------------------------------------- #
+SELECT count(*) FROM t1;
+
+# ----------------------------------------------------- #
+# --- Final cleanup                                 --- #
+# ----------------------------------------------------- #
+DROP TABLE t1;

=== modified file 'storage/falcon/BigInt.cpp'
--- a/storage/falcon/BigInt.cpp	2007-09-24 10:56:44 +0000
+++ b/storage/falcon/BigInt.cpp	2009-03-23 17:30:40 +0000
@@ -112,6 +112,22 @@ void BigInt::set(int64 value, int valueS
 		}
 }
 
+void BigInt::set(uint64 value, int valueScale)
+{
+	scale = valueScale;
+	neg = false;
+	length = 0;
+
+	if (value)
+		{
+		words[length++] = LOW_WORD(value);
+		BigWord highWord = HIGH_WORD(value);
+
+		if (highWord)
+			words[length++] = highWord;
+		}
+}
+
 void BigInt::subtract(int index, BigWord value)
 {
 	while (value)
@@ -728,7 +744,7 @@ int BigInt::divide(const BigInt* dividen
 void BigInt::buildPowerTable()
 	{
 	BigInt* bigInt = ::new BigInt;
-	bigInt->set(powersOfTen[9], 0);
+	bigInt->set((int64)powersOfTen[9], 0);
 	powerTable[9] = bigInt;
 
 	for (int i = 10; i < maxPowerOfTen; i++)

=== modified file 'storage/falcon/BigInt.h'
--- a/storage/falcon/BigInt.h	2007-09-20 15:44:25 +0000
+++ b/storage/falcon/BigInt.h	2009-03-23 17:30:40 +0000
@@ -62,6 +62,7 @@ public:
 	void			subtract(int index, BigWord value);
 	
 	void			set(int64 value, int scale=0);
+	void			set(uint64 value, int scale=0);
 	void			set(BigInt *bigInt);
 	void			setString(int stringLength, const char* str);
 	void			getString(int bufferLength, char* buffer);

=== modified file 'storage/falcon/StorageDatabase.cpp'
--- a/storage/falcon/StorageDatabase.cpp	2009-03-10 08:33:34 +0000
+++ b/storage/falcon/StorageDatabase.cpp	2009-03-23 17:30:40 +0000
@@ -1004,6 +1004,24 @@ int StorageDatabase::getSegmentValue(Sto
 			break;
 
 		case KEY_FORMAT_ULONGLONG:
+			{
+			uint64 temp = (uint64)
+				((uint64)(((uint32) ((UCHAR) ptr[0])) +
+					(((uint32) ((UCHAR) ptr[1])) << 8) +
+					(((uint32) ((UCHAR) ptr[2])) << 16) +
+					(((uint32) ((UCHAR) ptr[3])) << 24)) +
+				(((uint64)(((uint32) ((UCHAR) ptr[4])) +
+					(((uint32) ((UCHAR) ptr[5])) << 8) +
+					(((uint32) ((UCHAR) ptr[6])) << 16) +
+					(((uint32) ((UCHAR) ptr[7])) << 24)))
+				<< 32));
+
+			BigInt bigInt;
+			bigInt.set(temp);
+			value->setValue(&bigInt);
+			}
+			break;
+
 		case KEY_FORMAT_LONGLONG:
 			{
 			int64 temp = (int64)

=== modified file 'storage/falcon/Value.cpp'
--- a/storage/falcon/Value.cpp	2008-11-24 08:56:29 +0000
+++ b/storage/falcon/Value.cpp	2009-03-23 17:30:40 +0000
@@ -1853,11 +1853,11 @@ void Value::getBigInt(BigInt *bigInt)
 			break;
 
 		case Short:
-			bigInt->set(data.smallInt, -scale);
+			bigInt->set((int64)data.smallInt, -scale);
 			break;
 
 		case Int32:
-			bigInt->set(data.integer, -scale);
+			bigInt->set((int64)data.integer, -scale);
 			break;
 
 		case Int64:

=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp	2009-03-10 12:37:26 +0000
+++ b/storage/falcon/ha_falcon.cpp	2009-03-23 17:30:40 +0000
@@ -3001,7 +3001,6 @@ void StorageInterface::encodeRecord(ucha
 				case MYSQL_TYPE_SHORT:
 				case MYSQL_TYPE_INT24:
 				case MYSQL_TYPE_LONG:
-				case MYSQL_TYPE_LONGLONG:
 				case MYSQL_TYPE_DECIMAL:
 				case MYSQL_TYPE_ENUM:
 				case MYSQL_TYPE_SET:
@@ -3009,6 +3008,28 @@ void StorageInterface::encodeRecord(ucha
 					dataStream->encodeInt64(field->val_int());
 					break;
 
+				case MYSQL_TYPE_LONGLONG:
+					{
+
+					int64 temp = field->val_int();
+
+					// If this is unsigned, encode it as a BigInt 
+					// to support values with the MSB set
+
+					if (((Field_num*)field)->unsigned_flag)
+						{
+						BigInt bigInt;
+						bigInt.set((uint64)temp);
+						dataStream->encodeBigInt(&bigInt);
+						}
+					else
+						{
+						dataStream->encodeInt64(temp);
+						}
+
+					}
+					break;
+
 				case MYSQL_TYPE_YEAR:
 					// Have to use the ptr directly to get the same number for
 					// both two and four digit YEAR
@@ -3207,7 +3228,6 @@ void StorageInterface::decodeRecord(ucha
 				case MYSQL_TYPE_SHORT:
 				case MYSQL_TYPE_INT24:
 				case MYSQL_TYPE_LONG:
-				case MYSQL_TYPE_LONGLONG:
 				case MYSQL_TYPE_DECIMAL:
 				case MYSQL_TYPE_ENUM:
 				case MYSQL_TYPE_SET:
@@ -3216,6 +3236,25 @@ void StorageInterface::decodeRecord(ucha
 								((Field_num*)field)->unsigned_flag);
 					break;
 
+				case MYSQL_TYPE_LONGLONG:
+					{
+
+					// This value is unsigned and has been handled 
+					// specially in encodeRecord() to support values 
+					// with the MSB set.
+					if (dataStream->type == edsTypeBigInt)
+						{
+						int64 value = dataStream->bigInt.getInt();
+						field->store(value, ((Field_num*)field)->unsigned_flag);
+						}
+					else
+						{
+						field->store(dataStream->getInt64(),
+									 ((Field_num*)field)->unsigned_flag);
+						}
+					}
+					break;
+
 				case MYSQL_TYPE_YEAR:
 					// Must add 1900 to give Field_year::store the value it
 					// expects. See also case 'MYSQL_TYPE_YEAR' in encodeRecord()

Thread
bzr commit into mysql-6.0-falcon-team branch (lars-erik.bjork:3069) Bug#40950lars-erik.bjork23 Mar