diff --git a/include/matador/object/attribute.hpp b/include/matador/object/attribute.hpp index 08d08d0..25b7b3b 100644 --- a/include/matador/object/attribute.hpp +++ b/include/matador/object/attribute.hpp @@ -15,7 +15,6 @@ enum class null_option_type : uint8_t { }; class object; -class attribute_generator; class attribute { public: @@ -65,7 +64,6 @@ public: private: friend class object; - friend class attribute_generator; friend class object_generator; std::string name_; diff --git a/include/matador/object/attribute_generator.hpp b/include/matador/object/attribute_generator.hpp deleted file mode 100644 index 18fbb18..0000000 --- a/include/matador/object/attribute_generator.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef QUERY_COLUMN_DEFINITION_GENERATOR_HPP -#define QUERY_COLUMN_DEFINITION_GENERATOR_HPP - -#include "matador/object/attribute.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/identifier.hpp" -#include "matador/utils/primary_key_attribute.hpp" -#include "matador/utils/result.hpp" - -#include -#include -#include - -namespace matador::object { - -class repository; - -class fk_attribute_generator -{ -public: - fk_attribute_generator() = default; - - template - attribute generate(const char *id, Type &x) { - access::process(*this, x); - return attribute{id, type_, {utils::constraints::ForeignKey }, null_option_type::NotNull}; - } - - template - void on_primary_key(const char *, ValueType &/*pk*/, const utils::primary_key_attribute& attr = utils::default_pk_attributes) { - type_ = utils::data_type_traits::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 - static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} - template - static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} - template - static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} - template - 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 - static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} - -private: - utils::basic_type type_{}; -}; - -class attribute_generator final { -private: - attribute_generator(std::vector &columns, const repository &repo, const std::shared_ptr& obj); - -public: - ~attribute_generator() = default; - - template < class Type > - static std::vector generate(const repository &repo, const std::shared_ptr &obj) { - Type t; - return generate(t, repo, obj); - } - - template < class Type > - static std::vector generate(const Type& t, const repository &repo, const std::shared_ptr &obj) { - std::vector columns; - attribute_generator gen(columns, repo, obj); - access::process(gen, t); - 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 - 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*/) { - on_foreign_key(id, x); - } - template - static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} - - template - void on_foreign_key(const char *id, Pointer &x) { - attribute* ref_column; - std::type_index ti = typeid(typename Pointer::value_type); - if (auto result = determine_foreign_ref(std::type_index(ti))) { - ref_column = *result; - } else { - ref_column = nullptr; - 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)); - } else { - columns_.push_back(fk_column_generator_.generate(id, *x)); - } - } - template - static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} - template - 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 - static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} - -private: - [[nodiscard]] utils::result determine_foreign_ref(const std::type_index &ti) const; - void insert_missing_reference_column(const std::type_index &ti, attribute* ref_column) const; - - template - attribute &emplace_attribute(const char *id, const utils::field_attributes& attr, null_option_type null_option) { - auto &ref = columns_.emplace_back(id, utils::data_type_traits::type(attr.size()), attr, null_option); - ref.owner_ = obj_; - return ref; - } - - void prepare_primary_key(attribute &ref, utils::identifier &&pk) const; - -private: - size_t index_ = 0; - std::vector &columns_; - const repository &repo_; - const std::shared_ptr obj_; - - fk_attribute_generator fk_column_generator_; -}; - -template -void attribute_generator::on_primary_key(const char *id, ValueType &x, const utils::primary_key_attribute& attr) { - auto &ref = emplace_attribute(id, { attr.size(), utils::constraints::PrimaryKey }, null_option_type::NotNull); - prepare_primary_key(ref, utils::identifier(x)); -} - -template -void attribute_generator::on_attribute(const char *id, Type &/*x*/, const utils::field_attributes &attr) { - std::ignore = emplace_attribute(id, attr, null_option_type::NotNull); -} - -template -void attribute_generator::on_attribute(const char *id, std::optional & /*x*/, const utils::field_attributes &attr) { - std::ignore = emplace_attribute(id, attr, null_option_type::Nullable); -} - -} -#endif //QUERY_COLUMN_DEFINITION_GENERATOR_HPP diff --git a/include/matador/object/constraints_generator.hpp b/include/matador/object/constraints_generator.hpp deleted file mode 100644 index c914dc8..0000000 --- a/include/matador/object/constraints_generator.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef MATADOR_CONSTRAINTS_GENERATOR_HPP -#define MATADOR_CONSTRAINTS_GENERATOR_HPP - -#include "matador/object/restriction.hpp" - -#include "matador/utils/access.hpp" -#include "matador/utils/field_attributes.hpp" -#include "matador/utils/primary_key_attribute.hpp" - -#include -#include - -namespace matador::object { -class object; -class basic_object_info; -class repository; - -class constraints_generator final { -private: - constraints_generator(std::list &constraints, const repository &repo, const std::shared_ptr &obj); - -public: - constraints_generator() = delete; - - template < typename Type > - static std::list generate(const repository &repo, const std::shared_ptr &obj) { - Type t; - return generate(t, repo, obj); - } - - template < typename Type > - static std::list generate(const Type& t, const repository &repo, const std::shared_ptr &obj) { - std::list constraints; - constraints_generator gen(constraints, repo, obj); - access::process(gen, t); - return constraints; - } - - template < class Type > - void on_primary_key(const char *id, Type &/*x*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) { - create_pk_constraint(id); - } - static 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) { - if (utils::is_constraint_set(attr.options() ,utils::constraints::Unique)) { - create_unique_constraint(id); - } - } - - template - void on_belongs_to(const char *id, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) { - create_fk_constraint( typeid(typename Pointer::value_type), id); - } - template - static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} - template - static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} - template - 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 - static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} - -private: - void create_pk_constraint(const std::string& name) const; - void create_fk_constraint(const std::type_index& ti, const std::string& name) const; - void create_unique_constraint(const std::string& name) const; - - [[nodiscard]] std::list::iterator find_attribute_by_name(const std::string &name) const; - -private: - std::list &constraints_; - const repository &repo_; - std::shared_ptr obj_; -}; -} - -#endif //MATADOR_CONSTRAINTS_GENERATOR_HPP \ No newline at end of file diff --git a/include/matador/object/object.hpp b/include/matador/object/object.hpp index 6d9918d..4dff4f9 100644 --- a/include/matador/object/object.hpp +++ b/include/matador/object/object.hpp @@ -38,7 +38,6 @@ public: friend std::ostream& operator<<(std::ostream& os, const object& obj); private: - friend class constraints_generator; friend class attribute_generator; friend class object_generator; @@ -46,7 +45,7 @@ private: attribute* pk_attribute_{nullptr}; utils::identifier pk_identifier_; std::list attributes_; - std::list constraints_; + std::list constraints_; }; } #endif //MATADOR_OBJECT_HPP \ No newline at end of file diff --git a/include/matador/object/repository.hpp b/include/matador/object/repository.hpp index 11b4eb6..3236f45 100644 --- a/include/matador/object/repository.hpp +++ b/include/matador/object/repository.hpp @@ -189,7 +189,6 @@ private: private: friend class internal::shadow_repository; friend class repository_node; - friend class attribute_generator; template < typename NodeType > friend class foreign_node_completer; friend class object_generator; diff --git a/include/matador/object/repository_node.hpp b/include/matador/object/repository_node.hpp index 0638642..a2ecb3a 100644 --- a/include/matador/object/repository_node.hpp +++ b/include/matador/object/repository_node.hpp @@ -1,10 +1,12 @@ #ifndef SCHEMA_NODE_HPP #define SCHEMA_NODE_HPP -#include "matador/object/attribute_generator.hpp" #include "matador/object/object_generator.hpp" #include "matador/object/object_info.hpp" +#include "matador/utils/error.hpp" +#include "matador/utils/result.hpp" + #include namespace matador::object { diff --git a/include/matador/object/restriction.hpp b/include/matador/object/restriction.hpp index e95be7a..c8b0586 100644 --- a/include/matador/object/restriction.hpp +++ b/include/matador/object/restriction.hpp @@ -32,11 +32,10 @@ public: friend std::ostream& operator<<(std::ostream& os, const restriction& c); - std::string prefix() const; + std::string type_string() const; private: friend class constraint_builder; - friend class constraints_generator; friend class object_generator; friend class object; diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index dbf433c..386f137 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -14,9 +14,7 @@ add_library(matador-core STATIC ../../include/matador/net/select_fd_sets.hpp ../../include/matador/net/socket_interrupter.hpp ../../include/matador/object/attribute.hpp - ../../include/matador/object/attribute_generator.hpp ../../include/matador/object/basic_object_info.hpp - ../../include/matador/object/constraints_generator.hpp ../../include/matador/object/error_code.hpp ../../include/matador/object/foreign_node_completer.hpp ../../include/matador/object/internal/shadow_repository.hpp @@ -79,9 +77,7 @@ add_library(matador-core STATIC logger/logger.cpp logger/rotating_file_sink.cpp object/attribute.cpp - object/attribute_generator.cpp object/basic_object_info.cpp - object/constraints_generator.cpp object/error_code.cpp object/foreign_node_completer.cpp object/internal/shadow_repository.cpp diff --git a/source/core/object/attribute_generator.cpp b/source/core/object/attribute_generator.cpp deleted file mode 100644 index 1c0715e..0000000 --- a/source/core/object/attribute_generator.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "matador/object/attribute_generator.hpp" -#include "matador/object/repository.hpp" -#include "matador/object/object.hpp" - -namespace matador::object { - -attribute_generator::attribute_generator(std::vector &columns, const repository &repo, const std::shared_ptr &obj) -: columns_(columns) -, repo_(repo) -, obj_(obj) -{} - -void attribute_generator::on_revision(const char *id, uint64_t &rev) { - on_attribute(id, rev); -} - -utils::result attribute_generator::determine_foreign_ref(const std::type_index &ti) const { - return repo_.primary_key_attribute(ti); -} - -void attribute_generator::insert_missing_reference_column(const std::type_index& ti, attribute* ref_column) const { - const_cast(repo_).missing_references_.insert({ti, ref_column}); -} - -void attribute_generator::prepare_primary_key(attribute& ref, utils::identifier &&pk) const { - obj_->pk_attribute_ = &ref; - obj_->pk_identifier_ = std::move(pk); -} -} \ No newline at end of file diff --git a/source/core/object/constraints_generator.cpp b/source/core/object/constraints_generator.cpp deleted file mode 100644 index caf948c..0000000 --- a/source/core/object/constraints_generator.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "matador/object/constraints_generator.hpp" -#include "matador/object/object.hpp" -#include "matador/object/repository.hpp" - -#include - -namespace matador::object { -constraints_generator::constraints_generator(std::list &constraints, const repository& repo, const std::shared_ptr &obj) -: constraints_(constraints) -, repo_(repo) -, obj_(obj) {} - -void constraints_generator::create_pk_constraint(const std::string& name) const { - restriction pk_constraint("PK_" + obj_->name()); - pk_constraint.options_ |= utils::constraints::PrimaryKey; - if (const auto pk_attr = find_attribute_by_name(name); pk_attr != std::end(obj_->attributes_)) { - pk_constraint.attr_ = &*pk_attr; - } - pk_constraint.owner_ = obj_; - constraints_.emplace_back(std::move(pk_constraint)); -} - -void constraints_generator::create_fk_constraint(const std::type_index& ti, const std::string& name) const { - const auto result = repo_.basic_info(ti); - if (!result) { - return; - } - restriction pk_constraint("FK_" + obj_->name() + "_" + name); - pk_constraint.options_ |= utils::constraints::ForeignKey; - if (const auto pk_attr = find_attribute_by_name(name); pk_attr != std::end(obj_->attributes_)) { - pk_constraint.attr_ = &*pk_attr; - } - pk_constraint.owner_ = obj_; - constraints_.emplace_back(std::move(pk_constraint)); -} - -void constraints_generator::create_unique_constraint(const std::string& name) const { - class restriction pk_constraint("UK_" + obj_->name() + "_" + name); - pk_constraint.options_ |= utils::constraints::Unique; - if (const auto pk_attr = find_attribute_by_name(name); pk_attr != std::end(obj_->attributes_)) { - pk_constraint.attr_ = &*pk_attr; - } - pk_constraint.owner_ = obj_; -} - -std::list::iterator constraints_generator::find_attribute_by_name(const std::string& name) const { - return std::find_if(std::begin(obj_->attributes_), std::end(obj_->attributes_), [&name](const attribute& elem) { - return elem.name() == name; - }); -} -} \ No newline at end of file diff --git a/source/core/object/object_generator.cpp b/source/core/object/object_generator.cpp index b2666d3..655e892 100644 --- a/source/core/object/object_generator.cpp +++ b/source/core/object/object_generator.cpp @@ -66,7 +66,7 @@ void object_generator::prepare_primary_key(attribute& ref, utils::identifier &&p object_->pk_identifier_ = std::move(pk); } -std::shared_ptr object_generator::fk_object(const std::type_index& ti) const { +std::shared_ptr object_generator::fk_object(const std::type_index& ti) const { const auto result = repo_.basic_info(ti); if (result) { return result->get().object(); diff --git a/source/core/object/restriction.cpp b/source/core/object/restriction.cpp index 47cad89..d1d40be 100644 --- a/source/core/object/restriction.cpp +++ b/source/core/object/restriction.cpp @@ -8,7 +8,7 @@ restriction::restriction(std::string name) : name_(std::move(name)) {} std::string restriction::name() const { - return prefix() + name_; + return type_string() + name_; } const class attribute* restriction::attribute() const { @@ -55,21 +55,21 @@ const std::string& restriction::ref_column_name() const { } std::ostream & operator<<(std::ostream &os, const class restriction &c) { - os << "constraint " << c.name() << " for column " << c.column_name(); + os << "constraint " << c.type_string() << " for column " << c.column_name(); return os; } -std::string restriction::prefix() const { +std::string restriction::type_string() const { if (utils::is_constraint_set(options_, utils::constraints::PrimaryKey)) { - return "PK_"; + return "PrimaryKey"; } if (utils::is_constraint_set(options_, utils::constraints::ForeignKey)) { - return "FK_"; + return "ForeignKey"; } if (utils::is_constraint_set(options_, utils::constraints::Unique)) { - return "UK_"; + return "Unique"; } - return ""; + return "Unknown"; } // constraint_builder & constraint_builder::constraint(std::string name) { diff --git a/test/core/CMakeLists.txt b/test/core/CMakeLists.txt index 6052fcb..ac5d94d 100644 --- a/test/core/CMakeLists.txt +++ b/test/core/CMakeLists.txt @@ -5,7 +5,6 @@ list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) add_executable(CoreTests ../backends/SchemaFixture.hpp logger/LoggerTest.cpp - object/AttributeGeneratorTest.cpp object/ObjectTest.cpp object/PrimaryKeyResolverTest.cpp object/SchemaTest.cpp diff --git a/test/core/object/AttributeGeneratorTest.cpp b/test/core/object/AttributeGeneratorTest.cpp deleted file mode 100644 index dbb34b9..0000000 --- a/test/core/object/AttributeGeneratorTest.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include - -#include "matador/object/attribute_generator.hpp" -#include "matador/object/object.hpp" -#include "matador/object/repository.hpp" - -#include "../test/models/product.hpp" -#include "../test/models/optional.hpp" - -using namespace matador::object; -using namespace matador::utils; - -TEST_CASE("Generate column definitions from object", "[column][definition][generator]") { - repository repo("main"); - - auto result = repo.attach("products") - .and_then([&repo] { return repo.attach("supplier"); }) - .and_then([&repo] { return repo.attach("categories"); }); - REQUIRE(result); - - auto obj = std::make_shared("products"); - auto columns = attribute_generator::generate(repo, obj); - - const std::vector expected_columns = { - attribute{"product_name", basic_type::Varchar, constraints::PrimaryKey, null_option_type::NotNull }, - attribute{"supplier_id", basic_type::UInt32, constraints::ForeignKey, null_option_type::NotNull }, - attribute{"category_id", basic_type::UInt32, constraints::ForeignKey, null_option_type::NotNull }, - attribute{"quantity_per_unit", basic_type::Varchar, null_attributes, null_option_type::NotNull }, - attribute{"unit_price", basic_type::UInt32, null_attributes, null_option_type::NotNull }, - attribute{"units_in_stock", basic_type::UInt32, null_attributes, null_option_type::NotNull }, - attribute{"units_in_order", basic_type::UInt32, null_attributes, null_option_type::NotNull }, - attribute{"reorder_level", basic_type::UInt32, null_attributes, null_option_type::NotNull }, - attribute{"discontinued", basic_type::Boolean, null_attributes, null_option_type::NotNull } - }; - REQUIRE(!columns.empty()); - REQUIRE(columns.size() == expected_columns.size()); - - for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i].name() == columns[i].name()); - REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); - REQUIRE(expected_columns[i].type() == columns[i].type() ); - } -} - -TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { - repository repo("main"); - - auto obj = std::make_shared("optionals"); - auto columns = attribute_generator::generate(repo, obj); - - const std::vector expected_columns = { - attribute{"id", basic_type::UInt32, constraints::PrimaryKey, null_option_type::NotNull }, - attribute{"name", basic_type::Varchar, null_attributes, null_option_type::NotNull }, - attribute{"age", basic_type::UInt32, null_attributes, null_option_type::NotNull } - }; - REQUIRE(!columns.empty()); - REQUIRE(columns.size() == expected_columns.size()); - - for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i].name() == columns[i].name()); - REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); - REQUIRE(expected_columns[i].type() == columns[i].type() ); - } -} \ No newline at end of file