attaching schema nodes progress

This commit is contained in:
Sascha Kühl
2025-07-14 15:57:14 +02:00
parent 1b2847696d
commit 0d93b9b1ed
19 changed files with 182 additions and 91 deletions
@@ -25,6 +25,7 @@ public:
attribute_definition(attribute_definition&&) noexcept = default;
attribute_definition& operator=(attribute_definition&&) noexcept = default;
attribute_definition() = default;
template<typename Type>
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>::type(attr.size()), attr)
@@ -61,8 +62,10 @@ public:
void name(const std::string& n);
[[nodiscard]] std::string full_name() const;
[[nodiscard]] std::string table_name() const;
void table_name(const std::string& tn);
[[nodiscard]] int index() const;
[[nodiscard]] const utils::field_attributes& attributes() const;
[[nodiscard]] utils::field_attributes& attributes();
[[nodiscard]] bool is_nullable() const;
[[nodiscard]] utils::basic_type type() const;
[[nodiscard]] std::shared_ptr<attribute_definition> reference_column() const;
@@ -141,7 +144,7 @@ private:
* @param type
* @param attr Length of the column name
* @param null_opt
* @return A column object with given name
* @return A column object with a given name
*/
attribute_definition make_column(const std::string &name, utils::basic_type type, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL);
@@ -1,13 +1,13 @@
#ifndef QUERY_COLUMN_DEFINITION_GENERATOR_HPP
#define QUERY_COLUMN_DEFINITION_GENERATOR_HPP
#include "attribute_definition.hpp"
#include "matador/object/attribute_definition.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/foreign_attributes.hpp"
#include <memory>
#include <typeindex>
@@ -54,13 +54,13 @@ private:
class attribute_definition_generator final {
private:
attribute_definition_generator(std::vector<attribute_definition> &columns, const schema &repo);
attribute_definition_generator(std::vector<attribute_definition> &columns, schema &repo);
public:
~attribute_definition_generator() = default;
template < class Type >
static std::vector<attribute_definition> generate(const schema &repo)
static std::vector<attribute_definition> generate(schema &repo)
{
std::vector<attribute_definition> columns;
attribute_definition_generator gen(columns, repo);
@@ -69,6 +69,14 @@ public:
return columns;
}
template < class Type >
static std::vector<attribute_definition> generate(const Type& obj, schema &repo) {
std::vector<attribute_definition> columns;
attribute_definition_generator gen(columns, repo);
access::process(gen, obj);
return columns;
}
template < class V >
void on_primary_key(const char *, V &x, std::enable_if_t<std::is_integral_v<V> && !std::is_same_v<bool, V>>* = nullptr);
void on_primary_key(const char *id, std::string &pk, size_t size);
@@ -91,13 +99,19 @@ public:
template <class Pointer>
void on_foreign_key(const char *id, Pointer &x) {
if (const auto result = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)))) {
if (x.empty()) {
typename Pointer::value_type temp_val;
columns_.push_back(fk_column_generator_.generate(id, temp_val, *result));
} else {
columns_.push_back(fk_column_generator_.generate(id, *x, *result));
}
std::shared_ptr<attribute_definition> ref_column;
std::type_index ti = typeid(typename Pointer::value_type);
if (const auto result = determine_foreign_ref(std::type_index(ti))) {
ref_column = *result;
} else {
ref_column = std::make_shared<attribute_definition>();
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, ref_column));
} else {
columns_.push_back(fk_column_generator_.generate(id, *x, ref_column));
}
}
template<class ContainerType>
@@ -109,11 +123,12 @@ public:
private:
[[nodiscard]] utils::result<std::shared_ptr<attribute_definition>, utils::error> determine_foreign_ref(const std::type_index &ti) const;
void insert_missing_reference_column(const std::type_index &ti, std::shared_ptr<attribute_definition> ref_column) const;
private:
size_t index_ = 0;
std::vector<attribute_definition> &columns_;
const schema &repo_;
schema &repo_;
fk_attribute_generator fk_column_generator_;
};
+2 -3
View File
@@ -49,13 +49,12 @@ public:
[[nodiscard]] bool endpoints_empty() const;
protected:
basic_object_info(std::shared_ptr<schema_node> node, std::type_index type_index, utils::identifier &&pk, std::shared_ptr<attribute_definition> &&pk_column, object_definition &&definition);
basic_object_info(std::shared_ptr<schema_node> node, std::type_index type_index, utils::identifier &&pk, std::shared_ptr<attribute_definition> &&pk_column);
basic_object_info(std::shared_ptr<schema_node> node, std::type_index type_index, utils::identifier &&pk, const std::shared_ptr<attribute_definition> &pk_column, object_definition &&definition);
basic_object_info(std::shared_ptr<schema_node> node, std::type_index type_index, utils::identifier &&pk, const std::shared_ptr<attribute_definition> &pk_column);
basic_object_info(std::shared_ptr<schema_node> node, std::type_index type_index, object_definition &&definition);
protected:
std::shared_ptr<schema_node> node_; /**< prototype node of the represented object type */
std::type_index type_index_; /**< type index of the represented object type */
object_definition definition_;
std::optional<utils::identifier> identifier_;
std::shared_ptr<attribute_definition> pk_column_;
+6 -6
View File
@@ -13,23 +13,23 @@ public:
using create_func = std::function<std::unique_ptr<Type>()>;
object_info(const std::shared_ptr<schema_node>& node,
std::shared_ptr<attribute_definition> &&ref_column)
: basic_object_info(node, typeid(Type), {}, std::move(ref_column), {})
const std::shared_ptr<attribute_definition> &ref_column)
: basic_object_info(node, typeid(Type), {}, ref_column, {})
, creator_([]{return std::make_unique<Type>(); }){
}
object_info(const std::shared_ptr<schema_node>& node,
utils::identifier &&pk,
std::shared_ptr<attribute_definition> &&ref_column,
const std::shared_ptr<attribute_definition> &ref_column,
object_definition &&definition)
: basic_object_info(node, typeid(Type), std::move(pk), std::move(ref_column), std::move(definition))
: basic_object_info(node, typeid(Type), std::move(pk), ref_column, std::move(definition))
, creator_([]{return std::make_unique<Type>(); }){
}
object_info(const std::shared_ptr<schema_node>& node,
utils::identifier &&pk,
std::shared_ptr<attribute_definition> &&ref_column,
const std::shared_ptr<attribute_definition> &ref_column,
object_definition &&definition,
create_func&& creator)
: basic_object_info(node, typeid(Type), std::move(pk), std::move(ref_column), std::move(definition))
: basic_object_info(node, typeid(Type), std::move(pk), ref_column, std::move(definition))
, creator_(std::move(creator)){
}
object_info(const std::shared_ptr<schema_node>& node,
+12 -14
View File
@@ -129,17 +129,16 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
if (const auto endpoint = nodes_.top()->info().find_relation_endpoint(typeid(relation_value_type)); endpoint == nodes_.top()->info().endpoint_end()) {
// Endpoint was not found
log_.debug("node '%s' has has many foreign keys '%s' mapped by '%s'", nodes_.top()->name().c_str(), id, join_column);
const auto node = schema_node::make_relation_node<relation_value_type>(
result = schema_node::make_relation_node<relation_value_type>(
schema_.schema(), id, [join_column] {
return std::make_unique<relation_value_type>(join_column, "id");
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::HAS_MANY, nodes_.top());
const auto foreign_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, node);
const auto foreign_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, result.value());
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
foreign_endpoint->node_->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
link_relation_endpoints(local_endpoint, foreign_endpoint);
@@ -171,18 +170,17 @@ 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 node = schema_node::make_relation_node<relation_value_type>(
const auto result = schema_node::make_relation_node<relation_value_type>(
schema_.schema(), 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
}
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HAS_MANY, nodes_.top());
const auto foreign_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, node);
const auto foreign_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, result.value());
nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint);
foreign_endpoint->node_->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
link_relation_endpoints(local_endpoint, foreign_endpoint);
@@ -210,13 +208,18 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
}
link_relation_endpoints(local_endpoint, it->second);
} else {
// Relation not not found.
// Relation not found.
auto creator = [join_column, inverse_join_column] {
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
};
auto node = schema_node::make_relation_node<relation_value_type>(schema_.schema(), id, std::move(creator));
result = schema_node::make_relation_node<relation_value_type>(schema_.schema(), id, std::move(creator));
if (!result) {
// Todo: throw internal error
return;
}
auto& node = result.value();
auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HAS_MANY, nodes_.top());
auto join_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, node);
auto inverse_join_endpoint = std::make_shared<relation_endpoint>(inverse_join_column, relation_type::BELONGS_TO,
@@ -226,11 +229,6 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
link_relation_endpoints(local_endpoint, join_endpoint);
node->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type),
inverse_join_endpoint);
result = schema_.attach_node(node);
if (!result) {
// Todo: throw internal error
return;
}
}
}
+7 -4
View File
@@ -40,11 +40,11 @@ public:
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, const std::string &parent = "") {
if (const auto it = nodes_by_type_.find(typeid(Type)); it == nodes_by_type_.end() ) {
auto node = schema_node::make_node<Type>(*this, name);
foreign_node_completer::complete<Type>(node);
relation_completer<Type>::complete(node);
if (auto result = attach_node(node, parent); !result) {
return utils::failure(result.err());
}
foreign_node_completer::complete<Type>(node);
relation_completer<Type>::complete(node);
} else if (!has_node(name)) {
it->second->update_name(name);
nodes_by_name_[name] = it->second;
@@ -142,7 +142,7 @@ public:
return utils::ok(basic_object_info_ref{result.value()->info()});
}
[[nodiscard]] utils::result<std::shared_ptr<attribute_definition>, utils::error> reference(
[[nodiscard]] utils::result<std::shared_ptr<attribute_definition>, utils::error> reference_column(
const std::type_index &type_index) const;
void dump(std::ostream &os) const;
@@ -169,7 +169,8 @@ private:
private:
friend class internal::shadow_schema;
friend class foreign_node_completer;
friend class schema_node;
friend class attribute_definition_generator;
std::string name_;
std::shared_ptr<schema_node> root_;
@@ -177,6 +178,8 @@ private:
t_node_map nodes_by_name_;
t_type_index_node_map nodes_by_type_;
logger::logger log_;
std::unordered_map<std::type_index, std::shared_ptr<attribute_definition> > missing_references_;
};
}
+22 -9
View File
@@ -18,14 +18,15 @@ public:
template < typename Type >
static std::shared_ptr<schema_node> make_node(object::schema& tree, const std::string& name) {
auto node = std::shared_ptr<schema_node>(new schema_node(tree, name));
auto node = std::shared_ptr<schema_node>(new schema_node(tree, name, typeid(Type)));
primary_key_resolver resolver;
auto pk_info = resolver.resolve<Type>();
auto ref_column = determine_reference_column(typeid(Type), name, pk_info, tree);
auto info = std::make_unique<object_info<Type>>(
node,
std::move(pk_info.pk),
std::make_shared<attribute_definition>(pk_info.pk_column_name, name, pk_info.type, utils::constraints::FOREIGN_KEY),
ref_column,
object_definition{attribute_definition_generator::generate<Type>(tree)},
[]{ return std::make_unique<Type>(); }
);
@@ -35,17 +36,21 @@ public:
}
template < typename Type, typename CreatorFunc >
static std::shared_ptr<schema_node> make_relation_node(object::schema& tree, const std::string& name, CreatorFunc &&creator) {
auto node = std::shared_ptr<schema_node>(new schema_node(tree, name));
static utils::result<node_ptr, utils::error> make_relation_node(object::schema& tree, const std::string& name, CreatorFunc &&creator) {
const auto result = make_and_attach_node(tree, name, typeid(Type));
if (!result) {
return result;
}
auto obj = creator();
auto info = std::make_unique<object_info<Type>>(
node,
object_definition{attribute_definition_generator::generate<Type>(tree)},
result.value(),
object_definition{attribute_definition_generator::generate(*obj, tree)},
std::move(creator)
);
node->info_ = std::move(info);
result.value()->info_ = std::move(info);
return node;
return result;
}
static std::shared_ptr<schema_node> make_null_node(schema& tree);
@@ -77,10 +82,17 @@ public:
private:
explicit schema_node(object::schema& tree);
schema_node(object::schema& tree, std::string name);
schema_node(object::schema& tree, const std::type_index& ti);
schema_node(object::schema& tree, std::string name, const std::type_index& ti);
void unlink();
static utils::result<node_ptr, utils::error> make_and_attach_node(object::schema& tree, const std::string& name, const std::type_index& ti);
static std::shared_ptr<attribute_definition> determine_reference_column(const std::type_index& ti,
const std::string& name,
const primary_key_info& pk_info,
object::schema& tree);
private:
friend class schema;
template<typename Type>
@@ -89,6 +101,7 @@ private:
friend class const_schema_node_iterator;
object::schema &schema_;
std::type_index type_index_;
std::unique_ptr<basic_object_info> info_;
std::shared_ptr<schema_node> parent_;
@@ -11,9 +11,9 @@ class const_schema_node_iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = schema_node;
using pointer = value_type*;
using reference = value_type&;
using value_type = std::shared_ptr<schema_node>;
using pointer = schema_node*;
using reference = value_type;
/**
* Creates an empty iterator
@@ -28,7 +28,7 @@ public:
*
* @param node The schema node of the object
*/
explicit const_schema_node_iterator(std::shared_ptr<value_type> node);
explicit const_schema_node_iterator(const value_type& node);
/**
* Copy from a given const_object_view_iterator.
@@ -109,7 +109,7 @@ public:
*
* @return The iterators underlying node.
*/
const reference operator*() const;
reference operator*() const;
/**
* Returns the pointer to the node.
@@ -123,7 +123,7 @@ private:
void decrement();
private:
std::shared_ptr<value_type> node_;
value_type node_;
};
}
+1 -1
View File
@@ -50,7 +50,7 @@ public:
friend bool operator<(const error &lhs, const error &rhs);
friend bool operator<(const error &lhs, const std::error_code &rhs);
// friend std::ostream& operator<<(std::ostream &out, const error &err);
friend std::ostream& operator<<(std::ostream &out, const error &err);
[[nodiscard]] std::string message() const;
[[nodiscard]] std::string category() const;