diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp
index 2029b16197e..ca70b8c62a9 100644
--- a/ndb/include/kernel/signaldata/ScanTab.hpp
+++ b/ndb/include/kernel/signaldata/ScanTab.hpp
@@ -65,7 +65,12 @@ private:
   UintR buddyConPtr;          // DATA 8
   UintR batch_byte_size;      // DATA 9
   UintR first_batch_size;     // DATA 10
-  
+
+  /**
+   * Optional
+   */
+  Uint32 distributionKey;
+
   /**
    * Get:ers for requestInfo
    */
@@ -76,6 +81,7 @@ private:
   static Uint8 getRangeScanFlag(const UintR & requestInfo);
   static Uint8 getKeyinfoFlag(const UintR & requestInfo);
   static Uint16 getScanBatch(const UintR & requestInfo);
+  static Uint8 getDistributionKeyFlag(const UintR & requestInfo);
 
   /**
    * Set:ers for requestInfo
@@ -88,6 +94,7 @@ private:
   static void setRangeScanFlag(UintR & requestInfo, Uint32 flag);
   static void setKeyinfoFlag(UintR & requestInfo, Uint32 flag);
   static void setScanBatch(Uint32& requestInfo, Uint32 sz);
+  static void setDistributionKeyFlag(Uint32& requestInfo, Uint32 flag);
 };
 
 /**
@@ -100,6 +107,7 @@ private:
  k = Keyinfo               - 1  Bit 12
  x = Range Scan (TUX)      - 1  Bit 15
  b = Scan batch            - 10 Bit 16-25 (max 1023)
+ d = Distribution key flag
 
            1111111111222222222233
  01234567890123456789012345678901
@@ -127,6 +135,8 @@ private:
 #define SCAN_BATCH_SHIFT (16)
 #define SCAN_BATCH_MASK  (1023)
 
+#define SCAN_DISTR_KEY_SHIFT (26)
+
 inline
 Uint8
 ScanTabReq::getParallelism(const UintR & requestInfo){
@@ -225,6 +235,18 @@ ScanTabReq::setKeyinfoFlag(UintR & requestInfo, Uint32 flag){
   requestInfo |= (flag << KEYINFO_SHIFT);
 }
 
+inline
+Uint8
+ScanTabReq::getDistributionKeyFlag(const UintR & requestInfo){
+  return (Uint8)((requestInfo >> SCAN_DISTR_KEY_SHIFT) & 1);
+}
+
+inline
+void 
+ScanTabReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
+  ASSERT_BOOL(flag, "ScanTabReq::setKeyinfoFlag");
+  requestInfo |= (flag << SCAN_DISTR_KEY_SHIFT);
+}
 
 /**
  * 
diff --git a/ndb/include/kernel/signaldata/TcIndx.hpp b/ndb/include/kernel/signaldata/TcIndx.hpp
index 764d4e9fcd7..f82cd95878e 100644
--- a/ndb/include/kernel/signaldata/TcIndx.hpp
+++ b/ndb/include/kernel/signaldata/TcIndx.hpp
@@ -18,379 +18,7 @@
 #define TC_INDX_H
 
 #include "SignalData.hpp"
-
-class TcIndxReq {
-  /**
-   * Reciver(s)
-   */
-  friend class Dbtc;         // Reciver
-
-  /**
-   * Sender(s)
-   */
-  friend class NdbIndexOperation; 
-
-  /**
-   * For printing
-   */
-  friend bool printTCINDXREQ(FILE *, const Uint32 *, Uint32, Uint16);
-
-public:
-  /**
-   * Length of signal
-   */
-  STATIC_CONST( StaticLength = 8 );
-  STATIC_CONST( SignalLength = 25 );
-  STATIC_CONST( MaxKeyInfo = 8 );
-  STATIC_CONST( MaxAttrInfo = 5 );
-
-private:
-
-  enum CommitType {
-    CommitIfFailFree = 0,
-    TryCommit = 1,
-    CommitAsMuchAsPossible = 2
-  };
-
-  /**
-   * DATA VARIABLES
-   */
-//-------------------------------------------------------------
-// Unconditional part. First 8 words
-//-------------------------------------------------------------
-  UintR apiConnectPtr;        // DATA 0
-  UintR senderData;           // DATA 1
-  UintR attrLen;              // DATA 2 (including API Version)
-  UintR indexId;              // DATA 3
-  UintR requestInfo;          // DATA 4
-  UintR indexSchemaVersion;   // DATA 5
-  UintR transId1;             // DATA 6
-  UintR transId2;             // DATA 7
-//-------------------------------------------------------------
-// Conditional part. Those four words will be sent only if their
-// indicator is set.
-//-------------------------------------------------------------
-  UintR scanInfo;             // DATA 8
-  UintR distrGroupHashValue;  // DATA 9
-  UintR distributionKeySize;  // DATA 10
-  UintR storedProcId;         // DATA 11
-
-//-------------------------------------------------------------
-// Variable sized key and attrinfo part. Those will be placed to
-// pack the signal in an appropriate manner.
-//-------------------------------------------------------------
-  UintR keyInfo[MaxKeyInfo];           // DATA 12 - 19
-  UintR attrInfo[MaxAttrInfo];         // DATA 20 - 24
-
-  static Uint8  getAPIVersion(const UintR & attrLen);
-
-  /**
-   * Get:ers for requestInfo
-   */
-  static Uint8 getCommitFlag(const UintR & requestInfo);
-  static Uint8 getCommitType(const UintR & requestInfo);
-  static Uint8 getStartFlag(const UintR & requestInfo);
-  static Uint8 getSimpleFlag(const UintR & requestInfo);
-  static Uint8 getDirtyFlag(const UintR & requestInfo);
-  static Uint8 getInterpretedFlag(const UintR & requestInfo);
-  static Uint8 getDistributionGroupFlag(const UintR & requestInfo);
-  static Uint8 getDistributionGroupTypeFlag(const UintR & requestInfo);
-  static Uint8 getDistributionKeyFlag(const UintR & requestInfo);
-  static Uint8 getScanIndFlag(const UintR & requestInfo);
-  
-  static Uint8 getOperationType(const UintR & requestInfo);
-
-  static Uint16 getIndexLength(const UintR & requestInfo);
-  static Uint8  getAIInTcIndxReq(const UintR & requestInfo);
-
-  /**
-   * Get:ers for scanInfo
-   */
-
-  static void setAPIVersion(UintR & attrLen, Uint16 apiVersion);
-
-  /**
-   * Set:ers for requestInfo
-   */
-  static void clearRequestInfo(UintR & requestInfo);
-  static void setCommitType(UintR & requestInfo, Uint32 type);
-  static void setCommitFlag(UintR & requestInfo, Uint32 flag);
-  static void setStartFlag(UintR & requestInfo, Uint32 flag);
-  static void setSimpleFlag(UintR & requestInfo, Uint32 flag);
-  static void setDirtyFlag(UintR & requestInfo, Uint32 flag);
-  static void setInterpretedFlag(UintR & requestInfo, Uint32 flag);
-  static void setDistributionGroupFlag(UintR & requestInfo, Uint32 flag);
-  static void setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag);
-  static void setDistributionKeyFlag(UintR & requestInfo, Uint32 flag);
-  static void setScanIndFlag(UintR & requestInfo, Uint32 flag);
-  
-  static void setOperationType(UintR & requestInfo, Uint32 type);
-  
-  static void setIndexLength(UintR & requestInfo, Uint32 len);
-  static void setAIInTcIndxReq(UintR & requestInfo, Uint32 len);
-
-  /**
-   * Set:ers for scanInfo
-   */
-
-};
-
-#define API_VER_NO_SHIFT     (16)
-#define API_VER_NO_MASK      (65535)
-
-/**
- * Request Info
- *
- a = Attr Info in TCINDXREQ - 3  Bits -> Max 7 (Bit 16-18)
- b = Distribution Key Ind   - 1  Bit 2
- c = Commit Indicator       - 1  Bit 4
- d = Dirty Indicator        - 1  Bit 0
- e = Scan Indicator         - 1  Bit 14
- g = Distribution Group Ind - 1  Bit 1
- i = Interpreted Indicator  - 1  Bit 15
- k = Index lengt            - 12 Bits -> Max 4095 (Bit 20 - 31)
- o = Operation Type         - 3  Bits -> Max 7 (Bit 5-7)
- p = Simple Indicator       - 1  Bit 8
- s = Start Indicator        - 1  Bit 11
- t = Distribution GroupType - 1  Bit 3
- y = Commit Type            - 2  Bit 12-13
- x = Last Op in execute     - 1  Bit 19
-
-           1111111111222222222233
- 01234567890123456789012345678901
- dgbtcooop  syyeiaaa-kkkkkkkkkkkk
-*/
-
-#define COMMIT_SHIFT       (4)
-#define START_SHIFT        (11)
-#define SIMPLE_SHIFT       (8)
-#define DIRTY_SHIFT        (0)
-#define INTERPRETED_SHIFT  (15)
-#define DISTR_GROUP_SHIFT  (1)
-#define DISTR_GROUP_TYPE_SHIFT  (3)
-#define DISTR_KEY_SHIFT    (2)
-#define SCAN_SHIFT         (14)
-
-#define OPERATION_SHIFT   (5)
-#define OPERATION_MASK    (7)
-
-#define AINFO_SHIFT       (16)
-#define AINFO_MASK        (7)
-
-#define INDEX_LEN_SHIFT     (20)
-#define INDEX_LEN_MASK      (4095)
-
-#define COMMIT_TYPE_SHIFT  (12)
-#define COMMIT_TYPE_MASK   (3)
-
-#define LAST_OP_IN_EXEC_SHIFT (19)
-
-/**
- * Scan Info
- *
- 
-
-           1111111111222222222233
- 01234567890123456789012345678901
- 
-*/
-
-inline
-Uint8
-TcIndxReq::getCommitFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> COMMIT_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getCommitType(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> COMMIT_TYPE_SHIFT) & COMMIT_TYPE_MASK);
-}
-
-inline
-Uint8
-TcIndxReq::getStartFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> START_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getSimpleFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> SIMPLE_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDirtyFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> DIRTY_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getInterpretedFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> INTERPRETED_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionGroupFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> DISTR_GROUP_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionGroupTypeFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> DISTR_GROUP_TYPE_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionKeyFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> DISTR_KEY_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getScanIndFlag(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> SCAN_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getOperationType(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> OPERATION_SHIFT) & OPERATION_MASK);
-}
-
-inline
-Uint16 
-TcIndxReq::getIndexLength(const UintR & requestInfo){
-  return (Uint16)((requestInfo >> INDEX_LEN_SHIFT) & INDEX_LEN_MASK);
-}
-
-inline
-Uint8
-TcIndxReq::getAIInTcIndxReq(const UintR & requestInfo){
-  return (Uint8)((requestInfo >> AINFO_SHIFT) & AINFO_MASK);
-}
-
-inline
-void 
-TcIndxReq::clearRequestInfo(UintR & requestInfo){
-  requestInfo = 0;
-}
-
-inline
-void 
-TcIndxReq::setCommitType(UintR & requestInfo, Uint32 type){
-  ASSERT_MAX(type, COMMIT_TYPE_MASK, "TcIndxReq::setCommitType");
-  requestInfo |= (type << COMMIT_TYPE_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setCommitFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setCommitFlag");
-  requestInfo &= ~(1 << COMMIT_SHIFT);
-  requestInfo |= (flag << COMMIT_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setStartFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setStartFlag");
-  requestInfo &= ~(1 << START_SHIFT);
-  requestInfo |= (flag << START_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setSimpleFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setSimpleFlag");
-  requestInfo &= ~(1 << SIMPLE_SHIFT);
-  requestInfo |= (flag << SIMPLE_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setDirtyFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setDirtyFlag");
-  requestInfo &= ~(1 << DIRTY_SHIFT);
-  requestInfo |= (flag << DIRTY_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setInterpretedFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setInterpretedFlag");
-  requestInfo &= ~(1 << INTERPRETED_SHIFT);
-  requestInfo |= (flag << INTERPRETED_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setDistributionGroupTypeFlag");
-  requestInfo &= ~(1 << DISTR_GROUP_TYPE_SHIFT);
-  requestInfo |= (flag << DISTR_GROUP_TYPE_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setDistributionGroupFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setDistributionGroupFlag");
-  requestInfo &= ~(1 << DISTR_GROUP_SHIFT);
-  requestInfo |= (flag << DISTR_GROUP_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setDistributionKeyFlag");
-  requestInfo &= ~(1 << DISTR_KEY_SHIFT);
-  requestInfo |= (flag << DISTR_KEY_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setScanIndFlag(UintR & requestInfo, Uint32 flag){
-  ASSERT_BOOL(flag, "TcIndxReq::setScanIndFlag");
-  requestInfo &= ~(1 << SCAN_SHIFT);
-  requestInfo |= (flag << SCAN_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setOperationType(UintR & requestInfo, Uint32 type){
-  ASSERT_MAX(type, OPERATION_MASK, "TcIndxReq::setOperationType");
-  requestInfo |= (type << OPERATION_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setIndexLength(UintR & requestInfo, Uint32 len){
-  ASSERT_MAX(len, INDEX_LEN_MASK, "TcIndxReq::setKeyLength");
-  requestInfo |= (len << INDEX_LEN_SHIFT);
-}
-
-inline
-void 
-TcIndxReq::setAIInTcIndxReq(UintR & requestInfo, Uint32 len){
-  ASSERT_MAX(len, AINFO_MASK, "TcIndxReq::setAIInTcIndxReq");
-  requestInfo |= (len << AINFO_SHIFT);
-}
-
-inline
-Uint8 
-TcIndxReq::getAPIVersion(const UintR & anAttrLen){
-  return (Uint16)((anAttrLen >> API_VER_NO_SHIFT) & API_VER_NO_MASK);
-}
-
-inline
-void
-TcIndxReq::setAPIVersion(UintR & anAttrLen, Uint16 apiVersion){
-//  ASSERT_MAX(apiVersion, API_VER_NO_MASK, "TcIndxReq::setAPIVersion");
-  anAttrLen |= (apiVersion << API_VER_NO_SHIFT);
-}
+#include "TcKeyReq.hpp"
 
 class TcIndxConf {
 
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index 51a6895648f..0444b565a16 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -371,16 +371,6 @@ public:
     /** @} *******************************************************************/
     
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-    void setTupleKey(bool);
-    bool getTupleKey() const;
-    
-    void setDistributionGroup(bool, int bits = 16);
-    bool getDistributionGroup() const;
-    int getDistributionGroupBits() const;
-    
-    void setIndexOnlyStorage(bool);
-    bool getIndexOnlyStorage() const;
-
     const Table * getBlobTable() const;
 
     /** 
diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp
index 7612fe54d1b..830a6237e31 100644
--- a/ndb/include/ndbapi/NdbIndexOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexOperation.hpp
@@ -173,29 +173,17 @@ private:
   NdbIndexOperation(Ndb* aNdb);
   ~NdbIndexOperation();
 
-  void closeScan();
-
   int receiveTCINDXREF(NdbApiSignal* aSignal);
 
-  // Overloaded method from NdbOperation
-  void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag);
-
-  // Overloaded methods from NdbCursorOperation
-  int executeCursor(int ProcessorId);
-
   // Overloaded methods from NdbCursorOperation
   int indxInit(const class NdbIndexImpl* anIndex,
 	       const class NdbTableImpl* aTable, 
 	       NdbConnection* myConnection);
 
-  int equal_impl(const class NdbColumnImpl*, const char* aValue, Uint32 len);
   int prepareSend(Uint32  TC_ConnectPtr, Uint64  TransactionId);
 
   // Private attributes
   const NdbIndexImpl* m_theIndex;
-  Uint32 m_theIndexDefined[NDB_MAX_ATTRIBUTES_IN_INDEX][3];
-  Uint32 m_theIndexLen;	  	 // Length of the index in words
-  Uint32 m_theNoOfIndexDefined;  // The number of index attributes
 };
 
 #endif
diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp
index 8e0294e41e6..23ca32cab37 100644
--- a/ndb/include/ndbapi/NdbOperation.hpp
+++ b/ndb/include/ndbapi/NdbOperation.hpp
@@ -719,6 +719,15 @@ public:
 
   LockMode getLockMode() const { return theLockMode; }
 
+  /**
+   * Set/get distribution/partition key
+   */
+  void setPartitionId(Uint32 id);
+  void setPartitionHash(Uint32 key);
+  void setPartitionHash(const Uint64 *, Uint32 len);
+  Uint32 getPartitionId() const;
+protected:
+  int handle_distribution_key(const Uint64 *, Uint32 len);
 protected:
 /******************************************************************************
  * These are the methods used to create and delete the NdbOperation objects.
@@ -810,13 +819,12 @@ protected:
   int branch_col_null(Uint32 type, Uint32 col, Uint32 Label);
   
   // Handle ATTRINFO signals   
-  int 	      insertATTRINFO(Uint32 aData);
-  int         insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
-
-  int 	      insertKEYINFO(const char* aValue,	
-			    Uint32 aStartPosition,	
-			    Uint32 aKeyLenInByte,	
-			    Uint32 anAttrBitsInLastWord);
+  int insertATTRINFO(Uint32 aData);
+  int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
+  
+  int insertKEYINFO(const char* aValue,	
+		    Uint32 aStartPosition,	
+		    Uint32 aKeyLenInByte);
   
   virtual void setErrorCode(int aErrorCode);
   virtual void setErrorCodeAbort(int aErrorCode);
@@ -850,14 +858,18 @@ protected:
   Ndb*		   theNdb;	      	// Point back to the Ndb object.
   NdbConnection*   theNdbCon;	       	// Point back to the connection object.
   NdbOperation*	   theNext;	       	// Next pointer to operation.
-  NdbApiSignal*	   theTCREQ;		// The TC[KEY/INDX]REQ signal object
+
+  union {
+    NdbApiSignal* theTCREQ;		// The TC[KEY/INDX]REQ signal object
+    NdbApiSignal* theSCAN_TABREQ;
+  };
+
   NdbApiSignal*	   theFirstATTRINFO;	// The first ATTRINFO signal object 
   NdbApiSignal*	   theCurrentATTRINFO;	// The current ATTRINFO signal object  
   Uint32	   theTotalCurrAI_Len;	// The total number of attribute info
   		      			// words currently defined    
   Uint32	   theAI_LenInCurrAI;	// The number of words defined in the
 		      		     	// current ATTRINFO signal
-  NdbApiSignal*	   theFirstKEYINFO;	// The first KEYINFO signal object 
   NdbApiSignal*	   theLastKEYINFO;	// The first KEYINFO signal object 
 
   class NdbLabel*	    theFirstLabel;
@@ -874,8 +886,8 @@ protected:
   Uint32*           theKEYINFOptr;       // Pointer to where to write KEYINFO
   Uint32*           theATTRINFOptr;      // Pointer to where to write ATTRINFO
 
-  const class NdbTableImpl* m_currentTable;      // The current table
-  const class NdbTableImpl* m_accessTable;
+  const class NdbTableImpl* m_currentTable; // The current table
+  const class NdbTableImpl* m_accessTable;  // Index table (== current for pk)
 
   // Set to TRUE when a tuple key attribute has been defined. 
   Uint32	    theTupleKeyDefined[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY][3];
@@ -883,18 +895,18 @@ protected:
   Uint32	    theTotalNrOfKeyWordInSignal;     // The total number of
   						     // keyword in signal.
 
-  Uint32	    theTupKeyLen;	   // Length of the tuple key in words
-  Uint32	    theNoOfTupKeyDefined;  // The number of tuple key attributes
-		       			   // currently defined   
-  OperationType	  theOperationType;        // Read Request, Update Req......   
-
+  Uint32	    theTupKeyLen;	// Length of the tuple key in words
+		       		        // left until done
+  Uint8	theNoOfTupKeyLeft;  // The number of tuple key attributes
+  OperationType	theOperationType;        // Read Request, Update Req......   
+  
   LockMode        theLockMode;	   // Can be set to WRITE if read operation 
   OperationStatus theStatus;	   // The status of the operation.	
+  
   Uint32         theMagicNumber;  // Magic number to verify that object 
                                    // is correct
   Uint32 theScanInfo;      	   // Scan info bits (take over flag etc)
-  Uint32 theDistrKeySize;         // Distribution Key size if used
-  Uint32 theDistributionGroup;    // Distribution Group if used
+  Uint32 theDistributionKey;       // Distribution Key size if used
 
   Uint32 theSubroutineSize;	   // Size of subroutines for interpretation
   Uint32 theInitialReadSize;	   // Size of initial reads for interpretation
@@ -902,14 +914,12 @@ protected:
   Uint32 theFinalUpdateSize;	   // Size of final updates for interpretation
   Uint32 theFinalReadSize;	   // Size of final reads for interpretation
 
-  Uint8  theStartIndicator;	   // Indicator of whether start operation
-  Uint8  theCommitIndicator;	   // Indicator of whether commit operation
-  Uint8  theSimpleIndicator;	   // Indicator of whether simple operation
-  Uint8  theDirtyIndicator;	   // Indicator of whether dirty operation
-  Uint8  theInterpretIndicator;   // Indicator of whether interpreted operation
-  Uint8  theDistrGroupIndicator;  // Indicates whether distribution grp is used
-  Uint8  theDistrGroupType;       // Type of distribution group used
-  Uint8  theDistrKeyIndicator;    // Indicates whether distr. key is used
+  Uint8  theStartIndicator;	 // Indicator of whether start operation
+  Uint8  theCommitIndicator;	 // Indicator of whether commit operation
+  Uint8  theSimpleIndicator;	 // Indicator of whether simple operation
+  Uint8  theDirtyIndicator;	 // Indicator of whether dirty operation
+  Uint8  theInterpretIndicator;  // Indicator of whether interpreted operation
+  Int8  theDistrKeyIndicator_;    // Indicates whether distr. key is used
 
   Uint16 m_tcReqGSN;
   Uint16 m_keyInfoGSN;
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index 2e4d173ac75..81d0839ad8a 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -114,7 +114,6 @@ protected:
   // Scan related variables
   Uint32 theParallelism;
   Uint32 m_keyInfo;
-  NdbApiSignal* theSCAN_TABREQ;
 
   int getFirstATTRINFOScan();
   int doSendScan(int ProcessorId);
diff --git a/ndb/include/util/md5_hash.hpp b/ndb/include/util/md5_hash.hpp
index 4c3cf239881..b79dce3b5a9 100644
--- a/ndb/include/util/md5_hash.hpp
+++ b/ndb/include/util/md5_hash.hpp
@@ -20,6 +20,15 @@
 #include <ndb_types.h>
 
 // External declaration of hash function 
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words);
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words);
+
+inline
+Uint32
+md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+{
+  Uint32 result[4];
+  md5_hash(result, keybuf, no_of_32_words);
+  return result[0];
+}
 
 #endif
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index 3314f0bd097..8be576aa735 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -138,14 +138,10 @@ SignalDataPrintFunctions[] = {
   { GSN_ALTER_INDX_REQ, printALTER_INDX_REQ },
   { GSN_ALTER_INDX_CONF, printALTER_INDX_CONF },
   { GSN_ALTER_INDX_REF, printALTER_INDX_REF },
-  { GSN_TCINDXREQ, printTCINDXREQ },
   { GSN_TCINDXCONF, printTCINDXCONF },
   { GSN_TCINDXREF, printTCINDXREF },
   { GSN_INDXKEYINFO, printINDXKEYINFO },
   { GSN_INDXATTRINFO, printINDXATTRINFO },
-  //{ GSN_TCINDXNEXTREQ, printTCINDXNEXTREQ },
-  //{ GSN_TCINDEXNEXTCONF, printTCINDEXNEXTCONF },
-  //{ GSN_TCINDEXNEXREF, printTCINDEXNEXREF },
   { GSN_FSAPPENDREQ, printFSAPPENDREQ },
   { GSN_BACKUP_REQ,             printBACKUP_REQ },
   { GSN_BACKUP_DATA,            printBACKUP_DATA },
diff --git a/ndb/src/common/debugger/signaldata/TcIndx.cpp b/ndb/src/common/debugger/signaldata/TcIndx.cpp
index 6bfa29eff15..b0578f5b646 100644
--- a/ndb/src/common/debugger/signaldata/TcIndx.cpp
+++ b/ndb/src/common/debugger/signaldata/TcIndx.cpp
@@ -18,91 +18,6 @@
 #include <signaldata/TcKeyReq.hpp>
 #include <BlockNumbers.h>
 
-bool
-printTCINDXREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
-  
-  const TcIndxReq * const sig = (TcIndxReq *) theData;
-  
-  UintR requestInfo = sig->requestInfo;
-  UintR scanInfo    = sig->scanInfo;
-
-  fprintf(output, " apiConnectPtr: H\'%.8x, senderData: H\'%.8x\n", 
-	  sig->apiConnectPtr, sig->senderData);
- 
-  fprintf(output, " Operation: %s, Flags: ", 
-	  sig->getOperationType(requestInfo) == ZREAD    ? "Read" :
-	  sig->getOperationType(requestInfo) == ZREAD_EX ? "Read-Ex" :
-	  sig->getOperationType(requestInfo) == ZUPDATE  ? "Update" :
-	  sig->getOperationType(requestInfo) == ZINSERT  ? "Insert" :
-	  sig->getOperationType(requestInfo) == ZDELETE  ? "Delete" :
-	  sig->getOperationType(requestInfo) == ZWRITE   ? "Write" :
-	  "Unknown");
-
-  {
-    if(sig->getDirtyFlag(requestInfo)){
-      fprintf(output, "Dirty ");
-    }    
-    if(sig->getStartFlag(requestInfo)){
-      fprintf(output, "Start ");
-    }    
-    if (TcKeyReq::getExecuteFlag(sig->requestInfo)) {
-      fprintf(output, "Execute ");
-    }
-    if(sig->getCommitFlag(requestInfo)){
-      fprintf(output, "Commit, Type = ");
-      UintR TcommitType = sig->getCommitType(requestInfo);
-      if (TcommitType == TcIndxReq::CommitIfFailFree) {
-	fprintf(output, "FailFree ");
-      } else if (TcommitType == TcIndxReq::TryCommit) {
-        fprintf(output, "TryCommit ");
-      } else if (TcommitType == TcIndxReq::CommitAsMuchAsPossible) {
-	fprintf(output, "Always ");
-      }//if
-    }    
-    if(sig->getSimpleFlag(requestInfo)){
-      fprintf(output, "Simple ");
-    }   
-    if(sig->getInterpretedFlag(requestInfo)){
-      fprintf(output, "Interpreted ");
-    }
-    if(sig->getDistributionGroupFlag(requestInfo)){
-      fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
-    }
-    if(sig->getDistributionKeyFlag(sig->requestInfo)){
-      fprintf(output, "DKey = %d ", sig->distributionKeySize);
-    }
-    fprintf(output, "\n");
-  }
-  
-  const int indexLen     = sig->getIndexLength(requestInfo);
-  const int attrInThis = sig->getAIInTcIndxReq(requestInfo);
-  fprintf(output, 
-	  " indexLen: %d, attrLen: %d, AI in this: %d, indexId: %d, "
-	  "indexSchemaVer: %d, API Ver: %d\n",
-	  indexLen, sig->attrLen, attrInThis, 
-	  sig->indexId, sig->indexSchemaVersion, sig->getAPIVersion(scanInfo));
-    
-  fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n -- Variable Data --\n", 
-	  sig->transId1, sig->transId2);
-  
-  Uint32 restLen = (len - 8);
-  const Uint32 * rest = &sig->scanInfo;
-  while(restLen >= 7){
-    fprintf(output, 
-	    " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
-	    rest[0], rest[1], rest[2], rest[3], 
-	    rest[4], rest[5], rest[6]);
-    restLen -= 7;
-    rest += 7;
-  }
-  if(restLen > 0){
-    for(Uint32 i = 0; i<restLen; i++)
-      fprintf(output, " H\'%.8x", rest[i]);
-    fprintf(output, "\n");
-  }
-  
-  return true;
-}
 
 bool
 printTCINDXCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
diff --git a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
index 7304872ff9c..3918bd5db26 100644
--- a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
+++ b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
@@ -68,11 +68,8 @@ printTCKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiver
     if(sig->getInterpretedFlag(requestInfo)){
       fprintf(output, "Interpreted ");
     }
-    if(sig->getDistributionGroupFlag(requestInfo)){
-      fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
-    }
     if(sig->getDistributionKeyFlag(sig->requestInfo)){
-      fprintf(output, "DKey = %d ", sig->distributionKeySize);
+      fprintf(output, " d-key");
     }
     fprintf(output, "\n");
   }
diff --git a/ndb/src/common/util/md5_hash.cpp b/ndb/src/common/util/md5_hash.cpp
index 068843183ac..d4eedbc40fb 100644
--- a/ndb/src/common/util/md5_hash.cpp
+++ b/ndb/src/common/util/md5_hash.cpp
@@ -75,7 +75,7 @@ void byteReverse(unsigned char *buf, unsigned longs)
  * reflect the addition of 16 longwords of new data.  MD5Update blocks
  * the data and converts bytes into longwords for this routine.
  */
-void MD5Transform(Uint32 buf[4], Uint32 const in[16])
+static void MD5Transform(Uint32 buf[4], Uint32 const in[16])
 {
     register Uint32 a, b, c, d;
 
@@ -162,13 +162,13 @@ void MD5Transform(Uint32 buf[4], Uint32 const in[16])
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
  */
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words)
 {
-/*
- * This is the external interface of the module
- * It is assumed that keybuf is placed on 8 byte
- * alignment.
- */
+  /**
+   * This is the external interface of the module
+   * It is assumed that keybuf is placed on 8 byte
+   * alignment.
+   */
   Uint32 i;
   Uint32 buf[4];
   Uint64 transform64_buf[8];
@@ -230,6 +230,10 @@ Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
     byteReverse((unsigned char *)transform32_buf, 16);
     MD5Transform(buf, transform32_buf);    
   }
-  return buf[0];
+
+  result[0] = buf[0];
+  result[1] = buf[1];
+  result[2] = buf[2];
+  result[3] = buf[3];
 }
 
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index 9a1bbd86562..6810b426b04 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -9255,7 +9255,7 @@ void Dbacc::initFragAdd(Signal* signal,
   }//if
   regFragPtr.p->fragState = ACTIVEFRAG;
   // NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
-  regFragPtr.p->myfid = (rootFragIndex << (lhFragBits - 1)) | req->fragId;
+  regFragPtr.p->myfid = (req->fragId << 1) | rootFragIndex;
   regFragPtr.p->myroot = rootIndex;
   regFragPtr.p->myTableId = req->tableId;
   ndbrequire(req->kValue == 6);
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index d1a8128ea7f..76347d7d684 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -4097,8 +4097,8 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
     req->maxLoadFactor = tabPtr.p->maxLoadFactor;
     req->minLoadFactor = tabPtr.p->minLoadFactor;
     req->kValue = tabPtr.p->kValue;
-    req->lh3DistrBits = lhDistrBits;
-    req->lh3PageBits = lhPageBits;
+    req->lh3DistrBits = 0; //lhDistrBits;
+    req->lh3PageBits = 0; //lhPageBits;
     req->noOfAttributes = tabPtr.p->noOfAttributes;
     req->noOfNullAttributes = tabPtr.p->noOfNullAttr;
     req->noOfPagesToPreAllocate = 0;
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 76aa745c3e0..83ab897d0c3 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -6852,8 +6852,7 @@ void Dbdih::execDIGETNODESREQ(Signal* signal)
   TabRecord* regTabDesc = tabRecord;
   jamEntry();
   ptrCheckGuard(tabPtr, ttabFileSize, regTabDesc);
-  hashValue = hashValue >> tabPtr.p->kvalue;
-  Uint32 fragId = tabPtr.p->mask & hashValue;
+  Uint32 fragId = hashValue & tabPtr.p->mask;
   ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
   if (fragId < tabPtr.p->hashpointer) {
     jam();
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index d6987f3e478..ef35cecb2b1 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -861,10 +861,6 @@ public:
      *       heard of.
      */
     Uint8 fragDistributionKey;
-    /**
-     *       Used to calculate which local fragment to use.                  
-     */
-    Uint8 hashCheckBit;
     /**
      *       The identity of the next local checkpoint this fragment
      *       should perform.
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index cd15ad0c3b2..a6d9061cba4 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -1078,8 +1078,8 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
   if (DictTabInfo::isOrderedIndex(tableType)) {
     jam();
     // NOTE: next 2 lines stolen from ACC
-    addfragptr.p->fragid1 = (0 << tlhstar) | fragId;
-    addfragptr.p->fragid2 = (1 << tlhstar) | fragId;
+    addfragptr.p->fragid1 = (fragId << 1) | 0;
+    addfragptr.p->fragid2 = (fragId << 1) | 1;
     addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
     sendAddFragReq(signal);
     return;
@@ -1099,7 +1099,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
   Uint32 fragId2 = signal->theData[3];
   Uint32 accFragPtr1 = signal->theData[4];
   Uint32 accFragPtr2 = signal->theData[5];
-  Uint32 hashCheckBit = signal->theData[6];
   ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
   ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
 
@@ -1110,7 +1109,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   fragptr.p->accFragptr[0] = accFragPtr1;
   fragptr.p->accFragptr[1] = accFragPtr2;
-  fragptr.p->hashCheckBit = hashCheckBit;
 
   addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
   sendAddFragReq(signal);
@@ -1268,7 +1266,7 @@ Dblqh::sendAddFragReq(Signal* signal)
       tuxreq->noOfAttr = addfragptr.p->noOfAttr - 1; /* skip NDB$TNODE */
       tuxreq->fragId =
         addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX
-        ? addfragptr.p->fragid1 : addfragptr.p->fragid2;
+        ? addfragptr.p->fragid1: addfragptr.p->fragid2;
       tuxreq->fragOff = addfragptr.p->lh3DistrBits;
       tuxreq->tableType = addfragptr.p->tableType;
       tuxreq->primaryTableId = addfragptr.p->primaryTableId;
@@ -3420,7 +3418,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
     LQHKEY_error(signal, 6);
     return;
   }//if
-  regTcPtr->localFragptr = (regTcPtr->hashValue >> fragptr.p->hashCheckBit) & 1;
+  regTcPtr->localFragptr = regTcPtr->hashValue & 1;
   Uint8 TcopyType = fragptr.p->fragCopy;
   tfragDistKey = fragptr.p->fragDistributionKey;
   if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
@@ -8023,13 +8021,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   if (! scanptr.p->rangeScan) {
     tableRef = tcConnectptr.p->tableref;
-    if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
-      jam();
-      tupFragPtr = fragptr.p->tupFragptr[0];
-    } else {
-      jam();
-      tupFragPtr = fragptr.p->tupFragptr[1];
-    }//if
+    tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
   } else {
     jam();
     // for ordered index use primary table
@@ -8037,13 +8029,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
     tFragPtr.i = fragptr.p->tableFragptr;
     ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
     tableRef = tFragPtr.p->tabRef;
-    if (tFragPtr.p->fragId == scanptr.p->scanLocalFragid) {
-      jam();
-      tupFragPtr = tFragPtr.p->tupFragptr[0];
-    } else {
-      jam();
-      tupFragPtr = tFragPtr.p->tupFragptr[1];
-    }//if
+    tupFragPtr = tFragPtr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
   }
   {
     jam();
@@ -9122,13 +9108,7 @@ void Dblqh::copySendTupkeyReqLab(Signal* signal)
   scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
   fragptr.i = tcConnectptr.p->fragmentptr;
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
-  if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
-    jam();
-    tupFragPtr = fragptr.p->tupFragptr[0];
-  } else {
-    jam();
-    tupFragPtr = fragptr.p->tupFragptr[1];
-  }//if
+  tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
   {
     TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend(); 
 
@@ -13390,7 +13370,6 @@ void Dblqh::execSR_FRAGIDCONF(Signal* signal)
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   fragptr.p->accFragptr[0] = srFragidConf->fragPtr[0];
   fragptr.p->accFragptr[1] = srFragidConf->fragPtr[1];
-  fragptr.p->hashCheckBit = srFragidConf->hashCheckBit;
   Uint32 noLocFrag = srFragidConf->noLocFrag;
   ndbrequire(noLocFrag == 2);
   Uint32 fragid[2];
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index a209df24c44..41f35152127 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -561,7 +561,7 @@ public:
     Uint32 expectedTransIdAI;
     AttributeBuffer transIdAI; // For accumulating TransId_AI
     
-    TcIndxReq tcIndxReq;
+    TcKeyReq tcIndxReq;
     UintR connectionIndex;
     UintR indexReadTcConnect; //
     
@@ -897,11 +897,11 @@ public:
     UintR  hashValue;    /* THE HASH VALUE USED TO LOCATE FRAGMENT       */
     
     Uint8  distributionKeyIndicator;
-    Uint8  distributionGroupIndicator;
-    Uint8  distributionGroupType;
+    Uint8  unused1;
+    Uint8  unused2;
     Uint8  lenAiInTckeyreq;  /* LENGTH OF ATTRIBUTE INFORMATION IN TCKEYREQ */
 
-    Uint8  distributionKey;
+    Uint8  fragmentDistributionKey;  /* DIH generation no */
 
     /**
      * EXECUTION MODE OF OPERATION                    
@@ -925,9 +925,9 @@ public:
     // Second 16 byte cache line in second 64 byte cache
     // line. Diverse use.
     //---------------------------------------------------
-    UintR  distributionGroup;
+    UintR  distributionKey;
     UintR  nextCacheRec;
-    UintR  distributionKeySize;
+    UintR  unused3;
     Uint32 scanInfo;
     
     //---------------------------------------------------
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index d8b3ee10532..b9c553bb805 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -2250,29 +2250,17 @@ void Dbtc::hash(Signal* signal)
       ti += 4;
     }//while
   }//if
-  UintR ThashValue;
-  UintR TdistrHashValue;
-  ThashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)regCachePtr->keylen);
+  Uint32 tmp[4];
+  md5_hash(tmp, (Uint64*)&Tdata32[0], (UintR)regCachePtr->keylen);
 
-  if (regCachePtr->distributionGroupIndicator == 1) {
-    if (regCachePtr->distributionGroupType == 1) {
-      jam();
-      TdistrHashValue = (regCachePtr->distributionGroup << 6);
-    } else {
-      jam();
-      Tdata32[0] = regCachePtr->distributionGroup;
-      TdistrHashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)1);
-    }//if
-  } else if (regCachePtr->distributionKeyIndicator == 1) {
+  thashValue = tmp[0];
+  if (regCachePtr->distributionKeyIndicator == 1) {
     jam();
-    TdistrHashValue = md5_hash((Uint64*)&Tdata32[0], 
-                               (UintR)regCachePtr->distributionKeySize);
+    tdistrHashValue = regCachePtr->distributionKey;
   } else {
     jam();
-    TdistrHashValue = ThashValue;
+    tdistrHashValue = tmp[1];
   }//if
-  thashValue = ThashValue;
-  tdistrHashValue = TdistrHashValue;
 }//Dbtc::hash()
 
 /*
@@ -2666,18 +2654,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
   Uint8 TSimpleFlag         = tcKeyReq->getSimpleFlag(Treqinfo);
   Uint8 TDirtyFlag          = tcKeyReq->getDirtyFlag(Treqinfo);
   Uint8 TInterpretedFlag    = tcKeyReq->getInterpretedFlag(Treqinfo);
-  Uint8 TDistrGroupFlag     = tcKeyReq->getDistributionGroupFlag(Treqinfo);
-  Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
   Uint8 TDistrKeyFlag       = tcKeyReq->getDistributionKeyFlag(Treqinfo);
   Uint8 TexecuteFlag        = TexecFlag;
   
   regCachePtr->opSimple = TSimpleFlag;
   regCachePtr->opExec   = TInterpretedFlag;
   regTcPtr->dirtyOp  = TDirtyFlag;
-
-  regCachePtr->distributionGroupIndicator = TDistrGroupFlag;
-  regCachePtr->distributionGroupType      = TDistrGroupTypeFlag;
-  regCachePtr->distributionKeyIndicator   = TDistrKeyFlag;
+  regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
 
   //-------------------------------------------------------------
   // The next step is to read the upto three conditional words.
@@ -2686,7 +2669,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
   Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
   {
     Uint32  TDistrGHIndex    = tcKeyReq->getScanIndFlag(Treqinfo);
-    Uint32  TDistrKeyIndex   = TDistrGHIndex + TDistrGroupFlag;
+    Uint32  TDistrKeyIndex   = TDistrGHIndex;
 
     Uint32 TscanNode = tcKeyReq->getTakeOverScanNode(TOptionalDataPtr[0]);
     Uint32 TscanInfo = tcKeyReq->getTakeOverScanInfo(TOptionalDataPtr[0]);
@@ -2695,8 +2678,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
     regCachePtr->scanNode = TscanNode;
     regCachePtr->scanInfo = TscanInfo;
 
-    regCachePtr->distributionGroup   = TOptionalDataPtr[TDistrGHIndex];
-    regCachePtr->distributionKeySize = TOptionalDataPtr[TDistrKeyIndex];
+    regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
 
     TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
   }
@@ -2957,7 +2939,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
   tnoOfBackup = tnodeinfo & 3;
   tnoOfStandby = (tnodeinfo >> 8) & 3;
  
-  regCachePtr->distributionKey = (tnodeinfo >> 16) & 255;
+  regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
   if (Toperation == ZREAD) {
     if (Tdirty == 1) {
       jam();
@@ -3127,7 +3109,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
   /* ---------------------------------------------------------------------- */
   // Bit16 == 0 since StoredProcedures are not yet supported.
   /* ---------------------------------------------------------------------- */
-  LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->distributionKey);
+  LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
   LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
 
   Tdata10 = 0;
@@ -8477,7 +8459,7 @@ void Dbtc::systemErrorLab(Signal* signal)
 void Dbtc::execSCAN_TABREQ(Signal* signal) 
 {
   const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
-  const Uint32 reqinfo = scanTabReq->requestInfo;
+  const Uint32 ri = scanTabReq->requestInfo;
   const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
   const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
   const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
@@ -8487,8 +8469,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
   const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
   Uint32 currSavePointId = 0;
   
-  Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo);
-  Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo);
+  Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
+  Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
   Uint32 scanParallel = scanConcurrency;
   Uint32 errCode;
   ScanRecordPtr scanptr;
@@ -8563,6 +8545,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
   seizeCacheRecord(signal);
   cachePtr.p->keylen = keyLen;
   cachePtr.p->save1 = 0;
+  cachePtr.p->distributionKey = scanTabReq->distributionKey;
+  cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
   scanptr = seizeScanrec(signal);
 
   ndbrequire(transP->apiScanRec == RNIL);
@@ -8639,6 +8623,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
 		       UintR scanParallel,
 		       UintR noOprecPerFrag) 
 {
+  const UintR ri = scanTabReq->requestInfo;
   scanptr.p->scanTcrec = tcConnectptr.i;
   scanptr.p->scanApiRec = apiConnectptr.i;
   scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
@@ -8651,7 +8636,6 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
   scanptr.p->batch_byte_size= scanTabReq->batch_byte_size;
 
   Uint32 tmp = 0;
-  const UintR ri = scanTabReq->requestInfo;
   ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
   ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
   ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
@@ -8767,14 +8751,42 @@ void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
     return;
   }
 
+  scanptr.p->scanNextFragId = 0;
   scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
-  /*************************************************
-   * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED. 
-   * WE MUST FIRST GET THE NUMBER OF  FRAGMENTS IN THE TABLE.
-   ***************************************************/
-  signal->theData[0] = tcConnectptr.p->dihConnectptr;
-  signal->theData[1] = scanptr.p->scanTableref;
-  sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+  
+  if(!cachePtr.p->distributionKeyIndicator)
+  {
+    jam();
+    /*************************************************
+     * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED. 
+     * WE MUST FIRST GET THE NUMBER OF  FRAGMENTS IN THE TABLE.
+     ***************************************************/
+    signal->theData[0] = tcConnectptr.p->dihConnectptr;
+    signal->theData[1] = scanptr.p->scanTableref;
+    sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+  }
+  else 
+  {
+    signal->theData[0] = tcConnectptr.p->dihConnectptr;
+    signal->theData[1] = tabPtr.i;
+    signal->theData[2] = cachePtr.p->distributionKey;
+    EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
+    UintR TerrorIndicator = signal->theData[0];
+    jamEntry();
+    if (TerrorIndicator != 0) {
+      signal->theData[0] = tcConnectptr.i;
+      //signal->theData[1] Contains error
+      execDI_FCOUNTREF(signal);
+      return;
+    }
+    
+    UintR Tdata1 = signal->theData[1];
+    scanptr.p->scanNextFragId = Tdata1;
+
+    signal->theData[0] = tcConnectptr.i;
+    signal->theData[1] = 1; // Frag count
+    execDI_FCOUNTCONF(signal);
+  }
   return;
 }//Dbtc::diFcountReqLab()
 
@@ -8791,7 +8803,7 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
 {
   jamEntry();
   tcConnectptr.i = signal->theData[0];
-  const UintR tfragCount = signal->theData[1];
+  Uint32 tfragCount = signal->theData[1];
   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
   apiConnectptr.i = tcConnectptr.p->apiConnect;
   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -8825,24 +8837,17 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
     return;
   }
 
-  if(scanptr.p->scanParallel > tfragCount){
-    jam();
-    abortScanLab(signal, scanptr, ZTOO_HIGH_CONCURRENCY_ERROR);
-    return;
-  }
-  
   scanptr.p->scanParallel = tfragCount;
   scanptr.p->scanNoFrag = tfragCount;
-  scanptr.p->scanNextFragId = 0;
   scanptr.p->scanState = ScanRecord::RUNNING;
 
   setApiConTimer(apiConnectptr.i, 0, __LINE__);
   updateBuddyTimer(apiConnectptr);
   
   ScanFragRecPtr ptr;
-  ScanFragList list(c_scan_frag_pool, 
-		    scanptr.p->m_running_scan_frags);
-  for (list.first(ptr); !ptr.isNull(); list.next(ptr)){
+  ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+  for (list.first(ptr); !ptr.isNull() && tfragCount; 
+       list.next(ptr), tfragCount--){
     jam();
 
     ptr.p->lqhBlockref = 0;
@@ -8857,6 +8862,20 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
     signal->theData[3] = ptr.p->scanFragId;
     sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
   }//for
+
+  ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
+  for (; !ptr.isNull();)
+  {
+    ptr.p->m_ops = 0;
+    ptr.p->m_totalLen = 0;
+    ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
+    ptr.p->stopFragTimer();
+
+    ScanFragRecPtr tmp = ptr;
+    list.next(ptr);
+    list.remove(tmp);
+    queued.add(tmp);
+  }
 }//Dbtc::execDI_FCOUNTCONF()
 
 /******************************************************
@@ -11060,7 +11079,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
 {
   jamEntry();
 
-  TcIndxReq * const tcIndxReq =  (TcIndxReq *)signal->getDataPtr();
+  TcKeyReq * const tcIndxReq =  (TcKeyReq *)signal->getDataPtr();
   const UintR TapiIndex = tcIndxReq->apiConnectPtr;
   Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
   Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
@@ -11111,7 +11130,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
 
   // If operation is readTupleExclusive or updateTuple then read index 
   // table with exclusive lock
-  Uint32 indexLength = TcIndxReq::getIndexLength(tcIndxRequestInfo);
+  Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
   Uint32 attrLength = tcIndxReq->attrLen;
   indexOp->expectedKeyInfo = indexLength;
   Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
@@ -11524,7 +11543,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
     // Send TCINDXREF 
     
     jam();
-    TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
+    TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
     
     ndbassert(regApiPtr->noIndexOp);
@@ -11719,7 +11738,7 @@ void Dbtc::readIndexTable(Signal* signal,
     (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
 
   // Find index table
-  if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.indexId)) == NULL) {
+  if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
     jam();
     // Failed to find index record
     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
@@ -11736,7 +11755,7 @@ void Dbtc::readIndexTable(Signal* signal,
   tcKeyReq->transId2 = transId2;
   tcKeyReq->tableId = indexData->indexId;
   tcKeyLength += MIN(keyLength, keyBufSize);
-  tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.indexSchemaVersion;
+  tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
   TcKeyReq::setOperationType(tcKeyRequestInfo, 
 			     opType == ZREAD ? ZREAD : ZREAD_EX);
   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
@@ -11828,7 +11847,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
   Uint32 attrBufSize = 5;
   Uint32 dataPos = 0;
-  TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
+  TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
   Uint32 * dataPtr = &tcKeyReq->scanInfo;
   Uint32 tcKeyLength = TcKeyReq::StaticLength;
@@ -11839,7 +11858,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
   bool moreKeyData = indexOp->transIdAI.first(aiIter);
       
   // Find index table
-  if ((indexData = c_theIndexes.getPtr(tcIndxReq->indexId)) == NULL) {
+  if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
     jam();
     // Failed to find index record 
     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 8896324f793..0059f558995 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -449,7 +449,7 @@ private:
     State m_state;
     DictTabInfo::TableType m_tableType;
     Uint32 m_tableId;
-    Uint16 m_fragOff;           // offset for duplicate fragId bits
+    Uint16 unused;
     Uint16 m_numFrags;
     Uint32 m_fragId[MaxIndexFragments];
     Uint32 m_fragPtrI[MaxIndexFragments];
@@ -475,7 +475,7 @@ private:
   struct Frag {
     Uint32 m_tableId;           // copy from index level
     Uint32 m_indexId;
-    Uint16 m_fragOff;
+    Uint16 unused;
     Uint16 m_fragId;
     Uint32 m_descPage;          // copy from index level
     Uint16 m_descOff;
@@ -1072,7 +1072,6 @@ inline
 Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
   m_tableId(RNIL),
   m_indexId(RNIL),
-  m_fragOff(ZNIL),
   m_fragId(ZNIL),
   m_descPage(RNIL),
   m_descOff(0),
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index c5c22264460..01193b5e41f 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -370,7 +370,6 @@ operator<<(NdbOut& out, const Dbtux::Index& index)
 {
   out << "[Index " << hex << &index;
   out << " [tableId " << dec << index.m_tableId << "]";
-  out << " [fragOff " << dec << index.m_fragOff << "]";
   out << " [numFrags " << dec << index.m_numFrags << "]";
   for (unsigned i = 0; i < index.m_numFrags; i++) {
     out << " [frag " << dec << i << " ";
@@ -393,7 +392,6 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
   out << "[Frag " << hex << &frag;
   out << " [tableId " << dec << frag.m_tableId << "]";
   out << " [indexId " << dec << frag.m_indexId << "]";
-  out << " [fragOff " << dec << frag.m_fragOff << "]";
   out << " [fragId " << dec << frag.m_fragId << "]";
   out << " [descPage " << hex << frag.m_descPage << "]";
   out << " [descOff " << dec << frag.m_descOff << "]";
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 30afb51e7d7..2d256487dcc 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -57,9 +57,9 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
   c_indexPool.getPtr(indexPtr, req->indexId);
   ndbrequire(indexPtr.p->m_tableId == req->tableId);
   // get base fragment id and extra bits
-  const Uint32 fragOff = indexPtr.p->m_fragOff;
-  const Uint32 fragId = req->fragId & ((1 << fragOff) - 1);
-  const Uint32 fragBit = req->fragId >> fragOff;
+  const Uint32 fragId = req->fragId & ~1;
+  const Uint32 fragBit = req->fragId & 1;
+  
   // get the fragment
   FragPtr fragPtr;
   fragPtr.i = RNIL;
@@ -71,6 +71,7 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
       break;
     }
   }
+
   ndbrequire(fragPtr.i != RNIL);
   Frag& frag = *fragPtr.p;
   // set up index keys for this operation
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index 1577c5045e0..54882d99800 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -74,7 +74,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
     new (fragPtr.p) Frag(c_scanOpPool);
     fragPtr.p->m_tableId = req->primaryTableId;
     fragPtr.p->m_indexId = req->tableId;
-    fragPtr.p->m_fragOff = req->fragOff;
     fragPtr.p->m_fragId = req->fragId;
     fragPtr.p->m_numAttrs = req->noOfAttr;
     fragPtr.p->m_storeNullKey = true;  // not yet configurable
@@ -102,7 +101,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
       indexPtr.p->m_state = Index::Defining;
       indexPtr.p->m_tableType = (DictTabInfo::TableType)req->tableType;
       indexPtr.p->m_tableId = req->primaryTableId;
-      indexPtr.p->m_fragOff = req->fragOff;
       indexPtr.p->m_numAttrs = req->noOfAttr;
       indexPtr.p->m_storeNullKey = true;  // not yet configurable
       // allocate attribute descriptors
@@ -118,7 +116,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
           indexPtr.p->m_state == Index::Defining &&
           indexPtr.p->m_tableType == (DictTabInfo::TableType)req->tableType &&
           indexPtr.p->m_tableId == req->primaryTableId &&
-          indexPtr.p->m_fragOff == req->fragOff &&
           indexPtr.p->m_numAttrs == req->noOfAttr);
     }
     // copy metadata address to each fragment
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index 8677ae741b3..c56919865bd 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -34,7 +34,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
     fragPtr.i = RNIL;
     for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
       jam();
-      if (indexPtr.p->m_fragId[i] == req->fragmentNo) {
+      if (indexPtr.p->m_fragId[i] == req->fragmentNo << 1) {
         jam();
         c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
         break;
@@ -43,7 +43,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
     ndbrequire(fragPtr.i != RNIL);
     Frag& frag = *fragPtr.p;
     // must be normal DIH/TC fragment
-    ndbrequire(frag.m_fragId < (1 << frag.m_fragOff));
     TreeHead& tree = frag.m_tree;
     // check for empty fragment
     if (tree.m_root == NullTupLoc) {
@@ -354,7 +353,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
     NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
     conf->scanPtr = scan.m_userPtr;
     conf->accOperationPtr = RNIL;       // no tuple returned
-    conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+    conf->fragId = frag.m_fragId | ent.m_fragBit;
     unsigned signalLength = 3;
     // if TC has ordered scan close, it will be detected here
     sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
@@ -397,7 +396,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
       lockReq->userPtr = scanPtr.i;
       lockReq->userRef = reference();
       lockReq->tableId = scan.m_tableId;
-      lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+      lockReq->fragId = frag.m_fragId | ent.m_fragBit;
       lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
       const Uint32* const buf32 = static_cast<Uint32*>(pkData);
       const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
@@ -496,7 +495,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
       accLockOp = (Uint32)-1;
     }
     conf->accOperationPtr = accLockOp;
-    conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+    conf->fragId = frag.m_fragId | ent.m_fragBit;
     conf->localKey[0] = getTupAddr(frag, ent);
     conf->localKey[1] = 0;
     conf->localKeyLength = 1;
@@ -890,7 +889,7 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
   const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
   Uint32 fragBit = ent.m_fragBit;
   Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit];
-  Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff);
+  Uint32 fragId = frag.m_fragId | fragBit;
   Uint32 tupAddr = getTupAddr(frag, ent);
   Uint32 tupVersion = ent.m_tupVersion;
   // check for same tuple twice in row
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index a1d34896968..b1671e593e1 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -213,7 +213,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
       theTrace                = TestOrd::TraceAPI;
       theReceiversBlockNumber = DBTC;
       theVerId_signalNumber   = GSN_TCINDXREQ;
-      theLength               = TcIndxReq::SignalLength;
+      theLength               = TcKeyReq::SignalLength;
     }
     break;
 
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index feab95d8ca5..615c167991f 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -107,8 +107,8 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
   }
   { NdbDictionary::Column bc("PK");
     bc.setType(NdbDictionary::Column::Unsigned);
-    assert(t->m_sizeOfKeysInWords != 0);
-    bc.setLength(t->m_sizeOfKeysInWords);
+    assert(t->m_keyLenInWords != 0);
+    bc.setLength(t->m_keyLenInWords);
     bc.setPrimaryKey(true);
     bt.addColumn(bc);
   }
@@ -325,7 +325,7 @@ int
 NdbBlob::setTableKeyValue(NdbOperation* anOp)
 {
   const Uint32* data = (const Uint32*)theKeyBuf.data;
-  DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_sizeOfKeysInWords));
+  DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_keyLenInWords));
   const unsigned columns = theTable->m_columns.size();
   unsigned pos = 0;
   for (unsigned i = 0; i < columns; i++) {
@@ -348,7 +348,7 @@ int
 NdbBlob::setAccessKeyValue(NdbOperation* anOp)
 {
   const Uint32* data = (const Uint32*)theAccessKeyBuf.data;
-  DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_sizeOfKeysInWords));
+  DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_keyLenInWords));
   const unsigned columns = theAccessTable->m_columns.size();
   unsigned pos = 0;
   for (unsigned i = 0; i < columns; i++) {
@@ -371,7 +371,7 @@ int
 NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
 {
   Uint32* data = (Uint32*)theKeyBuf.data;
-  unsigned size = theTable->m_sizeOfKeysInWords;
+  unsigned size = theTable->m_keyLenInWords;
   DBG("setPartKeyValue dist=" << getDistKey(part) << " part=" << part << " key=" << ndb_blob_debug(data, size));
   if (anOp->equal((Uint32)0, getDistKey(part)) == -1 ||
       anOp->equal((Uint32)1, part) == -1 ||
@@ -1043,8 +1043,8 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
     theBlobTable = &NdbTableImpl::getImpl(*bt);
   }
   // buffers
-  theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2);
-  theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2);
+  theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+  theAccessKeyBuf.alloc(theAccessTable->m_keyLenInWords << 2);
   theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
   thePartBuf.alloc(thePartSize);
   theHead = (Head*)theHeadInlineBuf.data;
@@ -1055,7 +1055,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
     if (isTableOp()) {
       // get table key
       Uint32* data = (Uint32*)theKeyBuf.data;
-      unsigned size = theTable->m_sizeOfKeysInWords;
+      unsigned size = theTable->m_keyLenInWords;
       if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
         setErrorCode(ErrUsage);
         return -1;
@@ -1064,7 +1064,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
     if (isIndexOp()) {
       // get index key
       Uint32* data = (Uint32*)theAccessKeyBuf.data;
-      unsigned size = theAccessTable->m_sizeOfKeysInWords;
+      unsigned size = theAccessTable->m_keyLenInWords;
       if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
         setErrorCode(ErrUsage);
         return -1;
@@ -1326,7 +1326,7 @@ NdbBlob::atNextResult()
   thePos = 0;
   // get primary key
   { Uint32* data = (Uint32*)theKeyBuf.data;
-    unsigned size = theTable->m_sizeOfKeysInWords;
+    unsigned size = theTable->m_keyLenInWords;
     if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
       setErrorCode(ErrUsage);
       return -1;
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index 1457792cf28..607afc8ddf4 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -1073,8 +1073,7 @@ NdbConnection::getNdbIndexScanOperation(const NdbIndexImpl* index,
   if (theCommitStatus == Started){
     const NdbTableImpl * indexTable = index->getIndexTable();
     if (indexTable != 0){
-      NdbIndexScanOperation* tOp = 
-	getNdbScanOperation((NdbTableImpl *) indexTable);
+      NdbIndexScanOperation* tOp = getNdbScanOperation(indexTable);
       tOp->m_currentTable = table;
       if(tOp) tOp->m_cursor_type = NdbScanOperation::IndexCursor;
       return tOp;
diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp
index c8414ec16a3..4bc1fa8eb59 100644
--- a/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/ndb/src/ndbapi/NdbDictionary.cpp
@@ -176,16 +176,6 @@ NdbDictionary::Column::getPrimaryKey() const {
   return m_impl.m_pk;
 }
 
-void
-NdbDictionary::Column::setTupleKey(bool val){
-  m_impl.m_tupleKey = val;
-}
-
-bool 
-NdbDictionary::Column::getTupleKey() const {
-  return m_impl.m_tupleKey;
-}
-
 void 
 NdbDictionary::Column::setDistributionKey(bool val){
   m_impl.m_distributionKey = val;
@@ -196,32 +186,6 @@ NdbDictionary::Column::getDistributionKey() const{
   return m_impl.m_distributionKey;
 }
 
-void
-NdbDictionary::Column::setDistributionGroup(bool val, int bits){
-  m_impl.m_distributionGroup = val;
-  m_impl.m_distributionGroupBits = bits;
-}
-
-bool 
-NdbDictionary::Column::getDistributionGroup() const {
-  return m_impl.m_distributionGroup;
-}
-
-int 
-NdbDictionary::Column::getDistributionGroupBits() const{
-  return m_impl.m_distributionGroupBits;
-}
-
-void 
-NdbDictionary::Column::setIndexOnlyStorage(bool val){
-  m_impl.m_indexOnly = val;
-}
-
-bool 
-NdbDictionary::Column::getIndexOnlyStorage() const {
-  return m_impl.m_indexOnly;
-}
-
 const NdbDictionary::Table * 
 NdbDictionary::Column::getBlobTable() const {
   NdbTableImpl * t = m_impl.m_blobTable;
@@ -956,6 +920,9 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
     out << " NOT NULL";
   else
     out << " NULL";
+
+  if(col.getDistributionKey())
+    out << " DISTRIBUTION KEY";
   return out;
 }
 
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index cf51a30fe0b..79ae484aff8 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -69,12 +69,8 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
   m_scale = col.m_scale;
   m_length = col.m_length;
   m_pk = col.m_pk;
-  m_tupleKey = col.m_tupleKey;
   m_distributionKey = col.m_distributionKey;
-  m_distributionGroup = col.m_distributionGroup;
-  m_distributionGroupBits = col.m_distributionGroupBits;
   m_nullable = col.m_nullable;
-  m_indexOnly = col.m_indexOnly;
   m_autoIncrement = col.m_autoIncrement;
   m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
   m_defaultValue = col.m_defaultValue;
@@ -154,11 +150,7 @@ NdbColumnImpl::init(Type t)
   }
   m_pk = false;
   m_nullable = false;
-  m_tupleKey = false;
-  m_indexOnly = false;
   m_distributionKey = false;
-  m_distributionGroup = false;
-  m_distributionGroupBits = 8;
   m_keyInfoPos = 0;
   // next 2 are set at run time
   m_attrSize = 0;
@@ -188,22 +180,9 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
     return false;
   }
   if(m_pk){
-    if(m_tupleKey != col.m_tupleKey){
-      return false;
-    }
-    if(m_indexOnly != col.m_indexOnly){
-      return false;
-    }
     if(m_distributionKey != col.m_distributionKey){
       return false;
     }
-    if(m_distributionGroup != col.m_distributionGroup){
-      return false;
-    }
-    if(m_distributionGroup && 
-       (m_distributionGroupBits != col.m_distributionGroupBits)){
-      return false;
-    }
   }
   if (m_precision != col.m_precision ||
       m_scale != col.m_scale ||
@@ -286,8 +265,9 @@ NdbTableImpl::init(){
   m_indexType = NdbDictionary::Index::Undefined;
   
   m_noOfKeys = 0;
+  m_noOfDistributionKeys = 0;
   m_fragmentCount = 0;
-  m_sizeOfKeysInWords = 0;
+  m_keyLenInWords = 0;
   m_noOfBlobs = 0;
 }
 
@@ -366,8 +346,9 @@ NdbTableImpl::assign(const NdbTableImpl& org)
     delete m_index;
   m_index = org.m_index;
   
+  m_noOfDistributionKeys = org.m_noOfDistributionKeys;
   m_noOfKeys = org.m_noOfKeys;
-  m_sizeOfKeysInWords = org.m_sizeOfKeysInWords;
+  m_keyLenInWords = org.m_keyLenInWords;
   m_noOfBlobs = org.m_noOfBlobs;
 
   m_version = org.m_version;
@@ -1234,6 +1215,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
   Uint32 keyInfoPos = 0;
   Uint32 keyCount = 0;
   Uint32 blobCount = 0;
+  Uint32 distKeys = 0;
   
   for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
     DictTabInfo::Attribute attrDesc; attrDesc.init();
@@ -1287,12 +1269,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
     col->m_arraySize = attrDesc.AttributeArraySize;
     
     col->m_pk = attrDesc.AttributeKeyFlag;
-    col->m_tupleKey = 0;
     col->m_distributionKey = attrDesc.AttributeDKey;
-    col->m_distributionGroup = attrDesc.AttributeDGroup;
-    col->m_distributionGroupBits = 16;
     col->m_nullable = attrDesc.AttributeNullableFlag;
-    col->m_indexOnly = (attrDesc.AttributeStoredInd ? false : true);
     col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
     col->m_autoIncrementInitialValue = ~0;
     col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
@@ -1301,6 +1279,9 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
       col->m_keyInfoPos = keyInfoPos + 1;
       keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
       keyCount++;
+      
+      if(attrDesc.AttributeDKey)
+	distKeys++;
     } else {
       col->m_keyInfoPos = 0;
     }
@@ -1319,8 +1300,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
 
   impl->m_noOfKeys = keyCount;
   impl->m_keyLenInWords = keyInfoPos;
-  impl->m_sizeOfKeysInWords = keyInfoPos;
   impl->m_noOfBlobs = blobCount;
+  impl->m_noOfDistributionKeys = distKeys;
   * ret = impl;
   return 0;
 }
@@ -1528,11 +1509,11 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
     BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName), 
 	     col->m_name.c_str());
     tmpAttr.AttributeId = i;
-    tmpAttr.AttributeKeyFlag = col->m_pk || col->m_tupleKey;
+    tmpAttr.AttributeKeyFlag = col->m_pk;
     tmpAttr.AttributeNullableFlag = col->m_nullable;
-    tmpAttr.AttributeStoredInd = (col->m_indexOnly ? 0 : 1);
+    tmpAttr.AttributeStoredInd = 1;
     tmpAttr.AttributeDKey = col->m_distributionKey;
-    tmpAttr.AttributeDGroup = col->m_distributionGroup;
+    tmpAttr.AttributeDGroup = 0;
 
     tmpAttr.AttributeExtType =
       getKernelConstant(col->m_type,
@@ -2030,10 +2011,6 @@ NdbDictInterface::createIndex(Ndb & ndb,
     // Copy column definition
     *impl.m_columns[i] = *col;
 
-    if(col->m_pk && col->m_indexOnly){
-      m_error.code = 4245;
-      return -1;
-    }
     // index key type check
     if (it == DictTabInfo::UniqueHashIndex &&
         ! NdbSqlUtil::usable_in_hash_index(col->m_type, col->m_cs) ||
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 12f0946ab67..955ac3ed3c7 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -63,12 +63,8 @@ public:
   CHARSET_INFO * m_cs;          // not const in MySQL
   
   bool m_pk;
-  bool m_tupleKey;
   bool m_distributionKey;
-  bool m_distributionGroup;
-  int m_distributionGroupBits;
   bool m_nullable;
-  bool m_indexOnly;
   bool m_autoIncrement;
   Uint64 m_autoIncrementInitialValue;
   BaseString m_defaultValue;
@@ -128,8 +124,8 @@ public:
   int m_kvalue;
   int m_minLoadFactor;
   int m_maxLoadFactor;
-  int m_keyLenInWords;
-  int m_fragmentCount;
+  Uint16 m_keyLenInWords;
+  Uint16 m_fragmentCount;
 
   NdbDictionaryImpl * m_dictionary;
   NdbIndexImpl * m_index;
@@ -147,9 +143,9 @@ public:
   /**
    * Aggregates
    */
-  Uint32 m_noOfKeys;
-  unsigned short m_sizeOfKeysInWords;
-  unsigned short m_noOfBlobs;
+  Uint8 m_noOfKeys;
+  Uint8 m_noOfDistributionKeys;
+  Uint8 m_noOfBlobs;
 
   /**
    * Equality/assign
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index 9abde639914..545d1ef10b0 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -28,9 +28,7 @@
 
 NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
   NdbOperation(aNdb),
-  m_theIndex(NULL),
-  m_theIndexLen(0),
-  m_theNoOfIndexDefined(0)
+  m_theIndex(NULL)
 {
   m_tcReqGSN = GSN_TCINDXREQ;
   m_attrInfoGSN = GSN_INDXATTRINFO;
@@ -72,16 +70,7 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
   }
   m_theIndex = anIndex;
   m_accessTable = anIndex->m_table;
-  m_theIndexLen = 0;
-  m_theNoOfIndexDefined = 0;
-  for (Uint32 i=0; i<NDB_MAX_ATTRIBUTES_IN_INDEX; i++)
-    for (int j=0; j<3; j++)
-      m_theIndexDefined[i][j] = false;  
-  
-  TcIndxReq * const tcIndxReq = CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
-  tcIndxReq->scanInfo = 0;
-  theKEYINFOptr = &tcIndxReq->keyInfo[0];
-  theATTRINFOptr = &tcIndxReq->attrInfo[0];
+  theNoOfTupKeyLeft = m_accessTable->getNoOfPrimaryKeys();
   return 0;
 }
 
@@ -172,306 +161,6 @@ int NdbIndexOperation::interpretedDeleteTuple()
   return NdbOperation::interpretedDeleteTuple();
 }
 
-int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo, 
-                                  const char* aValuePassed, 
-                                  Uint32 aVariableKeyLen)
-{
-  register Uint32 tAttrId;
-  
-  Uint32 tData;
-  Uint32 tKeyInfoPosition;
-  const char* aValue = aValuePassed;
-  Uint32 xfrmData[1024];
-  Uint32 tempData[1024];
-  
-  if ((theStatus == OperationDefined) &&
-      (aValue != NULL) &&
-      (tAttrInfo != NULL )) {
-    /************************************************************************
-     *	Start by checking that the attribute is an index key. 
-     *      This value is also the word order in the tuple key of this 
-     *      tuple key attribute. 
-     *      Then check that this tuple key has not already been defined. 
-     *      Finally check if all tuple key attributes have been defined. If
-     *	this is true then set Operation state to tuple key defined.
-     ************************************************************************/
-    tAttrId = tAttrInfo->m_attrId;
-    tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
-    Uint32 i = 0;
-    
-    // Check that the attribute is part if the index attributes
-    // by checking if it is a primary key attribute of index table
-    if (tAttrInfo->m_pk) {
-      Uint32 tKeyDefined = theTupleKeyDefined[0][2];
-      Uint32 tKeyAttrId = theTupleKeyDefined[0][0];
-      do {
-	if (tKeyDefined == false) {
-	  goto keyEntryFound;
-	} else {
-	  if (tKeyAttrId != tAttrId) {
-	    /******************************************************************
-	     * We read the key defined variable in advance. 
-	     * It could potentially read outside its area when 
-	     * i = MAXNROFTUPLEKEY - 1, 
-	     * it is not a problem as long as the variable 
-	     * theTupleKeyDefined is defined
-	     * in the middle of the object. 
-	     * Reading wrong data and not using it causes no problems.
-	     *****************************************************************/
-	    i++;
-	    tKeyAttrId = theTupleKeyDefined[i][0];
-	    tKeyDefined = theTupleKeyDefined[i][2];
-	    continue;
-	  } else {
-	    goto equal_error2;
-	  }//if
-	}//if
-      } while (i < NDB_MAX_ATTRIBUTES_IN_INDEX);
-      goto equal_error2;
-    } else {
-      goto equal_error1;
-    }
-    /**************************************************************************
-     *	Now it is time to retrieve the tuple key data from the pointer supplied
-     *      by the application. 
-     *      We have to retrieve the size of the attribute in words and bits.
-     *************************************************************************/
-  keyEntryFound:
-    m_theIndexDefined[i][0] = tAttrId;
-    m_theIndexDefined[i][1] = tKeyInfoPosition; 
-    m_theIndexDefined[i][2] = true;
-
-    Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
-    {
-      /*************************************************************************
-       *	Check if the pointer of the value passed is aligned on a 4 byte 
-       *      boundary. If so only assign the pointer to the internal variable 
-       *      aValue. If it is not aligned then we start by copying the value to 
-       *      tempData and use this as aValue instead.
-       *************************************************************************/
-      const int attributeSize = sizeInBytes;
-      const int slack = sizeInBytes & 3;
-      if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
-	memcpy(&tempData[0], aValue, attributeSize);
-	aValue = (char*)&tempData[0];
-	if(slack != 0) {
-	  char * tmp = (char*)&tempData[0];
-	  memset(&tmp[attributeSize], 0, (4 - slack));
-	}//if
-      }//if
-    }
-    const char* aValueToWrite = aValue;
-
-    CHARSET_INFO* cs = tAttrInfo->m_cs;
-    if (cs != 0) {
-      // current limitation: strxfrm does not increase length
-      assert(cs->strxfrm_multiply == 1);
-      unsigned n = 
-      (*cs->coll->strnxfrm)(cs,
-                            (uchar*)xfrmData, sizeof(xfrmData),
-                            (const uchar*)aValue, sizeInBytes);
-      while (n < sizeInBytes)
-        ((uchar*)xfrmData)[n++] = 0x20;
-      aValue = (char*)xfrmData;
-    }
-
-    Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
-    Uint32 totalSizeInWords = (sizeInBytes + 3)/4;// Inc. bits in last word
-    Uint32 sizeInWords = sizeInBytes / 4;         // Exc. bits in last word
-
-    if (true){ //tArraySize != 0) {
-      Uint32 tIndexLen = m_theIndexLen;
-
-      m_theIndexLen = tIndexLen + totalSizeInWords;
-      if ((aVariableKeyLen == sizeInBytes) ||
-	  (aVariableKeyLen == 0)) {
-	;
-      } else {
-	goto equal_error3;
-      }
-    }
-#if 0
-    else {
-      /************************************************************************
-       * The attribute is a variable array. We need to use the length parameter
-       * to know the size of this attribute in the key information and 
-       * variable area. A key is however not allowed to be larger than 4 
-       * kBytes and this is checked for variable array attributes
-       * used as keys.
-       ***********************************************************************/
-      Uint32 tMaxVariableKeyLenInWord = (MAXTUPLEKEYLENOFATTERIBUTEINWORD -
-					 tKeyInfoPosition);
-      tAttrSizeInBits = aVariableKeyLen << 3;
-      tAttrSizeInWords = tAttrSizeInBits >> 5;
-      tAttrBitsInLastWord = tAttrSizeInBits - (tAttrSizeInWords << 5);
-      tAttrLenInWords = ((tAttrSizeInBits + 31) >> 5);
-      if (tAttrLenInWords > tMaxVariableKeyLenInWord) {
-	setErrorCodeAbort(4207);
-	return -1;
-      }//if
-      m_theIndexLen = m_theIndexLen + tAttrLenInWords;
-    }//if
-#endif
-    int tDistrKey = tAttrInfo->m_distributionKey;
-    int tDistrGroup = tAttrInfo->m_distributionGroup;
-    OperationType tOpType = theOperationType;
-    if ((tDistrKey != 1) && (tDistrGroup != 1)) {
-      ;
-    } else if (tDistrKey == 1) {
-      theDistrKeySize += totalSizeInWords;
-      theDistrKeyIndicator = 1;
-    } else {
-      Uint32 TsizeInBytes = sizeInBytes;
-      Uint32 TbyteOrderFix = 0;
-      char*   TcharByteOrderFix = (char*)&TbyteOrderFix;
-      if (tAttrInfo->m_distributionGroupBits == 8) {
-	char tFirstChar = aValue[TsizeInBytes - 2];
-	char tSecondChar = aValue[TsizeInBytes - 2];
-	TcharByteOrderFix[0] = tFirstChar;
-	TcharByteOrderFix[1] = tSecondChar;
-	TcharByteOrderFix[2] = 0x30;
-	TcharByteOrderFix[3] = 0x30;
-	theDistrGroupType = 0;
-      } else {
-	TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10) 
-	  + (aValue[TsizeInBytes - 1] - 0x30);
-	theDistrGroupType = 1;
-      }//if
-      theDistributionGroup = TbyteOrderFix;
-      theDistrGroupIndicator = 1;
-    }//if
-    /**************************************************************************
-     *	If the operation is an insert request and the attribute is stored then
-     *      we also set the value in the stored part through putting the 
-     *      information in the INDXATTRINFO signals.
-     *************************************************************************/
-    if ((tOpType == InsertRequest) ||
-	(tOpType == WriteRequest)) {
-      if (!tAttrInfo->m_indexOnly){
-        // invalid data can crash kernel
-        if (cs != NULL &&
-            (*cs->cset->well_formed_len)(cs,
-                                         aValueToWrite,
-                                         aValueToWrite + sizeInBytes,
-                                         sizeInBytes) != sizeInBytes)
-          goto equal_error4;
-	Uint32 ahValue;
-	Uint32 sz = totalSizeInWords;
-	AttributeHeader::init(&ahValue, tAttrId, sz);
-	insertATTRINFO( ahValue );
-	insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
-	if (bitsInLastWord != 0) {
-	  tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
-	  tData = convertEndian(tData);
-	  tData = tData & ((1 << bitsInLastWord) - 1);
-	  tData = convertEndian(tData);
-	  insertATTRINFO( tData );
-	}//if
-      }//if
-    }//if
-
-    /**************************************************************************
-     *	Store the Key information in the TCINDXREQ and INDXKEYINFO signals. 
-     *************************************************************************/
-    if (insertKEYINFO(aValue, tKeyInfoPosition, 
-		      totalSizeInWords, bitsInLastWord) != -1) {
-      /************************************************************************
-       * Add one to number of tuple key attributes defined. 
-       * If all have been defined then set the operation state to indicate 
-       * that tuple key is defined. 
-       * Thereby no more search conditions are allowed in this version.
-       ***********************************************************************/
-      Uint32 tNoIndexDef = m_theNoOfIndexDefined;
-      Uint32 tErrorLine = theErrorLine;
-      int tNoIndexAttrs = m_theIndex->m_columns.size();
-      unsigned char tInterpretInd = theInterpretIndicator;
-      tNoIndexDef++;
-      m_theNoOfIndexDefined = tNoIndexDef;
-      tErrorLine++;
-      theErrorLine = tErrorLine;
-      if (int(tNoIndexDef) == tNoIndexAttrs) {
-	if (tOpType == UpdateRequest) {
-	  if (tInterpretInd == 1) {
-	    theStatus = GetValue;
-	  } else {
-	    theStatus = SetValue;
-	  }//if
-	  return 0;
-	} else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
-		   (tOpType == ReadExclusive)) {
-	  theStatus = GetValue;
-          // create blob handles automatically
-          if (tOpType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
-            for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
-              NdbColumnImpl* c = m_currentTable->m_columns[i];
-              assert(c != 0);
-              if (c->getBlobType()) {
-                if (getBlobHandle(theNdbCon, c) == NULL)
-                  return -1;
-              }
-            }
-          }
-	  return 0;
-	} else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
-	  theStatus = SetValue;
-	  return 0;
-	} else {
-	  setErrorCodeAbort(4005);
-	  return -1;
-	}//if
-      }//if
-      return 0;
-    } else {
-     
-      return -1;
-    }//if
-  } else {
-    if (theStatus != OperationDefined) {
-      return -1;
-    }//if
-
-    if (aValue == NULL) {
-      setErrorCodeAbort(4505);
-      return -1;
-    }//if
-    
-    if ( tAttrInfo == NULL ) {      
-      setErrorCodeAbort(4004);
-      return -1;
-    }//if
-  }//if
-  return -1;
-
- equal_error1:
-  setErrorCodeAbort(4205);
-  return -1;
-
- equal_error2:
-  setErrorCodeAbort(4206);
-  return -1;
-
- equal_error3:
-  setErrorCodeAbort(4209);
-  return -1;
- 
- equal_error4:
-  setErrorCodeAbort(744);
-  return -1;
-}
-
-int NdbIndexOperation::executeCursor(int aProcessorId)
-{
-  printf("NdbIndexOperation::executeCursor NYI\n");
-  // NYI
-  return -1;
-}
-void
-NdbIndexOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
-{
-  TcIndxReq * const req = CAST_PTR(TcIndxReq, signal->getDataPtrSend());
-  TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
-}
-
 int 
 NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
 {
@@ -512,18 +201,18 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
 // We start by filling in the first 8 unconditional words of the
 // TCINDXREQ signal.
 //-------------------------------------------------------------
-  TcIndxReq * const tcIndxReq = 
-    CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
+  TcKeyReq * tcKeyReq = 
+    CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
 
   Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
   Uint32 tIndexId = m_theIndex->m_indexId;
   Uint32 tSchemaVersion = m_theIndex->m_version;
   
-  tcIndxReq->apiConnectPtr      = aTC_ConnectPtr;
-  tcIndxReq->senderData         = ptr2int();
-  tcIndxReq->attrLen            = tTotalCurrAI_Len;
-  tcIndxReq->indexId            = tIndexId;
-  tcIndxReq->indexSchemaVersion = tSchemaVersion;
+  tcKeyReq->apiConnectPtr      = aTC_ConnectPtr;
+  tcKeyReq->senderData         = ptr2int();
+  tcKeyReq->attrLen            = tTotalCurrAI_Len;
+  tcKeyReq->tableId            = tIndexId;
+  tcKeyReq->tableSchemaVersion = tSchemaVersion;
 
   tTransId1 = (Uint32) aTransactionId;
   tTransId2 = (Uint32) (aTransactionId >> 32);
@@ -551,59 +240,53 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
   Uint8 tSimpleState = tReadInd & tSimpleAlt;
   //theNdbCon->theSimpleState = tSimpleState;
 
-  tcIndxReq->transId1           = tTransId1;
-  tcIndxReq->transId2           = tTransId2;
+  tcKeyReq->transId1           = tTransId1;
+  tcKeyReq->transId2           = tTransId2;
   
   tReqInfo = 0;
 
-  if (tTotalCurrAI_Len <= TcIndxReq::MaxAttrInfo) {
-    tcIndxReq->setAIInTcIndxReq(tReqInfo, tTotalCurrAI_Len);
+  if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
+    tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
   } else {
-    tcIndxReq->setAIInTcIndxReq(tReqInfo, TcIndxReq::MaxAttrInfo);
+    tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
   }//if
 
-  tcIndxReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
-  tcIndxReq->setCommitFlag(tReqInfo, tCommitIndicator);
-  tcIndxReq->setStartFlag(tReqInfo, tStartIndicator);
+  tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
+  tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
+  tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
   const Uint8 tInterpretIndicator = theInterpretIndicator;
-  tcIndxReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+  tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
 
   Uint8 tDirtyIndicator = theDirtyIndicator;
   OperationType tOperationType = theOperationType;
-  Uint32 tIndexLen = m_theIndexLen;
+  Uint32 tIndexLen = theTupKeyLen;
   Uint8 abortOption = theNdbCon->m_abortOption;
 
-  tcIndxReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
-  tcIndxReq->setOperationType(tReqInfo, tOperationType);
-  tcIndxReq->setIndexLength(tReqInfo, tIndexLen);
-  tcIndxReq->setCommitType(tReqInfo, abortOption);
+  tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
+  tcKeyReq->setOperationType(tReqInfo, tOperationType);
+  tcKeyReq->setKeyLength(tReqInfo, tIndexLen);
+  tcKeyReq->setAbortOption(tReqInfo, abortOption);
   
-  Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
-  Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
-  Uint8 tDistrGroupType = theDistrGroupType;
+  Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
   Uint8 tScanIndicator = theScanInfo & 1;
 
-  tcIndxReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
-  tcIndxReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
-  tcIndxReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
-  tcIndxReq->setScanIndFlag(tReqInfo, tScanIndicator);
+  tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
+  tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
 
-  tcIndxReq->requestInfo  = tReqInfo;
+  tcKeyReq->requestInfo  = tReqInfo;
 
 //-------------------------------------------------------------
 // The next step is to fill in the upto three conditional words.
 //-------------------------------------------------------------
-  Uint32* tOptionalDataPtr = &tcIndxReq->scanInfo;
+  Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
   Uint32 tDistrGHIndex = tScanIndicator;
-  Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+  Uint32 tDistrKeyIndex = tDistrGHIndex;
 
   Uint32 tScanInfo = theScanInfo;
-  Uint32 tDistributionGroup = theDistributionGroup;
-  Uint32 tDistrKeySize = theDistrKeySize;
+  Uint32 tDistrKey = theDistributionKey;
 
   tOptionalDataPtr[0] = tScanInfo;
-  tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
-  tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+  tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
 
 //-------------------------------------------------------------
 // The next is step is to compress the key data part of the
@@ -611,10 +294,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
 //-------------------------------------------------------------
   Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
   Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
-  Uint32 Tdata1 = tcIndxReq->keyInfo[0];
-  Uint32 Tdata2 = tcIndxReq->keyInfo[1];
-  Uint32 Tdata3 = tcIndxReq->keyInfo[2];
-  Uint32 Tdata4 = tcIndxReq->keyInfo[3];
+  Uint32 Tdata1 = tcKeyReq->keyInfo[0];
+  Uint32 Tdata2 = tcKeyReq->keyInfo[1];
+  Uint32 Tdata3 = tcKeyReq->keyInfo[2];
+  Uint32 Tdata4 = tcKeyReq->keyInfo[3];
   Uint32 Tdata5;
 
   tKeyDataPtr[0] = Tdata1;
@@ -622,10 +305,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
   tKeyDataPtr[2] = Tdata3;
   tKeyDataPtr[3] = Tdata4;
   if (tIndexLen > 4) {
-    Tdata1 = tcIndxReq->keyInfo[4];
-    Tdata2 = tcIndxReq->keyInfo[5];
-    Tdata3 = tcIndxReq->keyInfo[6];
-    Tdata4 = tcIndxReq->keyInfo[7];
+    Tdata1 = tcKeyReq->keyInfo[4];
+    Tdata2 = tcKeyReq->keyInfo[5];
+    Tdata3 = tcKeyReq->keyInfo[6];
+    Tdata4 = tcKeyReq->keyInfo[7];
 
     tKeyDataPtr[4] = Tdata1;
     tKeyDataPtr[5] = Tdata2;
@@ -639,12 +322,12 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
 //-------------------------------------------------------------
   Uint32 tAttrInfoIndex;  
 
-  if (tIndexLen > TcIndxReq::MaxKeyInfo) {
+  if (tIndexLen > TcKeyReq::MaxKeyInfo) {
     /**
      *	Set transid and TC connect ptr in the INDXKEYINFO signals
      */
-    NdbApiSignal* tSignal = theFirstKEYINFO;
-    Uint32 remainingKey = tIndexLen - TcIndxReq::MaxKeyInfo;
+    NdbApiSignal* tSignal = theTCREQ->next();
+    Uint32 remainingKey = tIndexLen - TcKeyReq::MaxKeyInfo;
 
     do {
       Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -665,7 +348,7 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
       }
       tSignal = tnextSignal;
     } while (tSignal != NULL);
-    tAttrInfoIndex = tKeyIndex + TcIndxReq::MaxKeyInfo;
+    tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
   } else {
     tAttrInfoIndex = tKeyIndex + tIndexLen;
   }//if
@@ -675,14 +358,14 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
 // above.
 //-------------------------------------------------------------
   Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
-  Tdata1 = tcIndxReq->attrInfo[0];
-  Tdata2 = tcIndxReq->attrInfo[1];
-  Tdata3 = tcIndxReq->attrInfo[2];
-  Tdata4 = tcIndxReq->attrInfo[3];
-  Tdata5 = tcIndxReq->attrInfo[4];
+  Tdata1 = tcKeyReq->attrInfo[0];
+  Tdata2 = tcKeyReq->attrInfo[1];
+  Tdata3 = tcKeyReq->attrInfo[2];
+  Tdata4 = tcKeyReq->attrInfo[3];
+  Tdata5 = tcKeyReq->attrInfo[4];
 
-  theTCREQ->setLength(tcIndxReq->getAIInTcIndxReq(tReqInfo) + 
-                      tAttrInfoIndex + TcIndxReq::StaticLength);
+  theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) + 
+                      tAttrInfoIndex + TcKeyReq::StaticLength);
   tAIDataPtr[0] = Tdata1;
   tAIDataPtr[1] = Tdata2;
   tAIDataPtr[2] = Tdata3;
@@ -711,11 +394,6 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64  aTransactionId)
   return 0;
 }
 
-void NdbIndexOperation::closeScan()
-{
-  printf("NdbIndexOperation::closeScan NYI\n");
-}
-
 /***************************************************************************
 int receiveTCINDXREF( NdbApiSignal* aSignal)
 
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index b0b95d0ff43..4f39286a624 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -49,7 +49,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
   theCurrentATTRINFO(NULL),
   theTotalCurrAI_Len(0),
   theAI_LenInCurrAI(0),
-  theFirstKEYINFO(NULL),
   theLastKEYINFO(NULL),
 
   theFirstLabel(NULL),
@@ -68,13 +67,11 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
   //theSchemaVersion(0), 
   theTotalNrOfKeyWordInSignal(8),
   theTupKeyLen(0),
-  theNoOfTupKeyDefined(0),
+  theNoOfTupKeyLeft(0),
   theOperationType(NotDefined),
   theStatus(Init),
   theMagicNumber(0xFE11D0),
   theScanInfo(0),
-  theDistrKeySize(0),
-  theDistributionGroup(0),
   m_tcReqGSN(GSN_TCKEYREQ),
   m_keyInfoGSN(GSN_KEYINFO),
   m_attrInfoGSN(GSN_ATTRINFO),
@@ -144,14 +141,11 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
 
   theFirstATTRINFO    = NULL;
   theCurrentATTRINFO  = NULL;
-  theFirstKEYINFO     = NULL;
   theLastKEYINFO      = NULL;  
   
 
-  theTupKeyLen		= 0;
-  theNoOfTupKeyDefined	= 0;
-  theDistrKeySize	= 0;
-  theDistributionGroup	= 0;
+  theTupKeyLen	    = 0;
+  theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();
 
   theTotalCurrAI_Len	= 0;
   theAI_LenInCurrAI	= 0;
@@ -160,9 +154,7 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
   theSimpleIndicator	= 0;
   theDirtyIndicator	= 0;
   theInterpretIndicator	= 0;
-  theDistrGroupIndicator= 0;
-  theDistrGroupType     = 0;
-  theDistrKeyIndicator  = 0;
+  theDistrKeyIndicator_  = 0;
   theScanInfo        	= 0;
   theTotalNrOfKeyWordInSignal = 8;
   theMagicNumber        = 0xABCDEF01;
@@ -208,11 +200,16 @@ NdbOperation::release()
   NdbBlob* tBlob;
   NdbBlob* tSaveBlob;
 
-  if (theTCREQ != NULL)
+  tSignal = theTCREQ;
+  while (tSignal != NULL)
   {
-    theNdb->releaseSignal(theTCREQ);
-  }
+    tSaveSignal = tSignal;
+    tSignal = tSignal->next();
+    theNdb->releaseSignal(tSaveSignal);
+  }				
   theTCREQ = NULL;
+  theLastKEYINFO = NULL;
+
   tSignal = theFirstATTRINFO;
   while (tSignal != NULL)
   {
@@ -222,15 +219,7 @@ NdbOperation::release()
   }
   theFirstATTRINFO = NULL;
   theCurrentATTRINFO = NULL;
-  tSignal = theFirstKEYINFO;
-  while (tSignal != NULL)
-  {
-    tSaveSignal = tSignal;
-    tSignal = tSignal->next();
-    theNdb->releaseSignal(tSaveSignal);
-  }				
-  theFirstKEYINFO = NULL;
-  theLastKEYINFO = NULL;
+
   if (theInterpretIndicator == 1)
   {
     tBranch = theFirstBranch;
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index 35abb15b00d..d9aa860f71f 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -350,7 +350,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
 {
   NdbRecAttr* tRecAttr;
   if ((tAttrInfo != NULL) &&
-      (!tAttrInfo->m_indexOnly) && 
       (theStatus != Init)){
     if (theStatus != GetValue) {
       if (theInterpretIndicator == 1) {
@@ -398,10 +397,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
       setErrorCodeAbort(4004);      
       return NULL;
     }//if
-    if (tAttrInfo->m_indexOnly){
-      setErrorCodeAbort(4208);
-      return NULL;
-    }//if
   }//if
   setErrorCodeAbort(4200);
   return NULL;
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index f1338ae01e4..7fa6627afa8 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -65,7 +65,7 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
   if (tReturnCode == -1) {
     return -1;
   }
-  NdbApiSignal *tSignal = theFirstKEYINFO;
+  NdbApiSignal *tSignal = theTCREQ->next();
   while (tSignal != NULL) {
     NdbApiSignal* tnextSignal = tSignal->next();
     tReturnCode = tp->sendSignal(tSignal, aNodeId);
@@ -201,13 +201,9 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
   abortOption = tSimpleIndicator ? IgnoreError : abortOption;
   tcKeyReq->setAbortOption(tReqInfo, abortOption);
   
-  Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
-  Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
-  Uint8 tDistrGroupType = theDistrGroupType;
+  Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
   Uint8 tScanIndicator = theScanInfo & 1;
 
-  tcKeyReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
-  tcKeyReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
   tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
   tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
 
@@ -218,15 +214,13 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
 //-------------------------------------------------------------
   Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
   Uint32 tDistrGHIndex = tScanIndicator;
-  Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+  Uint32 tDistrKeyIndex = tDistrGHIndex;
 
   Uint32 tScanInfo = theScanInfo;
-  Uint32 tDistributionGroup = theDistributionGroup;
-  Uint32 tDistrKeySize = theDistrKeySize;
+  Uint32 tDistrKey = theDistributionKey;
 
   tOptionalDataPtr[0] = tScanInfo;
-  tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
-  tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+  tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
 
 //-------------------------------------------------------------
 // The next is step is to compress the key data part of the
@@ -266,7 +260,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
     /**
      *	Set transid, TC connect ptr and length in the KEYINFO signals
      */
-    NdbApiSignal* tSignal = theFirstKEYINFO;
+    NdbApiSignal* tSignal = theTCREQ->next();
     Uint32 remainingKey = tTupKeyLen - TcKeyReq::MaxKeyInfo;
     do {
       Uint32* tSigDataPtr = tSignal->getDataPtrSend();
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index 69b4e803acd..4f2d26f4501 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -38,7 +38,9 @@ Adjust:  971022  UABMNST   First version.
 
 #include <AttributeHeader.hpp>
 #include <signaldata/TcKeyReq.hpp>
+#include <signaldata/KeyInfo.hpp>
 #include "NdbDictionaryImpl.hpp"
+#include <md5_hash.hpp>
 
 /******************************************************************************
 CondIdType equal(const char* anAttrName, char* aValue, Uint32 aVarKeylen);
@@ -60,8 +62,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
   Uint32 tData;
   Uint32 tKeyInfoPosition;
   const char* aValue = aValuePassed;
-  Uint32 xfrmData[1024];
-  Uint32 tempData[1024];
+  Uint64 xfrmData[512];
+  Uint64 tempData[512];
 
   if ((theStatus == OperationDefined) &&
       (aValue != NULL) &&
@@ -76,6 +78,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
  *****************************************************************************/
     tAttrId = tAttrInfo->m_attrId;
     tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
+    bool tDistrKey = tAttrInfo->m_distributionKey;
+
     Uint32 i = 0;
     if (tAttrInfo->m_pk) {
       Uint32 tKeyDefined = theTupleKeyDefined[0][2];
@@ -119,30 +123,30 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
 
     Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
     {
-      /***************************************************************************
-       *	Check if the pointer of the value passed is aligned on a 4 byte 
-       *      boundary. If so only assign the pointer to the internal variable 
-       *      aValue. If it is not aligned then we start by copying the value to 
-       *      tempData and use this as aValue instead.
-       *****************************************************************************/
+      /************************************************************************
+       * Check if the pointer of the value passed is aligned on a 4 byte 
+       * boundary. If so only assign the pointer to the internal variable 
+       * aValue. If it is not aligned then we start by copying the value to 
+       * tempData and use this as aValue instead.
+       ***********************************************************************/
       const int attributeSize = sizeInBytes;
       const int slack = sizeInBytes & 3;
-      
-      if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
+      const int align = UintPtr(aValue) & 7;
+
+      if (((align & 3) != 0) || (slack != 0) || (tDistrKey && (align != 0)))
+      {
+	((Uint32*)tempData)[attributeSize >> 2] = 0;
 	memcpy(&tempData[0], aValue, attributeSize);
 	aValue = (char*)&tempData[0];
-	if(slack != 0) {
-	  char * tmp = (char*)&tempData[0];
-	  memset(&tmp[attributeSize], 0, (4 - slack));
-	}//if
       }//if
     }
     const char* aValueToWrite = aValue;
-
+    
     CHARSET_INFO* cs = tAttrInfo->m_cs;
     if (cs != 0) {
       // current limitation: strxfrm does not increase length
       assert(cs->strxfrm_multiply == 1);
+      ((Uint32*)xfrmData)[sizeInBytes >> 2] = 0;
       unsigned n =
       (*cs->coll->strnxfrm)(cs,
                             (uchar*)xfrmData, sizeof(xfrmData),
@@ -152,9 +156,7 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
       aValue = (char*)xfrmData;
     }
 
-    Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
     Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
-    Uint32 sizeInWords = sizeInBytes / 4;          // Exc. bits in last word
     
     if (true){ //tArraySize != 0) {
       Uint32 tTupKeyLen = theTupKeyLen;
@@ -190,84 +192,49 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
     }//if
 #endif
 
-    int tDistrKey = tAttrInfo->m_distributionKey;
-    int tDistrGroup = tAttrInfo->m_distributionGroup;
     OperationType tOpType = theOperationType;
-    if ((tDistrKey != 1) && (tDistrGroup != 1)) {
-      ;
-    } else if (tDistrKey == 1) {
-      theDistrKeySize += totalSizeInWords;
-      theDistrKeyIndicator = 1;
-    } else {
-      Uint32 TsizeInBytes = sizeInBytes;
-      Uint32 TbyteOrderFix = 0;
-      char*   TcharByteOrderFix = (char*)&TbyteOrderFix;
-      if (tAttrInfo->m_distributionGroupBits == 8) {
-	char tFirstChar = aValue[TsizeInBytes - 2];
-	char tSecondChar = aValue[TsizeInBytes - 2];
-	TcharByteOrderFix[0] = tFirstChar;
-	TcharByteOrderFix[1] = tSecondChar;
-	TcharByteOrderFix[2] = 0x30;
-	TcharByteOrderFix[3] = 0x30;
-	theDistrGroupType = 0;
-      } else {
-	TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10) 
-	  + (aValue[TsizeInBytes - 1] - 0x30);
-	theDistrGroupType = 1;
-      }//if
-      theDistributionGroup = TbyteOrderFix;
-      theDistrGroupIndicator = 1;
-    }//if
-    /******************************************************************************
+    /**************************************************************************
      *	If the operation is an insert request and the attribute is stored then
      *      we also set the value in the stored part through putting the 
      *      information in the ATTRINFO signals.
-     *****************************************************************************/
+     *************************************************************************/
     if ((tOpType == InsertRequest) ||
 	(tOpType == WriteRequest)) {
-      if (!tAttrInfo->m_indexOnly){
-        // invalid data can crash kernel
-        if (cs != NULL &&
-           (*cs->cset->well_formed_len)(cs,
-                                        aValueToWrite,
-                                        aValueToWrite + sizeInBytes,
-                                        sizeInBytes) != sizeInBytes)
-          goto equal_error4;
-	Uint32 ahValue;
-	const Uint32 sz = totalSizeInWords;
-	AttributeHeader::init(&ahValue, tAttrId, sz);
-	insertATTRINFO( ahValue );
-	insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
-	if (bitsInLastWord != 0) {
-	  tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
-	  tData = convertEndian(tData);
-	  tData = tData & ((1 << bitsInLastWord) - 1);
-	  tData = convertEndian(tData);
-	  insertATTRINFO( tData );
-	}//if
-      }//if
+      // invalid data can crash kernel
+      if (cs != NULL &&
+	  (*cs->cset->well_formed_len)(cs,
+				       aValueToWrite,
+				       aValueToWrite + sizeInBytes,
+				       sizeInBytes) != sizeInBytes)
+	goto equal_error4;
+      Uint32 ahValue;
+      const Uint32 sz = totalSizeInWords;
+      AttributeHeader::init(&ahValue, tAttrId, sz);
+      insertATTRINFO( ahValue );
+      insertATTRINFOloop((Uint32*)aValueToWrite, sz);
     }//if
     
-    /***************************************************************************
+    /**************************************************************************
      *	Store the Key information in the TCKEYREQ and KEYINFO signals. 
-     **************************************************************************/
-    if (insertKEYINFO(aValue, tKeyInfoPosition, 
-		      totalSizeInWords, bitsInLastWord) != -1) {
-      /*************************************************************************
+     *************************************************************************/
+    if (insertKEYINFO(aValue, tKeyInfoPosition, totalSizeInWords) != -1) {
+      /************************************************************************
        * Add one to number of tuple key attributes defined. 
        * If all have been defined then set the operation state to indicate 
        * that tuple key is defined. 
        * Thereby no more search conditions are allowed in this version.
-       ************************************************************************/
-      Uint32 tNoKeysDef = theNoOfTupKeyDefined;
+       ***********************************************************************/
+      Uint32 tNoKeysDef = theNoOfTupKeyLeft - 1;
       Uint32 tErrorLine = theErrorLine;
-      int tNoTableKeys = m_currentTable->m_noOfKeys;
       unsigned char tInterpretInd = theInterpretIndicator;
-      tNoKeysDef++;
-      theNoOfTupKeyDefined = tNoKeysDef;
+      theNoOfTupKeyLeft = tNoKeysDef;
       tErrorLine++;
       theErrorLine = tErrorLine;
-      if (int(tNoKeysDef) == tNoTableKeys) {
+
+      if(tDistrKey)
+	handle_distribution_key((Uint64*)aValue, totalSizeInWords);
+      
+      if (tNoKeysDef == 0) {	
 	if (tOpType == UpdateRequest) {
 	  if (tInterpretInd == 1) {
 	    theStatus = GetValue;
@@ -297,13 +264,14 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
 	  setErrorCodeAbort(4005);
 	  return -1;
 	}//if
+	return 0;
       }//if
-      return 0;
     } else {
       return -1;
     }//if
+    return 0;
   }
-
+  
   if (aValue == NULL) {
     // NULL value in primary key
     setErrorCodeAbort(4505);
@@ -321,6 +289,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
     setErrorCodeAbort(4225);
     return -1;
   }//if
+
+  ndbout_c("theStatus: %d", theStatus);
   
   // If we come here, set a general errorcode
   // and exit
@@ -387,8 +357,7 @@ NdbOperation::setTupleId()
 int
 NdbOperation::insertKEYINFO(const char* aValue,
 			    register Uint32 aStartPosition,
-			    register Uint32 anAttrSizeInWords,
-			    register Uint32 anAttrBitsInLastWord)
+			    register Uint32 anAttrSizeInWords)
 {
   NdbApiSignal* tSignal;
   NdbApiSignal* tCurrentKEYINFO;
@@ -408,7 +377,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
  *****************************************************************************/
   tEndPos = aStartPosition + anAttrSizeInWords - 1;
 
-  if ((tEndPos < 9) && (anAttrBitsInLastWord == 0)) {
+  if ((tEndPos < 9)) {
     register Uint32 tkeyData = *(Uint32*)aValue;
     //TcKeyReq* tcKeyReq = CAST_PTR(TcKeyReq, tTCREQ->getDataPtrSend());
     register Uint32* tDataPtr = (Uint32*)aValue;
@@ -449,10 +418,11 @@ NdbOperation::insertKEYINFO(const char* aValue,
       setErrorCodeAbort(4001);
       return -1;
     }
-    if (theFirstKEYINFO != NULL)
+    if (theTCREQ->next() != NULL)
        theLastKEYINFO->next(tSignal);
     else
-       theFirstKEYINFO = tSignal;
+      theTCREQ->next(tSignal);
+
     theLastKEYINFO = tSignal;
     theLastKEYINFO->next(NULL);
     theTotalNrOfKeyWordInSignal += 20;
@@ -465,7 +435,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
  *	this is the first word in a KEYINFO signal.			     *
  *****************************************************************************/
   tPosition = aStartPosition;
-  tCurrentKEYINFO = theFirstKEYINFO;
+  tCurrentKEYINFO = theTCREQ->next();
  
 /*****************************************************************************
  *	Start by filling up Key information in the 8 words allocated in the  *
@@ -518,39 +488,20 @@ NdbOperation::insertKEYINFO(const char* aValue,
   } while (1);
 
 LastWordLabel:
-
-/*****************************************************************************
- *	There could be a last word that only contains partial data. This word*
- *	will contain zeroes in the rest of the bits since the index expects  *
- *	a certain number of words and do not care for parts of words.	     *
- *****************************************************************************/
-  if (anAttrBitsInLastWord != 0) {
-    tData = *(Uint32*)(aValue + (anAttrSizeInWords - 1) * 4);
-    tData = convertEndian(tData);
-    tData = tData & ((1 << anAttrBitsInLastWord) - 1);
-    tData = convertEndian(tData);
-    if (tPosition > 8) {
-      tCurrentKEYINFO->setData(tData, signalCounter);
-      signalCounter++;
-    } else {
-      theTCREQ->setData(tData, (12 + tPosition));
-    }//if
-  }//if
-
   return 0;
 }
 
 int
 NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
 {
-  assert(m_accessTable != 0 && m_accessTable->m_sizeOfKeysInWords != 0);
-  assert(m_accessTable->m_sizeOfKeysInWords == size);
+  assert(m_accessTable != 0 && m_accessTable->m_keyLenInWords != 0);
+  assert(m_accessTable->m_keyLenInWords == size);
   unsigned pos = 0;
   while (pos < 8 && pos < size) {
     data[pos] = theKEYINFOptr[pos];
     pos++;
   }
-  NdbApiSignal* tSignal = theFirstKEYINFO;
+  NdbApiSignal* tSignal = theTCREQ->next();
   unsigned n = 0;
   while (pos < size) {
     if (n == 20) {
@@ -561,3 +512,113 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
   }
   return 0;
 }
+
+int
+NdbOperation::handle_distribution_key(const Uint64* value, Uint32 len)
+{
+  if(theDistrKeyIndicator_ == 1 || 
+     (theNoOfTupKeyLeft > 0 && m_accessTable->m_noOfDistributionKeys > 1))
+  {
+    return 0;
+  }
+  
+  if(m_accessTable->m_noOfDistributionKeys == 1)
+  {
+    setPartitionHash(value, len);
+  }
+  else 
+  {
+    /**
+     * Copy distribution key to linear memory
+     */
+    NdbColumnImpl* const * cols = m_accessTable->m_columns.getBase();
+    Uint32 len = 0;
+    Uint64 tmp[1000];
+
+    Uint32 chunk = 8;
+    Uint32* dst = (Uint32*)tmp;
+    NdbApiSignal* tSignal = theTCREQ;
+    Uint32* src = ((TcKeyReq*)tSignal->getDataPtrSend())->keyInfo;
+    if(tSignal->readSignalNumber() == GSN_SCAN_TABREQ)
+    {
+      tSignal = tSignal->next();
+      src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+      chunk = KeyInfo::DataLength;
+    }
+
+    for(unsigned i = m_accessTable->m_columns.size(); i>0; cols++, i--)
+    {
+      if (!(* cols)->getPrimaryKey())
+	continue;
+      
+      NdbColumnImpl* tAttrInfo = * cols;
+      Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+      Uint32 currLen = (sizeInBytes + 3) >> 2;
+      if (tAttrInfo->getDistributionKey())
+      {
+	while (currLen >= chunk)
+	{
+	  memcpy(dst, src, 4*chunk);
+	  dst += chunk;
+	  tSignal = tSignal->next();
+	  src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+	  currLen -= chunk;
+	  chunk = KeyInfo::DataLength;
+	}
+
+	memcpy(dst, src, 4*currLen);
+	dst += currLen;
+	src += currLen;
+	chunk -= currLen;
+      }
+      else
+      {
+	while (currLen >= chunk)
+	{
+	  tSignal = tSignal->next();
+	  src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+	  currLen -= chunk;
+	  chunk = KeyInfo::DataLength;
+	}
+	
+	src += currLen;
+	chunk -= currLen;
+      }
+    }
+    setPartitionHash(tmp, (Uint32*)tmp - dst);
+  }
+  return 0;
+}
+
+void
+NdbOperation::setPartitionHash(Uint32 value)
+{
+  union {
+    Uint32 tmp32;
+    Uint64 tmp64;
+  };
+
+  tmp32 = value;
+  setPartitionHash(&tmp64, 1);
+}
+
+void
+NdbOperation::setPartitionHash(const Uint64* value, Uint32 len)
+{
+  Uint32 buf[4];
+  md5_hash(buf, value, len);
+  setPartitionId(buf[1]);
+}
+
+void
+NdbOperation::setPartitionId(Uint32 value)
+{
+  theDistributionKey = value;
+  theDistrKeyIndicator_ = 1;
+}
+
+Uint32
+NdbOperation::getPartitionId() const 
+{
+  return theDistributionKey;
+}
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index fd63ce96f25..b2e7d6b425c 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -118,7 +118,7 @@ NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
   theStatus = GetValue;
   theOperationType = OpenScanRequest;
   theNdbCon->theMagicNumber = 0xFE11DF;
-
+  theNoOfTupKeyLeft = tab->m_noOfDistributionKeys;
   return 0;
 }
 
@@ -199,6 +199,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
     return 0;
   }//if
   
+  theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ);
   ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
   req->apiConnectPtr = theNdbCon->theTCConPtr;
   req->tableId = m_accessTable->m_tableId;
@@ -219,16 +220,17 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
   req->transId1 = (Uint32) transId;
   req->transId2 = (Uint32) (transId >> 32);
 
-  NdbApiSignal* tSignal = 
-    theFirstKEYINFO;
-
-  theFirstKEYINFO = (tSignal ? tSignal : tSignal = theNdb->getSignal());
+  NdbApiSignal* tSignal = theSCAN_TABREQ->next();
+  if(!tSignal)
+  {
+    theSCAN_TABREQ->next(tSignal = theNdb->getSignal());
+  }
   theLastKEYINFO = tSignal;
   
   tSignal->setSignal(GSN_KEYINFO);
   theKEYINFOptr = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
   theTotalNrOfKeyWordInSignal= 0;
-
+  
   getFirstATTRINFOScan();
   return getResultSet();
 }
@@ -348,60 +350,6 @@ NdbScanOperation::getFirstATTRINFOScan()
 #define FAKE_PTR 2
 #define API_PTR 3
 
-
-/*
- * After setBound() are done, move the accumulated ATTRINFO signals to
- * a separate list.  Then continue with normal scan.
- */
-#if 0
-int
-NdbIndexScanOperation::saveBoundATTRINFO()
-{
-  theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
-  theBoundATTRINFO = theFirstATTRINFO;
-  theTotalBoundAI_Len = theTotalCurrAI_Len;
-  theTotalCurrAI_Len = 5;
-  theBoundATTRINFO->setData(theTotalBoundAI_Len, 4);
-  theBoundATTRINFO->setData(0, 5);
-  theBoundATTRINFO->setData(0, 6);
-  theBoundATTRINFO->setData(0, 7);
-  theBoundATTRINFO->setData(0, 8);
-  theStatus = GetValue;
-
-  int res = getFirstATTRINFOScan();
-
-  /**
-   * Define each key with getValue (if ordered)
-   *   unless the one's with EqBound
-   */
-  if(!res && m_ordered){
-
-    /**
-     * If setBound EQ
-     */
-    Uint32 i = 0;
-    while(theTupleKeyDefined[i][0] == SETBOUND_EQ)
-      i++;
-    
-    
-    Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
-    m_sort_columns = cnt - i;
-    for(; i<cnt; i++){
-      const NdbColumnImpl* key = m_accessTable->m_index->m_columns[i];
-      const NdbColumnImpl* col = m_currentTable->getColumn(key->m_keyInfoPos);
-      NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1);
-      UintPtr newVal = UintPtr(tmp);
-      theTupleKeyDefined[i][0] = FAKE_PTR;
-      theTupleKeyDefined[i][1] = (newVal & 0xFFFFFFFF);
-#if (SIZEOF_CHARP == 8)
-      theTupleKeyDefined[i][2] = (newVal >> 32);
-#endif
-    }
-  }
-  return res;
-}
-#endif
-
 #define WAITFOR_SCAN_TIMEOUT 120000
 
 int
@@ -683,12 +631,14 @@ void NdbScanOperation::release()
   for(Uint32 i = 0; i<m_allocated_receivers; i++){
     m_receivers[i]->release();
   }
+
+  NdbOperation::release();
+  
   if(theSCAN_TABREQ)
   {
     theNdb->releaseSignal(theSCAN_TABREQ);
     theSCAN_TABREQ = 0;
   }
-  NdbOperation::release();
 }
 
 /***************************************************************************
@@ -783,10 +733,6 @@ NdbScanOperation::doSendScan(int aProcessorId)
   
   assert(theSCAN_TABREQ != NULL);
   tSignal = theSCAN_TABREQ;
-  if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
-    setErrorCode(4001);
-    return -1;
-  }
   
   Uint32 tupKeyLen = theTupKeyLen;
   Uint32 len = theTotalNrOfKeyWordInSignal;
@@ -798,6 +744,10 @@ NdbScanOperation::doSendScan(int aProcessorId)
   // we created the ATTRINFO signals after the SCAN_TABREQ signal.
   ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
   req->attrLenKeyLen = (tupKeyLen << 16) | theTotalCurrAI_Len;
+  Uint32 tmp = req->requestInfo;
+  ScanTabReq::setDistributionKeyFlag(tmp, theDistrKeyIndicator_);
+  req->distributionKey = theDistributionKey;
+  tSignal->setLength(ScanTabReq::StaticLength + theDistrKeyIndicator_);
   
   TransporterFacade *tp = TransporterFacade::instance();
   LinearSectionPtr ptr[3];
@@ -814,8 +764,8 @@ NdbScanOperation::doSendScan(int aProcessorId)
     tSignal = theLastKEYINFO;
     tSignal->setLength(KeyInfo::HeaderLength + theTotalNrOfKeyWordInSignal);
     
-    assert(theFirstKEYINFO != NULL);
-    tSignal = theFirstKEYINFO;
+    assert(theSCAN_TABREQ->next() != NULL);
+    tSignal = theSCAN_TABREQ->next();
     
     NdbApiSignal* last;
     do {
@@ -942,7 +892,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
     
     if(i < len){
       NdbApiSignal* tSignal = theNdb->getSignal();
-      newOp->theFirstKEYINFO = tSignal;      
+      newOp->theTCREQ->next(tSignal); 
       
       Uint32 left = len - i;
       while(tSignal && left > KeyInfo::DataLength){
@@ -1077,37 +1027,51 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
     Uint32 currLen = theTotalNrOfKeyWordInSignal;
     Uint32 remaining = KeyInfo::DataLength - currLen;
     Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+    bool tDistrKey = tAttrInfo->m_distributionKey;
 
-    // normalize char bound
-    CHARSET_INFO* cs = tAttrInfo->m_cs;
-    Uint32 xfrmData[2000];
-    if (cs != NULL && aValue != NULL) {
-      // current limitation: strxfrm does not increase length
-      assert(cs->strxfrm_multiply == 1);
-      unsigned n =
-      (*cs->coll->strnxfrm)(cs,
-                            (uchar*)xfrmData, sizeof(xfrmData),
-                            (const uchar*)aValue, sizeInBytes);
-      while (n < sizeInBytes)
-        ((uchar*)xfrmData)[n++] = 0x20;
-      aValue = (char*)xfrmData;
-    }
+    len = aValue != NULL ? sizeInBytes : 0;
     if (len != sizeInBytes && (len != 0)) {
       setErrorCodeAbort(4209);
       return -1;
     }
+    
+    // normalize char bound
+    CHARSET_INFO* cs = tAttrInfo->m_cs;
+    Uint64 xfrmData[1001];
+    if (cs != NULL && aValue != NULL) {
+      // current limitation: strxfrm does not increase length
+      assert(cs->strxfrm_multiply == 1);
+      ((Uint32*)xfrmData)[len >> 2] = 0;
+      unsigned n =
+	(*cs->coll->strnxfrm)(cs,
+                            (uchar*)xfrmData, sizeof(xfrmData),
+                            (const uchar*)aValue, len);
+      
+      while (n < len)
+        ((uchar*)xfrmData)[n++] = 0x20;
+
+      if(len & 3)
+      {
+	len += (4 - (len & 3));
+      }
+
+      aValue = (char*)xfrmData;
+    }
+
     // insert attribute header
-    len = aValue != NULL ? sizeInBytes : 0;
     Uint32 tIndexAttrId = tAttrInfo->m_attrId;
     Uint32 sizeInWords = (len + 3) / 4;
     AttributeHeader ah(tIndexAttrId, sizeInWords);
     const Uint32 ahValue = ah.m_value;
 
-    const bool aligned = (UintPtr(aValue) & 3) == 0;
+    const Uint32 align = (UintPtr(aValue) & 7);
+    const bool aligned = (tDistrKey && type == BoundEQ) ? 
+      (align == 0) : (align & 3) == 0;
+
     const bool nobytes = (len & 0x3) == 0;
     const Uint32 totalLen = 2 + sizeInWords;
     Uint32 tupKeyLen = theTupKeyLen;
-    if(remaining > totalLen &&  aligned && nobytes){
+    if(remaining > totalLen && aligned && nobytes){
       Uint32 * dst = theKEYINFOptr + currLen;
       * dst ++ = type;
       * dst ++ = ahValue;
@@ -1115,12 +1079,12 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
       theTotalNrOfKeyWordInSignal = currLen + totalLen;
     } else {
       if(!aligned || !nobytes){
-	Uint32 tempData[2002];
+	Uint32 *tempData = (Uint32*)xfrmData;
 	tempData[0] = type;
 	tempData[1] = ahValue;
+	tempData[2 + (len >> 2)] = 0;
         memcpy(tempData+2, aValue, len);
-        while ((len & 0x3) != 0)
-          ((char*)&tempData[2])[len++] = 0;
+	
 	insertBOUNDS(tempData, 2+sizeInWords);
       } else {
 	Uint32 buf[2] = { type, ahValue };
@@ -1139,11 +1103,11 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
      * so it's safe to use [tIndexAttrId] 
      * (instead of looping as is NdbOperation::equal_impl)
      */
-    if(type == BoundEQ && !theTupleKeyDefined[tIndexAttrId][0]){
-      theNoOfTupKeyDefined++;
-      theTupleKeyDefined[tIndexAttrId][0] = SETBOUND_EQ;
+    if(type == BoundEQ && tDistrKey)
+    {
+      theNoOfTupKeyLeft--;
+      return handle_distribution_key((Uint64*)aValue, sizeInWords);
     }
-    
     return 0;
   } else {
     setErrorCodeAbort(4228);    // XXX wrong code
@@ -1559,10 +1523,12 @@ NdbIndexScanOperation::reset_bounds(){
     theError.code = 0;
     reset_receivers(theParallelism, m_ordered);
     
-    theLastKEYINFO = theFirstKEYINFO;
-    theKEYINFOptr = ((KeyInfo*)theFirstKEYINFO->getDataPtrSend())->keyData;
+    theLastKEYINFO = theSCAN_TABREQ->next();
+    theKEYINFOptr = ((KeyInfo*)theLastKEYINFO->getDataPtrSend())->keyData;
     theTupKeyLen = 0;
     theTotalNrOfKeyWordInSignal = 0;
+    theNoOfTupKeyLeft = m_accessTable->m_noOfDistributionKeys;
+    theDistrKeyIndicator_ = 0;
     m_transConnection
       ->remove_list((NdbOperation*&)m_transConnection->m_firstExecutedScanOp,
 		    this);
diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp
index aa78f7d4e2c..fb0df8aa35b 100644
--- a/ndb/test/include/NDBT_Tables.hpp
+++ b/ndb/test/include/NDBT_Tables.hpp
@@ -23,11 +23,13 @@
 #include <NdbDictionary.hpp>
 #include <NDBT_Table.hpp>
 
+typedef int (* NDBT_CreateTableHook)(Ndb*, NdbDictionary::Table&, int when);
+
 class NDBT_Tables {
 public:
-  
+
   static int createTable(Ndb* pNdb, const char* _name, bool _temp = false, 
-			 bool existsOK = false);
+			 bool existsOK = false, NDBT_CreateTableHook = 0);
   static int createAllTables(Ndb* pNdb, bool _temp, bool existsOK = false);
   static int createAllTables(Ndb* pNdb);
 
diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp
index e8e2d992345..d3da8ae4ba2 100644
--- a/ndb/test/src/HugoOperations.cpp
+++ b/ndb/test/src/HugoOperations.cpp
@@ -456,11 +456,6 @@ int HugoOperations::setValueForAttr(NdbOperation* pOp,
   int check = 0;
   const NdbDictionary::Column* attr = tab.getColumn(attrId);     
 
-  if (attr->getTupleKey()){
-    // Don't set values for TupleId PKs
-    return check;
-  }
-  
   switch (attr->getType()){
   case NdbDictionary::Column::Char:
   case NdbDictionary::Column::Varchar:
diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp
index ff6db3e892c..b61d48b216c 100644
--- a/ndb/test/src/NDBT_Tables.cpp
+++ b/ndb/test/src/NDBT_Tables.cpp
@@ -820,21 +820,25 @@ NDBT_Tables::createAllTables(Ndb* pNdb){
 
 int
 NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, 
-			 bool existsOk){
+			 bool existsOk, NDBT_CreateTableHook f){
   
   const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name);
   if (tab == NULL){
     ndbout << "Could not create table " << _name 
 	   << ", it doesn't exist in list of tables "\
-              "that NDBT_Tables can create!" << endl;
+      "that NDBT_Tables can create!" << endl;
     return NDBT_WRONGARGS;
   }
-
+  
   int r = 0;
   do {
     NdbDictionary::Table tmpTab(* tab);
     tmpTab.setStoredTable(_temp ? 0 : 1);
-  
+    if(f != 0 && f(pNdb, tmpTab, 0))
+    {
+      ndbout << "Failed to create table" << endl;
+      return NDBT_FAILED;
+    }      
     r = pNdb->getDictionary()->createTable(tmpTab);
     if(r == -1){
       if(!existsOk){
@@ -883,6 +887,11 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp,
 	}
       }
     }
+    if(f != 0 && f(pNdb, tmpTab, 1))
+    {
+      ndbout << "Failed to create table" << endl;
+      return NDBT_FAILED;
+    }      
   } while(false);
   
   return r;
diff --git a/ndb/test/src/NdbSchemaOp.cpp b/ndb/test/src/NdbSchemaOp.cpp
index a296094ea9d..9bce0b10fc3 100644
--- a/ndb/test/src/NdbSchemaOp.cpp
+++ b/ndb/test/src/NdbSchemaOp.cpp
@@ -158,7 +158,6 @@ NdbSchemaOp::createAttribute( const char* anAttrName,
     col.setPrimaryKey(false);
 
   col.setDistributionKey(aDistributionKeyFlag);
-  col.setDistributionGroup(aDistributionGroupFlag,aDistributionGroupNoOfBits);
   col.setAutoIncrement(aAutoIncrement);
   col.setDefaultValue(aDefaultValue != 0 ? aDefaultValue : "");