MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbtupRoutines.cpp
1 /*
2  Copyright (c) 2003, 2010, 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 
19 #define DBTUP_C
20 #define DBTUP_ROUTINES_CPP
21 #include "Dbtup.hpp"
22 #include <RefConvert.hpp>
23 #include <ndb_limits.h>
24 #include <pc.hpp>
25 #include <AttributeDescriptor.hpp>
26 #include "AttributeOffset.hpp"
27 #include <AttributeHeader.hpp>
28 #include <dblqh/Dblqh.hpp>
29 
30 void
31 Dbtup::setUpQueryRoutines(Tablerec *regTabPtr)
32 {
33  Uint32 startDescriptor= regTabPtr->tabDescriptor;
34  ndbrequire((startDescriptor + (regTabPtr->m_no_of_attributes << ZAD_LOG_SIZE))
35  <= cnoOfTabDescrRec);
36  for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++) {
37  Uint32 attrDescrStart= startDescriptor + (i << ZAD_LOG_SIZE);
38  Uint32 attrDescr= tableDescriptor[attrDescrStart].tabDescr;
39  Uint32 attrOffset= tableDescriptor[attrDescrStart + 1].tabDescr;
40 
41  //Uint32 type = AttributeDescriptor::getType(attrDescr);
42  Uint32 array = AttributeDescriptor::getArrayType(attrDescr);
43  Uint32 charset = AttributeOffset::getCharsetFlag(attrOffset);
44  Uint32 size = AttributeDescriptor::getSize(attrDescr);
45  Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescr);
46  Uint32 words = AttributeDescriptor::getSizeInWords(attrDescr);
47  Uint32 nullable = AttributeDescriptor::getNullable(attrDescr);
48  Uint32 dynamic = AttributeDescriptor::getDynamic(attrDescr);
49 
50  if (!dynamic)
51  {
52  if (array == NDB_ARRAYTYPE_FIXED)
53  {
54  if (!nullable)
55  {
56  switch(size){
57  case DictTabInfo::aBit:
58  jam();
59  regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNotNULL;
60  regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNotNULL;
61  break;
62  case DictTabInfo::an8Bit:
63  case DictTabInfo::a16Bit:
64  jam();
65  regTabPtr->readFunctionArray[i]=
66  &Dbtup::readFixedSizeTHManyWordNotNULL;
67  regTabPtr->updateFunctionArray[i]=
68  &Dbtup::updateFixedSizeTHManyWordNotNULL;
69  break;
70  case DictTabInfo::a32Bit:
71  case DictTabInfo::a64Bit:
72  case DictTabInfo::a128Bit:
73  default:
74  switch(bytes){
75  case 4:
76  jam();
77  regTabPtr->readFunctionArray[i] =
78  &Dbtup::readFixedSizeTHOneWordNotNULL;
79  regTabPtr->updateFunctionArray[i] =
80  &Dbtup::updateFixedSizeTHOneWordNotNULL;
81  break;
82  case 8:
83  jam();
84  regTabPtr->readFunctionArray[i] =
85  &Dbtup::readFixedSizeTHTwoWordNotNULL;
86  regTabPtr->updateFunctionArray[i] =
87  &Dbtup::updateFixedSizeTHManyWordNotNULL;
88  break;
89  default:
90  jam();
91  regTabPtr->readFunctionArray[i] =
92  &Dbtup::readFixedSizeTHManyWordNotNULL;
93  regTabPtr->updateFunctionArray[i] =
94  &Dbtup::updateFixedSizeTHManyWordNotNULL;
95  break;
96  }
97  }
98  if (charset)
99  {
100  jam();
101  regTabPtr->readFunctionArray[i] =
102  &Dbtup::readFixedSizeTHManyWordNotNULL;
103  regTabPtr->updateFunctionArray[i] =
104  &Dbtup::updateFixedSizeTHManyWordNotNULL;
105  }
106  }
107  else // nullable
108  {
109  switch(size){
110  case DictTabInfo::aBit:
111  jam();
112  regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNULLable;
113  regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNULLable;
114  break;
115  case DictTabInfo::an8Bit:
116  case DictTabInfo::a16Bit:
117  jam();
118  regTabPtr->readFunctionArray[i]=
119  &Dbtup::readFixedSizeTHManyWordNULLable;
120  regTabPtr->updateFunctionArray[i]=
121  &Dbtup::updateFixedSizeTHManyWordNULLable;
122  break;
123  case DictTabInfo::a32Bit:
124  case DictTabInfo::a64Bit:
125  case DictTabInfo::a128Bit:
126  default:
127  switch(bytes){
128  case 4:
129  jam();
130  regTabPtr->readFunctionArray[i] =
131  &Dbtup::readFixedSizeTHOneWordNULLable;
132  regTabPtr->updateFunctionArray[i] =
133  &Dbtup::updateFixedSizeTHManyWordNULLable;
134  break;
135  case 8:
136  jam();
137  regTabPtr->readFunctionArray[i] =
138  &Dbtup::readFixedSizeTHTwoWordNULLable;
139  regTabPtr->updateFunctionArray[i] =
140  &Dbtup::updateFixedSizeTHManyWordNULLable;
141  break;
142  default:
143  jam();
144  regTabPtr->readFunctionArray[i] =
145  &Dbtup::readFixedSizeTHManyWordNULLable;
146  regTabPtr->updateFunctionArray[i] =
147  &Dbtup::updateFixedSizeTHManyWordNULLable;
148  break;
149  }
150  }
151  if (charset)
152  {
153  jam();
154  regTabPtr->readFunctionArray[i] =
155  &Dbtup::readFixedSizeTHManyWordNULLable;
156  regTabPtr->updateFunctionArray[i] =
157  &Dbtup::updateFixedSizeTHManyWordNULLable;
158  }
159  }
160  } else
161  {
162  if (!nullable)
163  {
164  jam();
165  regTabPtr->readFunctionArray[i]=
166  &Dbtup::readVarSizeNotNULL;
167  regTabPtr->updateFunctionArray[i]=
168  &Dbtup::updateVarSizeNotNULL;
169  }
170  else
171  {
172  jam();
173  regTabPtr->readFunctionArray[i]=
174  &Dbtup::readVarSizeNULLable;
175  regTabPtr->updateFunctionArray[i]=
176  &Dbtup::updateVarSizeNULLable;
177  }
178  }
179  if(AttributeDescriptor::getDiskBased(attrDescr))
180  {
181  // array initializer crashes gcc-2.95.3
182  ReadFunction r[6];
183  {
184  r[0] = &Dbtup::readDiskBitsNotNULL;
185  r[1] = &Dbtup::readDiskBitsNULLable;
186  r[2] = &Dbtup::readDiskFixedSizeNotNULL;
187  r[3] = &Dbtup::readDiskFixedSizeNULLable;
188  r[4] = &Dbtup::readDiskVarAsFixedSizeNotNULL;
189  r[5] = &Dbtup::readDiskVarAsFixedSizeNULLable;
190  /*
191  r[4] = &Dbtup::readDiskVarSizeNULLable;
192  r[5] = &Dbtup::readDiskVarSizeNotNULL;
193  */
194  }
195  UpdateFunction u[6];
196  {
197  u[0] = &Dbtup::updateDiskBitsNotNULL;
198  u[1] = &Dbtup::updateDiskBitsNULLable;
199  u[2] = &Dbtup::updateDiskFixedSizeNotNULL;
200  u[3] = &Dbtup::updateDiskFixedSizeNULLable;
201  u[4] = &Dbtup::updateDiskVarAsFixedSizeNotNULL;
202  u[5] = &Dbtup::updateDiskVarAsFixedSizeNULLable;
203  /*
204  u[4] = &Dbtup::updateDiskVarSizeNULLable;
205  u[5] = &Dbtup::updateDiskVarSizeNotNULL;
206  */
207  }
208  Uint32 a=
209  AttributeDescriptor::getArrayType(attrDescr) == NDB_ARRAYTYPE_FIXED
210  ? 2 : 4;
211 
212  if(AttributeDescriptor::getSize(attrDescr) == 0)
213  a= 0;
214 
215  Uint32 b=
216  AttributeDescriptor::getNullable(attrDescr)? 1 : 0;
217  regTabPtr->readFunctionArray[i]= r[a+b];
218  regTabPtr->updateFunctionArray[i]= u[a+b];
219  }
220  }
221  else // dynamic
222  {
223  if (nullable)
224  {
225  if (array == NDB_ARRAYTYPE_FIXED)
226  {
227  if (size == 0)
228  {
229  jam();
230  regTabPtr->readFunctionArray[i]= &Dbtup::readDynBitsNULLable;
231  regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynBitsNULLable;
232  }
233  else if (words > InternalMaxDynFix)
234  {
235  jam();
236  regTabPtr->readFunctionArray[i]=
237  &Dbtup::readDynBigFixedSizeNULLable;
238  regTabPtr->updateFunctionArray[i]=
239  &Dbtup::updateDynBigFixedSizeNULLable;
240  }
241  else
242  {
243  jam();
244  regTabPtr->readFunctionArray[i]=
245  &Dbtup::readDynFixedSizeNULLable;
246  regTabPtr->updateFunctionArray[i]=
247  &Dbtup::updateDynFixedSizeNULLable;
248  }
249  }
250  else
251  {
252  regTabPtr->readFunctionArray[i]= &Dbtup::readDynVarSizeNULLable;
253  regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynVarSizeNULLable;
254  }
255  }
256  else // nullable
257  {
258  if (array == NDB_ARRAYTYPE_FIXED)
259  {
260  if (size == 0)
261  {
262  jam();
263  regTabPtr->readFunctionArray[i]= &Dbtup::readDynBitsNotNULL;
264  regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynBitsNotNULL;
265  }
266  else if (words > InternalMaxDynFix)
267  {
268  jam();
269  regTabPtr->readFunctionArray[i]=
270  &Dbtup::readDynBigFixedSizeNotNULL;
271  regTabPtr->updateFunctionArray[i]=
272  &Dbtup::updateDynBigFixedSizeNotNULL;
273  }
274  else
275  {
276  jam();
277  regTabPtr->readFunctionArray[i]=
278  &Dbtup::readDynFixedSizeNotNULL;
279  regTabPtr->updateFunctionArray[i]=
280  &Dbtup::updateDynFixedSizeNotNULL;
281  }
282  }
283  else
284  {
285  jam();
286  regTabPtr->readFunctionArray[i]= &Dbtup::readDynVarSizeNotNULL;
287  regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynVarSizeNotNULL;
288  }
289  }
290  }
291  }
292 }
293 
294 #if 0
295 /* Dump a byte buffer, for debugging. */
296 static void dump_buf_hex(unsigned char *p, Uint32 bytes)
297 {
298  char buf[3001];
299  char *q= buf;
300  buf[0]= '\0';
301 
302  for(Uint32 i=0; i<bytes; i++)
303  {
304  if(i==((sizeof(buf)/3)-1))
305  {
306  sprintf(q, "...");
307  break;
308  }
309  sprintf(q+3*i, " %02X", p[i]);
310  }
311  ndbout_c("%8p: %s", p, buf);
312 }
313 #endif
314 
315 static
316 inline
317 Uint32
318 pad32(Uint32 bytepos, Uint32 bitsused)
319 {
320  if (bitsused)
321  {
322  assert((bytepos & 3) == 0);
323  }
324  Uint32 ret = 4 * ((bitsused + 31) >> 5) +
325  ((bytepos + 3) & ~(Uint32)3);
326  return ret;
327 }
328 
329 /* ---------------------------------------------------------------- */
330 /* THIS ROUTINE IS USED TO READ A NUMBER OF ATTRIBUTES IN THE */
331 /* DATABASE AND PLACE THE RESULT IN ATTRINFO RECORDS. */
332 //
333 // In addition to the parameters used in the call it also relies on the
334 // following variables set-up properly.
335 //
336 // operPtr.p Operation record pointer
337 // fragptr.p Fragment record pointer
338 // tabptr.p Table record pointer
339 
340 // It requires the following fields in KeyReqStruct to be properly
341 // filled in:
342 // tuple_header Reference to the tuple
343 // check_offset Record size
344 // attr_descr Reference to the Table Descriptor for the table
345 //
346 // The read functions in addition expects that the following fields in
347 // KeyReqStruct is set up:
348 // out_buf_index Index for output buffer
349 // max_read Size of output buffer
350 // attr_descriptor Attribute Descriptor from where attribute size
351 // can be read
352 /* ---------------------------------------------------------------- */
353 int Dbtup::readAttributes(KeyReqStruct *req_struct,
354  const Uint32* inBuffer,
355  Uint32 inBufLen,
356  Uint32* outBuf,
357  Uint32 maxRead,
358  bool xfrm_flag)
359 {
360  Uint32 attributeId, descr_index, tmpAttrBufIndex, tmpAttrBufBits, inBufIndex;
361  Uint32 attributeOffset;
362  TableDescriptor* attr_descr;
363  AttributeHeader* ahOut;
364 
365  Tablerec* const regTabPtr = req_struct->tablePtrP;
366  Uint32 numAttributes= regTabPtr->m_no_of_attributes;
367 
368  inBufIndex= 0;
369  req_struct->out_buf_index= 0;
370  req_struct->out_buf_bits = 0;
371  req_struct->max_read= 4*maxRead;
372  req_struct->xfrm_flag= xfrm_flag;
373  Uint8*outBuffer = (Uint8*)outBuf;
374  while (inBufIndex < inBufLen) {
375  tmpAttrBufIndex= req_struct->out_buf_index;
376  tmpAttrBufBits = req_struct->out_buf_bits;
377  AttributeHeader ahIn(inBuffer[inBufIndex]);
378  inBufIndex++;
379  attributeId= ahIn.getAttributeId();
380  descr_index= attributeId << ZAD_LOG_SIZE;
381  thrjam(req_struct->jamBuffer);
382 
383  tmpAttrBufIndex = pad32(tmpAttrBufIndex, tmpAttrBufBits);
384  AttributeHeader::init((Uint32 *)&outBuffer[tmpAttrBufIndex],
385  attributeId, 0);
386  ahOut= (AttributeHeader*)&outBuffer[tmpAttrBufIndex];
387  req_struct->out_buf_index= tmpAttrBufIndex + 4;
388  req_struct->out_buf_bits = 0;
389  attr_descr= req_struct->attr_descr;
390  if (attributeId < numAttributes) {
391  attributeOffset= attr_descr[descr_index + 1].tabDescr;
392  ReadFunction f= regTabPtr->readFunctionArray[attributeId];
393  req_struct->attr_descriptor= attr_descr[descr_index].tabDescr;
394  if ((this->*f)(outBuffer,
395  req_struct,
396  ahOut,
397  attributeOffset)) {
398  continue;
399  } else {
400  return -(int)req_struct->errorCode;
401  }
402  }
403  else if(attributeId & AttributeHeader::PSEUDO)
404  {
405  int sz = read_pseudo(inBuffer, inBufIndex,
406  req_struct,
407  (Uint32*)outBuffer);
408  if (likely(sz >= 0))
409  {
410  inBufIndex += Uint32(sz);
411  }
412  else
413  {
414  return sz;
415  }
416  }
417  else
418  {
419  return -ZATTRIBUTE_ID_ERROR;
420  }//if
421  }//while
422  return pad32(req_struct->out_buf_index, req_struct->out_buf_bits) >> 2;
423 }
424 
425 bool
426 Dbtup::readFixedSizeTHOneWordNotNULL(Uint8* outBuffer,
427  KeyReqStruct *req_struct,
428  AttributeHeader* ahOut,
429  Uint32 attrDes2)
430 {
431  ndbassert((req_struct->out_buf_index & 3) == 0);
432  ndbassert(req_struct->out_buf_bits == 0);
433 
434  Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
435  Uint32 indexBuf= req_struct->out_buf_index;
436  Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
437  Uint32 const wordRead= tuple_header[readOffset];
438 
439  Uint32 newIndexBuf = indexBuf + 4;
440  Uint32* dst = (Uint32*)(outBuffer + indexBuf);
441  Uint32 maxRead= req_struct->max_read;
442 
443  ndbrequire(readOffset < req_struct->check_offset[MM]);
444  if (newIndexBuf <= maxRead) {
445  thrjam(req_struct->jamBuffer);
446  dst[0] = wordRead;
447  ahOut->setDataSize(1);
448  req_struct->out_buf_index= newIndexBuf;
449  return true;
450  } else {
451  thrjam(req_struct->jamBuffer);
452  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
453  return false;
454  }
455 }
456 
457 bool
458 Dbtup::readFixedSizeTHTwoWordNotNULL(Uint8* outBuffer,
459  KeyReqStruct *req_struct,
460  AttributeHeader* ahOut,
461  Uint32 attrDes2)
462 {
463  ndbassert((req_struct->out_buf_index & 3) == 0);
464  ndbassert(req_struct->out_buf_bits == 0);
465 
466  Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
467  Uint32 indexBuf= req_struct->out_buf_index;
468  Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
469  Uint32 const wordReadFirst= tuple_header[readOffset];
470  Uint32 const wordReadSecond= tuple_header[readOffset + 1];
471  Uint32 maxRead= req_struct->max_read;
472 
473  Uint32 newIndexBuf = indexBuf + 8;
474  Uint32* dst = (Uint32*)(outBuffer + indexBuf);
475 
476  ndbrequire(readOffset + 1 < req_struct->check_offset[MM]);
477  if (newIndexBuf <= maxRead) {
478  thrjam(req_struct->jamBuffer);
479  ahOut->setDataSize(2);
480  dst[0] = wordReadFirst;
481  dst[1] = wordReadSecond;
482  req_struct->out_buf_index= newIndexBuf;
483  return true;
484  } else {
485  thrjam(req_struct->jamBuffer);
486  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
487  return false;
488  }
489 }
490 
491 
492 static inline
493 void
494 zero32(Uint8* dstPtr, const Uint32 len)
495 {
496  Uint32 odd = len & 3;
497  if (odd != 0)
498  {
499  Uint32 aligned = len & ~3;
500  Uint8* dst = dstPtr+aligned;
501  switch(odd){ /* odd is: {1..3} */
502  case 1:
503  dst[1] = 0;
504  case 2:
505  dst[2] = 0;
506  default: /* Known to be odd==3 */
507  dst[3] = 0;
508  }
509  }
510 }
511 
512 bool
513 Dbtup::readFixedSizeTHManyWordNotNULL(Uint8* outBuffer,
514  KeyReqStruct *req_struct,
515  AttributeHeader* ahOut,
516  Uint32 attrDes2)
517 {
518  ndbassert(req_struct->out_buf_bits == 0);
519 
520  Uint32 attrDescriptor= req_struct->attr_descriptor;
521  Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
522  Uint32 indexBuf= req_struct->out_buf_index;
523  Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
524  Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
525  Uint32 attrNoOfWords= (srcBytes + 3) >> 2;
526  Uint32 maxRead= req_struct->max_read;
527  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
528 
529  Uint32 newIndexBuf = indexBuf + srcBytes;
530  Uint8* dst = (outBuffer + indexBuf);
531  const Uint8* src = (Uint8*)(tuple_header + readOffset);
532 
533  ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[MM]);
534  if (! charsetFlag || ! req_struct->xfrm_flag) {
535  if (newIndexBuf <= maxRead) {
536  thrjam(req_struct->jamBuffer);
537  ahOut->setByteSize(srcBytes);
538  memcpy(dst, src, srcBytes);
539  zero32(dst, srcBytes);
540  req_struct->out_buf_index = newIndexBuf;
541  return true;
542  } else {
543  thrjam(req_struct->jamBuffer);
544  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
545  return false;
546  }//if
547  }
548  else
549  {
550  return xfrm_reader(dst, req_struct, ahOut, attrDes2, src, srcBytes);
551  }
552 }//Dbtup::readFixedSizeTHManyWordNotNULL()
553 
554 bool
555 Dbtup::readFixedSizeTHOneWordNULLable(Uint8* outBuffer,
556  KeyReqStruct *req_struct,
557  AttributeHeader* ahOut,
558  Uint32 attrDes2)
559 {
560  if (!nullFlagCheck(req_struct, attrDes2)) {
561  thrjam(req_struct->jamBuffer);
562  return readFixedSizeTHOneWordNotNULL(outBuffer,
563  req_struct,
564  ahOut,
565  attrDes2);
566  } else {
567  thrjam(req_struct->jamBuffer);
568  ahOut->setNULL();
569  return true;
570  }
571 }
572 
573 bool
574 Dbtup::readFixedSizeTHTwoWordNULLable(Uint8* outBuffer,
575  KeyReqStruct *req_struct,
576  AttributeHeader* ahOut,
577  Uint32 attrDes2)
578 {
579  if (!nullFlagCheck(req_struct, attrDes2)) {
580  thrjam(req_struct->jamBuffer);
581  return readFixedSizeTHTwoWordNotNULL(outBuffer,
582  req_struct,
583  ahOut,
584  attrDes2);
585  } else {
586  thrjam(req_struct->jamBuffer);
587  ahOut->setNULL();
588  return true;
589  }
590 }
591 
592 bool
593 Dbtup::readFixedSizeTHManyWordNULLable(Uint8* outBuffer,
594  KeyReqStruct *req_struct,
595  AttributeHeader* ahOut,
596  Uint32 attrDes2)
597 {
598  if (!nullFlagCheck(req_struct, attrDes2)) {
599  thrjam(req_struct->jamBuffer);
600  return readFixedSizeTHManyWordNotNULL(outBuffer,
601  req_struct,
602  ahOut,
603  attrDes2);
604  } else {
605  thrjam(req_struct->jamBuffer);
606  ahOut->setNULL();
607  return true;
608  }
609 }
610 
611 bool
612 Dbtup::readFixedSizeTHZeroWordNULLable(Uint8* outBuffer,
613  KeyReqStruct *req_struct,
614  AttributeHeader* ahOut,
615  Uint32 attrDes2)
616 {
617  thrjam(req_struct->jamBuffer);
618  if (nullFlagCheck(req_struct, attrDes2)) {
619  thrjam(req_struct->jamBuffer);
620  ahOut->setNULL();
621  }
622  return true;
623 }
624 
625 bool
626 Dbtup::nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2)
627 {
628  Uint32 ind =
629  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
630  Uint32(DD) : Uint32(MM);
631  Tablerec* const regTabPtr = req_struct->tablePtrP;
632  Uint32 *bits= (ind) ? req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD) :
633  req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
634  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
635 
636  return BitmaskImpl::get(regTabPtr->m_offsets[ind].m_null_words, bits, pos);
637 }
638 
639 bool
640 Dbtup::disk_nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2)
641 {
642  Tablerec* const regTabPtr = req_struct->tablePtrP;
643  Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
644  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
645 
646  return BitmaskImpl::get(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
647 }
648 
649 /* Shared code for reading static varsize and expanded dynamic attributes. */
650 bool
651 Dbtup::varsize_reader(Uint8* outBuffer,
652  KeyReqStruct *req_struct,
653  AttributeHeader* ah_out,
654  Uint32 attr_des2,
655  const void * srcPtr,
656  Uint32 srcBytes)
657 {
658  ndbassert(req_struct->out_buf_bits == 0);
659 
660  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attr_des2);
661  Uint32 attr_descriptor= req_struct->attr_descriptor;
662  Uint32 indexBuf= req_struct->out_buf_index;
663  Uint32 max_var_size= AttributeDescriptor::getSizeInBytes(attr_descriptor);
664  Uint32 max_read= req_struct->max_read;
665 
666  Uint32 newIndexBuf = indexBuf + srcBytes;
667  Uint8* dst = (outBuffer + indexBuf);
668 
669  ndbrequire(srcBytes <= max_var_size);
670  if (! charsetFlag || ! req_struct->xfrm_flag)
671  {
672  if (newIndexBuf <= max_read) {
673  thrjam(req_struct->jamBuffer);
674  ah_out->setByteSize(srcBytes);
675  memcpy(dst, srcPtr, srcBytes);
676  zero32(dst, srcBytes);
677  req_struct->out_buf_index= newIndexBuf;
678  return true;
679  }
680  }
681  else
682  {
683  return xfrm_reader(dst, req_struct, ah_out, attr_des2, srcPtr, srcBytes);
684  }
685 
686  thrjam(req_struct->jamBuffer);
687  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
688  return false;
689 }
690 
691 bool
692 Dbtup::xfrm_reader(Uint8* dstPtr,
693  KeyReqStruct* req_struct,
694  AttributeHeader* ahOut,
695  Uint32 attrDes2,
696  const void* srcPtr, Uint32 srcBytes)
697 {
698  thrjam(req_struct->jamBuffer);
699  ndbassert(req_struct->out_buf_bits == 0);
700 
701  Tablerec* regTabPtr = req_struct->tablePtrP;
702  Uint32 attrDes1 = req_struct->attr_descriptor;
703  Uint32 indexBuf= req_struct->out_buf_index;
704  Uint32 maxRead= req_struct->max_read;
705  Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
706  Uint32 typeId = AttributeDescriptor::getType(attrDes1);
707  Uint32 maxBytes = AttributeDescriptor::getSizeInBytes(attrDes1);
708 
709  ndbrequire(i < regTabPtr->noOfCharsets);
710  CHARSET_INFO* cs = regTabPtr->charsetArray[i];
711 
712  Uint32 lb, len;
713  bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
714  Uint32 xmul = cs->strxfrm_multiply;
715  if (xmul == 0)
716  xmul = 1;
717  Uint32 dstLen = xmul * (maxBytes - lb);
718  Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
719  if (maxIndexBuf <= maxRead && ok)
720  {
721  thrjam(req_struct->jamBuffer);
722  int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen,
723  (const Uint8*)srcPtr + lb, len);
724  ndbrequire(n != -1);
725  zero32(dstPtr, n);
726  ahOut->setByteSize(n);
727  Uint32 newIndexBuf = indexBuf + n;
728  ndbrequire(newIndexBuf <= maxRead);
729  req_struct->out_buf_index = newIndexBuf;
730  return true;
731  } else {
732  thrjam(req_struct->jamBuffer);
733  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
734  }
735  return false;
736 }
737 
738 bool
739 Dbtup::bits_reader(Uint8* outBuffer,
740  KeyReqStruct *req_struct,
741  AttributeHeader* ahOut,
742  const Uint32* bmptr, Uint32 bmlen,
743  Uint32 bitPos, Uint32 bitCount)
744 {
745  ndbassert((req_struct->out_buf_index & 3) == 0);
746 
747  Uint32 indexBuf = req_struct->out_buf_index;
748  Uint32 indexBits = req_struct->out_buf_bits;
749  Uint32 maxRead = req_struct->max_read;
750 
751  Uint32 sz32 = (bitCount + 31) >> 5;
752  Uint32 newIndexBuf = indexBuf + 4 * ((indexBits + bitCount) >> 5);
753  Uint32 newIndexBits = (indexBits + bitCount) & 31;
754 
755  Uint32* dst = (Uint32*)(outBuffer + indexBuf);
756  if (newIndexBuf <= maxRead) {
757  jam();
758  ahOut->setDataSize(sz32);
759  req_struct->out_buf_index = newIndexBuf;
760  req_struct->out_buf_bits = newIndexBits;
761 
762  if (bitCount == 1)
763  {
764  * dst &= (1 << indexBits) - 1;
765  BitmaskImpl::set(1, dst, indexBits,
766  BitmaskImpl::get(bmlen, bmptr, bitPos));
767  }
768  else if (indexBits == 0)
769  {
770  BitmaskImpl::getField(bmlen, bmptr, bitPos, bitCount, dst);
771  }
772  else
773  {
774  BitmaskImpl::getField(bmlen, bmptr, bitPos, bitCount, dst + 2);
775  BitmaskImpl::setField(1+sz32, dst, indexBits, bitCount, dst + 2);
776  }
777 
778  return true;
779  } else {
780  jam();
781  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
782  return false;
783  }//if
784 }
785 
786 bool
787 Dbtup::readVarSizeNotNULL(Uint8* out_buffer,
788  KeyReqStruct *req_struct,
789  AttributeHeader* ah_out,
790  Uint32 attr_des2)
791 {
792  Uint32 var_idx= AttributeOffset::getOffset(attr_des2);
793  Uint32 var_attr_pos= req_struct->m_var_data[MM].m_offset_array_ptr[var_idx];
794  Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
795  Uint32 srcBytes =
796  req_struct->m_var_data[MM].m_offset_array_ptr[var_idx+idx] - var_attr_pos;
797  const char* src_ptr= req_struct->m_var_data[MM].m_data_ptr+var_attr_pos;
798 
799  return varsize_reader(out_buffer, req_struct, ah_out, attr_des2,
800  src_ptr, srcBytes);
801 }
802 
803 bool
804 Dbtup::readVarSizeNULLable(Uint8* outBuffer,
805  KeyReqStruct *req_struct,
806  AttributeHeader* ahOut,
807  Uint32 attrDes2)
808 {
809  if (!nullFlagCheck(req_struct, attrDes2)) {
810  thrjam(req_struct->jamBuffer);
811  return readVarSizeNotNULL(outBuffer,
812  req_struct,
813  ahOut,
814  attrDes2);
815  } else {
816  thrjam(req_struct->jamBuffer);
817  ahOut->setNULL();
818  return true;
819  }
820 }
821 
822 bool
823 Dbtup::readDynFixedSizeNotNULL(Uint8* outBuffer,
824  KeyReqStruct *req_struct,
825  AttributeHeader* ahOut,
826  Uint32 attrDes2)
827 {
828  thrjam(req_struct->jamBuffer);
829  if(req_struct->is_expanded)
830  return readDynFixedSizeExpandedNotNULL(outBuffer, req_struct,
831  ahOut, attrDes2);
832  else
833  return readDynFixedSizeShrunkenNotNULL(outBuffer, req_struct,
834  ahOut, attrDes2);
835 }
836 
837 bool
838 Dbtup::readDynFixedSizeNULLable(Uint8* outBuffer,
839  KeyReqStruct *req_struct,
840  AttributeHeader* ahOut,
841  Uint32 attrDes2)
842 {
843  thrjam(req_struct->jamBuffer);
844  if(req_struct->is_expanded)
845  return readDynFixedSizeExpandedNULLable(outBuffer, req_struct,
846  ahOut, attrDes2);
847  else
848  return readDynFixedSizeShrunkenNULLable(outBuffer, req_struct,
849  ahOut, attrDes2);
850 }
851 
852 bool
853 Dbtup::readDynFixedSizeExpandedNotNULL(Uint8* outBuffer,
854  KeyReqStruct *req_struct,
855  AttributeHeader* ahOut,
856  Uint32 attrDes2)
857 {
858  /*
859  In the expanded format, we share the read code with static varsized, just
860  using different data base pointer and offset/lenght arrays.
861  */
862  thrjam(req_struct->jamBuffer);
863  Uint32 attr_descriptor= req_struct->attr_descriptor;
864  Uint32 ind =
865  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
866  Uint32(DD) : Uint32(MM);
867 
868  char *src_ptr= req_struct->m_var_data[ind].m_dyn_data_ptr;
869  Uint32 var_index= AttributeOffset::getOffset(attrDes2);
870  Uint16* off_arr= req_struct->m_var_data[ind].m_dyn_offset_arr_ptr;
871  Uint32 var_attr_pos= off_arr[var_index];
872  Uint32 vsize_in_bytes=
873  AttributeDescriptor::getSizeInBytes(attr_descriptor);
874  return varsize_reader(outBuffer, req_struct, ahOut, attrDes2,
875  src_ptr + var_attr_pos, vsize_in_bytes);
876 }
877 
878 bool
879 Dbtup::readDynFixedSizeExpandedNULLable(Uint8* outBuffer,
880  KeyReqStruct *req_struct,
881  AttributeHeader* ahOut,
882  Uint32 attrDes2)
883 {
884  /*
885  Check for NULL. In the expanded format, the bitmap is guaranteed
886  to be stored in full length.
887  */
888 
889  Uint32 ind =
890  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
891  Uint32(DD) : Uint32(MM);
892 
893  Uint32 *src_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
894  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
895  if(!BitmaskImpl::get((* src_ptr) & DYN_BM_LEN_MASK, src_ptr, pos))
896  {
897  thrjam(req_struct->jamBuffer);
898  ahOut->setNULL();
899  return true;
900  }
901 
902  return readDynFixedSizeExpandedNotNULL(outBuffer, req_struct,
903  ahOut, attrDes2);
904 }
905 
906 bool
907 Dbtup::readDynFixedSizeShrunkenNotNULL(Uint8* outBuffer,
908  KeyReqStruct *req_struct,
909  AttributeHeader* ahOut,
910  Uint32 attrDes2)
911 {
912  Uint32 attr_descriptor= req_struct->attr_descriptor;
913  Uint32 ind =
914  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
915  Uint32(DD) : Uint32(MM);
916 
917  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
918  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
919  ndbrequire(dyn_len != 0);
920  Uint32 bm_len= (* bm_ptr) & DYN_BM_LEN_MASK; // In 32-bit words
921  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
922  ndbrequire(BitmaskImpl::get(bm_len, bm_ptr, pos));
923 
924  /*
925  The attribute is not NULL. Now to get the data offset, we count the number
926  of bits set in the bitmap for fixed-size dynamic attributes prior to this
927  attribute. Since there is one bit for each word of fixed-size attribute,
928  and since fixed-size attributes are stored word-aligned backwards from the
929  end of the row, this gives the distance in words from the row end to the
930  end of the data for this attribute.
931 
932  We use a pre-computed bitmask to mask away all bits for fixed-sized
933  dynamic attributes, and we also mask away the initial bitmap length byte and
934  any trailing non-bitmap bytes to save a few conditionals.
935  */
936  thrjam(req_struct->jamBuffer);
937  Tablerec * regTabPtr = req_struct->tablePtrP;
938  Uint32 *bm_mask_ptr= regTabPtr->dynFixSizeMask[ind];
939  Uint32 bm_pos= AttributeOffset::getNullFlagOffset(attrDes2);
940  Uint32 prevMask= (1 << (pos & 31)) - 1;
941  Uint32 bit_count= BitmaskImpl::count_bits(prevMask & bm_mask_ptr[bm_pos] & bm_ptr[bm_pos]);
942  for(Uint32 i=0; i<bm_pos; i++)
943  bit_count+= BitmaskImpl::count_bits(bm_mask_ptr[i] & bm_ptr[i]);
944 
945  /* Now compute the data pointer from the row length. */
946  Uint32 vsize_in_bytes= AttributeDescriptor::getSizeInBytes(attr_descriptor);
947  Uint32 vsize_in_words= (vsize_in_bytes+3)>>2;
948  Uint32 *data_ptr= bm_ptr + dyn_len - bit_count - vsize_in_words;
949 
950  return varsize_reader(outBuffer, req_struct, ahOut, attrDes2,
951  (Uint8 *)data_ptr, vsize_in_bytes);
952 }
953 
954 static
955 inline
956 bool
957 dynCheckNull(Uint32 totlen, Uint32 bm_len, const Uint32* bm_ptr, Uint32 pos)
958 {
959  return totlen == 0 || !(bm_len > (pos >> 5)) ||
960  !BitmaskImpl::get(bm_len, bm_ptr, pos);
961 }
962 
963 bool
964 Dbtup::readDynFixedSizeShrunkenNULLable(Uint8* outBuffer,
965  KeyReqStruct *req_struct,
966  AttributeHeader* ahOut,
967  Uint32 attrDes2)
968 {
969  Uint32 ind =
970  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
971  Uint32(DD) : Uint32(MM);
972 
973  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
974  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
975  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
976  /* Check for NULL (including the case of an empty bitmap). */
977  if(dyn_len == 0 || dynCheckNull(dyn_len, (* bm_ptr) & DYN_BM_LEN_MASK,
978  bm_ptr, pos))
979  {
980  thrjam(req_struct->jamBuffer);
981  ahOut->setNULL();
982  return true;
983  }
984 
985  return readDynFixedSizeShrunkenNotNULL(outBuffer, req_struct,
986  ahOut, attrDes2);
987 }
988 
989 bool
990 Dbtup::readDynBigFixedSizeNotNULL(Uint8* outBuffer,
991  KeyReqStruct *req_struct,
992  AttributeHeader* ahOut,
993  Uint32 attrDes2)
994 {
995  thrjam(req_struct->jamBuffer);
996  if(req_struct->is_expanded)
997  return readDynBigFixedSizeExpandedNotNULL(outBuffer, req_struct,
998  ahOut, attrDes2);
999  else
1000  return readDynBigFixedSizeShrunkenNotNULL(outBuffer, req_struct,
1001  ahOut, attrDes2);
1002 }//Dbtup::readDynBigVarSize()
1003 
1004 bool
1005 Dbtup::readDynBigFixedSizeNULLable(Uint8* outBuffer,
1006  KeyReqStruct *req_struct,
1007  AttributeHeader* ahOut,
1008  Uint32 attrDes2)
1009 {
1010  thrjam(req_struct->jamBuffer);
1011  if(req_struct->is_expanded)
1012  return readDynBigFixedSizeExpandedNULLable(outBuffer, req_struct,
1013  ahOut, attrDes2);
1014  else
1015  return readDynBigFixedSizeShrunkenNULLable(outBuffer, req_struct,
1016  ahOut, attrDes2);
1017 }//Dbtup::readDynBigVarSize()
1018 
1019 bool
1020 Dbtup::readDynBigFixedSizeExpandedNotNULL(Uint8* outBuffer,
1021  KeyReqStruct *req_struct,
1022  AttributeHeader* ahOut,
1023  Uint32 attrDes2)
1024 {
1025  /*
1026  In the expanded format, we share the read code with static varsized, just
1027  using different data base pointer and offset/lenght arrays.
1028  */
1029  thrjam(req_struct->jamBuffer);
1030  Uint32 attr_descriptor= req_struct->attr_descriptor;
1031  Uint32 ind =
1032  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1033  Uint32(DD) : Uint32(MM);
1034 
1035  char *src_ptr= req_struct->m_var_data[ind].m_dyn_data_ptr;
1036  Uint32 var_index= AttributeOffset::getOffset(attrDes2);
1037  Uint16* off_arr= req_struct->m_var_data[ind].m_dyn_offset_arr_ptr;
1038  Uint32 var_attr_pos= off_arr[var_index];
1039  Uint32 vsize_in_bytes=
1040  AttributeDescriptor::getSizeInBytes(attr_descriptor);
1041  Uint32 idx= req_struct->m_var_data[ind].m_dyn_len_offset;
1042  ndbrequire(vsize_in_bytes <= off_arr[var_index+idx] - var_attr_pos);
1043  return varsize_reader(outBuffer, req_struct, ahOut, attrDes2,
1044  src_ptr + var_attr_pos, vsize_in_bytes);
1045 }
1046 
1047 bool
1048 Dbtup::readDynBigFixedSizeExpandedNULLable(Uint8* outBuffer,
1049  KeyReqStruct *req_struct,
1050  AttributeHeader* ahOut,
1051  Uint32 attrDes2)
1052 {
1053  /*
1054  Check for NULL. In the expanded format, the bitmap is guaranteed
1055  to be stored in full length.
1056  */
1057 
1058  Uint32 ind =
1059  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1060  Uint32(DD) : Uint32(MM);
1061 
1062  Uint32 *src_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1063  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1064  if(!BitmaskImpl::get((* src_ptr) & DYN_BM_LEN_MASK, src_ptr, pos))
1065  {
1066  thrjam(req_struct->jamBuffer);
1067  ahOut->setNULL();
1068  return true;
1069  }
1070 
1071  return readDynBigFixedSizeExpandedNotNULL(outBuffer, req_struct,
1072  ahOut, attrDes2);
1073 }
1074 
1075 bool
1076 Dbtup::readDynBigFixedSizeShrunkenNotNULL(Uint8* outBuffer,
1077  KeyReqStruct *req_struct,
1078  AttributeHeader* ahOut,
1079  Uint32 attrDes2)
1080 {
1081  Uint32 attr_descriptor= req_struct->attr_descriptor;
1082  Uint32 ind =
1083  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1084  Uint32(DD) : Uint32(MM);
1085 
1086  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1087  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
1088  ndbrequire(dyn_len!=0);
1089  Uint32 bm_len = (* bm_ptr) & DYN_BM_LEN_MASK;
1090  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1091  ndbrequire(BitmaskImpl::get(bm_len, bm_ptr, pos));
1092 
1093  /*
1094  The attribute is not NULL. Now to get the data offset, we count the number
1095  of varsize dynamic attributes prior to this one that are not NULL.
1096 
1097  We use a pre-computed bitmask to mask away all bits for fixed-sized
1098  dynamic attributes, and we also mask away the initial bitmap length byte and
1099  any trailing non-bitmap bytes to save a few conditionals.
1100  */
1101  Tablerec * regTabPtr = req_struct->tablePtrP;
1102  Uint32 *bm_mask_ptr= regTabPtr->dynVarSizeMask[ind];
1103  Uint32 bm_pos= AttributeOffset::getNullFlagOffset(attrDes2);
1104  Uint32 prevMask= (1 << (pos & 31)) - 1;
1105  Uint32 bit_count= BitmaskImpl::count_bits(prevMask & bm_mask_ptr[bm_pos] & bm_ptr[bm_pos]);
1106  for(Uint32 i=0; i<bm_pos; i++)
1107  bit_count+= BitmaskImpl::count_bits(bm_mask_ptr[i] & bm_ptr[i]);
1108 
1109  /* Now find the data pointer and length from the offset array. */
1110  Uint32 vsize_in_bytes= AttributeDescriptor::getSizeInBytes(attr_descriptor);
1111  //Uint16 *offset_array= req_struct->m_var_data[MM].m_dyn_offset_arr_ptr;
1112  Uint16* offset_array = (Uint16*)(bm_ptr + bm_len);
1113  Uint16 data_offset= offset_array[bit_count];
1114  ndbrequire(vsize_in_bytes <= Uint32(offset_array[bit_count+1]- data_offset));
1115 
1116  /*
1117  In the expanded format, we share the read code with static varsized, just
1118  using different data base pointer and offset/lenght arrays.
1119  */
1120  thrjam(req_struct->jamBuffer);
1121  return varsize_reader(outBuffer, req_struct, ahOut, attrDes2,
1122  ((char *)offset_array) + data_offset, vsize_in_bytes);
1123 }
1124 
1125 bool
1126 Dbtup::readDynBigFixedSizeShrunkenNULLable(Uint8* outBuffer,
1127  KeyReqStruct *req_struct,
1128  AttributeHeader* ahOut,
1129  Uint32 attrDes2)
1130 {
1131  Uint32 ind =
1132  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1133  Uint32(DD) : Uint32(MM);
1134 
1135  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1136  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
1137  /* Check for NULL (including the case of an empty bitmap). */
1138  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1139  if(dyn_len == 0 || dynCheckNull(dyn_len, (* bm_ptr) & DYN_BM_LEN_MASK,
1140  bm_ptr, pos))
1141  {
1142  thrjam(req_struct->jamBuffer);
1143  ahOut->setNULL();
1144  return true;
1145  }
1146 
1147  return readDynBigFixedSizeShrunkenNotNULL(outBuffer, req_struct,
1148  ahOut, attrDes2);
1149 }
1150 
1151 bool
1152 Dbtup::readDynBitsNotNULL(Uint8* outBuffer,
1153  KeyReqStruct *req_struct,
1154  AttributeHeader* ahOut,
1155  Uint32 attrDes2)
1156 {
1157  thrjam(req_struct->jamBuffer);
1158  if(req_struct->is_expanded)
1159  return readDynBitsExpandedNotNULL(outBuffer, req_struct, ahOut, attrDes2);
1160  else
1161  return readDynBitsShrunkenNotNULL(outBuffer, req_struct, ahOut, attrDes2);
1162 }
1163 
1164 bool
1165 Dbtup::readDynBitsNULLable(Uint8* outBuffer,
1166  KeyReqStruct *req_struct,
1167  AttributeHeader* ahOut,
1168  Uint32 attrDes2)
1169 {
1170  thrjam(req_struct->jamBuffer);
1171  if(req_struct->is_expanded)
1172  return readDynBitsExpandedNULLable(outBuffer, req_struct, ahOut, attrDes2);
1173  else
1174  return readDynBitsShrunkenNULLable(outBuffer, req_struct, ahOut, attrDes2);
1175 }
1176 
1177 bool
1178 Dbtup::readDynBitsShrunkenNotNULL(Uint8* outBuffer,
1179  KeyReqStruct* req_struct,
1180  AttributeHeader* ahOut,
1181  Uint32 attrDes2)
1182 {
1183  Uint32 attr_descriptor= req_struct->attr_descriptor;
1184  Uint32 ind =
1185  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1186  Uint32(DD) : Uint32(MM);
1187 
1188  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1189  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
1190  ndbrequire(dyn_len != 0);
1191  Uint32 bm_len = (* bm_ptr) & DYN_BM_LEN_MASK;
1192  Uint32 bitCount =
1193  AttributeDescriptor::getArraySize(attr_descriptor);
1194  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1195  /* Make sure we have sufficient data in the row. */
1196  ndbrequire((pos>>5)<bm_len);
1197  /* The bit data is stored just before the NULL bit. */
1198  ndbassert(pos>bitCount);
1199  pos-= bitCount;
1200 
1201  return bits_reader(outBuffer, req_struct, ahOut,
1202  bm_ptr, bm_len,
1203  pos, bitCount);
1204 }
1205 
1206 bool
1207 Dbtup::readDynBitsShrunkenNULLable(Uint8* outBuffer,
1208  KeyReqStruct* req_struct,
1209  AttributeHeader* ahOut,
1210  Uint32 attrDes2)
1211 {
1212  Uint32 ind =
1213  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1214  Uint32(DD) : Uint32(MM);
1215 
1216  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1217  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
1218  /* Check for NULL (including the case of an empty bitmap). */
1219  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1220  if(dyn_len == 0 || dynCheckNull(dyn_len, (* bm_ptr) & DYN_BM_LEN_MASK,
1221  bm_ptr, pos))
1222  {
1223  thrjam(req_struct->jamBuffer);
1224  ahOut->setNULL();
1225  return true;
1226  }
1227 
1228  return readDynBitsShrunkenNotNULL(outBuffer, req_struct, ahOut, attrDes2);
1229 }
1230 
1231 bool
1232 Dbtup::readDynBitsExpandedNotNULL(Uint8* outBuffer,
1233  KeyReqStruct* req_struct,
1234  AttributeHeader* ahOut,
1235  Uint32 attrDes2)
1236 {
1237  Uint32 attr_descriptor= req_struct->attr_descriptor;
1238  Uint32 ind =
1239  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1240  Uint32(DD) : Uint32(MM);
1241 
1242  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1243  Uint32 bm_len = (* bm_ptr) & DYN_BM_LEN_MASK;
1244  Uint32 bitCount =
1245  AttributeDescriptor::getArraySize(attr_descriptor);
1246  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1247  /* The bit data is stored just before the NULL bit. */
1248  ndbassert(pos>bitCount);
1249  pos-= bitCount;
1250 
1251  return bits_reader(outBuffer, req_struct, ahOut,
1252  bm_ptr, bm_len,
1253  pos, bitCount);
1254 }
1255 
1256 bool
1257 Dbtup::readDynBitsExpandedNULLable(Uint8* outBuffer,
1258  KeyReqStruct* req_struct,
1259  AttributeHeader* ahOut,
1260  Uint32 attrDes2)
1261 {
1262 
1263  Uint32 ind =
1264  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1265  Uint32(DD) : Uint32(MM);
1266 
1267  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1268  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1269  if(!BitmaskImpl::get((* bm_ptr) & DYN_BM_LEN_MASK, bm_ptr, pos))
1270  {
1271  thrjam(req_struct->jamBuffer);
1272  ahOut->setNULL();
1273  return true;
1274  }
1275 
1276  return readDynBitsExpandedNotNULL(outBuffer, req_struct, ahOut, attrDes2);
1277 }
1278 
1279 bool
1280 Dbtup::readDynVarSizeNotNULL(Uint8* outBuffer,
1281  KeyReqStruct *req_struct,
1282  AttributeHeader* ahOut,
1283  Uint32 attrDes2)
1284 {
1285  thrjam(req_struct->jamBuffer);
1286  if(req_struct->is_expanded)
1287  return readDynVarSizeExpandedNotNULL(outBuffer, req_struct,
1288  ahOut, attrDes2);
1289  else
1290  return readDynVarSizeShrunkenNotNULL(outBuffer, req_struct,
1291  ahOut, attrDes2);
1292 }//Dbtup::readDynBigVarSize()
1293 
1294 bool
1295 Dbtup::readDynVarSizeNULLable(Uint8* outBuffer,
1296  KeyReqStruct *req_struct,
1297  AttributeHeader* ahOut,
1298  Uint32 attrDes2)
1299 {
1300  thrjam(req_struct->jamBuffer);
1301  if(req_struct->is_expanded)
1302  return readDynVarSizeExpandedNULLable(outBuffer, req_struct,
1303  ahOut, attrDes2);
1304  else
1305  return readDynVarSizeShrunkenNULLable(outBuffer, req_struct,
1306  ahOut, attrDes2);
1307 }//Dbtup::readDynBigVarSize()
1308 
1309 bool
1310 Dbtup::readDynVarSizeExpandedNotNULL(Uint8* outBuffer,
1311  KeyReqStruct *req_struct,
1312  AttributeHeader* ahOut,
1313  Uint32 attrDes2)
1314 {
1315  /*
1316  In the expanded format, we share the read code with static varsized, just
1317  using different data base pointer and offset/lenght arrays.
1318  */
1319  thrjam(req_struct->jamBuffer);
1320  Uint32 ind =
1321  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1322  Uint32(DD) : Uint32(MM);
1323 
1324  char *src_ptr= req_struct->m_var_data[ind].m_dyn_data_ptr;
1325  Uint32 var_index= AttributeOffset::getOffset(attrDes2);
1326  Uint16* off_arr= req_struct->m_var_data[ind].m_dyn_offset_arr_ptr;
1327  Uint32 var_attr_pos= off_arr[var_index];
1328  Uint32 idx= req_struct->m_var_data[ind].m_dyn_len_offset;
1329  Uint32 vsize_in_bytes= off_arr[var_index+idx] - var_attr_pos;
1330  return varsize_reader(outBuffer, req_struct, ahOut, attrDes2,
1331  src_ptr + var_attr_pos, vsize_in_bytes);
1332 }
1333 
1334 bool
1335 Dbtup::readDynVarSizeExpandedNULLable(Uint8* outBuffer,
1336  KeyReqStruct *req_struct,
1337  AttributeHeader* ahOut,
1338  Uint32 attrDes2)
1339 {
1340  /*
1341  Check for NULL. In the expanded format, the bitmap is guaranteed
1342  to be stored in full length.
1343  */
1344 
1345  Uint32 ind =
1346  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1347  Uint32(DD) : Uint32(MM);
1348 
1349  Uint32 *src_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1350  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1351  if(!BitmaskImpl::get((* src_ptr) & DYN_BM_LEN_MASK, src_ptr, pos))
1352  {
1353  thrjam(req_struct->jamBuffer);
1354  ahOut->setNULL();
1355  return true;
1356  }
1357 
1358  return readDynVarSizeExpandedNotNULL(outBuffer, req_struct,
1359  ahOut, attrDes2);
1360 }
1361 
1362 bool
1363 Dbtup::readDynVarSizeShrunkenNotNULL(Uint8* outBuffer,
1364  KeyReqStruct *req_struct,
1365  AttributeHeader* ahOut,
1366  Uint32 attrDes2)
1367 {
1368  Uint32 ind =
1369  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1370  Uint32(DD) : Uint32(MM);
1371 
1372  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1373  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
1374  ndbrequire(dyn_len!=0);
1375  Uint32 bm_len = (* bm_ptr) & DYN_BM_LEN_MASK;
1376  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1377  ndbrequire(BitmaskImpl::get(bm_len, bm_ptr, pos));
1378 
1379  /*
1380  The attribute is not NULL. Now to get the data offset, we count the number
1381  of varsize dynamic attributes prior to this one that are not NULL.
1382 
1383  We use a pre-computed bitmask to mask away all bits for fixed-sized
1384  dynamic attributes, and we also mask away the initial bitmap length byte and
1385  any trailing non-bitmap bytes to save a few conditionals.
1386  */
1387  Tablerec * regTabPtr = req_struct->tablePtrP;
1388  Uint32 *bm_mask_ptr= regTabPtr->dynVarSizeMask[ind];
1389  Uint32 bm_pos= AttributeOffset::getNullFlagOffset(attrDes2);
1390  Uint32 prevMask= (1 << (pos & 31)) - 1;
1391  Uint32 bit_count= BitmaskImpl::count_bits(prevMask & bm_mask_ptr[bm_pos] & bm_ptr[bm_pos]);
1392  for(Uint32 i=0; i<bm_pos; i++)
1393  bit_count+= BitmaskImpl::count_bits(bm_mask_ptr[i] & bm_ptr[i]);
1394 
1395  /* Now find the data pointer and length from the offset array. */
1396  //Uint16* offset_array = req_struct->m_var_data[MM].m_dyn_offset_arr_ptr;
1397  Uint16* offset_array = (Uint16*)(bm_ptr + bm_len);
1398  Uint16 data_offset= offset_array[bit_count];
1399  Uint32 vsize_in_bytes= offset_array[bit_count+1] - data_offset;
1400 
1401  /*
1402  In the expanded format, we share the read code with static varsized, just
1403  using different data base pointer and offset/lenght arrays.
1404  */
1405  thrjam(req_struct->jamBuffer);
1406  return varsize_reader(outBuffer, req_struct, ahOut, attrDes2,
1407  ((char *)offset_array) + data_offset, vsize_in_bytes);
1408 }
1409 
1410 bool
1411 Dbtup::readDynVarSizeShrunkenNULLable(Uint8* outBuffer,
1412  KeyReqStruct *req_struct,
1413  AttributeHeader* ahOut,
1414  Uint32 attrDes2)
1415 {
1416  Uint32 ind =
1417  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
1418  Uint32(DD) : Uint32(MM);
1419 
1420  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
1421  Uint32 dyn_len= req_struct->m_var_data[ind].m_dyn_part_len;
1422  /* Check for NULL (including the case of an empty bitmap). */
1423  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1424  if(dyn_len == 0 || dynCheckNull(dyn_len, (* bm_ptr) & DYN_BM_LEN_MASK,
1425  bm_ptr, pos))
1426  {
1427  thrjam(req_struct->jamBuffer);
1428  ahOut->setNULL();
1429  return true;
1430  }
1431 
1432  return readDynVarSizeShrunkenNotNULL(outBuffer, req_struct,
1433  ahOut, attrDes2);
1434 }
1435 
1436 bool
1437 Dbtup::readDiskFixedSizeNotNULL(Uint8* outBuffer,
1438  KeyReqStruct *req_struct,
1439  AttributeHeader* ahOut,
1440  Uint32 attrDes2)
1441 {
1442  ndbassert(req_struct->out_buf_bits == 0);
1443 
1444  Uint32 attrDescriptor= req_struct->attr_descriptor;
1445  Uint32 *tuple_header= req_struct->m_disk_ptr->m_data;
1446  Uint32 indexBuf= req_struct->out_buf_index;
1447  Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
1448  Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
1449  Uint32 attrNoOfWords= (srcBytes + 3) >> 2;
1450  Uint32 maxRead= req_struct->max_read;
1451  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
1452  Uint32 newIndexBuf = indexBuf + srcBytes;
1453  Uint8* dst = (outBuffer + indexBuf);
1454  const Uint8* src = (Uint8*)(tuple_header+readOffset);
1455 
1456  ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[DD]);
1457  if (! charsetFlag || ! req_struct->xfrm_flag)
1458  {
1459  if (newIndexBuf <= maxRead)
1460  {
1461  jam();
1462  ahOut->setByteSize(srcBytes);
1463  memcpy(dst, src, srcBytes);
1464  zero32(dst, srcBytes);
1465  req_struct->out_buf_index = newIndexBuf;
1466  return true;
1467  }
1468  }
1469  else
1470  {
1471  return xfrm_reader(dst, req_struct, ahOut, attrDes2, src, srcBytes);
1472  }
1473 
1474  jam();
1475  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
1476  return false;
1477 }
1478 
1479 bool
1480 Dbtup::readDiskFixedSizeNULLable(Uint8* outBuffer,
1481  KeyReqStruct *req_struct,
1482  AttributeHeader* ahOut,
1483  Uint32 attrDes2)
1484 {
1485  if (!disk_nullFlagCheck(req_struct, attrDes2)) {
1486  jam();
1487  return readDiskFixedSizeNotNULL(outBuffer,
1488  req_struct,
1489  ahOut,
1490  attrDes2);
1491  } else {
1492  jam();
1493  ahOut->setNULL();
1494  return true;
1495  }
1496 }
1497 
1498 bool
1499 Dbtup::readDiskVarAsFixedSizeNotNULL(Uint8* outBuffer,
1500  KeyReqStruct *req_struct,
1501  AttributeHeader* ahOut,
1502  Uint32 attrDes2)
1503 {
1504  ndbassert(req_struct->out_buf_bits == 0);
1505 
1506  Uint32 attrDescriptor= req_struct->attr_descriptor;
1507  Uint32 *tuple_header= req_struct->m_disk_ptr->m_data;
1508  Uint32 indexBuf= req_struct->out_buf_index;
1509  Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
1510 
1511  Uint32 maxRead= req_struct->max_read;
1512  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
1513  Uint8* dst = (outBuffer + indexBuf);
1514  const Uint8* src = (Uint8*)(tuple_header+readOffset);
1515 
1516  Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
1517  Uint32 attrNoOfWords= (srcBytes + 3) >> 2;
1518  Uint32 newIndexBuf = indexBuf + srcBytes;
1519  Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
1520  Uint32 lb, len;
1521 
1522  if (typeId != NDB_ARRAYTYPE_FIXED &&
1523  NdbSqlUtil::get_var_length(typeId, src, srcBytes, lb, len)) {
1524  srcBytes = len + lb;
1525  newIndexBuf = indexBuf + srcBytes;
1526  attrNoOfWords= (srcBytes + 3) >> 2;
1527  }
1528 
1529  ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[DD]);
1530  if (! charsetFlag || ! req_struct->xfrm_flag)
1531  {
1532  if (newIndexBuf <= maxRead)
1533  {
1534  jam();
1535  ahOut->setByteSize(srcBytes);
1536  memcpy(dst, src, srcBytes);
1537  zero32(dst, srcBytes);
1538  req_struct->out_buf_index = newIndexBuf;
1539  return true;
1540  }
1541  }
1542  else
1543  {
1544  return xfrm_reader(dst, req_struct, ahOut, attrDes2, src, srcBytes);
1545  }
1546 
1547  jam();
1548  req_struct->errorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
1549  return false;
1550 }
1551 
1552 bool
1553 Dbtup::readDiskVarAsFixedSizeNULLable(Uint8* outBuffer,
1554  KeyReqStruct *req_struct,
1555  AttributeHeader* ahOut,
1556  Uint32 attrDes2)
1557 {
1558  if (!disk_nullFlagCheck(req_struct, attrDes2)) {
1559  jam();
1560  return readDiskVarAsFixedSizeNotNULL(outBuffer,
1561  req_struct,
1562  ahOut,
1563  attrDes2);
1564  } else {
1565  jam();
1566  ahOut->setNULL();
1567  return true;
1568  }
1569 }
1570 
1571 bool
1572 Dbtup::readDiskVarSizeNotNULL(Uint8* out_buffer,
1573  KeyReqStruct *req_struct,
1574  AttributeHeader* ah_out,
1575  Uint32 attr_des2)
1576 {
1577  ndbrequire(false);
1578  return 0;
1579 }
1580 
1581 bool
1582 Dbtup::readDiskVarSizeNULLable(Uint8* outBuffer,
1583  KeyReqStruct *req_struct,
1584  AttributeHeader* ahOut,
1585  Uint32 attrDes2)
1586 {
1587  if (!disk_nullFlagCheck(req_struct, attrDes2)) {
1588  jam();
1589  return readDiskVarSizeNotNULL(outBuffer,
1590  req_struct,
1591  ahOut,
1592  attrDes2);
1593  } else {
1594  jam();
1595  ahOut->setNULL();
1596  return true;
1597  }
1598 }
1599 
1600 bool
1601 Dbtup::readDiskBitsNotNULL(Uint8* outBuffer,
1602  KeyReqStruct* req_struct,
1603  AttributeHeader* ahOut,
1604  Uint32 attrDes2)
1605 {
1606  Tablerec * const regTabPtr = req_struct->tablePtrP;
1607  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1608  Uint32 bitCount =
1609  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
1610  Uint32 bm_len = regTabPtr->m_offsets[DD].m_null_words;
1611  Uint32* bm_ptr = req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
1612 
1613  return bits_reader(outBuffer, req_struct, ahOut,
1614  bm_ptr, bm_len,
1615  pos, bitCount);
1616 
1617 }
1618 
1619 bool
1620 Dbtup::readDiskBitsNULLable(Uint8* outBuffer,
1621  KeyReqStruct* req_struct,
1622  AttributeHeader* ahOut,
1623  Uint32 attrDes2)
1624 {
1625  Tablerec * const regTabPtr = req_struct->tablePtrP;
1626  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
1627  Uint32 bitCount =
1628  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
1629 
1630  Uint32 bm_len = regTabPtr->m_offsets[DD].m_null_words;
1631  Uint32 *bm_ptr= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
1632 
1633  if(BitmaskImpl::get(bm_len, bm_ptr, pos))
1634  {
1635  jam();
1636  ahOut->setNULL();
1637  return true;
1638  }
1639 
1640  return bits_reader(outBuffer, req_struct, ahOut,
1641  bm_ptr, bm_len,
1642  pos+1, bitCount);
1643 }
1644 
1645 
1646 
1647 /* ---------------------------------------------------------------------- */
1648 /* THIS ROUTINE IS USED TO UPDATE A NUMBER OF ATTRIBUTES. IT IS */
1649 /* USED BY THE INSERT ROUTINE, THE UPDATE ROUTINE AND IT CAN BE */
1650 /* CALLED SEVERAL TIMES FROM THE INTERPRETER. */
1651 // In addition to the parameters used in the call it also relies on the
1652 // following variables set-up properly.
1653 //
1654 // operPtr.p Operation record pointer
1655 // tabptr.p Table record pointer
1656 /* ---------------------------------------------------------------------- */
1657 int Dbtup::updateAttributes(KeyReqStruct *req_struct,
1658  Uint32* inBuffer,
1659  Uint32 inBufLen)
1660 {
1661  Tablerec * const regTabPtr = req_struct->tablePtrP;
1662  Operationrec* const regOperPtr = req_struct->operPtrP;
1663  Uint32 numAttributes= regTabPtr->m_no_of_attributes;
1664  TableDescriptor *attr_descr= req_struct->attr_descr;
1665 
1666  Uint32 inBufIndex= 0;
1667  req_struct->in_buf_index= 0;
1668  req_struct->in_buf_len= inBufLen;
1669 
1670  while (inBufIndex < inBufLen) {
1671  AttributeHeader ahIn(inBuffer[inBufIndex]);
1672  Uint32 attributeId= ahIn.getAttributeId();
1673  Uint32 attrDescriptorIndex= attributeId << ZAD_LOG_SIZE;
1674  if (likely(attributeId < numAttributes)) {
1675  Uint32 attrDescriptor= attr_descr[attrDescriptorIndex].tabDescr;
1676  Uint32 attributeOffset= attr_descr[attrDescriptorIndex + 1].tabDescr;
1677  if ((AttributeDescriptor::getPrimaryKey(attrDescriptor)) &&
1678  (regOperPtr->op_struct.op_type != ZINSERT)) {
1679  if (checkUpdateOfPrimaryKey(req_struct,
1680  &inBuffer[inBufIndex],
1681  regTabPtr)) {
1682  jam();
1683  return -ZTRY_UPDATE_PRIMARY_KEY;
1684  }
1685  }
1686  UpdateFunction f= regTabPtr->updateFunctionArray[attributeId];
1687  jam();
1688  req_struct->attr_descriptor= attrDescriptor;
1689  req_struct->changeMask.set(attributeId);
1690  if ((this->*f)(inBuffer,
1691  req_struct,
1692  attributeOffset)) {
1693  inBufIndex= req_struct->in_buf_index;
1694  continue;
1695  } else {
1696  jam();
1697  return -(int)req_struct->errorCode;
1698  }
1699  }
1700  else if(attributeId == AttributeHeader::READ_LCP)
1701  {
1702  Uint32 sz= ahIn.getDataSize();
1703  update_lcp(req_struct, inBuffer+inBufIndex+1, sz);
1704  inBufIndex += 1 + sz;
1705  req_struct->in_buf_index = inBufIndex;
1706  }
1707  else if (attributeId == AttributeHeader::READ_PACKED)
1708  {
1709  Uint32 sz = update_packed(req_struct, inBuffer+inBufIndex);
1710  inBufIndex += 1 + sz;
1711  req_struct->in_buf_index = inBufIndex;
1712  }
1713  else if(attributeId == AttributeHeader::DISK_REF)
1714  {
1715  jam();
1716  Uint32 sz= ahIn.getDataSize();
1717  ndbrequire(sz == 2);
1718  req_struct->m_tuple_ptr->m_header_bits |= Tuple_header::DISK_PART;
1719  memcpy(req_struct->m_tuple_ptr->get_disk_ref_ptr(regTabPtr),
1720  inBuffer+inBufIndex+1, sz << 2);
1721  inBufIndex += 1 + sz;
1722  req_struct->in_buf_index = inBufIndex;
1723  }
1724  else if(attributeId == AttributeHeader::ANY_VALUE)
1725  {
1726  jam();
1727  Uint32 sz= ahIn.getDataSize();
1728  ndbrequire(sz == 1);
1729  regOperPtr->m_any_value = * (inBuffer + inBufIndex + 1);
1730  inBufIndex += 1 + sz;
1731  req_struct->in_buf_index = inBufIndex;
1732  }
1733  else if(attributeId == AttributeHeader::OPTIMIZE)
1734  {
1735  jam();
1736  Uint32 sz= ahIn.getDataSize();
1737  ndbrequire(sz == 1);
1741  req_struct->optimize_options = * (inBuffer + inBufIndex + 1);
1742  req_struct->optimize_options &=
1743  AttributeHeader::OPTIMIZE_OPTIONS_MASK;
1744  inBufIndex += 1 + sz;
1745  req_struct->in_buf_index = inBufIndex;
1746  }
1747  else if (attributeId == AttributeHeader::ROW_AUTHOR)
1748  {
1749  jam();
1750  Uint32 sz= ahIn.getDataSize();
1751  ndbrequire(sz == 1);
1752 
1753  Uint32 value = * (inBuffer + inBufIndex + 1);
1754  Uint32 attrId =
1755  regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
1756 
1757  if (unlikely(!(regTabPtr->m_bits & Tablerec::TR_ExtraRowAuthorBits)))
1758  {
1759  return -ZATTRIBUTE_ID_ERROR;
1760  }
1761 
1762  if (unlikely(store_extra_row_bits(attrId, regTabPtr,
1763  req_struct->m_tuple_ptr,
1764  value, /* truncate */ false) == false))
1765  {
1766  return -ZAI_INCONSISTENCY_ERROR;
1767  }
1768  inBufIndex += 1 + sz;
1769  req_struct->in_buf_index = inBufIndex;
1770  }
1771  else if (attributeId == AttributeHeader::ROW_GCI64)
1772  {
1773  jam();
1774  Uint32 sz= ahIn.getDataSize();
1775  ndbrequire(sz == 2);
1776  Uint32 attrId =
1777  regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>();
1778  Uint32 gciLo = * (inBuffer + inBufIndex + 1);
1779  Uint32 gciHi = * (inBuffer + inBufIndex + 2);
1780 
1781  if (unlikely(!(regTabPtr->m_bits & Tablerec::TR_RowGCI)))
1782  {
1783  return -ZATTRIBUTE_ID_ERROR;
1784  }
1785 
1786  /* Record that GCI has been set explicitly */
1787  regOperPtr->op_struct.m_gci_written = 1;
1788 
1789  *req_struct->m_tuple_ptr->get_mm_gci(regTabPtr) = gciHi;
1790 
1791  if (regTabPtr->m_bits & Tablerec::TR_ExtraRowGCIBits)
1792  {
1793  if (unlikely(store_extra_row_bits(attrId, regTabPtr,
1794  req_struct->m_tuple_ptr,
1795  gciLo, /*truncate*/ true) == false))
1796  {
1797  return -ZAI_INCONSISTENCY_ERROR;
1798  }
1799  }
1800 
1801  inBufIndex+= 1 + sz;
1802  req_struct->in_buf_index = inBufIndex;
1803  }
1804  else
1805  {
1806  jam();
1807  return -(int)req_struct->errorCode;
1808  }
1809  }
1810  return 0;
1811 }
1812 
1813 bool
1814 Dbtup::checkUpdateOfPrimaryKey(KeyReqStruct* req_struct,
1815  Uint32* updateBuffer,
1816  Tablerec* const regTabPtr)
1817 {
1818  Uint32 keyReadBuffer[MAX_KEY_SIZE_IN_WORDS];
1819  TableDescriptor* attr_descr = req_struct->attr_descr;
1820  AttributeHeader ahIn(*updateBuffer);
1821  Uint32 attributeId = ahIn.getAttributeId();
1822  Uint32 attrDescriptorIndex = attributeId << ZAD_LOG_SIZE;
1823  Uint32 attrDescriptor = attr_descr[attrDescriptorIndex].tabDescr;
1824  Uint32 attributeOffset = attr_descr[attrDescriptorIndex + 1].tabDescr;
1825 
1826  Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
1827  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset);
1828  if (charsetFlag) {
1829  Uint32 csIndex = AttributeOffset::getCharsetPos(attributeOffset);
1830  CHARSET_INFO* cs = regTabPtr->charsetArray[csIndex];
1831  Uint32 srcPos = 0;
1832  Uint32 dstPos = 0;
1833  xfrm_attr(attrDescriptor, cs, &updateBuffer[1], srcPos,
1834  &xfrmBuffer[1], dstPos, MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY);
1835  ahIn.setDataSize(dstPos);
1836  xfrmBuffer[0] = ahIn.m_value;
1837  updateBuffer = xfrmBuffer;
1838  }
1839 
1840  ReadFunction f = regTabPtr->readFunctionArray[attributeId];
1841 
1842  AttributeHeader attributeHeader(attributeId, 0);
1843  req_struct->out_buf_index = 0;
1844  req_struct->out_buf_bits = 0;
1845  req_struct->max_read = sizeof(keyReadBuffer);
1846  req_struct->attr_descriptor = attrDescriptor;
1847 
1848  bool tmp = req_struct->xfrm_flag;
1849  req_struct->xfrm_flag = true;
1850  ndbrequire((this->*f)((Uint8*)keyReadBuffer,
1851  req_struct,
1852  &attributeHeader,
1853  attributeOffset));
1854  req_struct->xfrm_flag = tmp;
1855 
1856  ndbrequire(req_struct->out_buf_index == attributeHeader.getByteSize());
1857  if (ahIn.getDataSize() != attributeHeader.getDataSize()) {
1858  jam();
1859  return true;
1860  }
1861  if (memcmp(&keyReadBuffer[0],
1862  &updateBuffer[1],
1863  req_struct->out_buf_index) != 0) {
1864  jam();
1865  return true;
1866  }
1867  return false;
1868 }
1869 
1870 bool
1871 Dbtup::updateFixedSizeTHOneWordNotNULL(Uint32* inBuffer,
1872  KeyReqStruct *req_struct,
1873  Uint32 attrDes2)
1874 {
1875  Uint32 indexBuf= req_struct->in_buf_index;
1876  Uint32 inBufLen= req_struct->in_buf_len;
1877  Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
1878  AttributeHeader ahIn(inBuffer[indexBuf]);
1879  Uint32 nullIndicator= ahIn.isNULL();
1880  Uint32 newIndex= indexBuf + 2;
1881  Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
1882  ndbrequire(updateOffset < req_struct->check_offset[MM]);
1883 
1884  if (newIndex <= inBufLen) {
1885  Uint32 updateWord= inBuffer[indexBuf + 1];
1886  if (!nullIndicator) {
1887  jam();
1888  req_struct->in_buf_index= newIndex;
1889  tuple_header[updateOffset]= updateWord;
1890  return true;
1891  } else {
1892  jam();
1893  req_struct->errorCode = ZNOT_NULL_ATTR;
1894  return false;
1895  }
1896  } else {
1897  jam();
1898  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
1899  return false;
1900  }
1901  return true;
1902 }
1903 
1904 bool
1905 Dbtup::updateFixedSizeTHTwoWordNotNULL(Uint32* inBuffer,
1906  KeyReqStruct *req_struct,
1907  Uint32 attrDes2)
1908 {
1909  Uint32 indexBuf= req_struct->in_buf_index;
1910  Uint32 inBufLen= req_struct->in_buf_len;
1911  Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
1912  AttributeHeader ahIn(inBuffer[indexBuf]);
1913  Uint32 nullIndicator= ahIn.isNULL();
1914  Uint32 newIndex= indexBuf + 3;
1915  Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
1916  ndbrequire((updateOffset + 1) < req_struct->check_offset[MM]);
1917 
1918  if (newIndex <= inBufLen) {
1919  Uint32 updateWord1= inBuffer[indexBuf + 1];
1920  Uint32 updateWord2= inBuffer[indexBuf + 2];
1921  if (!nullIndicator) {
1922  jam();
1923  req_struct->in_buf_index= newIndex;
1924  tuple_header[updateOffset]= updateWord1;
1925  tuple_header[updateOffset + 1]= updateWord2;
1926  return true;
1927  } else {
1928  jam();
1929  req_struct->errorCode = ZNOT_NULL_ATTR;
1930  return false;
1931  }
1932  } else {
1933  jam();
1934  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
1935  return false;
1936  }
1937 }
1938 
1939 bool
1940 Dbtup::fixsize_updater(Uint32* inBuffer,
1941  KeyReqStruct *req_struct,
1942  Uint32 attrDes2,
1943  Uint32 *dst_ptr,
1944  Uint32 updateOffset,
1945  Uint32 checkOffset)
1946 {
1947  Uint32 attrDescriptor= req_struct->attr_descriptor;
1948  Uint32 indexBuf= req_struct->in_buf_index;
1949  Uint32 inBufLen= req_struct->in_buf_len;
1950  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
1951 
1952  AttributeHeader ahIn(inBuffer[indexBuf]);
1953  Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
1954  Uint32 nullIndicator= ahIn.isNULL();
1955  Uint32 newIndex= indexBuf + noOfWords + 1;
1956  ndbrequire((updateOffset + noOfWords - 1) < checkOffset);
1957 
1958  if (newIndex <= inBufLen) {
1959  if (!nullIndicator) {
1960  jam();
1961  if (charsetFlag) {
1962  jam();
1963  Tablerec * regTabPtr = req_struct->tablePtrP;
1964  Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
1965  Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
1966  Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
1967  ndbrequire(i < regTabPtr->noOfCharsets);
1968  // not const in MySQL
1969  CHARSET_INFO* cs = regTabPtr->charsetArray[i];
1970  int not_used;
1971  const char* ssrc = (const char*)&inBuffer[indexBuf + 1];
1972  Uint32 lb, len;
1973  if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
1974  jam();
1975  req_struct->errorCode = ZINVALID_CHAR_FORMAT;
1976  return false;
1977  }
1978  // fast fix bug#7340
1979  if (typeId != NDB_TYPE_TEXT &&
1980  (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, &not_used) != len) {
1981  jam();
1982  req_struct->errorCode = ZINVALID_CHAR_FORMAT;
1983  return false;
1984  }
1985  }
1986  req_struct->in_buf_index= newIndex;
1987  MEMCOPY_NO_WORDS(&(dst_ptr[updateOffset]),
1988  &inBuffer[indexBuf + 1],
1989  noOfWords);
1990 
1991  return true;
1992  } else {
1993  jam();
1994  req_struct->errorCode = ZNOT_NULL_ATTR;
1995  return false;
1996  }
1997  } else {
1998  jam();
1999  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2000  return false;
2001  }
2002 }
2003 
2004 bool
2005 Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
2006  KeyReqStruct *req_struct,
2007  Uint32 attrDes2)
2008 {
2009  Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
2010  Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
2011  Uint32 checkOffset= req_struct->check_offset[MM];
2012  return fixsize_updater(inBuffer, req_struct, attrDes2, tuple_header,
2013  updateOffset, checkOffset);
2014 }
2015 
2016 bool
2017 Dbtup::updateFixedSizeTHManyWordNULLable(Uint32* inBuffer,
2018  KeyReqStruct *req_struct,
2019  Uint32 attrDes2)
2020 {
2021  Tablerec * const regTabPtr = req_struct->tablePtrP;
2022  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
2023  Uint32 nullIndicator= ahIn.isNULL();
2024  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2025  Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
2026 
2027  if (!nullIndicator) {
2028  jam();
2029  BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
2030  return updateFixedSizeTHManyWordNotNULL(inBuffer,
2031  req_struct,
2032  attrDes2);
2033  } else {
2034  Uint32 newIndex= req_struct->in_buf_index + 1;
2035  if (newIndex <= req_struct->in_buf_len) {
2036  BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
2037  jam();
2038  req_struct->in_buf_index= newIndex;
2039  return true;
2040  } else {
2041  jam();
2042  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2043  return false;
2044  }
2045  }
2046 }
2047 
2048 bool
2049 Dbtup::updateVarSizeNotNULL(Uint32* in_buffer,
2050  KeyReqStruct *req_struct,
2051  Uint32 attr_des2)
2052 {
2053  Uint32 var_index;
2054  char *var_data_start= req_struct->m_var_data[MM].m_data_ptr;
2055  var_index= AttributeOffset::getOffset(attr_des2);
2056  Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
2057  Uint16 *vpos_array= req_struct->m_var_data[MM].m_offset_array_ptr;
2058  Uint16 offset= vpos_array[var_index];
2059  Uint16 *len_offset_ptr= &(vpos_array[var_index+idx]);
2060  return varsize_updater(in_buffer, req_struct, var_data_start,
2061  offset, len_offset_ptr,
2062  req_struct->m_var_data[MM].m_max_var_offset);
2063 }
2064 bool
2065 Dbtup::varsize_updater(Uint32* in_buffer,
2066  KeyReqStruct *req_struct,
2067  char *var_data_start,
2068  Uint32 var_attr_pos,
2069  Uint16 *len_offset_ptr,
2070  Uint32 check_offset)
2071 {
2072  Uint32 attr_descriptor, index_buf, in_buf_len, null_ind;
2073  Uint32 vsize_in_words, new_index, max_var_size;
2074 
2075  attr_descriptor= req_struct->attr_descriptor;
2076  index_buf= req_struct->in_buf_index;
2077  in_buf_len= req_struct->in_buf_len;
2078  AttributeHeader ahIn(in_buffer[index_buf]);
2079  null_ind= ahIn.isNULL();
2080  Uint32 size_in_bytes = ahIn.getByteSize();
2081  vsize_in_words= (size_in_bytes + 3) >> 2;
2082  max_var_size= AttributeDescriptor::getSizeInBytes(attr_descriptor);
2083  Uint32 arrayType = AttributeDescriptor::getArrayType(attr_descriptor);
2084  new_index= index_buf + vsize_in_words + 1;
2085 
2086  Uint32 dataLen = size_in_bytes;
2087  const Uint8 * src = (const Uint8*)&in_buffer[index_buf + 1];
2088 
2089  if (new_index <= in_buf_len && size_in_bytes <= max_var_size)
2090  {
2091  if (!null_ind) {
2092  jam();
2093 
2094  if (arrayType == NDB_ARRAYTYPE_SHORT_VAR)
2095  {
2096  dataLen = 1 + src[0];
2097  }
2098  else if (arrayType == NDB_ARRAYTYPE_MEDIUM_VAR)
2099  {
2100  dataLen = 2 + src[0] + 256 * Uint32(src[1]);
2101  }
2102 
2103  if (dataLen == size_in_bytes)
2104  {
2105  *len_offset_ptr= var_attr_pos+size_in_bytes;
2106  req_struct->in_buf_index= new_index;
2107 
2108  ndbrequire(var_attr_pos+size_in_bytes <= check_offset);
2109  memcpy(var_data_start+var_attr_pos, src, size_in_bytes);
2110  return true;
2111  }
2112  jam();
2113  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2114  return false;
2115  }
2116 
2117  jam();
2118  req_struct->errorCode = ZNOT_NULL_ATTR;
2119  return false;
2120  }
2121 
2122  jam();
2123  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2124  return false;
2125 }
2126 
2127 bool
2128 Dbtup::updateVarSizeNULLable(Uint32* inBuffer,
2129  KeyReqStruct *req_struct,
2130  Uint32 attrDes2)
2131 {
2132  Tablerec * const regTabPtr = req_struct->tablePtrP;
2133  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
2134  Uint32 nullIndicator= ahIn.isNULL();
2135  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2136  Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
2137  Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
2138 
2139  if (!nullIndicator) {
2140  jam();
2141  BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
2142  return updateVarSizeNotNULL(inBuffer,
2143  req_struct,
2144  attrDes2);
2145  } else {
2146  Uint32 newIndex= req_struct->in_buf_index + 1;
2147  Uint32 var_index= AttributeOffset::getOffset(attrDes2);
2148  Uint32 var_pos= req_struct->var_pos_array[var_index];
2149  if (newIndex <= req_struct->in_buf_len) {
2150  jam();
2151  BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
2152  req_struct->var_pos_array[var_index+idx]= var_pos;
2153  req_struct->in_buf_index= newIndex;
2154  return true;
2155  } else {
2156  jam();
2157  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2158  return false;
2159  }
2160  }
2161 }
2162 
2163 bool
2164 Dbtup::updateDynFixedSizeNotNULL(Uint32* inBuffer,
2165  KeyReqStruct *req_struct,
2166  Uint32 attrDes2)
2167 {
2168  Uint32 attrDescriptor= req_struct->attr_descriptor;
2169  Uint32 ind =
2170  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2171  Uint32(DD) : Uint32(MM);
2172 
2173  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2174  Uint32 nullbits= AttributeDescriptor::getSizeInWords(attrDescriptor);
2175 
2176  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
2177  ndbassert(nullbits && nullbits <= 16);
2178 
2179  /*
2180  Compute two 16-bit bitmasks and a 16-bit aligned bitmap offset for setting
2181  all the null bits for the fixed-size dynamic attribute.
2182  There are at most 16 bits (corresponding to 64 bytes fixsize; longer
2183  attributes are stored more efficiently as varsize internally anyway).
2184  */
2185 
2186  Uint32 bm_idx= (pos >> 5);
2187  /* Store bits in little-endian so fit with length byte and trailing padding*/
2188  Uint64 bm_mask = ((Uint64(1) << nullbits) - 1) << (pos & 31);
2189  Uint32 bm_mask1 = (Uint32)(bm_mask & 0xFFFFFFFF);
2190  Uint32 bm_mask2 = (Uint32)(bm_mask >> 32);
2191 
2192  jam();
2193  /* Set all the bits in the NULL bitmap. */
2194  bm_ptr[bm_idx]|= bm_mask1;
2195  /*
2196  It is possible that bm_ptr[bm_idx+1] points off the end of the
2197  bitmap. But in that case, we are merely ANDing all ones into the offset
2198  array (no-op), cheaper than a conditional.
2199  */
2200  bm_ptr[bm_idx+1]|= bm_mask2;
2201 
2202  /* Compute the data and offset location and write the actual data. */
2203  Uint32 off_index= AttributeOffset::getOffset(attrDes2);
2204  Uint16* off_arr= req_struct->m_var_data[ind].m_dyn_offset_arr_ptr;
2205  Uint32 offset= off_arr[off_index];
2206  Uint32 *dst_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
2207  Uint32 check_offset= req_struct->m_var_data[ind].m_max_dyn_offset;
2208 
2209  ndbassert((offset&3)==0);
2210  ndbassert((check_offset&3)==0);
2211  bool result= fixsize_updater(inBuffer, req_struct, attrDes2, dst_ptr,
2212  (offset>>2), (check_offset>>2));
2213  return result;
2214 }
2215 
2216 bool
2217 Dbtup::updateDynFixedSizeNULLable(Uint32* inBuffer,
2218  KeyReqStruct *req_struct,
2219  Uint32 attrDes2)
2220 {
2221  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
2222  Uint32 nullIndicator= ahIn.isNULL();
2223 
2224  if(!nullIndicator)
2225  return updateDynFixedSizeNotNULL(inBuffer, req_struct, attrDes2);
2226 
2227  Uint32 attrDescriptor= req_struct->attr_descriptor;
2228  Uint32 ind =
2229  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2230  Uint32(DD) : Uint32(MM);
2231 
2232  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2233  Uint32 nullbits= AttributeDescriptor::getSizeInWords(attrDescriptor);
2234  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
2235 
2236  ndbassert(nullbits && nullbits <= 16);
2237 
2238  /*
2239  Compute two 16-bit bitmasks and a 16-bit aligned bitmap offset for
2240  clearing all the null bits for the fixed-size dynamic attribute.
2241  There are at most 16 bits (corresponding to 64 bytes fixsize; longer
2242  attributes are stored more efficiently as varsize internally anyway).
2243  */
2244 
2245  Uint32 bm_idx= (pos >> 5);
2246  /* Store bits in little-endian so fit with length byte and trailing padding*/
2247  Uint64 bm_mask = ~(((Uint64(1) << nullbits) - 1) << (pos & 31));
2248  Uint32 bm_mask1 = (Uint32)(bm_mask & 0xFFFFFFFF);
2249  Uint32 bm_mask2 = (Uint32)(bm_mask >> 32);
2250 
2251  Uint32 newIndex= req_struct->in_buf_index + 1;
2252  if (newIndex <= req_struct->in_buf_len) {
2253  jam();
2254  /* Clear the bits in the NULL bitmap. */
2255  bm_ptr[bm_idx] &= bm_mask1;
2256  bm_ptr[bm_idx+1] &= bm_mask2;
2257  req_struct->in_buf_index= newIndex;
2258  return true;
2259  } else {
2260  jam();
2261  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2262  return false;
2263  }
2264 }
2265 
2266 /* Update a big dynamic fixed-size column, stored internally as varsize. */
2267 bool
2268 Dbtup::updateDynBigFixedSizeNotNULL(Uint32* inBuffer,
2269  KeyReqStruct *req_struct,
2270  Uint32 attrDes2)
2271 {
2272  Uint32 attrDescriptor= req_struct->attr_descriptor;
2273  Uint32 ind =
2274  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2275  Uint32(DD) : Uint32(MM);
2276 
2277  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2278  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
2279 
2280  jam();
2281  BitmaskImpl::set((* bm_ptr) & DYN_BM_LEN_MASK, bm_ptr, pos);
2282  /* Compute the data and offset location and write the actual data. */
2283  Uint32 off_index= AttributeOffset::getOffset(attrDes2);
2284  Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
2285  Uint16* off_arr= req_struct->m_var_data[ind].m_dyn_offset_arr_ptr;
2286  Uint32 offset= off_arr[off_index];
2287  Uint32 idx= req_struct->m_var_data[ind].m_dyn_len_offset;
2288 
2289  ndbassert((offset&3)==0);
2290  bool res= fixsize_updater(inBuffer,
2291  req_struct,
2292  attrDes2,
2293  bm_ptr,
2294  offset>>2,
2295  req_struct->m_var_data[ind].m_max_dyn_offset);
2296  /* Set the correct size for fixsize data. */
2297  off_arr[off_index+idx]= offset+(noOfWords<<2);
2298  return res;
2299 }
2300 
2301 bool
2302 Dbtup::updateDynBigFixedSizeNULLable(Uint32* inBuffer,
2303  KeyReqStruct *req_struct,
2304  Uint32 attrDes2)
2305 {
2306  Uint32 ind =
2307  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2308  Uint32(DD) : Uint32(MM);
2309 
2310  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
2311  Uint32 nullIndicator= ahIn.isNULL();
2312  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2313  Uint32 *bm_ptr= (Uint32*)req_struct->m_var_data[ind].m_dyn_data_ptr;
2314 
2315  if (!nullIndicator)
2316  return updateDynBigFixedSizeNotNULL(inBuffer, req_struct, attrDes2);
2317 
2318  Uint32 newIndex= req_struct->in_buf_index + 1;
2319  if (newIndex <= req_struct->in_buf_len) {
2320  jam();
2321  BitmaskImpl::clear((* bm_ptr) & DYN_BM_LEN_MASK, bm_ptr, pos);
2322  req_struct->in_buf_index= newIndex;
2323  return true;
2324  } else {
2325  jam();
2326  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2327  return false;
2328  }
2329 }
2330 
2331 bool
2332 Dbtup::updateDynBitsNotNULL(Uint32* inBuffer,
2333  KeyReqStruct *req_struct,
2334  Uint32 attrDes2)
2335 {
2336  Uint32 attrDescriptor= req_struct->attr_descriptor;
2337  Uint32 ind =
2338  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2339  Uint32(DD) : Uint32(MM);
2340 
2341  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2342  Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
2343  Uint32 *bm_ptr= (Uint32 *)(req_struct->m_var_data[ind].m_dyn_data_ptr);
2344  Uint32 bm_len = (* bm_ptr) & DYN_BM_LEN_MASK;
2345  jam();
2346  BitmaskImpl::set(bm_len, bm_ptr, pos);
2347 
2348  Uint32 indexBuf= req_struct->in_buf_index;
2349  Uint32 inBufLen= req_struct->in_buf_len;
2350  AttributeHeader ahIn(inBuffer[indexBuf]);
2351  Uint32 nullIndicator = ahIn.isNULL();
2352  Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
2353 
2354  if (newIndex <= inBufLen) {
2355  if (!nullIndicator) {
2356  ndbassert(pos>=bitCount);
2357  BitmaskImpl::setField(bm_len, bm_ptr, pos-bitCount, bitCount,
2358  inBuffer+indexBuf+1);
2359  req_struct->in_buf_index= newIndex;
2360  return true;
2361  } else {
2362  jam();
2363  req_struct->errorCode = ZNOT_NULL_ATTR;
2364  return false;
2365  }//if
2366  } else {
2367  jam();
2368  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2369  return false;
2370  }//if
2371  return true;
2372 }
2373 
2374 bool
2375 Dbtup::updateDynBitsNULLable(Uint32* inBuffer,
2376  KeyReqStruct *req_struct,
2377  Uint32 attrDes2)
2378 {
2379  Uint32 ind =
2380  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2381  Uint32(DD) : Uint32(MM);
2382 
2383  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
2384  Uint32 nullIndicator= ahIn.isNULL();
2385 
2386  if(!nullIndicator)
2387  return updateDynBitsNotNULL(inBuffer, req_struct, attrDes2);
2388 
2389  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2390  Uint32 *bm_ptr= (Uint32*)req_struct->m_var_data[ind].m_dyn_data_ptr;
2391 
2392  Uint32 newIndex= req_struct->in_buf_index + 1;
2393  if (newIndex <= req_struct->in_buf_len) {
2394  jam();
2395  BitmaskImpl::clear((* bm_ptr) & DYN_BM_LEN_MASK, bm_ptr, pos);
2396  req_struct->in_buf_index= newIndex;
2397  return true;
2398  } else {
2399  jam();
2400  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2401  return false;
2402  }
2403 }
2404 
2405 bool
2406 Dbtup::updateDynVarSizeNotNULL(Uint32* inBuffer,
2407  KeyReqStruct *req_struct,
2408  Uint32 attrDes2)
2409 {
2410  Uint32 ind =
2411  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2412  Uint32(DD) : Uint32(MM);
2413 
2414  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2415  Uint32 *bm_ptr= (Uint32*)req_struct->m_var_data[ind].m_dyn_data_ptr;
2416 
2417  jam();
2418  BitmaskImpl::set((* bm_ptr) & DYN_BM_LEN_MASK, bm_ptr, pos);
2419  /* Compute the data and offset location and write the actual data. */
2420  Uint32 off_index= AttributeOffset::getOffset(attrDes2);
2421  Uint16* off_arr= req_struct->m_var_data[ind].m_dyn_offset_arr_ptr;
2422  Uint32 offset= off_arr[off_index];
2423  Uint32 idx= req_struct->m_var_data[ind].m_dyn_len_offset;
2424 
2425  bool res= varsize_updater(inBuffer,
2426  req_struct,
2427  (char*)bm_ptr,
2428  offset,
2429  &(off_arr[off_index+idx]),
2430  req_struct->m_var_data[ind].m_max_dyn_offset);
2431  return res;
2432 }
2433 
2434 bool
2435 Dbtup::updateDynVarSizeNULLable(Uint32* inBuffer,
2436  KeyReqStruct *req_struct,
2437  Uint32 attrDes2)
2438 {
2439  Uint32 ind =
2440  (AttributeDescriptor::getDiskBased(req_struct->attr_descriptor)) ?
2441  Uint32(DD) : Uint32(MM);
2442 
2443  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
2444  Uint32 nullIndicator= ahIn.isNULL();
2445  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
2446  Uint32 *bm_ptr= (Uint32*)req_struct->m_var_data[ind].m_dyn_data_ptr;
2447 
2448  if (!nullIndicator)
2449  return updateDynVarSizeNotNULL(inBuffer, req_struct, attrDes2);
2450 
2451  Uint32 newIndex= req_struct->in_buf_index + 1;
2452  if (newIndex <= req_struct->in_buf_len) {
2453  jam();
2454  BitmaskImpl::clear((* bm_ptr) & DYN_BM_LEN_MASK, bm_ptr, pos);
2455  req_struct->in_buf_index= newIndex;
2456  return true;
2457  } else {
2458  jam();
2459  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2460  return false;
2461  }
2462 }
2463 
2464 int
2465 Dbtup::read_pseudo(const Uint32 * inBuffer, Uint32 inPos,
2466  KeyReqStruct *req_struct,
2467  Uint32* outBuf)
2468 {
2469  ndbassert(inPos);
2470  ndbassert(req_struct->out_buf_index);
2471  ndbassert(req_struct->out_buf_bits == 0);
2472  ndbassert((req_struct->out_buf_index & 3) == 0);
2473 
2474  Uint32 attrId = (* (inBuffer + inPos - 1)) >> 16;
2475  Uint32 outPos = req_struct->out_buf_index;
2476  Uint32* outBuffer = outBuf + ((outPos - 1) >> 2);
2477 
2478  Uint32 sz;
2479  const Uint32 DataSz = MAX_INDEX_STAT_KEY_SIZE;
2480  SignalT<DataSz> signalT;
2481  Signal * signal = new (&signalT) Signal(0);
2482  bzero(signal, sizeof(signalT));
2483  switch(attrId){
2484  case AttributeHeader::READ_LCP:
2485  return read_lcp(inBuffer, inPos, req_struct, outBuf);
2486  case AttributeHeader::READ_PACKED:
2487  case AttributeHeader::READ_ALL:
2488  return (int)read_packed(inBuffer, inPos, req_struct, outBuf);
2489  case AttributeHeader::FRAGMENT:
2490  outBuffer[1] = req_struct->fragPtrP->fragmentId;
2491  sz = 1;
2492  break;
2493  case AttributeHeader::FRAGMENT_FIXED_MEMORY:
2494  {
2495  Uint64 tmp = req_struct->fragPtrP->noOfPages;
2496  tmp*= 32768;
2497  memcpy(outBuffer + 1, &tmp, 8);
2498  sz = 2;
2499  break;
2500  }
2501  case AttributeHeader::FRAGMENT_VARSIZED_MEMORY:
2502  {
2503  Uint64 tmp= req_struct->fragPtrP->noOfVarPages;
2504  tmp*= 32768;
2505  memcpy(outBuffer + 1, &tmp, 8);
2506  sz = 2;
2507  break;
2508  }
2509  case AttributeHeader::ROW_SIZE:
2510  outBuffer[1] = req_struct->tablePtrP->m_offsets[MM].m_fix_header_size << 2;
2511  sz = 1;
2512  break;
2513  case AttributeHeader::ROW_COUNT:
2514  case AttributeHeader::COMMIT_COUNT:
2515  signal->theData[0] = req_struct->operPtrP->userpointer;
2516  signal->theData[1] = attrId;
2517 
2518  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2519  outBuffer[1] = signal->theData[0];
2520  outBuffer[2] = signal->theData[1];
2521  sz = 2;
2522  break;
2523  case AttributeHeader::RANGE_NO:
2524  signal->theData[0] = req_struct->operPtrP->userpointer;
2525  signal->theData[1] = attrId;
2526 
2527  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2528  outBuffer[1] = signal->theData[0];
2529  sz = 1;
2530  break;
2531  case AttributeHeader::DISK_REF:
2532  {
2533  Uint32 *ref= req_struct->m_tuple_ptr->get_disk_ref_ptr(req_struct->tablePtrP);
2534  outBuffer[1] = ref[0];
2535  outBuffer[2] = ref[1];
2536  sz = 2;
2537  break;
2538  }
2539  case AttributeHeader::RECORDS_IN_RANGE:
2540  signal->theData[0] = req_struct->operPtrP->userpointer;
2541  signal->theData[1] = attrId;
2542 
2543  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2544  outBuffer[1] = signal->theData[0];
2545  outBuffer[2] = signal->theData[1];
2546  outBuffer[3] = signal->theData[2];
2547  outBuffer[4] = signal->theData[3];
2548  sz = 4;
2549  break;
2550  case AttributeHeader::INDEX_STAT_KEY:
2551  case AttributeHeader::INDEX_STAT_VALUE:
2552  {
2553  signal->theData[0] = req_struct->operPtrP->userpointer;
2554  signal->theData[1] = attrId;
2555 
2556  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2557 
2558  const Uint8* src = (Uint8*)&signal->theData[0];
2559  Uint32 byte_sz = 2 + src[0] + (src[1] << 8);
2560  Uint8* dst = (Uint8*)&outBuffer[1];
2561  memcpy(dst, src, byte_sz);
2562  while (byte_sz % 4 != 0)
2563  dst[byte_sz++] = 0;
2564  sz = byte_sz / 4;
2565  break;
2566  }
2567  case AttributeHeader::ROWID:
2568  outBuffer[1] = req_struct->frag_page_id;
2569  outBuffer[2] = req_struct->operPtrP->m_tuple_location.m_page_idx;
2570  sz = 2;
2571  break;
2572  case AttributeHeader::ROW_GCI:
2573  sz = 0;
2574  if (req_struct->tablePtrP->m_bits & Tablerec::TR_RowGCI)
2575  {
2576  Uint64 tmp = * req_struct->m_tuple_ptr->get_mm_gci(req_struct->tablePtrP);
2577  memcpy(outBuffer + 1, &tmp, sizeof(tmp));
2578  sz = 2;
2579  }
2580  break;
2581  case AttributeHeader::ROW_GCI64:
2582  {
2583  sz = 0;
2584  if (req_struct->tablePtrP->m_bits & Tablerec::TR_RowGCI)
2585  {
2586  Uint32 tmp0 = *req_struct->m_tuple_ptr->get_mm_gci(req_struct->tablePtrP);
2587  Uint32 tmp1 = ~Uint32(0);
2588  if (req_struct->tablePtrP->m_bits & Tablerec::TR_ExtraRowGCIBits)
2589  {
2590  Uint32 attrId =
2591  req_struct->tablePtrP->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>();
2592  read_extra_row_bits(attrId,
2593  req_struct->tablePtrP,
2594  req_struct->m_tuple_ptr,
2595  &tmp1,
2596  /* extend */ true);
2597  }
2598  Uint64 tmp = Uint64(tmp0) << 32 | tmp1;
2599  memcpy(outBuffer + 1, &tmp, sizeof(tmp));
2600  sz = 2;
2601  }
2602  break;
2603  }
2604  case AttributeHeader::ROW_AUTHOR:
2605  {
2606  sz = 0;
2607  if (req_struct->tablePtrP->m_bits & Tablerec::TR_ExtraRowAuthorBits)
2608  {
2609  Uint32 attrId = req_struct->tablePtrP
2610  ->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
2611 
2612  Uint32 tmp;
2613  read_extra_row_bits(attrId,
2614  req_struct->tablePtrP,
2615  req_struct->m_tuple_ptr,
2616  &tmp,
2617  /* extend */ false);
2618  outBuffer[1] = tmp;
2619  sz = 1;
2620  }
2621  break;
2622  }
2623  case AttributeHeader::ANY_VALUE:
2624  {
2633  jam();
2634  Uint32 RlogSize = req_struct->log_size;
2635  req_struct->operPtrP->m_any_value = inBuffer[inPos];
2636  * (clogMemBuffer + RlogSize) = inBuffer[inPos - 1];
2637  * (clogMemBuffer + RlogSize + 1) = inBuffer[inPos];
2638  req_struct->out_buf_index = outPos - 4;
2639  req_struct->log_size = RlogSize + 2;
2640  return 1;
2641  }
2642  case AttributeHeader::COPY_ROWID:
2643  sz = 2;
2644  outBuffer[1] = req_struct->operPtrP->m_copy_tuple_location.m_page_no;
2645  outBuffer[2] = req_struct->operPtrP->m_copy_tuple_location.m_page_idx;
2646  break;
2647  case AttributeHeader::FLUSH_AI:
2648  {
2649  jam();
2650  Uint32 resultRef = inBuffer[inPos];
2651  Uint32 resultData = inBuffer[inPos + 1];
2652  Uint32 routeRef = inBuffer[inPos + 2];
2653  flush_read_buffer(req_struct, outBuf, resultRef, resultData, routeRef);
2654  return 3;
2655  }
2656  case AttributeHeader::CORR_FACTOR32:
2657  {
2658  jam();
2659  signal->theData[0] = req_struct->operPtrP->userpointer;
2660  signal->theData[1] = AttributeHeader::CORR_FACTOR64;
2661  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2662  sz = 1;
2663  outBuffer[1] = signal->theData[0];
2664  break;
2665  }
2666  case AttributeHeader::CORR_FACTOR64:
2667  {
2668  jam();
2669  signal->theData[0] = req_struct->operPtrP->userpointer;
2670  signal->theData[1] = AttributeHeader::CORR_FACTOR64;
2671  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2672  sz = 2;
2673  outBuffer[1] = signal->theData[0];
2674  outBuffer[2] = signal->theData[1];
2675  break;
2676  }
2677  case AttributeHeader::FRAGMENT_EXTENT_SPACE:
2678  {
2679  Uint64 res[2];
2680  disk_page_get_allocated(req_struct->tablePtrP, req_struct->fragPtrP, res);
2681  memcpy(outBuffer + 1, res + 0, 8);
2682  sz = 2;
2683  break;
2684  }
2685  case AttributeHeader::FRAGMENT_FREE_EXTENT_SPACE:
2686  {
2687  Uint64 res[2];
2688  disk_page_get_allocated(req_struct->tablePtrP, req_struct->fragPtrP, res);
2689  memcpy(outBuffer + 1, res + 1, 8);
2690  sz = 2;
2691  break;
2692  }
2693  case AttributeHeader::LOCK_REF:
2694  signal->theData[0] = req_struct->operPtrP->userpointer;
2695  signal->theData[1] = attrId;
2696 
2697  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2698  outBuffer[1] = signal->theData[0];
2699  outBuffer[2] = signal->theData[1];
2700  outBuffer[3] = signal->theData[2];
2701  sz = 3;
2702  break;
2703  case AttributeHeader::OP_ID:
2704  signal->theData[0] = req_struct->operPtrP->userpointer;
2705  signal->theData[1] = attrId;
2706 
2707  EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
2708  outBuffer[1] = signal->theData[0];
2709  outBuffer[2] = signal->theData[1];
2710  sz = 2;
2711  break;
2712  default:
2713  return -ZATTRIBUTE_ID_ERROR;
2714  }
2715 
2716  AttributeHeader::init(outBuffer, attrId, sz << 2);
2717  req_struct->out_buf_index = outPos + 4*sz;
2718  return 0;
2719 }
2720 
2721 Uint32
2722 Dbtup::read_packed(const Uint32* inBuf, Uint32 inPos,
2723  KeyReqStruct *req_struct,
2724  Uint32* outBuffer)
2725 {
2726  ndbassert(req_struct->out_buf_index >= 4);
2727  ndbassert((req_struct->out_buf_index & 3) == 0);
2728  ndbassert(req_struct->out_buf_bits == 0);
2729 
2730  Tablerec * const regTabPtr = req_struct->tablePtrP;
2731  Uint32 outPos = req_struct->out_buf_index;
2732  Uint32 outBits = req_struct->out_buf_bits;
2733  Uint32 maxRead = req_struct->max_read;
2734 
2735  Uint32 cnt;
2736  Uint32 numAttributes = regTabPtr->m_no_of_attributes;
2737  Uint32 attrDescriptorStart = regTabPtr->tabDescriptor;
2738  Uint32 attrId = (* (inBuf + inPos - 1)) >> 16;
2739  Uint32 bmlen32 = ((* (inBuf + inPos - 1)) & 0xFFFF);
2740 
2742  if (attrId == AttributeHeader::READ_ALL)
2743  {
2744  cnt = bmlen32;
2745  for (Uint32 i = 0; i<cnt; i++)
2746  mask.set(i);
2747  bmlen32 = 0;
2748  }
2749  else
2750  {
2751  bmlen32 /= 4;
2752  cnt = 32*bmlen32 <= numAttributes ? 32*bmlen32 : numAttributes;
2753  mask.assign(bmlen32, inBuf + inPos);
2754  }
2755 
2756  // Compute result bitmap len
2757  Bitmask<MAXNROFATTRIBUTESINWORDS> nullable = mask;
2758  nullable.bitANDC(regTabPtr->notNullAttributeMask);
2759  Uint32 nullcnt = nullable.count();
2760  Uint32 masksz = (cnt + nullcnt + 31) >> 5;
2761 
2762  Uint32* dst = (Uint32*)(outBuffer + ((outPos - 4) >> 2));
2763  Uint32* dstmask = dst + 1;
2764  AttributeHeader::init(dst, AttributeHeader::READ_PACKED, 4*masksz);
2765  bzero(dstmask, 4*masksz);
2766 
2767  AttributeHeader ahOut;
2768  Uint8* outBuf = (Uint8*)outBuffer;
2769  outPos += 4*masksz;
2770  if (likely(outPos <= maxRead))
2771  {
2772  jam();
2773  for (Uint32 attrId = 0, maskpos = 0; attrId<cnt; attrId++, maskpos++)
2774  {
2775  jam();
2776  if (mask.get(attrId))
2777  {
2778  jam();
2779  Uint32 attrDescrIdx = attrDescriptorStart + (attrId << ZAD_LOG_SIZE);
2780  Uint32 attrDesc1 = tableDescriptor[attrDescrIdx].tabDescr;
2781  Uint32 attrDesc2 = tableDescriptor[attrDescrIdx + 1].tabDescr;
2782  ReadFunction f = regTabPtr->readFunctionArray[attrId];
2783 
2784  if (outBits)
2785  {
2786  ndbassert((outPos & 3) == 0);
2787  }
2788 
2789  Uint32 save[2] = { outPos, outBits };
2790  switch(AttributeDescriptor::getSize(attrDesc1)){
2791  case DictTabInfo::aBit: // bit
2792  outPos = (outPos + 3) & ~(Uint32)3;
2793  break;
2794  case DictTabInfo::an8Bit: // char
2795  case DictTabInfo::a16Bit: // uint16
2796  outPos = outPos + 4 * ((outBits + 31) >> 5);
2797  outBits = 0;
2798  break;
2799  case DictTabInfo::a32Bit: // uint32
2800  case DictTabInfo::a64Bit: // uint64
2801  case DictTabInfo::a128Bit:
2802  outPos = ((outPos + 3) & ~(Uint32)3) + 4 * ((outBits + 31) >> 5);
2803  outBits = 0;
2804  break;
2805 #ifdef VM_TRACE
2806  default:
2807  ndbrequire(false);
2808 #endif
2809  }
2810 
2811  req_struct->out_buf_index = outPos;
2812  req_struct->out_buf_bits = outBits;
2813  req_struct->attr_descriptor = attrDesc1;
2814  if ((this->*f)(outBuf, req_struct, &ahOut, attrDesc2))
2815  {
2816  jam();
2817  BitmaskImpl::set(masksz, dstmask, maskpos);
2818 
2819  outPos = req_struct->out_buf_index;
2820  outBits = req_struct->out_buf_bits;
2821 
2822  if (nullable.get(attrId))
2823  {
2824  jam();
2825  maskpos++;
2826  if (ahOut.isNULL())
2827  {
2828  jam();
2829  BitmaskImpl::set(masksz, dstmask, maskpos);
2830  outPos = save[0];
2831  outBits = save[1];
2832  }
2833  }
2834  continue;
2835  } else {
2836  goto error;
2837  }//if
2838  }
2839  }
2840 
2841  req_struct->out_buf_index = pad32(outPos, outBits);
2842  req_struct->out_buf_bits = 0;
2843  return bmlen32;
2844  }
2845 
2846 error:
2847  ndbrequire(false);
2848  return 0;
2849 }
2850 
2851 #include <signaldata/TransIdAI.hpp>
2852 
2853 void
2854 Dbtup::flush_read_buffer(KeyReqStruct *req_struct,
2855  const Uint32 * outBuf,
2856  Uint32 resultRef,
2857  Uint32 resultData,
2858  Uint32 routeRef)
2859 {
2860  Uint32 sig1= req_struct->trans_id1;
2861  Uint32 sig2= req_struct->trans_id2;
2862  Uint32 len = (req_struct->out_buf_index >> 2) - 1;
2863  Signal * signal = req_struct->signal;
2864 
2865  bool connectedToNode= getNodeInfo(refToNode(resultRef)).m_connected;
2866 
2867  LinearSectionPtr ptr[3];
2868  ptr[0].p= (Uint32*)outBuf; // Should really remove this
2869  ptr[0].sz= len;
2870 
2871  TransIdAI * transIdAI= (TransIdAI *)signal->getDataPtrSend();
2872  transIdAI->connectPtr= resultData;
2873  transIdAI->transId[0]= sig1;
2874  transIdAI->transId[1]= sig2;
2875 
2876  if (likely(connectedToNode))
2877  {
2878  sendSignal(resultRef, GSN_TRANSID_AI, signal, 3, JBB, ptr, 1);
2879  }
2880  else
2881  {
2882  jam();
2883  if (outBuf == signal->theData + 3)
2884  {
2885  jam();
2890  memmove(signal->theData+25, signal->theData+3, 4*len);
2891  ptr[0].p = signal->theData+25;
2892  }
2893  transIdAI->attrData[0] = resultRef;
2894  sendSignal(routeRef, GSN_TRANSID_AI_R, signal, 4, JBB, ptr, 1);
2895  }
2896 
2897  req_struct->out_buf_index = 0; // Reset buffer
2898  req_struct->out_buf_bits = 0;
2899  req_struct->read_length += len;
2900 }
2901 
2902 Uint32
2903 Dbtup::update_packed(KeyReqStruct *req_struct, const Uint32* inBuf)
2904 {
2905  return 0;
2906 }
2907 
2908 bool
2909 Dbtup::readBitsNotNULL(Uint8* outBuffer,
2910  KeyReqStruct* req_struct,
2911  AttributeHeader* ahOut,
2912  Uint32 attrDes2)
2913 {
2914  Tablerec * const regTabPtr = req_struct->tablePtrP;
2915  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
2916  Uint32 bitCount =
2917  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
2918  Uint32 *bmptr= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
2919  Uint32 bmlen = regTabPtr->m_offsets[MM].m_null_words;
2920 
2921  return bits_reader(outBuffer,
2922  req_struct,
2923  ahOut,
2924  bmptr, bmlen,
2925  pos, bitCount);
2926 }
2927 
2928 bool
2929 Dbtup::readBitsNULLable(Uint8* outBuffer,
2930  KeyReqStruct* req_struct,
2931  AttributeHeader* ahOut,
2932  Uint32 attrDes2)
2933 {
2934  Tablerec * const regTabPtr = req_struct->tablePtrP;
2935  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
2936  Uint32 bitCount =
2937  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
2938 
2939  Uint32 *bm_ptr= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
2940  Uint32 bm_len = regTabPtr->m_offsets[MM].m_null_words;
2941 
2942  if(BitmaskImpl::get(bm_len, bm_ptr, pos))
2943  {
2944  jam();
2945  ahOut->setNULL();
2946  return true;
2947  }
2948 
2949  return bits_reader(outBuffer, req_struct, ahOut,
2950  bm_ptr, bm_len,
2951  pos+1, bitCount);
2952 }
2953 
2954 bool
2955 Dbtup::updateBitsNotNULL(Uint32* inBuffer,
2956  KeyReqStruct* req_struct,
2957  Uint32 attrDes2)
2958 {
2959  Tablerec* const regTabPtr = req_struct->tablePtrP;
2960  Uint32 indexBuf = req_struct->in_buf_index;
2961  Uint32 inBufLen = req_struct->in_buf_len;
2962  AttributeHeader ahIn(inBuffer[indexBuf]);
2963  Uint32 nullIndicator = ahIn.isNULL();
2964  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
2965  Uint32 bitCount =
2966  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
2967  Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
2968  Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
2969 
2970  if (newIndex <= inBufLen) {
2971  if (!nullIndicator) {
2972  BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
2973  bitCount, inBuffer+indexBuf+1);
2974  req_struct->in_buf_index = newIndex;
2975  return true;
2976  } else {
2977  jam();
2978  req_struct->errorCode = ZNOT_NULL_ATTR;
2979  return false;
2980  }//if
2981  } else {
2982  jam();
2983  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
2984  return false;
2985  }//if
2986  return true;
2987 }
2988 
2989 bool
2990 Dbtup::updateBitsNULLable(Uint32* inBuffer,
2991  KeyReqStruct* req_struct,
2992  Uint32 attrDes2)
2993 {
2994  Tablerec* const regTabPtr = req_struct->tablePtrP;
2995  Uint32 indexBuf = req_struct->in_buf_index;
2996  AttributeHeader ahIn(inBuffer[indexBuf]);
2997  Uint32 nullIndicator = ahIn.isNULL();
2998  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
2999  Uint32 bitCount =
3000  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
3001  Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
3002 
3003  if (!nullIndicator) {
3004  BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
3005  BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos+1,
3006  bitCount, inBuffer+indexBuf+1);
3007 
3008  Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
3009  req_struct->in_buf_index = newIndex;
3010  return true;
3011  } else {
3012  Uint32 newIndex = indexBuf + 1;
3013  if (newIndex <= req_struct->in_buf_len)
3014  {
3015  jam();
3016  BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
3017 
3018  req_struct->in_buf_index = newIndex;
3019  return true;
3020  } else {
3021  jam();
3022  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3023  return false;
3024  }//if
3025  }//if
3026 }
3027 
3028 bool
3029 Dbtup::updateDiskFixedSizeNotNULL(Uint32* inBuffer,
3030  KeyReqStruct *req_struct,
3031  Uint32 attrDes2)
3032 {
3033  Uint32 attrDescriptor= req_struct->attr_descriptor;
3034  Uint32 indexBuf= req_struct->in_buf_index;
3035  Uint32 inBufLen= req_struct->in_buf_len;
3036  Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
3037  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
3038 
3039  AttributeHeader ahIn(inBuffer[indexBuf]);
3040  Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
3041  Uint32 nullIndicator= ahIn.isNULL();
3042  Uint32 newIndex= indexBuf + noOfWords + 1;
3043  Uint32 *tuple_header= req_struct->m_disk_ptr->m_data;
3044  ndbrequire((updateOffset + noOfWords - 1) < req_struct->check_offset[DD]);
3045 
3046  if (newIndex <= inBufLen) {
3047  if (!nullIndicator) {
3048  jam();
3049  if (charsetFlag) {
3050  jam();
3051  Tablerec * regTabPtr = req_struct->tablePtrP;
3052  Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
3053  Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
3054  Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
3055  ndbrequire(i < regTabPtr->noOfCharsets);
3056  // not const in MySQL
3057  CHARSET_INFO* cs = regTabPtr->charsetArray[i];
3058  int not_used;
3059  const char* ssrc = (const char*)&inBuffer[indexBuf + 1];
3060  Uint32 lb, len;
3061  if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
3062  jam();
3063  req_struct->errorCode = ZINVALID_CHAR_FORMAT;
3064  return false;
3065  }
3066  // fast fix bug#7340
3067  if (typeId != NDB_TYPE_TEXT &&
3068  (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, &not_used) != len) {
3069  jam();
3070  req_struct->errorCode = ZINVALID_CHAR_FORMAT;
3071  return false;
3072  }
3073  }
3074  req_struct->in_buf_index= newIndex;
3075  MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
3076  &inBuffer[indexBuf + 1],
3077  noOfWords);
3078  return true;
3079  } else {
3080  jam();
3081  req_struct->errorCode = ZNOT_NULL_ATTR;
3082  return false;
3083  }
3084  } else {
3085  jam();
3086  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3087  return false;
3088  }
3089 }
3090 
3091 bool
3092 Dbtup::updateDiskFixedSizeNULLable(Uint32* inBuffer,
3093  KeyReqStruct *req_struct,
3094  Uint32 attrDes2)
3095 {
3096  Tablerec * const regTabPtr = req_struct->tablePtrP;
3097  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
3098  Uint32 nullIndicator= ahIn.isNULL();
3099  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
3100  Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
3101 
3102  if (!nullIndicator) {
3103  jam();
3104  BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3105  return updateDiskFixedSizeNotNULL(inBuffer,
3106  req_struct,
3107  attrDes2);
3108  } else {
3109  Uint32 newIndex= req_struct->in_buf_index + 1;
3110  if (newIndex <= req_struct->in_buf_len) {
3111  BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3112  jam();
3113  req_struct->in_buf_index= newIndex;
3114  return true;
3115  } else {
3116  jam();
3117  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3118  return false;
3119  }
3120  }
3121 }
3122 
3123 bool
3124 Dbtup::updateDiskVarAsFixedSizeNotNULL(Uint32* inBuffer,
3125  KeyReqStruct* req_struct,
3126  Uint32 attrDes2)
3127 {
3128  Uint32 attrDescriptor= req_struct->attr_descriptor;
3129  Uint32 indexBuf= req_struct->in_buf_index;
3130  Uint32 inBufLen= req_struct->in_buf_len;
3131  Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
3132  Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
3133 
3134  AttributeHeader ahIn(inBuffer[indexBuf]);
3135  Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
3136  Uint32 nullIndicator= ahIn.isNULL();
3137  Uint32 size_in_words= ahIn.getDataSize();
3138 
3139  Uint32 newIndex= indexBuf + size_in_words + 1;
3140  Uint32 *tuple_header= req_struct->m_disk_ptr->m_data;
3141  ndbrequire((updateOffset + noOfWords - 1) < req_struct->check_offset[DD]);
3142 
3143  if (size_in_words <= noOfWords) {
3144  if (!nullIndicator) {
3145  jam();
3146  if (charsetFlag) {
3147  jam();
3148  Tablerec* regTabPtr = req_struct->tablePtrP;
3149  Uint32 typeId= AttributeDescriptor::getType(attrDescriptor);
3150  Uint32 bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
3151  Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
3152  ndbrequire(i < regTabPtr->noOfCharsets);
3153  // not const in MySQL
3154  CHARSET_INFO* cs = regTabPtr->charsetArray[i];
3155  int not_used;
3156  const char* ssrc = (const char*)&inBuffer[indexBuf + 1];
3157  Uint32 lb, len;
3158  if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
3159  jam();
3160  req_struct->errorCode = ZINVALID_CHAR_FORMAT;
3161  return false;
3162  }
3163  // fast fix bug#7340
3164  if (typeId != NDB_TYPE_TEXT &&
3165  (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, &not_used) != len) {
3166  jam();
3167  req_struct->errorCode = ZINVALID_CHAR_FORMAT;
3168  return false;
3169  }
3170  }
3171 
3172  req_struct->in_buf_index= newIndex;
3173  MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
3174  &inBuffer[indexBuf + 1],
3175  size_in_words);
3176  return true;
3177  } else {
3178  jam();
3179  req_struct->errorCode= ZNOT_NULL_ATTR;
3180  return false;
3181  }
3182  } else {
3183  jam();
3184  req_struct->errorCode= ZAI_INCONSISTENCY_ERROR;
3185  return false;
3186  }
3187 }
3188 
3189 bool
3190 Dbtup::updateDiskVarAsFixedSizeNULLable(Uint32* inBuffer,
3191  KeyReqStruct *req_struct,
3192  Uint32 attrDes2)
3193 {
3194  Tablerec* const regTabPtr = req_struct->tablePtrP;
3195  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
3196  Uint32 nullIndicator= ahIn.isNULL();
3197  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
3198  Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
3199 
3200  if (!nullIndicator) {
3201  jam();
3202  BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3203  return updateDiskVarAsFixedSizeNotNULL(inBuffer,
3204  req_struct,
3205  attrDes2);
3206  } else {
3207  Uint32 newIndex= req_struct->in_buf_index + 1;
3208  if (newIndex <= req_struct->in_buf_len) {
3209  BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3210  jam();
3211  req_struct->in_buf_index= newIndex;
3212  return true;
3213  } else {
3214  jam();
3215  req_struct->errorCode= ZAI_INCONSISTENCY_ERROR;
3216  return false;
3217  }
3218  }
3219 }
3220 
3221 bool
3222 Dbtup::updateDiskVarSizeNotNULL(Uint32* in_buffer,
3223  KeyReqStruct *req_struct,
3224  Uint32 attr_des2)
3225 {
3226  Uint32 attr_descriptor, index_buf, in_buf_len, var_index, null_ind;
3227  Uint32 vsize_in_words, new_index, max_var_size;
3228  Uint32 var_attr_pos;
3229  char *var_data_start;
3230  Uint16 *vpos_array;
3231 
3232  attr_descriptor= req_struct->attr_descriptor;
3233  index_buf= req_struct->in_buf_index;
3234  in_buf_len= req_struct->in_buf_len;
3235  var_index= AttributeOffset::getOffset(attr_des2);
3236  AttributeHeader ahIn(in_buffer[index_buf]);
3237  null_ind= ahIn.isNULL();
3238  Uint32 size_in_bytes = ahIn.getByteSize();
3239  vsize_in_words= (size_in_bytes + 3) >> 2;
3240  max_var_size= AttributeDescriptor::getSizeInBytes(attr_descriptor);
3241  new_index= index_buf + vsize_in_words + 1;
3242  vpos_array= req_struct->m_var_data[DD].m_offset_array_ptr;
3243  Uint32 idx= req_struct->m_var_data[DD].m_var_len_offset;
3244  Uint32 check_offset= req_struct->m_var_data[DD].m_max_var_offset;
3245 
3246  if (new_index <= in_buf_len && vsize_in_words <= max_var_size) {
3247  if (!null_ind) {
3248  jam();
3249  var_attr_pos= vpos_array[var_index];
3250  var_data_start= req_struct->m_var_data[DD].m_data_ptr;
3251  vpos_array[var_index+idx]= var_attr_pos+size_in_bytes;
3252  req_struct->in_buf_index= new_index;
3253 
3254  ndbrequire(var_attr_pos+size_in_bytes <= check_offset);
3255  memcpy(var_data_start+var_attr_pos, &in_buffer[index_buf + 1],
3256  size_in_bytes);
3257  return true;
3258  } else {
3259  jam();
3260  req_struct->errorCode = ZNOT_NULL_ATTR;
3261  return false;
3262  }
3263  } else {
3264  jam();
3265  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3266  return false;
3267  }
3268  return false;
3269 }
3270 
3271 bool
3272 Dbtup::updateDiskVarSizeNULLable(Uint32* inBuffer,
3273  KeyReqStruct *req_struct,
3274  Uint32 attrDes2)
3275 {
3276  Tablerec * const regTabPtr = req_struct->tablePtrP;
3277  AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
3278  Uint32 nullIndicator= ahIn.isNULL();
3279  Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
3280  Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
3281  Uint32 idx= req_struct->m_var_data[DD].m_var_len_offset;
3282 
3283  if (!nullIndicator) {
3284  jam();
3285  BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3286  return updateDiskVarSizeNotNULL(inBuffer,
3287  req_struct,
3288  attrDes2);
3289  } else {
3290  Uint32 newIndex= req_struct->in_buf_index + 1;
3291  Uint32 var_index= AttributeOffset::getOffset(attrDes2);
3292  Uint32 var_pos= req_struct->var_pos_array[var_index];
3293  if (newIndex <= req_struct->in_buf_len) {
3294  jam();
3295  BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3296  req_struct->var_pos_array[var_index+idx]= var_pos;
3297  req_struct->in_buf_index= newIndex;
3298  return true;
3299  } else {
3300  jam();
3301  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3302  return false;
3303  }
3304  }
3305 }
3306 
3307 bool
3308 Dbtup::updateDiskBitsNotNULL(Uint32* inBuffer,
3309  KeyReqStruct* req_struct,
3310  Uint32 attrDes2)
3311 {
3312  Tablerec* const regTabPtr = req_struct->tablePtrP;
3313  Uint32 indexBuf = req_struct->in_buf_index;
3314  Uint32 inBufLen = req_struct->in_buf_len;
3315  AttributeHeader ahIn(inBuffer[indexBuf]);
3316  Uint32 nullIndicator = ahIn.isNULL();
3317  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
3318  Uint32 bitCount =
3319  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
3320  Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
3321  Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
3322 
3323  if (newIndex <= inBufLen) {
3324  if (!nullIndicator) {
3325  BitmaskImpl::setField(regTabPtr->m_offsets[DD].m_null_words, bits, pos,
3326  bitCount, inBuffer+indexBuf+1);
3327  req_struct->in_buf_index = newIndex;
3328  return true;
3329  } else {
3330  jam();
3331  req_struct->errorCode = ZNOT_NULL_ATTR;
3332  return false;
3333  }//if
3334  } else {
3335  jam();
3336  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3337  return false;
3338  }//if
3339  return true;
3340 }
3341 
3342 bool
3343 Dbtup::updateDiskBitsNULLable(Uint32* inBuffer,
3344  KeyReqStruct* req_struct,
3345  Uint32 attrDes2)
3346 {
3347  Tablerec* const regTabPtr = req_struct->tablePtrP;
3348  Uint32 indexBuf = req_struct->in_buf_index;
3349  AttributeHeader ahIn(inBuffer[indexBuf]);
3350  Uint32 nullIndicator = ahIn.isNULL();
3351  Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
3352  Uint32 bitCount =
3353  AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
3354  Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
3355 
3356  if (!nullIndicator) {
3357  BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3358  BitmaskImpl::setField(regTabPtr->m_offsets[DD].m_null_words, bits, pos+1,
3359  bitCount, inBuffer+indexBuf+1);
3360 
3361  Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
3362  req_struct->in_buf_index = newIndex;
3363  return true;
3364  } else {
3365  Uint32 newIndex = indexBuf + 1;
3366  if (newIndex <= req_struct->in_buf_len)
3367  {
3368  jam();
3369  BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
3370 
3371  req_struct->in_buf_index = newIndex;
3372  return true;
3373  } else {
3374  jam();
3375  req_struct->errorCode = ZAI_INCONSISTENCY_ERROR;
3376  return false;
3377  }//if
3378  }//if
3379 }
3380 
3381 Uint32
3382 Dbtup::read_lcp(const Uint32* inBuf, Uint32 inPos,
3383  KeyReqStruct *req_struct,
3384  Uint32* outBuffer)
3385 {
3386  ndbassert(req_struct->out_buf_index >= 4);
3387  ndbassert((req_struct->out_buf_index & 3) == 0);
3388  ndbassert(req_struct->out_buf_bits == 0);
3389 
3390  Tablerec* const regTabPtr = req_struct->tablePtrP;
3391  Uint32 outPos = req_struct->out_buf_index;
3392 
3393  Uint32 fixsz = 4 * (regTabPtr->m_offsets[MM].m_fix_header_size - Tuple_header::HeaderSize);
3394  Uint32 varlen = 0;
3395  char* varstart = 0;
3396  if (req_struct->m_tuple_ptr->m_header_bits & Tuple_header::VAR_PART)
3397  {
3398  ndbassert(req_struct->is_expanded == false);
3399  varstart = (char*)req_struct->m_var_data[MM].m_offset_array_ptr;
3400  char * end = req_struct->m_var_data->m_dyn_data_ptr +
3401  4*req_struct->m_var_data[MM].m_dyn_part_len;
3402  varlen = Uint32(end - varstart);
3403  varlen = (varlen + 3) & ~(Uint32)3;
3404  ndbassert(varlen < 32768);
3405  }
3406  Uint32 totsz = fixsz + varlen;
3407 
3408  Uint32* dst = (Uint32*)(outBuffer + ((outPos - 4) >> 2));
3409  dst[0] = req_struct->frag_page_id;
3410  dst[1] = req_struct->operPtrP->m_tuple_location.m_page_idx;
3411  ndbassert(req_struct->m_tuple_ptr->m_data != 0);
3412  memcpy(dst+2, req_struct->m_tuple_ptr->m_data, fixsz);
3413 
3414  if (varstart)
3415  {
3416  memcpy(dst + 2 + (fixsz >> 2), varstart, varlen);
3417  }
3418 
3419  req_struct->out_buf_index = outPos + 8 + totsz - /* remove header */ 4;
3420 
3421  return 0;
3422 }
3423 
3424 void
3425 Dbtup::update_lcp(KeyReqStruct* req_struct, const Uint32 * src, Uint32 len)
3426 {
3427  Tablerec* const tabPtrP = req_struct->tablePtrP;
3428 
3429  req_struct->m_is_lcp = true;
3430  Uint32 fixsz32 = (tabPtrP->m_offsets[MM].m_fix_header_size - Tuple_header::HeaderSize);
3431  Uint32 fixsz = 4 * fixsz32;
3432  Tuple_header* ptr = (Tuple_header*)req_struct->m_tuple_ptr;
3433  memcpy(ptr->m_data, src, fixsz);
3434 
3435  Uint16 mm_vars= tabPtrP->m_attributes[MM].m_no_of_varsize;
3436  Uint16 mm_dyns= tabPtrP->m_attributes[MM].m_no_of_dynamic;
3437 
3438  Uint32 varlen32 = 0;
3439  if (mm_vars || mm_dyns)
3440  {
3441  varlen32 = len - fixsz32;
3442  if (mm_dyns == 0)
3443  {
3444  ndbassert(len > fixsz32);
3445  }
3446  Varpart_copy* vp = (Varpart_copy*)ptr->get_end_of_fix_part_ptr(tabPtrP);
3447  vp->m_len = varlen32;
3448  memcpy(vp->m_data, src + fixsz32, 4*varlen32);
3449  }
3450  req_struct->m_lcp_varpart_len = varlen32;
3451  ptr->m_header_bits |= (tabPtrP->m_bits & Tablerec::TR_DiskPart) ?
3452  Tuple_header::DISK_PART : 0;
3453  ptr->m_header_bits |= (varlen32) ? Tuple_header::VAR_PART : 0;
3454 
3455  req_struct->changeMask.set();
3456 }
3457 
3458 Uint32
3459 Dbtup::read_lcp_keys(Uint32 tableId,
3460  const Uint32 * src, Uint32 len, Uint32 *dst)
3461 {
3462  TablerecPtr tabPtr;
3463  tabPtr.i= tableId;
3464  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
3465  Tablerec* tabPtrP = tabPtr.p;
3466 
3470  Tuple_header*ptr = (Tuple_header*)(src - Tuple_header::HeaderSize);
3471  KeyReqStruct req_struct(this);
3472  req_struct.tablePtrP = tabPtr.p;
3473  req_struct.m_tuple_ptr = ptr;
3474  req_struct.check_offset[MM]= len;
3475  req_struct.is_expanded = false;
3476 
3480  {
3481  Uint16 mm_vars = tabPtrP->m_attributes[MM].m_no_of_varsize;
3482  Uint16 mm_dyns = tabPtrP->m_attributes[MM].m_no_of_dynamic;
3483  Uint32 src_len = Tuple_header::HeaderSize + len - tabPtrP->m_offsets[MM].m_fix_header_size;
3484 
3485  const Uint32 *src_ptr= ptr->get_end_of_fix_part_ptr(tabPtrP);
3486  if(mm_vars || mm_dyns)
3487  {
3488  const Uint32 *src_data= src_ptr;
3489  KeyReqStruct::Var_data* dst= &req_struct.m_var_data[MM];
3490 
3491  if (mm_vars)
3492  {
3493  char* varstart = (char*)(((Uint16*)src_data)+mm_vars+1);
3494  Uint32 varlen = ((Uint16*)src_data)[mm_vars];
3495  Uint32* dynstart = ALIGN_WORD(varstart + varlen);
3496 
3497  dst->m_data_ptr= varstart;
3498  dst->m_offset_array_ptr= (Uint16*)src_data;
3499  dst->m_var_len_offset= 1;
3500  dst->m_max_var_offset= varlen;
3501 
3502  Uint32 dynlen = Uint32(src_len - (dynstart - src_data));
3503  dst->m_dyn_data_ptr= (char*)dynstart;
3504  dst->m_dyn_part_len= dynlen;
3505  }
3506  else
3507  {
3508  dst->m_dyn_data_ptr= (char*)src_data;
3509  dst->m_dyn_part_len= src_len;
3510  }
3511  }
3512  }
3513 
3514  Uint32 descr_start= tabPtrP->tabDescriptor;
3515  TableDescriptor *tab_descr= &tableDescriptor[descr_start];
3516  req_struct.attr_descr= tab_descr;
3517  const Uint32* attrIds= &tableDescriptor[tabPtrP->readKeyArray].tabDescr;
3518  const Uint32 numAttrs= tabPtrP->noOfKeyAttr;
3519  // read pk attributes from original tuple
3520 
3521  // save globals
3522  // do it
3523  int ret = readAttributes(&req_struct,
3524  attrIds,
3525  numAttrs,
3526  dst,
3527  ZNIL,
3528  false);
3529 
3530  {
3531  Uint32 *src = dst;
3532  Uint32 *tmp = dst;
3533  for (Uint32 * end = src + ret; src < end;)
3534  {
3535  AttributeHeader ah(* src);
3536  memmove(tmp, src + 1, 4*ah.getDataSize());
3537  tmp += ah.getDataSize();
3538  src += 1 + ah.getDataSize();
3539  }
3540  ret -= numAttrs;
3541  }
3542 
3543  ndbrequire(ret > 0);
3544 
3545  return ret;
3546 }
3547 
3548 bool
3549 Dbtup::store_extra_row_bits(Uint32 extra_no,
3550  const Tablerec* regTabPtr,
3551  Tuple_header* ptr,
3552  Uint32 value,
3553  bool truncate)
3554 {
3555  jam();
3556  if (unlikely(extra_no >= regTabPtr->m_no_of_extra_columns))
3557  return false;
3561  Uint32 num_attr= regTabPtr->m_no_of_attributes;
3562  Uint32 attrId = num_attr + extra_no;
3563  Uint32 descr_start = regTabPtr->tabDescriptor;
3564  TableDescriptor *tab_descr = &tableDescriptor[descr_start];
3565  ndbrequire(descr_start + (attrId << ZAD_LOG_SIZE)<= cnoOfTabDescrRec);
3566 
3567  Uint32 attrDescriptorIndex = attrId << ZAD_LOG_SIZE;
3568  Uint32 attrDescriptor = tab_descr[attrDescriptorIndex].tabDescr;
3569  Uint32 attrOffset = tab_descr[attrDescriptorIndex + 1].tabDescr;
3570 
3571  Uint32 pos = AttributeOffset::getNullFlagPos(attrOffset);
3572  Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
3573  Uint32 maxVal = (1 << bitCount) - 1;
3574  Uint32 *bits= ptr->get_null_bits(regTabPtr);
3575 
3576  if (value > maxVal)
3577  {
3578  if (truncate)
3579  {
3580  value = maxVal;
3581  }
3582  else
3583  {
3584  return false;
3585  }
3586  }
3587 
3588  Uint32 check = regTabPtr->m_offsets[MM].m_null_words;
3589  BitmaskImpl::setField(check, bits, pos, bitCount, &value);
3590  return true;
3591 }
3592 
3593 void
3594 Dbtup::read_extra_row_bits(Uint32 extra_no,
3595  const Tablerec* regTabPtr,
3596  Tuple_header* ptr,
3597  Uint32 * value,
3598  bool extend)
3599 {
3603  ndbrequire(extra_no < regTabPtr->m_no_of_extra_columns);
3604  Uint32 num_attr= regTabPtr->m_no_of_attributes;
3605  Uint32 attrId = num_attr + extra_no;
3606  Uint32 descr_start = regTabPtr->tabDescriptor;
3607  TableDescriptor *tab_descr = &tableDescriptor[descr_start];
3608  ndbrequire(descr_start + (attrId << ZAD_LOG_SIZE)<= cnoOfTabDescrRec);
3609 
3610  Uint32 attrDescriptorIndex = attrId << ZAD_LOG_SIZE;
3611  Uint32 attrDescriptor = tab_descr[attrDescriptorIndex].tabDescr;
3612  Uint32 attrOffset = tab_descr[attrDescriptorIndex + 1].tabDescr;
3613 
3614  Uint32 pos = AttributeOffset::getNullFlagPos(attrOffset);
3615  Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
3616  Uint32 maxVal = (1 << bitCount) - 1;
3617  Uint32 *bits= ptr->get_null_bits(regTabPtr);
3618 
3619  Uint32 tmp;
3620  Uint32 check = regTabPtr->m_offsets[MM].m_null_words;
3621  BitmaskImpl::getField(check, bits, pos, bitCount, &tmp);
3622 
3623  if (tmp == maxVal && extend)
3624  {
3625  tmp = ~Uint32(0);
3626  }
3627  * value = tmp;
3628 }