diff options
Diffstat (limited to 'storage/ndb/src/ndbapi/NdbOperationDefine.cpp')
-rw-r--r-- | storage/ndb/src/ndbapi/NdbOperationDefine.cpp | 723 |
1 files changed, 723 insertions, 0 deletions
diff --git a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp new file mode 100644 index 00000000000..835e33dfb40 --- /dev/null +++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -0,0 +1,723 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <ndb_global.h> +#include <NdbOperation.hpp> +#include "NdbApiSignal.hpp" +#include <NdbTransaction.hpp> +#include <Ndb.hpp> +#include <NdbRecAttr.hpp> +#include "NdbUtil.hpp" +#include "NdbOut.hpp" +#include "NdbImpl.hpp" +#include <NdbIndexScanOperation.hpp> +#include <NdbBlob.hpp> + +#include <Interpreter.hpp> + +#include <AttributeHeader.hpp> +#include <signaldata/TcKeyReq.hpp> + +/***************************************************************************** + * int insertTuple(); + *****************************************************************************/ +int +NdbOperation::insertTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + theOperationType = InsertRequest; + tNdbCon->theSimpleState = 0; + theErrorLine = tErrorLine++; + theLockMode = LM_Exclusive; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::insertTuple() +/****************************************************************************** + * int updateTuple(); + *****************************************************************************/ +int +NdbOperation::updateTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = UpdateRequest; + theErrorLine = tErrorLine++; + theLockMode = LM_Exclusive; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::updateTuple() +/***************************************************************************** + * int writeTuple(); + *****************************************************************************/ +int +NdbOperation::writeTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = WriteRequest; + theErrorLine = tErrorLine++; + theLockMode = LM_Exclusive; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::writeTuple() +/****************************************************************************** + * int readTuple(); + *****************************************************************************/ +int +NdbOperation::readTuple(NdbOperation::LockMode lm) +{ + switch(lm) { + case LM_Read: + return readTuple(); + break; + case LM_Exclusive: + return readTupleExclusive(); + break; + case LM_CommittedRead: + return committedRead(); + break; + default: + return -1; + }; +} +/****************************************************************************** + * int readTuple(); + *****************************************************************************/ +int +NdbOperation::readTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = ReadRequest; + theErrorLine = tErrorLine++; + theLockMode = LM_Read; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::readTuple() + +/***************************************************************************** + * int deleteTuple(); + *****************************************************************************/ +int +NdbOperation::deleteTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = DeleteRequest; + theErrorLine = tErrorLine++; + theLockMode = LM_Exclusive; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::deleteTuple() + +/****************************************************************************** + * int readTupleExclusive(); + *****************************************************************************/ +int +NdbOperation::readTupleExclusive() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = ReadExclusive; + theErrorLine = tErrorLine++; + theLockMode = LM_Exclusive; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::readTupleExclusive() + +/***************************************************************************** + * int simpleRead(); + *****************************************************************************/ +int +NdbOperation::simpleRead() +{ + /** + * Currently/still disabled + */ + return readTuple(); +#if 0 + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + theOperationType = ReadRequest; + theSimpleIndicator = 1; + theErrorLine = tErrorLine++; + theLockMode = LM_Read; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +#endif +}//NdbOperation::simpleRead() + +/***************************************************************************** + * int dirtyRead(); + *****************************************************************************/ +int +NdbOperation::dirtyRead() +{ + return committedRead(); +}//NdbOperation::dirtyRead() + +/***************************************************************************** + * int committedRead(); + *****************************************************************************/ +int +NdbOperation::committedRead() +{ + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + theOperationType = ReadRequest; + theSimpleIndicator = 1; + theDirtyIndicator = 1; + theErrorLine = tErrorLine++; + theLockMode = LM_CommittedRead; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::committedRead() + +/***************************************************************************** + * int dirtyUpdate(); + ****************************************************************************/ +int +NdbOperation::dirtyUpdate() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + theOperationType = UpdateRequest; + tNdbCon->theSimpleState = 0; + theSimpleIndicator = 1; + theDirtyIndicator = 1; + theErrorLine = tErrorLine++; + theLockMode = LM_CommittedRead; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::dirtyUpdate() + +/****************************************************************************** + * int dirtyWrite(); + *****************************************************************************/ +int +NdbOperation::dirtyWrite() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + theOperationType = WriteRequest; + tNdbCon->theSimpleState = 0; + theSimpleIndicator = 1; + theDirtyIndicator = 1; + theErrorLine = tErrorLine++; + theLockMode = LM_CommittedRead; + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::dirtyWrite() + +/****************************************************************************** + * int interpretedUpdateTuple(); + ****************************************************************************/ +int +NdbOperation::interpretedUpdateTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = UpdateRequest; + theAI_LenInCurrAI = 25; + theLockMode = LM_Exclusive; + theErrorLine = tErrorLine++; + initInterpreter(); + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::interpretedUpdateTuple() + +/***************************************************************************** + * int interpretedDeleteTuple(); + *****************************************************************************/ +int +NdbOperation::interpretedDeleteTuple() +{ + NdbTransaction* tNdbCon = theNdbCon; + int tErrorLine = theErrorLine; + if (theStatus == Init) { + theStatus = OperationDefined; + tNdbCon->theSimpleState = 0; + theOperationType = DeleteRequest; + + theErrorLine = tErrorLine++; + theAI_LenInCurrAI = 25; + theLockMode = LM_Exclusive; + initInterpreter(); + return 0; + } else { + setErrorCode(4200); + return -1; + }//if +}//NdbOperation::interpretedDeleteTuple() + + + +/****************************************************************************** + * int getValue(AttrInfo* tAttrInfo, char* aRef ) + * + * Return Value Return 0 : GetValue was successful. + * Return -1: In all other case. + * Parameters: tAttrInfo : Attribute object of the retrieved attribute + * value. + * Remark: Define an attribute to retrieve in query. + *****************************************************************************/ +NdbRecAttr* +NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue) +{ + NdbRecAttr* tRecAttr; + if ((tAttrInfo != NULL) && + (theStatus != Init)){ + if (theStatus != GetValue) { + if (theInterpretIndicator == 1) { + if (theStatus == FinalGetValue) { + ; // Simply continue with getValue + } else if (theStatus == ExecInterpretedValue) { + if (insertATTRINFO(Interpreter::EXIT_OK) == -1) + return NULL; + theInterpretedSize = theTotalCurrAI_Len - + (theInitialReadSize + 5); + } else if (theStatus == SetValueInterpreted) { + theFinalUpdateSize = theTotalCurrAI_Len - + (theInitialReadSize + theInterpretedSize + 5); + } else { + setErrorCodeAbort(4230); + return NULL; + }//if + // MASV - How would execution come here? + theStatus = FinalGetValue; + } else { + setErrorCodeAbort(4230); + return NULL; + }//if + }//if + Uint32 ah; + AttributeHeader::init(&ah, tAttrInfo->m_attrId, 0); + if (insertATTRINFO(ah) != -1) { + // Insert Attribute Id into ATTRINFO part. + + /************************************************************************ + * Get a Receive Attribute object and link it into the operation object. + ***********************************************************************/ + if((tRecAttr = theReceiver.getValue(tAttrInfo, aValue)) != 0){ + theErrorLine++; + return tRecAttr; + } else { + setErrorCodeAbort(4000); + return NULL; + } + } else { + return NULL; + }//if insertATTRINFO failure + } else { + if (tAttrInfo == NULL) { + setErrorCodeAbort(4004); + return NULL; + }//if + }//if + setErrorCodeAbort(4200); + return NULL; +} + +/***************************************************************************** + * int setValue(AttrInfo* tAttrInfo, char* aValue, Uint32 len) + * + * Return Value: Return 0 : SetValue was succesful. + * Return -1: In all other case. + * Parameters: tAttrInfo : Attribute object where the attribute + * info exists. + * aValue : Reference to the variable with the new value. + * len : Length of the value + * Remark: Define a attribute to set in a query. +******************************************************************************/ +int +NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, + const char* aValuePassed, Uint32 len) +{ + DBUG_ENTER("NdbOperation::setValue"); + DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u", + tAttrInfo->m_name.c_str(), + theOperationType, + aValuePassed, len)); + if (aValuePassed != NULL) + DBUG_DUMP("value", (char*)aValuePassed, len); + + int tReturnCode; + Uint32 tAttrId; + Uint32 tData; + Uint32 tempData[2000]; + OperationType tOpType = theOperationType; + OperationStatus tStatus = theStatus; + + + if ((tOpType == UpdateRequest) || + (tOpType == WriteRequest)) { + if (theInterpretIndicator == 0) { + if (tStatus == SetValue) { + ; + } else { + setErrorCodeAbort(4234); + DBUG_RETURN(-1); + }//if + } else { + if (tStatus == GetValue) { + theInitialReadSize = theTotalCurrAI_Len - 5; + } else if (tStatus == ExecInterpretedValue) { + //-------------------------------------------------------------------- + // We insert an exit from interpretation since we are now starting + // to set values in the tuple by setValue. + //-------------------------------------------------------------------- + if (insertATTRINFO(Interpreter::EXIT_OK) == -1){ + DBUG_RETURN(-1); + } + theInterpretedSize = theTotalCurrAI_Len - + (theInitialReadSize + 5); + } else if (tStatus == SetValueInterpreted) { + ; // Simply continue adding new setValue + } else { + //-------------------------------------------------------------------- + // setValue used in the wrong context. Application coding error. + //------------------------------------------------------------------- + setErrorCodeAbort(4234); //Wrong error code + DBUG_RETURN(-1); + }//if + theStatus = SetValueInterpreted; + }//if + } else if (tOpType == InsertRequest) { + if ((theStatus != SetValue) && (theStatus != OperationDefined)) { + setErrorCodeAbort(4234); + DBUG_RETURN(-1); + }//if + } else if (tOpType == ReadRequest || tOpType == ReadExclusive) { + setErrorCodeAbort(4504); + DBUG_RETURN(-1); + } else if (tOpType == DeleteRequest) { + setErrorCodeAbort(4504); + DBUG_RETURN(-1); + } else if (tOpType == OpenScanRequest || tOpType == OpenRangeScanRequest) { + setErrorCodeAbort(4228); + DBUG_RETURN(-1); + } else { + //--------------------------------------------------------------------- + // setValue with undefined operation type. + // Probably application coding error. + //--------------------------------------------------------------------- + setErrorCodeAbort(4108); + DBUG_RETURN(-1); + }//if + if (tAttrInfo == NULL) { + setErrorCodeAbort(4004); + DBUG_RETURN(-1); + }//if + if (tAttrInfo->m_pk) { + if (theOperationType == InsertRequest) { + DBUG_RETURN(equal_impl(tAttrInfo, aValuePassed, len)); + } else { + setErrorCodeAbort(4202); + DBUG_RETURN(-1); + }//if + }//if + if (len > 8000) { + setErrorCodeAbort(4216); + DBUG_RETURN(-1); + }//if + + tAttrId = tAttrInfo->m_attrId; + const char *aValue = aValuePassed; + Uint32 ahValue; + if (aValue == NULL) { + if (tAttrInfo->m_nullable) { + AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, 0); + ah.setNULL(); + insertATTRINFO(ahValue); + // Insert Attribute Id with the value + // NULL into ATTRINFO part. + DBUG_RETURN(0); + } else { + /*********************************************************************** + * Setting a NULL value on a NOT NULL attribute is not allowed. + **********************************************************************/ + setErrorCodeAbort(4203); + DBUG_RETURN(-1); + }//if + }//if + + // Insert Attribute Id into ATTRINFO part. + const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize; + +#if 0 + tAttrSize = tAttrInfo->theAttrSize; + tArraySize = tAttrInfo->theArraySize; + if (tArraySize == 0) { + setErrorCodeAbort(4201); + return -1; + }//if + tAttrSizeInBits = tAttrSize*tArraySize; + tAttrSizeInWords = tAttrSizeInBits >> 5; +#endif + const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ; + if (len != sizeInBytes && (len != 0)) { + setErrorCodeAbort(4209); + DBUG_RETURN(-1); + }//if + const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word + const Uint32 sizeInWords = sizeInBytes / 4; // Excluding bits in last word + AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, + totalSizeInWords); + insertATTRINFO( ahValue ); + + /*********************************************************************** + * Check if the pointer of the value passed is aligned on a 4 byte boundary. + * If so only assign the pointer to the internal variable aValue. + * If it is not aligned then we start by copying the value to tempData and + * use this as aValue instead. + *************************************************************************/ + const int attributeSize = sizeInBytes; + const int slack = sizeInBytes & 3; + + if (((UintPtr)aValue & 3) != 0 || (slack != 0)){ + memcpy(&tempData[0], aValue, attributeSize); + aValue = (char*)&tempData[0]; + if(slack != 0) { + char * tmp = (char*)&tempData[0]; + memset(&tmp[attributeSize], 0, (4 - slack)); + }//if + }//if + + tReturnCode = insertATTRINFOloop((Uint32*)aValue, sizeInWords); + if (tReturnCode == -1) { + DBUG_RETURN(tReturnCode); + }//if + if (bitsInLastWord != 0) { + tData = *(Uint32*)(aValue + sizeInWords*4); + tData = convertEndian(tData); + tData = tData & ((1 << bitsInLastWord) - 1); + tData = convertEndian(tData); + tReturnCode = insertATTRINFO(tData); + if (tReturnCode == -1) { + DBUG_RETURN(tReturnCode); + }//if + }//if + theErrorLine++; + DBUG_RETURN(0); +}//NdbOperation::setValue() + +NdbBlob* +NdbOperation::getBlobHandle(NdbTransaction* aCon, const NdbColumnImpl* tAttrInfo) +{ + NdbBlob* tBlob = theBlobList; + NdbBlob* tLastBlob = NULL; + while (tBlob != NULL) { + if (tBlob->theColumn == tAttrInfo) + return tBlob; + tLastBlob = tBlob; + tBlob = tBlob->theNext; + } + tBlob = theNdb->getNdbBlob(); + if (tBlob == NULL) + return NULL; + if (tBlob->atPrepare(aCon, this, tAttrInfo) == -1) { + theNdb->releaseNdbBlob(tBlob); + return NULL; + } + if (tLastBlob == NULL) + theBlobList = tBlob; + else + tLastBlob->theNext = tBlob; + tBlob->theNext = NULL; + theNdbCon->theBlobFlag = true; + return tBlob; +} + +/**************************************************************************** + * int insertATTRINFO( Uint32 aData ); + * + * Return Value: Return 0 : insertATTRINFO was succesful. + * Return -1: In all other case. + * Parameters: aData: the data to insert into ATTRINFO. + * Remark: Puts the the data into either TCKEYREQ signal or + * ATTRINFO signal. + *****************************************************************************/ +int +NdbOperation::insertATTRINFO( Uint32 aData ) +{ + NdbApiSignal* tSignal; + register Uint32 tAI_LenInCurrAI = theAI_LenInCurrAI; + register Uint32* tAttrPtr = theATTRINFOptr; + register Uint32 tTotCurrAILen = theTotalCurrAI_Len; + + if (tAI_LenInCurrAI >= 25) { + Ndb* tNdb = theNdb; + NdbApiSignal* tFirstAttrinfo = theFirstATTRINFO; + tAI_LenInCurrAI = 3; + tSignal = tNdb->getSignal(); + if (tSignal != NULL) { + tSignal->setSignal(m_attrInfoGSN); + tAttrPtr = &tSignal->getDataPtrSend()[3]; + if (tFirstAttrinfo == NULL) { + tSignal->next(NULL); + theFirstATTRINFO = tSignal; + theCurrentATTRINFO = tSignal; + } else { + NdbApiSignal* tCurrentAttrinfoBeforeUpdate = theCurrentATTRINFO; + tSignal->next(NULL); + theCurrentATTRINFO = tSignal; + tCurrentAttrinfoBeforeUpdate->next(tSignal); + }//if + } else { + goto insertATTRINFO_error1; + }//if + }//if + *tAttrPtr = aData; + tAttrPtr++; + tTotCurrAILen++; + tAI_LenInCurrAI++; + theTotalCurrAI_Len = tTotCurrAILen; + theAI_LenInCurrAI = tAI_LenInCurrAI; + theATTRINFOptr = tAttrPtr; + return 0; + +insertATTRINFO_error1: + setErrorCodeAbort(4000); + return -1; + +}//NdbOperation::insertATTRINFO() + +/***************************************************************************** + * int insertATTRINFOloop(Uint32* aDataPtr, Uint32 aLength ); + * + * Return Value: Return 0 : insertATTRINFO was succesful. + * Return -1: In all other case. + * Parameters: aDataPtr: Pointer to the data to insert into ATTRINFO. + * aLength: Length of data to be copied + * Remark: Puts the the data into either TCKEYREQ signal or + * ATTRINFO signal. + *****************************************************************************/ +int +NdbOperation::insertATTRINFOloop(register const Uint32* aDataPtr, + register Uint32 aLength) +{ + NdbApiSignal* tSignal; + register Uint32 tAI_LenInCurrAI = theAI_LenInCurrAI; + register Uint32 tTotCurrAILen = theTotalCurrAI_Len; + register Uint32* tAttrPtr = theATTRINFOptr; + Ndb* tNdb = theNdb; + + while (aLength > 0) { + if (tAI_LenInCurrAI >= 25) { + NdbApiSignal* tFirstAttrinfo = theFirstATTRINFO; + tAI_LenInCurrAI = 3; + tSignal = tNdb->getSignal(); + if (tSignal != NULL) { + tSignal->setSignal(m_attrInfoGSN); + tAttrPtr = &tSignal->getDataPtrSend()[3]; + if (tFirstAttrinfo == NULL) { + tSignal->next(NULL); + theFirstATTRINFO = tSignal; + theCurrentATTRINFO = tSignal; + } else { + NdbApiSignal* tCurrentAttrinfoBeforeUpdate = theCurrentATTRINFO; + tSignal->next(NULL); + theCurrentATTRINFO = tSignal; + tCurrentAttrinfoBeforeUpdate->next(tSignal); + }//if + } else { + goto insertATTRINFO_error1; + }//if + }//if + { + register Uint32 tData = *aDataPtr; + aDataPtr++; + aLength--; + tAI_LenInCurrAI++; + *tAttrPtr = tData; + tAttrPtr++; + tTotCurrAILen++; + } + }//while + theATTRINFOptr = tAttrPtr; + theTotalCurrAI_Len = tTotCurrAILen; + theAI_LenInCurrAI = tAI_LenInCurrAI; + return 0; + +insertATTRINFO_error1: + setErrorCodeAbort(4000); + return -1; + +}//NdbOperation::insertATTRINFOloop() + + + + |