18 #include <NdbSqlUtil.hpp>
19 #include <ndb_version.h>
27 NdbSqlUtil::m_typeList[] = {
197 Type::Olddecimalunsigned,
198 cmpOlddecimalunsigned,
209 Type::Decimalunsigned,
219 if (typeId <
sizeof(m_typeList) /
sizeof(m_typeList[0]) &&
220 m_typeList[typeId].m_typeId != Type::Undefined) {
221 return m_typeList[typeId];
223 return m_typeList[Type::Undefined];
231 NdbSqlUtil::cmpTinyint(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
233 assert(info == 0 && n1 == 1 && n2 == 1);
243 NdbSqlUtil::cmpTinyunsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
245 assert(info == 0 && n1 == 1 && n2 == 1);
255 NdbSqlUtil::cmpSmallint(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
257 assert(info == 0 && n1 == 2 && n2 == 2);
267 NdbSqlUtil::cmpSmallunsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
269 assert(info == 0 && n1 == 2 && n2 == 2);
279 NdbSqlUtil::cmpMediumint(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
281 assert(info == 0 && n1 == 3 && n2 == 3);
288 int w1 = (int)sint3korr(b1);
289 int w2 = (int)sint3korr(b2);
294 NdbSqlUtil::cmpMediumunsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
296 assert(info == 0 && n1 == 3 && n2 == 3);
303 int w1 = (int)uint3korr(b1);
304 int w2 = (int)uint3korr(b2);
309 NdbSqlUtil::cmpInt(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
311 assert(info == 0 && n1 == 4 && n2 == 4);
323 NdbSqlUtil::cmpUnsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
325 assert(info == 0 && n1 == 4 && n2 == 4);
337 NdbSqlUtil::cmpBigint(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
339 assert(info == 0 && n1 == 8 && n2 == 8);
351 NdbSqlUtil::cmpBigunsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
353 assert(info == 0 && n1 == 8 && n2 == 8);
365 NdbSqlUtil::cmpFloat(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
367 assert(info == 0 && n1 == 4 && n2 == 4);
371 require(!isnan(v1) && !isnan(v2));
380 NdbSqlUtil::cmpDouble(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
382 assert(info == 0 && n1 == 8 && n2 == 8);
386 require(!isnan(v1) && !isnan(v2));
395 NdbSqlUtil::cmpOlddecimal(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
397 assert(info == 0 && n1 == n2);
398 const uchar* v1 = (
const uchar*)p1;
399 const uchar* v2 = (
const uchar*)p2;
408 }
else if (c1 ==
'-') {
410 }
else if (c2 ==
'-') {
412 }
else if (c1 < c2) {
423 NdbSqlUtil::cmpOlddecimalunsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
425 return cmpOlddecimal(info, p1, n1, p2, n2);
429 NdbSqlUtil::cmpDecimal(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
431 return cmpBinary(info, p1, n1, p2, n2);
435 NdbSqlUtil::cmpDecimalunsigned(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
437 return cmpBinary(info, p1, n1, p2, n2);
441 NdbSqlUtil::cmpChar(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
445 const uchar* v1 = (
const uchar*)p1;
446 const uchar* v2 = (
const uchar*)p2;
449 int k = (*cs->coll->strnncollsp)(cs, v1, n1, v2, n2,
false);
454 NdbSqlUtil::cmpVarchar(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
458 const uchar* v1 = (
const uchar*)p1;
459 const uchar* v2 = (
const uchar*)p2;
462 require(lb + m1 <= n1 && lb + m2 <= n2);
465 int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2,
false);
470 NdbSqlUtil::cmpBinary(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
474 const uchar* v1 = (
const uchar*)p1;
475 const uchar* v2 = (
const uchar*)p2;
478 k = memcmp(v1, v2, n1);
481 }
else if (n1 > n2) {
482 k = memcmp(v1, v2, n2);
486 k = memcmp(v1, v2, n1);
492 NdbSqlUtil::cmpVarbinary(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
496 const uchar* v1 = (
const uchar*)p1;
497 const uchar* v2 = (
const uchar*)p2;
500 require(lb + m1 <= n1 && lb + m2 <= n2);
501 int k = cmpBinary(info, v1 + lb, m1, v2 + lb, m2);
506 NdbSqlUtil::cmpDatetime(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
508 assert(info == 0 && n1 == 8 && n2 == 8);
510 memcpy(&v1, p1,
sizeof(Int64));
511 memcpy(&v2, p2,
sizeof(Int64));
520 NdbSqlUtil::cmpDate(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
522 assert(info == 0 && n1 == 3 && n2 == 3);
530 int w1 = (int)uint3korr(b1);
531 int w2 = (int)uint3korr(b2);
537 NdbSqlUtil::cmpBlob(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
545 NdbSqlUtil::cmpText(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
552 NdbSqlUtil::cmpBit(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
560 const Uint32 bytes= MIN(n1, n2);
561 Uint32 words= (bytes + 3) >> 2;
567 if (unlikely(((((UintPtr)p1) & 3) != 0) ||
568 ((((UintPtr)p2) & 3) != 0)))
570 Uint32 copyP1[ MAX_TUPLE_SIZE_IN_WORDS ];
571 Uint32 copyP2[ MAX_TUPLE_SIZE_IN_WORDS ];
572 memcpy(copyP1, p1, words << 2);
573 memcpy(copyP2, p2, words << 2);
575 return cmpBit(info, copyP1, bytes, copyP2, bytes);
578 const Uint32* wp1= (
const Uint32*) p1;
579 const Uint32* wp2= (
const Uint32*) p2;
584 if (*(wp1++) > *(wp2++))
589 const Uint32 sigBytes= bytes & 3;
590 const Uint32 mask= sigBytes?
591 (1 << (sigBytes *8)) -1 :
593 const Uint32 lastWord1= *wp1 & mask;
594 const Uint32 lastWord2= *wp2 & mask;
596 if (lastWord1 < lastWord2)
598 if (lastWord1 > lastWord2)
606 NdbSqlUtil::cmpTime(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
608 assert(info == 0 && n1 == 3 && n2 == 3);
616 int j1 = (int)sint3korr(b1);
617 int j2 = (int)sint3korr(b2);
628 NdbSqlUtil::cmpLongvarchar(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
632 const uchar* v1 = (
const uchar*)p1;
633 const uchar* v2 = (
const uchar*)p2;
634 uint m1 = v1[0] | (v1[1] << 8);
635 uint m2 = v2[0] | (v2[1] << 8);
636 require(lb + m1 <= n1 && lb + m2 <= n2);
639 int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2,
false);
644 NdbSqlUtil::cmpLongvarbinary(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
648 const uchar* v1 = (
const uchar*)p1;
649 const uchar* v2 = (
const uchar*)p2;
650 uint m1 = v1[0] | (v1[1] << 8);
651 uint m2 = v2[0] | (v2[1] << 8);
652 require(lb + m1 <= n1 && lb + m2 <= n2);
653 int k = cmpBinary(info, v1 + lb, m1, v2 + lb, m2);
658 NdbSqlUtil::cmpYear(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
660 assert(info == 0 && n1 == 1 && n2 == 1);
670 NdbSqlUtil::cmpTimestamp(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
672 assert(info == 0 && n1 == 4 && n2 == 4);
685 static const int ndb_wild_prefix =
'\\';
686 static const int ndb_wild_one =
'_';
687 static const int ndb_wild_many =
'%';
690 NdbSqlUtil::likeChar(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
692 const char* v1 = (
const char*)p1;
693 const char* v2 = (
const char*)p2;
696 n1 = (*cs->cset->lengthsp)(cs, v1, n1);
697 int k = (*cs->coll->wildcmp)(cs, v1, v1 + n1, v2, v2 + n2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
698 return k == 0 ? 0 : +1;
702 NdbSqlUtil::likeBinary(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
705 return likeChar(&my_charset_bin, p1, n1, p2, n2);
709 NdbSqlUtil::likeVarchar(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
711 const unsigned lb = 1;
713 const uchar* v1 = (
const uchar*)p1;
714 const uchar* v2 = (
const uchar*)p2;
718 const char* w1 = (
const char*)v1 + lb;
719 const char* w2 = (
const char*)v2;
721 int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
722 return k == 0 ? 0 : +1;
729 NdbSqlUtil::likeVarbinary(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
732 return likeVarchar(&my_charset_bin, p1, n1, p2, n2);
736 NdbSqlUtil::likeLongvarchar(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
738 const unsigned lb = 2;
740 const uchar* v1 = (
const uchar*)p1;
741 const uchar* v2 = (
const uchar*)p2;
742 unsigned m1 = uint2korr(v1);
745 const char* w1 = (
const char*)v1 + lb;
746 const char* w2 = (
const char*)v2;
748 int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
749 return k == 0 ? 0 : +1;
756 NdbSqlUtil::likeLongvarbinary(
const void* info,
const void* p1,
unsigned n1,
const void* p2,
unsigned n2)
759 return likeLongvarchar(&my_charset_bin, p1, n1, p2, n2);
766 NdbSqlUtil::maskBit(
const void* data,
unsigned dataLen,
const void* mask,
unsigned maskLen,
bool cmpZero)
773 const Uint32 bytes = MIN(dataLen, maskLen);
774 Uint32 words = (bytes + 3) >> 2;
780 if (unlikely(((((UintPtr)data) & 3) != 0) ||
781 ((((UintPtr)mask) & 3) != 0)))
783 Uint32 copydata[ MAX_TUPLE_SIZE_IN_WORDS ];
784 Uint32 copymask[ MAX_TUPLE_SIZE_IN_WORDS ];
785 memcpy(copydata, data, words << 2);
786 memcpy(copymask, mask, words << 2);
788 return maskBit(data, bytes, mask, bytes, cmpZero);
791 const Uint32* wdata= (
const Uint32*) data;
792 const Uint32* wmask= (
const Uint32*) mask;
798 if ((*(wdata++) & *(wmask++)) != 0)
803 const Uint32 sigBytes= bytes & 3;
804 const Uint32 comparisonMask= sigBytes?
805 (1 << (sigBytes *8)) -1 :
807 const Uint32 lastDataWord= *wdata & comparisonMask;
808 const Uint32 lastMaskWord= *wmask & comparisonMask;
810 if ((lastDataWord & lastMaskWord) != 0)
819 if ((*(wdata++) & *wmask) != *wmask)
826 const Uint32 sigBytes= bytes & 3;
827 const Uint32 comparisonMask= sigBytes?
828 (1 << (sigBytes *8)) -1 :
830 const Uint32 lastDataWord= *wdata & comparisonMask;
831 const Uint32 lastMaskWord= *wmask & comparisonMask;
833 if ((lastDataWord & lastMaskWord) != lastMaskWord)
847 switch (type.m_typeId) {
850 case Type::Longvarchar:
856 cs->coll->strnxfrm != 0 &&
857 cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
863 case Type::Undefined:
875 NdbSqlUtil::check_column_for_hash_index(Uint32 typeId,
const void* info)
881 NdbSqlUtil::check_column_for_ordered_index(Uint32 typeId,
const void* info)
884 if (type.m_cmp == NULL)
886 switch (type.m_typeId) {
889 case Type::Longvarchar:
895 cs->coll->strnxfrm != 0 &&
896 cs->coll->strnncollsp != 0 &&
897 cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
903 case Type::Undefined:
919 const unsigned char*
const src = (
const unsigned char*)p;
921 case NdbSqlUtil::Type::Varchar:
922 case NdbSqlUtil::Type::Varbinary:
926 if (attrlen >= lb + len)
930 case NdbSqlUtil::Type::Longvarchar:
931 case NdbSqlUtil::Type::Longvarbinary:
934 len = src[0] + (src[1] << 8);
935 if (attrlen >= lb + len)
951 uchar *dst,
size_t dstlen,
952 const uchar *src,
size_t srclen)
954 #if NDB_MYSQL_VERSION_D < NDB_MAKE_VERSION(5,6,0)
955 return (*cs->coll->strnxfrm)(cs, dst, dstlen, src, srclen);
962 return (*cs->coll->strnxfrm)(cs, dst, dstlen, dstlen,
963 src, srclen, MY_STRXFRM_PAD_WITH_SPACE);
972 unsigned char nsp[20];
973 unsigned char xsp[20];
975 memset(nsp, 0x1f,
sizeof(nsp));
976 memset(xsp, 0x1f,
sizeof(xsp));
979 int n1 = (*cs->cset->wc_mb)(cs, (my_wc_t)0x20, nsp, nsp +
sizeof(nsp));
987 memset(dst, 0x0, dstLen);
992 while (n4 < (
int)dstLen) {
993 dst[n4] = xsp[(n4 - n3) % n2];
1000 #if defined(WORDS_BIGENDIAN) || defined (VM_TRACE)
1003 void determineParams(Uint32 typeId,
1004 Uint32 typeLog2Size,
1007 Uint32 dataByteSize,
1018 case NdbSqlUtil::Type::Datetime:
1021 assert(typeLog2Size == 3);
1022 assert(arraySize == 8);
1023 assert(dataByteSize == 8);
1028 case NdbSqlUtil::Type::Timestamp:
1031 assert(typeLog2Size == 3);
1032 assert(arraySize == 4);
1033 assert(dataByteSize == 4);
1038 case NdbSqlUtil::Type::Bit:
1041 assert(typeLog2Size == 0);
1043 convLen = (arraySize + 31)/32;
1046 case NdbSqlUtil::Type::Blob:
1047 case NdbSqlUtil::Type::Text:
1049 if (arrayType == NDB_ARRAYTYPE_FIXED)
1053 assert(typeLog2Size == 3);
1054 assert(arraySize > 8);
1055 assert(dataByteSize > 8);
1064 convSize = 1 << typeLog2Size;
1065 convLen = arraySize;
1069 const Uint32 unitBytes = (convSize >> 3);
1071 if (dataByteSize < (unitBytes * convLen))
1078 assert((dataByteSize % unitBytes) == 0);
1079 convLen = dataByteSize / unitBytes;
1084 assert(dataByteSize >= (unitBytes * convLen));
1088 void doConvert(Uint32 convSize,
1099 Uint16* ptr = (Uint16*)data;
1100 for (Uint32 i = 0; i < convLen; i++){
1102 ((*ptr & 0xFF00) >> 8) |
1103 ((*ptr & 0x00FF) << 8);
1111 Uint32* ptr = (Uint32*)data;
1112 for (Uint32 i = 0; i < convLen; i++){
1114 ((*ptr & 0xFF000000) >> 24) |
1115 ((*ptr & 0x00FF0000) >> 8) |
1116 ((*ptr & 0x0000FF00) << 8) |
1117 ((*ptr & 0x000000FF) << 24);
1125 Uint64* ptr = (Uint64*)data;
1126 for (Uint32 i = 0; i < convLen; i++){
1128 ((*ptr & (Uint64)0xFF00000000000000LL) >> 56) |
1129 ((*ptr & (Uint64)0x00FF000000000000LL) >> 40) |
1130 ((*ptr & (Uint64)0x0000FF0000000000LL) >> 24) |
1131 ((*ptr & (Uint64)0x000000FF00000000LL) >> 8) |
1132 ((*ptr & (Uint64)0x00000000FF000000LL) << 8) |
1133 ((*ptr & (Uint64)0x0000000000FF0000LL) << 24) |
1134 ((*ptr & (Uint64)0x000000000000FF00LL) << 40) |
1135 ((*ptr & (Uint64)0x00000000000000FFLL) << 56);
1153 Uint32 typeLog2Size,
1157 Uint32 dataByteSize)
1159 #if defined(WORDS_BIGENDIAN) || defined (VM_TRACE)
1162 determineParams(typeId,
1170 size_t mask = (((size_t) convSize) >> 3) -1;
1171 bool aligned = (((size_t) data) & mask) == 0;
1172 uchar* dataPtr = data;
1173 const Uint32 bufSize = (MAX_TUPLE_SIZE_IN_WORDS + 1)/2;
1174 Uint64 alignedBuf[bufSize];
1178 assert(dataByteSize <= 4 * MAX_TUPLE_SIZE_IN_WORDS);
1179 memcpy(alignedBuf, data, dataByteSize);
1180 dataPtr = (uchar*) alignedBuf;
1189 #ifndef WORDS_BIGENDIAN
1199 memcpy(data, alignedBuf, dataByteSize);