Compare commits
No commits in common. "57246d874299a431963a3cdfb781412e51c98e1b" and "f751541bddff3fc2c4a5f14b50fa69ab2061aeb2" have entirely different histories.
57246d8742
...
f751541bdd
|
|
@ -281,7 +281,7 @@ utils::result<std::vector<object::attribute>, utils::error> postgres_connection:
|
||||||
null_opt = object::null_option_type::NotNull;
|
null_opt = object::null_option_type::NotNull;
|
||||||
}
|
}
|
||||||
// f.default_value(res->column(4));
|
// f.default_value(res->column(4));
|
||||||
prototype.emplace_back(name, type, utils::NullAttributes, null_opt);
|
prototype.emplace_back(name, type, utils::null_attributes, null_opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok(prototype);
|
return utils::ok(prototype);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ public:
|
||||||
attribute() = default;
|
attribute() = default;
|
||||||
attribute(std::string name,
|
attribute(std::string name,
|
||||||
utils::basic_type type,
|
utils::basic_type type,
|
||||||
const utils::field_attributes& opts = utils::NullAttributes,
|
const utils::field_attributes& opts = utils::null_attributes,
|
||||||
null_option_type null_opt = null_option_type::NotNull)
|
null_option_type null_opt = null_option_type::NotNull)
|
||||||
: name_(std::move(name)), type_(type), options_(opts), null_option_type_(null_opt) {}
|
: name_(std::move(name)), type_(type), options_(opts), null_option_type_(null_opt) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public:
|
||||||
attribute() = default;
|
attribute() = default;
|
||||||
attribute(std::string name,
|
attribute(std::string name,
|
||||||
utils::basic_type type,
|
utils::basic_type type,
|
||||||
const utils::field_attributes &attr = utils::NullAttributes,
|
const utils::field_attributes &attr = utils::null_attributes,
|
||||||
null_option_type null_opt = null_option_type::NotNull);
|
null_option_type null_opt = null_option_type::NotNull);
|
||||||
|
|
||||||
[[nodiscard]] const std::string& name() const;
|
[[nodiscard]] const std::string& name() const;
|
||||||
|
|
@ -39,9 +39,9 @@ public:
|
||||||
[[nodiscard]] bool is_nullable() const;
|
[[nodiscard]] bool is_nullable() const;
|
||||||
[[nodiscard]] utils::basic_type type() const;
|
[[nodiscard]] utils::basic_type type() const;
|
||||||
[[nodiscard]] std::shared_ptr<object> owner() const;
|
[[nodiscard]] std::shared_ptr<object> owner() const;
|
||||||
void change_type(utils::basic_type type, const utils::field_attributes &attr = utils::NullAttributes);
|
void change_type(utils::basic_type type, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
void change_type(const utils::field_attributes &attr = utils::NullAttributes) {
|
void change_type(const utils::field_attributes &attr = utils::null_attributes) {
|
||||||
type_ = utils::data_type_traits<Type>::type(attr.size());
|
type_ = utils::data_type_traits<Type>::type(attr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class PrimaryKeyType>
|
template<class PrimaryKeyType>
|
||||||
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute & /*attr*/) {}
|
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute & /*attr*/ = utils::default_pk_attributes) {}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<typename AttributeType>
|
template<typename AttributeType>
|
||||||
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<typename AttributeType>
|
template<typename AttributeType>
|
||||||
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class ForeignPointerType>
|
template<class ForeignPointerType>
|
||||||
void on_belongs_to(const char *id, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/);
|
void on_belongs_to(const char *id, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/);
|
||||||
template<class ForeignPointerType>
|
template<class ForeignPointerType>
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ public:
|
||||||
return join_columns_;
|
return join_columns_;
|
||||||
}
|
}
|
||||||
template < class V >
|
template < class V >
|
||||||
static void on_primary_key(const char * /*id*/, V &, const utils::primary_key_attribute& /*attr*/) {}
|
static void on_primary_key(const char * /*id*/, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
static void on_attribute(const char * /*id*/, Type &, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *, ValueType &/*pk*/, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *, ValueType &/*pk*/, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
type_ = utils::data_type_traits<ValueType>::type(attr.size());
|
type_ = utils::data_type_traits<ValueType>::type(attr.size());
|
||||||
}
|
}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
static void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
|
|
@ -75,14 +75,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_primary_key(const char *, Type &x, const utils::primary_key_attribute& attr);
|
void on_primary_key(const char *, Type &x, const utils::primary_key_attribute& attr = utils::default_pk_attributes);
|
||||||
void on_revision(const char *id, uint64_t &rev);
|
void on_revision(const char *id, uint64_t &rev);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &x, const utils::field_attributes &attr);
|
void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, std::optional<Type> &x, const utils::field_attributes &attr);
|
void on_attribute(const char *id, std::optional<Type> &x, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct pk_field_locator {
|
||||||
: base(&obj) {}
|
: base(&obj) {}
|
||||||
|
|
||||||
template <typename PrimaryKeyType>
|
template <typename PrimaryKeyType>
|
||||||
void on_primary_key(const char *, PrimaryKeyType &pk, const utils::primary_key_attribute & /*attr*/) {
|
void on_primary_key(const char *, PrimaryKeyType &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||||
// Offset bestimmen
|
// Offset bestimmen
|
||||||
const auto* obj_bytes = reinterpret_cast<std::uint8_t*>(base);
|
const auto* obj_bytes = reinterpret_cast<std::uint8_t*>(base);
|
||||||
const auto* pk_bytes = reinterpret_cast<std::uint8_t*>(&pk);
|
const auto* pk_bytes = reinterpret_cast<std::uint8_t*>(&pk);
|
||||||
|
|
@ -113,7 +113,7 @@ struct pk_field_locator {
|
||||||
}
|
}
|
||||||
static void on_revision(const char *, std::uint64_t &) {}
|
static void on_revision(const char *, std::uint64_t &) {}
|
||||||
template <typename V>
|
template <typename V>
|
||||||
static void on_attribute(const char *, V &, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char *, V &, const utils::field_attributes & = matador::utils::null_attributes) {}
|
||||||
template <typename Pointer>
|
template <typename Pointer>
|
||||||
static void on_belongs_to(const char *, Pointer &, const utils::foreign_attributes &) {}
|
static void on_belongs_to(const char *, Pointer &, const utils::foreign_attributes &) {}
|
||||||
template <typename Pointer>
|
template <typename Pointer>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_primary_key(const char *id, Type &pk, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *id, Type &pk, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
primary_key_info_.pk_column_name = id;
|
primary_key_info_.pk_column_name = id;
|
||||||
primary_key_info_.type = utils::data_type_traits<Type>::type(attr.size());
|
primary_key_info_.type = utils::data_type_traits<Type>::type(attr.size());
|
||||||
primary_key_info_.pk = pk;
|
primary_key_info_.pk = pk;
|
||||||
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
static void on_attribute(const char * /*id*/, Type &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*val*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*val*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class PrimaryKeyType>
|
template<class PrimaryKeyType>
|
||||||
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute& /*attr*/) {}
|
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<typename AttributeType>
|
template<typename AttributeType>
|
||||||
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<typename AttributeType>
|
template<typename AttributeType>
|
||||||
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
|
|
||||||
template<class ForeignPointerType>
|
template<class ForeignPointerType>
|
||||||
void on_belongs_to(const char *id, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char *id, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
||||||
|
|
@ -103,12 +103,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class PrimaryKeyType>
|
template<class PrimaryKeyType>
|
||||||
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute& /*attr*/) {}
|
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<typename AttributeType>
|
template<typename AttributeType>
|
||||||
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<typename AttributeType>
|
template<typename AttributeType>
|
||||||
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
|
|
||||||
template<class ForeignPointerType>
|
template<class ForeignPointerType>
|
||||||
void on_belongs_to(const char *id, ForeignPointerType &obj, const utils::foreign_attributes &attr);
|
void on_belongs_to(const char *id, ForeignPointerType &obj, const utils::foreign_attributes &attr);
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void on_primary_key(const char * /*id*/, Type &x, const utils::primary_key_attribute & /*attr*/) {
|
void on_primary_key(const char * /*id*/, Type &x, const utils::primary_key_attribute & /*attr*/ = utils::default_pk_attributes) {
|
||||||
stmt_.bind(binding_position_, x);
|
stmt_.bind(binding_position_, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,17 +187,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,12 @@ public:
|
||||||
return generator_type_;
|
return generator_type_;
|
||||||
}
|
}
|
||||||
template<class V>
|
template<class V>
|
||||||
void on_primary_key(const char * /*id*/, V &/*pk*/, const utils::primary_key_attribute &attr) {
|
void on_primary_key(const char * /*id*/, V &/*pk*/, const utils::primary_key_attribute &attr = utils::default_pk_attributes) {
|
||||||
generator_type_ = attr.generator();
|
generator_type_ = attr.generator();
|
||||||
}
|
}
|
||||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||||
template<class P>
|
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 utils::foreign_attributes & ) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
|
|
|
||||||
|
|
@ -60,15 +60,15 @@ struct dependency_collector {
|
||||||
std::vector<fk_ref> refs;
|
std::vector<fk_ref> refs;
|
||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
static void on_primary_key(const char*, V&, const utils::primary_key_attribute& /*attr*/) {}
|
static void on_primary_key(const char*, V&, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
|
|
||||||
static void on_revision(const char*, std::uint64_t&) {}
|
static void on_revision(const char*, std::uint64_t&) {}
|
||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
static void on_attribute(const char*, V&, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char*, V&, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_belongs_to(const char* id, Pointer& p, utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char* id, Pointer& p, utils::foreign_attributes &attr) {
|
||||||
// Erwartung: Pointer verhält sich wie matador::object::object_ptr<T>
|
// Erwartung: Pointer verhält sich wie matador::object::object_ptr<T>
|
||||||
// also: p.get() liefert raw ptr, und Pointer::value_type / element_type ist T.
|
// also: p.get() liefert raw ptr, und Pointer::value_type / element_type ist T.
|
||||||
auto* raw = p.get();
|
auto* raw = p.get();
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *, ValueType &pk, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char *, ValueType &pk, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
value_ = pk;
|
value_ = pk;
|
||||||
}
|
}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
static void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
push(id);
|
push(id);
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
push(id);
|
push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class CollectionType>
|
template<class CollectionType>
|
||||||
void on_has_many(const char * /*id*/, CollectionType &, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/, std::enable_if_t<!object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
void on_has_many(const char * /*id*/, CollectionType &, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t<!object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
|
|
@ -170,13 +170,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
void on_primary_key(const char * /*id*/, V &/*x*/, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char * /*id*/, V &/*x*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
result_.emplace_back(utils::_);
|
result_.emplace_back(utils::_);
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
result_.emplace_back(utils::_);
|
result_.emplace_back(utils::_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -228,13 +228,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
void on_primary_key(const char *id, V &x, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char *id, V &x, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
push_back(id, x);
|
push_back(id, x);
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
push_back(id, x);
|
push_back(id, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,81 @@
|
||||||
#include "matador/query/query.hpp"
|
#include "matador/query/query.hpp"
|
||||||
#include "matador/query/query_builder_exception.hpp"
|
#include "matador/query/query_builder_exception.hpp"
|
||||||
|
|
||||||
#include "matador/utils/primary_key_accessor.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
|
struct pk_setter {
|
||||||
|
const std::string &name;
|
||||||
|
std::uint64_t value;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
pk = static_cast<V>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {}
|
||||||
|
template<class P>
|
||||||
|
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
|
template<class P>
|
||||||
|
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
|
template<class C>
|
||||||
|
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::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 & ) {}
|
||||||
|
template<class C>
|
||||||
|
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {}
|
||||||
|
template<class P>
|
||||||
|
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
|
template<class P>
|
||||||
|
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
|
template<class C>
|
||||||
|
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::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 & ) {}
|
||||||
|
template<class C>
|
||||||
|
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pk_value_extractor {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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) {}
|
||||||
|
template<class P>
|
||||||
|
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
|
template<class P>
|
||||||
|
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
|
template<class C>
|
||||||
|
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::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 & ) {}
|
||||||
|
template<class C>
|
||||||
|
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||||
|
};
|
||||||
|
|
||||||
class insert_query_builder {
|
class insert_query_builder {
|
||||||
public:
|
public:
|
||||||
using step_query_t = std::variant<executable_query, fetchable_query>;
|
using step_query_t = std::variant<executable_query, fetchable_query>;
|
||||||
|
|
@ -18,7 +90,10 @@ public:
|
||||||
|
|
||||||
// Session uses these to handle manual/sequence/table pre-insert PKs
|
// Session uses these to handle manual/sequence/table pre-insert PKs
|
||||||
utils::generator_type pk_generator{utils::generator_type::Manual};
|
utils::generator_type pk_generator{utils::generator_type::Manual};
|
||||||
utils::primary_key_accessor pk_accessor;
|
std::string pk_name;
|
||||||
|
|
||||||
|
std::function<bool()> pk_is_unset{};
|
||||||
|
std::function<void(std::uint64_t)> set_pk{};
|
||||||
|
|
||||||
// Identity post-insert
|
// Identity post-insert
|
||||||
std::function<void(const sql::record &)> apply_returning{};
|
std::function<void(const sql::record &)> apply_returning{};
|
||||||
|
|
@ -48,11 +123,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
static void on_primary_key(const char * /*id*/, V &, const utils::primary_key_attribute& /*attr*/) {}
|
static void on_primary_key(const char * /*id*/, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
static void on_revision(const char *id, uint64_t &/*rev*/);
|
static void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
static void on_attribute(const char * /*id*/, Type &, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_belongs_to(const char * /*id*/, Pointer &obj, const utils::foreign_attributes &attr) {
|
void on_belongs_to(const char * /*id*/, Pointer &obj, const utils::foreign_attributes &attr) {
|
||||||
|
|
@ -63,19 +138,8 @@ public:
|
||||||
void on_has_one(const char * /*id*/, Pointer &obj, const utils::foreign_attributes &attr) {
|
void on_has_one(const char * /*id*/, Pointer &obj, const utils::foreign_attributes &attr) {
|
||||||
on_foreign_object(obj, attr);
|
on_foreign_object(obj, attr);
|
||||||
}
|
}
|
||||||
template<class CollectionType>
|
template<class Collection>
|
||||||
void on_has_many(const char * /*id*/, CollectionType &con, const char *, const utils::foreign_attributes &attr, std::enable_if_t<object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
static void on_has_many(const char * /*id*/, Collection &/*con*/, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||||
if (!utils::is_cascade_type_set(attr.cascade(), utils::cascade_type::Insert)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto &obj : con) {
|
|
||||||
obj.is_persistent() ? build_for(obj) : on_foreign_object(obj, attr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
template<class CollectionType>
|
|
||||||
void on_has_many(const char * /*id*/, CollectionType &/*con*/, const char *, const utils::foreign_attributes &/*attr*/, std::enable_if_t<!object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {}
|
|
||||||
template<class Collection>
|
template<class Collection>
|
||||||
void on_has_many_to_many(const char *id, Collection &container, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes & ) {
|
void on_has_many_to_many(const char *id, Collection &container, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes & ) {
|
||||||
if (id == nullptr || join_column == nullptr || inverse_join_column == nullptr) {
|
if (id == nullptr || join_column == nullptr || inverse_join_column == nullptr) {
|
||||||
|
|
@ -105,18 +169,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract FK value from the foreign object
|
// Extract FK value from the foreign object
|
||||||
insert_step rel_step{};
|
pk_value_extractor fk{};
|
||||||
const auto pk = rel_step.pk_accessor.get(obj);
|
access::process(fk, *obj);
|
||||||
if (pk.is_valid()) {
|
if (fk.value == 0ULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build INSERT into relation table with the 2 FK columns
|
// Build INSERT into relation table with the 2 FK columns
|
||||||
// rel_step.query = executable_query{
|
insert_step rel_step{};
|
||||||
// insert()
|
rel_step.query = executable_query{
|
||||||
// .into(relation_table, {table_column{&relation_table, join_column}, table_column{&relation_table, inverse_join_column}})
|
insert()
|
||||||
// .values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}})
|
.into(relation_table, {table_column{&relation_table, join_column}, table_column{&relation_table, inverse_join_column}})
|
||||||
// };
|
.values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}})
|
||||||
|
};
|
||||||
relation_steps_.push_back(std::move(rel_step));
|
relation_steps_.push_back(std::move(rel_step));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,18 +227,29 @@ private:
|
||||||
const auto &info = it->second.node().info();
|
const auto &info = it->second.node().info();
|
||||||
insert_step step{};
|
insert_step step{};
|
||||||
if (info.has_primary_key()) {
|
if (info.has_primary_key()) {
|
||||||
|
step.pk_name = info.primary_key_attribute()->name();
|
||||||
step.pk_generator = it->second.pk_generator().type();
|
step.pk_generator = it->second.pk_generator().type();
|
||||||
|
|
||||||
|
step.pk_is_unset = [ptr, name = step.pk_name]() {
|
||||||
|
pk_unset_checker chk{name};
|
||||||
|
access::process(chk, *ptr);
|
||||||
|
return chk.unset;
|
||||||
|
};
|
||||||
|
|
||||||
|
step.set_pk = [ptr, name = step.pk_name](std::uint64_t v) {
|
||||||
|
pk_setter setter{name, v};
|
||||||
|
access::process(setter, *ptr);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.has_primary_key() && step.pk_generator == utils::generator_type::Identity) {
|
if (info.has_primary_key() && step.pk_generator == utils::generator_type::Identity) {
|
||||||
const auto pk_name = info.primary_key_attribute()->name();
|
const table_column pk_col(&it->second.table(), step.pk_name);
|
||||||
const table_column pk_col(&it->second.table(), pk_name);
|
|
||||||
step.query = fetchable_query{insert().into(it->second.table()).values(*ptr).returning(pk_col)};
|
step.query = fetchable_query{insert().into(it->second.table()).values(*ptr).returning(pk_col)};
|
||||||
step.apply_returning = [ptr, &step, pk_name = pk_name](const sql::record &rec) {
|
step.apply_returning = [ptr, pk_name = step.pk_name](const sql::record &rec) {
|
||||||
const auto& f = rec.at(pk_name);
|
if (auto v = rec.at<std::uint64_t>(pk_name); v.has_value()) {
|
||||||
utils::identifier id;
|
pk_setter setter{pk_name, *v};
|
||||||
id.assign(f.value());
|
access::process(setter, *ptr);
|
||||||
step.pk_accessor.set(*ptr, id);
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
step.query = executable_query{insert().into(it->second.table()).values(*ptr)};
|
step.query = executable_query{insert().into(it->second.table()).values(*ptr)};
|
||||||
|
|
@ -202,7 +278,6 @@ private:
|
||||||
std::vector<insert_step> relation_steps_;
|
std::vector<insert_step> relation_steps_;
|
||||||
std::unordered_set<std::pair<std::type_index, const void *>, visit_key_hash> visited_;
|
std::unordered_set<std::pair<std::type_index, const void *>, visit_key_hash> visited_;
|
||||||
|
|
||||||
|
|
||||||
std::uint64_t current_entity_pk_{0};
|
std::uint64_t current_entity_pk_{0};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
void on_primary_key(const char *id, V &x, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char *id, V &x, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
result_.emplace_back(id, x);
|
result_.emplace_back(id, x);
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/) const;
|
void on_revision(const char *id, uint64_t &/*rev*/) const;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
result_.emplace_back(id, x);
|
result_.emplace_back(id, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,10 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
static void on_primary_key(const char * /*id*/, ValueType &/*value*/, const utils::primary_key_attribute& /*attr*/) {}
|
static void on_primary_key(const char * /*id*/, ValueType &/*value*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<class Type>
|
template<class Type>
|
||||||
static void on_attribute(const char * /*id*/, Type &/*value*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*value*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
push(id);
|
push(id);
|
||||||
if (!is_root_entity()) {
|
if (!is_root_entity()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -101,7 +101,7 @@ public:
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/)
|
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes)
|
||||||
{
|
{
|
||||||
push(id);
|
push(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *, ValueType &x, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *, ValueType &x, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
utils::data_type_traits<ValueType>::bind_value(*this, 0, x, attr.size());
|
utils::data_type_traits<ValueType>::bind_value(*this, 0, x, attr.size());
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &rev);
|
void on_revision(const char *id, uint64_t &rev);
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_attribute(const char *, Type &x, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
utils::data_type_traits<Type>::bind_value(*this, 0, x);
|
utils::data_type_traits<Type>::bind_value(*this, 0, x);
|
||||||
}
|
}
|
||||||
void on_attribute(const char *id, char *x, const utils::field_attributes &/*attr*/);
|
void on_attribute(const char *id, char *x, const utils::field_attributes &/*attr*/ = utils::null_attributes);
|
||||||
void on_attribute(const char *id, std::string &x, const utils::field_attributes &/*attr*/);
|
void on_attribute(const char *id, std::string &x, const utils::field_attributes &/*attr*/ = utils::null_attributes);
|
||||||
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
template<class Type, template < class ... > class Pointer>
|
||||||
void on_belongs_to(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/) {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ public:
|
||||||
[[nodiscard]] utils::constraints type() const;
|
[[nodiscard]] utils::constraints type() const;
|
||||||
[[nodiscard]] size_t size() const;
|
[[nodiscard]] size_t size() const;
|
||||||
[[nodiscard]] int index() const;
|
[[nodiscard]] int index() const;
|
||||||
[[nodiscard]] utils::value value() const;
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
std::optional<Type> as() const {
|
std::optional<Type> as() const {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template < class V >
|
||||||
void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/) {
|
void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
if (has_many_to_many_) {
|
if (has_many_to_many_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ public:
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
if (has_many_to_many_) {
|
if (has_many_to_many_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
utils::data_type_traits<ValueType>::read_value(reader_, id, column_index_, value, attr.size());
|
utils::data_type_traits<ValueType>::read_value(reader_, id, column_index_, value, attr.size());
|
||||||
identifier_ = value;
|
identifier_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
|
|
|
||||||
|
|
@ -28,21 +28,21 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr);
|
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes);
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
@ -74,32 +74,32 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_primary_key(const char *id, Type &val, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *id, Type &val, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
utils::data_type_traits<Type>::read_value(*binder_, id, index_++, val, attr.size());
|
utils::data_type_traits<Type>::read_value(*binder_, id, index_++, val, attr.size());
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char *id, Type &val, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *id, Type &val, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
utils::data_type_traits<Type>::read_value(*binder_, id, index_++, val);
|
utils::data_type_traits<Type>::read_value(*binder_, id, index_++, val);
|
||||||
}
|
}
|
||||||
void on_attribute(const char *id, char *value, const utils::field_attributes &attr);
|
void on_attribute(const char *id, char *value, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
void on_attribute(const char *id, std::string &value, const utils::field_attributes &attr);
|
void on_attribute(const char *id, std::string &value, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr);
|
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
template<class Type, template < class ... > class Pointer>
|
||||||
void on_belongs_to(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||||
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class Type, template < class ... > class Pointer>
|
template<class Type, template < class ... > class Pointer>
|
||||||
void on_has_one(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/) {
|
void on_has_one(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||||
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr);
|
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes);
|
||||||
void on_revision(const char * /*id*/, uint64_t &/*rev*/) {
|
void on_revision(const char * /*id*/, uint64_t &/*rev*/) {
|
||||||
++column_index_;
|
++column_index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
++column_index_;
|
++column_index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public:
|
||||||
size_t column_index = 0);
|
size_t column_index = 0);
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
utils::data_type_traits<ValueType>::read_value(*reader_, id, column_index_++, value, attr.size());
|
utils::data_type_traits<ValueType>::read_value(*reader_, id, column_index_++, value, attr.size());
|
||||||
if (type_stack_.size() == 1) {
|
if (type_stack_.size() == 1) {
|
||||||
last_pk_ = current_pk_;
|
last_pk_ = current_pk_;
|
||||||
|
|
@ -52,13 +52,13 @@ public:
|
||||||
void on_revision(const char *id, uint64_t &rev);
|
void on_revision(const char *id, uint64_t &rev);
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
utils::data_type_traits<Type>::read_value(*reader_, id, column_index_++, x);
|
utils::data_type_traits<Type>::read_value(*reader_, id, column_index_++, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_attribute(const char *id, char *value, const utils::field_attributes &attr);
|
void on_attribute(const char *id, char *value, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
void on_attribute(const char *id, std::string &value, const utils::field_attributes &attr);
|
void on_attribute(const char *id, std::string &value, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr);
|
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_belongs_to(const char * /*id*/, Pointer &x, const utils::foreign_attributes &attr) {
|
void on_belongs_to(const char * /*id*/, Pointer &x, const utils::foreign_attributes &attr) {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &/*value*/, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char *id, ValueType &/*value*/, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
if (!type_stack_.empty()) {
|
if (!type_stack_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -39,8 +39,8 @@ public:
|
||||||
void on_revision(const char * /*id*/, uint64_t &/*rev*/) { ++column_index_; }
|
void on_revision(const char * /*id*/, uint64_t &/*rev*/) { ++column_index_; }
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) { ++column_index_; }
|
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) { ++column_index_; }
|
||||||
void on_attribute(const char *id, const utils::value &x, const utils::field_attributes &attr);
|
void on_attribute(const char *id, const utils::value &x, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &attr) { on_foreign_key<typename Pointer::value_type>(attr.fetch() ); }
|
void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &attr) { on_foreign_key<typename Pointer::value_type>(attr.fetch() ); }
|
||||||
|
|
|
||||||
|
|
@ -18,29 +18,29 @@ public:
|
||||||
[[nodiscard]] size_t current_index() const;
|
[[nodiscard]] size_t current_index() const;
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_primary_key(const char * /*id*/, Type &val, const utils::primary_key_attribute& attr) {
|
void on_primary_key(const char * /*id*/, Type &val, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
utils::data_type_traits<Type>::bind_value(*binder_, index_++, val, attr.size());
|
utils::data_type_traits<Type>::bind_value(*binder_, index_++, val, attr.size());
|
||||||
}
|
}
|
||||||
void on_revision(const char *id, uint64_t &/*rev*/);
|
void on_revision(const char *id, uint64_t &/*rev*/);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void on_attribute(const char * /*id*/, Type &val, const utils::field_attributes &/*attr*/) {
|
void on_attribute(const char * /*id*/, Type &val, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
||||||
utils::data_type_traits<Type>::bind_value(*binder_, index_++, val);
|
utils::data_type_traits<Type>::bind_value(*binder_, index_++, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
template<class Type, template < class ... > class Pointer>
|
||||||
void on_belongs_to(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||||
pk_binder_.bind(*x, index_++, *binder_);
|
pk_binder_.bind(*x, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class Type, template < class ... > class Pointer>
|
template<class Type, template < class ... > class Pointer>
|
||||||
void on_has_one(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/) {
|
void on_has_one(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||||
pk_binder_.bind(*x, index_++, *binder_);
|
pk_binder_.bind(*x, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -20,21 +20,21 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr);
|
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes);
|
||||||
static void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {}
|
static void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {}
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
#ifndef OOS_ACCESS_HPP
|
#ifndef OOS_ACCESS_HPP
|
||||||
#define OOS_ACCESS_HPP
|
#define OOS_ACCESS_HPP
|
||||||
|
|
||||||
#include "matador/utils/primary_key_attribute.hpp"
|
#include <cstdint>
|
||||||
#include "matador/utils/field_attributes.hpp"
|
|
||||||
#include "matador/utils/foreign_attributes.hpp"
|
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace matador {
|
namespace matador {
|
||||||
|
|
@ -32,66 +29,108 @@ template<class Base, class Derived, class Operator>
|
||||||
void process_base(Operator &op, const Derived &object) {
|
void process_base(Operator &op, const Derived &object) {
|
||||||
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
||||||
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
||||||
op.on_base(static_cast<const Base&>(object));
|
process(op, static_cast<const Base&>(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Base, class Derived, class Operator>
|
template<class Base, class Derived, class Operator>
|
||||||
void process_base(Operator &op, Derived &object) {
|
void process_base(Operator &op, Derived &object) {
|
||||||
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
||||||
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
||||||
op.on_base(static_cast<Base&>(object));
|
process(op, static_cast<Base&>(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
template< class Operator, class Type >
|
template< class Operator, class Type >
|
||||||
void primary_key(Operator &op, const char *id, Type &value, const utils::primary_key_attribute &attr = utils::DefaultPkAttributes) {
|
void primary_key(Operator &op, const char *id, Type &value, const utils::primary_key_attribute &attr) {
|
||||||
op.on_primary_key(id, value, attr);
|
op.on_primary_key(id, value, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< class Operator, class Type >
|
||||||
|
void primary_key(Operator &op, const char *id, Type &value) {
|
||||||
|
op.on_primary_key(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void revision(Operator &op, const char *id, uint64_t &value) {
|
void revision(Operator &op, const char *id, uint64_t &value) {
|
||||||
op.on_revision(id, value);
|
op.on_revision(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Operator, class Type>
|
template<class Operator, class Type>
|
||||||
void attribute(Operator &op, const char *id, Type &value, const utils::field_attributes &attr = utils::NullAttributes) {
|
void attribute(Operator &op, const char *id, Type &value, const utils::field_attributes &attr) {
|
||||||
op.on_attribute(id, value, attr);
|
op.on_attribute(id, value, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Operator, class Type>
|
template<class Operator, class Type>
|
||||||
void attribute(Operator &op, const char *id, std::optional<Type> &value, const utils::field_attributes &attr = utils::NullAttributes) {
|
void attribute(Operator &op, const char *id, std::optional<Type> &value, const utils::field_attributes &attr) {
|
||||||
op.on_attribute(id, value, attr);
|
op.on_attribute(id, value, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Operator, class Type>
|
template<class Operator, class Type>
|
||||||
void has_one(Operator &op, const char *id, Type &value, const utils::foreign_attributes &attr = utils::CascadeNoneFetchLazy) {
|
void attribute(Operator &op, const char *id, Type &value) {
|
||||||
|
op.on_attribute(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Operator, class Type>
|
||||||
|
void has_one(Operator &op, const char *id, Type &value, const utils::foreign_attributes &attr) {
|
||||||
op.on_has_one(id, value, attr);
|
op.on_has_one(id, value, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Operator, class Type>
|
template<class Operator, class Type>
|
||||||
void belongs_to(Operator &op, const char *id, Type &value, const utils::foreign_attributes &attr = utils::CascadeNoneFetchLazy) {
|
void has_one(Operator &op, const char *id, Type &value) {
|
||||||
|
op.on_has_one(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Operator, class Type>
|
||||||
|
void belongs_to(Operator &op, const char *id, Type &value, const utils::foreign_attributes &attr) {
|
||||||
op.on_belongs_to(id, value, attr);
|
op.on_belongs_to(id, value, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Operator, class Type>
|
||||||
|
void belongs_to(Operator &op, const char *id, Type &value) {
|
||||||
|
op.on_belongs_to(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||||
void has_many(Operator &op, const char *id, ContainerType<Type> &c, const char *join_column, const utils::foreign_attributes &attr = utils::CascadeNoneFetchLazy) {
|
void has_many(Operator &op, const char *id, ContainerType<Type> &c, const char *join_column, const utils::foreign_attributes &attr) {
|
||||||
op.on_has_many(id, c, join_column, attr);
|
op.on_has_many(id, c, join_column, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Operator, class Type, template<class ...> class ContainerType>
|
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||||
void has_many(Operator &op, const char *id, ContainerType<Type> &c, const utils::foreign_attributes &attr = utils::CascadeNoneFetchLazy) {
|
void has_many(Operator &op, const char *id, ContainerType<Type> &c, const char *join_column) {
|
||||||
|
op.on_has_many(id, c, join_column);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||||
|
void has_many(Operator &op, const char *id, ContainerType<Type> &c, const utils::foreign_attributes &attr) {
|
||||||
op.on_has_many(id, c, attr);
|
op.on_has_many(id, c, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Operator, class Type, template<class ...> class ContainerType>
|
||||||
|
void has_many(Operator &op, const char *id, ContainerType<Type> &c) {
|
||||||
|
op.on_has_many(id, c);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Operator, class ContainerType>
|
template<class Operator, class ContainerType>
|
||||||
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &attr = utils::CascadeNoneFetchLazy) {
|
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &attr) {
|
||||||
op.on_has_many_to_many(id, c, join_column, inverse_join_column, attr);
|
op.on_has_many_to_many(id, c, join_column, inverse_join_column, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Operator, class ContainerType>
|
template<class Operator, class ContainerType>
|
||||||
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const utils::foreign_attributes &attr = utils::CascadeNoneFetchLazy) {
|
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column) {
|
||||||
|
op.on_has_many_to_many(id, c, join_column, inverse_join_column);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Operator, class ContainerType>
|
||||||
|
void has_many_to_many(Operator &op, const char *id, ContainerType &c, const utils::foreign_attributes &attr) {
|
||||||
op.on_has_many_to_many(id, c, attr);
|
op.on_has_many_to_many(id, c, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Operator, class ContainerType>
|
||||||
|
void has_many_to_many(Operator &op, const char *id, ContainerType &c) {
|
||||||
|
op.on_has_many_to_many(id, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //OOS_ACCESS_HPP
|
#endif //OOS_ACCESS_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ namespace matador::utils {
|
||||||
|
|
||||||
enum class utils_error {
|
enum class utils_error {
|
||||||
InvalidVersionString,
|
InvalidVersionString,
|
||||||
IdentifierTypeMismatch
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class utils_category_impl final : public std::error_category
|
class utils_category_impl final : public std::error_category
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ private:
|
||||||
constraints options_ = constraints::None;
|
constraints options_ = constraints::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
const field_attributes NullAttributes {};
|
const field_attributes null_attributes {};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //MATADOR_FIELD_ATTRIBUTES_HPP
|
#endif //MATADOR_FIELD_ATTRIBUTES_HPP
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,16 @@
|
||||||
#ifndef MATADOR_IDENTIFIER_HPP
|
#ifndef MATADOR_IDENTIFIER_HPP
|
||||||
#define MATADOR_IDENTIFIER_HPP
|
#define MATADOR_IDENTIFIER_HPP
|
||||||
|
|
||||||
#include "matador/utils/basic_types.hpp"
|
|
||||||
#include "matador/utils/default_type_traits.hpp"
|
#include "matador/utils/default_type_traits.hpp"
|
||||||
#include "matador/utils/error.hpp"
|
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
#include "matador/utils/result.hpp"
|
#include "matador/utils/basic_types.hpp"
|
||||||
#include "matador/utils/types.hpp"
|
#include "matador/utils/types.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
class value;
|
|
||||||
class identifier_serializer {
|
class identifier_serializer {
|
||||||
public:
|
public:
|
||||||
virtual ~identifier_serializer() = default;
|
virtual ~identifier_serializer() = default;
|
||||||
|
|
@ -37,13 +31,7 @@ template<typename Type, class Enabled = void>
|
||||||
struct identifier_type_traits;
|
struct identifier_type_traits;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type> && std::is_signed_v<Type> > > {
|
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_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 bool is_valid(Type value) { return value > 0; }
|
||||||
static std::string to_string(const Type value) { return std::to_string(value); }
|
static std::string to_string(const Type value) { return std::to_string(value); }
|
||||||
};
|
};
|
||||||
|
|
@ -60,77 +48,127 @@ struct identifier_type_traits<null_type_t, void> {
|
||||||
static std::string to_string() { return "null"; }
|
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 {
|
namespace detail {
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
size_t hash(const Type &value) {
|
size_t hash(const Type &value) {
|
||||||
return std::hash<Type>()(value);
|
return std::hash<Type>()(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hash(const std::string &value);
|
size_t hash(const char *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 {
|
class identifier {
|
||||||
public:
|
private:
|
||||||
using value_type = std::variant<
|
struct base {
|
||||||
std::monostate,
|
base(const std::type_index &ti, basic_type type);
|
||||||
int8_t, int16_t, int32_t, int64_t,
|
base(const base &x) = delete;
|
||||||
uint8_t, uint16_t, uint32_t, uint64_t,
|
base &operator=(const base &x) = delete;
|
||||||
std::string
|
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:
|
||||||
identifier();
|
identifier();
|
||||||
template<typename Type, std::enable_if_t<is_identifier_supported_v<Type>, int> = 0>
|
|
||||||
explicit identifier(Type &&id)
|
template<typename Type>
|
||||||
: value_(std::forward<Type>(id)) {
|
explicit identifier(const Type &id)
|
||||||
|
: id_(std::make_shared<pk<Type> >(id)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier(const identifier &x) = default;
|
explicit identifier(const char *id)
|
||||||
|
: id_(std::make_shared<pk<std::string> >(id)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
identifier(const identifier &x);
|
||||||
identifier &operator=(const identifier &x);
|
identifier &operator=(const identifier &x);
|
||||||
identifier(identifier &&x) noexcept = default;
|
identifier(identifier &&x) noexcept;
|
||||||
identifier &operator=(identifier &&x) noexcept = default;
|
identifier &operator=(identifier &&x) noexcept;
|
||||||
|
|
||||||
explicit identifier(std::nullptr_t);
|
template<typename Type>
|
||||||
explicit identifier(const char *value);
|
identifier &operator=(const Type &value) {
|
||||||
|
id_ = std::make_shared<pk<Type> >(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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier& operator=(const std::string &value);
|
identifier &operator=(const char *value) {
|
||||||
identifier& operator=(const char *value);
|
id_ = std::make_shared<pk<std::string> >(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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~identifier() = default;
|
~identifier() = default;
|
||||||
|
|
||||||
result<void, error> assign(const value &val);
|
|
||||||
|
|
||||||
static result<identifier, error> from_value(const value &val);
|
|
||||||
[[nodiscard]] database_type to_database_type() 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 operator<(const identifier &x) const;
|
||||||
|
|
@ -142,8 +180,17 @@ public:
|
||||||
[[nodiscard]] const std::type_index &type_index() const;
|
[[nodiscard]] const std::type_index &type_index() const;
|
||||||
[[nodiscard]] basic_type type() const;
|
[[nodiscard]] basic_type type() const;
|
||||||
|
|
||||||
|
[[nodiscard]] identifier share() const;
|
||||||
|
[[nodiscard]] size_t use_count() const;
|
||||||
|
|
||||||
[[nodiscard]] bool is_integer() 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_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_null() const;
|
||||||
|
|
||||||
[[nodiscard]] bool is_valid() const;
|
[[nodiscard]] bool is_valid() const;
|
||||||
|
|
@ -153,97 +200,15 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] size_t hash() const;
|
[[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);
|
friend std::ostream &operator<<(std::ostream &out, const identifier &id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Type>
|
explicit identifier(const std::shared_ptr<base> &id);
|
||||||
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:
|
private:
|
||||||
value_type value_{std::monostate{}};
|
std::shared_ptr<base> id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
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{};
|
static identifier null_identifier{};
|
||||||
|
|
||||||
/// @cond MATADOR_DEV
|
/// @cond MATADOR_DEV
|
||||||
|
|
@ -254,11 +219,13 @@ struct id_pk_hash {
|
||||||
/// @endcond
|
/// @endcond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace std {
|
||||||
template<>
|
template<>
|
||||||
struct std::hash<matador::utils::identifier> {
|
struct hash<matador::utils::identifier> {
|
||||||
size_t operator()(const matador::utils::identifier &id) const noexcept {
|
size_t operator()(const matador::utils::identifier &id) const noexcept {
|
||||||
return id.hash();
|
return id.hash();
|
||||||
}
|
}
|
||||||
}; // namespace std
|
};
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
#endif //MATADOR_IDENTIFIER_HPP
|
#endif //MATADOR_IDENTIFIER_HPP
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
#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,125 +1,104 @@
|
||||||
#ifndef MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
#ifndef MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
||||||
#define 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/field_attributes.hpp"
|
||||||
#include "matador/utils/identifier.hpp"
|
|
||||||
#include "matador/utils/primary_key_attribute.hpp"
|
#include "matador/utils/primary_key_attribute.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
class foreign_attributes;
|
class foreign_attributes;
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
template < typename PrimaryKeyType >
|
||||||
class primary_key_setter {
|
class primary_key_setter {
|
||||||
public:
|
public:
|
||||||
template <typename ObjectType>
|
explicit primary_key_setter(const std::string &name, const PrimaryKeyType& value)
|
||||||
void set(ObjectType &obj, const identifier& pk) {
|
: name_(name)
|
||||||
pk_ = pk;
|
, value_(value){}
|
||||||
access::process(*this, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename PrimaryKeyType>
|
void on_primary_key(const char *id, PrimaryKeyType &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &pk, const primary_key_attribute & = DefaultPkAttributes) {
|
if (id != nullptr && name_ == id) {
|
||||||
const auto value = pk_.as<PrimaryKeyType>();
|
pk = static_cast<PrimaryKeyType>(value_);
|
||||||
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*/) {}
|
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void on_attribute(const char * /*id*/, T &, const field_attributes & = NullAttributes) {}
|
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
static void on_belongs_to(const char * /*id*/, P &, const foreign_attributes & ) {}
|
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
static void on_has_one(const char * /*id*/, P &, const foreign_attributes & ) {}
|
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const foreign_attributes & ) {}
|
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const foreign_attributes & ) {}
|
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const foreign_attributes & ) {}
|
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
identifier pk_{};
|
const std::string &name_;
|
||||||
|
PrimaryKeyType value_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pk_unset_checker {
|
struct pk_unset_checker {
|
||||||
|
const std::string &name;
|
||||||
bool unset{true};
|
bool unset{true};
|
||||||
|
|
||||||
template<class PrimaryKeyType>
|
template<class V>
|
||||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &pk, const primary_key_attribute & = DefaultPkAttributes) {
|
void on_primary_key(const char *id, V &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||||
unset = !identifier_type_traits<PrimaryKeyType>::is_valid(pk);
|
if (id != nullptr && name == id) {
|
||||||
|
// Your convention: 0 means unset for integer PKs
|
||||||
|
unset = (static_cast<std::uint64_t>(pk) == 0ULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void on_attribute(const char * /*id*/, T &, const field_attributes & = NullAttributes) {}
|
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
static void on_belongs_to(const char * /*id*/, P &, const foreign_attributes & ) {}
|
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
static void on_has_one(const char * /*id*/, P &, const foreign_attributes & ) {}
|
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const foreign_attributes & ) {}
|
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const foreign_attributes & ) {}
|
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const foreign_attributes & ) {}
|
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct primary_key_getter {
|
struct pk_value_extractor {
|
||||||
std::uint64_t value{0};
|
std::uint64_t value{0};
|
||||||
|
|
||||||
template<class PrimaryKeyType>
|
template<class V>
|
||||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &pk, const primary_key_attribute & = DefaultPkAttributes) {
|
void on_primary_key(const char * /*id*/, V &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||||
pk_ = pk;
|
value = static_cast<std::uint64_t>(pk);
|
||||||
}
|
}
|
||||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void on_attribute(const char * /*id*/, T &, const field_attributes & = NullAttributes) {}
|
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
static void on_belongs_to(const char * /*id*/, P &, const foreign_attributes & ) {}
|
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
template<class P>
|
template<class P>
|
||||||
static void on_has_one(const char * /*id*/, P &, const foreign_attributes & ) {}
|
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const foreign_attributes & ) {}
|
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const foreign_attributes & ) {}
|
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class C>
|
template<class C>
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const foreign_attributes & ) {}
|
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||||
|
|
||||||
identifier pk_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename PrimaryKeyType>
|
||||||
class primary_key_accessor {
|
class primary_key_accessor {
|
||||||
public:
|
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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ private:
|
||||||
generator_type generator_ = generator_type::Manual;
|
generator_type generator_ = generator_type::Manual;
|
||||||
};
|
};
|
||||||
|
|
||||||
const primary_key_attribute DefaultPkAttributes {};
|
const primary_key_attribute default_pk_attributes {};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //PRIMARY_KEY_ATTRIBUTE_HPP
|
#endif //PRIMARY_KEY_ATTRIBUTE_HPP
|
||||||
|
|
|
||||||
|
|
@ -6,39 +6,46 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
|
|
||||||
class uuid {
|
class uuid {
|
||||||
public:
|
public:
|
||||||
using uuid_array = std::array<uint32_t, 4>;
|
using uuid_array = std::array<uint32_t, 4>;
|
||||||
|
|
||||||
// Default constructor initializes to zero
|
// Default constructor initializes to zero
|
||||||
uuid() = default;
|
uuid() = default;
|
||||||
|
|
||||||
// Static UUID v4 generator
|
// Static UUID v4 generator
|
||||||
static uuid generate();
|
static uuid generate();
|
||||||
|
|
||||||
// Returns UUID as a string
|
// Returns UUID as a string
|
||||||
[[nodiscard]] std::string str() const;
|
[[nodiscard]] std::string str() const;
|
||||||
|
|
||||||
// Access to internal data
|
// Access to internal data
|
||||||
[[nodiscard]] const uuid_array &data() const;
|
[[nodiscard]] const uuid_array& data() const;
|
||||||
|
|
||||||
// Reset UUID to zero
|
// Reset UUID to zero
|
||||||
void clear() { _data.fill(0); }
|
void clear() { _data.fill(0); }
|
||||||
|
|
||||||
// Comparisons
|
// Comparisons
|
||||||
friend bool operator==(const uuid &lhs, const uuid &rhs);
|
friend bool operator==(const uuid& lhs, const uuid& rhs);
|
||||||
friend bool operator!=(const uuid &lhs, const uuid &rhs);
|
friend bool operator!=(const uuid& lhs, const uuid& rhs);
|
||||||
friend bool operator<(const uuid &lhs, const uuid &rhs);
|
friend bool operator<(const uuid& lhs, const uuid& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uuid_array _data{0, 0, 0, 0};
|
uuid_array _data{0, 0, 0, 0};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash specialization to allow use in unordered containers
|
// Hash specialization to allow use in unordered containers
|
||||||
template<>
|
template <>
|
||||||
struct std::hash<matador::utils::uuid> {
|
struct std::hash<matador::utils::uuid> {
|
||||||
std::size_t operator()(const matador::utils::uuid &u) const noexcept;
|
std::size_t operator()(const matador::utils::uuid& u) const noexcept {
|
||||||
|
std::size_t h = 0;
|
||||||
|
for (const uint32_t val : u.data()) {
|
||||||
|
h ^= std::hash<uint32_t>{}(val) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //MATADOR_UUID_HPP
|
#endif //MATADOR_UUID_HPP
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,12 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/object/collection_proxy.hpp
|
../../include/matador/object/collection_proxy.hpp
|
||||||
../../include/matador/object/collection_resolver.hpp
|
../../include/matador/object/collection_resolver.hpp
|
||||||
../../include/matador/object/collection_resolver_factory.hpp
|
../../include/matador/object/collection_resolver_factory.hpp
|
||||||
../../include/matador/object/collection_utils.hpp
|
|
||||||
../../include/matador/object/error_code.hpp
|
../../include/matador/object/error_code.hpp
|
||||||
../../include/matador/object/foreign_node_completer.hpp
|
../../include/matador/object/foreign_node_completer.hpp
|
||||||
../../include/matador/object/internal/observer_list_copy_creator.hpp
|
../../include/matador/object/internal/observer_list_copy_creator.hpp
|
||||||
../../include/matador/object/internal/observer_list_creator.hpp
|
../../include/matador/object/internal/observer_list_creator.hpp
|
||||||
../../include/matador/object/many_to_many_relation.hpp
|
../../include/matador/object/many_to_many_relation.hpp
|
||||||
../../include/matador/object/object.hpp
|
../../include/matador/object/object.hpp
|
||||||
../../include/matador/object/object_cache.hpp
|
|
||||||
../../include/matador/object/object_generator.hpp
|
../../include/matador/object/object_generator.hpp
|
||||||
../../include/matador/object/object_info.hpp
|
../../include/matador/object/object_info.hpp
|
||||||
../../include/matador/object/object_proxy.hpp
|
../../include/matador/object/object_proxy.hpp
|
||||||
|
|
@ -37,7 +35,6 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/object/object_resolver.hpp
|
../../include/matador/object/object_resolver.hpp
|
||||||
../../include/matador/object/object_resolver_factory.hpp
|
../../include/matador/object/object_resolver_factory.hpp
|
||||||
../../include/matador/object/observer.hpp
|
../../include/matador/object/observer.hpp
|
||||||
../../include/matador/object/pk_field_locator.hpp
|
|
||||||
../../include/matador/object/primary_key_resolver.hpp
|
../../include/matador/object/primary_key_resolver.hpp
|
||||||
../../include/matador/object/relation_completer.hpp
|
../../include/matador/object/relation_completer.hpp
|
||||||
../../include/matador/object/relation_endpoint.hpp
|
../../include/matador/object/relation_endpoint.hpp
|
||||||
|
|
@ -66,7 +63,6 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/utils/file.hpp
|
../../include/matador/utils/file.hpp
|
||||||
../../include/matador/utils/foreign_attributes.hpp
|
../../include/matador/utils/foreign_attributes.hpp
|
||||||
../../include/matador/utils/identifier.hpp
|
../../include/matador/utils/identifier.hpp
|
||||||
../../include/matador/utils/identifier_accessor.hpp
|
|
||||||
../../include/matador/utils/identifier_to_value_converter.hpp
|
../../include/matador/utils/identifier_to_value_converter.hpp
|
||||||
../../include/matador/utils/leader_follower_thread_pool.hpp
|
../../include/matador/utils/leader_follower_thread_pool.hpp
|
||||||
../../include/matador/utils/library.hpp
|
../../include/matador/utils/library.hpp
|
||||||
|
|
@ -74,7 +70,6 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/utils/message_bus.hpp
|
../../include/matador/utils/message_bus.hpp
|
||||||
../../include/matador/utils/os.hpp
|
../../include/matador/utils/os.hpp
|
||||||
../../include/matador/utils/placeholder.hpp
|
../../include/matador/utils/placeholder.hpp
|
||||||
../../include/matador/utils/primary_key_accessor.hpp
|
|
||||||
../../include/matador/utils/primary_key_attribute.hpp
|
../../include/matador/utils/primary_key_attribute.hpp
|
||||||
../../include/matador/utils/primary_key_generator_type.hpp
|
../../include/matador/utils/primary_key_generator_type.hpp
|
||||||
../../include/matador/utils/result.hpp
|
../../include/matador/utils/result.hpp
|
||||||
|
|
@ -96,7 +91,6 @@ add_library(matador-core STATIC
|
||||||
object/attribute.cpp
|
object/attribute.cpp
|
||||||
object/basic_object_info.cpp
|
object/basic_object_info.cpp
|
||||||
object/basic_repository.cpp
|
object/basic_repository.cpp
|
||||||
object/collection_utils.cpp
|
|
||||||
object/error_code.cpp
|
object/error_code.cpp
|
||||||
object/foreign_node_completer.cpp
|
object/foreign_node_completer.cpp
|
||||||
object/object.cpp
|
object/object.cpp
|
||||||
|
|
@ -114,7 +108,6 @@ add_library(matador-core STATIC
|
||||||
utils/file.cpp
|
utils/file.cpp
|
||||||
utils/foreign_attributes.cpp
|
utils/foreign_attributes.cpp
|
||||||
utils/identifier.cpp
|
utils/identifier.cpp
|
||||||
utils/identifier_accessor.cpp
|
|
||||||
utils/identifier_to_value_converter.cpp
|
utils/identifier_to_value_converter.cpp
|
||||||
utils/leader_follower_thread_pool.cpp
|
utils/leader_follower_thread_pool.cpp
|
||||||
utils/library.cpp
|
utils/library.cpp
|
||||||
|
|
@ -127,6 +120,11 @@ add_library(matador-core STATIC
|
||||||
utils/uuid.cpp
|
utils/uuid.cpp
|
||||||
utils/value.cpp
|
utils/value.cpp
|
||||||
utils/version.cpp
|
utils/version.cpp
|
||||||
|
../../include/matador/object/collection_utils.hpp
|
||||||
|
object/collection_utils.cpp
|
||||||
|
../../include/matador/object/pk_field_locator.hpp
|
||||||
|
../../include/matador/object/object_cache.hpp
|
||||||
|
../../include/matador/utils/primary_key_accessor.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ std::shared_ptr<object> object_generator::acquire_object(basic_repository &repo,
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_generator::on_revision(const char* id, uint64_t& rev) {
|
void object_generator::on_revision(const char* id, uint64_t& rev) {
|
||||||
access::attribute(*this, id, rev);
|
on_attribute(id, rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_generator::create_pk_constraint(const std::string& name) const {
|
void object_generator::create_pk_constraint(const std::string& name) const {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ std::string utils_category_impl::message(const int ev) const {
|
||||||
switch (static_cast<utils_error>(ev)) {
|
switch (static_cast<utils_error>(ev)) {
|
||||||
case (utils_error::InvalidVersionString):
|
case (utils_error::InvalidVersionString):
|
||||||
return "Invalid version string";
|
return "Invalid version string";
|
||||||
case utils_error::IdentifierTypeMismatch:
|
|
||||||
return "Identifier type mismatch";
|
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,234 +1,97 @@
|
||||||
#include "matador/utils/identifier.hpp"
|
#include "matador/utils/identifier.hpp"
|
||||||
|
|
||||||
#include "matador/utils/value.hpp"
|
#include <cstring>
|
||||||
#include "matador/utils/errors.hpp"
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
|
size_t detail::hash(const char *value) {
|
||||||
|
return std::hash<std::string_view>()(std::string_view(value, std::strlen(value)));
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
bool identifier_type_traits<const char *>::is_valid(const char *value) {
|
||||||
inline const std::type_index& null_type_index() {
|
return value != nullptr && strlen(value) > 0;
|
||||||
static const std::type_index value{typeid(null_type_t)};
|
}
|
||||||
|
|
||||||
|
std::string identifier_type_traits<const char *>::to_string(const char *value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& i8_type_index() {
|
identifier::base::base(const std::type_index &ti, const basic_type type)
|
||||||
static const std::type_index value{typeid(int8_t)};
|
: type_index_(ti)
|
||||||
return value;
|
, type_(type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& i16_type_index() {
|
identifier::null_pk::null_pk()
|
||||||
static const std::type_index value{typeid(int16_t)};
|
: base(std::type_index(typeid(null_type_t)), basic_type::Null) {
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& i32_type_index() {
|
identifier::base *identifier::null_pk::copy() const {
|
||||||
static const std::type_index value{typeid(int32_t)};
|
return new null_pk;
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& i64_type_index() {
|
bool identifier::null_pk::equal_to(const base &x) const {
|
||||||
static const std::type_index value{typeid(int64_t)};
|
return type_index_ == x.type_index_;
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& u8_type_index() {
|
bool identifier::null_pk::less(const base &x) const {
|
||||||
static const std::type_index value{typeid(uint8_t)};
|
return type_index_ == x.type_index_;
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& u16_type_index() {
|
bool identifier::null_pk::is_valid() const {
|
||||||
static const std::type_index value{typeid(uint16_t)};
|
return identifier_type_traits<null_type_t>::is_valid();
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& u32_type_index() {
|
std::string identifier::null_pk::str() const {
|
||||||
static const std::type_index value{typeid(uint32_t)};
|
return identifier_type_traits<null_type_t>::to_string();
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& u64_type_index() {
|
void identifier::null_pk::serialize(identifier_serializer &s) {
|
||||||
static const std::type_index value{typeid(uint64_t)};
|
s.serialize(null_, {});
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::type_index& string_type_index() {
|
size_t identifier::null_pk::hash() const {
|
||||||
static const std::type_index value{typeid(std::string)};
|
return std::hash<nullptr_t>()(nullptr);
|
||||||
return value;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
size_t detail::hash(const std::string &value) {
|
|
||||||
return std::hash<std::string_view>()(std::string_view(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier::identifier()
|
identifier::identifier()
|
||||||
: value_(std::monostate{}) {
|
: id_(std::make_shared<null_pk>()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t identifier::type_rank(const value_type &value) {
|
identifier::identifier(const identifier &x)
|
||||||
return value.index();
|
: id_(x.id_->copy()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::type_index identifier::type_index_from_value(const value_type &value) {
|
identifier &identifier::operator=(const identifier &x) {
|
||||||
return std::visit([](const auto &v) -> std::type_index {
|
if (this == &x) {
|
||||||
using T = std::decay_t<decltype(v)>;
|
return *this;
|
||||||
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());
|
||||||
|
|
||||||
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(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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
result<identifier, error> identifier::from_value(const value &val) {
|
identifier::identifier(identifier &&x) noexcept
|
||||||
identifier id;
|
: id_(std::move(x.id_)) {
|
||||||
if (const auto result = id.assign(val); result.is_error()) {
|
x.clear();
|
||||||
return failure(result.err());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
database_type identifier::to_database_type() const {
|
identifier &identifier::operator=(identifier &&x) noexcept {
|
||||||
return std::visit([](const auto &v) -> database_type {
|
id_ = std::move(x.id_);
|
||||||
using T = std::decay_t<decltype(v)>;
|
x.clear();
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
return *this;
|
||||||
return nullptr;
|
|
||||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
|
||||||
return v;
|
|
||||||
} else {
|
|
||||||
return static_cast<T>(v);
|
|
||||||
}
|
|
||||||
}, value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
result<void, error> identifier::assign(const value &val) {
|
|
||||||
switch (val.type()) {
|
|
||||||
case basic_type::Null:
|
|
||||||
value_ = std::monostate{};
|
|
||||||
return ok<void>{};
|
|
||||||
|
|
||||||
case basic_type::Int8:
|
|
||||||
if (auto v = val.as<int8_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
case basic_type::Int16:
|
|
||||||
if (auto v = val.as<int16_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
case basic_type::Int32:
|
|
||||||
if (auto v = val.as<int32_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
case basic_type::Int64:
|
|
||||||
if (auto v = val.as<int64_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
|
|
||||||
case basic_type::UInt8:
|
|
||||||
if (auto v = val.as<uint8_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
case basic_type::UInt16:
|
|
||||||
if (auto v = val.as<uint16_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
case basic_type::UInt32:
|
|
||||||
if (auto v = val.as<uint32_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
case basic_type::UInt64:
|
|
||||||
if (auto v = val.as<uint64_t>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
|
|
||||||
case basic_type::Text:
|
|
||||||
case basic_type::Varchar:
|
|
||||||
if (auto v = val.as<std::string>()) { value_ = *v; return ok<void>{}; }
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return failure(error{utils_error::IdentifierTypeMismatch});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::operator==(const identifier &x) const {
|
bool identifier::operator==(const identifier &x) const {
|
||||||
return value_ == x.value_;
|
return id_->equal_to(*x.id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::operator!=(const identifier &x) const {
|
bool identifier::operator!=(const identifier &x) const {
|
||||||
return !operator==(x);
|
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 {
|
bool identifier::operator<(const identifier &x) const {
|
||||||
if (value_.index() != x.value_.index()) {
|
return id_->less(*x.id_);
|
||||||
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 {
|
bool identifier::operator<=(const identifier &x) const {
|
||||||
|
|
@ -244,78 +107,79 @@ bool identifier::operator>=(const identifier &x) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string identifier::str() const {
|
std::string identifier::str() const {
|
||||||
return std::visit([](const auto &v) -> std::string {
|
return id_->str();
|
||||||
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();
|
const std::type_index &identifier::type_index() const {
|
||||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
return id_->type_index_;
|
||||||
return identifier_type_traits<std::string>::to_string(v);
|
|
||||||
} else {
|
|
||||||
return identifier_type_traits<T>::to_string(v);
|
|
||||||
}
|
|
||||||
}, value_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_type identifier::type() const {
|
basic_type identifier::type() const {
|
||||||
return type_from_value(value_);
|
return id_->type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
identifier identifier::share() const {
|
||||||
|
return identifier(id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t identifier::use_count() const {
|
||||||
|
return id_.use_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::is_integer() const {
|
bool identifier::is_integer() const {
|
||||||
return std::holds_alternative<int8_t>(value_)
|
return id_->type_ >= basic_type::Int8 && id_->type_ <= basic_type::UInt64;
|
||||||
|| std::holds_alternative<int16_t>(value_)
|
}
|
||||||
|| std::holds_alternative<int32_t>(value_)
|
|
||||||
|| std::holds_alternative<int64_t>(value_)
|
bool identifier::is_floating_point() const {
|
||||||
|| std::holds_alternative<uint8_t>(value_)
|
return id_->type_ == basic_type::Float || id_->type_ == basic_type::Double;
|
||||||
|| std::holds_alternative<uint16_t>(value_)
|
}
|
||||||
|| std::holds_alternative<uint32_t>(value_)
|
|
||||||
|| std::holds_alternative<uint64_t>(value_);
|
bool identifier::is_bool() const {
|
||||||
|
return id_->type_ == basic_type::Boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::is_varchar() const {
|
bool identifier::is_varchar() const {
|
||||||
return std::holds_alternative<std::string>(value_);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::is_null() const {
|
bool identifier::is_null() const {
|
||||||
return std::holds_alternative<std::monostate>(value_);
|
return type_index() == null_identifier.type_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::is_valid() const {
|
bool identifier::is_valid() const {
|
||||||
return std::visit([](const auto &v) -> bool {
|
return id_->is_valid();
|
||||||
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() {
|
void identifier::clear() {
|
||||||
value_ = std::monostate{};
|
id_ = std::make_unique<null_pk>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void identifier::serialize(identifier_serializer &s) const {
|
void identifier::serialize(identifier_serializer &s) const {
|
||||||
std::visit([&s](const auto &v) {
|
id_->serialize(s);
|
||||||
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 {
|
size_t identifier::hash() const {
|
||||||
return std::visit([](const auto &v) -> size_t {
|
return id_->hash();
|
||||||
using T = std::decay_t<decltype(v)>;
|
}
|
||||||
if constexpr (std::is_same_v<T, std::monostate>) {
|
|
||||||
return std::hash<int>{}(0);
|
identifier::identifier(const std::shared_ptr<base> &id)
|
||||||
} else {
|
: id_(id) {
|
||||||
return detail::hash(v);
|
|
||||||
}
|
|
||||||
}, value_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const identifier &id) {
|
std::ostream &operator<<(std::ostream &out, const identifier &id) {
|
||||||
|
|
@ -326,5 +190,4 @@ std::ostream &operator<<(std::ostream &out, const identifier &id) {
|
||||||
size_t id_pk_hash::operator()(const identifier &id) const {
|
size_t id_pk_hash::operator()(const identifier &id) const {
|
||||||
return id.hash();
|
return id.hash();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // namespace matador::utils
|
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
#include "matador/utils/identifier_accessor.hpp"
|
|
||||||
#include "matador/utils/default_type_traits.hpp"
|
|
||||||
|
|
||||||
namespace matador::utils {
|
|
||||||
identifier_setter::identifier_setter(identifier &id)
|
|
||||||
: id_(id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(int16_t &val, const field_attributes &) {
|
|
||||||
if (id_.type() == data_type_traits<int16_t>::type()) {
|
|
||||||
id_ = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(int32_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(int64_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(uint8_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(uint16_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(uint32_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(uint64_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(std::string &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_setter::serialize(null_type_t &, const field_attributes &) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,80 +3,73 @@
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
|
|
||||||
uuid uuid::generate() {
|
uuid uuid::generate() {
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937_64 gen(rd());
|
std::mt19937_64 gen(rd());
|
||||||
std::uniform_int_distribution<uint64_t> dist;
|
std::uniform_int_distribution<uint64_t> dist;
|
||||||
|
|
||||||
uint64_t high = dist(gen);
|
uint64_t high = dist(gen);
|
||||||
uint64_t low = dist(gen);
|
uint64_t low = dist(gen);
|
||||||
|
|
||||||
// Set version to 4 (UUID v4)
|
// Set version to 4 (UUID v4)
|
||||||
high &= 0xFFFFFFFFFFFF0FFFULL;
|
high &= 0xFFFFFFFFFFFF0FFFULL;
|
||||||
high |= 0x0000000000004000ULL;
|
high |= 0x0000000000004000ULL;
|
||||||
|
|
||||||
// Set variant to 10xx (RFC 4122)
|
// Set variant to 10xx (RFC 4122)
|
||||||
low &= 0x3FFFFFFFFFFFFFFFULL;
|
low &= 0x3FFFFFFFFFFFFFFFULL;
|
||||||
low |= 0x8000000000000000ULL;
|
low |= 0x8000000000000000ULL;
|
||||||
|
|
||||||
uuid result;
|
uuid result;
|
||||||
result._data[0] = static_cast<uint32_t>(high >> 32);
|
result._data[0] = static_cast<uint32_t>(high >> 32);
|
||||||
result._data[1] = static_cast<uint32_t>(high & 0xFFFFFFFF);
|
result._data[1] = static_cast<uint32_t>(high & 0xFFFFFFFF);
|
||||||
result._data[2] = static_cast<uint32_t>(low >> 32);
|
result._data[2] = static_cast<uint32_t>(low >> 32);
|
||||||
result._data[3] = static_cast<uint32_t>(low & 0xFFFFFFFF);
|
result._data[3] = static_cast<uint32_t>(low & 0xFFFFFFFF);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string uuid::str() const {
|
std::string uuid::str() const {
|
||||||
const char *hex = "0123456789abcdef";
|
const char* hex = "0123456789abcdef";
|
||||||
char out[36]; // UUID string format is 36 characters
|
char out[36]; // UUID string format is 36 characters
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
auto write_hex = [&](uint32_t value, int digits) {
|
auto write_hex = [&](uint32_t value, int digits) {
|
||||||
for (int i = digits - 1; i >= 0; --i) {
|
for (int i = digits - 1; i >= 0; --i) {
|
||||||
out[pos + i] = hex[value & 0xF];
|
out[pos + i] = hex[value & 0xF];
|
||||||
value >>= 4;
|
value >>= 4;
|
||||||
}
|
}
|
||||||
pos += digits;
|
pos += digits;
|
||||||
};
|
};
|
||||||
|
|
||||||
write_hex(_data[0] >> 16, 8);
|
write_hex(_data[0] >> 16, 8);
|
||||||
out[pos++] = '-';
|
out[pos++] = '-';
|
||||||
write_hex(_data[0] & 0xFFFF, 4);
|
write_hex(_data[0] & 0xFFFF, 4);
|
||||||
out[pos++] = '-';
|
out[pos++] = '-';
|
||||||
write_hex(_data[1] >> 16, 4);
|
write_hex(_data[1] >> 16, 4);
|
||||||
out[pos++] = '-';
|
out[pos++] = '-';
|
||||||
write_hex(_data[1] & 0xFFFF, 4);
|
write_hex(_data[1] & 0xFFFF, 4);
|
||||||
out[pos++] = '-';
|
out[pos++] = '-';
|
||||||
write_hex(_data[2] >> 16, 4);
|
write_hex(_data[2] >> 16, 4);
|
||||||
write_hex(_data[2] & 0xFFFF, 4);
|
write_hex(_data[2] & 0xFFFF, 4);
|
||||||
write_hex(_data[3], 4);
|
write_hex(_data[3], 4);
|
||||||
|
|
||||||
return {out, 36};
|
return {out, 36};
|
||||||
}
|
}
|
||||||
|
|
||||||
const uuid::uuid_array &uuid::data() const {
|
const uuid::uuid_array& uuid::data() const {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const uuid &lhs, const uuid &rhs) {
|
bool operator==( const uuid& lhs, const uuid& rhs ) {
|
||||||
return lhs._data == rhs._data;
|
return lhs._data == rhs._data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const uuid &lhs, const uuid &rhs) {
|
bool operator!=( const uuid& lhs, const uuid& rhs ) {
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const uuid &lhs, const uuid &rhs) {
|
bool operator<( const uuid& lhs, const uuid& rhs ) {
|
||||||
return lhs._data < rhs._data;
|
return lhs._data < rhs._data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t std::hash<matador::utils::uuid>::operator()(const matador::utils::uuid &u) const noexcept {
|
|
||||||
std::size_t h = 0;
|
|
||||||
for (const uint32_t val: u.data()) {
|
|
||||||
h ^= std::hash<uint32_t>{}(val) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,6 @@ int field::index() const {
|
||||||
return index_;
|
return index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::value field::value() const {
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const field &col) {
|
std::ostream &operator<<(std::ostream &out, const field &col) {
|
||||||
out << col.str();
|
out << col.str();
|
||||||
return out;
|
return out;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ using namespace matador::object;
|
||||||
using namespace matador::test;
|
using namespace matador::test;
|
||||||
|
|
||||||
TEST_CASE_METHOD(SessionFixture, "Test insert object with has many relation", "[session][insert][has_many]") {
|
TEST_CASE_METHOD(SessionFixture, "Test insert object with has many relation", "[session][insert][has_many]") {
|
||||||
const auto result = schema.attach<book>("books")
|
auto result = schema.attach<book>("books")
|
||||||
.and_then( [this] { return schema.attach<author>("authors"); } )
|
.and_then( [this] { return schema.attach<author>("authors"); } )
|
||||||
.and_then([this] { return schema.create(db); } );
|
.and_then([this] { return schema.create(db); } );
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
|
||||||
add_executable(CoreTests
|
add_executable(CoreTests
|
||||||
../backends/SchemaFixture.hpp
|
../backends/SchemaFixture.hpp
|
||||||
logger/LoggerTest.cpp
|
logger/LoggerTest.cpp
|
||||||
object/ObjectCacheTest.cpp
|
|
||||||
object/ObjectTest.cpp
|
object/ObjectTest.cpp
|
||||||
object/PrimaryKeyResolverTest.cpp
|
object/PrimaryKeyResolverTest.cpp
|
||||||
object/RepositoryTest.cpp
|
object/RepositoryTest.cpp
|
||||||
|
|
@ -15,13 +14,13 @@ add_executable(CoreTests
|
||||||
utils/DependencyInjectionTest.cpp
|
utils/DependencyInjectionTest.cpp
|
||||||
utils/FieldAttributeTest.cpp
|
utils/FieldAttributeTest.cpp
|
||||||
utils/IdentifierTest.cpp
|
utils/IdentifierTest.cpp
|
||||||
utils/IsDatabasePrimitiveTest.cpp
|
|
||||||
utils/MessageBusTest.cpp
|
utils/MessageBusTest.cpp
|
||||||
utils/PrimaryKeyAccessorTest.cpp
|
|
||||||
utils/ResultTest.cpp
|
utils/ResultTest.cpp
|
||||||
utils/StringTest.cpp
|
utils/StringTest.cpp
|
||||||
utils/ThreadPoolTest.cpp
|
utils/ThreadPoolTest.cpp
|
||||||
utils/VersionTest.cpp
|
utils/VersionTest.cpp
|
||||||
|
utils/IsDatabasePrimitiveTest.cpp
|
||||||
|
object/ObjectCacheTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(CoreTests matador-core Catch2::Catch2WithMain)
|
target_link_libraries(CoreTests matador-core Catch2::Catch2WithMain)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "matador/utils/identifier.hpp"
|
#include "matador/utils/identifier.hpp"
|
||||||
#include "matador/utils/default_type_traits.hpp"
|
#include "matador/utils/default_type_traits.hpp"
|
||||||
#include "matador/utils/value.hpp"
|
|
||||||
|
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
|
|
||||||
|
|
@ -11,7 +10,12 @@ TEST_CASE("Test create identifier", "[identifier][create]") {
|
||||||
|
|
||||||
REQUIRE(id.is_null());
|
REQUIRE(id.is_null());
|
||||||
REQUIRE(!id.is_integer());
|
REQUIRE(!id.is_integer());
|
||||||
|
REQUIRE(!id.is_floating_point());
|
||||||
|
REQUIRE(!id.is_bool());
|
||||||
REQUIRE(!id.is_varchar());
|
REQUIRE(!id.is_varchar());
|
||||||
|
REQUIRE(!id.is_date());
|
||||||
|
REQUIRE(!id.is_time());
|
||||||
|
REQUIRE(!id.is_blob());
|
||||||
REQUIRE(!id.is_valid());
|
REQUIRE(!id.is_valid());
|
||||||
REQUIRE(id.str() == "null");
|
REQUIRE(id.str() == "null");
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +88,7 @@ TEST_CASE("Test copy identifier" "[identifier][copy]") {
|
||||||
identifier id3 = id1;
|
identifier id3 = id1;
|
||||||
|
|
||||||
REQUIRE(id1 == id3);
|
REQUIRE(id1 == id3);
|
||||||
REQUIRE(!(id1 < id3));
|
REQUIRE(id1 < id3);
|
||||||
REQUIRE(id3.is_null());
|
REQUIRE(id3.is_null());
|
||||||
REQUIRE(id1.hash() == id3.hash());
|
REQUIRE(id1.hash() == id3.hash());
|
||||||
|
|
||||||
|
|
@ -99,268 +103,16 @@ TEST_CASE("Test move identifier", "[identifier][move]") {
|
||||||
REQUIRE(!id1.is_null());
|
REQUIRE(!id1.is_null());
|
||||||
|
|
||||||
const auto id2 = std::move(id1);
|
const auto id2 = std::move(id1);
|
||||||
REQUIRE(!id1.is_null());
|
REQUIRE(id1.is_null());
|
||||||
REQUIRE(id2.is_integer());
|
REQUIRE(id2.is_integer());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("identifier assignment from integer types", "[utils][identifier][assign]") {
|
TEST_CASE("Test share identifier", "[identifier][share]") {
|
||||||
identifier id;
|
const identifier id1{6};
|
||||||
|
|
||||||
id = int8_t{-5};
|
REQUIRE(id1.use_count() == 1);
|
||||||
REQUIRE(id.type() == basic_type::Int8);
|
|
||||||
REQUIRE(id.str() == "-5");
|
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
|
|
||||||
id = int16_t{42};
|
auto id2 = id1.share();
|
||||||
REQUIRE(id.type() == basic_type::Int16);
|
REQUIRE(id1 == id2);
|
||||||
REQUIRE(id.str() == "42");
|
REQUIRE(id1.use_count() == 2);
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
|
|
||||||
id = uint32_t{123456u};
|
|
||||||
REQUIRE(id.type() == basic_type::UInt32);
|
|
||||||
REQUIRE(id.str() == "123456");
|
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier assignment from string type", "[utils][identifier][assign]") {
|
|
||||||
identifier id;
|
|
||||||
|
|
||||||
id = std::string{"hello"};
|
|
||||||
REQUIRE(id.type() == basic_type::Varchar);
|
|
||||||
REQUIRE(id.str() == "hello");
|
|
||||||
REQUIRE(id.is_varchar());
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
|
|
||||||
id = std::string{};
|
|
||||||
REQUIRE(id.type() == basic_type::Varchar);
|
|
||||||
REQUIRE(id.str().empty());
|
|
||||||
REQUIRE_FALSE(id.is_valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier assignment from const char*", "[utils][identifier][assign]") {
|
|
||||||
identifier id;
|
|
||||||
|
|
||||||
id = "world";
|
|
||||||
REQUIRE(id.type() == basic_type::Varchar);
|
|
||||||
REQUIRE(id.str() == "world");
|
|
||||||
REQUIRE(id.is_varchar());
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
|
|
||||||
id = static_cast<const char*>(nullptr);
|
|
||||||
REQUIRE(id.type() == basic_type::Varchar);
|
|
||||||
REQUIRE(id.str().empty());
|
|
||||||
REQUIRE_FALSE(id.is_valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier assignment from nullptr", "[utils][identifier][assign]") {
|
|
||||||
identifier id{42};
|
|
||||||
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
REQUIRE_FALSE(id.is_null());
|
|
||||||
|
|
||||||
id = nullptr;
|
|
||||||
REQUIRE(id.is_null());
|
|
||||||
REQUIRE(id.type() == basic_type::Null);
|
|
||||||
REQUIRE(id.str() == "null");
|
|
||||||
REQUIRE_FALSE(id.is_valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier reassignment between types", "[utils][identifier][assign]") {
|
|
||||||
identifier id{uint64_t{7}};
|
|
||||||
|
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.str() == "7");
|
|
||||||
|
|
||||||
id = std::string{"abc"};
|
|
||||||
REQUIRE(id.is_varchar());
|
|
||||||
REQUIRE(id.str() == "abc");
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
|
|
||||||
id = int64_t{99};
|
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.str() == "99");
|
|
||||||
REQUIRE(id.is_valid());
|
|
||||||
|
|
||||||
id = nullptr;
|
|
||||||
REQUIRE(id.is_null());
|
|
||||||
REQUIRE(id.str() == "null");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier as() returns exact integer type", "[utils][identifier][as]") {
|
|
||||||
identifier id{int32_t{42}};
|
|
||||||
|
|
||||||
const auto as_i32 = id.as<int32_t>();
|
|
||||||
REQUIRE(as_i32.is_ok());
|
|
||||||
REQUIRE(*as_i32 == 42);
|
|
||||||
|
|
||||||
const auto as_i64 = id.as<int64_t>();
|
|
||||||
REQUIRE(as_i64.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier as() returns exact string type", "[utils][identifier][as]") {
|
|
||||||
identifier id{std::string{"hello"}};
|
|
||||||
|
|
||||||
const auto as_string = id.as<std::string>();
|
|
||||||
REQUIRE(as_string.is_ok());
|
|
||||||
REQUIRE(*as_string == "hello");
|
|
||||||
|
|
||||||
const auto as_i32 = id.as<int32_t>();
|
|
||||||
REQUIRE(as_i32.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier as() returns null type failure for null identifier", "[utils][identifier][as]") {
|
|
||||||
identifier id{nullptr};
|
|
||||||
|
|
||||||
const auto as_i32 = id.as<int32_t>();
|
|
||||||
REQUIRE(as_i32.is_error());
|
|
||||||
|
|
||||||
const auto as_string = id.as<std::string>();
|
|
||||||
REQUIRE(as_string.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier convert() converts between integer types", "[utils][identifier][convert]") {
|
|
||||||
identifier id{int32_t{123}};
|
|
||||||
|
|
||||||
const auto as_i64 = id.convert<int64_t>();
|
|
||||||
REQUIRE(as_i64.is_ok());
|
|
||||||
REQUIRE(*as_i64 == 123);
|
|
||||||
|
|
||||||
const auto as_u8 = id.convert<uint8_t>();
|
|
||||||
REQUIRE(as_u8.is_ok());
|
|
||||||
REQUIRE(*as_u8 == 123);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier convert() rejects out of range integer conversion", "[utils][identifier][convert]") {
|
|
||||||
identifier id{int32_t{300}};
|
|
||||||
|
|
||||||
const auto as_u8 = id.convert<uint8_t>();
|
|
||||||
REQUIRE(as_u8.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier convert() rejects negative to unsigned conversion", "[utils][identifier][convert]") {
|
|
||||||
identifier id{int32_t{-1}};
|
|
||||||
|
|
||||||
const auto as_u32 = id.convert<uint32_t>();
|
|
||||||
REQUIRE(as_u32.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier convert() rejects non-integer source types", "[utils][identifier][convert]") {
|
|
||||||
identifier id{std::string{"123"}};
|
|
||||||
|
|
||||||
const auto as_i32 = id.convert<int32_t>();
|
|
||||||
REQUIRE(as_i32.is_error());
|
|
||||||
|
|
||||||
identifier null_id{nullptr};
|
|
||||||
const auto null_to_i64 = null_id.convert<int64_t>();
|
|
||||||
REQUIRE(null_to_i64.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier convert() works with unsigned integer sources", "[utils][identifier][convert]") {
|
|
||||||
identifier id{uint16_t{500}};
|
|
||||||
|
|
||||||
const auto as_i32 = id.convert<int32_t>();
|
|
||||||
REQUIRE(as_i32.is_ok());
|
|
||||||
REQUIRE(*as_i32 == 500);
|
|
||||||
|
|
||||||
const auto as_u8 = id.convert<uint8_t>();
|
|
||||||
REQUIRE(as_u8.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier as() and convert() behave consistently for same integer type", "[utils][identifier][as][convert]") {
|
|
||||||
identifier id{uint64_t{77}};
|
|
||||||
|
|
||||||
const auto as_u64 = id.as<uint64_t>();
|
|
||||||
REQUIRE(as_u64.is_ok());
|
|
||||||
REQUIRE(*as_u64 == 77);
|
|
||||||
|
|
||||||
const auto conv_u64 = id.convert<uint64_t>();
|
|
||||||
REQUIRE(conv_u64.is_ok());
|
|
||||||
REQUIRE(*conv_u64 == 77);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier assign from value", "[utils][identifier][assign]") {
|
|
||||||
identifier id;
|
|
||||||
|
|
||||||
value v1{int32_t{17}};
|
|
||||||
const auto r1 = id.assign(v1);
|
|
||||||
REQUIRE(r1.is_ok());
|
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.str() == "17");
|
|
||||||
|
|
||||||
value v2{std::string{"abc"}};
|
|
||||||
const auto r2 = id.assign(v2);
|
|
||||||
REQUIRE(r2.is_ok());
|
|
||||||
REQUIRE(id.is_varchar());
|
|
||||||
REQUIRE(id.str() == "abc");
|
|
||||||
|
|
||||||
value v3{basic_type::Double, 0};
|
|
||||||
const auto r3 = id.assign(v3);
|
|
||||||
REQUIRE(r3.is_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier assign from value with exact type mapping", "[utils][identifier][assign]") {
|
|
||||||
identifier id;
|
|
||||||
|
|
||||||
SECTION("integer types") {
|
|
||||||
value v{int16_t{12}};
|
|
||||||
const auto r = id.assign(v);
|
|
||||||
REQUIRE(r.is_ok());
|
|
||||||
REQUIRE(id.is_integer());
|
|
||||||
REQUIRE(id.str() == "12");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("string types") {
|
|
||||||
value v{std::string{"abc"}};
|
|
||||||
const auto r = id.assign(v);
|
|
||||||
REQUIRE(r.is_ok());
|
|
||||||
REQUIRE(id.is_varchar());
|
|
||||||
REQUIRE(id.str() == "abc");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("null") {
|
|
||||||
value v{basic_type::Null, 0};
|
|
||||||
const auto r = id.assign(v);
|
|
||||||
REQUIRE(r.is_ok());
|
|
||||||
REQUIRE(id.is_null());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("identifier::to_database_type converts internal value to database_type", "[identifier]") {
|
|
||||||
SECTION("null identifier becomes nullptr") {
|
|
||||||
identifier id{nullptr};
|
|
||||||
|
|
||||||
const auto db_value = id.to_database_type();
|
|
||||||
|
|
||||||
REQUIRE(std::holds_alternative<std::nullptr_t>(db_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("signed integral identifier becomes same signed database type") {
|
|
||||||
identifier id{int32_t{42}};
|
|
||||||
|
|
||||||
const auto db_value = id.to_database_type();
|
|
||||||
|
|
||||||
REQUIRE(std::holds_alternative<int32_t>(db_value));
|
|
||||||
REQUIRE(std::get<int32_t>(db_value) == 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("unsigned integral identifier becomes same unsigned database type") {
|
|
||||||
identifier id{uint64_t{123456789ULL}};
|
|
||||||
|
|
||||||
const auto db_value = id.to_database_type();
|
|
||||||
|
|
||||||
REQUIRE(std::holds_alternative<uint64_t>(db_value));
|
|
||||||
REQUIRE(std::get<uint64_t>(db_value) == 123456789ULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("string identifier becomes std::string database type") {
|
|
||||||
identifier id{std::string{"customer_1"}};
|
|
||||||
|
|
||||||
const auto db_value = id.to_database_type();
|
|
||||||
|
|
||||||
REQUIRE(std::holds_alternative<std::string>(db_value));
|
|
||||||
REQUIRE(std::get<std::string>(db_value) == "customer_1");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
#include <catch2/catch_test_macros.hpp>
|
|
||||||
|
|
||||||
#include "matador/utils/identifier.hpp"
|
|
||||||
#include "matador/utils/primary_key_accessor.hpp"
|
|
||||||
|
|
||||||
#include "../test/models/person.hpp"
|
|
||||||
|
|
||||||
TEST_CASE("primary_key_accessor detects unset primary key", "[utils][primary_key_accessor]") {
|
|
||||||
using namespace matador;
|
|
||||||
|
|
||||||
utils::primary_key_accessor accessor;
|
|
||||||
test::person p{};
|
|
||||||
|
|
||||||
REQUIRE_FALSE(accessor.is_set(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("primary_key_accessor detects set primary key", "[utils][primary_key_accessor]") {
|
|
||||||
using namespace matador;
|
|
||||||
|
|
||||||
utils::primary_key_accessor accessor;
|
|
||||||
test::person p{};
|
|
||||||
p.id = 42;
|
|
||||||
|
|
||||||
REQUIRE(accessor.is_set(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("primary_key_accessor gets integer primary key", "[utils][primary_key_accessor]") {
|
|
||||||
using namespace matador;
|
|
||||||
|
|
||||||
utils::primary_key_accessor accessor;
|
|
||||||
test::person p{};
|
|
||||||
p.id = 17;
|
|
||||||
|
|
||||||
const auto pk = accessor.get(p);
|
|
||||||
|
|
||||||
REQUIRE(pk.is_integer());
|
|
||||||
REQUIRE(pk.is_valid());
|
|
||||||
REQUIRE(pk.as<unsigned int>().is_ok());
|
|
||||||
REQUIRE(*pk.as<unsigned int>() == 17u);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("primary_key_accessor sets integer primary key", "[utils][primary_key_accessor]") {
|
|
||||||
using namespace matador;
|
|
||||||
|
|
||||||
utils::primary_key_accessor accessor;
|
|
||||||
test::person p{};
|
|
||||||
|
|
||||||
accessor.set(p, utils::identifier{123u});
|
|
||||||
|
|
||||||
REQUIRE(p.id == 123u);
|
|
||||||
REQUIRE(accessor.is_set(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("primary_key_accessor can round-trip primary key value", "[utils][primary_key_accessor]") {
|
|
||||||
using namespace matador;
|
|
||||||
|
|
||||||
utils::primary_key_accessor accessor;
|
|
||||||
test::person original{};
|
|
||||||
original.id = 88u;
|
|
||||||
|
|
||||||
const auto pk = accessor.get(original);
|
|
||||||
|
|
||||||
test::person copy{};
|
|
||||||
accessor.set(copy, pk);
|
|
||||||
|
|
||||||
REQUIRE(copy.id == 88u);
|
|
||||||
REQUIRE(accessor.is_set(copy));
|
|
||||||
}
|
|
||||||
|
|
@ -14,7 +14,7 @@ struct coordinate {
|
||||||
|
|
||||||
namespace matador::access {
|
namespace matador::access {
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void attribute(Operator &op, const char *id, test::coordinate &value, const utils::field_attributes &attr = utils::NullAttributes) {
|
void attribute(Operator &op, const char *id, test::coordinate &value, const utils::field_attributes &attr = utils::null_attributes) {
|
||||||
attribute(op, (std::string(id) + "_x").c_str(), value.x, attr);
|
attribute(op, (std::string(id) + "_x").c_str(), value.x, attr);
|
||||||
attribute(op, (std::string(id) + "_y").c_str(), value.y, attr);
|
attribute(op, (std::string(id) + "_y").c_str(), value.y, attr);
|
||||||
attribute(op, (std::string(id) + "_z").c_str(), value.z, attr);
|
attribute(op, (std::string(id) + "_z").c_str(), value.z, attr);
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
#include "../backend/test_backend_service.hpp"
|
#include "../backend/test_backend_service.hpp"
|
||||||
|
|
||||||
#include "../../models/author.hpp"
|
|
||||||
#include "../../models/book.hpp"
|
|
||||||
#include "../../models/airplane.hpp"
|
#include "../../models/airplane.hpp"
|
||||||
#include "../../models/flight.hpp"
|
#include "../../models/flight.hpp"
|
||||||
|
|
||||||
|
|
@ -34,8 +32,8 @@ TEST_CASE("insert query builder test", "[query][insert_query_builder]") {
|
||||||
|
|
||||||
insert_query_builder iqb(scm);
|
insert_query_builder iqb(scm);
|
||||||
|
|
||||||
const auto a380 = make_object<airplane>(1, "Boeing", "A380" );
|
const auto a380 = object_ptr(std::make_shared<airplane>(1, "Boeing", "A380" ));
|
||||||
auto build_result = iqb.build(a380);
|
auto build_result = iqb.build<airplane>(a380);
|
||||||
REQUIRE(build_result.is_ok());
|
REQUIRE(build_result.is_ok());
|
||||||
|
|
||||||
const auto& stmts = *build_result;
|
const auto& stmts = *build_result;
|
||||||
|
|
@ -47,30 +45,3 @@ TEST_CASE("insert query builder test", "[query][insert_query_builder]") {
|
||||||
const auto sql = std::get<executable_query>(step.query).str(db);
|
const auto sql = std::get<executable_query>(step.query).str(db);
|
||||||
REQUIRE(sql == R"(INSERT INTO "airplanes" ("id", "brand", "model") VALUES (1, 'Boeing', 'A380'))");
|
REQUIRE(sql == R"(INSERT INTO "airplanes" ("id", "brand", "model") VALUES (1, 'Boeing', 'A380'))");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test insert builder has many", "[query][insert_query_builder][has_many]") {
|
|
||||||
using namespace matador::test;
|
|
||||||
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
|
|
||||||
connection db("noop://noop.db");
|
|
||||||
|
|
||||||
schema scm;
|
|
||||||
const auto result = scm.attach<book>("books")
|
|
||||||
.and_then( [&scm] { return scm.attach<author>("authors"); } );
|
|
||||||
REQUIRE(result.is_ok());
|
|
||||||
|
|
||||||
auto s_king = make_object<author>(1, "Steven", "King", "21.9.1947", 1956, false);
|
|
||||||
|
|
||||||
s_king->books.push_back(make_object<book>(2, "Carrie", object_ptr<author>{}, 1974));
|
|
||||||
s_king->books.push_back(make_object<book>(3, "The Shining", object_ptr<author>{}, 1977));
|
|
||||||
s_king->books.push_back(make_object<book>(4, "It", object_ptr<author>{}, 1986));
|
|
||||||
s_king->books.push_back(make_object<book>(5, "Misery", object_ptr<author>{}, 1987));
|
|
||||||
s_king->books.push_back(make_object<book>(6, "The Dark Tower: The Gunslinger", object_ptr<author>{}, 1982));
|
|
||||||
|
|
||||||
insert_query_builder iqb(scm);
|
|
||||||
|
|
||||||
auto build_result = iqb.build(s_king);
|
|
||||||
REQUIRE(build_result.is_ok());
|
|
||||||
|
|
||||||
const auto& stmts = *build_result;
|
|
||||||
REQUIRE(stmts.size() == 1);
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue