=== modified file 'mysql-test/suite/ndb/r/ndb_blob.result'
--- a/mysql-test/suite/ndb/r/ndb_blob.result	2008-05-21 16:43:13 +0000
+++ b/mysql-test/suite/ndb/r/ndb_blob.result	2008-06-03 10:34:58 +0000
@@ -620,3 +620,19 @@
 Level	Code	Message
 drop table t1;
 drop table t2;
+create table t1 (
+a    int primary key,
+giga longblob) 
+engine=ndb;
+set @stuff = '1234567890';
+insert into t1 values (0, repeat(@stuff, 2000));
+select sha1(repeat(@stuff, 2000));
+sha1(repeat(@stuff, 2000))
+c8d94eb4127361ac22cf1c8a8f1178a37fb25e41
+select sha1(giga) from t1;
+sha1(giga)
+c8d94eb4127361ac22cf1c8a8f1178a37fb25e41
+select (giga = repeat(@stuff, 2000)) from t1 where a=0;
+(giga = repeat(@stuff, 2000))
+1
+drop table t1;

=== modified file 'mysql-test/suite/ndb/t/ndb_blob.test'
--- a/mysql-test/suite/ndb/t/ndb_blob.test	2008-05-21 16:43:13 +0000
+++ b/mysql-test/suite/ndb/t/ndb_blob.test	2008-06-03 10:34:58 +0000
@@ -564,3 +564,27 @@
 
 drop table t1;
 drop table t2;
+
+# bug # 31284
+#   Long Blob (8000 byte parts) with Blob v2 (+2 bytes length)
+#   exposed buffer overrun for old Api setValue() call used for
+#   writing parts.
+#   Check that data written into long Blob can be retrieved
+#   correctly
+create table t1 (
+  a    int primary key,
+  giga longblob) 
+engine=ndb;
+
+# length 10
+set @stuff = '1234567890';
+
+# 20,000 bytes = 3 parts
+insert into t1 values (0, repeat(@stuff, 2000));
+
+# Check that we get the same data back that we put in
+select sha1(repeat(@stuff, 2000));
+select sha1(giga) from t1;
+select (giga = repeat(@stuff, 2000)) from t1 where a=0;
+
+drop table t1;

=== modified file 'storage/ndb/include/kernel/signaldata/KeyInfo.hpp'
--- a/storage/ndb/include/kernel/signaldata/KeyInfo.hpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/include/kernel/signaldata/KeyInfo.hpp	2008-06-03 10:00:31 +0000
@@ -37,6 +37,16 @@
   STATIC_CONST( HeaderLength = 3 );
   STATIC_CONST( DataLength = 20 );
   STATIC_CONST( MaxSignalLength = HeaderLength + DataLength );
+  
+  /* IndexBound constants */
+  STATIC_CONST( PerBoundColumnOverhead = 2 );
+  /* Max number of key columns with max total key size */
+  STATIC_CONST( MaxWordsPerBoundRow =   \
+                (PerBoundColumnOverhead * MAX_ATTRIBUTES_IN_INDEX)    \
+                + MAX_KEY_SIZE_IN_WORDS );
+  /* Single key column with max total key size */
+  STATIC_CONST( MaxWordsPerBoundColumn =     \
+                PerBoundColumnOverhead + MAX_KEY_SIZE_IN_WORDS );
 
 private:
   Uint32 connectPtr;

=== modified file 'storage/ndb/src/ndbapi/Ndb.cpp'
--- a/storage/ndb/src/ndbapi/Ndb.cpp	2008-02-20 09:25:11 +0000
+++ b/storage/ndb/src/ndbapi/Ndb.cpp	2008-06-03 10:34:58 +0000
@@ -550,7 +550,8 @@
       Uint32 hashValue;
       {
 	Uint32 buf[4];
-        Uint64 tmp[1000];
+        const Uint32 MaxKeySizeInLongWords= (NDB_MAX_KEY_SIZE + 7) / 8;
+        Uint64 tmp[ MaxKeySizeInLongWords ];
 
         if (keyLen >= sizeof(tmp))
         {

=== modified file 'storage/ndb/src/ndbapi/NdbBlob.cpp'
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp	2008-05-23 10:20:10 +0000
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp	2008-06-03 10:00:31 +0000
@@ -621,7 +621,7 @@
 NdbBlob::copyKeyFromRow(const NdbRecord *record, const char *row,
                         Buf& packedBuf, Buf& unpackedBuf)
 {
-  char buf[256];
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
   DBUG_ENTER("NdbBlob::copyKeyFromRow");
 
   assert(record->flags & NdbRecord::RecHasAllKeys);

=== modified file 'storage/ndb/src/ndbapi/NdbIndexStat.cpp'
--- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp	2008-06-03 10:00:31 +0000
@@ -398,7 +398,7 @@
                              Uint32* keyStatData,
                              Uint32& keyLength)
 {
-  char buf[256]; // For shrinking MySQLD varchars
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
 
   Uint32 key_index= record->key_indexes[ keyPartNum ];
   const NdbRecord::Attr *column= &record->columns[ key_index ];

=== modified file 'storage/ndb/src/ndbapi/NdbOperationDefine.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2008-04-08 13:40:43 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2008-06-03 10:34:58 +0000
@@ -481,7 +481,7 @@
   int tReturnCode;
   Uint32 tAttrId;
   Uint32 tData;
-  Uint32 tempData[2000];
+  Uint32 tempData[ NDB_MAX_TUPLE_SIZE_IN_WORDS ];
   OperationType tOpType = theOperationType;
   OperationStatus tStatus = theStatus;
 
@@ -891,7 +891,9 @@
   DBUG_PRINT("info", ("aLen=%u", (Uint32)aLen));
 
   // wl3717_todo not optimal..
-  Uint64 buf[2048];
+  const Uint32 MaxTupleSizeInLongWords= (NDB_MAX_TUPLE_SIZE + 7)/ 8;
+  Uint64 buf[ MaxTupleSizeInLongWords ];
+  assert( aLen < (NDB_MAX_TUPLE_SIZE - 2) );
   unsigned char* p = (unsigned char*)buf;
   p[0] = (aLen & 0xff);
   p[1] = (aLen >> 8);

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2008-04-08 10:53:06 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2008-06-03 10:34:58 +0000
@@ -618,7 +618,7 @@
 NdbOperation::buildSignalsNdbRecord(Uint32 aTC_ConnectPtr, 
                                     Uint64 aTransId)
 {
-  char buf[256];
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
   Uint32 *keyInfoPtr, *attrInfoPtr;
   Uint32 remain;
   int res;

=== modified file 'storage/ndb/src/ndbapi/NdbOperationInt.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationInt.cpp	2008-05-27 19:50:49 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationInt.cpp	2008-06-03 10:34:58 +0000
@@ -1115,7 +1115,7 @@
 
   m_no_disk_flag &= (col->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
 
-  Uint32 tempData[2000];
+  Uint32 tempData[ NDB_MAX_TUPLE_SIZE_IN_WORDS ];
   if (((UintPtr)val & 3) != 0) {
     memcpy(tempData, val, len);
     val = tempData;

=== modified file 'storage/ndb/src/ndbapi/NdbOperationSearch.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp	2008-04-08 08:31:46 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp	2008-06-03 10:00:31 +0000
@@ -62,7 +62,8 @@
                        (long) aValuePassed));
   
   const char* aValue = aValuePassed;
-  Uint64 tempData[512];
+  const Uint32 MaxKeyLenInLongWords= (NDB_MAX_KEY_SIZE + 7)/8;
+  Uint64 tempData[ MaxKeyLenInLongWords ];
 
   if ((theStatus == OperationDefined) &&
       (aValue != NULL) &&
@@ -465,8 +466,8 @@
 void
 NdbOperation::reorderKEYINFO()
 {
-  Uint32 data[4000];
-  Uint32 size = 4000;
+  Uint32 data[ NDB_MAX_KEYSIZE_IN_WORDS ];
+  Uint32 size = NDB_MAX_KEYSIZE_IN_WORDS;
   getKeyFromTCREQ(data, size);
   Uint32 pos = 1;
   Uint32 k;
@@ -480,7 +481,8 @@
           if (theTupleKeyDefined[j][0] == i) {
             Uint32 off = theTupleKeyDefined[j][1] - 1;
             Uint32 len = theTupleKeyDefined[j][2];
-            assert(off < 4000 && off + len <= 4000);
+            assert(off < NDB_MAX_KEYSIZE_IN_WORDS && 
+                   off + len <= NDB_MAX_KEYSIZE_IN_WORDS);
             int ret = insertKEYINFO((char*)&data[off], pos, len);
             assert(ret == 0);
             pos += len;
@@ -508,11 +510,12 @@
   NdbApiSignal* tSignal = theTCREQ->next();
   unsigned n = 0;
   while (pos < size) {
-    if (n == 20) {
+    if (n == KeyInfo::DataLength) {
       tSignal = tSignal->next();
       n = 0;
     }
-    data[pos++] = tSignal->getDataPtrSend()[3 + n++];
+    data[pos++] = 
+      tSignal->getDataPtrSend()[KeyInfo::HeaderLength + n++];
   }
   return 0;
 }
@@ -538,7 +541,8 @@
     ptrs[0].len = len;
     ptrs[1].ptr = 0;
     
-    Uint64 tmp[1000];
+    const Uint32 MaxKeyLenInLongWords= (NDB_MAX_KEY_SIZE + 7)/ 8; 
+    Uint64 tmp[ MaxKeyLenInLongWords ]; 
     Uint32 hashValue;
     int ret = Ndb::computeHash(&hashValue, 
                                m_currentTable,

=== modified file 'storage/ndb/src/ndbapi/NdbRecord.hpp'
--- a/storage/ndb/src/ndbapi/NdbRecord.hpp	2008-04-04 17:36:54 +0000
+++ b/storage/ndb/src/ndbapi/NdbRecord.hpp	2008-06-03 10:34:58 +0000
@@ -137,6 +137,9 @@
       return (flags & IsNullable) &&
              (row[nullbit_byte_offset] & (1 << nullbit_bit_in_byte));
     }
+
+    /* 255 bytes of data and 1 byte of length */
+    STATIC_CONST( SHRINK_VARCHAR_BUFFSIZE= 256 );
     /*
       Mysqld uses a slightly different format for storing varchar in
       index keys; the length is always two bytes little endian, even
@@ -147,7 +150,7 @@
     {
       const char *p= row + offset;
       Uint32 len= uint2korr(p);
-      if (len >= 256 || len >= maxSize)
+      if (len >= SHRINK_VARCHAR_BUFFSIZE || len >= maxSize)
         return false;
       buf[0]= (unsigned char)len;
       memcpy(buf+1, p+2, len);

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2008-05-27 11:49:46 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2008-06-03 10:34:58 +0000
@@ -597,7 +597,8 @@
                                            const char *row,
                                            Uint32 distkeyMax)
 {
-  Uint64 tmp[1000];
+  const Uint32 MaxKeySizeInLongWords= (NDB_MAX_KEY_SIZE + 7) / 8; 
+  Uint64 tmp[ MaxKeySizeInLongWords ];
   char* tmpshrink = (char*)tmp;
   size_t tmplen = sizeof(tmp);
   
@@ -2865,7 +2866,7 @@
                                               const char *row,
                                               Uint32 bound_type)
 {
-  char buf[256];
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
   Uint32 currLen= theTotalNrOfKeyWordInSignal;
   Uint32 remaining= KeyInfo::DataLength - currLen;
   const NdbRecord::Attr *column= &key_record->columns[column_index];
@@ -2915,7 +2916,10 @@
     theTotalNrOfKeyWordInSignal= currLen + totalLen;
   } else {
     if(!aligned || !nobytes){
-      Uint32 tempData[2000];
+      /* Space for Bound type, Attr header and (possibly max-sized)
+       * key column
+       */
+      Uint32 tempData[ KeyInfo::MaxWordsPerBoundColumn ];
       if (len > sizeof(tempData))
         len= sizeof(tempData);
       tempData[0] = bound_type;



