refactored identifier, added tests and added primary_key_accessor and tests
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
#ifndef MATADOR_IDENTIFIER_HPP
|
||||
#define MATADOR_IDENTIFIER_HPP
|
||||
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
#include "matador/utils/error.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
#include "matador/utils/result.hpp"
|
||||
#include "matador/utils/types.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeindex>
|
||||
#include <variant>
|
||||
|
||||
namespace matador::utils {
|
||||
class identifier_serializer {
|
||||
@@ -31,7 +36,13 @@ template<typename Type, class Enabled = void>
|
||||
struct identifier_type_traits;
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type> > > {
|
||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type> && std::is_signed_v<Type> > > {
|
||||
static bool is_valid(Type value) { return value != 0; }
|
||||
static std::string to_string(const Type value) { return std::to_string(value); }
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type> && !std::is_signed_v<Type> > > {
|
||||
static bool is_valid(Type value) { return value > 0; }
|
||||
static std::string to_string(const Type value) { return std::to_string(value); }
|
||||
};
|
||||
@@ -48,122 +59,70 @@ struct identifier_type_traits<null_type_t, void> {
|
||||
static std::string to_string() { return "null"; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct identifier_type_traits<const char *, void> {
|
||||
static bool is_valid(const char *value);
|
||||
static std::string to_string(const char *value);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename Type>
|
||||
size_t hash(const Type &value) {
|
||||
return std::hash<Type>()(value);
|
||||
}
|
||||
|
||||
size_t hash(const char *value);
|
||||
size_t hash(const std::string &value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct is_identifier_supported : std::false_type {};
|
||||
|
||||
template <> struct is_identifier_supported<int8_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<int16_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<int32_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<int64_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<uint8_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<uint16_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<uint32_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<uint64_t> : std::true_type {};
|
||||
template <> struct is_identifier_supported<std::string> : std::true_type {};
|
||||
|
||||
template <class T>
|
||||
inline constexpr bool is_identifier_supported_v = is_identifier_supported<std::decay_t<T>>::value;
|
||||
|
||||
class identifier {
|
||||
private:
|
||||
struct base {
|
||||
base(const std::type_index &ti, basic_type type);
|
||||
base(const base &x) = delete;
|
||||
base &operator=(const base &x) = delete;
|
||||
base(base &&x) = delete;
|
||||
base &operator=(base &&x) = delete;
|
||||
virtual ~base() = default;
|
||||
|
||||
[[nodiscard]] virtual base *copy() const = 0;
|
||||
[[nodiscard]] virtual bool equal_to(const base &x) const = 0;
|
||||
[[nodiscard]] virtual bool less(const base &x) const = 0;
|
||||
[[nodiscard]] virtual bool is_valid() const = 0;
|
||||
virtual void serialize(identifier_serializer &s) = 0;
|
||||
[[nodiscard]] virtual std::string str() const = 0;
|
||||
[[nodiscard]] virtual size_t hash() const = 0;
|
||||
|
||||
std::type_index type_index_;
|
||||
basic_type type_{basic_type::Null};
|
||||
};
|
||||
|
||||
template<class IdType>
|
||||
struct pk final : base {
|
||||
using self = pk;
|
||||
|
||||
explicit pk(const IdType &id)
|
||||
: base(std::type_index(typeid(IdType)), data_type_traits<IdType>::type(1))
|
||||
, id_(id)
|
||||
, size_(sizeof(IdType)) {
|
||||
}
|
||||
|
||||
[[nodiscard]] base *copy() const override {
|
||||
return new self(id_);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool equal_to(const base &x) const override {
|
||||
return static_cast<const pk &>(x).id_ == id_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool less(const base &x) const override {
|
||||
return id_ < static_cast<const pk &>(x).id_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_valid() const override {
|
||||
return identifier_type_traits<IdType>::is_valid(id_);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string str() const override {
|
||||
return identifier_type_traits<IdType>::to_string(id_);
|
||||
}
|
||||
|
||||
void serialize(identifier_serializer &s) override {
|
||||
s.serialize(id_, size_);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t hash() const override {
|
||||
return detail::hash(id_);
|
||||
}
|
||||
|
||||
IdType id_;
|
||||
size_t size_{};
|
||||
};
|
||||
|
||||
struct null_pk final : base {
|
||||
null_pk();
|
||||
[[nodiscard]] base *copy() const override;
|
||||
[[nodiscard]] bool equal_to(const base &x) const override;
|
||||
[[nodiscard]] bool less(const base &x) const override;
|
||||
[[nodiscard]] bool is_valid() const override;
|
||||
void serialize(identifier_serializer &s) override;
|
||||
[[nodiscard]] std::string str() const override;
|
||||
[[nodiscard]] size_t hash() const override;
|
||||
null_type_t null_;
|
||||
};
|
||||
|
||||
public:
|
||||
using value_type = std::variant<
|
||||
std::monostate,
|
||||
int8_t, int16_t, int32_t, int64_t,
|
||||
uint8_t, uint16_t, uint32_t, uint64_t,
|
||||
std::string
|
||||
>;
|
||||
|
||||
identifier();
|
||||
|
||||
template<typename Type>
|
||||
explicit identifier(const Type &id)
|
||||
: id_(std::make_shared<pk<Type> >(id)) {
|
||||
template<typename Type, std::enable_if_t<is_identifier_supported_v<Type>, int> = 0>
|
||||
explicit identifier(Type &&id)
|
||||
: value_(std::forward<Type>(id)) {
|
||||
}
|
||||
|
||||
explicit identifier(const char *id)
|
||||
: id_(std::make_shared<pk<std::string> >(id)) {
|
||||
}
|
||||
|
||||
identifier(const identifier &x);
|
||||
identifier(const identifier &x) = default;
|
||||
identifier &operator=(const identifier &x);
|
||||
identifier(identifier &&x) noexcept;
|
||||
identifier &operator=(identifier &&x) noexcept;
|
||||
identifier(identifier &&x) noexcept = default;
|
||||
identifier &operator=(identifier &&x) noexcept = default;
|
||||
|
||||
template<typename Type>
|
||||
identifier &operator=(const Type &value) {
|
||||
id_ = std::make_shared<pk<Type> >(value);
|
||||
explicit identifier(std::nullptr_t);
|
||||
explicit identifier(const char *value);
|
||||
|
||||
identifier& operator=(std::nullptr_t);
|
||||
|
||||
template<typename Type, std::enable_if_t<std::is_integral_v<std::decay_t<Type>> && !std::is_same_v<std::decay_t<Type>, bool>, int> = 0>
|
||||
identifier& operator=(Type value) {
|
||||
assign_integral(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
identifier &operator=(const char *value) {
|
||||
id_ = std::make_shared<pk<std::string> >(value);
|
||||
identifier& operator=(const std::string &value);
|
||||
|
||||
identifier& operator=(const char *value);
|
||||
|
||||
template<typename Type, std::enable_if_t<is_identifier_supported_v<Type> && std::is_same_v<std::decay_t<Type>, bool>, int> = 0>
|
||||
identifier &operator=(Type &&value) {
|
||||
value_ = std::forward<Type>(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -180,17 +139,8 @@ public:
|
||||
[[nodiscard]] const std::type_index &type_index() const;
|
||||
[[nodiscard]] basic_type type() const;
|
||||
|
||||
[[nodiscard]] identifier share() const;
|
||||
[[nodiscard]] size_t use_count() const;
|
||||
|
||||
[[nodiscard]] bool is_integer() const;
|
||||
[[nodiscard]] bool is_floating_point() const;
|
||||
[[nodiscard]] bool is_bool() const;
|
||||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_timestamp() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
[[nodiscard]] bool is_valid() const;
|
||||
@@ -200,15 +150,97 @@ public:
|
||||
|
||||
[[nodiscard]] size_t hash() const;
|
||||
|
||||
template <typename Type, std::enable_if_t<is_identifier_supported_v<Type>, int> = 0>
|
||||
result<Type, error> as() const;
|
||||
|
||||
template <typename Type, std::enable_if_t<std::is_integral_v<Type> && !std::is_same_v<Type, bool>, int> = 0>
|
||||
result<Type, error> convert() const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const identifier &id);
|
||||
|
||||
private:
|
||||
explicit identifier(const std::shared_ptr<base> &id);
|
||||
template<typename Type>
|
||||
void assign_integral(Type value) {
|
||||
if constexpr (std::is_signed_v<Type>) {
|
||||
if (sizeof(Type) <= sizeof(int8_t)) {
|
||||
value_ = static_cast<int8_t>(value);
|
||||
} else if (sizeof(Type) <= sizeof(int16_t)) {
|
||||
value_ = static_cast<int16_t>(value);
|
||||
} else if (sizeof(Type) <= sizeof(int32_t)) {
|
||||
value_ = static_cast<int32_t>(value);
|
||||
} else {
|
||||
value_ = static_cast<int64_t>(value);
|
||||
}
|
||||
} else {
|
||||
if (sizeof(Type) <= sizeof(uint8_t)) {
|
||||
value_ = static_cast<uint8_t>(value);
|
||||
} else if (sizeof(Type) <= sizeof(uint16_t)) {
|
||||
value_ = static_cast<uint16_t>(value);
|
||||
} else if (sizeof(Type) <= sizeof(uint32_t)) {
|
||||
value_ = static_cast<uint32_t>(value);
|
||||
} else {
|
||||
value_ = static_cast<uint64_t>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t type_rank(const value_type &value);
|
||||
static std::type_index type_index_from_value(const value_type &value);
|
||||
static basic_type type_from_value(const value_type &value);
|
||||
|
||||
private:
|
||||
std::shared_ptr<base> id_;
|
||||
value_type value_{std::monostate{}};
|
||||
};
|
||||
|
||||
template <typename Target, typename Source>
|
||||
bool in_range(Source value) {
|
||||
if constexpr (std::is_signed_v<Source> == std::is_signed_v<Target>) {
|
||||
return value >= static_cast<Target>(std::numeric_limits<Source>::min()) &&
|
||||
value <= static_cast<Target>(std::numeric_limits<Source>::max());
|
||||
} else if constexpr (std::is_signed_v<Source> && !std::is_signed_v<Target>) {
|
||||
if (value < 0) {
|
||||
return false;
|
||||
}
|
||||
using UnsignedSource = std::make_unsigned_t<Source>;
|
||||
return static_cast<UnsignedSource>(value) <= std::numeric_limits<Target>::max();
|
||||
} else {
|
||||
return value <= static_cast<std::make_unsigned_t<Target>>(std::numeric_limits<Target>::max());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type, std::enable_if_t<is_identifier_supported_v<Type>, int>>
|
||||
result<Type, error> identifier::as() const {
|
||||
return std::visit([](const auto &v) -> result<Type, error> {
|
||||
using StoredType = std::decay_t<decltype(v)>;
|
||||
|
||||
if constexpr (std::is_same_v<StoredType, std::monostate>) {
|
||||
return failure(error{});
|
||||
} else if constexpr (std::is_same_v<StoredType, Type>) {
|
||||
return ok<Type>(v);
|
||||
} else {
|
||||
return failure(error{});
|
||||
}
|
||||
}, value_);
|
||||
}
|
||||
|
||||
template <typename Type, std::enable_if_t<std::is_integral_v<Type> && !std::is_same_v<Type, bool>, int>>
|
||||
result<Type, error> identifier::convert() const {
|
||||
return std::visit([](const auto &v) -> result<Type, error> {
|
||||
using Stored = std::decay_t<decltype(v)>;
|
||||
|
||||
if constexpr (std::is_same_v<Stored, std::monostate>) {
|
||||
return failure(error{});
|
||||
} else if constexpr (std::is_integral_v<Stored>) {
|
||||
if (!in_range<Type>(v)) {
|
||||
return failure(error{});
|
||||
}
|
||||
return ok<Type>(static_cast<Type>(v));
|
||||
} else {
|
||||
return failure(error{});
|
||||
}
|
||||
}, value_);
|
||||
}
|
||||
|
||||
static identifier null_identifier{};
|
||||
|
||||
/// @cond MATADOR_DEV
|
||||
@@ -219,13 +251,11 @@ struct id_pk_hash {
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<matador::utils::identifier> {
|
||||
struct std::hash<matador::utils::identifier> {
|
||||
size_t operator()(const matador::utils::identifier &id) const noexcept {
|
||||
return id.hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
}; // namespace std
|
||||
|
||||
#endif //MATADOR_IDENTIFIER_HPP
|
||||
#endif //MATADOR_IDENTIFIER_HPP
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef MATADOR_IDENTIFIER_ACCESSOR_HPP
|
||||
#define MATADOR_IDENTIFIER_ACCESSOR_HPP
|
||||
|
||||
#include "matador/utils/identifier.hpp"
|
||||
#include "matador/utils/result.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
class identifier_setter : public identifier_serializer {
|
||||
public:
|
||||
explicit identifier_setter(identifier &id);
|
||||
|
||||
template <typename ValueType>
|
||||
void set(const ValueType &val) {
|
||||
id_.serialize(*this, val);
|
||||
}
|
||||
void serialize(int16_t &, const field_attributes &) override;
|
||||
void serialize(int32_t &, const field_attributes &) override;
|
||||
void serialize(int64_t &, const field_attributes &) override;
|
||||
void serialize(uint8_t &, const field_attributes &) override;
|
||||
void serialize(uint16_t &, const field_attributes &) override;
|
||||
void serialize(uint32_t &, const field_attributes &) override;
|
||||
void serialize(uint64_t &, const field_attributes &) override;
|
||||
void serialize(std::string &, const field_attributes &) override;
|
||||
void serialize(null_type_t &, const field_attributes &) override;
|
||||
|
||||
private:
|
||||
identifier &id_;
|
||||
};
|
||||
}
|
||||
#endif //MATADOR_IDENTIFIER_ACCESSOR_HPP
|
||||
@@ -1,104 +1,125 @@
|
||||
#ifndef MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
||||
#define MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
||||
|
||||
#include "matador/utils/access.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
#include "matador/utils/identifier.hpp"
|
||||
#include "matador/utils/primary_key_attribute.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::utils {
|
||||
class foreign_attributes;
|
||||
namespace detail {
|
||||
template < typename PrimaryKeyType >
|
||||
class primary_key_setter {
|
||||
public:
|
||||
explicit primary_key_setter(const std::string &name, const PrimaryKeyType& value)
|
||||
: name_(name)
|
||||
, value_(value){}
|
||||
template <typename ObjectType>
|
||||
void set(ObjectType &obj, const identifier& pk) {
|
||||
pk_ = pk;
|
||||
access::process(*this, obj);
|
||||
}
|
||||
|
||||
void on_primary_key(const char *id, PrimaryKeyType &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||
if (id != nullptr && name_ == id) {
|
||||
pk = static_cast<PrimaryKeyType>(value_);
|
||||
template<typename PrimaryKeyType>
|
||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &pk, const primary_key_attribute & = default_pk_attributes) {
|
||||
const auto value = pk_.as<PrimaryKeyType>();
|
||||
if (!value) {
|
||||
// Todo: throw error
|
||||
}
|
||||
|
||||
pk = value.value();
|
||||
}
|
||||
template<typename ValueType>
|
||||
static void on_primary_key(const char * /*id*/, ValueType & /*pk*/, const utils::primary_key_attribute & = utils::default_pk_attributes) {}
|
||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||
template<typename T>
|
||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||
static void on_attribute(const char * /*id*/, T &, const field_attributes & = null_attributes) {}
|
||||
template<class P>
|
||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
static void on_belongs_to(const char * /*id*/, P &, const foreign_attributes & ) {}
|
||||
template<class P>
|
||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
static void on_has_one(const char * /*id*/, P &, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const foreign_attributes & ) {}
|
||||
|
||||
private:
|
||||
const std::string &name_;
|
||||
PrimaryKeyType value_{};
|
||||
identifier pk_{};
|
||||
};
|
||||
|
||||
struct pk_unset_checker {
|
||||
const std::string &name;
|
||||
bool unset{true};
|
||||
|
||||
template<class V>
|
||||
void on_primary_key(const char *id, V &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||
if (id != nullptr && name == id) {
|
||||
// Your convention: 0 means unset for integer PKs
|
||||
unset = (static_cast<std::uint64_t>(pk) == 0ULL);
|
||||
}
|
||||
template<class PrimaryKeyType>
|
||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &pk, const primary_key_attribute & = default_pk_attributes) {
|
||||
unset = !identifier_type_traits<PrimaryKeyType>::is_valid(pk);
|
||||
}
|
||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||
template<typename T>
|
||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||
static void on_attribute(const char * /*id*/, T &, const field_attributes & = null_attributes) {}
|
||||
template<class P>
|
||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
static void on_belongs_to(const char * /*id*/, P &, const foreign_attributes & ) {}
|
||||
template<class P>
|
||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
static void on_has_one(const char * /*id*/, P &, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const foreign_attributes & ) {}
|
||||
};
|
||||
|
||||
struct pk_value_extractor {
|
||||
struct primary_key_getter {
|
||||
std::uint64_t value{0};
|
||||
|
||||
template<class V>
|
||||
void on_primary_key(const char * /*id*/, V &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||
value = static_cast<std::uint64_t>(pk);
|
||||
template<class PrimaryKeyType>
|
||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &pk, const primary_key_attribute & = default_pk_attributes) {
|
||||
pk_ = pk;
|
||||
}
|
||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||
template<typename T>
|
||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||
static void on_attribute(const char * /*id*/, T &, const field_attributes & = null_attributes) {}
|
||||
template<class P>
|
||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
static void on_belongs_to(const char * /*id*/, P &, const foreign_attributes & ) {}
|
||||
template<class P>
|
||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
static void on_has_one(const char * /*id*/, P &, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const foreign_attributes & ) {}
|
||||
|
||||
identifier pk_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename PrimaryKeyType>
|
||||
class primary_key_accessor {
|
||||
public:
|
||||
template<class Type>
|
||||
identifier get(const Type &obj) {
|
||||
access::process(pk_getter_, obj);
|
||||
return pk_getter_.pk_;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void set(Type &obj, const identifier &pk) {
|
||||
pk_setter_.set(obj, pk);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
bool is_set(const Type &obj) {
|
||||
access::process(pk_unset_checker_, obj);
|
||||
return !pk_unset_checker_.unset;
|
||||
}
|
||||
|
||||
private:
|
||||
detail::primary_key_setter pk_setter_;
|
||||
detail::pk_unset_checker pk_unset_checker_;
|
||||
detail::primary_key_getter pk_getter_;
|
||||
|
||||
PrimaryKeyType get() const;
|
||||
PrimaryKeyType
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user