diff --git a/storage/ndb/include/ndbapi/NdbBlob.hpp b/storage/ndb/include/ndbapi/NdbBlob.hpp
index 92265b4feef36031532e0fad873e33b8b1a87b38..9ae0ba6f02369ad2a44df11603f2f8580c7bfbfe 100644
--- a/storage/ndb/include/ndbapi/NdbBlob.hpp
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp
@@ -292,6 +292,7 @@ private:
   };
   Buf theKeyBuf;
   Buf theAccessKeyBuf;
+  Buf thePackKeyBuf;
   Buf theHeadInlineBuf;
   Buf theHeadInlineCopyBuf;     // for writeTuple
   Buf thePartBuf;
@@ -328,6 +329,9 @@ private:
   Uint32 getPartNumber(Uint64 pos);
   Uint32 getPartCount();
   Uint32 getDistKey(Uint32 part);
+  // pack / unpack
+  int packKeyValue(const NdbTableImpl* aTable, const Buf& srcBuf);
+  int unpackKeyValue(const NdbTableImpl* aTable, Buf& dstBuf);
   // getters and setters
   int getTableKeyValue(NdbOperation* anOp);
   int setTableKeyValue(NdbOperation* anOp);
diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp
index c403b2c3438f706922ccf592a4985af5cee79090..3a442c94253a5f467190fb24546863f330333268 100644
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp
@@ -881,7 +881,7 @@ protected:
   Uint32 ptr2int() { return theReceiver.getId(); };
 
   // get table or index key from prepared signals
-  int getKeyFromTCREQ(Uint32* data, unsigned size);
+  int getKeyFromTCREQ(Uint32* data, Uint32 & size);
 
 /******************************************************************************
  * These are the private variables that are defined in the operation objects.
diff --git a/storage/ndb/include/ndbapi/NdbScanOperation.hpp b/storage/ndb/include/ndbapi/NdbScanOperation.hpp
index 103eabbe1a22f09bf0b3f3007627a4a24ff66acc..048e7a0c9523767fce154461b25720b8e4cf1d88 100644
--- a/storage/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/storage/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -240,7 +240,7 @@ protected:
   void receiver_completed(NdbReceiver*);
   void execCLOSE_SCAN_REP();
 
-  int getKeyFromKEYINFO20(Uint32* data, unsigned size);
+  int getKeyFromKEYINFO20(Uint32* data, Uint32 & size);
   NdbOperation*	takeOverScanOp(OperationType opType, NdbTransaction*);
   
   bool m_ordered;
diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp
index 663d346c8efdd255be27c4051a6f27497c61bc2b..680f9e5c70eba1865d99be39f2766b0c51877f24 100644
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp
@@ -310,7 +310,7 @@ NdbBlob::Buf::alloc(unsigned n)
 void
 NdbBlob::Buf::copyfrom(const NdbBlob::Buf& src)
 {
-  assert(size == src.size);
+  size = src.size;
   memcpy(data, src.data, size);
 }
 
@@ -408,6 +408,75 @@ NdbBlob::getDistKey(Uint32 part)
   return (part / theStripeSize) % theStripeSize;
 }
 
+// pack/unpack table/index key  XXX support routines, shortcuts
+
+int
+NdbBlob::packKeyValue(const NdbTableImpl* aTable, const Buf& srcBuf)
+{
+  DBUG_ENTER("NdbBlob::packKeyValue");
+  const Uint32* data = (const Uint32*)srcBuf.data;
+  unsigned pos = 0;
+  Uint32* pack_data = (Uint32*)thePackKeyBuf.data;
+  unsigned pack_pos = 0;
+  for (unsigned i = 0; i < aTable->m_columns.size(); i++) {
+    NdbColumnImpl* c = aTable->m_columns[i];
+    assert(c != NULL);
+    if (c->m_pk) {
+      unsigned len = c->m_attrSize * c->m_arraySize;
+      Uint32 pack_len;
+      bool ok = c->get_var_length(&data[pos], pack_len);
+      if (! ok) {
+        setErrorCode(NdbBlobImpl::ErrCorruptPK);
+        DBUG_RETURN(-1);
+      }
+      memcpy(&pack_data[pack_pos], &data[pos], pack_len);
+      while (pack_len % 4 != 0) {
+        char* p = (char*)&pack_data[pack_pos] + pack_len++;
+        *p = 0;
+      }
+      pos += (len + 3) / 4;
+      pack_pos += pack_len / 4;
+    }
+  }
+  assert(4 * pos == srcBuf.size);
+  assert(4 * pack_pos <= thePackKeyBuf.maxsize);
+  thePackKeyBuf.size = 4 * pack_pos;
+  DBUG_RETURN(0);
+}
+
+int
+NdbBlob::unpackKeyValue(const NdbTableImpl* aTable, Buf& dstBuf)
+{
+  DBUG_ENTER("NdbBlob::unpackKeyValue");
+  Uint32* data = (Uint32*)dstBuf.data;
+  unsigned pos = 0;
+  const Uint32* pack_data = (const Uint32*)thePackKeyBuf.data;
+  unsigned pack_pos = 0;
+  for (unsigned i = 0; i < aTable->m_columns.size(); i++) {
+    NdbColumnImpl* c = aTable->m_columns[i];
+    assert(c != NULL);
+    if (c->m_pk) {
+      unsigned len = c->m_attrSize * c->m_arraySize;
+      Uint32 pack_len;
+      bool ok = c->get_var_length(&pack_data[pack_pos], pack_len);
+      if (! ok) {
+        setErrorCode(NdbBlobImpl::ErrCorruptPK);
+        DBUG_RETURN(-1);
+      }
+      memcpy(&data[pos], &pack_data[pack_pos], pack_len);
+      while (pack_len % 4 != 0) {
+        char* p = (char*)&data[pos] + pack_len++;
+        *p = 0;
+      }
+      pos += (len + 3) / 4;
+      pack_pos += pack_len / 4;
+    }
+  }
+  assert(4 * pos == dstBuf.size);
+  assert(4 * pack_pos == thePackKeyBuf.size);
+  DBUG_RETURN(0);
+}
+
 // getters and setters
 
 int
@@ -489,12 +558,10 @@ int
 NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
 {
   DBUG_ENTER("NdbBlob::setPartKeyValue");
-  DBUG_PRINT("info", ("dist=%u part=%u key=", getDistKey(part), part));
-  DBUG_DUMP("info", theKeyBuf.data, 4 * theTable->m_keyLenInWords);
-  //Uint32* data = (Uint32*)theKeyBuf.data;
-  //unsigned size = theTable->m_keyLenInWords;
+  DBUG_PRINT("info", ("dist=%u part=%u packkey=", getDistKey(part), part));
+  DBUG_DUMP("info", thePackKeyBuf.data, 4 * thePackKeyBuf.size);
   // TODO use attr ids after compatibility with 4.1.7 not needed
-  if (anOp->equal("PK", theKeyBuf.data) == -1 ||
+  if (anOp->equal("PK", thePackKeyBuf.data) == -1 ||
       anOp->equal("DIST", getDistKey(part)) == -1 ||
       anOp->equal("PART", part) == -1) {
     setErrorCode(anOp);
@@ -1242,21 +1309,27 @@ NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl
   if (isKeyOp()) {
     if (isTableOp()) {
       // get table key
-      Uint32* data = (Uint32*)theKeyBuf.data;
-      unsigned size = theTable->m_keyLenInWords;
+      Uint32* data = (Uint32*)thePackKeyBuf.data;
+      Uint32 size = theTable->m_keyLenInWords; // in-out
       if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
         setErrorCode(NdbBlobImpl::ErrUsage);
         DBUG_RETURN(-1);
       }
+      thePackKeyBuf.size = 4 * size;
+      if (unpackKeyValue(theTable, theKeyBuf) == -1)
+        DBUG_RETURN(-1);
     }
     if (isIndexOp()) {
       // get index key
-      Uint32* data = (Uint32*)theAccessKeyBuf.data;
-      unsigned size = theAccessTable->m_keyLenInWords;
+      Uint32* data = (Uint32*)thePackKeyBuf.data;
+      Uint32 size = theAccessTable->m_keyLenInWords; // in-out
       if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
         setErrorCode(NdbBlobImpl::ErrUsage);
         DBUG_RETURN(-1);
       }
+      thePackKeyBuf.size = 4 * size;
+      if (unpackKeyValue(theAccessTable, theAccessKeyBuf) == -1)
+        DBUG_RETURN(-1);
     }
     if (isReadOp()) {
       // add read of head+inline in this op
@@ -1303,6 +1376,7 @@ NdbBlob::atPrepare(NdbEventOperationImpl* anOp, NdbEventOperationImpl* aBlobOp,
   theEventOp = anOp;
   theBlobEventOp = aBlobOp;
   theTable = anOp->m_eventImpl->m_tableImpl;
+  theAccessTable = theTable;
   theColumn = aColumn;
   // prepare blob column and table
   if (prepareColumn() == -1)
@@ -1321,7 +1395,7 @@ NdbBlob::atPrepare(NdbEventOperationImpl* anOp, NdbEventOperationImpl* aBlobOp,
   if (theBlobEventOp != NULL) {
     if ((theBlobEventPkRecAttr =
            theBlobEventOp->getValue(theBlobTable->getColumn((Uint32)0),
-                                    theKeyBuf.data, version)) == NULL ||
+                                    thePackKeyBuf.data, version)) == NULL ||
         (theBlobEventDistRecAttr =
            theBlobEventOp->getValue(theBlobTable->getColumn((Uint32)1),
                                     (char*)0, version)) == NULL ||
@@ -1380,6 +1454,7 @@ NdbBlob::prepareColumn()
   }
   // these buffers are always used
   theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+  thePackKeyBuf.alloc(max(theTable->m_keyLenInWords, theAccessTable->m_keyLenInWords) << 2);
   theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
   theHead = (Head*)theHeadInlineBuf.data;
   theInlineData = theHeadInlineBuf.data + sizeof(Head);
@@ -1464,7 +1539,7 @@ NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch)
         if (tOp == NULL ||
             tOp->readTuple() == -1 ||
             setAccessKeyValue(tOp) == -1 ||
-            tOp->getValue(pkAttrId, theKeyBuf.data) == NULL) {
+            tOp->getValue(pkAttrId, thePackKeyBuf.data) == NULL) {
           setErrorCode(tOp);
           DBUG_RETURN(-1);
         }
@@ -1553,10 +1628,12 @@ NdbBlob::postExecute(NdbTransaction::ExecType anExecType)
   assert(isKeyOp());
   if (isIndexOp()) {
     NdbBlob* tFirstBlob = theNdbOp->theBlobList;
-    if (this != tFirstBlob) {
+    if (this == tFirstBlob) {
+      packKeyValue(theTable, theKeyBuf);
+    } else {
       // copy key from first blob
-      assert(theKeyBuf.size == tFirstBlob->theKeyBuf.size);
-      memcpy(theKeyBuf.data, tFirstBlob->theKeyBuf.data, tFirstBlob->theKeyBuf.size);
+      theKeyBuf.copyfrom(tFirstBlob->theKeyBuf);
+      thePackKeyBuf.copyfrom(tFirstBlob->thePackKeyBuf);
     }
   }
   if (isReadOp()) {
@@ -1710,12 +1787,16 @@ NdbBlob::atNextResult()
     DBUG_RETURN(-1);
   assert(isScanOp());
   // get primary key
-  { Uint32* data = (Uint32*)theKeyBuf.data;
-    unsigned size = theTable->m_keyLenInWords;
-    if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
+  { NdbScanOperation* tScanOp = (NdbScanOperation*)theNdbOp;
+    Uint32* data = (Uint32*)thePackKeyBuf.data;
+    unsigned size = theTable->m_keyLenInWords; // in-out
+    if (tScanOp->getKeyFromKEYINFO20(data, size) == -1) {
       setErrorCode(NdbBlobImpl::ErrUsage);
       DBUG_RETURN(-1);
     }
+    thePackKeyBuf.size = 4 * size;
+    if (unpackKeyValue(theTable, theKeyBuf) == -1)
+      DBUG_RETURN(-1);
   }
   getHeadFromRecAttr();
   if (setPos(0) == -1)
diff --git a/storage/ndb/src/ndbapi/NdbBlobImpl.hpp b/storage/ndb/src/ndbapi/NdbBlobImpl.hpp
index 0030e910c52ed6b5a64ccc24f59eb910595b7f92..e6b41c964e64ff9034ac4be7c31dc254466982f4 100644
--- a/storage/ndb/src/ndbapi/NdbBlobImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbBlobImpl.hpp
@@ -34,6 +34,8 @@ public:
   STATIC_CONST( ErrAbort = 4268 );
   // "Unknown blob error"
   STATIC_CONST( ErrUnknown = 4269 );
+  // "Corrupted main table PK in blob operation"
+  STATIC_CONST( ErrCorruptPK = 4274 );
 };
 
 #endif
diff --git a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp
index f2d0d1079a0d9ce022219fa52f1b2b1c5ad7146f..cea8eff94122f2966944eb5f22e0d6244e776eb4 100644
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -472,7 +472,8 @@ void
 NdbOperation::reorderKEYINFO()
 {
   Uint32 data[4000];
-  getKeyFromTCREQ(data, 4000);
+  Uint32 size = 4000;
+  getKeyFromTCREQ(data, size);
   Uint32 pos = 1;
   Uint32 k;
   for (k = 0; k < m_accessTable->m_noOfKeys; k++) {
@@ -501,7 +502,7 @@ NdbOperation::reorderKEYINFO()
 }
 
 int
-NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
+NdbOperation::getKeyFromTCREQ(Uint32* data, Uint32 & size)
 {
   assert(size >= theTupKeyLen && theTupKeyLen > 0);
   size = theTupKeyLen;
diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp
index a03dd6c536f44bda6b740206cdcc033ee4b0b250..5931a00fcf7998fc057f4b0a042df4084e18b2fe 100644
--- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -199,7 +199,7 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
       out << hex << "H'" << r.u_32_value() << dec;
       break;
     case NdbDictionary::Column::Unsigned:
-      out << r.u_32_value();
+      out << *((Uint32*)r.aRef() + j);
       break;
     case NdbDictionary::Column::Smallunsigned:
       out << r.u_short_value();
diff --git a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
index 9e6ff352987c3688c2b3a2a81a5923b37c3a8d3e..08cd275d4a887e93f856ab62f229bb480a0bb0cd 100644
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -912,13 +912,20 @@ NdbScanOperation::doSendScan(int aProcessorId)
  *     the scan process. 
  ****************************************************************************/
 int
-NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
+NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, Uint32 & size)
 {
   NdbRecAttr * tRecAttr = m_curr_row;
   if(tRecAttr)
   {
     const Uint32 * src = (Uint32*)tRecAttr->aRef();
-    memcpy(data, src, 4*size);
+
+    assert(tRecAttr->get_size_in_bytes() > 0);
+    assert(tRecAttr->get_size_in_bytes() < 65536);
+    const Uint32 len = (tRecAttr->get_size_in_bytes() + 3)/4-1;
+
+    assert(size >= len);
+    memcpy(data, src, 4*len);
+    size = len;
     return 0;
   }
   return -1;
diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c
index bb4616a9ee2895823a6822a9dc935e17adabbe6c..9bc9fd4242e76a023a591043557fe44af0ed56cf 100644
--- a/storage/ndb/src/ndbapi/ndberror.c
+++ b/storage/ndb/src/ndbapi/ndberror.c
@@ -599,7 +599,8 @@ ErrorBundle ErrorCodes[] = {
   { 4336, DMEC, AE, "Auto-increment value set below current value" },
   { 4271, DMEC, AE, "Invalid index object, not retrieved via getIndex()" },
   { 4272, DMEC, AE, "Table definition has undefined column" },
-  { 4273, DMEC, IE, "No blob table in dict cache" }
+  { 4273, DMEC, IE, "No blob table in dict cache" },
+  { 4274, DMEC, IE, "Corrupted main table PK in blob operation" }
 };
 
 static
diff --git a/storage/ndb/test/ndbapi/testBlobs.cpp b/storage/ndb/test/ndbapi/testBlobs.cpp
index fff5ac247dfdc06880ea19423409673ccc7cffa0..a1b0c89652e29948e34490cf437751ae7b21e11e 100644
--- a/storage/ndb/test/ndbapi/testBlobs.cpp
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp
@@ -223,7 +223,7 @@ dropTable()
 {
   NdbDictionary::Table tab(g_opt.m_tname);
   if (g_dic->getTable(g_opt.m_tname) != 0)
-    CHK(g_dic->dropTable(tab) == 0);
+    CHK(g_dic->dropTable(g_opt.m_tname) == 0);
   return 0;
 }