18 #include <ndb_global.h>
19 #include <NdbPack.hpp>
26 NdbPack::Error::get_error_code()
const
32 NdbPack::Error::get_error_line()
const
38 NdbPack::Error::set_error(
int code,
int line)
const
43 const char* p = NdbEnv_GetEnv(
"NDB_PACK_ABORT_ON_ERROR", (
char*)0, 0);
44 if (p != 0 && strchr(
"1Y", p[0]) != 0)
50 NdbPack::Error::set_error(
const Error& e2)
const
52 set_error(e2.m_error_code, e2.m_error_line);
58 NdbPack::Endian::convert(
void* ptr, Uint32 len)
60 Uint8* p = (Uint8*)ptr;
61 for (Uint32
i = 0;
i < len / 2;
i++)
63 Uint32 j = len -
i - 1;
81 g_ndb_pack_type_info[] = {
115 static const int g_ndb_pack_type_info_cnt =
116 sizeof(g_ndb_pack_type_info) /
sizeof(g_ndb_pack_type_info[0]);
119 NdbPack::Type::complete()
123 set_error(TypeNotSet, __LINE__);
126 if (m_typeId >= g_ndb_pack_type_info_cnt)
128 set_error(TypeNotSet, __LINE__);
132 if (!info.m_supported)
134 set_error(TypeNotSupported, __LINE__);
139 set_error(TypeSizeZero, __LINE__);
142 if (info.m_fixSize != 0 && m_byteSize != info.m_fixSize)
144 set_error(TypeFixSizeInvalid, __LINE__);
147 if (!(m_nullable <= 1))
149 set_error(TypeNullableNotBool, __LINE__);
152 if (info.m_charType && m_csNumber == 0)
154 set_error(CharsetNotSpecified, __LINE__);
157 if (info.m_charType && all_charsets[m_csNumber] == 0)
162 set_error(CharsetNotFound, __LINE__);
165 all_charsets[m_csNumber] = cs;
167 if (!info.m_charType && m_csNumber != 0)
169 set_error(CharsetNotAllowed, __LINE__);
172 m_arrayType = info.m_arrayType;
179 NdbPack::Spec::add(Type
type)
182 Uint32 nullable_cnt = m_nullableCnt;
183 Uint32 varsize_cnt = m_varsizeCnt;
184 Uint32 max_byte_size = m_maxByteSize;
185 if (type.complete() == -1)
190 type.m_nullbitPos = 0xFFFF;
193 type.m_nullbitPos = nullable_cnt;
196 if (type.m_arrayType != 0)
200 max_byte_size += type.m_byteSize;
201 if (cnt >= m_bufMaxCnt)
203 set_error(SpecBufOverflow, __LINE__);
209 m_nullableCnt = nullable_cnt;
210 m_varsizeCnt = varsize_cnt;
211 m_maxByteSize = max_byte_size;
216 NdbPack::Spec::add(Type type, Uint32 cnt)
218 for (Uint32
i = 0;
i < cnt;
i++)
227 NdbPack::Spec::copy(
const Spec& s2)
229 assert(m_bufMaxCnt >= s2.m_cnt);
232 m_nullableCnt = s2.m_nullableCnt;
233 m_varsizeCnt = s2.m_varsizeCnt;
234 m_maxByteSize = s2.m_maxByteSize;
235 for (Uint32
i = 0;
i < m_cnt;
i++)
237 m_buf[
i] = s2.m_buf[
i];
244 NdbPack::Iter::desc(
const Uint8* item)
246 const Uint32
i = m_cnt;
247 assert(i < m_spec.m_cnt);
248 const Type& type = m_spec.m_buf[
i];
249 const Uint32 lenBytes = type.m_arrayType;
253 bareLen = type.m_byteSize;
259 bareLen = item[0] + (item[1] << 8);
263 set_error(InternalError, __LINE__);
266 const Uint32 itemLen = lenBytes + bareLen;
267 if (itemLen > type.m_byteSize)
269 set_error(DataValueOverflow, __LINE__);
272 m_itemPos += m_itemLen;
274 m_lenBytes = lenBytes;
281 NdbPack::Iter::desc_null()
283 assert(m_cnt < m_spec.m_cnt);
285 m_itemPos += m_itemLen;
295 NdbPack::Iter::cmp(
const Iter& r2,
const Uint8* buf1,
const Uint8* buf2)
const
297 const Iter& r1 = *
this;
298 assert(&r1.m_spec == &r2.m_spec);
299 assert(r1.m_cnt == r2.m_cnt && r1.m_cnt > 0);
300 const Uint32 i = r1.m_cnt - 1;
302 const Uint32 n1 = r1.m_itemLen;
303 const Uint32 n2 = r2.m_itemLen;
308 const Type& type = r1.m_spec.m_buf[
i];
310 const Uint8* p1 = &buf1[r1.m_itemPos];
311 const Uint8* p2 = &buf2[r2.m_itemPos];
313 res = (*sqlType.m_cmp)(cs, p1, n1, p2, n2);
331 NdbPack::DataC::desc(
Iter& r)
const
333 const Uint32 i = r.m_cnt;
335 const Type& type = m_spec.m_buf[
i];
336 if (type.m_nullable || m_allNullable)
338 Uint32 nullbitPos = 0;
340 nullbitPos = type.m_nullbitPos;
343 const Uint32 byte_pos = nullbitPos / 8;
344 const Uint32 bit_pos = nullbitPos % 8;
345 const Uint8 bit_mask = (1 << bit_pos);
346 const Uint8& the_byte = m_buf[byte_pos];
347 if ((the_byte & bit_mask) != 0)
349 if (r.desc_null() == -1)
357 const Uint32 pos = r.m_itemPos + r.m_itemLen;
358 const Uint8* item = &m_buf[pos];
359 if (r.desc(item) == -1)
368 NdbPack::DataC::cmp(
const DataC& d2, Uint32 cnt, Uint32& num_eq)
const
370 const DataC& d1 = *
this;
371 assert(cnt <= d1.m_cnt);
372 assert(cnt <= d2.m_cnt);
377 for (i = 0; i < cnt; i++)
381 res = r1.cmp(r2, d1.m_buf, d2.m_buf);
392 NdbPack::Data::add(
const void* data, Uint32* len_out)
395 const Uint8* item = (
const Uint8*)data;
396 const Uint32 i = m_cnt;
397 if (i >= m_spec.m_cnt)
399 set_error(DataCntOverflow, __LINE__);
403 assert(r.m_cnt == i);
404 const Uint32 fullLen = m_varBytes + r.m_itemPos + r.m_itemLen;
405 if (r.desc(item) == -1)
410 if (fullLen + r.m_itemLen > m_bufMaxLen)
412 set_error(DataBufOverflow, __LINE__);
415 memcpy(&m_buf[fullLen], item, r.m_itemLen);
416 *len_out = r.m_itemLen;
422 NdbPack::Data::add(
const void* data, Uint32 cnt, Uint32* len_out)
424 const Uint8* data_ptr = (
const Uint8*)data;
426 for (Uint32 i = 0; i < cnt; i++)
429 if (add(data_ptr, &len) == -1)
440 NdbPack::Data::add_null(Uint32* len_out)
442 const Uint32 i = m_cnt;
443 if (i >= m_spec.m_cnt)
445 set_error(DataCntOverflow, __LINE__);
449 assert(r.m_cnt == i);
450 if (r.desc_null() == -1)
455 Uint32 nullbitPos = 0;
458 const Type& type = m_spec.m_buf[
i];
459 if (!type.m_nullable)
461 set_error(DataNotNullable, __LINE__);
464 nullbitPos = type.m_nullbitPos;
470 const Uint32 byte_pos = nullbitPos / 8;
471 const Uint32 bit_pos = nullbitPos % 8;
472 const Uint8 bit_mask = (1 << bit_pos);
473 Uint8& the_byte = m_buf[m_varBytes + byte_pos];
474 assert((the_byte & bit_mask) == 0);
475 the_byte |= bit_mask;
476 *len_out = r.m_itemLen;
482 NdbPack::Data::add_null(Uint32 cnt, Uint32* len_out)
485 for (Uint32 i = 0; i < cnt; i++)
488 if (add_null(&len) == -1)
497 NdbPack::Data::add_poai(
const Uint32* poai, Uint32* len_out)
502 if (add(&poai[1], len_out) == -1)
507 if (add_null(len_out) == -1)
510 if (ah.getByteSize() != *len_out)
512 set_error(InvalidAttrInfo, __LINE__);
519 NdbPack::Data::add_poai(
const Uint32* poai, Uint32 cnt, Uint32* len_out)
522 for (Uint32 i = 0; i < cnt; i++)
525 if (add_poai(poai, &len) == -1)
528 poai += 1 + (len + 3) / 4;
535 NdbPack::Data::finalize_impl()
537 const Uint32 dataLen = m_iter.m_itemPos + m_iter.m_itemLen;
538 switch (m_varBytes) {
548 if (dataLen <= 0xFFFF)
550 m_buf[0] = (dataLen & 0xFF);
551 m_buf[1] = (dataLen >> 8);
558 set_error(InternalError, __LINE__);
563 NdbPack::Data::desc_all(Uint32 cnt, Endian::Value from_endian)
565 if (from_endian == NdbPack::Endian::Native)
566 from_endian = NdbPack::Endian::get_endian();
567 m_endian = from_endian;
569 for (Uint32 i = 0; i < cnt; i++)
572 if (desc(m_iter) == -1)
575 if (finalize() == -1)
581 NdbPack::Data::copy(
const DataC& d2)
585 const Uint32 cnt2 = d2.m_cnt;
586 for (Uint32 i = 0; i < cnt2; i++)
588 if (d2.desc(r2) == -1)
590 Uint32 len_out = ~(Uint32)0;
591 if (r2.m_itemLen != 0)
593 if (add(&d2.m_buf[r2.m_itemPos], &len_out) == -1)
595 assert(len_out == r2.m_itemLen);
599 if (add_null(&len_out) == -1)
604 if (finalize() == -1)
610 NdbPack::Data::convert_impl(Endian::Value to_endian)
612 const Spec& spec = m_spec;
614 for (Uint32 i = 0; i < m_cnt; i++)
616 if (DataC::desc(r) == -1)
621 const Type& type = spec.m_buf[
i];
622 const Uint32 typeId = type.m_typeId;
626 Uint8* ptr = &m_buf[m_varBytes + r.m_itemPos];
627 Uint32 len = r.m_itemLen;
628 Endian::convert(ptr, len);
637 NdbPack::BoundC::finalize(
int side)
639 if (m_data.m_cnt == 0 && side != 0)
641 set_error(BoundEmptySide, __LINE__);
644 if (m_data.m_cnt != 0 && side != -1 && side != +1)
646 set_error(BoundNonemptySide, __LINE__);
654 NdbPack::BoundC::cmp(
const BoundC& b2, Uint32 cnt, Uint32& num_eq)
const
656 const BoundC& b1 = *
this;
657 const DataC& d1 = b1.m_data;
658 const DataC& d2 = b2.m_data;
659 int res = d1.cmp(d2, cnt, num_eq);
662 if (cnt < d1.m_cnt && cnt < d2.m_cnt)
664 else if (d1.m_cnt < d2.m_cnt)
665 res = (+1) * b1.m_side;
666 else if (d1.m_cnt > d2.m_cnt)
667 res = (-1) * b2.m_side;
668 else if (b1.m_side < b2.m_side)
670 else if (b1.m_side > b2.m_side)
680 NdbPack::Print::Print(
char*
buf, Uint32 bufsz) :
681 m_buf(buf), m_bufsz(bufsz), m_sz(0) {}
684 NdbPack::Print::print(
const char*
fmt, ...)
690 BaseString::vsnprintf(&m_buf[m_sz], m_bufsz - m_sz, fmt, ap);
691 m_sz += (Uint32)strlen(&m_buf[m_sz]);
706 NdbPack::Type::print(NdbOut& out)
const
709 out << print(buf,
sizeof(buf));
713 NdbPack::Type::print(
char* buf, Uint32 bufsz)
const
716 p.print(
"typeId:%u", m_typeId);
717 p.print(
" byteSize:%u", m_byteSize);
718 p.print(
" nullable:%u", m_nullable);
719 p.print(
" csNumber:%u", m_csNumber);
733 NdbPack::Spec::print(NdbOut& out)
const
736 out << print(buf,
sizeof(buf));
740 NdbPack::Spec::print(
char* buf, Uint32 bufsz)
const
743 p.print(
"cnt:%u", m_cnt);
744 p.print(
" nullableCnt:%u", m_nullableCnt);
745 p.print(
" varsizeCnt:%u", m_varsizeCnt);
746 p.print(
" nullmaskLen:%u", get_nullmask_len(
false));
747 p.print(
" maxByteSize:%u", m_maxByteSize);
748 for (Uint32 i = 0; i < m_cnt; i++)
750 const Type& type = m_buf[
i];
752 p.print(
" typeId:%u", type.m_typeId);
753 p.print(
" nullable:%u", type.m_nullable);
754 p.print(
" byteSize:%u", type.m_byteSize);
755 p.print(
" csNumber:%u", type.m_csNumber);
763 bool g_ndb_pack_print_hex_always =
true;
773 NdbPack::DataC::print(NdbOut& out)
const
776 out << print(buf,
sizeof(buf));
780 NdbPack::DataC::print(
char* buf, Uint32 bufsz,
bool convert_flag)
const
783 const Spec& spec = m_spec;
784 const Uint32 nullmask_len = spec.get_nullmask_len(m_allNullable);
785 if (nullmask_len != 0)
787 p.print(
"nullmask:");
788 for (Uint32 i = 0; i < nullmask_len; i++)
795 for (Uint32 i = 0; i < m_cnt; i++)
798 const Uint8* value = &m_buf[r.m_itemPos];
800 p.print(
" pos:%u", r.m_itemPos);
801 p.print(
" len:%u", r.m_itemLen);
806 const Type& type = spec.m_buf[
i];
808 switch (type.m_typeId) {
809 case NDB_TYPE_TINYINT:
812 memcpy(&x, value, 1);
814 Endian::convert(&x, 1);
815 p.print(
"%d", (
int)x);
818 case NDB_TYPE_TINYUNSIGNED:
821 memcpy(&x, value, 1);
823 Endian::convert(&x, 1);
824 p.print(
"%u", (uint)x);
827 case NDB_TYPE_SMALLINT:
830 memcpy(&x, value, 2);
832 Endian::convert(&x, 2);
833 p.print(
"%d", (
int)x);
836 case NDB_TYPE_SMALLUNSIGNED:
839 memcpy(&x, value, 2);
841 Endian::convert(&x, 2);
842 p.print(
"%u", (uint)x);
848 memcpy(&x, value, 4);
850 Endian::convert(&x, 4);
851 p.print(
"%d", (
int)x);
854 case NDB_TYPE_UNSIGNED:
857 memcpy(&x, value, 4);
859 Endian::convert(&x, 4);
860 p.print(
"%u", (uint)x);
866 memcpy(&x, value, 4);
868 Endian::convert(&x, 4);
869 p.print(
"%g", (
double)x);
872 case NDB_TYPE_DOUBLE:
875 memcpy(&x, value, 8);
877 Endian::convert(&x, 8);
882 case NDB_TYPE_VARCHAR:
883 case NDB_TYPE_LONGVARCHAR:
885 const Uint32 off = type.m_arrayType;
886 for (Uint32 j = 0; j < r.m_bareLen; j++)
888 Uint8 x = value[off + j];
889 p.print(
"%c", (
int)x);
897 if (!ok || g_ndb_pack_print_hex_always)
900 for (Uint32 j = 0; j < r.m_itemLen; j++)
923 NdbPack::Data::print(NdbOut& out)
const
926 out << print(buf,
sizeof(buf));
930 NdbPack::Data::print(
char* buf, Uint32 bufsz)
const
936 p.print(
"varBytes:");
937 for (Uint32 i = 0; i < m_varBytes; i++)
944 p.print(
"dataLen:%u", m_iter.m_itemPos + m_iter.m_itemLen);
946 const bool convert_flag =
947 m_endian != Endian::Native &&
948 m_endian != Endian::get_endian();
949 DataC::print(&buf[p.m_sz], bufsz - p.m_sz, convert_flag);
963 NdbPack::BoundC::print(NdbOut& out)
const
966 out << print(buf,
sizeof(buf));
970 NdbPack::BoundC::print(
char* buf, Uint32 bufsz)
const
973 p.print(
"side:%s ", m_side < 0 ? "-" : m_side > 0 ?
"+" :
"0");
974 m_data.print(&buf[p.m_sz], bufsz - p.m_sz);
988 NdbPack::Bound::print(NdbOut& out)
const
991 out << print(buf,
sizeof(buf));
995 NdbPack::Bound::print(
char* buf, Uint32 bufsz)
const
997 BoundC::print(buf, bufsz);
1004 NdbPack::Type::validate()
const
1007 if (type2.complete() == -1)
1012 if (memcmp(
this, &type2,
sizeof(Type)) != 0)
1014 set_error(ValidationError, __LINE__);
1021 NdbPack::Spec::validate()
const
1023 Uint32 nullableCnt = 0;
1024 Uint32 varsizeCnt = 0;
1025 for (Uint32 i = 0; i < m_cnt; i++)
1027 const Type& type = m_buf[
i];
1028 if (type.validate() == -1)
1033 if (type.m_nullable)
1035 if (type.m_arrayType != 0)
1038 if (m_nullableCnt != nullableCnt)
1040 set_error(ValidationError, __LINE__);
1043 if (m_varsizeCnt != varsizeCnt)
1045 set_error(ValidationError, __LINE__);
1052 NdbPack::Data::validate()
const
1054 if (DataC::validate() == -1)
1056 const Iter& r = m_iter;
1057 if (r.m_cnt != m_cnt)
1059 set_error(ValidationError, __LINE__);
1063 for (Uint32 i = 0; i < m_cnt; i++)
1068 if (r.m_itemPos != r2.m_itemPos)
1070 set_error(ValidationError, __LINE__);
1073 if (r.m_cnt != r2.m_cnt)
1075 set_error(ValidationError, __LINE__);
1078 if (r.m_nullCnt != r2.m_nullCnt)
1080 set_error(ValidationError, __LINE__);
1083 if (r.m_itemLen != r2.m_itemLen)
1085 set_error(ValidationError, __LINE__);
1092 NdbPack::BoundC::validate()
const
1094 if (m_data.validate() == -1)
1099 if (m_data.m_cnt == 0 && m_side != 0)
1101 set_error(ValidationError, __LINE__);
1104 if (m_data.m_cnt != 0 && m_side != -1 && m_side != +1)
1106 set_error(ValidationError, __LINE__);
1113 NdbPack::Bound::validate()
const
1115 if (BoundC::validate() == -1)
1117 if (m_data.validate() == -1)
1125 #ifdef TEST_NDB_PACK
1126 #include <util/NdbTap.hpp>
1128 #define chk1(x) do { if (x) break; ndbout << "line " << __LINE__ << ": " << #x << endl; require(false); } while (0)
1130 #define chk2(x, e) do { if (x) break; ndbout << "line " << __LINE__ << ": " << #x << endl; ndbout << "NdbPack code: " << (e).get_error_code() << " line: " << (e).get_error_line() << endl; require(false); } while (0)
1132 #define ll0(x) do { if (verbose < 0) break; ndbout << "0- " << x << endl; } while (0)
1133 #define ll1(x) do { if (verbose < 1) break; ndbout << "1- " << x << endl; } while (0)
1134 #define ll2(x) do { if (verbose < 2) break; ndbout << "2- " << x << endl; } while (0)
1135 #define ll3(x) do { if (verbose < 3) break; ndbout << "3- " << x << endl; } while (0)
1137 #define xmin(a, b) ((a) < (b) ? (a) : (b))
1139 #include <ndb_rand.h>
1145 uint k = ndb_rand();
1152 getrandom(uint n, uint bias)
1155 uint k = getrandom(n);
1158 k = getrandom(k + 1);
1165 getrandompct(uint pct)
1167 return getrandom(100) < pct;
1171 static int seed = -1;
1172 static int loops = 0;
1173 static int spec_cnt = -1;
1174 static int fix_type = 0;
1175 static int no_nullable = 0;
1176 static int data_cnt = -1;
1177 static int bound_cnt = -1;
1178 static int verbose = 0;
1182 enum { MaxBuf = Max * 4000 };
1186 m_spec.set_buf(m_type, Max);
1192 operator<<(NdbOut& out,
const Tspec& tspec)
1194 out << tspec.m_spec;
1202 int cnt = spec_cnt == -1 ? 1 + getrandom(Tspec::Max, 3) : spec_cnt;
1205 int typeId = fix_type;
1207 typeId = getrandom(g_ndb_pack_type_info_cnt);
1211 case NDB_TYPE_UNSIGNED:
1213 case NDB_TYPE_VARCHAR:
1214 case NDB_TYPE_LONGVARCHAR:
1219 require(info.m_supported);
1221 if (info.m_fixSize != 0)
1222 byteSize = info.m_fixSize;
1223 else if (info.m_arrayType == 0)
1224 byteSize = 1 + getrandom(128, 1);
1225 else if (info.m_arrayType == 1)
1226 byteSize = 1 + getrandom(256, 2);
1227 else if (info.m_arrayType == 2)
1228 byteSize = 2 + getrandom(1024, 3);
1231 bool nullable = no_nullable ?
false : getrandompct(50);
1233 if (info.m_charType) {
1237 chk2(m_spec.add(type) == 0, m_spec);
1240 chk2(m_spec.validate() == 0, m_spec);
1244 const Tspec& m_tspec;
1246 const bool m_isBound;
1250 int m_xoff[Tspec::Max];
1251 int m_xlen[Tspec::Max];
1252 bool m_xnull[Tspec::Max];
1258 Tdata(Tspec& tspec,
bool isBound, uint varBytes) :
1260 m_data(tspec.m_spec, isBound, varBytes),
1263 m_cnt = tspec.m_spec.get_cnt();
1270 delete [] m_poaiBuf;
1271 delete [] m_packBuf;
1277 int xcmp(
const Tdata& tdata2,
int* num_eq)
const;
1281 operator<<(NdbOut& out,
const Tdata& tdata)
1283 out << tdata.m_data;
1291 Uint8 xbuf[Tspec::MaxBuf];
1294 memset(xbuf, 0x3f,
sizeof(xbuf));
1297 Uint32 poaiBuf[Tspec::MaxBuf / 4];
1298 memset(poaiBuf, 0x5f,
sizeof(poaiBuf));
1300 m_packLen = m_data.get_var_bytes();
1301 m_packLen += (m_tspec.m_spec.get_nullable_cnt(m_isBound) + 7) / 8;
1305 const int typeId = type.get_type_id();
1307 m_xnull[
i] = type.get_nullable() && getrandompct(25);
1309 if (type.get_nullable() || m_isBound)
1310 m_xnull[i] = getrandompct(20);
1313 m_xoff[
i] = m_xsize;
1314 Uint8* xptr = &xbuf[m_xsize];
1318 Int32 x = getrandom(10);
1319 if (getrandompct(50))
1321 memcpy(xptr, &x, 4);
1322 m_xlen[
i] = info.m_fixSize;
1325 case NDB_TYPE_UNSIGNED:
1327 Uint32 x = getrandom(10);
1328 memcpy(xptr, &x, 4);
1329 m_xlen[
i] = info.m_fixSize;
1334 require(type.get_byte_size() >= 1);
1335 int max_len = type.get_byte_size();
1336 int len = getrandom(max_len + 1, 1);
1337 for (j = 0; j < len; j++)
1339 xptr[j] =
'a' + getrandom(3);
1341 for (j = len; j < max_len; j++)
1345 m_xlen[
i] = max_len;
1350 case NDB_TYPE_VARCHAR:
1352 require(type.get_byte_size() >= 1);
1353 int max_len = type.get_byte_size() - 1;
1354 int len = getrandom(max_len, 2);
1357 for (j = 0; j < len; j++)
1359 xptr[1 + j] =
'a' + getrandom(3);
1361 m_xlen[
i] = 1 + len;
1366 case NDB_TYPE_LONGVARCHAR:
1368 require(type.get_byte_size() >= 2);
1369 int max_len = type.get_byte_size() - 2;
1370 int len = getrandom(max_len, 3);
1371 require(len < 256 * 256);
1372 xptr[0] = (len & 0xFF);
1373 xptr[1] = (len >> 8);
1374 for (j = 0; j < len; j++)
1376 xptr[2 + j] =
'a' + getrandom(3);
1378 m_xlen[
i] = 2 + len;
1387 m_xsize += m_xlen[
i] + pad;
1388 while (m_xsize % 8 != 0)
1390 m_packLen += m_xlen[
i];
1396 require(m_xnull[i] == (m_xoff[i] == -1));
1397 require(m_xnull[i] == (m_xlen[i] == 0));
1399 ah->setAttributeId(i);
1400 ah->setByteSize(m_xlen[i]);
1403 memcpy(&poaiBuf[m_poaiSize], &xbuf[m_xoff[i]], m_xlen[i]);
1404 m_poaiSize += (m_xlen[
i] + 3) / 4;
1408 require(m_xsize % 8 == 0);
1409 m_xbuf = (Uint8*)
new Uint64 [m_xsize / 8];
1410 memcpy(m_xbuf, xbuf, m_xsize);
1411 m_poaiBuf = (Uint32*)
new Uint32 [m_poaiSize];
1412 memcpy(m_poaiBuf, poaiBuf, m_poaiSize << 2);
1418 m_packBuf =
new Uint8 [m_packLen];
1419 m_data.set_buf(m_packBuf, m_packLen);
1427 Uint32 xlen = ~(Uint32)0;
1429 int xoff = m_xoff[
i];
1430 const Uint8* xptr = &m_xbuf[xoff];
1431 chk2(m_data.add(xptr, &xlen) == 0, m_data);
1432 chk1((
int)xlen == m_xlen[i]);
1434 chk2(m_data.add_null(&xlen) == 0, m_data);
1439 chk2(m_data.validate() == 0, m_data);
1440 chk1((
int)m_data.get_null_cnt() == m_xnulls);
1448 chk2(m_data.finalize() == 0, m_data);
1449 ll3(
"create: " << m_data);
1450 chk1((
int)m_data.get_full_len() == m_packLen);
1452 const Uint8* p = (
const Uint8*)m_data.get_full_buf();
1453 chk1(p[0] + (p[1] << 8) == m_packLen - 2);
1458 Tdata::xcmp(
const Tdata& tdata2,
int* num_eq)
const
1460 const Tdata& tdata1 = *
this;
1461 require(&tdata1.m_tspec == &tdata2.m_tspec);
1462 const Tspec& tspec = tdata1.m_tspec;
1464 int cnt = xmin(tdata1.m_cnt, tdata2.m_cnt);
1466 for (i = 0; i < cnt; i++) {
1467 if (!tdata1.m_xnull[i]) {
1468 if (!tdata2.m_xnull[i]) {
1470 const Uint8* xptr1 = &tdata1.m_xbuf[tdata1.m_xoff[
i]];
1471 const Uint8* xptr2 = &tdata2.m_xbuf[tdata2.m_xoff[
i]];
1472 const int xlen1 = tdata1.m_xlen[
i];
1473 const int xlen2 = tdata2.m_xlen[
i];
1475 const int typeId = type.get_type_id();
1476 const int csNumber = type.get_cs_number();
1482 Int32 x1 = *(
const Int32*)xptr1;
1483 Int32 x2 = *(
const Int32*)xptr2;
1488 ll3(
"cmp res:" << res <<
" x1:" << x1 <<
" x2:" << x2);
1491 case NDB_TYPE_UNSIGNED:
1494 Uint32 x1 = *(
const Uint32*)xptr1;
1495 Uint32 x2 = *(
const Uint32*)xptr2;
1500 ll3(
"cmp res:" << res <<
" x1:" << x1 <<
" x2:" << x2);
1505 require(cs != 0 && cs->coll != 0);
1506 const uint n1 = xlen1;
1507 const uint n2 = xlen2;
1508 const uchar* t1 = &xptr1[0];
1509 const uchar* t2 = &xptr2[0];
1510 const char* s1 = (
const char*)t1;
1511 const char* s2 = (
const char*)t2;
1512 chk1(n1 == strlen(s1));
1513 chk1(n2 == strlen(s2));
1514 res = (*cs->coll->strnncollsp)(cs, t1, n1, t2, n2,
false);
1515 ll3(
"cmp res:" << res <<
" s1:" << s1 <<
" s2:" << s2);
1518 case NDB_TYPE_VARCHAR:
1520 require(cs != 0 && cs->coll != 0);
1521 const uint n1 = xptr1[0];
1522 const uint n2 = xptr2[0];
1523 const uchar* t1 = &xptr1[1];
1524 const uchar* t2 = &xptr2[1];
1525 const char* s1 = (
const char*)t1;
1526 const char* s2 = (
const char*)t2;
1527 chk1(n1 == strlen(s1));
1528 chk1(n2 == strlen(s2));
1529 res = (*cs->coll->strnncollsp)(cs, t1, n1, t2, n2,
false);
1530 ll3(
"cmp res:" << res <<
" s1:" << s1 <<
" s2:" << s2);
1533 case NDB_TYPE_LONGVARCHAR:
1535 require(cs != 0 && cs->coll != 0);
1536 const uint n1 = xptr1[0] | (xptr1[1] << 8);
1537 const uint n2 = xptr2[0] | (xptr2[1] << 8);
1538 const uchar* t1 = &xptr1[2];
1539 const uchar* t2 = &xptr2[2];
1540 const char* s1 = (
const char*)t1;
1541 const char* s2 = (
const char*)t2;
1542 chk1(n1 == strlen(s1));
1543 chk1(n2 == strlen(s2));
1544 res = (*cs->coll->strnncollsp)(cs, t1, n1, t2, n2,
false);
1545 ll3(
"cmp res:" << res <<
" s1:" << s1 <<
" s2:" << s2);
1554 }
else if (!tdata2.m_xnull[i])
1560 ll3(
"xcmp res:" << res <<
" num_eq:" << *num_eq);
1567 Tbound(Tdata& tdata) :
1569 m_bound(tdata.m_data)
1571 m_tdata.m_cnt = 1 + getrandom(m_tdata.m_cnt);
1576 int xcmp(
const Tdata& tdata2,
int* num_eq)
const;
1577 int xcmp(
const Tbound& tbound2,
int* num_eq)
const;
1581 operator<<(NdbOut& out,
const Tbound& tbound)
1583 out << tbound.m_bound;
1602 int side = getrandompct(50) ? -1 : +1;
1603 chk2(m_bound.finalize(side) == 0, m_bound);
1604 chk2(m_bound.validate() == 0, m_bound);
1605 chk1((
int)m_tdata.m_data.get_full_len() == m_tdata.m_packLen);
1609 Tbound::xcmp(
const Tdata& tdata2,
int* num_eq)
const
1611 const Tbound& tbound1 = *
this;
1612 const Tdata& tdata1 = tbound1.m_tdata;
1613 require(tdata1.m_cnt <= tdata2.m_cnt);
1615 int res = tdata1.xcmp(tdata2, num_eq);
1617 chk1(*num_eq == tdata1.m_cnt);
1618 res = m_bound.get_side();
1624 Tbound::xcmp(
const Tbound& tbound2,
int* num_eq)
const
1626 const Tbound& tbound1 = *
this;
1627 const Tdata& tdata1 = tbound1.m_tdata;
1628 const Tdata& tdata2 = tbound2.m_tdata;
1630 int res = tdata1.xcmp(tdata2, num_eq);
1631 chk1(0 <= *num_eq && *num_eq <= xmin(tdata1.m_cnt, tdata2.m_cnt));
1633 chk1(*num_eq == xmin(tdata1.m_cnt, tdata2.m_cnt));
1634 if (tdata1.m_cnt < tdata2.m_cnt)
1635 res = (+1) * tbound1.m_bound.get_side();
1636 else if (tdata1.m_cnt > tdata2.m_cnt)
1637 res = (-1) * tbound2.m_bound.get_side();
1638 else if (tbound1.m_bound.get_side() < tbound2.m_bound.get_side())
1640 else if (tbound1.m_bound.get_side() > tbound2.m_bound.get_side())
1647 enum { Max = 1000 };
1648 Tdata* m_tdata[Max];
1650 Tdatalist(Tspec& tspec) {
1651 m_cnt = data_cnt == -1 ? Max : data_cnt;
1653 for (i = 0; i < m_cnt; i++) {
1654 m_tdata[
i] =
new Tdata(tspec,
false, 2);
1659 for (i = 0; i < m_cnt; i++) {
1668 operator<<(NdbOut& out,
const Tdatalist& tdatalist)
1671 for (i = 0; i < tdatalist.m_cnt; i++) {
1672 out <<
"data " << i <<
": " << *tdatalist.m_tdata[
i];
1673 if (i + 1 < tdatalist.m_cnt)
1683 for (i = 0; i < m_cnt; i++) {
1684 Tdata& tdata = *m_tdata[
i];
1692 data_cmp(
const void* a1,
const void* a2)
1694 const Tdata& tdata1 = **(
const Tdata**)a1;
1695 const Tdata& tdata2 = **(
const Tdata**)a2;
1696 require(tdata1.m_cnt == tdata2.m_cnt);
1697 const Uint32 cnt = tdata1.m_cnt;
1698 Uint32 num_eq = ~(Uint32)0;
1699 int res = tdata1.m_data.cmp(tdata2.m_data, cnt, num_eq);
1700 require(num_eq <= (Uint32)tdata1.m_cnt);
1701 require(num_eq <= (Uint32)tdata2.m_cnt);
1708 ll1(
"data sort: in");
1710 qsort(m_tdata, m_cnt,
sizeof(Tdata*), data_cmp);
1711 ll1(
"data sort: out");
1714 for (i = 0; i + 1 < m_cnt; i++) {
1715 const Tdata& tdata1 = *m_tdata[
i];
1716 const Tdata& tdata2 = *m_tdata[i + 1];
1717 require(tdata1.m_cnt == tdata2.m_cnt);
1718 const Uint32 cnt = tdata1.m_cnt;
1719 Uint32 num_eq1 = ~(Uint32)0;
1720 int res = tdata1.m_data.cmp(tdata2.m_data, cnt, num_eq1);
1724 int res2 = tdata1.xcmp(tdata2, &num_eq2);
1731 chk1(num_eq1 == (Uint32)num_eq2);
1736 enum { Max = 1000 };
1737 Tbound* m_tbound[Max];
1739 Tboundlist(Tspec& tspec) {
1740 m_cnt = bound_cnt == -1 ? Max : bound_cnt;
1742 for (i = 0; i < m_cnt; i++) {
1743 Tdata* tdata =
new Tdata(tspec,
true, 0);
1744 m_tbound[
i] =
new Tbound(*tdata);
1749 for (i = 0; i < m_cnt; i++) {
1750 Tdata* tdata = &m_tbound[
i]->m_tdata;
1760 operator<<(NdbOut& out,
const Tboundlist& tboundlist)
1763 for (i = 0; i < tboundlist.m_cnt; i++) {
1764 out <<
"bound " << i <<
": " << *tboundlist.m_tbound[
i];
1765 if (i + 1 < tboundlist.m_cnt)
1772 Tboundlist::create()
1775 for (i = 0; i < m_cnt; i++) {
1776 Tbound& tbound = *m_tbound[
i];
1784 bound_cmp(
const void* a1,
const void* a2)
1786 const Tbound& tbound1 = **(
const Tbound**)a1;
1787 const Tbound& tbound2 = **(
const Tbound**)a2;
1788 const Uint32 cnt = xmin(tbound1.m_tdata.m_cnt, tbound2.m_tdata.m_cnt);
1789 Uint32 num_eq = ~(Uint32)0;
1790 int res = tbound1.m_bound.cmp(tbound2.m_bound, cnt, num_eq);
1791 require(num_eq <= cnt);
1792 require(num_eq <= cnt);
1799 ll1(
"bound sort: in");
1801 qsort(m_tbound, m_cnt,
sizeof(Tbound*), bound_cmp);
1802 ll1(
"bound sort: out");
1805 for (i = 0; i + 1 < m_cnt; i++) {
1806 const Tbound& tbound1 = *m_tbound[
i];
1807 const Tbound& tbound2 = *m_tbound[i + 1];
1808 const Uint32 cnt = xmin(tbound1.m_tdata.m_cnt, tbound2.m_tdata.m_cnt);
1809 Uint32 num_eq1 = ~(Uint32)0;
1810 int res = tbound1.m_bound.cmp(tbound2.m_bound, cnt, num_eq1);
1814 int res2 = tbound1.xcmp(tbound2, &num_eq2);
1821 chk1(num_eq1 == (Uint32)num_eq2);
1826 testdesc(
const Tdata& tdata)
1828 ll3(
"testdesc: " << tdata);
1829 const Tspec& tspec = tdata.m_tspec;
1831 const Uint8* buf_old = (
const Uint8*)data.get_full_buf();
1832 const Uint32 varBytes = data.get_var_bytes();
1833 const Uint32 nullMaskLen = tspec.m_spec.get_nullmask_len(
false);
1834 const Uint32 dataLen = data.get_data_len();
1835 const Uint32 fullLen = data.get_full_len();
1836 const Uint32 cnt = data.get_cnt();
1837 chk1(fullLen == varBytes + dataLen);
1839 Uint8 buf_new[Tspec::MaxBuf];
1840 data_new.set_buf(buf_new,
sizeof(buf_new));
1841 memcpy(buf_new, buf_old, fullLen);
1842 chk2(data_new.desc_all(cnt, NdbPack::Endian::Native) == 0, data_new);
1843 chk1(memcmp(buf_new, data.get_full_buf(), data.get_full_len()) == 0);
1844 chk1(data_new.get_data_len() == data.get_data_len());
1845 chk1(data_new.get_cnt() == data.get_cnt());
1846 chk1(data_new.get_null_cnt() == data.get_null_cnt());
1850 testcopy(
const Tdata& tdata)
1852 ll3(
"testcopy: " << tdata);
1853 const Tspec& tspec = tdata.m_tspec;
1855 uint n = getrandom(tdata.m_cnt + 1);
1857 ll3(
"testcopy: cnt:" << tdata.m_cnt <<
" n:" << n);
1859 data_old.set_buf(data.get_data_buf(), data.get_data_len(),
n);
1860 chk1(data_old.get_cnt() ==
n);
1862 Uint8 buf_new[Tspec::MaxBuf];
1863 data_new.set_buf(buf_new,
sizeof(buf_new));
1864 chk2(data_new.copy(data_old) == 0, data_new);
1865 chk1(data_new.get_cnt() ==
n);
1866 Uint32 num_eq1 = ~(Uint32)0;
1867 chk1(data_new.cmp(data_old, n, num_eq1) == 0);
1869 Uint32 num_eq2 = ~(Uint32)0;
1870 chk1(data_old.cmp(data_new, n, num_eq2) == 0);
1877 testpoai(
const Tdata& tdata)
1879 ll3(
"testpoai: " << tdata);
1880 const Tspec& tspec = tdata.m_tspec;
1882 NdbPack::Data data_new(tspec.m_spec,
false, data.get_var_bytes());
1883 Uint8 buf_new[Tspec::MaxBuf];
1884 data_new.set_buf(buf_new,
sizeof(buf_new));
1885 Uint32 poaiLen = ~(Uint32)0;
1886 chk2(data_new.add_poai(tdata.m_poaiBuf, tdata.m_cnt, &poaiLen) == 0, data);
1887 chk2(data_new.finalize() == 0, data_new);
1888 chk2(data_new.validate() == 0, data_new);
1889 chk1(tspec.m_spec.get_nullmask_len(
false) + poaiLen == data.get_data_len());
1890 chk1(data_new.get_full_len() == data.get_full_len());
1891 chk1(memcmp(data_new.get_full_buf(), data.get_full_buf(), data.get_full_len()) == 0);
1892 chk1(data_new.get_null_cnt() == data.get_null_cnt());
1896 testconvert(
const Tdata& tdata)
1898 ll3(
"testconvert: " << tdata);
1899 const Tspec& tspec = tdata.m_tspec;
1902 Uint8 buf_new[Tspec::MaxBuf];
1903 data_new.set_buf(buf_new,
sizeof(buf_new));
1904 chk2(data_new.copy(data) == 0, data_new);
1905 require(tdata.m_cnt == (
int)data.get_cnt());
1906 require(data.get_cnt() == data_new.get_cnt());
1907 const Uint32 cnt = tdata.m_cnt;
1910 for (i = 0; i < 10; i++) {
1911 int k = getrandom(3);
1912 NdbPack::Endian::Value v = (NdbPack::Endian::Value)k;
1913 chk2(data_new.convert(v) == 0, data_new);
1914 if (v == NdbPack::Endian::Native ||
1915 v == NdbPack::Endian::get_endian()) {
1916 num_eq = ~(Uint32)0;
1917 chk1(data.cmp(data_new, cnt, num_eq) == 0);
1918 require(num_eq == cnt);
1924 testdata(
const Tdatalist& tdatalist)
1927 for (i = 0; i < tdatalist.m_cnt; i++) {
1928 const Tdata& tdata = *tdatalist.m_tdata[
i];
1937 testcmp(
const Tbound& tbound,
const Tdatalist& tdatalist,
int* kb)
1939 ll3(
"testcmp: " << tbound);
1944 for (i = 0; i < tdatalist.m_cnt; i++) {
1945 const Tdata& tdata = *tdatalist.m_tdata[
i];
1946 require(tbound.m_tdata.m_cnt == (
int)tbound.m_bound.get_data().get_cnt());
1947 const Uint32 cnt = tbound.m_tdata.m_cnt;
1948 Uint32 num_eq1 = ~(Uint32)0;
1950 int res = (-1) * tbound.m_bound.cmp(tdata.m_data, cnt, num_eq1);
1952 res = (res < 0 ? (n1++, -1) : (n2++, +1));
1955 chk1(oldres <= res);
1960 int res2 = (-1) * tbound.xcmp(tdata, &num_eq2);
1965 chk1(num_eq1 == (Uint32)num_eq2);
1967 require(n1 + n2 == tdatalist.m_cnt);
1968 ll2(
"keys before:" << n1 <<
" after:" << n2);
1973 testcmp(
const Tboundlist& tboundlist,
const Tdatalist& tdatalist)
1977 for (i = 0; i < tboundlist.m_cnt; i++) {
1978 const Tbound& tbound = *tboundlist.m_tbound[
i];
1980 testcmp(tbound, tdatalist, &kb);
1993 ll1(
"spec: " << tspec);
1994 Tdatalist tdatalist(tspec);
1997 testdata(tdatalist);
1998 if (bound_cnt != 0) {
1999 Tboundlist tboundlist(tspec);
2000 tboundlist.create();
2002 testcmp(tboundlist, tdatalist);
2006 extern void NdbOut_Init();
2013 signal(SIGABRT, SIG_DFL);
2014 {
const char* p = NdbEnv_GetEnv(
"TEST_NDB_PACK_VERBOSE", (
char*)0, 0);
2019 ll0(
"random seed: loop number");
2023 ll0(
"random seed: " << seed);
2028 for (i = 0; loops == 0 || i < loops; i++) {
2029 ll0(
"loop:" << i <<
"/" << loops);
2035 ndbout <<
"passed" << endl;
2041 int ret = testmain();