summaryrefslogtreecommitdiff
path: root/ndb/include/util/NdbSqlUtil.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/include/util/NdbSqlUtil.hpp')
-rw-r--r--ndb/include/util/NdbSqlUtil.hpp349
1 files changed, 20 insertions, 329 deletions
diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp
index a79245868e0..3062d1e4e1b 100644
--- a/ndb/include/util/NdbSqlUtil.hpp
+++ b/ndb/include/util/NdbSqlUtil.hpp
@@ -40,21 +40,25 @@ public:
* Compare kernel attribute values. Returns -1, 0, +1 for less,
* equal, greater, respectively. Parameters are pointers to values,
* full attribute size in words, and size of available data in words.
- * There are 2 special return values to check first. All values fit
- * into a signed char.
+ * There is also pointer to type specific extra info. Char types
+ * receive CHARSET_INFO in it.
+ *
+ * If available size is less than full size, CmpUnknown may be
+ * returned. If a value cannot be parsed, it compares like NULL i.e.
+ * less than any valid value.
*/
- typedef int Cmp(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size);
+ typedef int Cmp(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size);
enum CmpResult {
CmpLess = -1,
CmpEqual = 0,
CmpGreater = 1,
- CmpUnknown = 126, // insufficient partial data
- CmpError = 127 // bad data format or unimplemented comparison
+ CmpUnknown = 2 // insufficient partial data
};
/**
* Kernel data types. Must match m_typeList in NdbSqlUtil.cpp.
+ * Now also must match types in NdbDictionary.
*/
struct Type {
enum Enum {
@@ -82,19 +86,25 @@ public:
Text // Text blob
};
Enum m_typeId;
- Cmp* m_cmp; // set to NULL if cmp not implemented
+ Cmp* m_cmp; // comparison method
};
/**
* Get type by id. Can return the Undefined type.
*/
- static const Type& type(Uint32 typeId);
+ static const Type& getType(Uint32 typeId);
/**
- * Inline comparison method. Most or all real methods Type::m_cmp are
- * implemented via this (trusting dead code elimination).
+ * Get type by id but replace char type by corresponding binary type.
*/
- static int cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size);
+ static const Type& getTypeBinary(Uint32 typeId);
+
+ /**
+ * Check character set.
+ */
+ static bool usable_in_pk(Uint32 typeId, const void* cs);
+ static bool usable_in_hash_index(Uint32 typeId, const void* cs);
+ static bool usable_in_ordered_index(Uint32 typeId, const void* cs);
private:
/**
@@ -127,323 +137,4 @@ private:
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) {
- case Type::Undefined:
- break;
- case Type::Tinyint:
- {
- if (size >= 1) {
- union { Uint32 p[1]; Int8 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Tinyunsigned:
- {
- if (size >= 1) {
- union { Uint32 p[1]; Uint8 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Smallint:
- {
- if (size >= 1) {
- union { Uint32 p[1]; Int16 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Smallunsigned:
- {
- if (size >= 1) {
- union { Uint32 p[1]; Uint16 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- 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:
- {
- 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) {
- union { Uint32 p[1]; Int32 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Unsigned:
- {
- if (size >= 1) {
- union { Uint32 p[1]; Uint32 v; } u1, u2;
- u1.v = p1[0];
- u2.v = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Bigint:
- {
- if (size >= 2) {
- union { Uint32 p[2]; Int64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Bigunsigned:
- {
- if (size >= 2) {
- union { Uint32 p[2]; Uint64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Float:
- {
- if (size >= 1) {
- union { Uint32 p[1]; float v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Double:
- {
- if (size >= 2) {
- union { Uint32 p[2]; double v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
- }
- return CmpUnknown;
- }
- case Type::Decimal:
- // XXX not used by MySQL or NDB
- break;
- case Type::Char:
- {
- /*
- * Char is blank-padded to length and null-padded to word size.
- * There is no terminator so we must compare the full values.
- */
- 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::Varchar:
- {
- /*
- * Varchar is not allowed to contain a null byte and the stored
- * value is null-padded. Therefore comparison does not need to
- * use the length.
- */
- 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 = strncmp(u1.v + 2, u2.v + 2, (size << 2) - 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
- }
- return CmpUnknown;
- }
- 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:
- {
- // 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:
- {
- /*
- * Datetime is CC YY MM DD hh mm ss \0
- */
- 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);
- return k < 0 ? -1 : k > 0 ? +1 : 0;
- }
- }
- return CmpUnknown;
- }
- 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 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;
- 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;
- }
- }
- return CmpError;
-}
-
#endif