1
/* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);