int UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb, NdbConnection* scanTrans, const NdbDictionary::Index* pIndex, NDBT_ResultRow& row ){ NdbDictionary::Index::Type indexType= pIndex->getType(); int retryAttempt = 0; const int retryMax = 100; int check, a; NdbConnection *pTrans1=NULL; NdbOperation *pOp; int return_code= NDBT_FAILED; // Allocate place to store the result NDBT_ResultRow tabRow(tab); NDBT_ResultRow indexRow(tab); const char * indexName = pIndex->getName(); while (true){ if(retryAttempt) ndbout_c("retryAttempt %d", retryAttempt); if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; goto close_all; } pTrans1 = pNdb->hupp(scanTrans); //startTransaction(); if (pTrans1 == NULL) { const NdbError err = pNdb->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); NdbSleep_MilliSleep(50); retryAttempt++; continue; } if(err.code == 0){ return_code = NDBT_OK; goto close_all; } ERR(err); goto close_all; } /** * Read the record from TABLE */ pOp = pTrans1->getNdbOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans1->getNdbError()); goto close_all; } check = pOp->readTuple(); if( check == -1 ) { ERR(pTrans1->getNdbError()); goto close_all; } // Define primary keys #if VERBOSE printf("PK: "); #endif for(a = 0; a<tab.getNoOfColumns(); a++){ const NdbDictionary::Column* attr = tab.getColumn(a); if (attr->getPrimaryKey() == true){ if (pOp->equal(attr->getName(), row.attributeStore(a)->aRef()) != 0){ ERR(pTrans1->getNdbError()); goto close_all; } #if VERBOSE printf("%s = %d: ", attr->getName(), row.attributeStore(a)->aRef()); #endif } } #if VERBOSE printf("\n"); #endif // Read all attributes #if VERBOSE printf("Reading %u attributes: ", tab.getNoOfColumns()); #endif for(a = 0; a<tab.getNoOfColumns(); a++){ if((tabRow.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans1->getNdbError()); goto close_all; } #if VERBOSE printf("%s ", tab.getColumn(a)->getName()); #endif } #if VERBOSE printf("\n"); #endif /** * Read the record from INDEX_TABLE */ NdbIndexOperation* pIndexOp= NULL; NdbIndexScanOperation *pScanOp= NULL; NdbOperation *pIOp= 0; bool null_found= false; for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){ const NdbDictionary::Column * col = pIndex->getColumn(a); if (row.attributeStore(col->getName())->isNULL()) { null_found= true; break; } } const char * tabName= tab.getName(); if(!null_found) { if (indexType == NdbDictionary::Index::UniqueHashIndex) { pIOp= pIndexOp= pTrans1->getNdbIndexOperation(indexName, tabName); } else { pIOp= pScanOp= pTrans1->getNdbIndexScanOperation(indexName, tabName); } if (pIOp == NULL) { ERR(pTrans1->getNdbError()); goto close_all; } { bool not_ok; if (pIndexOp) { not_ok = pIndexOp->readTuple() == -1; } else { not_ok = pScanOp->readTuples(); } if( not_ok ) { ERR(pTrans1->getNdbError()); goto close_all; } } // Define primary keys for index #if VERBOSE printf("SI: "); #endif for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){ const NdbDictionary::Column * col = pIndex->getColumn(a); int r; if ( !row.attributeStore(col->getName())->isNULL() ) { if(pIOp->equal(col->getName(), row.attributeStore(col->getName())->aRef()) != 0){ ERR(pTrans1->getNdbError()); goto close_all; } } #if VERBOSE printf("%s = %d: ", col->getName(), row.attributeStore(a)->aRef()); #endif } #if VERBOSE printf("\n"); #endif // Read all attributes #if VERBOSE printf("Reading %u attributes: ", tab.getNoOfColumns()); #endif for(a = 0; a<tab.getNoOfColumns(); a++){ void* pCheck; pCheck= indexRow.attributeStore(a)= pIOp->getValue(tab.getColumn(a)->getName()); if(pCheck == NULL) { ERR(pTrans1->getNdbError()); goto close_all; } #if VERBOSE printf("%s ", tab.getColumn(a)->getName()); #endif } } #if VERBOSE printf("\n"); #endif scanTrans->refresh(); check = pTrans1->execute(Commit, AbortOnError); if( check == -1 ) { const NdbError err = pTrans1->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); pNdb->closeTransaction(pTrans1); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ndbout << "Error when comparing records - normal op" << endl; ERR(err); ndbout << "row: " << row.c_str().c_str() << endl; goto close_all; } /** * Compare the two rows */ if(!null_found){ if (pScanOp) { if (pScanOp->nextResult() != 0){ const NdbError err = pTrans1->getNdbError(); ERR(err); ndbout << "Error when comparing records - index op next_result missing" << endl; ndbout << "row: " << row.c_str().c_str() << endl; goto close_all; } } if (!(tabRow.c_str() == indexRow.c_str())){ ndbout << "Error when comapring records" << endl; ndbout << " tabRow: \n" << tabRow.c_str().c_str() << endl; ndbout << " indexRow: \n" << indexRow.c_str().c_str() << endl; goto close_all; } if (pScanOp) { if (pScanOp->nextResult() == 0){ ndbout << "Error when comparing records - index op next_result to many" << endl; ndbout << "row: " << row.c_str().c_str() << endl; goto close_all; } } } return_code= NDBT_OK; goto close_all; } close_all: if (pTrans1) pNdb->closeTransaction(pTrans1); return return_code; }
bool NDBT_ResultRow::operator==(const NDBT_ResultRow& other) const { // quick and dirty return c_str() == other.c_str(); }