List:Commits« Previous MessageNext Message »
From:knielsen Date:February 14 2007 12:42pm
Subject:bk commit into 5.1 tree (knielsen:1.2434)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of knielsen. When knielsen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-02-14 13:42:31+01:00, knielsen@ymer.(none) +9 -0
  WL#2223: NdbRecord.
  Implement unique hash index operations for NdbRecord.

  storage/ndb/include/ndbapi/NdbIndexOperation.hpp@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +2 -1
    Implement unique index operations.

  storage/ndb/include/ndbapi/NdbTransaction.hpp@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +28 -2
    Implement unique index operations.

  storage/ndb/ndbapi-examples/Makefile@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +1 -0
    Implement unique index operations.

  storage/ndb/ndbapi-examples/ndbapi_simple_index_ndbrecord/ndbapi_simple_index_ndbrecord.cpp@stripped, 2007-02-14 13:42:29+01:00, knielsen@ymer.(none) +335 -0
    New BitKeeper file ``storage/ndb/ndbapi-examples/ndbapi_simple_index_ndbrecord/ndbapi_simple_index_ndbrecord.cpp''

  storage/ndb/ndbapi-examples/ndbapi_simple_index_ndbrecord/ndbapi_simple_index_ndbrecord.cpp@stripped, 2007-02-14 13:42:29+01:00, knielsen@ymer.(none) +0 -0

  storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +2 -1
    Implement unique index operations.

  storage/ndb/src/ndbapi/NdbIndexOperation.cpp@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +3 -2
    Implement unique index operations.

  storage/ndb/src/ndbapi/NdbOperationExec.cpp@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +1 -1
    Implement unique index operations.

  storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2007-02-14 13:42:28+01:00, knielsen@ymer.(none) +63 -67
    Implement unique index operations.

  storage/ndb/src/ndbapi/TransporterFacade.cpp@stripped, 2007-02-14 13:42:29+01:00, knielsen@ymer.(none) +1 -1
    Fix typo.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	knielsen
# Host:	ymer.(none)
# Root:	/usr/local/mysql/mysql-5.1-wl2223
--- New file ---
+++ storage/ndb/ndbapi-examples/ndbapi_simple_index_ndbrecord/ndbapi_simple_index_ndbrecord.cpp	07/02/14 13:42:29
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

//
//  ndbapi_simple_index_ndbrecord.cpp: Using secondary hash indexes in NDB API,
//  utilising the NdbRecord interface.
//
//  Correct output from this program is:
//
//  ATTR1 ATTR2
//    0     0
//    1     1
//    2     2
//    3     3
//    4     4
//    5     5
//    6     6
//    7     7
//    8     8
//    9     9
//  ATTR1 ATTR2
//    0    10
//    1     1
//    2    12
//  Detected that deleted tuple doesn't exist!
//    4    14
//    5     5
//    6    16
//    7     7
//    8    18
//    9     9

#include <mysql.h>
#include <NdbApi.hpp>

// Used for cout
#include <stdio.h>
#include <iostream>

#define PRINT_ERROR(code,msg) \
  std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
            << ", code: " << code \
            << ", msg: " << msg << "." << std::endl
#define MYSQLERROR(mysql) { \
  PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
  exit(1); }
#define APIERROR(error) { \
  PRINT_ERROR(error.code,error.message); \
  exit(1); }

int main(int argc, char** argv)
{
  if (argc != 3)
    {
    std::cout << "Arguments are <socket mysqld> <connect_string cluster>.\n";
    exit(1);
  }
  char * mysqld_sock  = argv[1];
  const char *connectstring = argv[2];
  ndb_init();
  MYSQL mysql;

  /**************************************************************
   * Connect to mysql server and create table                   *
   **************************************************************/
  {
    if ( !mysql_init(&mysql) ) {
      std::cout << "mysql_init failed\n";
      exit(1);
    }
    if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
                             0, mysqld_sock, 0) )
      MYSQLERROR(mysql);

    mysql_query(&mysql, "CREATE DATABASE TEST_DB_1");
    if (mysql_query(&mysql, "USE TEST_DB_1") != 0)
      MYSQLERROR(mysql);

    mysql_query(&mysql, "DROP TABLE MYTABLENAME");
    if (mysql_query(&mysql,
                    "CREATE TABLE"
                    "  MYTABLENAME"
                    "    (ATTR1 INT UNSIGNED,"
                    "     ATTR2 INT UNSIGNED NOT NULL,"
                    "     PRIMARY KEY USING HASH (ATTR1),"
                    "     UNIQUE MYINDEXNAME USING HASH (ATTR2))"
                    "  ENGINE=NDB"))
      MYSQLERROR(mysql);
  }

  /**************************************************************
   * Connect to ndb cluster                                     *
   **************************************************************/

  Ndb_cluster_connection *cluster_connection=
    new Ndb_cluster_connection(connectstring); // Object representing the cluster

  if (cluster_connection->connect(5,3,1))
  {
    std::cout << "Connect to cluster management server failed.\n";
    exit(1);
  }

  if (cluster_connection->wait_until_ready(30,30))
  {
    std::cout << "Cluster was not ready within 30 secs.\n";
    exit(1);
  }

  Ndb* myNdb = new Ndb( cluster_connection,
                        "TEST_DB_1" );  // Object representing the database
  if (myNdb->init() == -1) {
    APIERROR(myNdb->getNdbError());
    exit(1);
  }

  NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
  const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
  if (myTable == NULL)
    APIERROR(myDict->getNdbError());
  const NdbDictionary::Index *myIndex= myDict->getIndex("MYINDEXNAME$unique","MYTABLENAME");
  if (myIndex == NULL)
    APIERROR(myDict->getNdbError());

  /* Create NdbRecord descriptors. */
  const NdbDictionary::Column *col1= myTable->getColumn("ATTR1");
  if (col1 == NULL)
    APIERROR(myDict->getNdbError());
  const NdbDictionary::Column *col2= myTable->getColumn("ATTR2");
  if (col2 == NULL)
    APIERROR(myDict->getNdbError());

  /* NdbRecord for primary key lookup. */
  NdbDictionary::RecordSpecification spec[2];
  spec[0].column= col1;
  spec[0].offset= 0;
  spec[0].nullbit_byte_offset= 0;
  spec[0].nullbit_bit_in_byte= 0;
  const NdbRecord *pk_record=
    myDict->createRecord(myTable, spec, 1, sizeof(spec[0]));
  if (pk_record == NULL)
    APIERROR(myDict->getNdbError());

  /* NdbRecord for all table attributes (insert/read). */
  spec[0].column= col1;
  spec[0].offset= 0;
  spec[0].nullbit_byte_offset= 0;
  spec[0].nullbit_bit_in_byte= 0;
  spec[1].column= col2;
  spec[1].offset= 4;
  spec[1].nullbit_byte_offset= 0;
  spec[1].nullbit_bit_in_byte= 0;
  const NdbRecord *attr_record=
    myDict->createRecord(myTable, spec, 2, sizeof(spec[0]));
  if (attr_record == NULL)
    APIERROR(myDict->getNdbError());

  /* NdbRecord for unique key lookup. */
  spec[0].column= col2;
  spec[0].offset= 4;
  spec[0].nullbit_byte_offset= 0;
  spec[0].nullbit_bit_in_byte= 0;
  const NdbRecord *key_record=
    myDict->createRecord(myIndex, spec, 1, sizeof(spec[0]));
  if (key_record == NULL)
    APIERROR(myDict->getNdbError());
  char row[2][8];

  /**************************************************************************
   * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
   **************************************************************************/
  for (int i = 0; i < 5; i++) {
    NdbTransaction *myTransaction= myNdb->startTransaction();
    if (myTransaction == NULL) APIERROR(myNdb->getNdbError());

    /*
      Fill in rows with data. We need two rows, as the data must remain valid
      until NdbTransaction::execute() returns.
    */
    memcpy(&row[0][0], &i, 4);
    memcpy(&row[0][4], &i, 4);
    int value= i+5;
    memcpy(&row[1][0], &value, 4);
    memcpy(&row[1][4], &value, 4);

    NdbOperation *myOperation=
      myTransaction->insertTuple(attr_record, &row[0][0]);
    if (myOperation == NULL)
      APIERROR(myTransaction->getNdbError());
    myOperation= 
      myTransaction->insertTuple(attr_record, &row[1][0]);
    if (myOperation == NULL)
      APIERROR(myTransaction->getNdbError());

    if (myTransaction->execute( NdbTransaction::Commit ) == -1)
      APIERROR(myTransaction->getNdbError());

    myNdb->closeTransaction(myTransaction);
  }

  /*****************************************
   * Read and print all tuples using index *
   *****************************************/
  std::cout << "ATTR1 ATTR2" << std::endl;

  for (int i = 0; i < 10; i++) {
    NdbTransaction *myTransaction= myNdb->startTransaction();
    if (myTransaction == NULL)
      APIERROR(myNdb->getNdbError());

    memcpy(&row[0][4], &i, 4);
    unsigned char mask[1]= { 0x01 };            // Only read ATTR1
    NdbOperation *myOperation=
      myTransaction->readTuple(key_record, &row[0][0],
                               attr_record, &row[1][0],
                               NdbOperation::LM_Read, mask);
    if (myOperation == NULL)
      APIERROR(myTransaction->getNdbError());

    if (myTransaction->execute( NdbTransaction::Commit,
                                NdbOperation::AbortOnError ) != -1)
    {
      int value;
      memcpy(&value, &row[1][0], 4);
      printf(" %2d    %2d\n", value, i);
    }

    myNdb->closeTransaction(myTransaction);
  }

  /*****************************************************************
   * Update the second attribute in half of the tuples (adding 10) *
   *****************************************************************/
  for (int i = 0; i < 10; i+=2) {
    NdbTransaction *myTransaction= myNdb->startTransaction();
    if (myTransaction == NULL)
      APIERROR(myNdb->getNdbError());

    memcpy(&row[0][4], &i, 4);
    int value= i+10;
    memcpy(&row[1][4], &value, 4);
    unsigned char mask[1]= { 0x02 };            // Only update ATTR2
    NdbOperation *myOperation=
      myTransaction->updateTuple(key_record, &row[0][0],
                                 attr_record, &row[1][0], mask);
    if (myOperation == NULL)
      APIERROR(myTransaction->getNdbError());

    if ( myTransaction->execute( NdbTransaction::Commit ) == -1 )
      APIERROR(myTransaction->getNdbError());

    myNdb->closeTransaction(myTransaction);
  }

  /*************************************************
   * Delete one tuple (the one with unique key 3) *
   *************************************************/
  {
    NdbTransaction *myTransaction= myNdb->startTransaction();
    if (myTransaction == NULL)
      APIERROR(myNdb->getNdbError());

    int value= 3;
    memcpy(&row[0][4], &value, 4);
    NdbOperation *myOperation=
      myTransaction->deleteTuple(key_record, &row[0][0]);
    if (myOperation == NULL)
      APIERROR(myTransaction->getNdbError());

    if (myTransaction->execute(NdbTransaction::Commit) == -1)
      APIERROR(myTransaction->getNdbError());

    myNdb->closeTransaction(myTransaction);
  }

  /*****************************
   * Read and print all tuples *
   *****************************/
  {
    std::cout << "ATTR1 ATTR2" << std::endl;

    for (int i = 0; i < 10; i++) {
      NdbTransaction *myTransaction= myNdb->startTransaction();
      if (myTransaction == NULL)
        APIERROR(myNdb->getNdbError());

      memcpy(&row[0][0], &i, 4);
      NdbOperation *myOperation=
        myTransaction->readTuple(pk_record, &row[0][0],
                                 attr_record, &row[1][0]);
      if (myOperation == NULL)
        APIERROR(myTransaction->getNdbError());

      if (myTransaction->execute( NdbTransaction::Commit,
                                  NdbOperation::AbortOnError ) == -1)
        if (i == 3) {
          std::cout << "Detected that deleted tuple doesn't exist!\n";
        } else {
          APIERROR(myTransaction->getNdbError());
        }

      if (i != 3) {
        int value1, value2;
        memcpy(&value1, &row[1][0], 4);
        memcpy(&value2, &row[1][4], 4);
        printf(" %2d    %2d\n", value1, value2);
      }
      myNdb->closeTransaction(myTransaction);
    }
  }

  /**************
   * Drop table *
   **************/
  if (mysql_query(&mysql, "DROP TABLE MYTABLENAME"))
    MYSQLERROR(mysql);

  delete myNdb;
  delete cluster_connection;

  ndb_end(0);
  return 0;
}


--- 1.11/storage/ndb/ndbapi-examples/Makefile	2007-02-14 13:42:38 +01:00
+++ 1.12/storage/ndb/ndbapi-examples/Makefile	2007-02-14 13:42:38 +01:00
@@ -3,6 +3,7 @@ BIN_DIRS := 	ndbapi_simple \
 	 	ndbapi_async1 \
 		ndbapi_retries \
 		ndbapi_simple_index \
+		ndbapi_simple_index_ndbrecord \
 		ndbapi_event \
 		ndbapi_scan \
 		mgmapi_logevent \

--- 1.58/storage/ndb/include/ndbapi/NdbTransaction.hpp	2007-02-14 13:42:38 +01:00
+++ 1.59/storage/ndb/include/ndbapi/NdbTransaction.hpp	2007-02-14 13:42:38 +01:00
@@ -295,7 +295,8 @@ public:
    *                     ExecType::Rollback rollbacks the entire transaction.
    * @param abortOption  Handling of error while excuting
    *                     AbortOnError - Abort transaction if an operation fail
-   *                     IgnoreError  - Accept failing operations
+   *                     AO_IgnoreError  - Accept failing operations
+   *                     DefaultAbortOption - Use per-operation abort option
    * @param force        When operations should be sent to NDB Kernel.
    *                     (See @ref secAdapt.)
    *                     - 0: non-force, adaptive algorithm notices it 
@@ -560,6 +561,23 @@ public:
   Uint32 getConnectedNodeId(); // Get Connected node id
 #endif
 
+  /*
+    NdbRecord primary key and unique key operations.
+
+    If the key_rec passed in is for a table, the operation will be a primary
+    key operation. If it is for an index, it will be a unique key operation
+    using that index.
+
+    The key_row passed in defined the primary or unique key of the affected
+    tuple, and must remain valid until execute() is called.
+
+    The mask, if != NULL, defines a subset of attributes to read, update, or
+    insert. It is copied by the methods, so need not remain valid after the
+    call returns.
+
+    For unique index operations, the attr_rec must refer to the underlying
+    table of the index.
+  */
 
   NdbOperation *readTuple(const NdbRecord *key_rec, const char *key_row,
                           const NdbRecord *result_rec, char *result_row,
@@ -774,10 +792,18 @@ private:						
   NdbIndexScanOperation* getNdbScanOperation(const class NdbTableImpl* aTable);
   NdbIndexOperation* getNdbIndexOperation(const class NdbIndexImpl* anIndex, 
                                           const class NdbTableImpl* aTable,
-                                          NdbOperation* aNextOp = 0);
+                                          NdbOperation* aNextOp = 0,
+                                          bool useRec= false);
   NdbIndexScanOperation* getNdbIndexScanOperation(const NdbIndexImpl* index,
 						  const NdbTableImpl* table);
   
+  NdbOperation *setupRecordOp(NdbOperation::OperationType type,
+                              NdbOperation::LockMode lock_mode,
+                              const NdbRecord *key_record,
+                              const char *key_row,
+                              const NdbRecord *attribute_record,
+                              const char *attribute_row);
+
   void		handleExecuteCompletion();
   
   /****************************************************************************

--- 1.14/storage/ndb/include/ndbapi/NdbIndexOperation.hpp	2007-02-14 13:42:38 +01:00
+++ 1.15/storage/ndb/include/ndbapi/NdbIndexOperation.hpp	2007-02-14 13:42:38 +01:00
@@ -179,7 +179,8 @@ private:
   // Overloaded methods from NdbCursorOperation
   int indxInit(const class NdbIndexImpl* anIndex,
 	       const class NdbTableImpl* aTable, 
-	       NdbTransaction*);
+	       NdbTransaction*,
+               bool useRec);
 
   // Private attributes
   const NdbIndexImpl* m_theIndex;

--- 1.75/storage/ndb/src/ndbapi/NdbTransaction.cpp	2007-02-14 13:42:38 +01:00
+++ 1.76/storage/ndb/src/ndbapi/NdbTransaction.cpp	2007-02-14 13:42:38 +01:00
@@ -1334,7 +1334,8 @@ NdbTransaction::getNdbScanOperation(cons
 NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
 					const char* aTableName);
 
-Return Value    Return a pointer to a NdbOperation object if getNdbIndexOperation was succesful.
+Return Value    Return a pointer to an NdbIndexOperation object if
+                getNdbIndexOperation was succesful.
                 Return NULL : In all other case. 	
 Parameters:     aTableName : Name of the database table. 	
 Remark:         Get an operation from NdbIndexOperation idlelist and get the NdbTransaction object 
@@ -1396,8 +1397,9 @@ Remark:         Get an operation from Nd
 *****************************************************************************/
 NdbIndexOperation*
 NdbTransaction::getNdbIndexOperation(const NdbIndexImpl * anIndex, 
-				    const NdbTableImpl * aTable,
-                                    NdbOperation* aNextOp)
+                                     const NdbTableImpl * aTable,
+                                     NdbOperation* aNextOp,
+                                     bool useRec)
 { 
   NdbIndexOperation* tOp;
   
@@ -1426,7 +1428,7 @@ NdbTransaction::getNdbIndexOperation(con
     }
     tOp->next(aNextOp);
   }
-  if (tOp->indxInit(anIndex, aTable, this)!= -1) {
+  if (tOp->indxInit(anIndex, aTable, this, useRec)!= -1) {
     return tOp;
   } else {
     theNdb->releaseOperation(tOp);
@@ -2076,6 +2078,42 @@ NdbTransaction::getNextCompletedOperatio
 }
 
 NdbOperation *
+NdbTransaction::setupRecordOp(NdbOperation::OperationType type,
+                              NdbOperation::LockMode lock_mode,
+                              const NdbRecord *key_record,
+                              const char *key_row,
+                              const NdbRecord *attribute_record,
+                              const char *attribute_row)
+{
+  NdbOperation *op;
+  /*
+    We are actually passing the table object for the index here, not the table
+    object of the underlying table. But we only need it to keep the existing
+    NdbOperation code happy, it is not actually used for NdbRecord operation.
+    We will eliminate the need for passing table and index completely when
+    implementing WL#3707.
+  */
+  if (key_record->flags & NdbRecord::RecIsIndex)
+    op= getNdbIndexOperation(key_record->table->m_index, key_record->table,
+                             NULL, true);
+  else
+    op= getNdbOperation(key_record->table, NULL, true);
+  if(!op)
+    return op;
+
+  op->theStatus= NdbOperation::UseNdbRecord;
+  op->theOperationType= type;
+  op->theErrorLine++;
+  op->theLockMode= lock_mode;
+  op->m_key_record= key_record;
+  op->m_key_row= key_row;
+  op->m_attribute_record= attribute_record;
+  op->m_attribute_row= attribute_row;
+
+  return op;
+}
+
+NdbOperation *
 NdbTransaction::readTuple(const NdbRecord *key_rec, const char *key_row,
                           const NdbRecord *result_rec, char *result_row,
                           NdbOperation::LockMode lock_mode,
@@ -2088,21 +2126,15 @@ NdbTransaction::readTuple(const NdbRecor
     return NULL;
   }
 
-  NdbOperation *op= getNdbOperation(key_rec->table, NULL, true);
-  if(!op)
-    return op;
+  NdbOperation *op= setupRecordOp(NdbOperation::ReadRequest,
+                                  lock_mode, key_rec, key_row,
+                                  result_rec, NULL);
+  if (!op)
+    return NULL;
 
-  op->theStatus= NdbOperation::UseNdbRecord;
-  op->theOperationType= NdbOperation::ReadRequest;
-  op->theErrorLine++;
-  op->theLockMode= NdbOperation::LM_Read;
   op->m_abortOption= AO_IgnoreError;
-
-  theSimpleState= 0;
-
-  /* Setup the record/row for sending the primary key. */
-  op->m_key_record= key_rec;
-  op->m_key_row= key_row;
+  if (lock_mode != NdbOperation::LM_CommittedRead)
+    theSimpleState= 0;
   result_rec->copyMask(op->m_read_mask, result_mask);
 
   /* Setup the record/row for receiving the results. */
@@ -2122,23 +2154,14 @@ NdbTransaction::insertTuple(const NdbRec
     return NULL;
   }
 
-  NdbOperation *op= getNdbOperation(rec->table, NULL, true);
-  if(!op)
-    return op;
+  NdbOperation *op= setupRecordOp(NdbOperation::InsertRequest,
+                                  NdbOperation::LM_Exclusive, rec, row,
+                                  rec, row);
+  if (!op)
+    return NULL;
 
-  op->theStatus= NdbOperation::UseNdbRecord;
-  op->theOperationType= NdbOperation::InsertRequest;
-  op->theErrorLine++;
-  op->theLockMode= NdbOperation::LM_Exclusive;
   op->m_abortOption = AbortOnError;
-
   theSimpleState= 0;
-
-  /* Setup the record/row for sending the primary key. */
-  op->m_key_record= rec;
-  op->m_key_row= row;
-  op->m_attribute_record= rec;
-  op->m_attribute_row= row;
   rec->copyMask(op->m_read_mask, mask);
 
   return op;
@@ -2156,23 +2179,14 @@ NdbTransaction::updateTuple(const NdbRec
     return NULL;
   }
 
-  NdbOperation *op= getNdbOperation(key_rec->table, NULL, true);
+  NdbOperation *op= setupRecordOp(NdbOperation::UpdateRequest,
+                                  NdbOperation::LM_Exclusive, key_rec, key_row,
+                                  attr_rec, attr_row);
   if(!op)
     return op;
 
-  op->theStatus= NdbOperation::UseNdbRecord;
-  op->theOperationType= NdbOperation::UpdateRequest;
-  op->theErrorLine++;
-  op->theLockMode= NdbOperation::LM_Exclusive;
   op->m_abortOption = AbortOnError;
-
   theSimpleState= 0;
-
-  /* Setup the record/row for sending the primary key. */
-  op->m_key_record= key_rec;
-  op->m_key_row= key_row;
-  op->m_attribute_record= attr_rec;
-  op->m_attribute_row= attr_row;
   attr_rec->copyMask(op->m_read_mask, mask);
 
   return op;
@@ -2188,24 +2202,15 @@ NdbTransaction::deleteTuple(const NdbRec
     return NULL;
   }
 
-  NdbOperation *op= getNdbOperation(key_rec->table, NULL, true);
+  NdbOperation *op= setupRecordOp(NdbOperation::DeleteRequest,
+                                  NdbOperation::LM_Exclusive, key_rec, key_row,
+                                  key_rec, NULL);
   if(!op)
     return op;
 
-  op->theStatus= NdbOperation::UseNdbRecord;
-  op->theOperationType= NdbOperation::DeleteRequest;
-  op->theErrorLine++;
-  op->theLockMode= NdbOperation::LM_Exclusive;
   op->m_abortOption = AbortOnError;
-
   theSimpleState= 0;
 
-  /* Setup the record/row for sending the primary key. */
-  op->m_key_record= key_rec;
-  op->m_key_row= key_row;
-  /* Set the m_attribute_record so we know this is an NdbRecord operation. */
-  op->m_attribute_record= key_rec;
-
   return op;
 }
 
@@ -2221,22 +2226,14 @@ NdbTransaction::writeTuple(const NdbReco
     return NULL;
   }
 
-  NdbOperation *op= getNdbOperation(key_rec->table, NULL, true);
+  NdbOperation *op= setupRecordOp(NdbOperation::WriteRequest,
+                                  NdbOperation::LM_Exclusive, key_rec, key_row,
+                                  attr_rec, attr_row);
   if(!op)
     return op;
 
-  op->theStatus= NdbOperation::UseNdbRecord;
-  op->theOperationType= NdbOperation::WriteRequest;
-  op->theErrorLine++;
-  op->theLockMode= NdbOperation::LM_Exclusive;
   op->m_abortOption = AbortOnError;
-
   theSimpleState= 0;
-
-  op->m_key_record= key_rec;
-  op->m_key_row= key_row;
-  op->m_attribute_record= attr_rec;
-  op->m_attribute_row= attr_row;
   attr_rec->copyMask(op->m_read_mask, mask);
 
   return op;
@@ -2256,7 +2253,6 @@ NdbTransaction::scanTable(const NdbRecor
   */
   NdbIndexScanOperation *op_idx;
   NdbScanOperation *op;
-  Uint32 fragCount;
   int res;
 
   op_idx= getNdbScanOperation(result_record->table);

--- 1.160/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2007-02-14 13:42:38 +01:00
+++ 1.161/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2007-02-14 13:42:38 +01:00
@@ -4548,7 +4548,8 @@ NdbDictionaryImpl::createRecord(const Nd
     return NULL;
   }
 
-  isIndex= table->m_indexType==NdbDictionary::Object::OrderedIndex;
+  isIndex= (table->m_indexType==NdbDictionary::Object::OrderedIndex ||
+            table->m_indexType==NdbDictionary::Object::UniqueHashIndex);
 
   /* Count the number of key columns in the table or index. */
   if (isIndex)

--- 1.31/storage/ndb/src/ndbapi/NdbIndexOperation.cpp	2007-02-14 13:42:38 +01:00
+++ 1.32/storage/ndb/src/ndbapi/NdbIndexOperation.cpp	2007-02-14 13:42:38 +01:00
@@ -52,9 +52,10 @@ NdbIndexOperation::~NdbIndexOperation()
 int
 NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
 			    const NdbTableImpl * aTable, 
-			    NdbTransaction* myConnection)
+			    NdbTransaction* myConnection,
+                            bool useRec)
 {
-  NdbOperation::init(aTable, myConnection, false);
+  NdbOperation::init(aTable, myConnection, useRec);
 
   switch (anIndex->m_type) {
   case(NdbDictionary::Index::UniqueHashIndex):

--- 1.29/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2007-02-14 13:42:38 +01:00
+++ 1.30/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2007-02-14 13:42:38 +01:00
@@ -546,7 +546,7 @@ NdbOperation::prepareSendNdbRecord(Uint3
 
   TcKeyReq *tcKeyReq= CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
   Uint32 hdrSize= fillTcKeyReqHdr(tcKeyReq, aTC_ConnectPtr, aTransId,
-                                  m_attribute_record, ao);
+                                  m_key_record, ao);
   keyInfoPtr= theTCREQ->getDataPtrSend() + hdrSize;
   remain= TcKeyReq::MaxKeyInfo;
 

--- 1.59/storage/ndb/src/ndbapi/TransporterFacade.cpp	2007-02-14 13:42:38 +01:00
+++ 1.60/storage/ndb/src/ndbapi/TransporterFacade.cpp	2007-02-14 13:42:38 +01:00
@@ -38,7 +38,7 @@
 #include <signaldata/SumaImpl.hpp>
 
 //#define REPORT_TRANSPORTER
-//#define API_TRACE;
+//#define API_TRACE
 
 static int numberToIndex(int number)
 {
Thread
bk commit into 5.1 tree (knielsen:1.2434)knielsen14 Feb