schema node analyze progress

This commit is contained in:
Sascha Kühl
2025-02-11 16:34:06 +01:00
parent a631a5a36c
commit 1d83abcb1b
18 changed files with 174 additions and 96 deletions
@@ -59,6 +59,7 @@ public:
attribute_definition(std::string name, utils::basic_type type, size_t index, const std::shared_ptr<attribute_definition> &ref_column, const utils::field_attributes& attr, null_option null_opt);
[[nodiscard]] const std::string& name() const;
void name(const std::string& n);
[[nodiscard]] std::string full_name() const;
[[nodiscard]] std::string table_name() const;
[[nodiscard]] int index() const;
@@ -5,6 +5,7 @@
#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"
@@ -21,15 +22,13 @@ public:
fk_attribute_generator() = default;
template<class Type>
attribute_definition generate(const char *id, Type &x, const std::shared_ptr<attribute_definition> &ref_column)
{
attribute_definition generate(const char *id, Type &x, const std::shared_ptr<attribute_definition> &ref_column) {
access::process(*this, x);
return attribute_definition{id, type_, 0, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
}
template<typename ValueType>
void on_primary_key(const char *, ValueType &/*pk*/, std::enable_if_t<std::is_integral_v<ValueType> && !std::is_same_v<bool, ValueType>>* = nullptr)
{
void on_primary_key(const char *, ValueType &/*pk*/, std::enable_if_t<std::is_integral_v<ValueType> && !std::is_same_v<bool, ValueType>>* = nullptr) {
type_ = utils::data_type_traits<ValueType>::type(0);
}
void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t size);
@@ -81,16 +80,16 @@ public:
void on_attribute(const char *id, std::optional<Type> &x, const utils::field_attributes &attr = utils::null_attributes);
template<class Pointer>
void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/)
{
const auto ref_column = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)));
columns_.push_back(fk_column_generator_.generate(id, *x, ref_column));
void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) {
if (const auto result = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)))) {
columns_.push_back(fk_column_generator_.generate(id, *x, *result));
}
}
template<class Pointer>
void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/)
{
const auto ref_column = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)));
columns_.push_back(fk_column_generator_.generate(id, *x, ref_column));
void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) {
if (const auto result = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)))) {
columns_.push_back(fk_column_generator_.generate(id, *x, *result));
}
}
template<class ContainerType>
void on_has_many(const char *id, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
@@ -100,7 +99,7 @@ public:
void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {}
private:
std::shared_ptr<attribute_definition> determine_foreign_ref(const std::type_index &ti);
[[nodiscard]] utils::result<std::shared_ptr<attribute_definition>, utils::error> determine_foreign_ref(const std::type_index &ti) const;
private:
size_t index_ = 0;
+5 -3
View File
@@ -2,6 +2,7 @@
#define BASIC_PROTOTYPE_INFO_HPP
#include "matador/object/object_definition.hpp"
#include "matador/utils/identifier.hpp"
#include <string>
#include <typeindex>
@@ -20,14 +21,15 @@ public:
[[nodiscard]] std::shared_ptr<attribute_definition> reference_column() const;
protected:
basic_object_info(std::type_index type_index, object_definition &&definition, std::shared_ptr<attribute_definition> &&reference_column);
basic_object_info(std::type_index type_index, std::shared_ptr<attribute_definition> &&reference_column);
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);
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::shared_ptr<attribute_definition> reference_column_;
std::optional<utils::identifier> identifier_;
std::shared_ptr<attribute_definition> pk_column_;
};
using basic_object_info_ref = std::reference_wrapper<const basic_object_info>;
+7 -5
View File
@@ -10,13 +10,15 @@ class schema_node;
template<typename Type>
class object_info final : public basic_object_info {
public:
explicit object_info(object_definition &&definition,
explicit object_info(const std::shared_ptr<schema_node>& node,
std::shared_ptr<attribute_definition> &&ref_column)
: basic_object_info(typeid(Type), std::move(definition), std::move(ref_column)) {
: basic_object_info(node, typeid(Type), {}, std::move(ref_column), {}) {
}
explicit object_info(schema_node &node,
std::shared_ptr<attribute_definition> &&ref_column)
: basic_object_info(typeid(Type), std::move(ref_column)) {
explicit object_info(const std::shared_ptr<schema_node>& node,
utils::identifier &&pk,
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)) {
}
const Type &prototype() const { return prototype_; }
@@ -14,7 +14,8 @@
namespace matador::object {
struct primary_key_info {
std::string column_name;
std::string pk_column_name;
utils::basic_type type;
utils::identifier pk;
};
@@ -36,25 +37,26 @@ public:
template < class Type >
void on_primary_key(const char *id, Type &pk, std::enable_if_t<std::is_integral_v<Type> && !std::is_same_v<bool, Type>>* = nullptr) {
primary_key_info_.column_name = id;
primary_key_info_.pk_column_name = id;
primary_key_info_.type = utils::data_type_traits<Type>::type();
primary_key_info_.pk = pk;
}
void on_primary_key(const char *id, const std::string &pk, size_t size);
void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
template<typename Type>
void on_attribute(const char * /*id*/, Type &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
static void on_attribute(const char * /*id*/, Type &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
template<class Pointer>
void on_belongs_to(const char * /*id*/, Pointer &/*val*/, const utils::foreign_attributes &/*attr*/) {}
static void on_belongs_to(const char * /*id*/, Pointer &/*val*/, const utils::foreign_attributes &/*attr*/) {}
template<class Pointer>
void on_has_one(const char * /*id*/, Pointer &/*val*/, const utils::foreign_attributes &/*attr*/) {}
static void on_has_one(const char * /*id*/, Pointer &/*val*/, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
void on_has_many(const char * /*id*/, ContainerType &/*col*/, const char *, const utils::foreign_attributes &/*attr*/) {}
static void on_has_many(const char * /*id*/, ContainerType &/*col*/, const char *, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
void on_has_many_to_many(const char * /*id*/, ContainerType &/*col*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
static void on_has_many_to_many(const char * /*id*/, ContainerType &/*col*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
void on_has_many_to_many(const char * /*id*/, ContainerType &/*col*/, const utils::foreign_attributes &/*attr*/) {}
static void on_has_many_to_many(const char * /*id*/, ContainerType &/*col*/, const utils::foreign_attributes &/*attr*/) {}
private:
primary_key_info primary_key_info_{};
+28 -24
View File
@@ -1,6 +1,7 @@
#ifndef SCHEMA_HPP
#define SCHEMA_HPP
#include "primary_key_resolver.hpp"
#include "matador/object/error_code.hpp"
#include "matador/object/schema_node.hpp"
#include "matador/object/schema_node_iterator.hpp"
@@ -24,14 +25,11 @@ class type_analyzer final {
public:
using value_type = Type;
static void analyze(schema &scm) {
static void prepare_expected_nodes(schema &scm) {
type_analyzer analyzer(scm);
Type obj;
const auto ti = std::type_index(typeid(Type));
analyzer.known_types_.emplace(ti);
access::process(analyzer, obj);
analyzer.known_types_.erase(ti);
}
template < class PrimaryKeyType >
@@ -47,12 +45,12 @@ public:
template<class ForeignPointerType>
void on_belongs_to(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) {
// const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)));
// columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column));
on_foreign_key<ForeignPointerType>();
}
template<class ForeignPointerType>
void on_has_one(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/);
void on_has_one(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) {
on_foreign_key<ForeignPointerType>();
}
template<class CollectionType>
void on_has_many(const char * /*id*/, CollectionType &, const char *, const utils::foreign_attributes &/*attr*/) {}
@@ -61,6 +59,10 @@ public:
template<class ContainerType>
void on_has_many_to_many(const char * /*id*/, ContainerType &/*col*/, const utils::foreign_attributes &/*attr*/) {}
private:
template<class ForeignPointerType>
void on_foreign_key();
private:
explicit type_analyzer(schema& schema)
: schema_(schema) {};
@@ -68,7 +70,6 @@ private:
private:
schema &schema_;
std::unordered_set<std::type_index> known_types_;
};
@@ -79,23 +80,30 @@ public:
/**
* Creates an empty schema
*/
explicit schema( const std::string& name = "");
explicit schema( std::string name = "");
template <typename Type>
[[nodiscard]] utils::result<void, utils::error> attach(const std::string& name, const std::string &parent = "") {
if (has_node(name)) {
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + name + "' already exists"));
}
if (const auto it = expected_node_map_.find(typeid(Type)); it != expected_node_map_.end()) {
const auto node = it->second;
expected_node_map_.erase(it);
// analyze node (collect unknown types by type index)
type_analyzer<Type>::analyze(*this);
node->update_name(name);
const auto node = schema_node::make_node(*this, name, {});
node_map_.insert({node->name(), node})/*.first*/;
type_index_node_map_.insert({node->type_index(), node});
} else {
// analyze node (collect unknown types by type index)
type_analyzer<Type>::prepare_expected_nodes(*this);
if (auto result = attach_node(node, parent); !result) {
return utils::failure(result.err());
const auto node = schema_node::make_node<Type>(*this, name);
if (auto result = attach_node(node, parent); !result) {
return utils::failure(result.err());
}
}
return utils::ok<void>();
}
@@ -195,22 +203,18 @@ private:
t_node_map node_map_;
t_type_index_node_map type_index_node_map_;
t_type_index_node_map expected_node_map_;
};
template<typename Type>
template<class ForeignPointerType>
void type_analyzer<Type>::on_has_one(const char *, ForeignPointerType &, const utils::foreign_attributes &) {
void type_analyzer<Type>::on_foreign_key() {
auto ti = std::type_index(typeid(typename ForeignPointerType::value_type));
if (schema_.has_node(ti)) {
if (schema_.has_node(ti) || schema_.expected_node_map_.count(ti) > 0) {
return;
}
auto info = std::make_unique<object_info<typename ForeignPointerType::value_type>>(object_definition{}, std::make_unique<attribute_definition>(std::string(""), std::string(ti.name()), utils::basic_type::type_null, utils::constraints::FOREIGN_KEY));
known_types_.insert(ti);
// const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)));
// columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column));
schema_.expected_node_map_.insert({ti, schema_node::make_node<typename ForeignPointerType::value_type>(schema_, ti.name())});
}
}
+23 -2
View File
@@ -3,6 +3,7 @@
#include "matador/object/attribute_definition_generator.hpp"
#include "matador/object/object_info.hpp"
#include "matador/object/primary_key_resolver.hpp"
#include <memory>
@@ -15,7 +16,24 @@ class schema_node final {
public:
using node_ptr = std::shared_ptr<schema_node>;
static std::shared_ptr<schema_node> make_node(schema& tree, const std::string& name, std::unique_ptr<basic_object_info> &&info);
template < typename Type >
static std::shared_ptr<schema_node> make_node(schema& tree, const std::string& name) {
auto node = std::shared_ptr<schema_node>(new schema_node(tree, name));
primary_key_resolver resolver;
auto pk_info = resolver.resolve<Type>();
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),
object_definition{attribute_definition_generator::generate<Type>(tree)}
);
node->info_ = std::move(info);
return node;
}
static std::shared_ptr<schema_node> make_null_node(schema& tree);
schema_node(const schema_node& other) = delete;
schema_node(schema_node&& other) = default;
@@ -31,14 +49,17 @@ public:
[[nodiscard]] const basic_object_info& basic_info() const;
void update_name(const std::string& name);
template <typename Type>
object_info_ref<Type> info() const {
auto ref = std::ref(static_cast<const object_info<Type>&>(*info_));
return std::ref(static_cast<const object_info<Type>&>(*info_));
}
private:
explicit schema_node(schema& tree);
schema_node(schema& tree, std::string name, std::unique_ptr<basic_object_info> &&info);
schema_node(schema& tree, std::string name);
private:
friend class schema;
+3 -6
View File
@@ -41,22 +41,19 @@ public:
}
template < class V >
void on_primary_key(const char *id, V &, std::enable_if_t<std::is_integral_v<V> && !std::is_same_v<bool, V>>* = nullptr)
{
void on_primary_key(const char *id, V &, std::enable_if_t<std::is_integral_v<V> && !std::is_same_v<bool, V>>* = nullptr) {
push(id);
}
void on_primary_key(const char *id, std::string &, size_t);
void on_revision(const char *id, unsigned long long &/*rev*/);
template<typename Type>
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes)
{
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {
push(id);
}
template<class Pointer>
void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &attr)
{
void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &attr) {
if (attr.fetch() == utils::fetch_type::LAZY || force_lazy_) {
push(id);
} else {