From: Date: June 20 2007 4:43am Subject: bk commit into 6.0-falcon tree (chris:1.2580) BUG#28725 List-Archive: http://lists.mysql.com/commits/29144 X-Bug: 28725 Message-Id: <20070620024320.C39401D89C@terrazzo.site> Below is the list of changes that have just been committed into a local 6.0-falcon repository of chris. When chris 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, 2007-06-19 21:43:12-05:00, chris@stripped +3 -0 Bug#28725 "Falcon: crash with decimal" - Always store BigInt numbers having a scale > 18 as an array of uint32. Bug#29201 "decimal(20,20) has rounding error - Added 64-bit casts to BigInt::divide to avoid bitshift overflows. storage/falcon/BigInt.cpp@stripped, 2007-06-19 21:43:10-05:00, chris@stripped +19 -8 BigInt::divide() - Handle cases where divisor is physically larger than dividend - Added uint64 casts for bit shift operations to avoid overflow - Added uint32 cases to remove compiler warngings storage/falcon/ScaledBinary.cpp@stripped, 2007-06-19 21:43:10-05:00, chris@stripped +5 -2 putBigInt() - Only store BigInts within int64 if scale is < 19 storage/falcon/ha_falcon.cpp@stripped, 2007-06-19 21:43:10-05:00, chris@stripped +4 -2 StorageInterface::encodeRecord() - Handle BigInts as int64 only if scale < 19 # 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: chris # Host: terrazzo.site # Root: /home/chris/work/dev/dev-9/mysql-5.1-falcon --- 1.13/storage/falcon/BigInt.cpp 2007-06-19 07:57:04 -05:00 +++ 1.14/storage/falcon/BigInt.cpp 2007-06-19 21:43:10 -05:00 @@ -302,7 +302,7 @@ if (delta == 0) return *result; - if (delta > 9) //cwp handle <= 9 + if (delta > 9) { *result = divide(powerTable[delta]); return *result; @@ -521,9 +521,20 @@ BigInt quotient; BigInt remainder; - divide(this, divisor, "ient, &remainder); - memcpy(this->words, quotient.words, sizeof(this->words)); - this->length = quotient.length; + // If the divisor is larger than the dividend (this), then set the quotient + // to 0 return the dividend as the remainder. + + if (divisor->length > length) + { + remainder = *this; + clear(); + } + else + { + divide(this, divisor, "ient, &remainder); + memcpy(this->words, quotient.words, sizeof(this->words)); + this->length = quotient.length; + } return(remainder); } @@ -588,15 +599,15 @@ vn = (uint32 *)malloc(4*n); for (i = n - 1; i > 0; i--) - vn[i] = (v[i] << s) | (v[i-1] >> (MPBASE-s)); + vn[i] = (v[i] << s) | (uint32)(((uint64)v[i-1]) >> (MPBASE-s)); vn[0] = v[0] << s; un = (uint32 *)malloc(4*(m+1)); - un[m] = u[m-1] >> (MPBASE-s); + un[m] = (uint32)(((uint64)u[m-1]) >> (MPBASE-s)); for (i = m - 1; i > 0; i--) - un[i] = (u[i] << s) | (u[i-1] >> (MPBASE-s)); + un[i] = (u[i] << s) | (uint32)(((uint64)u[i-1]) >> (MPBASE-s)); un[0] = u[0] << s; @@ -673,7 +684,7 @@ if (r != NULL) { for (i = 0; i < n; i++) - r[i] = (un[i] >> s) | (un[i+1] << (MPBASE-s)); + r[i] = (un[i] >> s) | (uint32)(((uint64)un[i+1]) << (MPBASE-s)); } // Take a best guess at the quotient length, adjust as necessary --- 1.12/storage/falcon/ScaledBinary.cpp 2007-06-18 18:13:06 -05:00 +++ 1.13/storage/falcon/ScaledBinary.cpp 2007-06-19 21:43:10 -05:00 @@ -282,7 +282,10 @@ void ScaledBinary::putBigInt(BigInt *bigInt, char* ptr, int precision, int scale) { - if (bigInt->fitsInInt64()) + // Handle value as int64 if possible, although even if the number fits + // an int64, it can only be scaled within 18 digits or less. + + if (bigInt->fitsInInt64() && scale < 19) { if (scale == -bigInt->scale) { @@ -340,7 +343,7 @@ // Isolate the trailing partial digits (< 9) - uint32 partial = bigFraction.divide(powersOfTen[partialDigits]); + uint32 partial = (uint32)bigFraction.divide(powersOfTen[partialDigits]); // Store each 9-digit group, descale by 10^9 for each --- 1.189/storage/falcon/ha_falcon.cpp 2007-06-18 06:30:42 -05:00 +++ 1.190/storage/falcon/ha_falcon.cpp 2007-06-19 21:43:10 -05:00 @@ -96,7 +96,6 @@ { if (falcon_log_file) fclose(falcon_log_file); - falcon_log_file = fopen(file, "a"); } @@ -1980,7 +1979,10 @@ BigInt bigInt; ScaledBinary::getBigIntFromBinaryDecimal((const char*) field->ptr, precision, scale, &bigInt); - if (bigInt.fitsInInt64()) + // Handle value as int64 if possible. Even if the number fits + // an int64, it can only be scaled within 18 digits or less. + + if (bigInt.fitsInInt64() && scale < 19) { int64 value = bigInt.getInt(); storageTable->dataStream.encodeInt64(value, scale);