attaching schema nodes progress
This commit is contained in:
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user