NdbRecAttr.cpp 10.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


18
#include <ndb_global.h>
19 20
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
unknown's avatar
unknown committed
21
#include <NdbBlob.hpp>
22
#include "NdbDictionaryImpl.hpp"
23
#include <NdbTCP.h>
24

25 26 27
NdbRecAttr::NdbRecAttr()
{
  init();
28 29 30 31 32 33 34
}

NdbRecAttr::~NdbRecAttr()
{
  release();
}

35 36 37 38 39
int
NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
{
  return setup(&(col->m_impl), aValue);
}
40 41 42 43 44 45 46 47
int
NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
{
  Uint32 tAttrSize = anAttrInfo->m_attrSize;
  Uint32 tArraySize = anAttrInfo->m_arraySize;
  Uint32 tAttrByteSize = tAttrSize * tArraySize;
  
  m_column = anAttrInfo;
48

49 50 51 52
  theAttrId = anAttrInfo->m_attrId;
  theAttrSize = tAttrSize;
  theArraySize = tArraySize;
  theValue = aValue;
unknown's avatar
unknown committed
53 54
  theNULLind = 0;
  m_nullable = anAttrInfo->m_nullable;
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

  // check alignment to signal data
  // a future version could check alignment per data type as well
  
  if (aValue != NULL && (UintPtr(aValue)&3) == 0 && (tAttrByteSize&3) == 0) {
    theStorageX = NULL;
    theRef = aValue;
    return 0;
  }
  if (tAttrByteSize <= 32) {
    theStorageX = NULL;
    theStorage[0] = 0;
    theStorage[1] = 0;
    theStorage[2] = 0;
    theStorage[3] = 0;
    theRef = theStorage;
    return 0;
  }
  Uint32 tSize = (tAttrByteSize + 7) >> 3;
  Uint64* tRef = new Uint64[tSize];
  if (tRef != NULL) {
    for (Uint32 i = 0; i < tSize; i++) {
      tRef[i] = 0;
    }
    theStorageX = tRef;
    theRef = tRef;
    return 0;
  }
  return -1;
}

void
NdbRecAttr::copyout()
{
  char* tRef = (char*)theRef;
  char* tValue = theValue;
  if (tRef != tValue && tRef != NULL && tValue != NULL) {
    Uint32 n = theAttrSize * theArraySize;
    while (n-- > 0) {
      *tValue++ = *tRef++;
    }
  }
}

NdbRecAttr *
NdbRecAttr::clone() const {
  NdbRecAttr * ret = new NdbRecAttr();

  ret->theAttrId = theAttrId;
  ret->theNULLind = theNULLind;
  ret->theAttrSize = theAttrSize;
  ret->theArraySize = theArraySize;
  ret->m_column = m_column;
  
  Uint32 n = theAttrSize * theArraySize;  
  if(n <= 32){
    ret->theRef = (char*)&ret->theStorage[0];
    ret->theStorageX = 0;
    ret->theValue = 0;
  } else {
    ret->theStorageX = new Uint64[((n + 7) >> 3)];
    ret->theRef = (char*)ret->theStorageX;    
    ret->theValue = 0;
  }
  memcpy(ret->theRef, theRef, n);
  return ret;
}
unknown's avatar
unknown committed
122 123 124 125 126

bool
NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
  const Uint32 n = (theAttrSize * theArraySize + 3) >> 2;  
  if(n == sz){
unknown's avatar
unknown committed
127
    theNULLind = 0;
unknown's avatar
unknown committed
128 129 130 131 132 133 134 135 136 137 138
    if(!copyoutRequired())
      memcpy(theRef, data, 4 * sz);
    else
      memcpy(theValue, data, theAttrSize * theArraySize);
    return true;
  } else if(sz == 0){
    setNULL();
    return true;
  }
  return false;
}
unknown's avatar
merge  
unknown committed
139

140 141 142 143
static void
ndbrecattr_print_string(NdbOut& out, const char *type,
			const char *ref, unsigned sz)
{
unknown's avatar
unknown committed
144
  int i, len, printable= 1;
145 146 147 148 149 150
  // trailing zeroes are not printed
  for (i=sz-1; i >= 0; i--)
    if (ref[i] == 0) sz--;
    else break;
  if (sz == 0) return; // empty

unknown's avatar
unknown committed
151 152
  for (len=0; len < (int)sz && ref[i] != 0; len++)
    if (printable && !isprint((int)ref[i]))
153
      printable= 0;
unknown's avatar
unknown committed
154

155
  if (printable)
unknown's avatar
unknown committed
156
    out.print("%.*s", len, ref);
157
  else
unknown's avatar
unknown committed
158 159
  {
    out.print("0x");
160
    for (i=0; i < len; i++)
unknown's avatar
unknown committed
161
      out.print("%02X", (int)ref[i]);
unknown's avatar
unknown committed
162
  }
163 164 165 166 167
  if (len != (int)sz)
  {
    out.print("[");
    for (i= len+1; ref[i] != 0; i++)
    out.print("%u]",len-i);
unknown's avatar
unknown committed
168
    assert((int)sz > i);
169 170 171 172
    ndbrecattr_print_string(out,type,ref+i,sz-i);
  }
}

unknown's avatar
unknown committed
173
NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
174 175 176
{
  if (r.isNULL())
  {
unknown's avatar
unknown committed
177 178
    out << "[NULL]";
    return out;
179 180
  }

181 182
  const NdbDictionary::Column* c = r.getColumn();
  uint length = c->getLength();
183
  if (length > 1)
unknown's avatar
unknown committed
184
    out << "[";
185

186
  for (Uint32 j = 0; j < length; j++) 
187 188
  {
    if (j > 0)
unknown's avatar
unknown committed
189
      out << " ";
190 191 192 193

    switch(r.getType())
      {
      case NdbDictionary::Column::Bigunsigned:
unknown's avatar
unknown committed
194
	out << r.u_64_value();
195
	break;
196 197 198
      case NdbDictionary::Column::Bit:
	out << hex << "H'" << r.u_32_value() << dec;
	break;
199
      case NdbDictionary::Column::Unsigned:
unknown's avatar
unknown committed
200
	out << r.u_32_value();
201 202
	break;
      case NdbDictionary::Column::Smallunsigned:
unknown's avatar
unknown committed
203
	out << r.u_short_value();
204 205
	break;
      case NdbDictionary::Column::Tinyunsigned:
unknown's avatar
unknown committed
206
	out << (unsigned) r.u_char_value();
207 208
	break;
      case NdbDictionary::Column::Bigint:
unknown's avatar
unknown committed
209
	out << r.int64_value();
210 211
	break;
      case NdbDictionary::Column::Int:
unknown's avatar
unknown committed
212
	out << r.int32_value();
213 214
	break;
      case NdbDictionary::Column::Smallint:
unknown's avatar
unknown committed
215
	out << r.short_value();
216 217
	break;
      case NdbDictionary::Column::Tinyint:
unknown's avatar
unknown committed
218
	out << (int) r.char_value();
219
	break;
220 221 222 223
      case NdbDictionary::Column::Binary:
	ndbrecattr_print_string(out,"Binary",r.aRef(),r.arraySize());
	j = r.arraySize();
	break;
224
      case NdbDictionary::Column::Char:
225
	ndbrecattr_print_string(out,"Char",r.aRef(),r.arraySize());
226
	j = length;
227 228
	break;
      case NdbDictionary::Column::Varchar:
unknown's avatar
unknown committed
229 230 231
        {
          unsigned len = *(const unsigned char*)r.aRef();
          ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
unknown's avatar
Merge  
unknown committed
232
          j = length;
unknown's avatar
unknown committed
233
        }
234
	break;
235
      case NdbDictionary::Column::Float:
unknown's avatar
unknown committed
236
	out << r.float_value();
237 238
	break;
      case NdbDictionary::Column::Double:
unknown's avatar
unknown committed
239
	out << r.double_value();
240
	break;
241 242 243 244 245 246 247 248 249 250 251 252
      case NdbDictionary::Column::Olddecimal:
        {
          short len = 1 + c->getPrecision() + (c->getScale() > 0);
          out.print("%.*s", len, r.aRef());
        }
        break;
      case NdbDictionary::Column::Olddecimalunsigned:
        {
          short len = 0 + c->getPrecision() + (c->getScale() > 0);
          out.print("%.*s", len, r.aRef());
        }
	break;
253 254 255 256
      case NdbDictionary::Column::Decimal:
      case NdbDictionary::Column::Decimalunsigned:
        goto unknown;   // TODO
        break;
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
      // for dates cut-and-paste from field.cc
      case NdbDictionary::Column::Datetime:
        {
          ulonglong tmp=r.u_64_value();
          long part1,part2,part3;
          part1=(long) (tmp/LL(1000000));
          part2=(long) (tmp - (ulonglong) part1*LL(1000000));
          char buf[40];
          char* pos=(char*) buf+19;
          *pos--=0;
          *pos--= (char) ('0'+(char) (part2%10)); part2/=10; 
          *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
          *pos--= ':';
          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
          *pos--= ':';
          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
          *pos--= (char) ('0'+(char) part3);
          *pos--= '/';
          *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
          *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
          *pos--= '-';
          *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
          *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
          *pos--= '-';
          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
          *pos=(char) ('0'+(char) part3);
          out << buf;
        }
	break;
      case NdbDictionary::Column::Date:
        {
unknown's avatar
unknown committed
291 292
          uint32 tmp=(uint32) uint3korr(r.aRef());
          int part;
293
          char buf[40];
unknown's avatar
unknown committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
          char *pos=(char*) buf+10;
          *pos--=0;
          part=(int) (tmp & 31);
          *pos--= (char) ('0'+part%10);
          *pos--= (char) ('0'+part/10);
          *pos--= '-';
          part=(int) (tmp >> 5 & 15);
          *pos--= (char) ('0'+part%10);
          *pos--= (char) ('0'+part/10);
          *pos--= '-';
          part=(int) (tmp >> 9);
          *pos--= (char) ('0'+part%10); part/=10;
          *pos--= (char) ('0'+part%10); part/=10;
          *pos--= (char) ('0'+part%10); part/=10;
          *pos=   (char) ('0'+part);
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
          out << buf;
        }
	break;
      case NdbDictionary::Column::Time:
        {
          long tmp=(long) sint3korr(r.aRef());
          int hour=(uint) (tmp/10000);
          int minute=(uint) (tmp/100 % 100);
          int second=(uint) (tmp % 100);
          char buf[40];
          sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
          out << buf;
        }
	break;
      case NdbDictionary::Column::Year:
        {
          uint year = 1900 + r.u_char_value();
          char buf[40];
          sprintf(buf, "%04d", year);
          out << buf;
        }
	break;
      case NdbDictionary::Column::Timestamp:
        {
          time_t time = r.u_32_value();
          out << (uint)time;
        }
	break;
unknown's avatar
unknown committed
337 338 339 340 341 342 343 344
      case NdbDictionary::Column::Blob:
        {
          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
          out << h->length << ":";
          const unsigned char* p = (const unsigned char*)(h + 1);
          unsigned n = r.arraySize() - sizeof(*h);
          for (unsigned k = 0; k < n && k < h->length; k++)
            out.print("%02X", (int)p[k]);
345
          j = length;
unknown's avatar
unknown committed
346 347 348 349 350 351 352 353 354 355
        }
        break;
      case NdbDictionary::Column::Text:
        {
          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
          out << h->length << ":";
          const unsigned char* p = (const unsigned char*)(h + 1);
          unsigned n = r.arraySize() - sizeof(*h);
          for (unsigned k = 0; k < n && k < h->length; k++)
            out.print("%c", (int)p[k]);
356
          j = length;
unknown's avatar
unknown committed
357 358
        }
        break;
unknown's avatar
unknown committed
359 360 361 362
      case NdbDictionary::Column::Longvarchar:
        {
          unsigned len = uint2korr(r.aRef());
          ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
unknown's avatar
Merge  
unknown committed
363
          j = length;
unknown's avatar
unknown committed
364 365
        }
        break;
366
      unknown:
367
      default: /* no print functions for the rest, just print type */
unknown's avatar
unknown committed
368
	out << (int) r.getType();
369
	j = length;
370
	if (j > 1)
unknown's avatar
unknown committed
371
	  out << " " << j << " times";
372 373 374 375
	break;
      }
  }

376
  if (length > 1)
377
  {
unknown's avatar
unknown committed
378
    out << "]";
379 380
  }

unknown's avatar
unknown committed
381
  return out;
382
}
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414

Int64
NdbRecAttr::int64_value() const 
{
  Int64 val;
  memcpy(&val,theRef,8);
  return val;
}

Uint64
NdbRecAttr::u_64_value() const
{
  Uint64 val;
  memcpy(&val,theRef,8);
  return val;
}

float
NdbRecAttr::float_value() const
{
  float val;
  memcpy(&val,theRef,sizeof(val));
  return val;
}

double
NdbRecAttr::double_value() const
{
  double val;
  memcpy(&val,theRef,sizeof(val));
  return val;
}