#ifndef QUERY_IDENTIFIER_HPP #define QUERY_IDENTIFIER_HPP #include "matador/utils/field_attributes.hpp" #include #include #include #include namespace matador::utils { struct null_type_t {}; namespace detail { enum class identifier_type_t : unsigned int { INTEGRAL_TYPE, STRING_TYPE, NULL_TYPE }; template struct identifier_type_traits; template struct identifier_type_traits::value>::type> { static identifier_type_t type() { return identifier_type_t::INTEGRAL_TYPE; } static std::string type_string() { return "integral"; } static bool is_valid(Type value) { return value > 0; } static std::string to_string(Type value) { return std::to_string(value); } }; template struct identifier_type_traits::value>::type> { static identifier_type_t type() { return identifier_type_t::STRING_TYPE; } static std::string type_string() { return "string"; } static bool is_valid(const Type &value) { return !value.empty(); } static std::string to_string(Type value) { return value; } }; template struct identifier_type_traits::value>::type> { static identifier_type_t type() { return identifier_type_t::NULL_TYPE; } static std::string type_string() { return "null"; } static bool is_valid() { return false; } static std::string to_string() { return "null_pk"; } }; } class identifier_serializer { public: virtual ~identifier_serializer() = default; virtual void serialize(short &, const field_attributes &) = 0; virtual void serialize(int &, const field_attributes &) = 0; virtual void serialize(long &, const field_attributes &) = 0; virtual void serialize(long long &, const field_attributes &) = 0; virtual void serialize(unsigned short &, const field_attributes &) = 0; virtual void serialize(unsigned int &, const field_attributes &) = 0; virtual void serialize(unsigned long &, const field_attributes &) = 0; virtual void serialize(unsigned long long &, const field_attributes &) = 0; virtual void serialize(std::string &, const field_attributes &) = 0; virtual void serialize(null_type_t &, const field_attributes &) = 0; }; class identifier { private: struct base { explicit base(const std::type_index &ti, detail::identifier_type_t id_type); base(const base &x) = delete; base &operator=(const base &x) = delete; base(base &&x) = delete; base &operator=(base &&x) = delete; virtual ~base() = default; template bool is_similar_type() const { return identifier_type_ == detail::identifier_type_traits::type(); } bool is_similar_type(const base &x) const; detail::identifier_type_t type() const; virtual base *copy() const = 0; virtual bool equal_to(const base &x) const = 0; virtual bool less(const base &x) const = 0; virtual bool is_valid() const = 0; virtual void serialize(identifier_serializer &s) = 0; virtual std::string str() const = 0; virtual size_t hash() const = 0; std::type_index type_index_; detail::identifier_type_t identifier_type_; }; template struct pk : public base { using self = pk; explicit pk(const IdType &id, size_t size = 0) : base(std::type_index(typeid(IdType)), detail::identifier_type_traits::type()) , id_(id) , size_(size) {} base *copy() const final { return new self(id_, size_); } bool equal_to(const base &x) const final { return static_cast &>(x).id_ == id_; } bool less(const base &x) const final { return static_cast &>(x).id_ < id_; } bool is_valid() const final { return detail::identifier_type_traits::is_valid(id_); } std::string str() const final { return detail::identifier_type_traits::to_string(id_); } void serialize(identifier_serializer &s) final { s.serialize(id_, size_); } size_t hash() const final { std::hash hash_func; return hash_func(id_); } IdType id_; size_t size_{}; }; struct null_pk : public base { null_pk(); base *copy() const final; bool equal_to(const base &x) const final; bool less(const base &x) const final; bool is_valid() const final; void serialize(identifier_serializer &s) final; std::string str() const final; size_t hash() const final; null_type_t null_; }; public: identifier(); template explicit identifier(const Type &id, long size = -1) : id_(std::make_shared>(id, size)) {} identifier(const identifier &x); identifier &operator=(const identifier &x); identifier(identifier &&x) noexcept ; identifier &operator=(identifier &&x) noexcept; template identifier &operator=(const Type &value) { id_ = std::make_shared>(value); return *this; } ~identifier() = default; bool operator==(const identifier &x) const; bool operator!=(const identifier &x) const; bool operator<(const identifier &x) const; bool operator<=(const identifier &x) const; bool operator>(const identifier &x) const; bool operator>=(const identifier &x) const; bool is_similar_type(const identifier &x) const; template bool is_similar_type() const { return id_->is_similar_type(); } std::string str() const; const std::type_index &type_index() const; identifier share() const; size_t use_count() const; bool is_null() const; bool is_valid() const; void clear(); void serialize(identifier_serializer &s); size_t hash() const; friend std::ostream &operator<<(std::ostream &out, const identifier &id); private: explicit identifier(const std::shared_ptr& id); private: std::shared_ptr id_; }; static identifier null_identifier{}; struct id_pk_hash { size_t operator()(const identifier &id) const; }; } #endif //QUERY_IDENTIFIER_HPP