From e3e0eb932ce9c5668cb74069d8c4c003e7ef50b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Mon, 10 Feb 2025 16:04:49 +0100 Subject: [PATCH] schema node analyze progress --- .../matador/object/attribute_definition.hpp | 40 ++++++++-- .../object/attribute_definition_generator.hpp | 10 +-- include/matador/object/basic_object_info.hpp | 5 +- include/matador/object/object_info.hpp | 8 +- include/matador/object/schema.hpp | 7 +- source/core/object/attribute_definition.cpp | 74 +++++++++++++++---- source/core/object/basic_object_info.cpp | 14 ++-- source/core/object/object_definition.cpp | 9 +-- source/core/object/schema.cpp | 2 +- source/core/object/schema_node.cpp | 3 +- source/orm/query/query_compiler.cpp | 10 +-- test/orm/sql/ColumnTest.cpp | 20 ++--- 12 files changed, 137 insertions(+), 65 deletions(-) diff --git a/include/matador/object/attribute_definition.hpp b/include/matador/object/attribute_definition.hpp index d19747a..3ee8b86 100644 --- a/include/matador/object/attribute_definition.hpp +++ b/include/matador/object/attribute_definition.hpp @@ -3,7 +3,6 @@ #include -#include "matador/utils/basic_type_converter.hpp" #include "matador/utils/basic_types.hpp" #include "matador/utils/default_type_traits.hpp" #include "matador/utils/field_attributes.hpp" @@ -27,6 +26,13 @@ public: attribute_definition(attribute_definition&&) noexcept = default; attribute_definition& operator=(attribute_definition&&) noexcept = default; + template + explicit attribute_definition(std::string name, std::string table_name, const utils::field_attributes& attr) + : attribute_definition(std::move(name), std::move(table_name), utils::data_type_traits::type(attr.size()), attr) + {} + + attribute_definition(std::string name, std::string table_name, utils::basic_type type, const utils::field_attributes& attr); + template explicit attribute_definition(std::string name, const utils::field_attributes& attr) : attribute_definition(std::move(name), utils::data_type_traits::type(attr.size()), attr) @@ -43,6 +49,7 @@ public: {} attribute_definition(std::string name, utils::basic_type type, const utils::field_attributes&, null_option null_opt, size_t index = 0); + attribute_definition(std::string name, std::string table_name, utils::basic_type type, const utils::field_attributes&, null_option null_opt, size_t index = 0); template attribute_definition(std::string name, const std::shared_ptr &ref_column, const utils::field_attributes& attr, null_option null_opt) @@ -126,8 +133,6 @@ private: null_option null_option_{null_option::NOT_NULL}; utils::value value_; std::shared_ptr reference_column_; - // std::string ref_table_; - // std::string ref_column_; }; /** @@ -158,8 +163,7 @@ template <> attribute_definition make_pk_column(const std::string &name, size_t size); template < typename Type > -attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) -{ +attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) { return {name, utils::data_type_traits::type(size), ref_column, { size, utils::constraints::FOREIGN_KEY }}; } @@ -170,7 +174,31 @@ template < typename Type > } template <> -attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column); +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column); + +template < typename Type > +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) { + return { + name, utils::data_type_traits::type(size), 0, + std::make_shared(ref_column_name, ref_table_name, utils::data_type_traits::type(size), utils::constraints::FOREIGN_KEY), + { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL + }; +} + +template < typename Type > +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, const std::string &ref_table_name, const std::string &ref_column_name) { + return { + name, utils::data_type_traits::type(0), 0, + std::make_shared(ref_column_name, ref_table_name, utils::data_type_traits::type(0), utils::constraints::FOREIGN_KEY), + { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL + }; +} + +template <> +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, const std::string &ref_table_name, const std::string &ref_column_name); + +template <> +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name); } diff --git a/include/matador/object/attribute_definition_generator.hpp b/include/matador/object/attribute_definition_generator.hpp index 6865b9b..215c0de 100644 --- a/include/matador/object/attribute_definition_generator.hpp +++ b/include/matador/object/attribute_definition_generator.hpp @@ -21,10 +21,10 @@ public: fk_attribute_generator() = default; template - attribute_definition generate(const char *id, Type &x, const std::string &ref_table, const std::string &ref_column) + attribute_definition generate(const char *id, Type &x, const std::shared_ptr &ref_column) { access::process(*this, x); - return attribute_definition{id, type_, 0, ref_table, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; + return attribute_definition{id, type_, 0, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; } template @@ -84,13 +84,13 @@ public: void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { const auto 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)); + columns_.push_back(fk_column_generator_.generate(id, *x, 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)); + const auto ref_column = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); + columns_.push_back(fk_column_generator_.generate(id, *x, ref_column)); } template void on_has_many(const char *id, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} diff --git a/include/matador/object/basic_object_info.hpp b/include/matador/object/basic_object_info.hpp index 5d1178c..8e2dd7d 100644 --- a/include/matador/object/basic_object_info.hpp +++ b/include/matador/object/basic_object_info.hpp @@ -20,10 +20,11 @@ public: [[nodiscard]] std::shared_ptr reference_column() const; protected: - basic_object_info(schema_node &node, std::type_index type_index, object_definition &&definition, std::shared_ptr &&reference_column); + basic_object_info(std::type_index type_index, object_definition &&definition, std::shared_ptr &&reference_column); + basic_object_info(std::type_index type_index, std::shared_ptr &&reference_column); protected: - schema_node &node_; /**< prototype node of the represented object type */ + std::shared_ptr node_; /**< prototype node of the represented object type */ std::type_index type_index_; /**< type index of the represented object type */ object_definition definition_; std::shared_ptr reference_column_; diff --git a/include/matador/object/object_info.hpp b/include/matador/object/object_info.hpp index 6befa7f..cb32a03 100644 --- a/include/matador/object/object_info.hpp +++ b/include/matador/object/object_info.hpp @@ -10,9 +10,13 @@ class schema_node; template class object_info final : public basic_object_info { public: - explicit object_info(schema_node &node, object_definition &&definition, + explicit object_info(object_definition &&definition, std::shared_ptr &&ref_column) - : basic_object_info(node, typeid(Type), std::move(definition), std::move(ref_column)) { + : basic_object_info(typeid(Type), std::move(definition), std::move(ref_column)) { + } + explicit object_info(schema_node &node, + std::shared_ptr &&ref_column) + : basic_object_info(typeid(Type), std::move(ref_column)) { } const Type &prototype() const { return prototype_; } diff --git a/include/matador/object/schema.hpp b/include/matador/object/schema.hpp index e8673fa..b47f817 100644 --- a/include/matador/object/schema.hpp +++ b/include/matador/object/schema.hpp @@ -90,10 +90,9 @@ public: // analyze node (collect unknown types by type index) type_analyzer::analyze(*this); - auto node = schema_node::make_node(*this, name); + const auto node = schema_node::make_node(*this, name, {}); - auto result = attach_node(node, parent); - if (!result) { + if (auto result = attach_node(node, parent); !result) { return utils::failure(result.err()); } @@ -206,7 +205,7 @@ void type_analyzer::on_has_one(const char *, ForeignPointerType &, const u return; } - auto info = std::make_unique>(); + auto info = std::make_unique>(object_definition{}, std::make_unique(std::string(""), std::string(ti.name()), utils::basic_type::type_null, utils::constraints::FOREIGN_KEY)); known_types_.insert(ti); diff --git a/source/core/object/attribute_definition.cpp b/source/core/object/attribute_definition.cpp index 3c7e941..05ecabe 100644 --- a/source/core/object/attribute_definition.cpp +++ b/source/core/object/attribute_definition.cpp @@ -5,23 +5,47 @@ namespace matador::object { attribute_definition::attribute_definition(const char *name) - : name_(name) - , attributes_(utils::null_attributes) { +: name_(name) +, attributes_(utils::null_attributes) { } attribute_definition::attribute_definition(std::string name) - : name_(std::move(name)) - , attributes_(utils::null_attributes) { +: name_(std::move(name)) +, attributes_(utils::null_attributes) { +} + +attribute_definition::attribute_definition(std::string name, + std::string table_name, + const utils::basic_type type, + const utils::field_attributes& attr) +: name_(std::move(name)) +, table_(std::move(table_name)) +, index_(0) +, attributes_(attr) +, value_(type, attr.size()) { } attribute_definition::attribute_definition(std::string name, const utils::basic_type type, const utils::field_attributes &attr, const null_option null_opt, const size_t index) - : name_(std::move(name)) - , index_(index) - , attributes_(attr) - , null_option_(null_opt) - , value_(type, attr.size()) { +: name_(std::move(name)) +, index_(index) +, attributes_(attr) +, null_option_(null_opt) +, value_(type, attr.size()) { +} + +attribute_definition::attribute_definition(std::string name, + std::string table_name, + const utils::basic_type type, + const utils::field_attributes &attr, const null_option null_opt, + const size_t index) +: name_(std::move(name)) +, table_(std::move(table_name)) +, index_(index) +, attributes_(attr) +, null_option_(null_opt) +, value_(type, attr.size()) { } attribute_definition::attribute_definition(std::string name, @@ -29,12 +53,12 @@ attribute_definition::attribute_definition(std::string name, const size_t index, const std::shared_ptr &ref_column, const utils::field_attributes &attr, const null_option null_opt) - : name_(std::move(name)) - , index_(index) - , attributes_(attr) - , null_option_(null_opt) - , value_(type, attr.size()) - , reference_column_(ref_column) { +: name_(std::move(name)) +, index_(index) +, attributes_(attr) +, null_option_(null_opt) +, value_(type, attr.size()) +, reference_column_(ref_column) { } const std::string &attribute_definition::name() const { @@ -140,7 +164,25 @@ attribute_definition make_pk_column(const std::string &name, size_t } template<> -[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) { +attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) { + return { + name, utils::data_type_traits::type(size), 0, ref_column, + {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL + }; +} + +template<> +attribute_definition make_fk_column( const std::string& name, const std::string& ref_table_name, const std::string& ref_column_name ) { + return { + name, utils::basic_type::type_varchar, 0, + std::make_shared(ref_column_name, ref_table_name, utils::basic_type::type_varchar, utils::constraints::FOREIGN_KEY), + { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL + }; +} + +template<> +attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) { + const auto ref_column = std::make_shared(ref_column_name, ref_table_name, utils::basic_type::type_varchar, utils::constraints::FOREIGN_KEY); return { name, utils::data_type_traits::type(size), 0, ref_column, {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL diff --git a/source/core/object/basic_object_info.cpp b/source/core/object/basic_object_info.cpp index 71a2b7d..2422314 100644 --- a/source/core/object/basic_object_info.cpp +++ b/source/core/object/basic_object_info.cpp @@ -5,22 +5,26 @@ #include namespace matador::object { -basic_object_info::basic_object_info(schema_node &node, - const std::type_index type_index, +basic_object_info::basic_object_info(const std::type_index type_index, object_definition &&definition, std::shared_ptr &&reference_column) -: node_(node) -, type_index_(type_index) +: type_index_(type_index) , definition_(std::move(definition)) , reference_column_(std::move(reference_column)) { } +basic_object_info::basic_object_info(const std::type_index type_index, + std::shared_ptr &&reference_column) +: type_index_(type_index) +, reference_column_(std::move(reference_column)) { +} + std::type_index basic_object_info::type_index() const { return type_index_; } std::string basic_object_info::name() const { - return node_.name(); + return node_->name(); } const object_definition &basic_object_info::definition() const { diff --git a/source/core/object/object_definition.cpp b/source/core/object/object_definition.cpp index c537833..306f2d7 100644 --- a/source/core/object/object_definition.cpp +++ b/source/core/object/object_definition.cpp @@ -2,21 +2,18 @@ namespace matador::object { object_definition::object_definition(const std::initializer_list columns) -: columns_(columns) -{ +: columns_(columns) { init(); } object_definition::object_definition(const std::vector &columns) -: columns_(columns) -{ +: columns_(columns) { init(); } object_definition::object_definition(const object_definition &x) : columns_(x.columns_) -, pk_index_(x.pk_index_) -{ +, pk_index_(x.pk_index_) { for (auto& col : columns_) { add_to_map(col, col.index()); } diff --git a/source/core/object/schema.cpp b/source/core/object/schema.cpp index f43f54c..1a41ef7 100644 --- a/source/core/object/schema.cpp +++ b/source/core/object/schema.cpp @@ -45,7 +45,7 @@ utils::result, utils::error> schema::refer return utils::failure(make_error(error_code::Failure, "Primary key not found")); } - return utils::ok(std::make_pair(node->name(), node->basic_info().definition().primary_key()->name())); + return utils::ok(std::make_shared(node->name(), node->basic_info().definition().primary_key()->name(), utils::basic_type::type_null, utils::constraints::FOREIGN_KEY)); } utils::result, utils::error> schema::attach_node(const std::shared_ptr &node, diff --git a/source/core/object/schema_node.cpp b/source/core/object/schema_node.cpp index 1c38fcc..e330240 100644 --- a/source/core/object/schema_node.cpp +++ b/source/core/object/schema_node.cpp @@ -5,13 +5,12 @@ namespace matador::object { schema_node::schema_node(schema &tree) : schema_(tree) -, info_(std::make_unique(*this, object_definition{})) { +, info_(std::make_unique(object_definition{}, std::shared_ptr{})) { } schema_node::schema_node(schema &tree, std::string name, std::unique_ptr &&info) : schema_(tree) , info_(std::move(info)) -// , info_(std::make_unique>(*this, object_definition(attribute_definition_generator::generate(schema_)))) , first_child_(std::shared_ptr(new schema_node(tree))) , last_child_(std::shared_ptr(new schema_node(tree))) , name_(std::move(name)) { diff --git a/source/orm/query/query_compiler.cpp b/source/orm/query/query_compiler.cpp index 4a34ea9..70c7443 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -229,11 +229,9 @@ void query_compiler::visit(internal::query_create_part &/*create_part*/) query_.sql = dialect_->token_at(sql::dialect_token::CREATE); } -struct fk_context -{ +struct fk_context { std::string column; - std::string ref_table; - std::string ref_column; + std::shared_ptr reference_column; }; struct column_context @@ -273,7 +271,7 @@ void query_compiler::visit(internal::query_create_table_part &create_table_part) result += ", CONSTRAINT FK_" + create_table_part.table().name; result += "_" + fk.column; result += " FOREIGN KEY (" + fk.column + ")"; - result += " REFERENCES " + fk.ref_table + "(" + fk.ref_column + ")"; + result += " REFERENCES " + fk.reference_column->table_name() + "(" + fk.reference_column->name() + ")"; } result += ")"; @@ -340,7 +338,7 @@ std::string build_create_column(const object::attribute_definition &col, const s context.primary_keys.emplace_back(col.name()); } if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) { - context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()}); + context.foreign_contexts.push_back({col.name(), col.reference_column()}); } return result; diff --git a/test/orm/sql/ColumnTest.cpp b/test/orm/sql/ColumnTest.cpp index 9bcc505..20b69eb 100644 --- a/test/orm/sql/ColumnTest.cpp +++ b/test/orm/sql/ColumnTest.cpp @@ -11,8 +11,8 @@ TEST_CASE("Test create empty column", "[column]") { REQUIRE(c.name() == "name"); REQUIRE(c.index() == -1); REQUIRE(c.type() == basic_type::type_null); - REQUIRE(c.ref_table().empty()); - REQUIRE(c.ref_column().empty()); + REQUIRE(c.reference_column()->table_name().empty()); + REQUIRE(c.reference_column()->name().empty()); c.set(std::string{"george"}, 255); REQUIRE(c.type() == basic_type::type_varchar); @@ -30,8 +30,8 @@ TEST_CASE("Test copy and move column", "[column]") { c.set(std::string{"george"}, 255); REQUIRE(c.name() == "name"); REQUIRE(c.index() == -1); - REQUIRE(c.ref_table().empty()); - REQUIRE(c.ref_column().empty()); + REQUIRE(c.reference_column()->table_name().empty()); + REQUIRE(c.reference_column()->name().empty()); REQUIRE(c.type() == basic_type::type_varchar); REQUIRE(c.as() == "george"); REQUIRE(c.attributes().size() == 255); @@ -39,8 +39,8 @@ TEST_CASE("Test copy and move column", "[column]") { auto c2 = c; REQUIRE(c2.name() == "name"); REQUIRE(c2.index() == -1); - REQUIRE(c2.ref_table().empty()); - REQUIRE(c2.ref_column().empty()); + REQUIRE(c2.reference_column()->table_name().empty()); + REQUIRE(c2.reference_column()->name().empty()); REQUIRE(c2.type() == basic_type::type_varchar); REQUIRE(c2.as() == "george"); REQUIRE(c2.attributes().size() == 255); @@ -48,16 +48,16 @@ TEST_CASE("Test copy and move column", "[column]") { auto c3 = std::move(c2); REQUIRE(c3.name() == "name"); REQUIRE(c3.index() == -1); - REQUIRE(c3.ref_table().empty()); - REQUIRE(c3.ref_column().empty()); + REQUIRE(c3.reference_column()->table_name().empty()); + REQUIRE(c3.reference_column()->name().empty()); REQUIRE(c3.type() == basic_type::type_varchar); REQUIRE(c3.as() == "george"); REQUIRE(c3.attributes().size() == 255); REQUIRE(c2.name().empty()); REQUIRE(c2.index() == -1); - REQUIRE(c2.ref_table().empty()); - REQUIRE(c2.ref_column().empty()); + REQUIRE(c2.reference_column()->table_name().empty()); + REQUIRE(c2.reference_column()->name().empty()); REQUIRE(c2.type() == basic_type::type_null); // REQUIRE(!c2.as().has_value()); REQUIRE(c2.attributes().size() == 255);