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

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:          NdbOperationSearch.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.  971206  UABRONM
  24.  *****************************************************************************/
  25. #include "API.hpp"
  26. #include <NdbOperation.hpp>
  27. #include "NdbApiSignal.hpp"
  28. #include <NdbConnection.hpp>
  29. #include <Ndb.hpp>
  30. #include "NdbImpl.hpp"
  31. #include <NdbOut.hpp>
  32. #include <AttributeHeader.hpp>
  33. #include <signaldata/TcKeyReq.hpp>
  34. #include "NdbDictionaryImpl.hpp"
  35. /******************************************************************************
  36. CondIdType equal(const char* anAttrName, char* aValue, Uint32 aVarKeylen);
  37. Return Value    Return 0 : Equal was successful.
  38.                 Return -1: In all other case. 
  39. Parameters:     anAttrName : Attribute name for search condition..
  40.                 aValue : Referense to the search value.
  41. aVariableKeylen : The length of key in bytes  
  42. Remark:         Defines search condition with equality anAttrName.
  43. ******************************************************************************/
  44. int
  45. NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo, 
  46.                          const char* aValuePassed, 
  47.                          Uint32 aVariableKeyLen)
  48. {
  49.   register Uint32 tAttrId;
  50.   
  51.   Uint32 tData;
  52.   Uint32 tKeyInfoPosition;
  53.   const char* aValue = aValuePassed;
  54.   Uint32 xfrmData[1024];
  55.   Uint32 tempData[1024];
  56.   if ((theStatus == OperationDefined) &&
  57.       (aValue != NULL) &&
  58.       (tAttrInfo != NULL )) {
  59. /******************************************************************************
  60.  * Start by checking that the attribute is a tuple key. 
  61.  *      This value is also the word order in the tuple key of this 
  62.  *      tuple key attribute. 
  63.  *      Then check that this tuple key has not already been defined. 
  64.  *      Finally check if all tuple key attributes have been defined. If
  65.  * this is true then set Operation state to tuple key defined.
  66.  *****************************************************************************/
  67.     tAttrId = tAttrInfo->m_attrId;
  68.     tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
  69.     Uint32 i = 0;
  70.     if (tAttrInfo->m_pk) {
  71.       Uint32 tKeyDefined = theTupleKeyDefined[0][2];
  72.       Uint32 tKeyAttrId = theTupleKeyDefined[0][0];
  73.       do {
  74. if (tKeyDefined == false) {
  75.   goto keyEntryFound;
  76. } else {
  77.   if (tKeyAttrId != tAttrId) {
  78.     /******************************************************************
  79.      * We read the key defined variable in advance. 
  80.      * It could potentially read outside its area when 
  81.      * i = MAXNROFTUPLEKEY - 1, 
  82.      * it is not a problem as long as the variable 
  83.      * theTupleKeyDefined is defined
  84.      * in the middle of the object. 
  85.      * Reading wrong data and not using it causes no problems.
  86.      *****************************************************************/
  87.     i++;
  88.     tKeyAttrId = theTupleKeyDefined[i][0];
  89.     tKeyDefined = theTupleKeyDefined[i][2];
  90.     continue;
  91.   } else {
  92.     goto equal_error2;
  93.   }//if
  94. }//if
  95.       } while (i < NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY);
  96.       goto equal_error2;
  97.     } else {
  98.       goto equal_error1;
  99.     }
  100.     /*************************************************************************
  101.      * Now it is time to retrieve the tuple key data from the pointer supplied
  102.      *      by the application. 
  103.      *      We have to retrieve the size of the attribute in words and bits.
  104.      *************************************************************************/
  105.   keyEntryFound:
  106.     theTupleKeyDefined[i][0] = tAttrId;
  107.     theTupleKeyDefined[i][1] = tKeyInfoPosition; 
  108.     theTupleKeyDefined[i][2] = true;
  109.     Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
  110.     {
  111.       /***************************************************************************
  112.        * Check if the pointer of the value passed is aligned on a 4 byte 
  113.        *      boundary. If so only assign the pointer to the internal variable 
  114.        *      aValue. If it is not aligned then we start by copying the value to 
  115.        *      tempData and use this as aValue instead.
  116.        *****************************************************************************/
  117.       const int attributeSize = sizeInBytes;
  118.       const int slack = sizeInBytes & 3;
  119.       
  120.       if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
  121. memcpy(&tempData[0], aValue, attributeSize);
  122. aValue = (char*)&tempData[0];
  123. if(slack != 0) {
  124.   char * tmp = (char*)&tempData[0];
  125.   memset(&tmp[attributeSize], 0, (4 - slack));
  126. }//if
  127.       }//if
  128.     }
  129.     const char* aValueToWrite = aValue;
  130.     CHARSET_INFO* cs = tAttrInfo->m_cs;
  131.     if (cs != 0) {
  132.       // current limitation: strxfrm does not increase length
  133.       assert(cs->strxfrm_multiply <= 1);
  134.       unsigned n =
  135.       (*cs->coll->strnxfrm)(cs,
  136.                             (uchar*)xfrmData, sizeof(xfrmData),
  137.                             (const uchar*)aValue, sizeInBytes);
  138.       while (n < sizeInBytes)
  139.         ((uchar*)xfrmData)[n++] = 0x20;
  140.       aValue = (char*)xfrmData;
  141.     }
  142.     Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
  143.     Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
  144.     Uint32 sizeInWords = sizeInBytes / 4;          // Exc. bits in last word
  145.     
  146.     if (true){ //tArraySize != 0) {
  147.       Uint32 tTupKeyLen = theTupKeyLen;
  148.       
  149.       theTupKeyLen = tTupKeyLen + totalSizeInWords;
  150.       if ((aVariableKeyLen == sizeInBytes) ||
  151.   (aVariableKeyLen == 0)) {
  152. ;
  153.       } else {
  154. goto equal_error3;
  155.       }
  156.     }
  157. #if 0
  158.     else {
  159.       /************************************************************************
  160.        * The attribute is a variable array. We need to use the length parameter
  161.        * to know the size of this attribute in the key information and 
  162.        * variable area. A key is however not allowed to be larger than 4 
  163.        * kBytes and this is checked for variable array attributes
  164.        * used as keys.
  165.        ************************************************************************/
  166.       Uint32 tMaxVariableKeyLenInWord = (MAXTUPLEKEYLENOFATTERIBUTEINWORD -
  167.  tKeyInfoPosition);
  168.       tAttrSizeInBits = aVariableKeyLen << 3;
  169.       tAttrSizeInWords = tAttrSizeInBits >> 5;
  170.       tAttrBitsInLastWord = tAttrSizeInBits - (tAttrSizeInWords << 5);
  171.       tAttrLenInWords = ((tAttrSizeInBits + 31) >> 5);
  172.       if (tAttrLenInWords > tMaxVariableKeyLenInWord) {
  173. setErrorCodeAbort(4207);
  174. return -1;
  175.       }//if
  176.       theTupKeyLen = theTupKeyLen + tAttrLenInWords;
  177.     }//if
  178. #endif
  179.     int tDistrKey = tAttrInfo->m_distributionKey;
  180.     int tDistrGroup = tAttrInfo->m_distributionGroup;
  181.     OperationType tOpType = theOperationType;
  182.     if ((tDistrKey != 1) && (tDistrGroup != 1)) {
  183.       ;
  184.     } else if (tDistrKey == 1) {
  185.       theDistrKeySize += totalSizeInWords;
  186.       theDistrKeyIndicator = 1;
  187.     } else {
  188.       Uint32 TsizeInBytes = sizeInBytes;
  189.       Uint32 TbyteOrderFix = 0;
  190.       char*   TcharByteOrderFix = (char*)&TbyteOrderFix;
  191.       if (tAttrInfo->m_distributionGroupBits == 8) {
  192. char tFirstChar = aValue[TsizeInBytes - 2];
  193. char tSecondChar = aValue[TsizeInBytes - 2];
  194. TcharByteOrderFix[0] = tFirstChar;
  195. TcharByteOrderFix[1] = tSecondChar;
  196. TcharByteOrderFix[2] = 0x30;
  197. TcharByteOrderFix[3] = 0x30;
  198. theDistrGroupType = 0;
  199.       } else {
  200. TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10) 
  201.   + (aValue[TsizeInBytes - 1] - 0x30);
  202. theDistrGroupType = 1;
  203.       }//if
  204.       theDistributionGroup = TbyteOrderFix;
  205.       theDistrGroupIndicator = 1;
  206.     }//if
  207.     /******************************************************************************
  208.      * If the operation is an insert request and the attribute is stored then
  209.      *      we also set the value in the stored part through putting the 
  210.      *      information in the ATTRINFO signals.
  211.      *****************************************************************************/
  212.     if ((tOpType == InsertRequest) ||
  213. (tOpType == WriteRequest)) {
  214.       if (!tAttrInfo->m_indexOnly){
  215.         int dummy_error;
  216.         // invalid data can crash kernel
  217.         if (cs != NULL &&
  218.            (*cs->cset->well_formed_len)(cs,
  219.                                         aValueToWrite,
  220.                                         aValueToWrite + sizeInBytes,
  221.                                         sizeInBytes,
  222.                                         &dummy_error) != sizeInBytes)
  223.           goto equal_error4;
  224. Uint32 ahValue;
  225. const Uint32 sz = totalSizeInWords;
  226. AttributeHeader::init(&ahValue, tAttrId, sz);
  227. insertATTRINFO( ahValue );
  228. insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
  229. if (bitsInLastWord != 0) {
  230.   tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
  231.   tData = convertEndian(tData);
  232.   tData = tData & ((1 << bitsInLastWord) - 1);
  233.   tData = convertEndian(tData);
  234.   insertATTRINFO( tData );
  235. }//if
  236.       }//if
  237.     }//if
  238.     
  239.     /***************************************************************************
  240.      * Store the Key information in the TCKEYREQ and KEYINFO signals. 
  241.      **************************************************************************/
  242.     if (insertKEYINFO(aValue, tKeyInfoPosition, 
  243.       totalSizeInWords, bitsInLastWord) != -1) {
  244.       /*************************************************************************
  245.        * Add one to number of tuple key attributes defined. 
  246.        * If all have been defined then set the operation state to indicate 
  247.        * that tuple key is defined. 
  248.        * Thereby no more search conditions are allowed in this version.
  249.        ************************************************************************/
  250.       Uint32 tNoKeysDef = theNoOfTupKeyDefined;
  251.       Uint32 tErrorLine = theErrorLine;
  252.       int tNoTableKeys = m_currentTable->m_noOfKeys;
  253.       unsigned char tInterpretInd = theInterpretIndicator;
  254.       tNoKeysDef++;
  255.       theNoOfTupKeyDefined = tNoKeysDef;
  256.       tErrorLine++;
  257.       theErrorLine = tErrorLine;
  258.       if (int(tNoKeysDef) == tNoTableKeys) {
  259. if (tOpType == UpdateRequest) {
  260.   if (tInterpretInd == 1) {
  261.     theStatus = GetValue;
  262.   } else {
  263.     theStatus = SetValue;
  264.   }//if
  265.   return 0;
  266. } else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
  267.    (tOpType == ReadExclusive)) {
  268.   theStatus = GetValue;
  269.           // create blob handles automatically
  270.           if (tOpType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
  271.             for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
  272.               NdbColumnImpl* c = m_currentTable->m_columns[i];
  273.               assert(c != 0);
  274.               if (c->getBlobType()) {
  275.                 if (getBlobHandle(theNdbCon, c) == NULL)
  276.                   return -1;
  277.               }
  278.             }
  279.           }
  280.   return 0;
  281. } else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
  282.   theStatus = SetValue;
  283.   return 0;
  284. } else {
  285.   setErrorCodeAbort(4005);
  286.   return -1;
  287. }//if
  288.       }//if
  289.       return 0;
  290.     } else {
  291.       return -1;
  292.     }//if
  293.   }
  294.   if (aValue == NULL) {
  295.     // NULL value in primary key
  296.     setErrorCodeAbort(4505);
  297.     return -1;
  298.   }//if
  299.   
  300.   if ( tAttrInfo == NULL ) {      
  301.     // Attribute name not found in table
  302.     setErrorCodeAbort(4004);
  303.     return -1;
  304.   }//if
  305.   if (theStatus == GetValue || theStatus == SetValue){
  306.     // All pk's defined
  307.     setErrorCodeAbort(4225);
  308.     return -1;
  309.   }//if
  310.   
  311.   // If we come here, set a general errorcode
  312.   // and exit
  313.   setErrorCodeAbort(4200);
  314.   return -1;
  315.  equal_error1:
  316.   setErrorCodeAbort(4205);
  317.   return -1;
  318.  equal_error2:
  319.   setErrorCodeAbort(4206);
  320.   return -1;
  321.  equal_error3:
  322.   setErrorCodeAbort(4209);
  323.   return -1;
  324.  equal_error4:
  325.   setErrorCodeAbort(744);
  326.   return -1;
  327. }
  328. /******************************************************************************
  329.  * Uint64 setTupleId( void )
  330.  *
  331.  * Return Value:  Return > 0: OK 
  332.  *                Return 0 : setTupleId failed
  333.  * Parameters:     
  334.  * Remark:
  335.  *****************************************************************************/
  336. Uint64
  337. NdbOperation::setTupleId()
  338. {
  339.   if (theStatus != OperationDefined)
  340.   {
  341.     return 0;
  342.   }
  343.   Uint64 tTupleId = theNdb->getTupleIdFromNdb(m_currentTable->m_tableId);
  344.   if (tTupleId == ~(Uint64)0){
  345.     setErrorCodeAbort(theNdb->theError.code);
  346.     return 0;
  347.   }
  348.   if (equal((Uint32)0, tTupleId) == -1)
  349.     return 0;
  350.   return tTupleId;
  351. }
  352. /******************************************************************************
  353.  * int insertKEYINFO(const char* aValue, aStartPosition, 
  354.  *                   anAttrSizeInWords, Uint32 anAttrBitsInLastWord);
  355.  *
  356.  * Return Value:   Return 0 : insertKEYINFO was succesful.
  357.  *                 Return -1: In all other case.   
  358.  * Parameters:     aValue: the data to insert into KEYINFO.
  359.  *        aStartPosition : Start position for Tuplekey in 
  360.  *                                  KEYINFO (TCKEYREQ).
  361.  *                 aKeyLenInByte : Length of tuplekey or part of tuplekey
  362.  *                 anAttrBitsInLastWord : Nr of bits in last word. 
  363.  * Remark:         Puts the the data into either TCKEYREQ signal 
  364.  *                 or KEYINFO signal.
  365.  *****************************************************************************/
  366. int
  367. NdbOperation::insertKEYINFO(const char* aValue,
  368.     register Uint32 aStartPosition,
  369.     register Uint32 anAttrSizeInWords,
  370.     register Uint32 anAttrBitsInLastWord)
  371. {
  372.   NdbApiSignal* tSignal;
  373.   NdbApiSignal* tCurrentKEYINFO;
  374.   //register NdbApiSignal* tTCREQ = theTCREQ;
  375.   register Uint32 tAttrPos;
  376.   Uint32 tPosition;
  377.   Uint32 tEndPos;
  378.   Uint32 tPos;
  379.   Uint32 signalCounter;
  380.   Uint32 tData;
  381. /*****************************************************************************
  382.  * Calculate the end position of the attribute in the key information.  *
  383.  * Since the first attribute starts at position one we need to subtract *
  384.  * one to get the correct end position.      *
  385.  * We must also remember the last word with only partial information.   *
  386.  *****************************************************************************/
  387.   tEndPos = aStartPosition + anAttrSizeInWords - 1;
  388.   if ((tEndPos < 9) && (anAttrBitsInLastWord == 0)) {
  389.     register Uint32 tkeyData = *(Uint32*)aValue;
  390.     //TcKeyReq* tcKeyReq = CAST_PTR(TcKeyReq, tTCREQ->getDataPtrSend());
  391.     register Uint32* tDataPtr = (Uint32*)aValue;
  392.     tAttrPos = 1;
  393.     register Uint32* tkeyDataPtr = theKEYINFOptr + aStartPosition - 1;
  394.     // (Uint32*)&tcKeyReq->keyInfo[aStartPosition - 1];
  395.     do {
  396.       tDataPtr++;
  397.       *tkeyDataPtr = tkeyData;
  398.       if (tAttrPos < anAttrSizeInWords) {
  399.         ;
  400.       } else {
  401.         return 0;
  402.       }//if
  403.       tkeyData = *tDataPtr;
  404.       tkeyDataPtr++;
  405.       tAttrPos++;
  406.     } while (1);
  407.     return 0;
  408.   }//if
  409. /*****************************************************************************
  410.  * Allocate all the KEYINFO signals needed for this key before starting *
  411.  * to fill the signals with data. This simplifies error handling and    *
  412.  *      avoids duplication of code.      *
  413.  *****************************************************************************/
  414.   tAttrPos = 0;
  415.   signalCounter = 1;
  416.   while(tEndPos > theTotalNrOfKeyWordInSignal)
  417.   {
  418.     tSignal = theNdb->getSignal();
  419.     if (tSignal == NULL)
  420.     {
  421.       setErrorCodeAbort(4000);
  422.       return -1;
  423.     }
  424.     if (tSignal->setSignal(m_keyInfoGSN) == -1)
  425.     {
  426.       setErrorCodeAbort(4001);
  427.       return -1;
  428.     }
  429.     if (theFirstKEYINFO != NULL)
  430.        theLastKEYINFO->next(tSignal);
  431.     else
  432.        theFirstKEYINFO = tSignal;
  433.     theLastKEYINFO = tSignal;
  434.     theLastKEYINFO->next(NULL);
  435.     theTotalNrOfKeyWordInSignal += 20;
  436.   }
  437. /*****************************************************************************
  438.  * Change to variable tPosition for more appropriate naming of rest of  *
  439.  * the code. We must set up current KEYINFO already here if the last    *
  440.  * word is a word which is set at LastWordLabel and at the same time    *
  441.  * this is the first word in a KEYINFO signal.      *
  442.  *****************************************************************************/
  443.   tPosition = aStartPosition;
  444.   tCurrentKEYINFO = theFirstKEYINFO;
  445.  
  446. /*****************************************************************************
  447.  * Start by filling up Key information in the 8 words allocated in the  *
  448.  * TC[KEY/INDX]REQ signal.      *
  449.  *****************************************************************************/
  450.   while (tPosition < 9)
  451.   {
  452.     theKEYINFOptr[tPosition-1] = * (Uint32*)(aValue + (tAttrPos << 2));
  453.     tAttrPos++;
  454.     if (anAttrSizeInWords == tAttrPos)
  455.       goto LastWordLabel;
  456.     tPosition++;
  457.   }
  458. /*****************************************************************************
  459.  * We must set up the start position of the writing of Key information  *
  460.  * before we start the writing of KEYINFO signals. If the start is not  *
  461.  * the first word of the first KEYINFO signals then we must step forward*
  462.  * to the proper KEYINFO signal and set the signalCounter properly.     *
  463.  * signalCounter is set to the actual position in the signal ( = 4 for  *
  464.  * first key word in KEYINFO signal.      *
  465.  *****************************************************************************/
  466.   tPos = 8;
  467.   while ((tPosition - tPos) > 20)
  468.   {
  469.     tCurrentKEYINFO = tCurrentKEYINFO->next();
  470.     tPos += 20;
  471.   }
  472.   signalCounter = tPosition - tPos + 3;    
  473. /*****************************************************************************
  474.  * The loop that actually fills in the Key information into the KEYINFO *
  475.  * signals. Can be optimised by writing larger chunks than 4 bytes at a *
  476.  * time.      *
  477.  *****************************************************************************/
  478.   do
  479.   {
  480.     if (signalCounter > 23)
  481.     {
  482.       tCurrentKEYINFO = tCurrentKEYINFO->next();
  483.       signalCounter = 4;
  484.     }
  485.     tCurrentKEYINFO->setData(*(Uint32*)(aValue + (tAttrPos << 2)), 
  486.      signalCounter);
  487.     tAttrPos++;
  488.     if (anAttrSizeInWords == tAttrPos)
  489.       goto LastWordLabel;
  490.     tPosition++;
  491.     signalCounter++;
  492.   } while (1);
  493. LastWordLabel:
  494. /*****************************************************************************
  495.  * There could be a last word that only contains partial data. This word*
  496.  * will contain zeroes in the rest of the bits since the index expects  *
  497.  * a certain number of words and do not care for parts of words.      *
  498.  *****************************************************************************/
  499.   if (anAttrBitsInLastWord != 0) {
  500.     tData = *(Uint32*)(aValue + (anAttrSizeInWords - 1) * 4);
  501.     tData = convertEndian(tData);
  502.     tData = tData & ((1 << anAttrBitsInLastWord) - 1);
  503.     tData = convertEndian(tData);
  504.     if (tPosition > 8) {
  505.       tCurrentKEYINFO->setData(tData, signalCounter);
  506.       signalCounter++;
  507.     } else {
  508.       theTCREQ->setData(tData, (12 + tPosition));
  509.     }//if
  510.   }//if
  511.   return 0;
  512. }
  513. int
  514. NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
  515. {
  516.   assert(m_accessTable != 0 && m_accessTable->m_sizeOfKeysInWords != 0);
  517.   assert(m_accessTable->m_sizeOfKeysInWords == size);
  518.   unsigned pos = 0;
  519.   while (pos < 8 && pos < size) {
  520.     data[pos] = theKEYINFOptr[pos];
  521.     pos++;
  522.   }
  523.   NdbApiSignal* tSignal = theFirstKEYINFO;
  524.   unsigned n = 0;
  525.   while (pos < size) {
  526.     if (n == 20) {
  527.       tSignal = tSignal->next();
  528.       n = 0;
  529.     }
  530.     data[pos++] = tSignal->getDataPtrSend()[3 + n++];
  531.   }
  532.   return 0;
  533. }