1 /* Copyright (c) 2003-2008 MySQL AB
2 Use is subject to license terms
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #include <ndb_global.h>
18 #include <NdbOperation.hpp>
19 #include "NdbApiSignal.hpp"
20 #include <NdbTransaction.hpp>
21 #include <Ndb.hpp>
22 #include <NdbRecAttr.hpp>
23 #include "NdbUtil.hpp"
24 #include "NdbOut.hpp"
25 #include "NdbImpl.hpp"
26 #include <NdbIndexScanOperation.hpp>
27 #include <NdbBlob.hpp>
28
29 #include <Interpreter.hpp>
30
31 #include <AttributeHeader.hpp>
32 #include <signaldata/TcKeyReq.hpp>
33
34 /*****************************************************************************
35 * int insertTuple();
36 *****************************************************************************/
37 int
insertTuple()38 NdbOperation::insertTuple()
39 {
40 NdbTransaction* tNdbCon = theNdbCon;
41 int tErrorLine = theErrorLine;
42 if (theStatus == Init) {
43 theStatus = OperationDefined;
44 theOperationType = InsertRequest;
45 tNdbCon->theSimpleState = 0;
46 theErrorLine = tErrorLine++;
47 theLockMode = LM_Exclusive;
48 m_abortOption = AbortOnError;
49 return 0;
50 } else {
51 setErrorCode(4200);
52 return -1;
53 }//if
54 }//NdbOperation::insertTuple()
55 /******************************************************************************
56 * int updateTuple();
57 *****************************************************************************/
58 int
updateTuple()59 NdbOperation::updateTuple()
60 {
61 NdbTransaction* tNdbCon = theNdbCon;
62 int tErrorLine = theErrorLine;
63 if (theStatus == Init) {
64 theStatus = OperationDefined;
65 tNdbCon->theSimpleState = 0;
66 theOperationType = UpdateRequest;
67 theErrorLine = tErrorLine++;
68 theLockMode = LM_Exclusive;
69 m_abortOption = AbortOnError;
70 return 0;
71 } else {
72 setErrorCode(4200);
73 return -1;
74 }//if
75 }//NdbOperation::updateTuple()
76 /*****************************************************************************
77 * int writeTuple();
78 *****************************************************************************/
79 int
writeTuple()80 NdbOperation::writeTuple()
81 {
82 NdbTransaction* tNdbCon = theNdbCon;
83 int tErrorLine = theErrorLine;
84 if (theStatus == Init) {
85 theStatus = OperationDefined;
86 tNdbCon->theSimpleState = 0;
87 theOperationType = WriteRequest;
88 theErrorLine = tErrorLine++;
89 theLockMode = LM_Exclusive;
90 m_abortOption = AbortOnError;
91 return 0;
92 } else {
93 setErrorCode(4200);
94 return -1;
95 }//if
96 }//NdbOperation::writeTuple()
97 /*****************************************************************************
98 * int deleteTuple();
99 *****************************************************************************/
100 int
deleteTuple()101 NdbOperation::deleteTuple()
102 {
103 NdbTransaction* tNdbCon = theNdbCon;
104 int tErrorLine = theErrorLine;
105 if (theStatus == Init) {
106 theStatus = OperationDefined;
107 tNdbCon->theSimpleState = 0;
108 theOperationType = DeleteRequest;
109 theErrorLine = tErrorLine++;
110 theLockMode = LM_Exclusive;
111 m_abortOption = AbortOnError;
112 return 0;
113 } else {
114 setErrorCode(4200);
115 return -1;
116 }//if
117 }//NdbOperation::deleteTuple()
118
119 /******************************************************************************
120 * int readTuple();
121 *****************************************************************************/
122 int
readTuple(NdbOperation::LockMode lm)123 NdbOperation::readTuple(NdbOperation::LockMode lm)
124 {
125 switch(lm) {
126 case LM_Read:
127 return readTuple();
128 break;
129 case LM_Exclusive:
130 return readTupleExclusive();
131 break;
132 case LM_CommittedRead:
133 return committedRead();
134 break;
135 case LM_SimpleRead:
136 return simpleRead();
137 default:
138 return -1;
139 };
140 }
141 /******************************************************************************
142 * int readTuple();
143 *****************************************************************************/
144 int
readTuple()145 NdbOperation::readTuple()
146 {
147 NdbTransaction* tNdbCon = theNdbCon;
148 int tErrorLine = theErrorLine;
149 if (theStatus == Init) {
150 theStatus = OperationDefined;
151 tNdbCon->theSimpleState = 0;
152 theOperationType = ReadRequest;
153 theErrorLine = tErrorLine++;
154 theLockMode = LM_Read;
155 m_abortOption = AO_IgnoreError;
156 return 0;
157 } else {
158 setErrorCode(4200);
159 return -1;
160 }//if
161 }//NdbOperation::readTuple()
162
163 /******************************************************************************
164 * int readTupleExclusive();
165 *****************************************************************************/
166 int
readTupleExclusive()167 NdbOperation::readTupleExclusive()
168 {
169 NdbTransaction* tNdbCon = theNdbCon;
170 int tErrorLine = theErrorLine;
171 if (theStatus == Init) {
172 theStatus = OperationDefined;
173 tNdbCon->theSimpleState = 0;
174 theOperationType = ReadExclusive;
175 theErrorLine = tErrorLine++;
176 theLockMode = LM_Exclusive;
177 m_abortOption = AO_IgnoreError;
178 return 0;
179 } else {
180 setErrorCode(4200);
181 return -1;
182 }//if
183 }//NdbOperation::readTupleExclusive()
184
185 /*****************************************************************************
186 * int simpleRead();
187 *****************************************************************************/
188 int
simpleRead()189 NdbOperation::simpleRead()
190 {
191 NdbTransaction* tNdbCon = theNdbCon;
192 int tErrorLine = theErrorLine;
193 if (theStatus == Init) {
194 theStatus = OperationDefined;
195 theOperationType = ReadRequest;
196 theSimpleIndicator = 1;
197 theDirtyIndicator = 0;
198 theErrorLine = tErrorLine++;
199 theLockMode = LM_SimpleRead;
200 m_abortOption = AO_IgnoreError;
201 tNdbCon->theSimpleState = 0;
202 return 0;
203 } else {
204 setErrorCode(4200);
205 return -1;
206 }//if
207 }//NdbOperation::simpleRead()
208
209 /*****************************************************************************
210 * int dirtyRead();
211 *****************************************************************************/
212 int
dirtyRead()213 NdbOperation::dirtyRead()
214 {
215 return committedRead();
216 }//NdbOperation::dirtyRead()
217
218 /*****************************************************************************
219 * int committedRead();
220 *****************************************************************************/
221 int
committedRead()222 NdbOperation::committedRead()
223 {
224 int tErrorLine = theErrorLine;
225 if (theStatus == Init) {
226 theStatus = OperationDefined;
227 theOperationType = ReadRequest;
228 theSimpleIndicator = 1;
229 theDirtyIndicator = 1;
230 theErrorLine = tErrorLine++;
231 theLockMode = LM_CommittedRead;
232 m_abortOption = AO_IgnoreError;
233 return 0;
234 } else {
235 setErrorCode(4200);
236 return -1;
237 }//if
238 }//NdbOperation::committedRead()
239
240 /*****************************************************************************
241 * int dirtyUpdate();
242 ****************************************************************************/
243 int
dirtyUpdate()244 NdbOperation::dirtyUpdate()
245 {
246 NdbTransaction* tNdbCon = theNdbCon;
247 int tErrorLine = theErrorLine;
248 if (theStatus == Init) {
249 theStatus = OperationDefined;
250 theOperationType = UpdateRequest;
251 tNdbCon->theSimpleState = 0;
252 theSimpleIndicator = 1;
253 theDirtyIndicator = 1;
254 theErrorLine = tErrorLine++;
255 theLockMode = LM_CommittedRead;
256 m_abortOption = AbortOnError;
257 return 0;
258 } else {
259 setErrorCode(4200);
260 return -1;
261 }//if
262 }//NdbOperation::dirtyUpdate()
263
264 /******************************************************************************
265 * int dirtyWrite();
266 *****************************************************************************/
267 int
dirtyWrite()268 NdbOperation::dirtyWrite()
269 {
270 NdbTransaction* tNdbCon = theNdbCon;
271 int tErrorLine = theErrorLine;
272 if (theStatus == Init) {
273 theStatus = OperationDefined;
274 theOperationType = WriteRequest;
275 tNdbCon->theSimpleState = 0;
276 theSimpleIndicator = 1;
277 theDirtyIndicator = 1;
278 theErrorLine = tErrorLine++;
279 theLockMode = LM_CommittedRead;
280 m_abortOption = AbortOnError;
281 return 0;
282 } else {
283 setErrorCode(4200);
284 return -1;
285 }//if
286 }//NdbOperation::dirtyWrite()
287
288 /******************************************************************************
289 * int interpretedUpdateTuple();
290 ****************************************************************************/
291 int
interpretedUpdateTuple()292 NdbOperation::interpretedUpdateTuple()
293 {
294 NdbTransaction* tNdbCon = theNdbCon;
295 int tErrorLine = theErrorLine;
296 if (theStatus == Init) {
297 theStatus = OperationDefined;
298 tNdbCon->theSimpleState = 0;
299 theOperationType = UpdateRequest;
300 theAI_LenInCurrAI = 25;
301 theLockMode = LM_Exclusive;
302 theErrorLine = tErrorLine++;
303 m_abortOption = AbortOnError;
304 initInterpreter();
305 return 0;
306 } else {
307 setErrorCode(4200);
308 return -1;
309 }//if
310 }//NdbOperation::interpretedUpdateTuple()
311
312 /*****************************************************************************
313 * int interpretedDeleteTuple();
314 *****************************************************************************/
315 int
interpretedDeleteTuple()316 NdbOperation::interpretedDeleteTuple()
317 {
318 NdbTransaction* tNdbCon = theNdbCon;
319 int tErrorLine = theErrorLine;
320 if (theStatus == Init) {
321 theStatus = OperationDefined;
322 tNdbCon->theSimpleState = 0;
323 theOperationType = DeleteRequest;
324
325 theErrorLine = tErrorLine++;
326 theAI_LenInCurrAI = 25;
327 theLockMode = LM_Exclusive;
328 m_abortOption = AbortOnError;
329 initInterpreter();
330 return 0;
331 } else {
332 setErrorCode(4200);
333 return -1;
334 }//if
335 }//NdbOperation::interpretedDeleteTuple()
336
337 void
setReadLockMode(LockMode lockMode)338 NdbOperation::setReadLockMode(LockMode lockMode)
339 {
340 /* We only support changing lock mode for read operations at this time. */
341 assert(theOperationType == ReadRequest || theOperationType == ReadExclusive);
342 switch (lockMode) {
343 case LM_CommittedRead: /* TODO, check theNdbCon->theSimpleState */
344 theOperationType= ReadRequest;
345 theSimpleIndicator= 1;
346 theDirtyIndicator= 1;
347 break;
348 case LM_SimpleRead: /* TODO, check theNdbCon->theSimpleState */
349 theOperationType= ReadRequest;
350 theSimpleIndicator= 1;
351 theDirtyIndicator= 0;
352 break;
353 case LM_Read:
354 theNdbCon->theSimpleState= 0;
355 theOperationType= ReadRequest;
356 theSimpleIndicator= 0;
357 theDirtyIndicator= 0;
358 break;
359 case LM_Exclusive:
360 theNdbCon->theSimpleState= 0;
361 theOperationType= ReadExclusive;
362 theSimpleIndicator= 0;
363 theDirtyIndicator= 0;
364 break;
365 default:
366 /* Not supported / invalid. */
367 assert(false);
368 }
369 theLockMode= lockMode;
370 }
371
372
373 /******************************************************************************
374 * int getValue(AttrInfo* tAttrInfo, char* aRef )
375 *
376 * Return Value Return 0 : GetValue was successful.
377 * Return -1: In all other case.
378 * Parameters: tAttrInfo : Attribute object of the retrieved attribute
379 * value.
380 * Remark: Define an attribute to retrieve in query.
381 *****************************************************************************/
382 NdbRecAttr*
getValue_impl(const NdbColumnImpl * tAttrInfo,char * aValue)383 NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
384 {
385 NdbRecAttr* tRecAttr;
386 if ((tAttrInfo != NULL) &&
387 (theStatus != Init)){
388 m_no_disk_flag &= (tAttrInfo->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
389 if (theStatus != GetValue) {
390 if (theInterpretIndicator == 1) {
391 if (theStatus == FinalGetValue) {
392 ; // Simply continue with getValue
393 } else if (theStatus == ExecInterpretedValue) {
394 if (insertATTRINFO(Interpreter::EXIT_OK) == -1)
395 return NULL;
396 theInterpretedSize = theTotalCurrAI_Len -
397 (theInitialReadSize + 5);
398 } else if (theStatus == SetValueInterpreted) {
399 theFinalUpdateSize = theTotalCurrAI_Len -
400 (theInitialReadSize + theInterpretedSize + 5);
401 } else {
402 setErrorCodeAbort(4230);
403 return NULL;
404 }//if
405 // MASV - How would execution come here?
406 theStatus = FinalGetValue;
407 } else {
408 setErrorCodeAbort(4230);
409 return NULL;
410 }//if
411 }//if
412 AttributeHeader ah(tAttrInfo->m_attrId, 0);
413 if (insertATTRINFO(ah.m_value) != -1) {
414 // Insert Attribute Id into ATTRINFO part.
415
416 /************************************************************************
417 * Get a Receive Attribute object and link it into the operation object.
418 ***********************************************************************/
419 if((tRecAttr = theReceiver.getValue(tAttrInfo, aValue)) != 0){
420 theErrorLine++;
421 return tRecAttr;
422 } else {
423 setErrorCodeAbort(4000);
424 return NULL;
425 }
426 } else {
427 return NULL;
428 }//if insertATTRINFO failure
429 } else {
430 if (tAttrInfo == NULL) {
431 setErrorCodeAbort(4004);
432 return NULL;
433 }//if
434 }//if
435 setErrorCodeAbort(4200);
436 return NULL;
437 }
438
439 /*****************************************************************************
440 * int setValue(AttrInfo* tAttrInfo, char* aValue, Uint32 len)
441 *
442 * Return Value: Return 0 : SetValue was succesful.
443 * Return -1: In all other case.
444 * Parameters: tAttrInfo : Attribute object where the attribute
445 * info exists.
446 * aValue : Reference to the variable with the new value.
447 * len : Length of the value
448 * Remark: Define a attribute to set in a query.
449 ******************************************************************************/
450 int
setValue(const NdbColumnImpl * tAttrInfo,const char * aValuePassed)451 NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
452 const char* aValuePassed)
453 {
454 DBUG_ENTER("NdbOperation::setValue");
455 DBUG_PRINT("enter", ("col: %s op:%d val: 0x%lx",
456 tAttrInfo->m_name.c_str(), theOperationType,
457 (long) aValuePassed));
458
459 int tReturnCode;
460 Uint32 tAttrId;
461 Uint32 tData;
462 Uint32 tempData[2000];
463 OperationType tOpType = theOperationType;
464 OperationStatus tStatus = theStatus;
465
466
467 if ((tOpType == UpdateRequest) ||
468 (tOpType == WriteRequest)) {
469 if (theInterpretIndicator == 0) {
470 if (tStatus == SetValue) {
471 ;
472 } else {
473 setErrorCodeAbort(4234);
474 DBUG_RETURN(-1);
475 }//if
476 } else {
477 if (tStatus == GetValue) {
478 theInitialReadSize = theTotalCurrAI_Len - 5;
479 } else if (tStatus == ExecInterpretedValue) {
480 //--------------------------------------------------------------------
481 // We insert an exit from interpretation since we are now starting
482 // to set values in the tuple by setValue.
483 //--------------------------------------------------------------------
484 if (insertATTRINFO(Interpreter::EXIT_OK) == -1){
485 DBUG_RETURN(-1);
486 }
487 theInterpretedSize = theTotalCurrAI_Len -
488 (theInitialReadSize + 5);
489 } else if (tStatus == SetValueInterpreted) {
490 ; // Simply continue adding new setValue
491 } else {
492 //--------------------------------------------------------------------
493 // setValue used in the wrong context. Application coding error.
494 //-------------------------------------------------------------------
495 setErrorCodeAbort(4234); //Wrong error code
496 DBUG_RETURN(-1);
497 }//if
498 theStatus = SetValueInterpreted;
499 }//if
500 } else if (tOpType == InsertRequest) {
501 if ((theStatus != SetValue) && (theStatus != OperationDefined)) {
502 setErrorCodeAbort(4234);
503 DBUG_RETURN(-1);
504 }//if
505 } else if (tOpType == ReadRequest || tOpType == ReadExclusive) {
506 setErrorCodeAbort(4504);
507 DBUG_RETURN(-1);
508 } else if (tOpType == DeleteRequest) {
509 setErrorCodeAbort(4504);
510 DBUG_RETURN(-1);
511 } else if (tOpType == OpenScanRequest || tOpType == OpenRangeScanRequest) {
512 setErrorCodeAbort(4228);
513 DBUG_RETURN(-1);
514 } else {
515 //---------------------------------------------------------------------
516 // setValue with undefined operation type.
517 // Probably application coding error.
518 //---------------------------------------------------------------------
519 setErrorCodeAbort(4108);
520 DBUG_RETURN(-1);
521 }//if
522 if (tAttrInfo == NULL) {
523 setErrorCodeAbort(4004);
524 DBUG_RETURN(-1);
525 }//if
526 if (tAttrInfo->m_pk) {
527 if (theOperationType == InsertRequest) {
528 DBUG_RETURN(equal_impl(tAttrInfo, aValuePassed));
529 } else {
530 setErrorCodeAbort(4202);
531 DBUG_RETURN(-1);
532 }//if
533 }//if
534
535 // Insert Attribute Id into ATTRINFO part.
536 tAttrId = tAttrInfo->m_attrId;
537 m_no_disk_flag &= (tAttrInfo->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
538 const char *aValue = aValuePassed;
539 if (aValue == NULL) {
540 if (tAttrInfo->m_nullable) {
541 AttributeHeader ah(tAttrId, 0);
542 ah.setNULL();
543 insertATTRINFO(ah.m_value);
544 // Insert Attribute Id with the value
545 // NULL into ATTRINFO part.
546 DBUG_RETURN(0);
547 } else {
548 /***********************************************************************
549 * Setting a NULL value on a NOT NULL attribute is not allowed.
550 **********************************************************************/
551 setErrorCodeAbort(4203);
552 DBUG_RETURN(-1);
553 }//if
554 }//if
555
556 Uint32 len;
557 if (! tAttrInfo->get_var_length(aValue, len)) {
558 setErrorCodeAbort(4209);
559 DBUG_RETURN(-1);
560 }
561
562 const Uint32 sizeInBytes = len;
563 const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
564
565 const int attributeSize = sizeInBytes;
566 const int slack = sizeInBytes & 3;
567
568 if (((UintPtr)aValue & 3) != 0 || (slack != 0)){
569 memcpy(&tempData[0], aValue, attributeSize);
570 aValue = (char*)&tempData[0];
571 if(slack != 0) {
572 char * tmp = (char*)&tempData[0];
573 memset(&tmp[attributeSize], 0, (4 - slack));
574 }//if
575 }//if
576
577 // Excluding bits in last word
578 const Uint32 sizeInWords = sizeInBytes / 4;
579 AttributeHeader ah(tAttrId, sizeInBytes);
580 insertATTRINFO( ah.m_value );
581
582 /***********************************************************************
583 * Check if the pointer of the value passed is aligned on a 4 byte boundary.
584 * If so only assign the pointer to the internal variable aValue.
585 * If it is not aligned then we start by copying the value to tempData and
586 * use this as aValue instead.
587 *************************************************************************/
588
589 tReturnCode = insertATTRINFOloop((Uint32*)aValue, sizeInWords);
590 if (tReturnCode == -1) {
591 DBUG_RETURN(tReturnCode);
592 }//if
593 if (bitsInLastWord != 0) {
594 tData = *(Uint32*)(aValue + sizeInWords*4);
595 tData = convertEndian(tData);
596 tData = tData & ((1 << bitsInLastWord) - 1);
597 tData = convertEndian(tData);
598 tReturnCode = insertATTRINFO(tData);
599 if (tReturnCode == -1) {
600 DBUG_RETURN(tReturnCode);
601 }//if
602 }//if
603 theErrorLine++;
604 DBUG_RETURN(0);
605 }//NdbOperation::setValue()
606
607
608 int
setAnyValue(Uint32 any_value)609 NdbOperation::setAnyValue(Uint32 any_value)
610 {
611 const NdbColumnImpl* impl =
612 &NdbColumnImpl::getImpl(* NdbDictionary::Column::ANY_VALUE);
613 OperationType tOpType = theOperationType;
614
615 switch(tOpType){
616 case DeleteRequest:{
617 Uint32 ah;
618 AttributeHeader::init(&ah, AttributeHeader::ANY_VALUE, 4);
619 if (insertATTRINFO(ah) != -1 && insertATTRINFO(any_value) != -1 )
620 {
621 return 0;
622 }
623 }
624 default:
625 return setValue(impl, (const char *)&any_value);
626 }
627
628 setErrorCodeAbort(4000);
629 return -1;
630 }
631
632
633 NdbBlob*
getBlobHandle(NdbTransaction * aCon,const NdbColumnImpl * tAttrInfo)634 NdbOperation::getBlobHandle(NdbTransaction* aCon, const NdbColumnImpl* tAttrInfo)
635 {
636 NdbBlob* tBlob = theBlobList;
637 NdbBlob* tLastBlob = NULL;
638 while (tBlob != NULL) {
639 if (tBlob->theColumn == tAttrInfo)
640 return tBlob;
641 tLastBlob = tBlob;
642 tBlob = tBlob->theNext;
643 }
644 tBlob = theNdb->getNdbBlob();
645 if (tBlob == NULL)
646 return NULL;
647 if (tBlob->atPrepare(aCon, this, tAttrInfo) == -1) {
648 theNdb->releaseNdbBlob(tBlob);
649 return NULL;
650 }
651 if (tLastBlob == NULL)
652 theBlobList = tBlob;
653 else
654 tLastBlob->theNext = tBlob;
655 tBlob->theNext = NULL;
656 theNdbCon->theBlobFlag = true;
657 return tBlob;
658 }
659
660 /****************************************************************************
661 * int insertATTRINFO( Uint32 aData );
662 *
663 * Return Value: Return 0 : insertATTRINFO was succesful.
664 * Return -1: In all other case.
665 * Parameters: aData: the data to insert into ATTRINFO.
666 * Remark: Puts the the data into either TCKEYREQ signal or
667 * ATTRINFO signal.
668 *****************************************************************************/
669 int
insertATTRINFO(Uint32 aData)670 NdbOperation::insertATTRINFO( Uint32 aData )
671 {
672 NdbApiSignal* tSignal;
673 register Uint32 tAI_LenInCurrAI = theAI_LenInCurrAI;
674 register Uint32* tAttrPtr = theATTRINFOptr;
675 register Uint32 tTotCurrAILen = theTotalCurrAI_Len;
676
677 if (tAI_LenInCurrAI >= 25) {
678 Ndb* tNdb = theNdb;
679 NdbApiSignal* tFirstAttrinfo = theFirstATTRINFO;
680 tAI_LenInCurrAI = 3;
681 tSignal = tNdb->getSignal();
682 if (tSignal != NULL) {
683 tSignal->setSignal(m_attrInfoGSN);
684 tAttrPtr = &tSignal->getDataPtrSend()[3];
685 if (tFirstAttrinfo == NULL) {
686 tSignal->next(NULL);
687 theFirstATTRINFO = tSignal;
688 theCurrentATTRINFO = tSignal;
689 } else {
690 NdbApiSignal* tCurrentAttrinfoBeforeUpdate = theCurrentATTRINFO;
691 tSignal->next(NULL);
692 theCurrentATTRINFO = tSignal;
693 tCurrentAttrinfoBeforeUpdate->next(tSignal);
694 }//if
695 } else {
696 goto insertATTRINFO_error1;
697 }//if
698 }//if
699 *tAttrPtr = aData;
700 tAttrPtr++;
701 tTotCurrAILen++;
702 tAI_LenInCurrAI++;
703 theTotalCurrAI_Len = tTotCurrAILen;
704 theAI_LenInCurrAI = tAI_LenInCurrAI;
705 theATTRINFOptr = tAttrPtr;
706 return 0;
707
708 insertATTRINFO_error1:
709 setErrorCodeAbort(4000);
710 return -1;
711
712 }//NdbOperation::insertATTRINFO()
713
714 /*****************************************************************************
715 * int insertATTRINFOloop(Uint32* aDataPtr, Uint32 aLength );
716 *
717 * Return Value: Return 0 : insertATTRINFO was succesful.
718 * Return -1: In all other case.
719 * Parameters: aDataPtr: Pointer to the data to insert into ATTRINFO.
720 * aLength: Length of data to be copied
721 * Remark: Puts the the data into either TCKEYREQ signal or
722 * ATTRINFO signal.
723 *****************************************************************************/
724 int
insertATTRINFOloop(register const Uint32 * aDataPtr,register Uint32 aLength)725 NdbOperation::insertATTRINFOloop(register const Uint32* aDataPtr,
726 register Uint32 aLength)
727 {
728 NdbApiSignal* tSignal;
729 register Uint32 tAI_LenInCurrAI = theAI_LenInCurrAI;
730 register Uint32 tTotCurrAILen = theTotalCurrAI_Len;
731 register Uint32* tAttrPtr = theATTRINFOptr;
732 Ndb* tNdb = theNdb;
733
734 while (aLength > 0) {
735 if (tAI_LenInCurrAI >= 25) {
736 NdbApiSignal* tFirstAttrinfo = theFirstATTRINFO;
737 tAI_LenInCurrAI = 3;
738 tSignal = tNdb->getSignal();
739 if (tSignal != NULL) {
740 tSignal->setSignal(m_attrInfoGSN);
741 tAttrPtr = &tSignal->getDataPtrSend()[3];
742 if (tFirstAttrinfo == NULL) {
743 tSignal->next(NULL);
744 theFirstATTRINFO = tSignal;
745 theCurrentATTRINFO = tSignal;
746 } else {
747 NdbApiSignal* tCurrentAttrinfoBeforeUpdate = theCurrentATTRINFO;
748 tSignal->next(NULL);
749 theCurrentATTRINFO = tSignal;
750 tCurrentAttrinfoBeforeUpdate->next(tSignal);
751 }//if
752 } else {
753 goto insertATTRINFO_error1;
754 }//if
755 }//if
756 {
757 register Uint32 tData = *aDataPtr;
758 aDataPtr++;
759 aLength--;
760 tAI_LenInCurrAI++;
761 *tAttrPtr = tData;
762 tAttrPtr++;
763 tTotCurrAILen++;
764 }
765 }//while
766 theATTRINFOptr = tAttrPtr;
767 theTotalCurrAI_Len = tTotCurrAILen;
768 theAI_LenInCurrAI = tAI_LenInCurrAI;
769 return 0;
770
771 insertATTRINFO_error1:
772 setErrorCodeAbort(4000);
773 return -1;
774
775 }//NdbOperation::insertATTRINFOloop()
776
777 NdbOperation::AbortOption
getAbortOption() const778 NdbOperation::getAbortOption() const
779 {
780 return (AbortOption)m_abortOption;
781 }
782
783 int
setAbortOption(AbortOption ao)784 NdbOperation::setAbortOption(AbortOption ao)
785 {
786 switch(ao)
787 {
788 case AO_IgnoreError:
789 case AbortOnError:
790 m_abortOption= ao;
791 return 0;
792 default:
793 return -1;
794 }
795 }
796