summaryrefslogtreecommitdiff
path: root/lib/mysql_types.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mysql_types.cpp')
-rw-r--r--lib/mysql_types.cpp212
1 files changed, 212 insertions, 0 deletions
diff --git a/lib/mysql_types.cpp b/lib/mysql_types.cpp
new file mode 100644
index 0000000..fa4698d
--- /dev/null
+++ b/lib/mysql_types.cpp
@@ -0,0 +1,212 @@
+#include "mysql_types.h"
+#include "helpers.h"
+#include "rawDataReader.h"
+#include <iostream>
+#include <stdexcept>
+
+namespace MyGrate::MySQL {
+ typename Type<MYSQL_TYPE_NULL, false>::C
+ Type<MYSQL_TYPE_NULL, false>::read(RawDataReader &, RawDataReader &)
+ {
+ return nullptr;
+ }
+
+#define INTEGER_TYPE(ET) \
+ typename Type<ET, false>::C Type<ET, false>::read(RawDataReader &, RawDataReader & data) \
+ { \
+ return data.readValue<typename Type<ET>::C>(); \
+ } \
+ typename Type<ET, true>::C Type<ET, true>::read(RawDataReader &, RawDataReader & data) \
+ { \
+ return data.readValue<typename Type<ET>::C>(); \
+ }
+ INTEGER_TYPE(MYSQL_TYPE_TINY);
+ INTEGER_TYPE(MYSQL_TYPE_SHORT);
+ INTEGER_TYPE(MYSQL_TYPE_LONG);
+ INTEGER_TYPE(MYSQL_TYPE_LONGLONG);
+#undef INTEGER_TYPE
+
+#define FLOAT_TYPE(ET) \
+ typename Type<ET, false>::C Type<ET, false>::read(RawDataReader & md, RawDataReader & data) \
+ { \
+ verify<std::length_error>(sizeof(typename Type<ET>::C) == md.readValue<uint8_t>(), "Invalid " #ET " size"); \
+ return data.readValue<typename Type<ET>::C>(); \
+ }
+ FLOAT_TYPE(MYSQL_TYPE_FLOAT);
+ FLOAT_TYPE(MYSQL_TYPE_DOUBLE);
+#undef FLOAT_TYPE
+
+ typename Type<MYSQL_TYPE_DECIMAL>::C
+ Type<MYSQL_TYPE_DECIMAL>::read(RawDataReader &, RawDataReader &)
+ {
+ throw std::logic_error("Not implemented");
+ }
+
+ typename Type<MYSQL_TYPE_NEWDECIMAL>::C
+ Type<MYSQL_TYPE_NEWDECIMAL>::read(RawDataReader &, RawDataReader &)
+ {
+ throw std::logic_error("Not implemented");
+ }
+
+#define INTEGER_TYPE(ET, s, l) \
+ typename Type<ET, s>::C Type<ET, s>::read(RawDataReader &, RawDataReader & data) \
+ { \
+ return data.readValue<typename Type<ET, s>::C, l>(); \
+ }
+ INTEGER_TYPE(MYSQL_TYPE_INT24, false, 3);
+ INTEGER_TYPE(MYSQL_TYPE_INT24, true, 3);
+ INTEGER_TYPE(MYSQL_TYPE_YEAR, false, 2);
+#undef INTEGER24_TYPE
+
+ static Blob
+ readBlob(RawDataReader & md, RawDataReader & data)
+ {
+ const auto lenlen {md.readValue<uint8_t>()};
+ const auto len {data.readValue<uint64_t>(lenlen)};
+ return data.viewValue<Blob>(len);
+ }
+#define BLOB_TYPE(ET) \
+ typename Type<ET, false>::C Type<ET, false>::read(RawDataReader & md, RawDataReader & data) \
+ { \
+ return readBlob(md, data); \
+ }
+ BLOB_TYPE(MYSQL_TYPE_TINY_BLOB);
+ BLOB_TYPE(MYSQL_TYPE_MEDIUM_BLOB);
+ BLOB_TYPE(MYSQL_TYPE_LONG_BLOB);
+ BLOB_TYPE(MYSQL_TYPE_GEOMETRY); // Ummm, pass this to the target to handle?
+#undef BLOB_TYPE
+
+ typename Type<MYSQL_TYPE_BLOB, false>::C
+ Type<MYSQL_TYPE_BLOB, false>::read(RawDataReader & md, RawDataReader & data)
+ {
+ const auto lenlen {md.readValue<uint8_t>()};
+ const auto len {data.readValue<uint64_t>(lenlen)};
+ return data.viewValue<std::string_view>(len);
+ }
+
+ typename Type<MYSQL_TYPE_BIT>::C
+ Type<MYSQL_TYPE_BIT>::read(RawDataReader &, RawDataReader &)
+ {
+ throw std::logic_error("Not implemented");
+ }
+
+#define STRING_TYPE(ET) \
+ typename Type<ET, false>::C Type<ET, false>::read(RawDataReader & md, RawDataReader & data) \
+ { \
+ const auto realtype {md.readValue<enum_field_types, 1>()}; \
+ const auto lenlen {md.readValue<uint8_t>()}; \
+ switch (realtype) { \
+ case MYSQL_TYPE_ENUM: { \
+ return data.viewValue<std::string_view>(lenlen); \
+ break; \
+ } \
+ default: \
+ throw std::logic_error("Not implemented: sub-type: " + std::to_string(realtype)); \
+ break; \
+ } \
+ throw std::logic_error("Didn't return a value: " + std::to_string(realtype)); \
+ }
+ STRING_TYPE(MYSQL_TYPE_STRING);
+ STRING_TYPE(MYSQL_TYPE_JSON);
+ STRING_TYPE(MYSQL_TYPE_SET);
+ STRING_TYPE(MYSQL_TYPE_ENUM);
+#undef STRING_TYPE
+
+ typename Type<MYSQL_TYPE_VARCHAR>::C
+ Type<MYSQL_TYPE_VARCHAR>::read(RawDataReader & md, RawDataReader & data)
+ {
+ const auto fieldlen {md.readValue<uint16_t>()};
+ const auto len {data.readValue<uint16_t>(fieldlen > 255 ? 2 : 1)};
+ return data.viewValue<std::string_view>(len);
+ }
+
+ typename Type<MYSQL_TYPE_VAR_STRING>::C
+ Type<MYSQL_TYPE_VAR_STRING>::read(RawDataReader & md, RawDataReader & data)
+ {
+ const auto fieldlen {md.readValue<uint16_t>()};
+ const auto len {md.readValue<uint16_t>(fieldlen > 255 ? 2 : 1)};
+ return data.viewValue<std::string_view>(len);
+ }
+
+ typename Type<MYSQL_TYPE_DATETIME>::C
+ Type<MYSQL_TYPE_DATETIME>::read(RawDataReader &, RawDataReader & data)
+ {
+ auto dtint {data.readValue<uint64_t>()};
+ DateTime dt;
+ dt.second = mod100_extract(dtint);
+ dt.minute = mod100_extract(dtint);
+ dt.hour = mod100_extract(dtint);
+ dt.day = mod100_extract(dtint);
+ dt.month = mod100_extract(dtint);
+ dt.year = dtint;
+ return dt;
+ }
+
+ typename Type<MYSQL_TYPE_TIME>::C
+ Type<MYSQL_TYPE_TIME>::read(RawDataReader &, RawDataReader & data)
+ {
+ auto tint {data.readValue<uint32_t, 3>()};
+ Time t;
+ t.second = mod100_extract(tint);
+ t.minute = mod100_extract(tint);
+ t.hour = tint;
+ return t;
+ }
+
+ typename Type<MYSQL_TYPE_TIME2>::C
+ Type<MYSQL_TYPE_TIME2>::read(RawDataReader &, RawDataReader &)
+ {
+ throw std::logic_error("Not implemented");
+ }
+
+ typename Type<MYSQL_TYPE_DATE>::C
+ Type<MYSQL_TYPE_DATE>::read(RawDataReader &, RawDataReader & data)
+ {
+ auto dint {data.readValue<uint32_t, 3>()};
+ Date d;
+ d.day = bitslice(dint, 0, 6);
+ d.month = bitslice(dint, 6, 4);
+ d.day = bitslice(dint, 10, 14);
+ return d;
+ }
+
+ typename Type<MYSQL_TYPE_NEWDATE>::C
+ Type<MYSQL_TYPE_NEWDATE>::read(RawDataReader &, RawDataReader &)
+ {
+ throw std::logic_error("Not implemented");
+ }
+
+ typename Type<MYSQL_TYPE_TIMESTAMP>::C
+ Type<MYSQL_TYPE_TIMESTAMP>::read(RawDataReader &, RawDataReader & data)
+ {
+ return {data.readValue<int32_t>(), 0};
+ }
+
+ typename Type<MYSQL_TYPE_TIMESTAMP2>::C
+ Type<MYSQL_TYPE_TIMESTAMP2>::read(RawDataReader & md, RawDataReader & data)
+ {
+ const auto decimals {md.readValue<uint8_t>()};
+ return {data.readValue<int32_t>(), data.readValue<long>(decimals)};
+ }
+
+ typename Type<MYSQL_TYPE_DATETIME2>::C
+ Type<MYSQL_TYPE_DATETIME2>::read(RawDataReader & md, RawDataReader & data)
+ {
+ md.discard(1);
+ union {
+ uint64_t i;
+ std::array<uint8_t, 5> b;
+ } r {};
+ r.b = data.readValue<decltype(r.b)>();
+ std::reverse(r.b.begin(), r.b.end());
+
+ DateTime dt;
+ dt.year = (bitslice(r.i, 22, 17) / 13);
+ dt.month = (bitslice(r.i, 22, 17) % 13);
+ dt.day = bitslice(r.i, 17, 5);
+ dt.hour = bitslice(r.i, 12, 5);
+ dt.minute = bitslice(r.i, 6, 6);
+ dt.second = bitslice(r.i, 0, 6);
+ return dt;
+ }
+}