MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbOperation.cpp
1 /*
2  Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include "API.hpp"
19 #include <signaldata/TcKeyReq.hpp>
20 
21 
22 /******************************************************************************
23  * NdbOperation(Ndb* aNdb, Table* aTable);
24  *
25  * Return Value: None
26  * Parameters: aNdb: Pointers to the Ndb object.
27  * aTable: Pointers to the Table object
28  * Remark: Creat an object of NdbOperation.
29  ****************************************************************************/
30 NdbOperation::NdbOperation(Ndb* aNdb, NdbOperation::Type aType) :
31  m_type(aType),
32  theReceiver(aNdb),
33  theErrorLine(0),
34  theNdb(aNdb),
35  //theTable(aTable),
36  theNdbCon(NULL),
37  theNext(NULL),
38  theTCREQ(NULL),
39  theFirstATTRINFO(NULL),
40  theCurrentATTRINFO(NULL),
41  theTotalCurrAI_Len(0),
42  theAI_LenInCurrAI(0),
43  theLastKEYINFO(NULL),
44 
45  theFirstLabel(NULL),
46  theLastLabel(NULL),
47  theFirstBranch(NULL),
48  theLastBranch(NULL),
49  theFirstCall(NULL),
50  theLastCall(NULL),
51  theFirstSubroutine(NULL),
52  theLastSubroutine(NULL),
53  theNoOfLabels(0),
54  theNoOfSubroutines(0),
55 
56  m_currentTable(NULL), //theTableId(0xFFFF),
57  m_accessTable(NULL), //theAccessTableId(0xFFFF),
58  //theSchemaVersion(0),
59  theTotalNrOfKeyWordInSignal(8),
60  theTupKeyLen(0),
61  theNoOfTupKeyLeft(0),
62  theOperationType(NotDefined),
63  theStatus(Init),
64  theMagicNumber(0xFE11D0),
65  theScanInfo(0),
66  m_tcReqGSN(GSN_TCKEYREQ),
67  m_keyInfoGSN(GSN_KEYINFO),
68  m_attrInfoGSN(GSN_ATTRINFO),
69  theBlobList(NULL),
70  m_abortOption(-1),
71  m_noErrorPropagation(false),
72  theLockHandle(NULL),
73  m_blob_lock_upgraded(false)
74 {
75  theReceiver.init(NdbReceiver::NDB_OPERATION, false, this);
76  theError.code = 0;
77  m_customData = NULL;
78 }
79 /*****************************************************************************
80  * ~NdbOperation();
81  *
82  * Remark: Delete tables for connection pointers (id).
83  *****************************************************************************/
84 NdbOperation::~NdbOperation( )
85 {
86 }
87 /******************************************************************************
88  *void setErrorCode(int anErrorCode);
89  *
90  * Remark: Set an Error Code on operation and
91  * on connection set an error status.
92  *****************************************************************************/
93 void
94 NdbOperation::setErrorCode(int anErrorCode) const
95 {
96  /* Setting an error is considered to be a const
97  operation, hence the nasty cast here */
98  NdbOperation *pnonConstThis=const_cast<NdbOperation *>(this);
99 
100  pnonConstThis->theError.code = anErrorCode;
101  theNdbCon->theErrorLine = theErrorLine;
102  theNdbCon->theErrorOperation = pnonConstThis;
103  if (!(m_abortOption == AO_IgnoreError && m_noErrorPropagation))
104  theNdbCon->setOperationErrorCode(anErrorCode);
105 }
106 
107 /******************************************************************************
108  * void setErrorCodeAbort(int anErrorCode);
109  *
110  * Remark: Set an Error Code on operation and on connection set
111  * an error status.
112  *****************************************************************************/
113 void
114 NdbOperation::setErrorCodeAbort(int anErrorCode) const
115 {
116  /* Setting an error is considered to be a const
117  operation, hence the nasty cast here */
118  NdbOperation *pnonConstThis=const_cast<NdbOperation *>(this);
119 
120  pnonConstThis->theError.code = anErrorCode;
121  theNdbCon->theErrorLine = theErrorLine;
122  theNdbCon->theErrorOperation = pnonConstThis;
123  // ignore m_noErrorPropagation
124  theNdbCon->setOperationErrorCodeAbort(anErrorCode);
125 }
126 
127 /*****************************************************************************
128  * int init();
129  *
130  * Return Value: Return 0 : init was successful.
131  * Return -1: In all other case.
132  * Remark: Initiates operation record after allocation.
133  *****************************************************************************/
134 
135 int
136 NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection,
137  bool useRec){
138  NdbApiSignal* tSignal;
139  theStatus = Init;
140  theError.code = 0;
141  theErrorLine = 1;
142  m_currentTable = m_accessTable = tab;
143 
144  theNdbCon = myConnection;
145  for (Uint32 i=0; i<NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; i++)
146  for (int j=0; j<3; j++)
147  theTupleKeyDefined[i][j] = 0;
148 
149  theFirstATTRINFO = NULL;
150  theCurrentATTRINFO = NULL;
151  theLastKEYINFO = NULL;
152 
153 
154  theTupKeyLen = 0;
155  theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();
156 
157  theTotalCurrAI_Len = 0;
158  theAI_LenInCurrAI = 0;
159  theStartIndicator = 0;
160  theCommitIndicator = 0;
161  theSimpleIndicator = 0;
162  theDirtyIndicator = 0;
163  theInterpretIndicator = 0;
164  theDistrKeyIndicator_ = 0;
165  theScanInfo = 0;
166  theTotalNrOfKeyWordInSignal = 8;
167  theMagicNumber = 0xABCDEF01;
168  m_attribute_record= NULL;
169  theBlobList = NULL;
170  m_abortOption = -1;
171  m_noErrorPropagation = false;
172  m_flags = 0;
173  m_flags |= OF_NO_DISK;
174  m_interpreted_code = NULL;
175  m_extraSetValues = NULL;
176  m_numExtraSetValues = 0;
177 
178  tSignal = theNdb->getSignal();
179  if (tSignal == NULL)
180  {
181  setErrorCode(4000);
182  return -1;
183  }
184  theTCREQ = tSignal;
185  theTCREQ->setSignal(m_tcReqGSN, refToBlock(theNdbCon->m_tcRef));
186 
187  theAI_LenInCurrAI = 20;
188  TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
189  tcKeyReq->scanInfo = 0;
190  theKEYINFOptr = &tcKeyReq->keyInfo[0];
191  theATTRINFOptr = &tcKeyReq->attrInfo[0];
192  if (theReceiver.init(NdbReceiver::NDB_OPERATION, useRec, this))
193  {
194  // theReceiver sets the error code of its owner
195  return -1;
196  }
197  m_customData = NULL;
198 
199  if (theNdb->theImpl->get_ndbapi_config_parameters().m_default_queue_option)
200  m_flags |= OF_QUEUEABLE;
201 
202  return 0;
203 }
204 
205 
206 /******************************************************************************
207  * void release();
208  *
209  * Remark: Release all objects connected to the operation object.
210  *****************************************************************************/
211 void
212 NdbOperation::release()
213 {
214  NdbBlob* tBlob;
215  NdbBlob* tSaveBlob;
216 
217  /* In case we didn't execute... */
218  postExecuteRelease();
219 
220  tBlob = theBlobList;
221  while (tBlob != NULL)
222  {
223  tSaveBlob = tBlob;
224  tBlob = tBlob->theNext;
225  theNdb->releaseNdbBlob(tSaveBlob);
226  }
227  theBlobList = NULL;
228  theReceiver.release();
229 
230  theLockHandle = NULL;
231  m_blob_lock_upgraded = false;
232 }
233 
234 void
235 NdbOperation::postExecuteRelease()
236 {
237  NdbApiSignal* tSignal;
238  NdbApiSignal* tSaveSignal;
239  NdbBranch* tBranch;
240  NdbBranch* tSaveBranch;
241  NdbLabel* tLabel;
242  NdbLabel* tSaveLabel;
243  NdbCall* tCall;
244  NdbCall* tSaveCall;
245  NdbSubroutine* tSubroutine;
246  NdbSubroutine* tSaveSubroutine;
247 
248  tSignal = theRequest; /* TCKEYREQ/TCINDXREQ/SCANTABREQ */
249  while (tSignal != NULL)
250  {
251  tSaveSignal = tSignal;
252  tSignal = tSignal->next();
253  theNdb->releaseSignal(tSaveSignal);
254  }
255  theRequest = NULL;
256  theLastKEYINFO = NULL;
257 #ifdef TODO
258 
261  if (theFirstATTRINFO)
262  {
263  theNdb->releaseSignals(1, theFirstATTRINFO, theCurrentATTRINFO);
264  }
265 #else
266  tSignal = theFirstATTRINFO;
267  while (tSignal != NULL)
268  {
269  tSaveSignal = tSignal;
270  tSignal = tSignal->next();
271  theNdb->releaseSignal(tSaveSignal);
272  }
273 #endif
274  theFirstATTRINFO = NULL;
275  theCurrentATTRINFO = NULL;
276 
277  if (theInterpretIndicator == 1)
278  {
279  tBranch = theFirstBranch;
280  while (tBranch != NULL)
281  {
282  tSaveBranch = tBranch;
283  tBranch = tBranch->theNext;
284  theNdb->releaseNdbBranch(tSaveBranch);
285  }
286  tLabel = theFirstLabel;
287  while (tLabel != NULL)
288  {
289  tSaveLabel = tLabel;
290  tLabel = tLabel->theNext;
291  theNdb->releaseNdbLabel(tSaveLabel);
292  }
293  tCall = theFirstCall;
294  while (tCall != NULL)
295  {
296  tSaveCall = tCall;
297  tCall = tCall->theNext;
298  theNdb->releaseNdbCall(tSaveCall);
299  }
300  tSubroutine = theFirstSubroutine;
301  while (tSubroutine != NULL)
302  {
303  tSaveSubroutine = tSubroutine;
304  tSubroutine = tSubroutine->theNext;
305  theNdb->releaseNdbSubroutine(tSaveSubroutine);
306  }
307  }
308 }
309 
310 NdbRecAttr*
311 NdbOperation::getValue(const char* anAttrName, char* aValue)
312 {
313  return getValue_impl(m_currentTable->getColumn(anAttrName), aValue);
314 }
315 
316 NdbRecAttr*
317 NdbOperation::getValue(Uint32 anAttrId, char* aValue)
318 {
319  return getValue_impl(m_currentTable->getColumn(anAttrId), aValue);
320 }
321 
322 NdbRecAttr*
323 NdbOperation::getValue(const NdbDictionary::Column* col, char* aValue)
324 {
325  if (theStatus != UseNdbRecord)
326  return getValue_impl(&NdbColumnImpl::getImpl(*col), aValue);
327 
328  setErrorCodeAbort(4508);
329  /* GetValue not allowed for NdbRecord defined operation */
330  return NULL;
331 }
332 
333 int
334 NdbOperation::equal(const char* anAttrName, const char* aValuePassed)
335 {
336  const NdbColumnImpl* col = m_accessTable->getColumn(anAttrName);
337  if (col == NULL)
338  {
339  setErrorCode(4004);
340  return -1;
341  }
342  else
343  {
344  return equal_impl(col, aValuePassed);
345  }
346 }
347 
348 int
349 NdbOperation::equal(Uint32 anAttrId, const char* aValuePassed)
350 {
351  const NdbColumnImpl* col = m_accessTable->getColumn(anAttrId);
352  if (col == NULL)
353  {
354  setErrorCode(4004);
355  return -1;
356  }
357  else
358  {
359  return equal_impl(col, aValuePassed);
360  }
361 }
362 
363 int
364 NdbOperation::setValue(const char* anAttrName, const char* aValuePassed)
365 {
366  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrName);
367  if (col == NULL)
368  {
369  setErrorCode(4004);
370  return -1;
371  }
372  else
373  {
374  return setValue(col, aValuePassed);
375  }
376 }
377 
378 
379 int
380 NdbOperation::setValue(Uint32 anAttrId, const char* aValuePassed)
381 {
382  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrId);
383  if (col == NULL)
384  {
385  setErrorCode(4004);
386  return -1;
387  }
388  else
389  {
390  return setValue(col, aValuePassed);
391  }
392 }
393 
394 NdbBlob*
395 NdbOperation::getBlobHandle(const char* anAttrName)
396 {
397  // semantics differs from overloaded 'getBlobHandle(const char*) const'
398  // by delegating to the non-const variant of internal getBlobHandle(...),
399  // which may create a new BlobHandle
400  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrName);
401  if (col == NULL)
402  {
403  setErrorCode(4004);
404  return NULL;
405  }
406  else
407  {
408  return getBlobHandle(theNdbCon, col);
409  }
410 }
411 
412 NdbBlob*
413 NdbOperation::getBlobHandle(Uint32 anAttrId)
414 {
415  // semantics differs from overloaded 'getBlobHandle(Uint32) const'
416  // by delegating to the non-const variant of internal getBlobHandle(...),
417  // which may create a new BlobHandle
418  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrId);
419  if (col == NULL)
420  {
421  setErrorCode(4004);
422  return NULL;
423  }
424  else
425  {
426  return getBlobHandle(theNdbCon, col);
427  }
428 }
429 
430 NdbBlob*
431 NdbOperation::getBlobHandle(const char* anAttrName) const
432 {
433  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrName);
434  if (col == NULL)
435  {
436  setErrorCode(4004);
437  return NULL;
438  }
439  else
440  {
441  return getBlobHandle(theNdbCon, col);
442  }
443 }
444 
445 NdbBlob*
446 NdbOperation::getBlobHandle(Uint32 anAttrId) const
447 {
448  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrId);
449  if (col == NULL)
450  {
451  setErrorCode(4004);
452  return NULL;
453  }
454  else
455  {
456  return getBlobHandle(theNdbCon, col);
457  }
458 }
459 
460 
461 int
462 NdbOperation::incValue(const char* anAttrName, Uint32 aValue)
463 {
464  return incValue(m_currentTable->getColumn(anAttrName), aValue);
465 }
466 
467 int
468 NdbOperation::incValue(const char* anAttrName, Uint64 aValue)
469 {
470  return incValue(m_currentTable->getColumn(anAttrName), aValue);
471 }
472 
473 int
474 NdbOperation::incValue(Uint32 anAttrId, Uint32 aValue)
475 {
476  return incValue(m_currentTable->getColumn(anAttrId), aValue);
477 }
478 
479 int
480 NdbOperation::incValue(Uint32 anAttrId, Uint64 aValue)
481 {
482  return incValue(m_currentTable->getColumn(anAttrId), aValue);
483 }
484 
485 int
486 NdbOperation::subValue( const char* anAttrName, Uint32 aValue)
487 {
488  return subValue(m_currentTable->getColumn(anAttrName), aValue);
489 }
490 
491 int
492 NdbOperation::subValue( const char* anAttrName, Uint64 aValue)
493 {
494  return subValue(m_currentTable->getColumn(anAttrName), aValue);
495 }
496 
497 int
498 NdbOperation::subValue(Uint32 anAttrId, Uint32 aValue)
499 {
500  return subValue(m_currentTable->getColumn(anAttrId), aValue);
501 }
502 
503 int
504 NdbOperation::subValue(Uint32 anAttrId, Uint64 aValue)
505 {
506  return subValue(m_currentTable->getColumn(anAttrId), aValue);
507 }
508 
509 int
510 NdbOperation::read_attr(const char* anAttrName, Uint32 RegDest)
511 {
512  return read_attr(m_currentTable->getColumn(anAttrName), RegDest);
513 }
514 
515 int
516 NdbOperation::read_attr(Uint32 anAttrId, Uint32 RegDest)
517 {
518  return read_attr(m_currentTable->getColumn(anAttrId), RegDest);
519 }
520 
521 int
522 NdbOperation::write_attr(const char* anAttrName, Uint32 RegDest)
523 {
524  return write_attr(m_currentTable->getColumn(anAttrName), RegDest);
525 }
526 
527 int
528 NdbOperation::write_attr(Uint32 anAttrId, Uint32 RegDest)
529 {
530  return write_attr(m_currentTable->getColumn(anAttrId), RegDest);
531 }
532 
533 const char*
535 {
536  return m_currentTable->m_externalName.c_str();
537 }
538 
541 {
542  return m_currentTable;
543 }
544 
547 {
548  return theNdbCon;
549 }
550 
551 int
552 NdbOperation::getLockHandleImpl()
553 {
554  assert(! theLockHandle);
555 
556  if (unlikely(theNdb->getMinDbNodeVersion() <
557  NDBD_UNLOCK_OP_SUPPORTED))
558  {
559  /* Function not implemented yet */
560  return 4003;
561  }
562 
563  if (likely(((theOperationType == ReadRequest) ||
564  (theOperationType == ReadExclusive)) &&
565  (m_type == PrimaryKeyAccess) &&
566  ((theLockMode == LM_Read) |
567  (theLockMode == LM_Exclusive))))
568  {
569  theLockHandle = theNdbCon->getLockHandle();
570  if (!theLockHandle)
571  {
572  return 4000;
573  }
574 
575  /* Now operation has a LockHandle - it'll be
576  * filled-in when the operation is prepared prior
577  * to execution.
578  */
579  assert(theLockHandle->m_state == NdbLockHandle::ALLOCATED);
580  assert(! theLockHandle->isLockRefValid());
581 
582  return 0;
583  }
584  else
585  {
586  /* getLockHandle only supported for primary key read with a lock */
587  return 4549;
588  }
589 }
590 
591 const NdbLockHandle*
592 NdbOperation::getLockHandle()
593 {
594  if (likely (! m_blob_lock_upgraded))
595  {
596  if (theLockHandle == NULL)
597  {
598  int rc = getLockHandleImpl();
599 
600  if (likely(rc == 0))
601  return theLockHandle;
602  else
603  {
604  setErrorCode(rc);
605  return NULL;
606  }
607  }
608  /* Return existing LockHandle */
609  return theLockHandle;
610  }
611  else
612  {
613  /* Not allowed to call getLockHandle() on a Blob-upgraded
614  * read
615  */
616  setErrorCode(4549);
617  return NULL;
618  }
619 }
620 
621 const NdbLockHandle*
622 NdbOperation::getLockHandle() const
623 {
624  /* NdbRecord / handle already exists variant */
625  return theLockHandle;
626 }