added join_column_index and inverse_join_column_index to object and table classes

This commit is contained in:
Sascha Kühl 2026-06-01 06:57:38 +02:00
parent bd06034ebf
commit cea7b97f2b
16 changed files with 164 additions and 75 deletions

View File

@ -34,6 +34,7 @@ public:
[[nodiscard]] const std::string& name() const;
void name(const std::string& n);
[[nodiscard]] std::string full_name() const;
[[nodiscard]] size_t index() const;
[[nodiscard]] const utils::field_attributes& attributes() const;
[[nodiscard]] utils::field_attributes& attributes();
[[nodiscard]] bool is_nullable() const;
@ -68,6 +69,7 @@ private:
friend class object_generator;
std::string name_;
size_t index_{0};
std::weak_ptr<object> owner_;
utils::basic_type type_{utils::basic_type::Null};
utils::field_attributes options_{};

View File

@ -27,12 +27,12 @@ public:
[[nodiscard]] std::type_index type_index() const;
[[nodiscard]] std::string name() const;
[[nodiscard]] std::shared_ptr<class object> object() const;
[[nodiscard]] const std::list<attribute>& attributes() const;
[[nodiscard]] const std::list<class restriction>& constraints() const;
[[nodiscard]] const std::vector<attribute>& attributes() const;
[[nodiscard]] const std::vector<restriction>& constraints() const;
[[nodiscard]] bool has_primary_key() const;
[[nodiscard]] const utils::identifier& primary_key() const;
[[nodiscard]] attribute* primary_key_attribute() const;
[[nodiscard]] const attribute* primary_key_attribute() const;
void update_name(const std::string& name) const;

View File

@ -95,7 +95,7 @@ public:
return basic_info(std::type_index(typeid(Type)));
}
[[nodiscard]] utils::result<attribute*, utils::error> primary_key_attribute(const std::type_index &ti) const;
[[nodiscard]] utils::result<const attribute*, utils::error> primary_key_attribute(const std::type_index &ti) const;
void dump(std::ostream &os) const;
static void dump(std::ostream &os, const repository_node& node);

View File

@ -17,21 +17,25 @@ public:
static const attribute& create_attribute(std::string name, const std::shared_ptr<object>& obj);
[[nodiscard]] attribute* primary_key_attribute() const;
[[nodiscard]] const attribute* primary_key_attribute() const;
[[nodiscard]] const utils::identifier& primary_key() const;
[[nodiscard]] bool has_primary_key() const;
[[nodiscard]] bool is_relation_object() const;
[[nodiscard]] const attribute* join_attribute() const;
[[nodiscard]] const attribute* inverse_join_attribute() const;
[[nodiscard]] const std::string& name() const;
void update_name(const std::string& name);
[[nodiscard]] bool has_attributes() const;
[[nodiscard]] size_t attribute_count() const;
[[nodiscard]] const std::list<attribute>& attributes() const;
[[nodiscard]] const std::vector<attribute>& attributes() const;
[[nodiscard]] bool has_constraints() const;
[[nodiscard]] size_t constraint_count() const;
[[nodiscard]] const std::list<restriction>& constraints() const;
[[nodiscard]] const std::vector<restriction>& constraints() const;
friend std::ostream& operator<<(std::ostream& os, const object& obj);
@ -40,10 +44,13 @@ private:
friend class object_generator;
std::string name_;
attribute* pk_attribute_{nullptr};
int pk_column_index_{-1};
int join_column_index_{-1};
int inverse_join_column_index_{-1};
utils::identifier pk_identifier_;
std::list<attribute> attributes_;
std::list<restriction> constraints_;
std::vector<attribute> attributes_;
std::vector<restriction> constraints_;
};
}
#endif //MATADOR_OBJECT_HPP

View File

@ -58,7 +58,11 @@ public:
}
template < class Type >
static std::shared_ptr<object> generate(std::unique_ptr<Type>&& t, basic_repository &repo, const std::string &name) {
static std::shared_ptr<object> generate(std::unique_ptr<Type>&& t,
basic_repository &repo,
const std::string &name,
const std::string &join_column = "",
const std::string &inverse_join_column = "") {
const std::type_index ti(typeid(Type));
if (repo.has_object_for_type(ti)) {
auto obj = repo.object_for_type(ti);
@ -71,6 +75,9 @@ public:
std::ignore = repo.provide_object_in_advance(ti, obj);
object_generator gen(repo, obj);
access::process(gen, *t);
if (!join_column.empty() && !inverse_join_column.empty()) {
gen.prepare_relation_table(join_column, inverse_join_column);
}
return obj;
}
@ -111,6 +118,7 @@ private:
template<typename ValueType>
attribute &emplace_attribute(const char *id, const utils::field_attributes& attr, null_option_type null_option) {
auto &ref = object_->attributes_.emplace_back(id, utils::data_type_traits<ValueType>::type(attr.size()), attr, null_option);
ref.index_ = object_->attributes_.size() - 1;
ref.owner_ = object_;
return ref;
}
@ -120,9 +128,10 @@ private:
void create_fk_constraint(const std::string& name) const;
void create_unique_constraint(const std::string& name) const;
[[nodiscard]] std::list<attribute>::iterator find_attribute_by_name(const std::string &name) const;
[[nodiscard]] std::vector<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(const attribute &ref, utils::identifier &&pk) const;
void prepare_relation_table(const std::string &join_column, const std::string &inverse_join_column) const;
template<typename Type>
[[nodiscard]] std::shared_ptr<object> fk_object() const;
@ -135,7 +144,7 @@ private:
template<typename ValueType>
void object_generator::on_primary_key(const char *id, ValueType &x, const utils::primary_key_attribute& attr) {
utils::constraints cs = utils::constraints::PrimaryKey;
auto cs = utils::constraints::PrimaryKey;
if (attr.generator() == utils::generator_type::Identity) {
cs |= utils::constraints::Identity;
}

View File

@ -367,7 +367,12 @@ void relation_completer<Type, Observers...>::attach_relation_node(const std::str
auto observers = internal::observer_list_copy_creator<Type, relation_value_type, Observers...>::copy_create(observers_);
auto node = repository_node::make_node<relation_value_type>(repo_, name, std::move(creator), std::move(observers));
auto node = repository_node::make_relation_node<relation_value_type>(repo_,
name,
join_column,
inverse_join_column,
std::move(creator),
std::move(observers));
auto result = repo_.attach_node(node.release(), "");
if (!result) {
// Todo: throw internal error

View File

@ -23,6 +23,13 @@ public:
const std::string& name,
creator_func<Type> creator,
std::vector<std::unique_ptr<observer<Type>>>&& observers);
template < typename Type, template<typename> typename... Observers >
static std::unique_ptr<repository_node> make_relation_node(basic_repository& repo,
const std::string& name,
const std::string& join_column,
const std::string& inverse_join_column,
creator_func<Type> creator,
std::vector<std::unique_ptr<observer<Type>>>&& observers);
explicit repository_node(basic_repository& repo);
repository_node(const repository_node& other) = delete;
@ -101,5 +108,28 @@ std::unique_ptr<repository_node> repository_node::make_node(basic_repository &re
return node;
}
template<typename Type, template <typename> class ... Observers>
std::unique_ptr<repository_node> repository_node::make_relation_node(basic_repository &repo,
const std::string &name,
const std::string &join_column,
const std::string &inverse_join_column,
creator_func<Type> creator,
std::vector<std::unique_ptr<observer<Type>>> &&observers) {
const std::type_index ti(typeid(Type));
auto node = std::unique_ptr<repository_node>(new repository_node(repo, name, ti));
internal::observer_list_creator<Type, Observers...>::create_missing(observers);
auto obj = object_generator::generate<Type>(creator(), repo, name, join_column, inverse_join_column);
node->info_.reset(std::make_unique<object_info<Type>>(
*node,
obj,
std::move(observers),
std::forward<creator_func<Type>>(creator)
).release());
return node;
}
}
#endif //REPOSITORY_NODE_HPP

View File

@ -11,6 +11,8 @@
#include "matador/object/attribute.hpp"
#include "matador/object/restriction.hpp"
#include <list>
namespace matador::query {
class table;
class query_create_table_columns_intermediate : public executable_query {
@ -28,7 +30,7 @@ public:
using query_intermediate::query_intermediate;
query_create_table_columns_intermediate columns(std::initializer_list<object::attribute> attributes);
query_create_table_columns_intermediate columns(const std::list<object::attribute> &attributes);
query_create_table_columns_intermediate columns(const std::vector<object::attribute> &attributes);
query_create_table_columns_intermediate columns(std::initializer_list<table_column> columns);
query_create_table_columns_intermediate columns(const std::list<table_column> &columns);
query_create_table_columns_intermediate columns(const std::vector<table_column> &columns);

View File

@ -318,6 +318,7 @@ public:
private:
iterator insert_table(const std::type_index& ti, const object::repository_node &node, utils::generator_type generator_type);
iterator insert_relation_table(const std::type_index& ti, const object::repository_node &node);
private:
template<typename Type>
@ -364,17 +365,16 @@ utils::result<sql::query_context, utils::error> query_joined_object_resolver_pro
template <typename Type>
void schema_observer<Type>::on_attach(const object::repository_node &node, const Type &/*prototype*/) const {
const object::object_info<Type>& info = node.info<Type>().get();
if (info.has_primary_key()) {
primary_key_generator_finder finder;
const auto generator_type = finder.find(node.info<Type>().get());
const auto generator_type = finder.find(info);
const auto it = schema_.insert_table(typeid(Type), node, generator_type);
if (!it->second.node().info().has_primary_key()) {
return;
}
auto producer = std::make_unique<query_object_resolver_producer<Type>>(schema_, it->second.table(), it->second.node().info().primary_key_attribute()->name());
schema_.resolver_producers_[typeid(Type)] = std::move(producer);
} else {
object::join_columns_collector collector;
}
}
template <typename Type>

View File

@ -32,6 +32,10 @@ std::string attribute::full_name() const {
return owner ? owner->name() + "." + name_ : name_;
}
size_t attribute::index() const {
return index_;
}
const utils::field_attributes &attribute::attributes() const {
return options_;
}

View File

@ -21,11 +21,11 @@ std::shared_ptr<class object> basic_object_info::object() const {
return object_;
}
const std::list<attribute>& basic_object_info::attributes() const {
const std::vector<attribute>& basic_object_info::attributes() const {
return object_->attributes();
}
const std::list<class restriction>& basic_object_info::constraints() const {
const std::vector<class restriction>& basic_object_info::constraints() const {
return object_->constraints();
}
@ -37,7 +37,7 @@ const utils::identifier& basic_object_info::primary_key() const {
return object_->primary_key();
}
attribute* basic_object_info::primary_key_attribute() const {
const attribute* basic_object_info::primary_key_attribute() const {
return object_->primary_key_attribute();
}

View File

@ -88,7 +88,7 @@ utils::result<basic_object_info_ref, utils::error> basic_repository::basic_info(
return utils::ok(basic_object_info_ref{it->info()});
}
utils::result<attribute*, utils::error> basic_repository::primary_key_attribute(const std::type_index &ti) const {
utils::result<const attribute*, utils::error> basic_repository::primary_key_attribute(const std::type_index &ti) const {
const auto it = find_node(ti);
if (it == end()) {
return utils::failure(make_error(error_code::NodeNotFound, "Node '" + std::string(ti.name()) + "' not found."));

View File

@ -10,8 +10,8 @@ const attribute& object::create_attribute(std::string name, const std::shared_pt
return obj->attributes_.emplace_back(std::move(attr));
}
attribute* object::primary_key_attribute() const {
return pk_attribute_;
const attribute* object::primary_key_attribute() const {
return pk_column_index_ != -1 ? &attributes_.at(pk_column_index_) : nullptr;
}
const utils::identifier& object::primary_key() const {
@ -19,7 +19,19 @@ const utils::identifier& object::primary_key() const {
}
bool object::has_primary_key() const {
return pk_attribute_ != nullptr;
return pk_column_index_ != -1;
}
bool object::is_relation_object() const {
return join_column_index_ != -1 && inverse_join_column_index_ != -1;
}
const attribute * object::join_attribute() const {
return join_column_index_ != -1 ? &attributes_.at(join_column_index_) : nullptr;
}
const attribute * object::inverse_join_attribute() const {
return inverse_join_column_index_ != -1 ? &attributes_.at(inverse_join_column_index_) : nullptr;
}
const std::string& object::name() const {
@ -38,7 +50,7 @@ size_t object::attribute_count() const {
return attributes_.size();
}
const std::list<attribute>& object::attributes() const {
const std::vector<attribute>& object::attributes() const {
return attributes_;
}
@ -50,7 +62,7 @@ size_t object::constraint_count() const {
return constraints_.size();
}
const std::list<restriction>& object::constraints() const {
const std::vector<restriction>& object::constraints() const {
return constraints_;
}

View File

@ -5,11 +5,12 @@
#include <algorithm>
namespace matador::object {
object_generator::object_generator(basic_repository& repo, const std::shared_ptr<object>& object)
object_generator::object_generator(basic_repository &repo, const std::shared_ptr<object> &object)
: repo_(repo)
, object_(object) {}
, object_(object) {
}
std::shared_ptr<object> object_generator::acquire_object(basic_repository &repo, const std::type_index &ti, const std::string& name) {
std::shared_ptr<object> object_generator::acquire_object(basic_repository &repo, const std::type_index &ti, const std::string &name) {
if (repo.has_object_for_type(ti)) {
auto obj = repo.object_for_type(ti);
repo.remove_object_for_type(ti);
@ -20,11 +21,11 @@ std::shared_ptr<object> object_generator::acquire_object(basic_repository &repo,
return repo.provide_object_in_advance(ti, std::make_shared<object>(name));
}
void object_generator::on_revision(const char* id, uint64_t& rev) {
void object_generator::on_revision(const char *id, uint64_t &rev) {
access::attribute(*this, id, rev);
}
void object_generator::create_pk_constraint(const std::string& name) const {
void object_generator::create_pk_constraint(const std::string &name) const {
const auto pk_attr = find_attribute_by_name(name);
if (pk_attr == std::end(object_->attributes_)) {
return;
@ -35,7 +36,7 @@ void object_generator::create_pk_constraint(const std::string& name) const {
object_->constraints_.emplace_back(std::move(pk_constraint));
}
void object_generator::create_unique_constraint(const std::string& name) const {
void object_generator::create_unique_constraint(const std::string &name) const {
const auto pk_attr = find_attribute_by_name(name);
if (pk_attr == std::end(object_->attributes_)) {
return;
@ -45,14 +46,28 @@ void object_generator::create_unique_constraint(const std::string& name) const {
pk_constraint.owner_ = object_;
}
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) {
std::vector<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 elem.name() == name;
});
}
void object_generator::prepare_primary_key(attribute& ref, utils::identifier &&pk) const {
object_->pk_attribute_ = &ref;
void object_generator::prepare_primary_key(const attribute &ref, utils::identifier &&pk) const {
object_->pk_column_index_ = static_cast<int>(ref.index_);
object_->pk_identifier_ = std::move(pk);
}
void object_generator::prepare_relation_table(const std::string &join_column, const std::string &inverse_join_column) const {
auto it = find_attribute_by_name(join_column);
if (it == std::end(object_->attributes_)) {
return;
}
object_->join_column_index_ = static_cast<int>(it->index_);
it = find_attribute_by_name(inverse_join_column);
if (it == std::end(object_->attributes_)) {
return;
}
object_->inverse_join_column_index_ = static_cast<int>(it->index_);
}
}

View File

@ -58,10 +58,10 @@ executable_query query_create_table_columns_intermediate::constraints(const std:
}
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::initializer_list<object::attribute> attributes) {
return columns(std::list(attributes));
return columns(std::vector(attributes));
}
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::list<object::attribute>& attributes) {
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::vector<object::attribute>& attributes) {
std::list<table_column> columns;
for (const auto& attr : attributes) {
auto options = attr.attributes().options();

View File

@ -59,4 +59,7 @@ schema::iterator schema::insert_table(const std::type_index &ti, const object::r
}
return schema_nodes_.insert({ti, schema_node{table(node.name(), columns), std::move(pk_generator), node}}).first;
}
basic_schema::iterator schema::insert_relation_table(const std::type_index &ti, const object::repository_node &node) {
}
} // namespace matador::query