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>
19 #include <NdbRecAttr.hpp>
20 #include <NdbBlob.hpp>
21 #include "NdbDictionaryImpl.hpp"
24 NdbRecAttr::NdbRecAttr(Ndb
*)
30 NdbRecAttr::~NdbRecAttr()
36 NdbRecAttr::setup(const class NdbDictionary::Column
* col
, char* aValue
)
38 return setup(&(col
->m_impl
), aValue
);
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
;
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) {
65 if (tAttrByteSize
<= 32) {
74 Uint32 tSize
= (tAttrByteSize
+ 7) >> 3;
75 Uint64
* tRef
= new Uint64
[tSize
];
77 for (Uint32 i
= 0; i
< tSize
; i
++) {
91 char* tRef
= (char*)theRef
;
92 char* tValue
= theValue
;
93 if (tRef
!= tValue
&& tRef
!= NULL
&& tValue
!= NULL
) {
94 Uint32 n
= m_size_in_bytes
;
102 NdbRecAttr::clone() const {
103 NdbRecAttr
* ret
= new NdbRecAttr(0);
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
;
115 ret
->theRef
= (char*)&ret
->theStorage
[0];
116 ret
->theStorageX
= 0;
119 ret
->theStorageX
= new Uint64
[((n
+ 7) >> 3)];
120 if (ret
->theStorageX
== NULL
)
126 ret
->theRef
= (char*)ret
->theStorageX
;
129 memcpy(ret
->theRef
, theRef
, n
);
134 NdbRecAttr::receive_data(const Uint32
* data
, Uint32 sz
)
138 if(!copyoutRequired())
139 memcpy(theRef
, data
, sz
);
141 memcpy(theValue
, data
, sz
);
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";
161 null_string
= "[NULL]";
164 NdbRecordPrintFormat::~NdbRecordPrintFormat() {}
165 static const NdbRecordPrintFormat default_print_format
;
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
--;
180 // trailing spaces are not printed
181 for (i
=sz
-1; i
>= 0; i
--)
182 if (ref
[i
] == 32) sz
--;
185 if (is_binary
&& f
.hex_format
)
193 for (len
= 0; len
< (int)sz
; len
++)
194 out
.print("%02X", (int)ref
[len
]);
197 if (sz
== 0) return; // empty
199 for (len
=0; len
< (int)sz
&& ref
[i
] != 0; len
++)
200 if (printable
&& !isprint((int)ref
[i
]))
204 out
.print("%.*s", len
, ref
);
208 for (i
=0; i
< len
; i
++)
209 out
.print("%02X", (int)ref
[i
]);
214 for (i
= len
+1; ref
[i
] != 0; i
++)
215 out
.print("%u]",len
-i
);
217 ndbrecattr_print_string(out
,f
,type
,is_binary
,aref
+i
,sz
-i
);
222 ndbrecattr_print_formatted(NdbOut
& out
, const NdbRecAttr
&r
,
223 const NdbRecordPrintFormat
&f
)
227 out
<< f
.null_string
;
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
;
239 fields_optionally_enclosed_by
= "";
240 out
<< f
.fields_enclosed_by
;
243 case NdbDictionary::Column::Bigunsigned
:
244 out
<< r
.u_64_value();
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
]);
254 out
.print("%.8X", buf
[--k
]);
257 case NdbDictionary::Column::Unsigned
:
259 out
<< f
.start_array_enclosure
;
260 out
<< *(Uint32
*)r
.aRef();
261 for (j
= 1; j
< length
; j
++)
262 out
<< " " << *((Uint32
*)r
.aRef() + j
);
264 out
<< f
.end_array_enclosure
;
266 case NdbDictionary::Column::Mediumunsigned
:
267 out
<< r
.u_medium_value();
269 case NdbDictionary::Column::Smallunsigned
:
270 out
<< r
.u_short_value();
272 case NdbDictionary::Column::Tinyunsigned
:
273 out
<< (unsigned) r
.u_8_value();
275 case NdbDictionary::Column::Bigint
:
276 out
<< r
.int64_value();
278 case NdbDictionary::Column::Int
:
279 out
<< r
.int32_value();
281 case NdbDictionary::Column::Mediumint
:
282 out
<< r
.medium_value();
284 case NdbDictionary::Column::Smallint
:
285 out
<< r
.short_value();
287 case NdbDictionary::Column::Tinyint
:
288 out
<< (int) r
.int8_value();
290 case NdbDictionary::Column::Binary
:
292 out
<< fields_optionally_enclosed_by
;
293 j
= r
.get_size_in_bytes();
294 ndbrecattr_print_string(out
,f
,"Binary", true, r
.aRef(), j
);
296 out
<< fields_optionally_enclosed_by
;
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
;
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
);
310 out
<< fields_optionally_enclosed_by
;
313 case NdbDictionary::Column::Varbinary
:
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
);
321 out
<< fields_optionally_enclosed_by
;
324 case NdbDictionary::Column::Float
:
325 out
<< r
.float_value();
327 case NdbDictionary::Column::Double
:
328 out
<< r
.double_value();
330 case NdbDictionary::Column::Olddecimal
:
332 short len
= 1 + c
->getPrecision() + (c
->getScale() > 0);
333 out
.print("%.*s", len
, r
.aRef());
336 case NdbDictionary::Column::Olddecimalunsigned
:
338 short len
= 0 + c
->getPrecision() + (c
->getScale() > 0);
339 out
.print("%.*s", len
, r
.aRef());
342 case NdbDictionary::Column::Decimal
:
343 case NdbDictionary::Column::Decimalunsigned
:
344 goto unknown
; // TODO
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));
354 char* pos
=(char*) buf
+19;
356 *pos
--= (char) ('0'+(char) (part2
%10)); part2
/=10;
357 *pos
--= (char) ('0'+(char) (part2
%10)); part3
= (int) (part2
/ 10);
359 *pos
--= (char) ('0'+(char) (part3
%10)); part3
/=10;
360 *pos
--= (char) ('0'+(char) (part3
%10)); part3
/=10;
362 *pos
--= (char) ('0'+(char) (part3
%10)); part3
/=10;
363 *pos
--= (char) ('0'+(char) part3
);
365 *pos
--= (char) ('0'+(char) (part1
%10)); part1
/=10;
366 *pos
--= (char) ('0'+(char) (part1
%10)); part1
/=10;
368 *pos
--= (char) ('0'+(char) (part1
%10)); part1
/=10;
369 *pos
--= (char) ('0'+(char) (part1
%10)); part3
= (int) (part1
/10);
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
);
378 case NdbDictionary::Column::Date
:
380 uint32 tmp
=(uint32
) uint3korr(r
.aRef());
383 char *pos
=(char*) buf
+10;
385 part
=(int) (tmp
& 31);
386 *pos
--= (char) ('0'+part
%10);
387 *pos
--= (char) ('0'+part
/10);
389 part
=(int) (tmp
>> 5 & 15);
390 *pos
--= (char) ('0'+part
%10);
391 *pos
--= (char) ('0'+part
/10);
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
);
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);
408 sprintf(buf
, "%02d:%02d:%02d", hour
, minute
, second
);
412 case NdbDictionary::Column::Year
:
414 uint year
= 1900 + r
.u_8_value();
416 sprintf(buf
, "%04d", year
);
420 case NdbDictionary::Column::Timestamp
:
422 time_t time
= r
.u_32_value();
426 case NdbDictionary::Column::Blob
:
427 case NdbDictionary::Column::Text
:
429 // user defined aRef() may not be aligned to Uint64
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
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
]);
442 out
.print("%c", (int)p
[k
]);
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
);
454 out
<< fields_optionally_enclosed_by
;
457 case NdbDictionary::Column::Longvarbinary
:
460 out
<< fields_optionally_enclosed_by
;
461 unsigned len
= uint2korr(r
.aRef());
462 ndbrecattr_print_string(out
,f
,"Longvarbinary", true, r
.aRef()+2,len
);
465 out
<< fields_optionally_enclosed_by
;
469 case NdbDictionary::Column::Undefined
:
471 //default: /* no print functions for the rest, just print type */
472 out
<< (int) r
.getType();
475 out
<< " " << j
<< " times";
478 out
<< f
.fields_enclosed_by
;
484 NdbOut
& operator<<(NdbOut
& out
, const NdbRecAttr
&r
)
486 return ndbrecattr_print_formatted(out
, r
, default_print_format
);
490 NdbRecAttr::int64_value() const
493 memcpy(&val
,theRef
,8);
498 NdbRecAttr::u_64_value() const
501 memcpy(&val
,theRef
,8);
506 NdbRecAttr::float_value() const
509 memcpy(&val
,theRef
,sizeof(val
));
514 NdbRecAttr::double_value() const
517 memcpy(&val
,theRef
,sizeof(val
));
522 NdbRecAttr::medium_value() const
524 return sint3korr((unsigned char *)theRef
);
528 NdbRecAttr::u_medium_value() const
530 return uint3korr((unsigned char*)theRef
);