NdbOperationDefine.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:22k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*****************************************************************************
  14.  * Name:          NdbOperationDefine.C
  15.  * Include:
  16.  * Link:
  17.  * Author:        UABMNST Mona Natterkvist UAB/B/SD                         
  18.  * Date:          970829
  19.  * Version:       0.1
  20.  * Description:   Interface between TIS and NDB
  21.  * Documentation:
  22.  * Adjust:  971022  UABMNST   First version.
  23.  *****************************************************************************/
  24. #include "NdbOperation.hpp"
  25. #include "NdbApiSignal.hpp"
  26. #include "NdbConnection.hpp"
  27. #include "Ndb.hpp"
  28. #include "NdbRecAttr.hpp"
  29. #include "NdbUtil.hpp"
  30. #include "NdbOut.hpp"
  31. #include "NdbImpl.hpp"
  32. #include <NdbIndexScanOperation.hpp>
  33. #include "NdbBlob.hpp"
  34. #include <Interpreter.hpp>
  35. #include <AttributeHeader.hpp>
  36. #include <signaldata/TcKeyReq.hpp>
  37. /*****************************************************************************
  38.  * int insertTuple();
  39.  *****************************************************************************/
  40. int
  41. NdbOperation::insertTuple()
  42. {
  43.   NdbConnection* tNdbCon = theNdbCon;
  44.   int tErrorLine = theErrorLine;
  45.   if (theStatus == Init) {
  46.     theStatus = OperationDefined;
  47.     theOperationType = InsertRequest;
  48.     tNdbCon->theSimpleState = 0;
  49.     theErrorLine = tErrorLine++;
  50.     theLockMode = LM_Exclusive;
  51.     return 0; 
  52.   } else {
  53.     setErrorCode(4200);
  54.     return -1;
  55.   }//if
  56. }//NdbOperation::insertTuple()
  57. /******************************************************************************
  58.  * int updateTuple();
  59.  *****************************************************************************/
  60. int
  61. NdbOperation::updateTuple()
  62. {  
  63.   NdbConnection* tNdbCon = theNdbCon;
  64.   int tErrorLine = theErrorLine;
  65.   if (theStatus == Init) {
  66.     theStatus = OperationDefined;
  67.     tNdbCon->theSimpleState = 0;
  68.     theOperationType = UpdateRequest;  
  69.     theErrorLine = tErrorLine++;
  70.     theLockMode = LM_Exclusive;
  71.     return 0; 
  72.   } else {
  73.     setErrorCode(4200);
  74.     return -1;
  75.   }//if
  76. }//NdbOperation::updateTuple()
  77. /*****************************************************************************
  78.  * int writeTuple();
  79.  *****************************************************************************/
  80. int
  81. NdbOperation::writeTuple()
  82. {  
  83.   NdbConnection* tNdbCon = theNdbCon;
  84.   int tErrorLine = theErrorLine;
  85.   if (theStatus == Init) {
  86.     theStatus = OperationDefined;
  87.     tNdbCon->theSimpleState = 0;
  88.     theOperationType = WriteRequest;  
  89.     theErrorLine = tErrorLine++;
  90.     theLockMode = LM_Exclusive;
  91.     return 0; 
  92.   } else {
  93.     setErrorCode(4200);
  94.     return -1;
  95.   }//if
  96. }//NdbOperation::writeTuple()
  97. /******************************************************************************
  98.  * int readTuple();
  99.  *****************************************************************************/
  100. int
  101. NdbOperation::readTuple(NdbOperation::LockMode lm)
  102.   switch(lm) {
  103.   case LM_Read:
  104.     return readTuple();
  105.     break;
  106.   case LM_Exclusive:
  107.     return readTupleExclusive();
  108.     break;
  109.   case LM_CommittedRead:
  110.     return committedRead();
  111.     break;
  112.   default:
  113.     return -1;
  114.   };
  115. }
  116. /******************************************************************************
  117.  * int readTuple();
  118.  *****************************************************************************/
  119. int
  120. NdbOperation::readTuple()
  121.   NdbConnection* tNdbCon = theNdbCon;
  122.   int tErrorLine = theErrorLine;
  123.   if (theStatus == Init) {
  124.     theStatus = OperationDefined;
  125.     tNdbCon->theSimpleState = 0;
  126.     theOperationType = ReadRequest;
  127.     theErrorLine = tErrorLine++;
  128.     theLockMode = LM_Read;
  129.     return 0;
  130.   } else {
  131.     setErrorCode(4200);
  132.     return -1;
  133.   }//if
  134. }//NdbOperation::readTuple()
  135. /*****************************************************************************
  136.  * int deleteTuple();
  137.  *****************************************************************************/
  138. int
  139. NdbOperation::deleteTuple()
  140. {
  141.   NdbConnection* tNdbCon = theNdbCon;
  142.   int tErrorLine = theErrorLine;
  143.   if (theStatus == Init) {
  144.     theStatus = OperationDefined;  
  145.     tNdbCon->theSimpleState = 0;
  146.     theOperationType = DeleteRequest;
  147.     theErrorLine = tErrorLine++;
  148.     theLockMode = LM_Exclusive;
  149.     return 0;
  150.   } else {
  151.     setErrorCode(4200);
  152.     return -1;
  153.   }//if
  154. }//NdbOperation::deleteTuple()
  155. /******************************************************************************
  156.  * int readTupleExclusive();
  157.  *****************************************************************************/
  158. int
  159. NdbOperation::readTupleExclusive()
  160.   NdbConnection* tNdbCon = theNdbCon;
  161.   int tErrorLine = theErrorLine;
  162.   if (theStatus == Init) {
  163.     theStatus = OperationDefined;
  164.     tNdbCon->theSimpleState = 0;
  165.     theOperationType = ReadExclusive;
  166.     theErrorLine = tErrorLine++;
  167.     theLockMode = LM_Exclusive;
  168.     return 0;
  169.   } else {
  170.     setErrorCode(4200);
  171.     return -1;
  172.   }//if
  173. }//NdbOperation::readTupleExclusive()
  174. /*****************************************************************************
  175.  * int simpleRead();
  176.  *****************************************************************************/
  177. int
  178. NdbOperation::simpleRead()
  179. {
  180.   /**
  181.    * Currently/still disabled
  182.    */
  183.   return readTuple();
  184. #if 0
  185.   int tErrorLine = theErrorLine;
  186.   if (theStatus == Init) {
  187.     theStatus = OperationDefined;
  188.     theOperationType = ReadRequest;
  189.     theSimpleIndicator = 1;
  190.     theErrorLine = tErrorLine++;
  191.     theLockMode = LM_Read;
  192.     return 0;
  193.   } else {
  194.     setErrorCode(4200);
  195.     return -1;
  196.   }//if
  197. #endif
  198. }//NdbOperation::simpleRead()
  199. /*****************************************************************************
  200.  * int dirtyRead();
  201.  *****************************************************************************/
  202. int
  203. NdbOperation::dirtyRead()
  204. {
  205.   return committedRead();
  206. }//NdbOperation::dirtyRead()
  207. /*****************************************************************************
  208.  * int committedRead();
  209.  *****************************************************************************/
  210. int
  211. NdbOperation::committedRead()
  212. {
  213.   int tErrorLine = theErrorLine;
  214.   if (theStatus == Init) {
  215.     theStatus = OperationDefined;
  216.     theOperationType = ReadRequest;
  217.     theSimpleIndicator = 1;
  218.     theDirtyIndicator = 1;
  219.     theErrorLine = tErrorLine++;
  220.     theLockMode = LM_CommittedRead;
  221.     return 0;
  222.   } else {
  223.     setErrorCode(4200);
  224.     return -1;
  225.   }//if
  226. }//NdbOperation::committedRead()
  227. /*****************************************************************************
  228.  * int dirtyUpdate();
  229.  ****************************************************************************/
  230. int
  231. NdbOperation::dirtyUpdate()
  232. {
  233.   NdbConnection* tNdbCon = theNdbCon;
  234.   int tErrorLine = theErrorLine;
  235.   if (theStatus == Init) {
  236.     theStatus = OperationDefined;
  237.     theOperationType = UpdateRequest;
  238.     tNdbCon->theSimpleState = 0;
  239.     theSimpleIndicator = 1;
  240.     theDirtyIndicator = 1;
  241.     theErrorLine = tErrorLine++;
  242.     theLockMode = LM_CommittedRead;
  243.     return 0;
  244.   } else {
  245.     setErrorCode(4200);
  246.     return -1;
  247.   }//if
  248. }//NdbOperation::dirtyUpdate()
  249. /******************************************************************************
  250.  * int dirtyWrite();
  251.  *****************************************************************************/
  252. int
  253. NdbOperation::dirtyWrite()
  254. {
  255.   NdbConnection* tNdbCon = theNdbCon;
  256.   int tErrorLine = theErrorLine;
  257.   if (theStatus == Init) {
  258.     theStatus = OperationDefined;
  259.     theOperationType = WriteRequest;
  260.     tNdbCon->theSimpleState = 0;
  261.     theSimpleIndicator = 1;
  262.     theDirtyIndicator = 1;
  263.     theErrorLine = tErrorLine++;
  264.     theLockMode = LM_CommittedRead;
  265.     return 0;
  266.   } else {
  267.     setErrorCode(4200);
  268.     return -1;
  269.   }//if
  270. }//NdbOperation::dirtyWrite()
  271. /******************************************************************************
  272.  * int interpretedUpdateTuple();
  273.  ****************************************************************************/
  274. int
  275. NdbOperation::interpretedUpdateTuple()
  276. {
  277.   NdbConnection* tNdbCon = theNdbCon;
  278.   int tErrorLine = theErrorLine;
  279.   if (theStatus == Init) {
  280.     theStatus = OperationDefined;
  281.     tNdbCon->theSimpleState = 0;
  282.     theOperationType = UpdateRequest;
  283.     theAI_LenInCurrAI = 25;
  284.     theLockMode = LM_Exclusive;
  285.     theErrorLine = tErrorLine++;
  286.     initInterpreter();
  287.     return 0;
  288.   } else {
  289.     setErrorCode(4200);
  290.     return -1;
  291.   }//if
  292. }//NdbOperation::interpretedUpdateTuple()
  293. /*****************************************************************************
  294.  * int interpretedDeleteTuple();
  295.  *****************************************************************************/
  296. int
  297. NdbOperation::interpretedDeleteTuple()
  298. {
  299.   NdbConnection* tNdbCon = theNdbCon;
  300.   int tErrorLine = theErrorLine;
  301.   if (theStatus == Init) {
  302.     theStatus = OperationDefined;
  303.     tNdbCon->theSimpleState = 0;
  304.     theOperationType = DeleteRequest;
  305.     theErrorLine = tErrorLine++;
  306.     theAI_LenInCurrAI = 25;
  307.     theLockMode = LM_Exclusive;
  308.     initInterpreter();
  309.     return 0;
  310.   } else {
  311.     setErrorCode(4200);
  312.     return -1;
  313.   }//if
  314. }//NdbOperation::interpretedDeleteTuple()
  315. /******************************************************************************
  316.  * int getValue(AttrInfo* tAttrInfo, char* aRef )
  317.  *
  318.  * Return Value   Return 0 : GetValue was successful.
  319.  *                Return -1: In all other case. 
  320.  * Parameters:    tAttrInfo : Attribute object of the retrieved attribute 
  321.  *                            value.
  322.  * Remark:        Define an attribute to retrieve in query.
  323.  *****************************************************************************/
  324. NdbRecAttr*
  325. NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
  326. {
  327.   NdbRecAttr* tRecAttr;
  328.   if ((tAttrInfo != NULL) &&
  329.       (!tAttrInfo->m_indexOnly) && 
  330.       (theStatus != Init)){
  331.     if (theStatus != GetValue) {
  332.       if (theInterpretIndicator == 1) {
  333. if (theStatus == FinalGetValue) {
  334.   ; // Simply continue with getValue
  335. } else if (theStatus == ExecInterpretedValue) {
  336.   if (insertATTRINFO(Interpreter::EXIT_OK) == -1)
  337.     return NULL;
  338.   theInterpretedSize = theTotalCurrAI_Len -
  339.     (theInitialReadSize + 5);
  340. } else if (theStatus == SetValueInterpreted) {
  341.   theFinalUpdateSize = theTotalCurrAI_Len - 
  342.     (theInitialReadSize + theInterpretedSize + 5);
  343. } else {
  344.   setErrorCodeAbort(4230);
  345.   return NULL;
  346. }//if
  347. // MASV - How would execution come here?
  348. theStatus = FinalGetValue;
  349.       } else {
  350. setErrorCodeAbort(4230);
  351. return NULL;
  352.       }//if
  353.     }//if
  354.     Uint32 ah;
  355.     AttributeHeader::init(&ah, tAttrInfo->m_attrId, 0);
  356.     if (insertATTRINFO(ah) != -1) {
  357.       // Insert Attribute Id into ATTRINFO part. 
  358.       
  359.       /************************************************************************
  360.        * Get a Receive Attribute object and link it into the operation object.
  361.        ***********************************************************************/
  362.       if((tRecAttr = theReceiver.getValue(tAttrInfo, aValue)) != 0){
  363. theErrorLine++;
  364. return tRecAttr;
  365.       } else {  
  366. setErrorCodeAbort(4000);
  367. return NULL;
  368.       }
  369.     } else {
  370.       return NULL;
  371.     }//if insertATTRINFO failure
  372.   } else {
  373.     if (tAttrInfo == NULL) {
  374.       setErrorCodeAbort(4004);      
  375.       return NULL;
  376.     }//if
  377.     if (tAttrInfo->m_indexOnly){
  378.       setErrorCodeAbort(4208);
  379.       return NULL;
  380.     }//if
  381.   }//if
  382.   setErrorCodeAbort(4200);
  383.   return NULL;
  384. }
  385. /*****************************************************************************
  386.  * int setValue(AttrInfo* tAttrInfo, char* aValue, Uint32 len)
  387.  *
  388.  * Return Value:  Return 0 : SetValue was succesful.
  389.  *                Return -1: In all other case.   
  390.  * Parameters:    tAttrInfo : Attribute object where the attribute 
  391.  *                            info exists.
  392.  *                aValue : Reference to the variable with the new value.
  393.  *   len    : Length of the value
  394.  * Remark:        Define a attribute to set in a query.
  395. ******************************************************************************/
  396. int
  397. NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, 
  398. const char* aValuePassed, Uint32 len)
  399. {
  400.   int tReturnCode;
  401.   Uint32 tAttrId;
  402.   Uint32 tData;
  403.   Uint32 tempData[2000];
  404.   OperationType tOpType = theOperationType;
  405.   OperationStatus tStatus = theStatus;
  406.   
  407.   if ((tOpType == UpdateRequest) ||
  408.       (tOpType == WriteRequest)) {
  409.     if (theInterpretIndicator == 0) {
  410.       if (tStatus == SetValue) {
  411.         ;
  412.       } else {
  413.         setErrorCodeAbort(4234);
  414.         return -1;
  415.       }//if
  416.     } else {
  417.       if (tStatus == GetValue) {
  418.         theInitialReadSize = theTotalCurrAI_Len - 5;
  419.       } else if (tStatus == ExecInterpretedValue) {
  420. //--------------------------------------------------------------------
  421. // We insert an exit from interpretation since we are now starting 
  422. // to set values in the tuple by setValue.
  423. //--------------------------------------------------------------------
  424.         if (insertATTRINFO(Interpreter::EXIT_OK) == -1){
  425.           return -1;
  426. }
  427.         theInterpretedSize = theTotalCurrAI_Len - 
  428.           (theInitialReadSize + 5);
  429.       } else if (tStatus == SetValueInterpreted) {
  430.         ; // Simply continue adding new setValue
  431.       } else {
  432. //--------------------------------------------------------------------
  433. // setValue used in the wrong context. Application coding error.
  434. //-------------------------------------------------------------------
  435.         setErrorCodeAbort(4234); //Wrong error code
  436.         return -1;
  437.       }//if
  438.       theStatus = SetValueInterpreted;
  439.     }//if
  440.   } else if (tOpType == InsertRequest) {
  441.     if ((theStatus != SetValue) && (theStatus != OperationDefined)) {
  442.       setErrorCodeAbort(4234);
  443.       return -1;
  444.     }//if
  445.   } else if (tOpType == ReadRequest || tOpType == ReadExclusive) {
  446.     setErrorCodeAbort(4504);
  447.     return -1;
  448.   } else if (tOpType == DeleteRequest) {
  449.     setErrorCodeAbort(4504);
  450.     return -1;
  451.   } else if (tOpType == OpenScanRequest || tOpType == OpenRangeScanRequest) {
  452.     setErrorCodeAbort(4228);
  453.     return -1;
  454.   } else {
  455.     //---------------------------------------------------------------------
  456.     // setValue with undefined operation type. 
  457.     // Probably application coding error.
  458.     //---------------------------------------------------------------------
  459.     setErrorCodeAbort(4108);
  460.     return -1;
  461.   }//if
  462.   if (tAttrInfo == NULL) {
  463.     setErrorCodeAbort(4004);      
  464.     return -1;
  465.   }//if
  466.   if (tAttrInfo->m_pk) {
  467.     if (theOperationType == InsertRequest) {
  468.       return equal_impl(tAttrInfo, aValuePassed, len);
  469.     } else {
  470.       setErrorCodeAbort(4202);      
  471.       return -1;
  472.     }//if
  473.   }//if
  474.   if (len > 8000) {
  475.     setErrorCodeAbort(4216);
  476.     return -1;
  477.   }//if
  478.   
  479.   tAttrId = tAttrInfo->m_attrId;
  480.   const char *aValue = aValuePassed; 
  481.   Uint32 ahValue;
  482.   if (aValue == NULL) {
  483.     if (tAttrInfo->m_nullable) {
  484.       AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, 0);
  485.       ah.setNULL();
  486.       insertATTRINFO(ahValue);
  487.       // Insert Attribute Id with the value
  488.       // NULL into ATTRINFO part. 
  489.       return 0;
  490.     } else {
  491.       /***********************************************************************
  492.        * Setting a NULL value on a NOT NULL attribute is not allowed.
  493.        **********************************************************************/
  494.       setErrorCodeAbort(4203);      
  495.       return -1;
  496.     }//if
  497.   }//if
  498.   
  499.   // Insert Attribute Id into ATTRINFO part. 
  500.   const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
  501.   CHARSET_INFO* cs = tAttrInfo->m_cs;
  502.   int dummy_error;
  503.   // invalid data can crash kernel
  504.   if (cs != NULL &&
  505.       // fast fix bug#7340
  506.       tAttrInfo->m_type != NdbDictionary::Column::Text &&
  507.      (*cs->cset->well_formed_len)(cs,
  508.                                    aValue,
  509.                                    aValue + sizeInBytes,
  510.                                    sizeInBytes,
  511.                                    &dummy_error) != sizeInBytes) {
  512.     setErrorCodeAbort(744);
  513.     return -1;
  514.   }
  515. #if 0
  516.   tAttrSize = tAttrInfo->theAttrSize;
  517.   tArraySize = tAttrInfo->theArraySize;
  518.   if (tArraySize == 0) {
  519.     setErrorCodeAbort(4201);      
  520.     return -1;
  521.   }//if
  522.   tAttrSizeInBits = tAttrSize*tArraySize;
  523.   tAttrSizeInWords = tAttrSizeInBits >> 5;
  524. #endif
  525.   const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
  526.   if (len != sizeInBytes && (len != 0)) {
  527.     setErrorCodeAbort(4209);
  528.     return -1;
  529.   }//if
  530.   const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word
  531.   const Uint32 sizeInWords = sizeInBytes / 4;          // Excluding bits in last word
  532.   AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, 
  533.       totalSizeInWords);
  534.   insertATTRINFO( ahValue );
  535.   /***********************************************************************
  536.    * Check if the pointer of the value passed is aligned on a 4 byte boundary.
  537.    * If so only assign the pointer to the internal variable aValue. 
  538.    * If it is not aligned then we start by copying the value to tempData and 
  539.    * use this as aValue instead.
  540.    *************************************************************************/
  541.   const int attributeSize = sizeInBytes;
  542.   const int slack = sizeInBytes & 3;
  543.   
  544.   if (((UintPtr)aValue & 3) != 0 || (slack != 0)){
  545.     memcpy(&tempData[0], aValue, attributeSize);
  546.     aValue = (char*)&tempData[0];
  547.     if(slack != 0) {
  548.       char * tmp = (char*)&tempData[0];
  549.       memset(&tmp[attributeSize], 0, (4 - slack));
  550.     }//if
  551.   }//if
  552.   
  553.   tReturnCode = insertATTRINFOloop((Uint32*)aValue, sizeInWords);
  554.   if (tReturnCode == -1) {
  555.     return tReturnCode;
  556.   }//if
  557.   if (bitsInLastWord != 0) {
  558.     tData = *(Uint32*)(aValue + sizeInWords*4);
  559.     tData = convertEndian(tData);
  560.     tData = tData & ((1 << bitsInLastWord) - 1);
  561.     tData = convertEndian(tData);
  562.     tReturnCode = insertATTRINFO(tData);
  563.     if (tReturnCode == -1) {
  564.       return tReturnCode;
  565.     }//if
  566.   }//if
  567.   theErrorLine++;  
  568.   return 0;
  569. }//NdbOperation::setValue()
  570. NdbBlob*
  571. NdbOperation::getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* tAttrInfo)
  572. {
  573.   NdbBlob* tBlob = theBlobList;
  574.   NdbBlob* tLastBlob = NULL;
  575.   while (tBlob != NULL) {
  576.     if (tBlob->theColumn == tAttrInfo)
  577.       return tBlob;
  578.     tLastBlob = tBlob;
  579.     tBlob = tBlob->theNext;
  580.   }
  581.   tBlob = theNdb->getNdbBlob();
  582.   if (tBlob == NULL)
  583.     return NULL;
  584.   if (tBlob->atPrepare(aCon, this, tAttrInfo) == -1) {
  585.     theNdb->releaseNdbBlob(tBlob);
  586.     return NULL;
  587.   }
  588.   if (tLastBlob == NULL)
  589.     theBlobList = tBlob;
  590.   else
  591.     tLastBlob->theNext = tBlob;
  592.   tBlob->theNext = NULL;
  593.   theNdbCon->theBlobFlag = true;
  594.   return tBlob;
  595. }
  596. /****************************************************************************
  597.  * int insertATTRINFO( Uint32 aData );
  598.  *
  599.  * Return Value:   Return 0 : insertATTRINFO was succesful.
  600.  *                 Return -1: In all other case.   
  601.  * Parameters:     aData: the data to insert into ATTRINFO.
  602.  * Remark:         Puts the the data into either TCKEYREQ signal or 
  603.  *                 ATTRINFO signal.
  604.  *****************************************************************************/
  605. int
  606. NdbOperation::insertATTRINFO( Uint32 aData )
  607. {
  608.   NdbApiSignal* tSignal;
  609.   register Uint32 tAI_LenInCurrAI = theAI_LenInCurrAI;
  610.   register Uint32* tAttrPtr = theATTRINFOptr;
  611.   register Uint32 tTotCurrAILen = theTotalCurrAI_Len;
  612.   if (tAI_LenInCurrAI >= 25) {
  613.     Ndb* tNdb = theNdb;
  614.     NdbApiSignal* tFirstAttrinfo = theFirstATTRINFO;
  615.     tAI_LenInCurrAI = 3;
  616.     tSignal = tNdb->getSignal();
  617.     if (tSignal != NULL) {
  618.       tSignal->setSignal(m_attrInfoGSN);
  619.       tAttrPtr = &tSignal->getDataPtrSend()[3];
  620.       if (tFirstAttrinfo == NULL) {
  621.         tSignal->next(NULL);
  622.         theFirstATTRINFO = tSignal;
  623.         theCurrentATTRINFO = tSignal;
  624.       } else {
  625.         NdbApiSignal* tCurrentAttrinfoBeforeUpdate = theCurrentATTRINFO;
  626.         tSignal->next(NULL);
  627.         theCurrentATTRINFO = tSignal;
  628.         tCurrentAttrinfoBeforeUpdate->next(tSignal);
  629.       }//if
  630.     } else {
  631.       goto insertATTRINFO_error1;
  632.     }//if
  633.   }//if
  634.   *tAttrPtr = aData;
  635.   tAttrPtr++;
  636.   tTotCurrAILen++;
  637.   tAI_LenInCurrAI++;
  638.   theTotalCurrAI_Len = tTotCurrAILen;
  639.   theAI_LenInCurrAI = tAI_LenInCurrAI;
  640.   theATTRINFOptr = tAttrPtr;
  641.   return 0;
  642. insertATTRINFO_error1:
  643.   setErrorCodeAbort(4000);
  644.   return -1;
  645. }//NdbOperation::insertATTRINFO()
  646. /*****************************************************************************
  647.  * int insertATTRINFOloop(Uint32* aDataPtr, Uint32 aLength );
  648.  *
  649.  * Return Value:  Return 0 : insertATTRINFO was succesful.
  650.  *                Return -1: In all other case.   
  651.  * Parameters:    aDataPtr: Pointer to the data to insert into ATTRINFO.
  652.  *                aLength: Length of data to be copied
  653.  * Remark:        Puts the the data into either TCKEYREQ signal or 
  654.  *                ATTRINFO signal.
  655.  *****************************************************************************/
  656. int
  657. NdbOperation::insertATTRINFOloop(register const Uint32* aDataPtr, 
  658.  register Uint32 aLength)
  659. {
  660.   NdbApiSignal* tSignal;
  661.   register Uint32 tAI_LenInCurrAI = theAI_LenInCurrAI;
  662.   register Uint32 tTotCurrAILen = theTotalCurrAI_Len;
  663.   register Uint32* tAttrPtr = theATTRINFOptr;  
  664.   Ndb* tNdb = theNdb;
  665.   while (aLength > 0) {
  666.     if (tAI_LenInCurrAI >= 25) {
  667.       NdbApiSignal* tFirstAttrinfo = theFirstATTRINFO;
  668.       tAI_LenInCurrAI = 3;
  669.       tSignal = tNdb->getSignal();
  670.       if (tSignal != NULL) {
  671.         tSignal->setSignal(m_attrInfoGSN);
  672.         tAttrPtr = &tSignal->getDataPtrSend()[3];
  673.         if (tFirstAttrinfo == NULL) {
  674.           tSignal->next(NULL);
  675.           theFirstATTRINFO = tSignal;
  676.           theCurrentATTRINFO = tSignal;
  677.         } else {
  678.           NdbApiSignal* tCurrentAttrinfoBeforeUpdate = theCurrentATTRINFO;
  679.           tSignal->next(NULL);
  680.           theCurrentATTRINFO = tSignal;
  681.           tCurrentAttrinfoBeforeUpdate->next(tSignal);
  682.         }//if
  683.       } else {
  684.         goto insertATTRINFO_error1;
  685.       }//if
  686.     }//if
  687.     {
  688.       register Uint32 tData = *aDataPtr;
  689.       aDataPtr++;
  690.       aLength--;
  691.       tAI_LenInCurrAI++;
  692.       *tAttrPtr = tData;
  693.       tAttrPtr++;
  694.       tTotCurrAILen++;
  695.     }
  696.   }//while
  697.   theATTRINFOptr = tAttrPtr;
  698.   theTotalCurrAI_Len = tTotCurrAILen;
  699.   theAI_LenInCurrAI = tAI_LenInCurrAI;
  700.   return 0;
  701. insertATTRINFO_error1:
  702.   setErrorCodeAbort(4000);
  703.   return -1;
  704. }//NdbOperation::insertATTRINFOloop()