#include "mysql_types.h" #include "helpers.h" #include "rawDataReader.h" #include #include #include #include #include namespace MyGrate::MySQL { #define NTOH(B) \ inline auto ntoh(uint##B##_t x) \ { \ if constexpr (__BYTE_ORDER == __LITTLE_ENDIAN) \ x = bswap_##B(x); \ return x; \ } NTOH(32); NTOH(64); typename Type::C Type::read(RawDataReader &, RawDataReader &) { return nullptr; } #define INTEGER_TYPE(ET) \ typename Type::C Type::read(RawDataReader &, RawDataReader & data) \ { \ return data.readValue::C>(); \ } \ typename Type::C Type::read(RawDataReader &, RawDataReader & data) \ { \ return data.readValue::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::C Type::read(RawDataReader & md, RawDataReader & data) \ { \ verify(sizeof(typename Type::C) == md.readValue(), "Invalid " #ET " size"); \ return data.readValue::C>(); \ } FLOAT_TYPE(MYSQL_TYPE_FLOAT); FLOAT_TYPE(MYSQL_TYPE_DOUBLE); #undef FLOAT_TYPE typename Type::C Type::read(RawDataReader &, RawDataReader &) { throw std::logic_error("Not implemented"); } typename Type::C Type::read(RawDataReader &, RawDataReader &) { throw std::logic_error("Not implemented"); } #define INTEGER_TYPE(ET, s, l) \ typename Type::C Type::read(RawDataReader &, RawDataReader & data) \ { \ return data.readValue::C, l>(); \ } INTEGER_TYPE(MYSQL_TYPE_INT24, false, 3); INTEGER_TYPE(MYSQL_TYPE_INT24, true, 3); #undef INTEGER_TYPE typename Type::C Type::read(RawDataReader &, RawDataReader & data) { auto y {data.readValue::C, 1>()}; if (y) { y += 1900; }; return y; } static Blob readBlob(RawDataReader & md, RawDataReader & data) { const auto lenlen {md.readValue()}; const auto len {data.readValue(lenlen)}; return data.viewValue(len); } #define BLOB_TYPE(ET) \ typename Type::C Type::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::C Type::read(RawDataReader & md, RawDataReader & data) { const auto lenlen {md.readValue()}; const auto len {data.readValue(lenlen)}; return data.viewValue(len); } typename Type::C Type::read(RawDataReader &, RawDataReader &) { throw std::logic_error("Not implemented"); } #define STRING_TYPE(ET) \ typename Type::C Type::read(RawDataReader & md, RawDataReader & data) \ { \ const auto realtype {md.readValue()}; \ const auto len {md.readValue()}; \ switch (realtype) { \ case MYSQL_TYPE_ENUM: \ case MYSQL_TYPE_VAR_STRING: \ return data.viewValue(len); \ default: \ throw std::logic_error("Not implemented: sub-type: " + std::to_string(realtype)); \ } \ 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::C Type::read(RawDataReader & md, RawDataReader & data) { const auto fieldlen {md.readValue()}; const auto len {data.readValue(fieldlen > 255 ? 2 : 1)}; return data.viewValue(len); } typename Type::C Type::read(RawDataReader & md, RawDataReader & data) { const auto fieldlen {md.readValue()}; const auto len {md.readValue(fieldlen > 255 ? 2 : 1)}; return data.viewValue(len); } typename Type::C Type::read(RawDataReader &, RawDataReader & data) { auto dtint {data.readValue()}; 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 = boost::numeric_cast(dtint); return dt; } typename Type::C Type::read(RawDataReader &, RawDataReader & data) { auto tint {data.readValue()}; Time t {}; t.second = mod100_extract(tint); t.minute = mod100_extract(tint); t.hour = boost::numeric_cast(tint); return t; } Time time2From24bit(uint32_t tint) { Time t {}; t.second = bitslice<6>(tint, 8); t.minute = bitslice<6>(tint, 14); t.hour = bitslice<5>(tint, 20); return t; } typename Type::C Type::read(RawDataReader & md, RawDataReader & data) { md.discard(1); return time2From24bit(ntoh(data.readValue(3))); } typename Type::C Type::read(RawDataReader &, RawDataReader & data) { const auto dint {data.readValue()}; Date d {}; d.day = bitslice<5>(dint, 0); d.month = bitslice<4>(dint, 5); d.year = bitslice<14>(dint, 9); return d; } typename Type::C Type::read(RawDataReader &, RawDataReader &) { throw std::logic_error("Not implemented"); } typename Type::C Type::read(RawDataReader &, RawDataReader & data) { return {data.readValue(), 0}; } typename Type::C Type::read(RawDataReader & md, RawDataReader & data) { const auto decimals {md.readValue()}; return {data.readValue(), data.readValue(decimals)}; } typename Type::C Type::read(RawDataReader & md, RawDataReader & data) { md.discard(1); return datetime2From40bit(ntoh(data.readValue(5))); } DateTime datetime2From40bit(uint64_t dtint) { DateTime dt; dt.year = boost::numeric_cast(bitslice<17>(dtint, 46) / 13); dt.month = boost::numeric_cast(bitslice<17>(dtint, 46) % 13); dt.day = bitslice<5>(dtint, 41); dt.hour = bitslice<5>(dtint, 36); dt.minute = bitslice<6>(dtint, 30); dt.second = bitslice<6>(dtint, 24); return dt; } }