~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/ndbapi/NdbRecAttr.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
 
 
17
#include <ndb_global.h>
 
18
#include <NdbOut.hpp>
 
19
#include <NdbRecAttr.hpp>
 
20
#include <NdbBlob.hpp>
 
21
#include "NdbDictionaryImpl.hpp"
 
22
#include <NdbTCP.h>
 
23
 
 
24
NdbRecAttr::NdbRecAttr(Ndb*)
 
25
{
 
26
  theStorageX = 0;
 
27
  init();
 
28
}
 
29
 
 
30
NdbRecAttr::~NdbRecAttr()
 
31
{
 
32
  release();
 
33
}
 
34
 
 
35
int
 
36
NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
 
37
{
 
38
  return setup(&(col->m_impl), aValue);
 
39
}
 
40
 
 
41
int
 
42
NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
 
43
{
 
44
  Uint32 tAttrSize = anAttrInfo->m_attrSize;
 
45
  Uint32 tArraySize = anAttrInfo->m_arraySize;
 
46
  Uint32 tAttrByteSize = tAttrSize * tArraySize;
 
47
  
 
48
  m_column = anAttrInfo;
 
49
 
 
50
  theAttrId = anAttrInfo->m_attrId;
 
51
  m_size_in_bytes = tAttrByteSize;
 
52
  theValue = aValue;
 
53
 
 
54
  if (theStorageX)
 
55
    delete[] theStorageX;
 
56
  
 
57
  // check alignment to signal data
 
58
  // a future version could check alignment per data type as well
 
59
  
 
60
  if (aValue != NULL && (UintPtr(aValue)&3) == 0 && (tAttrByteSize&3) == 0) {
 
61
    theStorageX = NULL;
 
62
    theRef = aValue;
 
63
    return 0;
 
64
  }
 
65
  if (tAttrByteSize <= 32) {
 
66
    theStorageX = NULL;
 
67
    theStorage[0] = 0;
 
68
    theStorage[1] = 0;
 
69
    theStorage[2] = 0;
 
70
    theStorage[3] = 0;
 
71
    theRef = theStorage;
 
72
    return 0;
 
73
  }
 
74
  Uint32 tSize = (tAttrByteSize + 7) >> 3;
 
75
  Uint64* tRef = new Uint64[tSize];
 
76
  if (tRef != NULL) {
 
77
    for (Uint32 i = 0; i < tSize; i++) {
 
78
      tRef[i] = 0;
 
79
    }
 
80
    theStorageX = tRef;
 
81
    theRef = tRef;
 
82
    return 0;
 
83
  }
 
84
  errno = ENOMEM;
 
85
  return -1;
 
86
}
 
87
 
 
88
void
 
89
NdbRecAttr::copyout()
 
90
{
 
91
  char* tRef = (char*)theRef;
 
92
  char* tValue = theValue;
 
93
  if (tRef != tValue && tRef != NULL && tValue != NULL) {
 
94
    Uint32 n = m_size_in_bytes;
 
95
    while (n-- > 0) {
 
96
      *tValue++ = *tRef++;
 
97
    }
 
98
  }
 
99
}
 
100
 
 
101
NdbRecAttr *
 
102
NdbRecAttr::clone() const {
 
103
  NdbRecAttr * ret = new NdbRecAttr(0);
 
104
  if (ret == NULL)
 
105
  {
 
106
    errno = ENOMEM;
 
107
    return NULL;
 
108
  }
 
109
  ret->theAttrId = theAttrId;
 
110
  ret->m_size_in_bytes = m_size_in_bytes;
 
111
  ret->m_column = m_column;
 
112
  
 
113
  Uint32 n = m_size_in_bytes;
 
114
  if(n <= 32){
 
115
    ret->theRef = (char*)&ret->theStorage[0];
 
116
    ret->theStorageX = 0;
 
117
    ret->theValue = 0;
 
118
  } else {
 
119
    ret->theStorageX = new Uint64[((n + 7) >> 3)];
 
120
    if (ret->theStorageX == NULL)
 
121
    {
 
122
      delete ret;
 
123
      errno = ENOMEM;
 
124
      return NULL;
 
125
    }
 
126
    ret->theRef = (char*)ret->theStorageX;    
 
127
    ret->theValue = 0;
 
128
  }
 
129
  memcpy(ret->theRef, theRef, n);
 
130
  return ret;
 
131
}
 
132
 
 
133
bool
 
134
NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz)
 
135
{
 
136
  if(sz)
 
137
  {
 
138
    if(!copyoutRequired())
 
139
      memcpy(theRef, data, sz);
 
140
    else
 
141
      memcpy(theValue, data, sz);
 
142
    m_size_in_bytes= sz;
 
143
    return true;
 
144
  } 
 
145
  else 
 
146
  {
 
147
    return setNULL();
 
148
  }
 
149
  return false;
 
150
}
 
151
 
 
152
NdbRecordPrintFormat::NdbRecordPrintFormat()
 
153
{
 
154
  fields_terminated_by= ";";
 
155
  start_array_enclosure= "[";
 
156
  end_array_enclosure= "]";
 
157
  fields_enclosed_by= "";
 
158
  fields_optionally_enclosed_by= "\"";
 
159
  lines_terminated_by= "\n";
 
160
  hex_prefix= "H'";
 
161
  null_string= "[NULL]";
 
162
  hex_format= 0;
 
163
}
 
164
NdbRecordPrintFormat::~NdbRecordPrintFormat() {}
 
165
static const NdbRecordPrintFormat default_print_format;
 
166
 
 
167
static void
 
168
ndbrecattr_print_string(NdbOut& out, const NdbRecordPrintFormat &f,
 
169
                        const char *type, bool is_binary,
 
170
                        const char *aref, unsigned sz)
 
171
{
 
172
  const unsigned char* ref = (const unsigned char*)aref;
 
173
  int i, len, printable= 1;
 
174
  // trailing zeroes are not printed
 
175
  for (i=sz-1; i >= 0; i--)
 
176
    if (ref[i] == 0) sz--;
 
177
    else break;
 
178
  if (!is_binary)
 
179
  {
 
180
    // trailing spaces are not printed
 
181
    for (i=sz-1; i >= 0; i--)
 
182
      if (ref[i] == 32) sz--;
 
183
      else break;
 
184
  }
 
185
  if (is_binary && f.hex_format)
 
186
  {
 
187
    if (sz == 0)
 
188
    {
 
189
      out.print("0x0");
 
190
      return;
 
191
    }
 
192
    out.print("0x");
 
193
    for (len = 0; len < (int)sz; len++)
 
194
      out.print("%02X", (int)ref[len]);
 
195
    return;
 
196
  }
 
197
  if (sz == 0) return; // empty
 
198
 
 
199
  for (len=0; len < (int)sz && ref[i] != 0; len++)
 
200
    if (printable && !isprint((int)ref[i]))
 
201
      printable= 0;
 
202
 
 
203
  if (printable)
 
204
    out.print("%.*s", len, ref);
 
205
  else
 
206
  {
 
207
    out.print("0x");
 
208
    for (i=0; i < len; i++)
 
209
      out.print("%02X", (int)ref[i]);
 
210
  }
 
211
  if (len != (int)sz)
 
212
  {
 
213
    out.print("[");
 
214
    for (i= len+1; ref[i] != 0; i++)
 
215
    out.print("%u]",len-i);
 
216
    assert((int)sz > i);
 
217
    ndbrecattr_print_string(out,f,type,is_binary,aref+i,sz-i);
 
218
  }
 
219
}
 
220
 
 
221
NdbOut&
 
222
ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
 
223
                           const NdbRecordPrintFormat &f)
 
224
{
 
225
  if (r.isNULL())
 
226
  {
 
227
    out << f.null_string;
 
228
    return out;
 
229
  }
 
230
  
 
231
  const NdbDictionary::Column* c = r.getColumn();
 
232
  uint length = c->getLength();
 
233
  {
 
234
    const char *fields_optionally_enclosed_by;
 
235
    if (f.fields_enclosed_by[0] == '\0')
 
236
      fields_optionally_enclosed_by=
 
237
        f.fields_optionally_enclosed_by;
 
238
    else
 
239
      fields_optionally_enclosed_by= "";
 
240
    out << f.fields_enclosed_by;
 
241
    Uint32 j;
 
242
    switch(r.getType()){
 
243
    case NdbDictionary::Column::Bigunsigned:
 
244
      out << r.u_64_value();
 
245
      break;
 
246
    case NdbDictionary::Column::Bit:
 
247
      out << f.hex_prefix << "0x";
 
248
      {
 
249
        const Uint32 *buf = (Uint32 *)r.aRef();
 
250
        int k = (length+31)/32;
 
251
        while (k > 0 && (buf[--k] == 0));
 
252
        out.print("%X", buf[k]);
 
253
        while (k > 0)
 
254
          out.print("%.8X", buf[--k]);
 
255
      }
 
256
      break;
 
257
    case NdbDictionary::Column::Unsigned:
 
258
      if (length > 1)
 
259
        out << f.start_array_enclosure;
 
260
      out << *(Uint32*)r.aRef();
 
261
      for (j = 1; j < length; j++)
 
262
        out << " " << *((Uint32*)r.aRef() + j);
 
263
      if (length > 1)
 
264
        out << f.end_array_enclosure;
 
265
      break;
 
266
    case NdbDictionary::Column::Mediumunsigned:
 
267
      out << r.u_medium_value();
 
268
      break;
 
269
    case NdbDictionary::Column::Smallunsigned:
 
270
      out << r.u_short_value();
 
271
      break;
 
272
    case NdbDictionary::Column::Tinyunsigned:
 
273
      out << (unsigned) r.u_8_value();
 
274
      break;
 
275
    case NdbDictionary::Column::Bigint:
 
276
      out << r.int64_value();
 
277
      break;
 
278
    case NdbDictionary::Column::Int:
 
279
      out << r.int32_value();
 
280
      break;
 
281
    case NdbDictionary::Column::Mediumint:
 
282
      out << r.medium_value();
 
283
      break;
 
284
    case NdbDictionary::Column::Smallint:
 
285
      out << r.short_value();
 
286
      break;
 
287
    case NdbDictionary::Column::Tinyint:
 
288
      out << (int) r.int8_value();
 
289
      break;
 
290
    case NdbDictionary::Column::Binary:
 
291
      if (!f.hex_format)
 
292
        out << fields_optionally_enclosed_by;
 
293
      j = r.get_size_in_bytes();
 
294
      ndbrecattr_print_string(out,f,"Binary", true, r.aRef(), j);
 
295
      if (!f.hex_format)
 
296
        out << fields_optionally_enclosed_by;
 
297
      break;
 
298
    case NdbDictionary::Column::Char:
 
299
      out << fields_optionally_enclosed_by;
 
300
      j = r.get_size_in_bytes();
 
301
      ndbrecattr_print_string(out,f,"Char", false, r.aRef(), j);
 
302
      out << fields_optionally_enclosed_by;
 
303
      break;
 
304
    case NdbDictionary::Column::Varchar:
 
305
    {
 
306
      out << fields_optionally_enclosed_by;
 
307
      unsigned len = *(const unsigned char*)r.aRef();
 
308
      ndbrecattr_print_string(out,f,"Varchar", false, r.aRef()+1,len);
 
309
      j = length;
 
310
      out << fields_optionally_enclosed_by;
 
311
    }
 
312
    break;
 
313
    case NdbDictionary::Column::Varbinary:
 
314
    {
 
315
      if (!f.hex_format)
 
316
        out << fields_optionally_enclosed_by;
 
317
      unsigned len = *(const unsigned char*)r.aRef();
 
318
      ndbrecattr_print_string(out,f,"Varbinary", true, r.aRef()+1,len);
 
319
      j = length;
 
320
      if (!f.hex_format)
 
321
        out << fields_optionally_enclosed_by;
 
322
    }
 
323
    break;
 
324
    case NdbDictionary::Column::Float:
 
325
      out << r.float_value();
 
326
      break;
 
327
    case NdbDictionary::Column::Double:
 
328
      out << r.double_value();
 
329
      break;
 
330
    case NdbDictionary::Column::Olddecimal:
 
331
    {
 
332
      short len = 1 + c->getPrecision() + (c->getScale() > 0);
 
333
      out.print("%.*s", len, r.aRef());
 
334
    }
 
335
    break;
 
336
    case NdbDictionary::Column::Olddecimalunsigned:
 
337
    {
 
338
      short len = 0 + c->getPrecision() + (c->getScale() > 0);
 
339
      out.print("%.*s", len, r.aRef());
 
340
    }
 
341
    break;
 
342
    case NdbDictionary::Column::Decimal:
 
343
    case NdbDictionary::Column::Decimalunsigned:
 
344
      goto unknown;   // TODO
 
345
      break;
 
346
      // for dates cut-and-paste from field.cc
 
347
    case NdbDictionary::Column::Datetime:
 
348
    {
 
349
      ulonglong tmp=r.u_64_value();
 
350
      long part1,part2,part3;
 
351
      part1=(long) (tmp/LL(1000000));
 
352
      part2=(long) (tmp - (ulonglong) part1*LL(1000000));
 
353
      char buf[40];
 
354
      char* pos=(char*) buf+19;
 
355
      *pos--=0;
 
356
      *pos--= (char) ('0'+(char) (part2%10)); part2/=10; 
 
357
      *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
 
358
      *pos--= ':';
 
359
      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
360
      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
361
      *pos--= ':';
 
362
      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
363
      *pos--= (char) ('0'+(char) part3);
 
364
      *pos--= '/';
 
365
      *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
366
      *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
367
      *pos--= '-';
 
368
      *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
369
      *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
 
370
      *pos--= '-';
 
371
      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
372
      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
373
      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
374
      *pos=(char) ('0'+(char) part3);
 
375
      out << buf;
 
376
    }
 
377
    break;
 
378
    case NdbDictionary::Column::Date:
 
379
    {
 
380
      uint32 tmp=(uint32) uint3korr(r.aRef());
 
381
      int part;
 
382
      char buf[40];
 
383
      char *pos=(char*) buf+10;
 
384
      *pos--=0;
 
385
      part=(int) (tmp & 31);
 
386
      *pos--= (char) ('0'+part%10);
 
387
      *pos--= (char) ('0'+part/10);
 
388
      *pos--= '-';
 
389
      part=(int) (tmp >> 5 & 15);
 
390
      *pos--= (char) ('0'+part%10);
 
391
      *pos--= (char) ('0'+part/10);
 
392
      *pos--= '-';
 
393
      part=(int) (tmp >> 9);
 
394
      *pos--= (char) ('0'+part%10); part/=10;
 
395
      *pos--= (char) ('0'+part%10); part/=10;
 
396
      *pos--= (char) ('0'+part%10); part/=10;
 
397
      *pos=   (char) ('0'+part);
 
398
      out << buf;
 
399
    }
 
400
    break;
 
401
    case NdbDictionary::Column::Time:
 
402
    {
 
403
      long tmp=(long) sint3korr(r.aRef());
 
404
      int hour=(uint) (tmp/10000);
 
405
      int minute=(uint) (tmp/100 % 100);
 
406
      int second=(uint) (tmp % 100);
 
407
      char buf[40];
 
408
      sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
 
409
      out << buf;
 
410
    }
 
411
    break;
 
412
    case NdbDictionary::Column::Year:
 
413
    {
 
414
      uint year = 1900 + r.u_8_value();
 
415
      char buf[40];
 
416
      sprintf(buf, "%04d", year);
 
417
      out << buf;
 
418
    }
 
419
    break;
 
420
    case NdbDictionary::Column::Timestamp:
 
421
    {
 
422
      time_t time = r.u_32_value();
 
423
      out << (uint)time;
 
424
    }
 
425
    break;
 
426
    case NdbDictionary::Column::Blob:
 
427
    case NdbDictionary::Column::Text:
 
428
    {
 
429
      // user defined aRef() may not be aligned to Uint64
 
430
      NdbBlob::Head head;
 
431
      memcpy(&head, r.aRef(), sizeof(head));
 
432
      out << head.length << ":";
 
433
      const unsigned char* p = (const unsigned char*)r.aRef() + sizeof(head);
 
434
      if (r.get_size_in_bytes() < sizeof(head))
 
435
        out << "***error***"; // really cannot happen
 
436
      else {
 
437
        unsigned n = r.get_size_in_bytes() - sizeof(head);
 
438
        for (unsigned k = 0; k < n && k < head.length; k++) {
 
439
          if (r.getType() == NdbDictionary::Column::Blob)
 
440
            out.print("%02X", (int)p[k]);
 
441
          else
 
442
            out.print("%c", (int)p[k]);
 
443
        }
 
444
      }
 
445
      j = length;
 
446
    }
 
447
    break;
 
448
    case NdbDictionary::Column::Longvarchar:
 
449
    {
 
450
      out << fields_optionally_enclosed_by;
 
451
      unsigned len = uint2korr(r.aRef());
 
452
      ndbrecattr_print_string(out,f,"Longvarchar", false, r.aRef()+2,len);
 
453
      j = length;
 
454
      out << fields_optionally_enclosed_by;
 
455
    }
 
456
    break;
 
457
    case NdbDictionary::Column::Longvarbinary:
 
458
    {
 
459
      if (!f.hex_format)
 
460
        out << fields_optionally_enclosed_by;
 
461
      unsigned len = uint2korr(r.aRef());
 
462
      ndbrecattr_print_string(out,f,"Longvarbinary", true, r.aRef()+2,len);
 
463
      j = length;
 
464
      if (!f.hex_format)
 
465
        out << fields_optionally_enclosed_by;
 
466
    }
 
467
    break;
 
468
 
 
469
    case NdbDictionary::Column::Undefined:
 
470
    unknown:
 
471
    //default: /* no print functions for the rest, just print type */
 
472
    out << (int) r.getType();
 
473
    j = length;
 
474
    if (j > 1)
 
475
      out << " " << j << " times";
 
476
    break;
 
477
    }
 
478
    out << f.fields_enclosed_by;
 
479
  }
 
480
 
 
481
  return out;
 
482
}
 
483
 
 
484
NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
 
485
{
 
486
  return ndbrecattr_print_formatted(out, r, default_print_format);
 
487
}
 
488
 
 
489
Int64
 
490
NdbRecAttr::int64_value() const 
 
491
{
 
492
  Int64 val;
 
493
  memcpy(&val,theRef,8);
 
494
  return val;
 
495
}
 
496
 
 
497
Uint64
 
498
NdbRecAttr::u_64_value() const
 
499
{
 
500
  Uint64 val;
 
501
  memcpy(&val,theRef,8);
 
502
  return val;
 
503
}
 
504
 
 
505
float
 
506
NdbRecAttr::float_value() const
 
507
{
 
508
  float val;
 
509
  memcpy(&val,theRef,sizeof(val));
 
510
  return val;
 
511
}
 
512
 
 
513
double
 
514
NdbRecAttr::double_value() const
 
515
{
 
516
  double val;
 
517
  memcpy(&val,theRef,sizeof(val));
 
518
  return val;
 
519
}
 
520
 
 
521
Int32
 
522
NdbRecAttr::medium_value() const
 
523
{
 
524
  return sint3korr((unsigned char *)theRef);
 
525
}
 
526
 
 
527
Uint32
 
528
NdbRecAttr::u_medium_value() const
 
529
{
 
530
  return uint3korr((unsigned char*)theRef);
 
531
}