removed make_relation_node method from repository_node
This commit is contained in:
parent
263c202c69
commit
d4ef97ef5a
|
|
@ -2,8 +2,8 @@ CPMAddPackage("gh:catchorg/Catch2@3.7.1")
|
|||
|
||||
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
|
||||
|
||||
set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:15442/matador")
|
||||
#set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador")
|
||||
#set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:15442/matador")
|
||||
set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador")
|
||||
|
||||
configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "matador/utils/field_attributes.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
|
|
@ -60,6 +61,8 @@ public:
|
|||
return type() == utils::data_type_traits<Type>::type(attributes().size());
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const attribute& attr);
|
||||
|
||||
private:
|
||||
friend class object;
|
||||
friend class attribute_generator;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ public:
|
|||
|
||||
[[nodiscard]] std::type_index type_index() const;
|
||||
[[nodiscard]] std::string name() const;
|
||||
[[nodiscard]] const class object& object() const;
|
||||
[[nodiscard]] const std::list<attribute>& attributes() const;
|
||||
[[nodiscard]] const std::list<class constraint>& constraints() const;
|
||||
|
||||
|
|
@ -54,10 +55,10 @@ public:
|
|||
[[nodiscard]] bool endpoints_empty() const;
|
||||
|
||||
protected:
|
||||
basic_object_info(std::shared_ptr<repository_node> node, std::unique_ptr<object> &&obj);
|
||||
basic_object_info(std::shared_ptr<repository_node> node, std::unique_ptr<class object> &&obj);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<object> object_;
|
||||
std::unique_ptr<class object> object_;
|
||||
std::shared_ptr<repository_node> node_; /**< prototype node of the represented object type */
|
||||
t_endpoint_map relation_endpoints_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "matador/utils/constraints.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
|
|
@ -28,6 +29,8 @@ public:
|
|||
[[nodiscard]] const std::string& ref_table_name() const;
|
||||
[[nodiscard]] const std::string& ref_column_name() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const constraint& c);
|
||||
|
||||
private:
|
||||
friend class constraint_builder;
|
||||
friend class constraints_generator;
|
||||
|
|
|
|||
|
|
@ -115,13 +115,13 @@ private:
|
|||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
result = repository_node::make_relation_node<relation_value_type>(repo_.repo(), name, std::move(creator));
|
||||
auto node = repository_node::make_node<relation_value_type>(repo_.repo(), name, std::move(creator));
|
||||
result = repo_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
|
||||
auto& node = result.value();
|
||||
complete<relation_value_type>(result.value());
|
||||
|
||||
// auto& node = result.value();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "matador/utils/identifier.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <ostream>
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
|
|
@ -38,6 +39,8 @@ public:
|
|||
[[nodiscard]] size_t constraint_count() const;
|
||||
[[nodiscard]] const std::list<class constraint>& constraints() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const object& obj);
|
||||
|
||||
private:
|
||||
friend class constraints_generator;
|
||||
friend class attribute_generator;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public:
|
|||
using create_func = std::function<std::unique_ptr<Type>()>;
|
||||
|
||||
object_info(const std::shared_ptr<repository_node>& node,
|
||||
std::unique_ptr<object> &&obj,
|
||||
std::unique_ptr<class object> &&obj,
|
||||
create_func&& creator)
|
||||
: basic_object_info(node, std::move(obj))
|
||||
, creator_(std::move(creator)){
|
||||
|
|
|
|||
|
|
@ -186,28 +186,28 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
|
|||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasMany, foreign_node);
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
|
||||
} else {
|
||||
// A relation table is necessary
|
||||
// Endpoint was not found.
|
||||
// Always attach a many-to-many relation type. If later a
|
||||
// belongs-to relation handles this relation, the many-to-many
|
||||
// relation is maybe detached.
|
||||
log_.debug("node '%s' has has many foreign keys '%s' mapped by '%s'", nodes_.top()->name().c_str(), id, join_column);
|
||||
result = repository_node::make_relation_node<relation_value_type>(
|
||||
schema_.repo(), id, [join_column] {
|
||||
return std::make_unique<relation_value_type>("id", join_column);
|
||||
});
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasMany, result.value());
|
||||
const auto foreign_endpoint = std::make_shared<relation_endpoint>("id", relation_type::BelongsTo, nodes_.top());
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
|
||||
result.value()->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
link_relation_endpoints(local_endpoint, foreign_endpoint);
|
||||
// A relation table is necessary
|
||||
// Endpoint was not found.
|
||||
// Always attach a many-to-many relation type. If later a
|
||||
// belongs-to relation handles this relation, the many-to-many
|
||||
// relation is maybe detached.
|
||||
log_.debug("node '%s' has has many foreign keys '%s' mapped by '%s'", nodes_.top()->name().c_str(), id, join_column);
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), id, [join_column] {
|
||||
return std::make_unique<relation_value_type>("id", join_column);
|
||||
});
|
||||
result = schema_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasMany, node);
|
||||
const auto foreign_endpoint = std::make_shared<relation_endpoint>("id", relation_type::BelongsTo, nodes_.top());
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
|
||||
node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
link_relation_endpoints(local_endpoint, foreign_endpoint);
|
||||
|
||||
const auto foreign_value_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BelongsTo, foreign_node);
|
||||
result.value()->info_->register_relation_endpoint(typeid(value_type), foreign_value_endpoint);
|
||||
const auto foreign_value_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BelongsTo, foreign_node);
|
||||
node->info_->register_relation_endpoint(typeid(value_type), foreign_value_endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,21 +220,20 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &, con
|
|||
using value_type = typename CollectionType::value_type;
|
||||
using relation_value_type = many_to_relation<Type, value_type>;
|
||||
|
||||
const auto result = repository_node::make_relation_node<relation_value_type>(
|
||||
schema_.repo(), id, [join_column] {
|
||||
return std::make_unique<relation_value_type>(join_column, "value");
|
||||
});
|
||||
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), id, [join_column] {
|
||||
return std::make_unique<relation_value_type>(join_column, "value");
|
||||
});
|
||||
const auto result = schema_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal exception
|
||||
return;
|
||||
}
|
||||
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasMany, result.value());
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasMany, node);
|
||||
const auto foreign_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BelongsTo, nodes_.top());
|
||||
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
|
||||
result.value()->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
link_relation_endpoints(local_endpoint, foreign_endpoint);
|
||||
}
|
||||
|
||||
|
|
@ -265,13 +264,13 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
|
|||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
result = repository_node::make_relation_node<relation_value_type>(schema_.repo(), id, std::move(creator));
|
||||
auto node = repository_node::make_node<relation_value_type>(schema_.repo(), id, std::move(creator));
|
||||
result = schema_.attach_node(node);
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
|
||||
auto& node = result.value();
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HasMany, node);
|
||||
const auto join_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BelongsTo, nodes_.top());
|
||||
const auto inverse_join_endpoint = std::make_shared<relation_endpoint>(inverse_join_column, relation_type::BelongsTo, foreign_node);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include "matador/object/attribute_generator.hpp"
|
||||
#include "matador/object/object_generator.hpp"
|
||||
#include "matador/object/object_info.hpp"
|
||||
#include "matador/object/primary_key_resolver.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -16,42 +15,24 @@ class repository;
|
|||
class repository_node final {
|
||||
public:
|
||||
using node_ptr = std::shared_ptr<repository_node>;
|
||||
template< typename Type>
|
||||
using creator_func = std::function<std::unique_ptr<Type>()>;
|
||||
|
||||
template < typename Type >
|
||||
static std::shared_ptr<repository_node> make_node(repository& repo, const std::string& name) {
|
||||
static std::shared_ptr<repository_node> make_node(repository& repo, const std::string& name, creator_func<Type> creator = []{ return std::make_unique<Type>(); }) {
|
||||
auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, typeid(Type)));
|
||||
|
||||
primary_key_resolver resolver;
|
||||
auto pk_info = resolver.resolve<Type>();
|
||||
auto obj = object_generator::generate<Type>(repo, name);
|
||||
auto obj = object_generator::generate<Type>(creator(), repo, name);
|
||||
auto info = std::make_unique<object_info<Type>>(
|
||||
node,
|
||||
std::move(obj),
|
||||
[]{ return std::make_unique<Type>(); }
|
||||
std::forward<creator_func<Type>>(creator)
|
||||
);
|
||||
node->info_ = std::move(info);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
template < typename Type, typename CreatorFunc >
|
||||
static utils::result<node_ptr, utils::error> make_relation_node(repository& repo, const std::string& name, CreatorFunc &&creator) {
|
||||
const auto result = make_and_attach_node(repo, name, typeid(Type));
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto obj = object_generator::generate(creator(), repo, name);
|
||||
auto info = std::make_unique<object_info<Type>>(
|
||||
result.value(),
|
||||
std::move(obj),
|
||||
std::forward<CreatorFunc>(creator)
|
||||
);
|
||||
result.value()->info_ = std::move(info);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::shared_ptr<repository_node> make_null_node(repository& repo);
|
||||
|
||||
repository_node(const repository_node& other) = delete;
|
||||
|
|
@ -87,10 +68,6 @@ private:
|
|||
void unlink();
|
||||
|
||||
static utils::result<node_ptr, utils::error> make_and_attach_node(repository& repo, const std::string& name, const std::type_index& ti);
|
||||
static attribute* determine_reference_column(const std::type_index& ti,
|
||||
const std::string& table_name,
|
||||
const primary_key_info& pk_info,
|
||||
repository& repo);
|
||||
|
||||
private:
|
||||
friend class repository;
|
||||
|
|
|
|||
|
|
@ -92,45 +92,9 @@ bool attribute::is_null() const {
|
|||
return type_ == utils::basic_type::type_null;
|
||||
}
|
||||
|
||||
// attribute make_column(const std::string &name, utils::basic_type type, utils::field_attributes attr,
|
||||
// null_option_type null_opt) {
|
||||
// return {name, type, attr, null_opt};
|
||||
// }
|
||||
//
|
||||
// template<>
|
||||
// attribute make_column<std::string>(const std::string &name, utils::field_attributes attr,
|
||||
// null_option_type null_opt) {
|
||||
// return make_column(name, utils::data_type_traits<std::string>::type(attr.size()), attr, null_opt);
|
||||
// }
|
||||
//
|
||||
// template<>
|
||||
// attribute make_pk_column<std::string>(const std::string &name, size_t size) {
|
||||
// return make_column<std::string>(name, {size, utils::constraints::PrimaryKey});
|
||||
// }
|
||||
//
|
||||
// template<>
|
||||
// attribute make_fk_column<std::string>(const std::string &name, size_t size, const std::shared_ptr<attribute> &ref_column) {
|
||||
// return {
|
||||
// name, utils::data_type_traits<std::string>::type(size), 0, ref_column,
|
||||
// {size, utils::constraints::ForeignKey}, null_option_type::NOT_NULL
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// template<>
|
||||
// attribute make_fk_column<std::string>( 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<attribute>(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::ForeignKey}),
|
||||
// { 0, utils::constraints::ForeignKey }, null_option_type::NOT_NULL
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// template<>
|
||||
// attribute make_fk_column<std::string>(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<attribute>(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::ForeignKey});
|
||||
// return {
|
||||
// name, utils::data_type_traits<std::string>::type(size), 0, ref_column,
|
||||
// {size, utils::constraints::ForeignKey}, null_option_type::NOT_NULL
|
||||
// };
|
||||
// }
|
||||
std::ostream & operator<<(std::ostream &os, const attribute &attr) {
|
||||
os << attr.name_;
|
||||
return os;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace matador::object {
|
|||
// : node_(std::move(node))
|
||||
// , attributes_(attributes) {}
|
||||
|
||||
basic_object_info::basic_object_info(std::shared_ptr<repository_node> node, std::unique_ptr<object>&& obj)
|
||||
basic_object_info::basic_object_info(std::shared_ptr<repository_node> node, std::unique_ptr<class object>&& obj)
|
||||
: object_(std::move(obj))
|
||||
, node_(std::move(node)) {}
|
||||
|
||||
|
|
@ -32,6 +32,10 @@ std::string basic_object_info::name() const {
|
|||
return node_->name();
|
||||
}
|
||||
|
||||
const class object & basic_object_info::object() const {
|
||||
return *object_;
|
||||
}
|
||||
|
||||
const std::list<attribute>& basic_object_info::attributes() const {
|
||||
return object_->attributes();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,11 @@ const std::string& constraint::ref_column_name() const {
|
|||
return ref_column_name_;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream &os, const class constraint &c) {
|
||||
os << "constraint " << c.name_ << " for column " << c.column_name();
|
||||
return os;
|
||||
}
|
||||
|
||||
constraint_builder & constraint_builder::constraint(std::string name) {
|
||||
constraint_name = std::move(name);
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -75,4 +75,17 @@ size_t object::constraint_count() const {
|
|||
const std::list<class constraint>& object::constraints() const {
|
||||
return constraints_;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream &os, const object &obj) {
|
||||
os << "Object " << obj.name_ << "\nAttributes:\n";
|
||||
for (const auto &attr : obj.attributes_) {
|
||||
os << " " << attr << "\n";
|
||||
}
|
||||
os << "Constraints:\n";
|
||||
for (const auto &con : obj.constraints_) {
|
||||
os << " " << con << "\n";
|
||||
}
|
||||
os << "\n";
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ repository_node::repository_node(repository &repo, std::string name, const std::
|
|||
|
||||
std::shared_ptr<repository_node> repository_node::make_null_node(repository &repo) {
|
||||
auto node = std::shared_ptr<repository_node>(new repository_node(repo));
|
||||
node->info_ = std::make_unique<null_info>(node/*, std::shared_ptr<attribute_definition>{}*/);
|
||||
node->info_ = std::make_unique<null_info>(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
|
@ -101,27 +101,4 @@ utils::result<repository_node::node_ptr, utils::error> repository_node::make_and
|
|||
|
||||
return repo.attach_node(node, "");
|
||||
}
|
||||
|
||||
attribute* repository_node::determine_reference_column(const std::type_index& ti,
|
||||
const std::string& table_name,
|
||||
const primary_key_info& pk_info,
|
||||
repository& repo) {
|
||||
const auto it = repo.missing_references_.find(ti);
|
||||
if (it == repo.missing_references_.end()) {
|
||||
return new attribute(pk_info.pk_column_name, pk_info.type, {utils::constraints::ForeignKey}, null_option_type::NotNull);
|
||||
}
|
||||
|
||||
auto ref_column = it->second;
|
||||
repo.missing_references_.erase(it);
|
||||
ref_column->name(pk_info.pk_column_name);
|
||||
ref_column->owner()->update_name(table_name);
|
||||
ref_column->change_type(pk_info.type);
|
||||
ref_column->attributes() = utils::constraints::ForeignKey;
|
||||
|
||||
if (table_name.empty()) {
|
||||
repo.missing_references_.insert({ti, ref_column});
|
||||
}
|
||||
|
||||
return ref_column;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ TEST_CASE("Test one to many", "[relation][one-to-many]") {
|
|||
REQUIRE(repo.size() == 2);
|
||||
REQUIRE(repo.contains("departments"));
|
||||
REQUIRE(repo.contains("employees"));
|
||||
|
||||
std::cout << repo.basic_info("departments")->get().object();
|
||||
std::cout << repo.basic_info("employees")->get().object();
|
||||
}
|
||||
|
||||
TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") {
|
||||
|
|
@ -117,6 +120,9 @@ TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") {
|
|||
REQUIRE(repo.size() == 2);
|
||||
REQUIRE(repo.contains("departments"));
|
||||
REQUIRE(repo.contains("employees"));
|
||||
|
||||
std::cout << repo.basic_info("departments")->get().object();
|
||||
std::cout << repo.basic_info("employees")->get().object();
|
||||
}
|
||||
|
||||
TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
||||
|
|
@ -133,5 +139,7 @@ TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
|||
REQUIRE(repo.contains("recipes"));
|
||||
REQUIRE(repo.contains("recipe_ingredients"));
|
||||
|
||||
auto info = repo.basic_info("ingredients");
|
||||
std::cout << repo.basic_info("ingredients")->get().object();
|
||||
std::cout << repo.basic_info("recipes")->get().object();
|
||||
std::cout << repo.basic_info("recipe_ingredients")->get().object();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue