refactored identifier, added tests and added primary_key_accessor and tests
This commit is contained in:
@@ -1,97 +1,165 @@
|
||||
#include "matador/utils/identifier.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::utils {
|
||||
size_t detail::hash(const char *value) {
|
||||
return std::hash<std::string_view>()(std::string_view(value, std::strlen(value)));
|
||||
}
|
||||
|
||||
bool identifier_type_traits<const char *>::is_valid(const char *value) {
|
||||
return value != nullptr && strlen(value) > 0;
|
||||
}
|
||||
|
||||
std::string identifier_type_traits<const char *>::to_string(const char *value) {
|
||||
namespace {
|
||||
inline const std::type_index& null_type_index() {
|
||||
static const std::type_index value{typeid(null_type_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
identifier::base::base(const std::type_index &ti, const basic_type type)
|
||||
: type_index_(ti)
|
||||
, type_(type) {
|
||||
inline const std::type_index& i8_type_index() {
|
||||
static const std::type_index value{typeid(int8_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
identifier::null_pk::null_pk()
|
||||
: base(std::type_index(typeid(null_type_t)), basic_type::Null) {
|
||||
inline const std::type_index& i16_type_index() {
|
||||
static const std::type_index value{typeid(int16_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
identifier::base *identifier::null_pk::copy() const {
|
||||
return new null_pk;
|
||||
inline const std::type_index& i32_type_index() {
|
||||
static const std::type_index value{typeid(int32_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::equal_to(const base &x) const {
|
||||
return type_index_ == x.type_index_;
|
||||
inline const std::type_index& i64_type_index() {
|
||||
static const std::type_index value{typeid(int64_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::less(const base &x) const {
|
||||
return type_index_ == x.type_index_;
|
||||
inline const std::type_index& u8_type_index() {
|
||||
static const std::type_index value{typeid(uint8_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::is_valid() const {
|
||||
return identifier_type_traits<null_type_t>::is_valid();
|
||||
inline const std::type_index& u16_type_index() {
|
||||
static const std::type_index value{typeid(uint16_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string identifier::null_pk::str() const {
|
||||
return identifier_type_traits<null_type_t>::to_string();
|
||||
inline const std::type_index& u32_type_index() {
|
||||
static const std::type_index value{typeid(uint32_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
void identifier::null_pk::serialize(identifier_serializer &s) {
|
||||
s.serialize(null_, {});
|
||||
inline const std::type_index& u64_type_index() {
|
||||
static const std::type_index value{typeid(uint64_t)};
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t identifier::null_pk::hash() const {
|
||||
return std::hash<nullptr_t>()(nullptr);
|
||||
inline const std::type_index& string_type_index() {
|
||||
static const std::type_index value{typeid(std::string)};
|
||||
return value;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
size_t detail::hash(const std::string &value) {
|
||||
return std::hash<std::string_view>()(std::string_view(value));
|
||||
}
|
||||
|
||||
identifier::identifier()
|
||||
: id_(std::make_shared<null_pk>()) {
|
||||
: value_(std::monostate{}) {
|
||||
}
|
||||
|
||||
identifier::identifier(const identifier &x)
|
||||
: id_(x.id_->copy()) {
|
||||
size_t identifier::type_rank(const value_type &value) {
|
||||
return value.index();
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(const identifier &x) {
|
||||
if (this == &x) {
|
||||
return *this;
|
||||
std::type_index identifier::type_index_from_value(const value_type &value) {
|
||||
return std::visit([](const auto &v) -> std::type_index {
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
return null_type_index();
|
||||
} else {
|
||||
return std::type_index(typeid(T));
|
||||
}
|
||||
}, value);
|
||||
}
|
||||
|
||||
const std::type_index &identifier::type_index() const {
|
||||
switch (value_.index()) {
|
||||
case 0: return null_type_index();
|
||||
case 1: return i8_type_index();
|
||||
case 2: return i16_type_index();
|
||||
case 3: return i32_type_index();
|
||||
case 4: return i64_type_index();
|
||||
case 5: return u8_type_index();
|
||||
case 6: return u16_type_index();
|
||||
case 7: return u32_type_index();
|
||||
case 8: return u64_type_index();
|
||||
case 9: return string_type_index();
|
||||
default: return null_type_index();
|
||||
}
|
||||
id_.reset(x.id_->copy());
|
||||
return *this;
|
||||
}
|
||||
|
||||
identifier::identifier(identifier &&x) noexcept
|
||||
: id_(std::move(x.id_)) {
|
||||
x.clear();
|
||||
basic_type identifier::type_from_value(const value_type &value) {
|
||||
return std::visit([](const auto &v) -> basic_type {
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
return basic_type::Null;
|
||||
} else {
|
||||
return data_type_traits<T>::type(1);
|
||||
}
|
||||
}, value);
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(identifier &&x) noexcept {
|
||||
id_ = std::move(x.id_);
|
||||
x.clear();
|
||||
identifier::identifier(std::nullptr_t)
|
||||
: value_(std::monostate{}) {
|
||||
}
|
||||
|
||||
identifier::identifier(const char *value)
|
||||
: value_(value ? std::string(value) : std::string{}) {
|
||||
}
|
||||
|
||||
identifier & identifier::operator=(const char *value) {
|
||||
value_ = value ? std::string(value) : std::string{};
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool identifier::operator==(const identifier &x) const {
|
||||
return id_->equal_to(*x.id_);
|
||||
return value_ == x.value_;
|
||||
}
|
||||
|
||||
bool identifier::operator!=(const identifier &x) const {
|
||||
return !operator==(x);
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(std::nullptr_t) {
|
||||
value_ = std::monostate{};
|
||||
return *this;
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(const std::string &value) {
|
||||
value_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(const identifier &other) {
|
||||
if (this != &other) {
|
||||
value_ = other.value_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool identifier::operator<(const identifier &x) const {
|
||||
return id_->less(*x.id_);
|
||||
if (value_.index() != x.value_.index()) {
|
||||
return value_.index() < x.value_.index();
|
||||
}
|
||||
|
||||
return std::visit([](const auto &lhs, const auto &rhs) -> bool {
|
||||
using L = std::decay_t<decltype(lhs)>;
|
||||
using R = std::decay_t<decltype(rhs)>;
|
||||
if constexpr (std::is_same_v<L, R>) {
|
||||
return lhs < rhs;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}, value_, x.value_);
|
||||
}
|
||||
|
||||
bool identifier::operator<=(const identifier &x) const {
|
||||
@@ -107,79 +175,78 @@ bool identifier::operator>=(const identifier &x) const {
|
||||
}
|
||||
|
||||
std::string identifier::str() const {
|
||||
return id_->str();
|
||||
}
|
||||
|
||||
const std::type_index &identifier::type_index() const {
|
||||
return id_->type_index_;
|
||||
return std::visit([](const auto &v) -> std::string {
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
return identifier_type_traits<null_type_t>::to_string();
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
return identifier_type_traits<std::string>::to_string(v);
|
||||
} else {
|
||||
return identifier_type_traits<T>::to_string(v);
|
||||
}
|
||||
}, value_);
|
||||
}
|
||||
|
||||
basic_type identifier::type() const {
|
||||
return id_->type_;
|
||||
}
|
||||
|
||||
identifier identifier::share() const {
|
||||
return identifier(id_);
|
||||
}
|
||||
|
||||
size_t identifier::use_count() const {
|
||||
return id_.use_count();
|
||||
return type_from_value(value_);
|
||||
}
|
||||
|
||||
bool identifier::is_integer() const {
|
||||
return id_->type_ >= basic_type::Int8 && id_->type_ <= basic_type::UInt64;
|
||||
}
|
||||
|
||||
bool identifier::is_floating_point() const {
|
||||
return id_->type_ == basic_type::Float || id_->type_ == basic_type::Double;
|
||||
}
|
||||
|
||||
bool identifier::is_bool() const {
|
||||
return id_->type_ == basic_type::Boolean;
|
||||
return std::holds_alternative<int8_t>(value_)
|
||||
|| std::holds_alternative<int16_t>(value_)
|
||||
|| std::holds_alternative<int32_t>(value_)
|
||||
|| std::holds_alternative<int64_t>(value_)
|
||||
|| std::holds_alternative<uint8_t>(value_)
|
||||
|| std::holds_alternative<uint16_t>(value_)
|
||||
|| std::holds_alternative<uint32_t>(value_)
|
||||
|| std::holds_alternative<uint64_t>(value_);
|
||||
}
|
||||
|
||||
bool identifier::is_varchar() const {
|
||||
return id_->type_ == basic_type::Varchar;
|
||||
}
|
||||
|
||||
bool identifier::is_date() const {
|
||||
return id_->type_ == basic_type::Date;
|
||||
}
|
||||
|
||||
bool identifier::is_time() const {
|
||||
return id_->type_ == basic_type::Time;
|
||||
}
|
||||
|
||||
bool identifier::is_timestamp() const {
|
||||
return id_->type_ == basic_type::DateTime;
|
||||
}
|
||||
|
||||
bool identifier::is_blob() const {
|
||||
return id_->type_ == basic_type::Blob;
|
||||
return std::holds_alternative<std::string>(value_);
|
||||
}
|
||||
|
||||
bool identifier::is_null() const {
|
||||
return type_index() == null_identifier.type_index();
|
||||
return std::holds_alternative<std::monostate>(value_);
|
||||
}
|
||||
|
||||
bool identifier::is_valid() const {
|
||||
return id_->is_valid();
|
||||
return std::visit([](const auto &v) -> bool {
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
return identifier_type_traits<null_type_t>::is_valid();
|
||||
} else {
|
||||
return identifier_type_traits<T>::is_valid(v);
|
||||
}
|
||||
}, value_);
|
||||
}
|
||||
|
||||
void identifier::clear() {
|
||||
id_ = std::make_unique<null_pk>();
|
||||
value_ = std::monostate{};
|
||||
}
|
||||
|
||||
void identifier::serialize(identifier_serializer &s) const {
|
||||
id_->serialize(s);
|
||||
std::visit([&s](const auto &v) {
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
null_type_t n{};
|
||||
s.serialize(n, {});
|
||||
} else {
|
||||
auto tmp = v;
|
||||
s.serialize(tmp, {});
|
||||
}
|
||||
}, value_);
|
||||
}
|
||||
|
||||
size_t identifier::hash() const {
|
||||
return id_->hash();
|
||||
}
|
||||
|
||||
identifier::identifier(const std::shared_ptr<base> &id)
|
||||
: id_(id) {
|
||||
return std::visit([](const auto &v) -> size_t {
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
||||
return std::hash<int>{}(0);
|
||||
} else {
|
||||
return detail::hash(v);
|
||||
}
|
||||
}, value_);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const identifier &id) {
|
||||
@@ -190,4 +257,5 @@ std::ostream &operator<<(std::ostream &out, const identifier &id) {
|
||||
size_t id_pk_hash::operator()(const identifier &id) const {
|
||||
return id.hash();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace matador::utils
|
||||
Reference in New Issue
Block a user