List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:October 6 2009 10:39am
Subject:bzr commit into mysql-5.1-telco-6.2 branch (frazer:3012) Bug#45282
View as plain text  
#At file:///home/frazer/bzr/mysql-5.1-telco-6.2/

 3012 Frazer Clement	2009-10-06
      Bug#45282 NDBAPI - Duplicate read of column results in Api failure
      modified:
        storage/ndb/src/ndbapi/NdbOperationExec.cpp
        storage/ndb/test/include/HugoCalculator.hpp
        storage/ndb/test/ndbapi/testNdbApi.cpp
        storage/ndb/test/run-test/daily-basic-tests.txt
        storage/ndb/test/src/HugoCalculator.cpp

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2009-10-06 10:39:02 +0000
@@ -350,7 +350,7 @@ Uint32
 NdbOperation::repack_read(Uint32 len)
 {
   Uint32 i;
-  Uint32 maxId = 0, check = 0;
+  Uint32 check = 0, prevId = 0;
   Uint32 save = len;
   Bitmask<MAXNROFATTRIBUTESINWORDS> mask;
   NdbApiSignal *tSignal = theFirstATTRINFO;
@@ -362,14 +362,16 @@ NdbOperation::repack_read(Uint32 len)
   {
     AttributeHeader tmp(* ptr++);
     Uint32 id = tmp.getAttributeId();
-    if (id >= NDB_MAX_ATTRIBUTES_IN_TABLE)
+    if (((i > 0) &&              // No prevId for first attrId
+         (id <= prevId)) ||
+        (id >= NDB_MAX_ATTRIBUTES_IN_TABLE))
     {
-      // Dont support == fallback
+      // AttrIds not strictly ascending with no duplicates
+      // and no pseudo-columns == fallback
       return save;
     }
+    prevId = id;
     mask.set(id);
-    maxId = (id > maxId) ? id : maxId;
-    check |= (id - maxId);
   }
 
   Uint32 cnt = 0;
@@ -382,20 +384,20 @@ NdbOperation::repack_read(Uint32 len)
     {
       AttributeHeader tmp(* ptr++);
       Uint32 id = tmp.getAttributeId();
-      if (id >= NDB_MAX_ATTRIBUTES_IN_TABLE)
+      if ((id <= prevId) ||
+          (id >= NDB_MAX_ATTRIBUTES_IN_TABLE))
       {
-        // Dont support == fallback
+        // AttrIds not strictly ascending with no duplicates
+        // and no pseudo-columns ==  fallback
         return save;
       }
+      prevId = id;
       
       mask.set(id);
-
-      maxId = (id > maxId) ? id : maxId;
-      check |= (id - maxId);
     }
     tSignal = tSignal->next();
   }
-  const Uint32 newlen = 1 + (maxId >> 5);
+  const Uint32 newlen = 1 + (prevId >> 5);
   const bool all = cols == save;
   if (check == 0)
   {

=== modified file 'storage/ndb/test/include/HugoCalculator.hpp'
--- a/storage/ndb/test/include/HugoCalculator.hpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/test/include/HugoCalculator.hpp	2009-10-06 10:39:02 +0000
@@ -37,6 +37,9 @@ public:
 			int len, Uint32* real_len) const;
 
   int verifyRowValues(NDBT_ResultRow* const  pRow) const;
+  int verifyRecAttr(int record, int updates, const NdbRecAttr* recAttr);
+  int verifyColValue(int record, int attrib, int updates, 
+                     const char* valPtr, Uint32 valLen);
   int getIdValue(NDBT_ResultRow* const pRow) const;
   int getUpdatesValue(NDBT_ResultRow* const pRow) const;
   int isIdCol(int colId) { return m_idCol == colId; };

=== modified file 'storage/ndb/test/ndbapi/testNdbApi.cpp'
--- a/storage/ndb/test/ndbapi/testNdbApi.cpp	2009-09-22 13:04:32 +0000
+++ b/storage/ndb/test/ndbapi/testNdbApi.cpp	2009-10-06 10:39:02 +0000
@@ -3121,6 +3121,157 @@ int runBulkPkReads(NDBT_Context* ctx, ND
   return NDBT_OK;
 }
   
+int runReadColumnDuplicates(NDBT_Context* ctx, NDBT_Step* step){
+
+  int result = NDBT_OK;
+  const NdbDictionary::Table* pTab = ctx->getTab();
+  HugoCalculator hc(*pTab);
+  Uint32 numRecords = ctx->getNumRecords();
+
+  Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
+  if (pNdb == NULL){
+    ndbout << "pNdb == NULL" << endl;      
+    return NDBT_FAILED;  
+  }
+  if (pNdb->init()){
+    ERR(pNdb->getNdbError());
+    delete pNdb;
+    return NDBT_FAILED;
+  }
+
+  HugoOperations hugoOps(*pTab);
+  
+  for (int m = 1; m < 100; m++){
+    Uint32 record = (100 - m) % numRecords;
+    NdbConnection* pCon = pNdb->startTransaction();
+    if (pCon == NULL){
+      delete pNdb;
+      return NDBT_FAILED;
+    }
+      
+    NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
+    if (pOp == NULL){
+      pNdb->closeTransaction(pCon);
+      delete pNdb;
+      return NDBT_FAILED;
+    }
+      
+    if (pOp->readTuple() != 0){
+      pNdb->closeTransaction(pCon);
+      delete pNdb;
+      return NDBT_FAILED;
+    }
+    
+    int numCols= pTab->getNoOfColumns();
+
+    for(int a = 0; a < numCols; a++){
+      if (pTab->getColumn(a)->getPrimaryKey() == true){
+	if(hugoOps.equalForAttr(pOp, a, record) != 0){
+	  ERR(pCon->getNdbError());
+	  pNdb->closeTransaction(pCon);
+	  delete pNdb;
+	  return NDBT_FAILED;
+	}
+      }
+    }
+      
+    int dupColNum = m % numCols;
+    int numReads = m + 1;
+    
+    NdbRecAttr* first = NULL;
+    ndbout << "Reading record " 
+           << record << " Column "
+           << dupColNum << " " << numReads
+           << " times" << endl;
+    while (numReads--)
+    {
+      NdbRecAttr* recAttr = pOp->getValue(dupColNum);
+      if (recAttr == NULL) {
+	const NdbError err = pCon->getNdbError();
+	ERR(err);
+        result = NDBT_FAILED;
+        pNdb->closeTransaction(pCon);	
+	break;
+      }
+      first = (first == NULL) ? recAttr : first;
+    };
+    
+    if (result == NDBT_FAILED)
+      break;
+
+    if (pCon->execute(Commit) != 0){
+      const NdbError err = pCon->getNdbError();
+      ERR(err);
+      result = NDBT_FAILED;
+      pNdb->closeTransaction(pCon);
+      break;
+    }
+
+    if (pCon->getNdbError().code != 0)
+    {
+      NdbError err = pCon->getNdbError();
+      if (err.code == 880)
+      {
+        /* Tried to read too much error - this column
+         * is probably too large.
+         * Skip to next iteration
+         */
+        ndbout << "Reading too much in one op, skipping..." << endl;
+        pNdb->closeTransaction(pCon);
+        continue;
+      }
+      ndbout << "Error at execute time : " << err.code
+             << ":" << err.message << endl;
+      pNdb->closeTransaction(pCon);
+      result = NDBT_FAILED;
+      break;
+    }
+
+    /* Let's check the results */
+
+    
+    const NdbRecAttr* curr = first;
+
+    for (int c= 0; c < (m+1); c++)
+    {
+      if (hc.verifyRecAttr(record,
+                           0,
+                           curr))
+      {
+        ndbout << "Mismatch on record "
+                 << record << " column "
+                 << dupColNum << " read number "
+                 << c+1 << endl;
+        result =  NDBT_FAILED;
+        break;
+      }
+
+      ndbout << "/";
+      
+      curr = curr->next();
+    }
+
+    ndbout << endl;
+
+    pNdb->closeTransaction(pCon);
+
+    if (result == NDBT_FAILED)
+      break;
+
+    if (curr != NULL)
+    {
+      ndbout << "Error - extra RecAttr(s) found" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+
+  }// m
+
+  delete pNdb;
+
+  return result;
+}
+
   
 
 NDBT_TESTSUITE(testNdbApi);
@@ -3290,6 +3441,12 @@ TESTCASE("ApiFailReqBehaviour",
   STEP(testApiFailReq);
   FINALIZER(runClearTable);
 }
+TESTCASE("ReadColumnDuplicates",
+         "Check NdbApi behaves ok when reading same column multiple times") {
+  INITIALIZER(runLoadTable);
+  STEP(runReadColumnDuplicates);
+  FINALIZER(runClearTable);
+}
 NDBT_TESTSUITE_END(testNdbApi);
 
 int main(int argc, const char** argv){

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2009-10-05 10:38:50 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2009-10-06 10:39:02 +0000
@@ -1362,3 +1362,7 @@ max-time: 300
 cmd: testNdbApi
 args: -n ApiFailReqBehaviour T1
 
+max-time: 300
+cmd: testNdbApi
+args: -n ReadColumnDuplicates
+

=== modified file 'storage/ndb/test/src/HugoCalculator.cpp'
--- a/storage/ndb/test/src/HugoCalculator.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/test/src/HugoCalculator.cpp	2009-10-06 10:39:02 +0000
@@ -304,6 +304,105 @@ HugoCalculator::verifyRowValues(NDBT_Res
   return result;
 }
 
+
+int
+HugoCalculator::verifyRecAttr(int record,
+                              int updates,
+                              const NdbRecAttr* recAttr)
+{
+  const char* valPtr = NULL;
+  int attrib = recAttr->getColumn()->getAttrId();
+  Uint32 valLen = recAttr->get_size_in_bytes();
+  if (!recAttr->isNULL())
+    valPtr= (const char*) recAttr->aRef();
+  
+  return verifyColValue(record,
+                        attrib,
+                        updates,
+                        valPtr,
+                        valLen);
+}
+
+int
+HugoCalculator::verifyColValue(int record, 
+                               int attrib,
+                               int updates,
+                               const char* valPtr,
+                               Uint32 valLen)
+{
+  int result = 0;	  
+  
+  if (attrib == m_updatesCol)
+  {
+    int val= *((const int*) valPtr);
+    if (val != updates)
+    {
+      g_err << "|- Updates column (" << attrib << ")" << endl;
+      g_err << "|- Expected " << updates << " but found " << val << endl;
+      result = -1;
+    }
+  }
+  else if (attrib == m_idCol)
+  {
+    int val= *((const int*) valPtr);
+    if (val != record)
+    {
+      g_err << "|- Identity column (" << attrib << ")" << endl;
+      g_err << "|- Expected " << record << " but found " << val << endl;
+      result = -1;
+    }
+  }
+  else
+  {
+    /* 'Normal' data column */
+    const NdbDictionary::Column* attr = m_tab.getColumn(attrib);      
+    Uint32 len = attr->getSizeInBytes(), real_len;
+    char buf[NDB_MAX_TUPLE_SIZE];
+    const char* res = calcValue(record, attrib, updates, buf, len, &real_len);
+    if (res == NULL){
+      if (valPtr != NULL){
+        g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl;
+        g_err << "|- Column length is " << valLen << " bytes" << endl;
+        g_err << "|- Column data follows :" << endl;
+        for (Uint32 j = 0; j < valLen; j ++)
+        {
+          g_err << j << ":" << hex << (Uint32)(Uint8)valPtr[j] << endl;
+        }
+        result = -1;
+      }
+    } else{
+      if (real_len != valLen)
+      {
+        g_err << "|- Invalid data found in attribute " << attrib << ": \""
+              << "Length of expected=" << real_len << endl
+              << "Length of passed=" 
+              << valLen << endl;
+        result= -1;
+      }
+      else if (memcmp(res, valPtr, real_len) != 0)
+      {
+        g_err << "|- Expected data mismatch on column "
+              << attr->getName() << " length " << real_len 
+              << " bytes " << endl;
+        g_err << "|- Bytewise comparison follows :" << endl;
+        for (Uint32 j = 0; j < real_len; j++)
+        {
+          g_err << j << ":" << hex << (Uint32)(Uint8)buf[j] << "[" << hex << (Uint32)(Uint8)valPtr[j] << "]";
+          if (buf[j] != valPtr[j])
+          {
+            g_err << "==>Match failed!";
+          }
+          g_err << endl;
+        }
+        g_err << endl;
+        result = -1;
+      }
+    }    
+  }
+
+  return result;
+}
+
 int
 HugoCalculator::getIdValue(NDBT_ResultRow* const pRow) const {
   return pRow->attributeStore(m_idCol)->u_32_value();

Thread
bzr commit into mysql-5.1-telco-6.2 branch (frazer:3012) Bug#45282Frazer Clement6 Oct