object generation progress

This commit is contained in:
Sascha Kühl 2025-12-01 22:03:07 +01:00
parent 422df82b7c
commit c156ab5e74
10 changed files with 62 additions and 77 deletions

View File

@ -6,6 +6,7 @@
#include "matador/utils/identifier.hpp" #include "matador/utils/identifier.hpp"
#include <list>
#include <string> #include <string>
#include <typeindex> #include <typeindex>
@ -24,8 +25,7 @@ public:
[[nodiscard]] std::type_index type_index() const; [[nodiscard]] std::type_index type_index() const;
[[nodiscard]] std::string name() const; [[nodiscard]] std::string name() const;
[[nodiscard]] const std::vector<attribute>& attributes() const; [[nodiscard]] const std::list<attribute>& attributes() const;
// [[nodiscard]] std::shared_ptr<attribute> reference_column() const;
[[nodiscard]] bool has_primary_key() const; [[nodiscard]] bool has_primary_key() const;
[[nodiscard]] const utils::identifier& primary_key() const; [[nodiscard]] const utils::identifier& primary_key() const;
@ -50,8 +50,6 @@ public:
[[nodiscard]] bool endpoints_empty() const; [[nodiscard]] bool endpoints_empty() const;
protected: protected:
// basic_object_info(std::shared_ptr<repository_node> node, const std::vector<attribute> &attributes, utils::identifier &&pk, const std::shared_ptr<attribute> &pk_as_fk_column);
// basic_object_info(std::shared_ptr<repository_node> node, const std::vector<attribute> &attributes);
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<object> &&obj);
protected: protected:

View File

@ -7,8 +7,8 @@
#include "matador/utils/field_attributes.hpp" #include "matador/utils/field_attributes.hpp"
#include "matador/utils/primary_key_attribute.hpp" #include "matador/utils/primary_key_attribute.hpp"
#include <list>
#include <typeindex> #include <typeindex>
#include <vector>
namespace matador::object { namespace matador::object {
class object; class object;
@ -17,20 +17,20 @@ class repository;
class constraints_generator final { class constraints_generator final {
private: private:
constraints_generator(std::vector<class constraint> &constraints, const repository &repo, object &obj); constraints_generator(std::list<class constraint> &constraints, const repository &repo, object &obj);
public: public:
constraints_generator() = delete; constraints_generator() = delete;
template < typename Type > template < typename Type >
static std::vector<class constraint> generate(const repository &repo, object &obj) { static std::list<class constraint> generate(const repository &repo, object &obj) {
Type t; Type t;
return generate(t, repo, obj); return generate(t, repo, obj);
} }
template < typename Type > template < typename Type >
static std::vector<class constraint> generate(const Type& t, const repository &repo, object &obj) { static std::list<class constraint> generate(const Type& t, const repository &repo, object &obj) {
std::vector<class constraint> constraints; std::list<class constraint> constraints;
constraints_generator gen(constraints, repo, obj); constraints_generator gen(constraints, repo, obj);
access::process(gen, t); access::process(gen, t);
return constraints; return constraints;
@ -66,10 +66,10 @@ private:
void create_fk_constraint(const std::type_index& ti, 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; void create_unique_constraint(const std::string& name) const;
[[nodiscard]] std::vector<attribute>::iterator find_attribute_by_name(const std::string &name) const; [[nodiscard]] std::list<attribute>::iterator find_attribute_by_name(const std::string &name) const;
private: private:
std::vector<class constraint> &constraints_; std::list<class constraint> &constraints_;
const repository &repo_; const repository &repo_;
object &obj_; object &obj_;
}; };

View File

@ -8,6 +8,8 @@
#include "matador/utils/identifier.hpp" #include "matador/utils/identifier.hpp"
#include <list>
namespace matador::object { namespace matador::object {
class repository; class repository;
@ -16,22 +18,6 @@ class object {
public: public:
explicit object(std::string name, std::string alias = ""); explicit object(std::string name, std::string alias = "");
// template<typename Type>
// static std::unique_ptr<object> generate(const repository& repo, std::string name, std::string alias = "") {
// auto obj = std::make_unique<object>(std::move(name), std::move(alias));
// obj->attributes_ = std::move(attribute_generator::generate<Type>(repo, *obj));
// obj->constraints_ = std::move(constraints_generator::generate<Type>(repo, *obj));
// return obj;
// }
//
// template<typename Type>
// static std::unique_ptr<object> generate(const std::unique_ptr<Type>& ptr, const repository& repo, std::string name, std::string alias = "") {
// auto obj = std::make_unique<object>(std::move(name), std::move(alias));
// obj->attributes_ = std::move(attribute_generator::generate(*ptr, repo, *obj));
// obj->constraints_ = std::move(constraints_generator::generate(*ptr, repo, *obj));
// return obj;
// }
static const attribute& create_attribute(std::string name, object& obj); static const attribute& create_attribute(std::string name, object& obj);
void add_attribute(attribute attr); void add_attribute(attribute attr);
@ -48,11 +34,11 @@ public:
[[nodiscard]] bool has_attributes() const; [[nodiscard]] bool has_attributes() const;
[[nodiscard]] size_t attribute_count() const; [[nodiscard]] size_t attribute_count() const;
[[nodiscard]] const std::vector<attribute>& attributes() const; [[nodiscard]] const std::list<attribute>& attributes() const;
[[nodiscard]] bool has_constraints() const; [[nodiscard]] bool has_constraints() const;
[[nodiscard]] size_t constraint_count() const; [[nodiscard]] size_t constraint_count() const;
[[nodiscard]] const std::vector<class constraint>& constraints() const; [[nodiscard]] const std::list<class constraint>& constraints() const;
private: private:
friend class constraints_generator; friend class constraints_generator;
@ -64,8 +50,8 @@ private:
attribute* pk_attribute_{nullptr}; attribute* pk_attribute_{nullptr};
utils::identifier pk_identifier_; utils::identifier pk_identifier_;
std::vector<attribute> attributes_; std::list<attribute> attributes_;
std::vector<class constraint> constraints_; std::list<class constraint> constraints_;
}; };
} }
#endif //MATADOR_OBJECT_HPP #endif //MATADOR_OBJECT_HPP

View File

@ -86,12 +86,10 @@ public:
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
template <class Pointer> template <class Pointer>
void on_foreign_key(const char *id, Pointer &x) { void on_foreign_key(const char *id, Pointer &/*x*/) {
const auto type = pk_type_determinator::determine<typename Pointer::value_type>(); const auto type = pk_type_determinator::determine<typename Pointer::value_type>();
auto &ref = object_->attributes_.emplace_back(id, type, utils::constraints::ForeignKey, null_option_type::NOT_NULL); auto &ref = object_->attributes_.emplace_back(id, type, utils::constraints::ForeignKey, null_option_type::NOT_NULL);
ref.owner_ = object_.get(); ref.owner_ = object_.get();
create_fk_constraint(typeid(typename Pointer::value_type), id);
} }
template<class ContainerType> template<class ContainerType>
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
@ -112,7 +110,7 @@ private:
void create_fk_constraint(const std::type_index& ti, 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; void create_unique_constraint(const std::string& name) const;
[[nodiscard]] std::vector<attribute>::iterator find_attribute_by_name(const std::string &name) const; [[nodiscard]] std::list<attribute>::iterator find_attribute_by_name(const std::string &name) const;
void prepare_primary_key(attribute &ref, utils::identifier &&pk) const; void prepare_primary_key(attribute &ref, utils::identifier &&pk) const;

View File

@ -114,27 +114,28 @@ public:
template<class ContainerType> template<class ContainerType>
void on_has_many(const char * /*id*/, ContainerType &, const char *join_column, const utils::foreign_attributes &attr) { void on_has_many(const char * /*id*/, ContainerType &, const char *join_column, const utils::foreign_attributes &attr) {
if (attr.fetch() == utils::fetch_type::EAGER) { if (attr.fetch() == utils::fetch_type::EAGER) {
const auto info = schema_.info<typename ContainerType::value_type::value_type>(); const auto result = schema_.basic_info(typeid(typename ContainerType::value_type::value_type));
if (!info) { if (!result) {
throw query_builder_exception{query_build_error::UnknownType}; throw query_builder_exception{query_build_error::UnknownType};
} }
auto next = processed_tables_.find(info->get().name()); const auto &info = result.value().get();
auto next = processed_tables_.find(info.name());
if (next != processed_tables_.end()) { if (next != processed_tables_.end()) {
return; return;
} }
table_info_stack_.push({info.value(), std::make_shared<query::table>(info->get().name(), build_alias('t', ++table_index))}); table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first; next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
typename ContainerType::value_type::value_type obj; typename ContainerType::value_type::value_type obj;
access::process(*this , obj); access::process(*this , obj);
table_info_stack_.pop(); table_info_stack_.pop();
if (!info->get().has_primary_key()) { if (!info.has_primary_key()) {
throw query_builder_exception{query_build_error::MissingPrimaryKey}; throw query_builder_exception{query_build_error::MissingPrimaryKey};
} }
append_join( append_join(
query::column{table_info_stack_.top().table, table_info_stack_.top().info.get().reference_column()->name()}, query::column{table_info_stack_.top().table, table_info_stack_.top().info.get().primary_key_attribute()->name()},
query::column{next->second, join_column} query::column{next->second, join_column}
); );
} }
@ -145,12 +146,13 @@ public:
if (attr.fetch() != utils::fetch_type::EAGER) { if (attr.fetch() != utils::fetch_type::EAGER) {
return; return;
} }
const auto info = schema_.info<typename ContainerType::value_type::value_type>(); const auto result = schema_.basic_info(typeid(typename ContainerType::value_type::value_type));
if (!info) { if (!result) {
throw query_builder_exception{query_build_error::UnknownType}; throw query_builder_exception{query_build_error::UnknownType};
} }
auto next = processed_tables_.find(info->get().name()); const auto &info = result.value().get();
auto next = processed_tables_.find(info.name());
if (next != processed_tables_.end()) { if (next != processed_tables_.end()) {
return; return;
} }
@ -159,23 +161,23 @@ public:
relation = processed_tables_.insert({id, std::make_shared<query::table>(id, build_alias('t', ++table_index))}).first; relation = processed_tables_.insert({id, std::make_shared<query::table>(id, build_alias('t', ++table_index))}).first;
} }
table_info_stack_.push({info.value(), std::make_shared<query::table>(info->get().name(), build_alias('t', ++table_index))}); table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first; next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
typename ContainerType::value_type::value_type obj; typename ContainerType::value_type::value_type obj;
access::process(*this , obj); access::process(*this , obj);
table_info_stack_.pop(); table_info_stack_.pop();
if (!info->get().has_primary_key()) { if (!info.has_primary_key()) {
throw query_builder_exception{query_build_error::MissingPrimaryKey}; throw query_builder_exception{query_build_error::MissingPrimaryKey};
} }
append_join( append_join(
query::column{table_info_stack_.top().table, table_info_stack_.top().info.get().reference_column()->name()}, query::column{table_info_stack_.top().table, table_info_stack_.top().info.get().primary_key_attribute()->name()},
query::column{relation->second, join_column} query::column{relation->second, join_column}
); );
append_join( append_join(
query::column{relation->second, inverse_join_column}, query::column{relation->second, inverse_join_column},
query::column{next->second, info->get().reference_column()->name()} query::column{next->second, info.primary_key_attribute()->name()}
); );
} }
@ -184,12 +186,13 @@ public:
if (attr.fetch() != utils::fetch_type::EAGER) { if (attr.fetch() != utils::fetch_type::EAGER) {
return; return;
} }
const auto info = schema_.info<typename ContainerType::value_type::value_type>(); const auto result = schema_.basic_info(typeid(typename ContainerType::value_type::value_type));
if (!info) { if (!result) {
throw query_builder_exception{query_build_error::UnknownType}; throw query_builder_exception{query_build_error::UnknownType};
} }
auto next = processed_tables_.find(info->get().name()); const auto &info = result.value().get();
auto next = processed_tables_.find(info.name());
if (next != processed_tables_.end()) { if (next != processed_tables_.end()) {
return; return;
} }
@ -198,25 +201,25 @@ public:
if (relation == processed_tables_.end()) { if (relation == processed_tables_.end()) {
relation = processed_tables_.insert({id, std::make_shared<query::table>(id, build_alias('t', ++table_index))}).first; relation = processed_tables_.insert({id, std::make_shared<query::table>(id, build_alias('t', ++table_index))}).first;
} }
table_info_stack_.push({info.value(), std::make_shared<query::table>(info->get().name(), build_alias('t', ++table_index))}); table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first; next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
typename ContainerType::value_type::value_type obj; typename ContainerType::value_type::value_type obj;
access::process(*this , obj); access::process(*this , obj);
table_info_stack_.pop(); table_info_stack_.pop();
if (!info->get().has_primary_key()) { if (!info.has_primary_key()) {
throw query_builder_exception{query_build_error::MissingPrimaryKey}; throw query_builder_exception{query_build_error::MissingPrimaryKey};
} }
const auto join_columns = join_columns_collector_.collect<typename ContainerType::value_type::value_type>(); const auto join_columns = join_columns_collector_.collect<typename ContainerType::value_type::value_type>();
append_join( append_join(
query::column{table_info_stack_.top().table, table_info_stack_.top().info.get().reference_column()->name()}, query::column{table_info_stack_.top().table, table_info_stack_.top().info.get().primary_key_attribute()->name()},
query::column{relation->second, join_columns.inverse_join_column} query::column{relation->second, join_columns.inverse_join_column}
); );
append_join( append_join(
query::column{relation->second, join_columns.join_column}, query::column{relation->second, join_columns.join_column},
query::column{next->second, info->get().reference_column()->name()} query::column{next->second, info.primary_key_attribute()->name()}
); );
} }

View File

@ -32,14 +32,10 @@ std::string basic_object_info::name() const {
return node_->name(); return node_->name();
} }
const std::vector<attribute>& basic_object_info::attributes() const { const std::list<attribute>& basic_object_info::attributes() const {
return object_->attributes(); return object_->attributes();
} }
// std::shared_ptr<attribute> basic_object_info::reference_column() const {
// return pk_as_fk_column_;
// }
bool basic_object_info::has_primary_key() const { bool basic_object_info::has_primary_key() const {
return object_->has_primary_key(); return object_->has_primary_key();
} }

View File

@ -5,7 +5,7 @@
#include <algorithm> #include <algorithm>
namespace matador::object { namespace matador::object {
constraints_generator::constraints_generator(std::vector<class constraint> &constraints, const repository& repo, object &obj) constraints_generator::constraints_generator(std::list<class constraint> &constraints, const repository& repo, object &obj)
: constraints_(constraints) : constraints_(constraints)
, repo_(repo) , repo_(repo)
, obj_(obj) {} , obj_(obj) {}
@ -46,7 +46,7 @@ void constraints_generator::create_unique_constraint(const std::string& name) co
pk_constraint.owner_ = &obj_; pk_constraint.owner_ = &obj_;
} }
std::vector<attribute>::iterator constraints_generator::find_attribute_by_name(const std::string& name) const { std::list<attribute>::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 std::find_if(std::begin(obj_.attributes_), std::end(obj_.attributes_), [&name](const attribute& elem) {
return elem.name() == name; return elem.name() == name;
}); });

View File

@ -53,7 +53,7 @@ size_t object::attribute_count() const {
return attributes_.size(); return attributes_.size();
} }
const std::vector<attribute>& object::attributes() const { const std::list<attribute>& object::attributes() const {
return attributes_; return attributes_;
} }
@ -65,7 +65,7 @@ size_t object::constraint_count() const {
return constraints_.size(); return constraints_.size();
} }
const std::vector<class constraint>& object::constraints() const { const std::list<class constraint>& object::constraints() const {
return constraints_; return constraints_;
} }
} }

View File

@ -2,6 +2,8 @@
#include "matador/object/repository.hpp" #include "matador/object/repository.hpp"
#include <algorithm>
namespace matador::object { namespace matador::object {
object_generator::object_generator( const repository& repo, std::unique_ptr<object>&& object ) object_generator::object_generator( const repository& repo, std::unique_ptr<object>&& object )
: repo_(repo) : repo_(repo)
@ -47,7 +49,7 @@ void object_generator::create_unique_constraint(const std::string& name) const {
pk_constraint.owner_ = object_.get(); pk_constraint.owner_ = object_.get();
} }
std::vector<attribute>::iterator object_generator::find_attribute_by_name(const std::string& name) const { std::list<attribute>::iterator object_generator::find_attribute_by_name(const std::string& name) const {
return std::find_if(std::begin(object_->attributes_), std::end(object_->attributes_), [&name](const attribute& elem) { return std::find_if(std::begin(object_->attributes_), std::end(object_->attributes_), [&name](const attribute& elem) {
return elem.name() == name; return elem.name() == name;
}); });

View File

@ -18,13 +18,15 @@ struct student final : person {};
struct teacher final : person {}; struct teacher final : person {};
struct names { struct names {
std::vector<std::string> names_list; unsigned int id{};
std::vector<std::string> names_list;
template<typename Operator> template<typename Operator>
void process(Operator &op) { void process(Operator &op) {
namespace field = matador::access; namespace field = matador::access;
field::has_many(op, "name_list", names_list, "names_id", utils::fetch_type::EAGER); field::primary_key(op, "id", id);
} field::has_many(op, "name_list", names_list, "names_id", utils::fetch_type::EAGER);
}
}; };
TEST_CASE("Test empty prototype tree", "[schema_node][empty]") { TEST_CASE("Test empty prototype tree", "[schema_node][empty]") {
@ -75,10 +77,10 @@ TEST_CASE("Test automatic creating of a relation table with foreign key", "[sche
} }
TEST_CASE("Test automatic creating of a relation table with values", "[schema][relation_table][values]") { TEST_CASE("Test automatic creating of a relation table with values", "[schema][relation_table][values]") {
object::repository tree; object::repository repo;
REQUIRE( tree.empty() ); REQUIRE( repo.empty() );
auto res = tree.attach<names>("names"); auto res = repo.attach<names>("names");
REQUIRE( res.is_ok() ); REQUIRE( res.is_ok() );
} }