refactored identifier, added tests and added primary_key_accessor and tests

This commit is contained in:
2026-04-03 19:14:14 +02:00
parent f751541bdd
commit 920fdc68ed
9 changed files with 696 additions and 275 deletions
+163 -95
View File
@@ -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