#ifndef QUERY_COLUMN_DEFINITION_GENERATOR_HPP #define QUERY_COLUMN_DEFINITION_GENERATOR_HPP #include "attribute_definition.hpp" #include "matador/utils/access.hpp" #include "matador/utils/data_type_traits.hpp" #include "matador/utils/field_attributes.hpp" #include "matador/utils/foreign_attributes.hpp" #include #include namespace matador::object { class schema; class fk_attribute_generator { public: fk_attribute_generator() = default; template attribute_definition generate(const char *id, Type &x, const std::string &ref_table, const std::string &ref_column) { access::process(*this, x); return attribute_definition{id, type_, 0, ref_table, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; } template void on_primary_key(const char *, ValueType &/*pk*/, std::enable_if_t && !std::is_same_v>* = nullptr) { type_ = utils::data_type_traits::type(0); } void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t size); void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {} template < class Type > void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} template void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} template void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} template void on_has_many(ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} template void on_has_many_to_many(const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {} template void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} private: utils::basic_type type_{}; }; class attribute_definition_generator final { private: attribute_definition_generator(std::vector &columns, const schema &repo); public: ~attribute_definition_generator() = default; template < class Type > static std::vector generate(const schema &repo) { std::vector columns; attribute_definition_generator gen(columns, repo); Type obj; access::process(gen, obj); return std::move(columns); } template < class V > void on_primary_key(const char *, V &x, std::enable_if_t && !std::is_same_v>* = nullptr); void on_primary_key(const char *id, std::string &pk, size_t size); void on_revision(const char *id, uint64_t &rev); template void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::null_attributes); template void on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr = utils::null_attributes); template void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); } template void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); } template void on_has_many(ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} template void on_has_many_to_many(const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {} template void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} private: std::pair determine_foreign_ref(const std::type_index &ti); private: size_t index_ = 0; std::vector &columns_; const schema &repo_; fk_attribute_generator fk_column_generator_; }; template void attribute_definition_generator::on_primary_key(const char *id, V &x, std::enable_if_t && !std::is_same_v>*) { on_attribute(id, x, { utils::constraints::PRIMARY_KEY }); } template void attribute_definition_generator::on_attribute(const char *id, Type &x, const utils::field_attributes &attr) { columns_.emplace_back(id, x, attr, null_option::NOT_NULL); } template void attribute_definition_generator::on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr) { columns_.emplace_back(id, utils::data_type_traits::type(attr.size()), attr, null_option::NULLABLE); } } #endif //QUERY_COLUMN_DEFINITION_GENERATOR_HPP