Commit 62321bd2 authored by unknown's avatar unknown
Browse files

bug#11133 - ndb

  incorrect handling of writeTuple with multi op transaction


ndb/src/kernel/blocks/dbacc/DbaccMain.cpp:
  1) Pass operation instead of insertIsDone to LQH
  2) transform operation correctly when in parallell que
     (multi op within same trans)
ndb/src/kernel/blocks/dblqh/DblqhMain.cpp:
  Let ACC decide what operation was performed when WRITE
ndb/test/ndbapi/testNdbApi.cpp:
  Add testcase for bug 11133
ndb/test/run-test/daily-basic-tests.txt:
  Add testcase for bug 11133
parent 4c30434d
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -1589,7 +1589,7 @@ void Dbacc::initOpRec(Signal* signal)
void Dbacc::sendAcckeyconf(Signal* signal) 
{
  signal->theData[0] = operationRecPtr.p->userptr;
  signal->theData[1] = operationRecPtr.p->insertIsDone;
  signal->theData[1] = operationRecPtr.p->operation;
  signal->theData[2] = operationRecPtr.p->fid;
  signal->theData[3] = operationRecPtr.p->localdata[0];
  signal->theData[4] = operationRecPtr.p->localdata[1];
@@ -1671,6 +1671,11 @@ void Dbacc::execACCKEYREQ(Signal* signal)
    case ZWRITE:
    case ZSCAN_OP:
      if (!tgeLocked){
	if(operationRecPtr.p->operation == ZWRITE)
	{
	  jam();
	  operationRecPtr.p->operation = ZUPDATE;
	}
        sendAcckeyconf(signal);
        if (operationRecPtr.p->dirtyRead == ZFALSE) {
	  /*---------------------------------------------------------------*/
@@ -2182,6 +2187,12 @@ Uint32 Dbacc::placeWriteInLockQueue(Signal* signal)
    return ZWRITE_ERROR;
  }//if
  if(operationRecPtr.p->operation == ZWRITE)
  {
    operationRecPtr.p->operation = 
      (mlpqOperPtr.p->operation == ZDELETE) ? ZINSERT : ZUPDATE;
  }
  
  operationRecPtr.p->localdata[0] = queOperPtr.p->localdata[0];
  operationRecPtr.p->localdata[1] = queOperPtr.p->localdata[1];
  operationRecPtr.p->prevParallelQue = mlpqOperPtr.i;
+14 −13
Original line number Diff line number Diff line
@@ -3897,20 +3897,21 @@ void Dblqh::execACCKEYCONF(Signal* signal)
   * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
   * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A 
   * TABLE.
   * ------------------------------------------------------------------------ */
  if (regTcPtr->operation == ZWRITE) {
    if (signal->theData[1] > 0) {
      /* --------------------------------------------------------------------
       * ACC did perform an insert and thus we should indicate that the WRITE 
       * is an INSERT otherwise it is an UPDATE.
       * -------------------------------------------------------------------- */
      jam();
      regTcPtr->operation = ZINSERT;
    } else {
      jam();
      tcConnectptr.p->operation = ZUPDATE;
    }//if
   * ----------------------------------------------------------------------- */
  if (regTcPtr->operation == ZWRITE) 
  {
    Uint32 op= signal->theData[1];
    if(likely(op == ZINSERT || op == ZUPDATE))
    {
      regTcPtr->operation = op;
    }
    else
    {
      warningEvent("Convering %d to ZUPDATE", op);
      regTcPtr->operation = ZUPDATE;
    }
  }//if
  
  ndbrequire(localKeyFlag == 1);
  localKey2 = localKey1 & MAX_TUPLES_PER_PAGE;
  localKey1 = localKey1 >> MAX_TUPLES_BITS;
+239 −0
Original line number Diff line number Diff line
@@ -1049,6 +1049,239 @@ int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){
  return result;
}

int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
  int result = NDBT_OK;
  const NdbDictionary::Table* pTab = ctx->getTab();

  HugoOperations hugoOps(*pTab);

  Ndb* pNdb = GETNDB(step);
  Uint32 lm;

  NdbConnection* pCon = pNdb->startTransaction();
  if (pCon == NULL){
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }
  
  NdbOperation* pOp = pCon->getNdbOperation(pTab->getName());
  if (pOp == NULL){
    ERR(pCon->getNdbError());
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }
  
  if (pOp->readTuple(NdbOperation::LM_Exclusive) != 0){
    pNdb->closeTransaction(pCon);
    ERR(pOp->getNdbError());
    return NDBT_FAILED;
  }
      
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() == true){
      if(hugoOps.equalForAttr(pOp, a, 1) != 0){
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }

  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() != true){
      if (pOp->getValue(pTab->getColumn(a)->getName()) == NULL) {
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  int check = pCon->execute(NoCommit);
  if (check == 0){
    ndbout << "execute worked" << endl;
  } else {
    ERR(pCon->getNdbError());
    result = NDBT_FAILED;
  }
  
  pOp = pCon->getNdbOperation(pTab->getName());
  if (pOp == NULL){
    ERR(pCon->getNdbError());
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }
  
  if (pOp->deleteTuple() != 0){
    pNdb->closeTransaction(pCon);
    ERR(pOp->getNdbError());
    return NDBT_FAILED;
  }
      
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() == true){
      if(hugoOps.equalForAttr(pOp, a, 1) != 0){
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }

  check = pCon->execute(NoCommit);
  if (check == 0){
    ndbout << "execute worked" << endl;
  } else {
    ERR(pCon->getNdbError());
    result = NDBT_FAILED;
  }

  pOp = pCon->getNdbOperation(pTab->getName());
  if (pOp == NULL){
    ERR(pCon->getNdbError());
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }
  
  if (pOp->writeTuple() != 0){
    pNdb->closeTransaction(pCon);
    ERR(pOp->getNdbError());
    return NDBT_FAILED;
  }
  
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() == true){
      if(hugoOps.equalForAttr(pOp, a, 1) != 0){
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() != true){
      if(hugoOps.setValueForAttr(pOp, a, 1, 1) != 0)
      {
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  check = pCon->execute(NoCommit);
  if (check == 0){
    ndbout << "execute worked" << endl;
  } else {
    ERR(pCon->getNdbError());
    result = NDBT_FAILED;
  }

  pOp = pCon->getNdbOperation(pTab->getName());
  if (pOp == NULL){
    ERR(pCon->getNdbError());
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }
  
  if (pOp->writeTuple() != 0){
    pNdb->closeTransaction(pCon);
    ERR(pOp->getNdbError());
    return NDBT_FAILED;
  }
  
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() == true){
      if(hugoOps.equalForAttr(pOp, a, 1) != 0){
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() != true){
      if(hugoOps.setValueForAttr(pOp, a, 1, 1) != 0)
      {
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  check = pCon->execute(NoCommit);
  if (check == 0){
    ndbout << "execute worked" << endl;
  } else {
    ERR(pCon->getNdbError());
    result = NDBT_FAILED;
  }
  
  check = pCon->execute(Rollback);
  if (check == 0){
    ndbout << "execute worked" << endl;
  } else {
    ERR(pCon->getNdbError());
    result = NDBT_FAILED;
  }
  
  pCon->close();

  pCon = pNdb->startTransaction();
  if (pCon == NULL){
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }

  pOp = pCon->getNdbOperation(pTab->getName());
  if (pOp == NULL){
    ERR(pCon->getNdbError());
    pNdb->closeTransaction(pCon);  
    return NDBT_FAILED;
  }
  
  if (pOp->writeTuple() != 0){
    pNdb->closeTransaction(pCon);
    ERR(pOp->getNdbError());
    return NDBT_FAILED;
  }
  
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() == true){
      if(hugoOps.equalForAttr(pOp, a, 1) != 0){
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  for(int a = 0; a<pTab->getNoOfColumns(); a++){
    if (pTab->getColumn(a)->getPrimaryKey() != true){
      if(hugoOps.setValueForAttr(pOp, a, 1, 1) != 0)
      {
	ERR(pCon->getNdbError());
	pNdb->closeTransaction(pCon);
	return NDBT_FAILED;
      }
    }
  }
  
  check = pCon->execute(Commit);
  if (check == 0){
    ndbout << "execute worked" << endl;
  } else {
    ERR(pCon->getNdbError());
    result = NDBT_FAILED;
  }
  
  return result;
}



NDBT_TESTSUITE(testNdbApi);
TESTCASE("MaxNdb", 
@@ -1124,6 +1357,12 @@ TESTCASE("ReadWithoutGetValue",
  INITIALIZER(runReadWithoutGetValue);
  FINALIZER(runClearTable);
}
TESTCASE("Bug_11133", 
	 "Test ReadEx-Delete-Write\n"){ 
  INITIALIZER(runLoadTable);
  INITIALIZER(runBug_11133);
  FINALIZER(runClearTable);
}
NDBT_TESTSUITE_END(testNdbApi);

int main(int argc, const char** argv){
+4 −0
Original line number Diff line number Diff line
@@ -546,6 +546,10 @@ max-time: 500
cmd: testNdbApi
args: -n ReadWithoutGetValue

max-time: 500
cmd: testNdbApi
args: -n Bug_11133 T1 

#max-time: 500
#cmd: testInterpreter
#args: T1