summaryrefslogtreecommitdiff
path: root/storage/ndb/src/ndbapi/NdbIndexOperation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/src/ndbapi/NdbIndexOperation.cpp')
-rw-r--r--storage/ndb/src/ndbapi/NdbIndexOperation.cpp412
1 files changed, 412 insertions, 0 deletions
diff --git a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp
new file mode 100644
index 00000000000..4cedffed4a2
--- /dev/null
+++ b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -0,0 +1,412 @@
+/* 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 <NdbIndexOperation.hpp>
+#include <Ndb.hpp>
+#include <NdbTransaction.hpp>
+#include "NdbApiSignal.hpp"
+#include <AttributeHeader.hpp>
+#include <signaldata/TcIndx.hpp>
+#include <signaldata/TcKeyReq.hpp>
+#include <signaldata/IndxKeyInfo.hpp>
+#include <signaldata/IndxAttrInfo.hpp>
+
+NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
+ NdbOperation(aNdb),
+ m_theIndex(NULL)
+{
+ m_tcReqGSN = GSN_TCINDXREQ;
+ m_attrInfoGSN = GSN_INDXATTRINFO;
+ m_keyInfoGSN = GSN_INDXKEYINFO;
+
+ /**
+ * Change receiver type
+ */
+ theReceiver.init(NdbReceiver::NDB_INDEX_OPERATION, this);
+}
+
+NdbIndexOperation::~NdbIndexOperation()
+{
+}
+
+/*****************************************************************************
+ * int indxInit();
+ *
+ * Return Value: Return 0 : init was successful.
+ * Return -1: In all other case.
+ * Remark: Initiates operation record after allocation.
+ *****************************************************************************/
+int
+NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
+ const NdbTableImpl * aTable,
+ NdbTransaction* myConnection)
+{
+ NdbOperation::init(aTable, myConnection);
+
+ switch (anIndex->m_type) {
+ case(NdbDictionary::Index::UniqueHashIndex):
+ break;
+ case(NdbDictionary::Index::Undefined):
+ case(NdbDictionary::Index::OrderedIndex):
+ setErrorCodeAbort(4003);
+ return -1;
+ }
+ m_theIndex = anIndex;
+ m_accessTable = anIndex->m_table;
+ theNoOfTupKeyLeft = m_accessTable->getNoOfPrimaryKeys();
+ return 0;
+}
+
+int NdbIndexOperation::readTuple(NdbOperation::LockMode lm)
+{
+ switch(lm) {
+ case LM_Read:
+ return readTuple();
+ break;
+ case LM_Exclusive:
+ return readTupleExclusive();
+ break;
+ case LM_CommittedRead:
+ return readTuple();
+ break;
+ default:
+ return -1;
+ };
+}
+
+int NdbIndexOperation::insertTuple()
+{
+ setErrorCode(4200);
+ return -1;
+}
+
+int NdbIndexOperation::readTuple()
+{
+ // First check that index is unique
+
+ return NdbOperation::readTuple();
+}
+
+int NdbIndexOperation::readTupleExclusive()
+{
+ // First check that index is unique
+
+ return NdbOperation::readTupleExclusive();
+}
+
+int NdbIndexOperation::simpleRead()
+{
+ // First check that index is unique
+
+ return NdbOperation::readTuple();
+}
+
+int NdbIndexOperation::dirtyRead()
+{
+ // First check that index is unique
+
+ return NdbOperation::readTuple();
+}
+
+int NdbIndexOperation::committedRead()
+{
+ // First check that index is unique
+
+ return NdbOperation::readTuple();
+}
+
+int NdbIndexOperation::updateTuple()
+{
+ // First check that index is unique
+
+ return NdbOperation::updateTuple();
+}
+
+int NdbIndexOperation::deleteTuple()
+{
+ // First check that index is unique
+
+ return NdbOperation::deleteTuple();
+}
+
+int NdbIndexOperation::dirtyUpdate()
+{
+ // First check that index is unique
+
+ return NdbOperation::dirtyUpdate();
+}
+
+int NdbIndexOperation::interpretedUpdateTuple()
+{
+ // First check that index is unique
+
+ return NdbOperation::interpretedUpdateTuple();
+}
+
+int NdbIndexOperation::interpretedDeleteTuple()
+{
+ // First check that index is unique
+
+ return NdbOperation::interpretedDeleteTuple();
+}
+
+int
+NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
+{
+ Uint32 tTransId1, tTransId2;
+ Uint32 tReqInfo;
+ Uint32 tSignalCount = 0;
+ Uint32 tInterpretInd = theInterpretIndicator;
+
+ theErrorLine = 0;
+
+ if (tInterpretInd != 1) {
+ OperationType tOpType = theOperationType;
+ OperationStatus tStatus = theStatus;
+ if ((tOpType == UpdateRequest) ||
+ (tOpType == InsertRequest) ||
+ (tOpType == WriteRequest)) {
+ if (tStatus != SetValue) {
+ setErrorCodeAbort(4506);
+ return -1;
+ }//if
+ } else if ((tOpType == ReadRequest) || (tOpType == ReadExclusive) ||
+ (tOpType == DeleteRequest)) {
+ if (tStatus != GetValue) {
+ setErrorCodeAbort(4506);
+ return -1;
+ }//if
+ } else {
+ setErrorCodeAbort(4507);
+ return -1;
+ }//if
+ } else {
+ if (prepareSendInterpreted() == -1) {
+ return -1;
+ }//if
+ }//if
+
+//-------------------------------------------------------------
+// We start by filling in the first 8 unconditional words of the
+// TCINDXREQ signal.
+//-------------------------------------------------------------
+ TcKeyReq * tcKeyReq =
+ CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
+
+ Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
+ Uint32 tIndexId = m_theIndex->m_indexId;
+ Uint32 tSchemaVersion = m_theIndex->m_version;
+
+ tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
+ tcKeyReq->senderData = ptr2int();
+ tcKeyReq->attrLen = tTotalCurrAI_Len;
+ tcKeyReq->tableId = tIndexId;
+ tcKeyReq->tableSchemaVersion = tSchemaVersion;
+
+ tTransId1 = (Uint32) aTransactionId;
+ tTransId2 = (Uint32) (aTransactionId >> 32);
+
+//-------------------------------------------------------------
+// Simple is simple if simple or both start and commit is set.
+//-------------------------------------------------------------
+// Temporarily disable simple stuff
+ Uint8 tSimpleIndicator = 0;
+// Uint8 tSimpleIndicator = theSimpleIndicator;
+ Uint8 tCommitIndicator = theCommitIndicator;
+ Uint8 tStartIndicator = theStartIndicator;
+// if ((theNdbCon->theLastOpInList == this) && (theCommitIndicator == 0))
+// abort();
+// Temporarily disable simple stuff
+ Uint8 tSimpleAlt = 0;
+// Uint8 tSimpleAlt = tStartIndicator & tCommitIndicator;
+ tSimpleIndicator = tSimpleIndicator | tSimpleAlt;
+
+//-------------------------------------------------------------
+// Simple state is set if start and commit is set and it is
+// a read request. Otherwise it is set to zero.
+//-------------------------------------------------------------
+ Uint8 tReadInd = (theOperationType == ReadRequest);
+ Uint8 tSimpleState = tReadInd & tSimpleAlt;
+ //theNdbCon->theSimpleState = tSimpleState;
+
+ tcKeyReq->transId1 = tTransId1;
+ tcKeyReq->transId2 = tTransId2;
+
+ tReqInfo = 0;
+
+ if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
+ } else {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
+ }//if
+
+ tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
+ tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
+ tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
+ const Uint8 tInterpretIndicator = theInterpretIndicator;
+ tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+
+ Uint8 tDirtyIndicator = theDirtyIndicator;
+ OperationType tOperationType = theOperationType;
+ Uint32 tIndexLen = theTupKeyLen;
+ Uint8 abortOption = theNdbCon->m_abortOption;
+
+ tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
+ tcKeyReq->setOperationType(tReqInfo, tOperationType);
+ tcKeyReq->setKeyLength(tReqInfo, tIndexLen);
+ tcKeyReq->setAbortOption(tReqInfo, abortOption);
+
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
+ Uint8 tScanIndicator = theScanInfo & 1;
+
+ tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
+ tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
+
+ tcKeyReq->requestInfo = tReqInfo;
+
+//-------------------------------------------------------------
+// The next step is to fill in the upto three conditional words.
+//-------------------------------------------------------------
+ Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
+ Uint32 tDistrGHIndex = tScanIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
+
+ Uint32 tScanInfo = theScanInfo;
+ Uint32 tDistrKey = theDistributionKey;
+
+ tOptionalDataPtr[0] = tScanInfo;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
+
+//-------------------------------------------------------------
+// The next is step is to compress the key data part of the
+// TCKEYREQ signal.
+//-------------------------------------------------------------
+ Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
+ Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
+ Uint32 Tdata1 = tcKeyReq->keyInfo[0];
+ Uint32 Tdata2 = tcKeyReq->keyInfo[1];
+ Uint32 Tdata3 = tcKeyReq->keyInfo[2];
+ Uint32 Tdata4 = tcKeyReq->keyInfo[3];
+ Uint32 Tdata5;
+
+ tKeyDataPtr[0] = Tdata1;
+ tKeyDataPtr[1] = Tdata2;
+ tKeyDataPtr[2] = Tdata3;
+ tKeyDataPtr[3] = Tdata4;
+ if (tIndexLen > 4) {
+ Tdata1 = tcKeyReq->keyInfo[4];
+ Tdata2 = tcKeyReq->keyInfo[5];
+ Tdata3 = tcKeyReq->keyInfo[6];
+ Tdata4 = tcKeyReq->keyInfo[7];
+
+ tKeyDataPtr[4] = Tdata1;
+ tKeyDataPtr[5] = Tdata2;
+ tKeyDataPtr[6] = Tdata3;
+ tKeyDataPtr[7] = Tdata4;
+ }//if
+//-------------------------------------------------------------
+// Finally we also compress the INDXATTRINFO part of the signal.
+// We optimise by using the if-statement for sending INDXKEYINFO
+// signals to calculating the new Attrinfo Index.
+//-------------------------------------------------------------
+ Uint32 tAttrInfoIndex;
+
+ if (tIndexLen > TcKeyReq::MaxKeyInfo) {
+ /**
+ * Set transid and TC connect ptr in the INDXKEYINFO signals
+ */
+ NdbApiSignal* tSignal = theTCREQ->next();
+ Uint32 remainingKey = tIndexLen - TcKeyReq::MaxKeyInfo;
+
+ do {
+ Uint32* tSigDataPtr = tSignal->getDataPtrSend();
+ NdbApiSignal* tnextSignal = tSignal->next();
+ tSignalCount++;
+ tSigDataPtr[0] = aTC_ConnectPtr;
+ tSigDataPtr[1] = tTransId1;
+ tSigDataPtr[2] = tTransId2;
+ if (remainingKey > IndxKeyInfo::DataLength) {
+ // The signal is full
+ tSignal->setLength(IndxKeyInfo::MaxSignalLength);
+ remainingKey -= IndxKeyInfo::DataLength;
+ }
+ else {
+ // Last signal
+ tSignal->setLength(IndxKeyInfo::HeaderLength + remainingKey);
+ remainingKey = 0;
+ }
+ tSignal = tnextSignal;
+ } while (tSignal != NULL);
+ tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
+ } else {
+ tAttrInfoIndex = tKeyIndex + tIndexLen;
+ }//if
+
+//-------------------------------------------------------------
+// Perform the Attrinfo packing in the TCKEYREQ signal started
+// above.
+//-------------------------------------------------------------
+ Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
+ Tdata1 = tcKeyReq->attrInfo[0];
+ Tdata2 = tcKeyReq->attrInfo[1];
+ Tdata3 = tcKeyReq->attrInfo[2];
+ Tdata4 = tcKeyReq->attrInfo[3];
+ Tdata5 = tcKeyReq->attrInfo[4];
+
+ theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
+ tAttrInfoIndex + TcKeyReq::StaticLength);
+ tAIDataPtr[0] = Tdata1;
+ tAIDataPtr[1] = Tdata2;
+ tAIDataPtr[2] = Tdata3;
+ tAIDataPtr[3] = Tdata4;
+ tAIDataPtr[4] = Tdata5;
+
+/***************************************************
+* Send the INDXATTRINFO signals.
+***************************************************/
+ if (tTotalCurrAI_Len > 5) {
+ // Set the last signal's length.
+ NdbApiSignal* tSignal = theFirstATTRINFO;
+ theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
+ do {
+ Uint32* tSigDataPtr = tSignal->getDataPtrSend();
+ NdbApiSignal* tnextSignal = tSignal->next();
+ tSignalCount++;
+ tSigDataPtr[0] = aTC_ConnectPtr;
+ tSigDataPtr[1] = tTransId1;
+ tSigDataPtr[2] = tTransId2;
+ tSignal = tnextSignal;
+ } while (tSignal != NULL);
+ }//if
+ theStatus = WaitResponse;
+ theReceiver.prepareSend();
+ return 0;
+}
+
+/***************************************************************************
+int receiveTCINDXREF( NdbApiSignal* aSignal)
+
+Return Value: Return 0 : send was succesful.
+ Return -1: In all other case.
+Parameters: aSignal: the signal object that contains the TCINDXREF signal from TC.
+Remark: Handles the reception of the TCKEYREF signal.
+***************************************************************************/
+int
+NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal)
+{
+ return receiveTCKEYREF(aSignal);
+}//NdbIndexOperation::receiveTCINDXREF()