153 lines
6.2 KiB
C++
153 lines
6.2 KiB
C++
#ifndef QUERY_COLUMN_DEFINITION_GENERATOR_HPP
|
|
#define QUERY_COLUMN_DEFINITION_GENERATOR_HPP
|
|
|
|
#include "matador/object/attribute_definition.hpp"
|
|
|
|
#include "matador/utils/access.hpp"
|
|
#include "matador/utils/data_type_traits.hpp"
|
|
#include "matador/utils/error.hpp"
|
|
#include "matador/utils/field_attributes.hpp"
|
|
#include "matador/utils/primary_key_attribute.hpp"
|
|
#include "matador/utils/result.hpp"
|
|
|
|
#include <memory>
|
|
#include <typeindex>
|
|
#include <vector>
|
|
|
|
namespace matador::object {
|
|
|
|
class repository;
|
|
|
|
class fk_attribute_generator
|
|
{
|
|
public:
|
|
fk_attribute_generator() = default;
|
|
|
|
template<class Type>
|
|
attribute_definition generate(const char *id, Type &x, const std::shared_ptr<attribute_definition> &ref_column) {
|
|
access::process(*this, x);
|
|
return attribute_definition{id, type_, 0, ref_column, {utils::constraints::FOREIGN_KEY }, null_option_type::NOT_NULL};
|
|
}
|
|
|
|
template<typename ValueType>
|
|
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());
|
|
}
|
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
|
template < class Type >
|
|
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*/ = utils::null_attributes) {}
|
|
template<class Pointer>
|
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
|
template<class Pointer>
|
|
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
|
template<class ContainerType>
|
|
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
|
|
template<class ContainerType>
|
|
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
|
template<class ContainerType>
|
|
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {}
|
|
|
|
private:
|
|
utils::basic_type type_{};
|
|
};
|
|
|
|
class attribute_definition_generator final {
|
|
private:
|
|
attribute_definition_generator(std::vector<attribute_definition> &columns, const repository &repo);
|
|
|
|
public:
|
|
~attribute_definition_generator() = default;
|
|
|
|
template < class Type >
|
|
static std::vector<attribute_definition> generate(const repository &repo)
|
|
{
|
|
std::vector<attribute_definition> columns;
|
|
attribute_definition_generator gen(columns, repo);
|
|
Type obj;
|
|
access::process(gen, obj);
|
|
return columns;
|
|
}
|
|
|
|
template < class Type >
|
|
static std::vector<attribute_definition> generate(const Type& obj, const repository &repo) {
|
|
std::vector<attribute_definition> columns;
|
|
attribute_definition_generator gen(columns, repo);
|
|
access::process(gen, obj);
|
|
return columns;
|
|
}
|
|
|
|
template < class Type >
|
|
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);
|
|
|
|
template<typename Type>
|
|
void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::null_attributes);
|
|
|
|
template<typename Type>
|
|
void on_attribute(const char *id, std::optional<Type> &x, const utils::field_attributes &attr = utils::null_attributes);
|
|
|
|
template<class Pointer>
|
|
void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) {
|
|
on_foreign_key(id, x);
|
|
}
|
|
template<class Pointer>
|
|
void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {
|
|
// on_foreign_key(id, x);
|
|
}
|
|
|
|
template <class Pointer>
|
|
void on_foreign_key(const char *id, Pointer &x) {
|
|
std::shared_ptr<attribute_definition> ref_column;
|
|
std::type_index ti = typeid(typename Pointer::value_type);
|
|
if (const auto result = determine_foreign_ref(std::type_index(ti))) {
|
|
ref_column = *result;
|
|
} else {
|
|
ref_column = std::make_shared<attribute_definition>();
|
|
insert_missing_reference_column(ti, ref_column);
|
|
}
|
|
if (x.empty()) {
|
|
typename Pointer::value_type temp_val;
|
|
columns_.push_back(fk_column_generator_.generate(id, temp_val, ref_column));
|
|
} else {
|
|
columns_.push_back(fk_column_generator_.generate(id, *x, ref_column));
|
|
}
|
|
}
|
|
template<class ContainerType>
|
|
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
|
|
template<class ContainerType>
|
|
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
|
template<class ContainerType>
|
|
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {}
|
|
|
|
private:
|
|
[[nodiscard]] utils::result<std::shared_ptr<attribute_definition>, utils::error> determine_foreign_ref(const std::type_index &ti) const;
|
|
void insert_missing_reference_column(const std::type_index &ti, const std::shared_ptr<attribute_definition>& ref_column) const;
|
|
|
|
private:
|
|
size_t index_ = 0;
|
|
std::vector<attribute_definition> &columns_;
|
|
const repository &repo_;
|
|
|
|
fk_attribute_generator fk_column_generator_;
|
|
};
|
|
|
|
template<typename ValueType>
|
|
void attribute_definition_generator::on_primary_key(const char *id, ValueType &x, const utils::primary_key_attribute& attr) {
|
|
on_attribute(id, x, { attr.size(), utils::constraints::PRIMARY_KEY });
|
|
}
|
|
|
|
template<typename Type>
|
|
void attribute_definition_generator::on_attribute(const char *id, Type &x, const utils::field_attributes &attr) {
|
|
columns_.emplace_back(id, utils::data_type_traits<Type>::type(attr.size()), attr, null_option_type::NOT_NULL);
|
|
}
|
|
|
|
template<typename Type>
|
|
void attribute_definition_generator::on_attribute(const char *id, std::optional<Type> & /*x*/, const utils::field_attributes &attr)
|
|
{
|
|
columns_.emplace_back(id, utils::data_type_traits<Type>::type(attr.size()), attr, null_option_type::NULLABLE);
|
|
}
|
|
|
|
}
|
|
#endif //QUERY_COLUMN_DEFINITION_GENERATOR_HPP
|