mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / src / ndbapi / NdbRecAttr.cpp
blob12e29e5578bd351a85f8dd5a2e1dc6cd34dd9672
1 /* Copyright (c) 2003-2007 MySQL AB
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
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>
24 NdbRecAttr::NdbRecAttr(Ndb*)
26 theStorageX = 0;
27 init();
30 NdbRecAttr::~NdbRecAttr()
32 release();
35 int
36 NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
38 return setup(&(col->m_impl), aValue);
41 int
42 NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
44 Uint32 tAttrSize = anAttrInfo->m_attrSize;
45 Uint32 tArraySize = anAttrInfo->m_arraySize;
46 Uint32 tAttrByteSize = tAttrSize * tArraySize;
48 m_column = anAttrInfo;
50 theAttrId = anAttrInfo->m_attrId;
51 m_size_in_bytes = tAttrByteSize;
52 theValue = aValue;
54 if (theStorageX)
55 delete[] theStorageX;
57 // check alignment to signal data
58 // a future version could check alignment per data type as well
60 if (aValue != NULL && (UintPtr(aValue)&3) == 0 && (tAttrByteSize&3) == 0) {
61 theStorageX = NULL;
62 theRef = aValue;
63 return 0;
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;
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;
80 theStorageX = tRef;
81 theRef = tRef;
82 return 0;
84 errno = ENOMEM;
85 return -1;
88 void
89 NdbRecAttr::copyout()
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++;
101 NdbRecAttr *
102 NdbRecAttr::clone() const {
103 NdbRecAttr * ret = new NdbRecAttr(0);
104 if (ret == NULL)
106 errno = ENOMEM;
107 return NULL;
109 ret->theAttrId = theAttrId;
110 ret->m_size_in_bytes = m_size_in_bytes;
111 ret->m_column = m_column;
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)
122 delete ret;
123 errno = ENOMEM;
124 return NULL;
126 ret->theRef = (char*)ret->theStorageX;
127 ret->theValue = 0;
129 memcpy(ret->theRef, theRef, n);
130 return ret;
133 bool
134 NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz)
136 if(sz)
138 if(!copyoutRequired())
139 memcpy(theRef, data, sz);
140 else
141 memcpy(theValue, data, sz);
142 m_size_in_bytes= sz;
143 return true;
145 else
147 return setNULL();
149 return false;
152 NdbRecordPrintFormat::NdbRecordPrintFormat()
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;
164 NdbRecordPrintFormat::~NdbRecordPrintFormat() {}
165 static const NdbRecordPrintFormat default_print_format;
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)
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)
180 // trailing spaces are not printed
181 for (i=sz-1; i >= 0; i--)
182 if (ref[i] == 32) sz--;
183 else break;
185 if (is_binary && f.hex_format)
187 if (sz == 0)
189 out.print("0x0");
190 return;
192 out.print("0x");
193 for (len = 0; len < (int)sz; len++)
194 out.print("%02X", (int)ref[len]);
195 return;
197 if (sz == 0) return; // empty
199 for (len=0; len < (int)sz && ref[i] != 0; len++)
200 if (printable && !isprint((int)ref[i]))
201 printable= 0;
203 if (printable)
204 out.print("%.*s", len, ref);
205 else
207 out.print("0x");
208 for (i=0; i < len; i++)
209 out.print("%02X", (int)ref[i]);
211 if (len != (int)sz)
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);
221 NdbOut&
222 ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
223 const NdbRecordPrintFormat &f)
225 if (r.isNULL())
227 out << f.null_string;
228 return out;
231 const NdbDictionary::Column* c = r.getColumn();
232 uint length = c->getLength();
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";
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]);
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:
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;
312 break;
313 case NdbDictionary::Column::Varbinary:
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;
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:
332 short len = 1 + c->getPrecision() + (c->getScale() > 0);
333 out.print("%.*s", len, r.aRef());
335 break;
336 case NdbDictionary::Column::Olddecimalunsigned:
338 short len = 0 + c->getPrecision() + (c->getScale() > 0);
339 out.print("%.*s", len, r.aRef());
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:
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;
377 break;
378 case NdbDictionary::Column::Date:
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;
400 break;
401 case NdbDictionary::Column::Time:
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;
411 break;
412 case NdbDictionary::Column::Year:
414 uint year = 1900 + r.u_8_value();
415 char buf[40];
416 sprintf(buf, "%04d", year);
417 out << buf;
419 break;
420 case NdbDictionary::Column::Timestamp:
422 time_t time = r.u_32_value();
423 out << (uint)time;
425 break;
426 case NdbDictionary::Column::Blob:
427 case NdbDictionary::Column::Text:
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]);
445 j = length;
447 break;
448 case NdbDictionary::Column::Longvarchar:
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;
456 break;
457 case NdbDictionary::Column::Longvarbinary:
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;
467 break;
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;
478 out << f.fields_enclosed_by;
481 return out;
484 NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
486 return ndbrecattr_print_formatted(out, r, default_print_format);
489 Int64
490 NdbRecAttr::int64_value() const
492 Int64 val;
493 memcpy(&val,theRef,8);
494 return val;
497 Uint64
498 NdbRecAttr::u_64_value() const
500 Uint64 val;
501 memcpy(&val,theRef,8);
502 return val;
505 float
506 NdbRecAttr::float_value() const
508 float val;
509 memcpy(&val,theRef,sizeof(val));
510 return val;
513 double
514 NdbRecAttr::double_value() const
516 double val;
517 memcpy(&val,theRef,sizeof(val));
518 return val;
521 Int32
522 NdbRecAttr::medium_value() const
524 return sint3korr((unsigned char *)theRef);
527 Uint32
528 NdbRecAttr::u_medium_value() const
530 return uint3korr((unsigned char*)theRef);