diff options
Diffstat (limited to 'ndb/include/util/NdbSqlUtil.hpp')
-rw-r--r-- | ndb/include/util/NdbSqlUtil.hpp | 126 |
1 files changed, 105 insertions, 21 deletions
diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp index 841da513d4a..a79245868e0 100644 --- a/ndb/include/util/NdbSqlUtil.hpp +++ b/ndb/include/util/NdbSqlUtil.hpp @@ -17,8 +17,7 @@ #ifndef NDB_SQL_UTIL_HPP #define NDB_SQL_UTIL_HPP -#include <string.h> -#include <ndb_types.h> +#include <ndb_global.h> #include <kernel/ndb_limits.h> class NdbSqlUtil { @@ -80,7 +79,7 @@ public: Datetime, // Precision down to 1 sec (size 8 bytes) Timespec, // Precision down to 1 nsec (size 12 bytes) Blob, // Blob - Clob // Text blob + Text // Text blob }; Enum m_typeId; Cmp* m_cmp; // set to NULL if cmp not implemented @@ -125,12 +124,13 @@ private: static Cmp cmpDatetime; static Cmp cmpTimespec; static Cmp cmpBlob; - static Cmp cmpClob; + static Cmp cmpText; }; inline int NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size) { + // XXX require size >= 1 if (size > full) return CmpError; switch ((Type::Enum)typeId) { @@ -192,10 +192,38 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, } return CmpUnknown; } - case Type::Mediumint: // XXX fix these - break; + case Type::Mediumint: + { + if (size >= 1) { + union { const Uint32* p; const unsigned char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + Int32 v1 = sint3korr(u1.v); + Int32 v2 = sint3korr(u2.v); + if (v1 < v2) + return -1; + if (v1 > v2) + return +1; + return 0; + } + return CmpUnknown; + } case Type::Mediumunsigned: - break; + { + if (size >= 1) { + union { const Uint32* p; const unsigned char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + Uint32 v1 = uint3korr(u1.v); + Uint32 v2 = uint3korr(u2.v); + if (v1 < v2) + return -1; + if (v1 > v2) + return +1; + return 0; + } + return CmpUnknown; + } case Type::Int: { if (size >= 1) { @@ -287,6 +315,7 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, return CmpUnknown; } case Type::Decimal: + // XXX not used by MySQL or NDB break; case Type::Char: { @@ -317,10 +346,28 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, } return CmpUnknown; } - case Type::Binary: // XXX fix these - break; + case Type::Binary: + { + // compare byte wise + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + int k = memcmp(u1.v, u2.v, size << 2); + return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; + } case Type::Varbinary: - break; + { + // assume correctly padded and compare byte wise + if (size >= 1) { + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + // length in first 2 bytes + int k = memcmp(u1.v + 2, u2.v + 2, (size << 2) - 2); + return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; + } + return CmpUnknown; + } case Type::Datetime: { /* @@ -331,29 +378,66 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, u1.p = p1; u2.p = p2; // skip format check - int k = strncmp(u1.v, u2.v, 4); + int k = memcmp(u1.v, u2.v, 4); if (k != 0) - return k; + return k < 0 ? -1 : +1; if (size >= 2) { - return strncmp(u1.v + 4, u2.v + 4, 4); + k = memcmp(u1.v + 4, u2.v + 4, 4); + return k < 0 ? -1 : k > 0 ? +1 : 0; } } return CmpUnknown; } - case Type::Timespec: // XXX fix this - break; - case Type::Blob: // XXX fix - break; - case Type::Clob: + case Type::Timespec: + { + /* + * Timespec is CC YY MM DD hh mm ss \0 NN NN NN NN + */ + if (size >= 1) { + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1; + u2.p = p2; + // skip format check + int k = memcmp(u1.v, u2.v, 4); + if (k != 0) + return k < 0 ? -1 : +1; + if (size >= 2) { + k = memcmp(u1.v + 4, u2.v + 4, 4); + if (k != 0) + return k < 0 ? -1 : +1; + Uint32 n1 = *(const Uint32*)(u1.v + 8); + Uint32 n2 = *(const Uint32*)(u2.v + 8); + if (n1 < n2) + return -1; + if (n2 > n1) + return +1; + return 0; + } + } + return CmpUnknown; + } + case Type::Blob: { - // skip blob head, the rest is varchar + // skip blob head, the rest is binary const unsigned skip = NDB_BLOB_HEAD_SIZE; if (size >= skip + 1) { union { const Uint32* p; const char* v; } u1, u2; u1.p = p1 + skip; u2.p = p2 + skip; - // length in first 2 bytes - int k = strncmp(u1.v + 2, u2.v + 2, ((size - skip) << 2) - 2); + int k = memcmp(u1.v, u2.v, (size - 1) << 2); + return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; + } + return CmpUnknown; + } + case Type::Text: + { + // skip blob head, the rest is char + const unsigned skip = NDB_BLOB_HEAD_SIZE; + if (size >= skip + 1) { + union { const Uint32* p; const char* v; } u1, u2; + u1.p = p1 + skip; + u2.p = p2 + skip; + int k = memcmp(u1.v, u2.v, (size - 1) << 2); return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown; } return CmpUnknown; |