reference column progress
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#ifndef QUERY_COLUMN_DEFINITION_HPP
|
||||
#define QUERY_COLUMN_DEFINITION_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "matador/utils/basic_type_converter.hpp"
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
@@ -43,11 +45,11 @@ public:
|
||||
attribute_definition(std::string name, utils::basic_type type, const utils::field_attributes&, null_option null_opt, size_t index = 0);
|
||||
|
||||
template<typename Type>
|
||||
attribute_definition(std::string name, std::string ref_table, std::string ref_column, const utils::field_attributes& attr, null_option null_opt)
|
||||
: attribute_definition(std::move(name), utils::data_type_traits<Type>::type(attr.size()), ref_table, ref_column, attr, null_opt)
|
||||
attribute_definition(std::string name, const std::shared_ptr<attribute_definition> &ref_column, const utils::field_attributes& attr, null_option null_opt)
|
||||
: attribute_definition(std::move(name), utils::data_type_traits<Type>::type(attr.size()), ref_column, attr, null_opt)
|
||||
{}
|
||||
|
||||
attribute_definition(std::string name, utils::basic_type type, size_t index, std::string ref_table, std::string ref_column, const utils::field_attributes& attr, null_option null_opt);
|
||||
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;
|
||||
[[nodiscard]] std::string full_name() const;
|
||||
@@ -56,8 +58,7 @@ public:
|
||||
[[nodiscard]] const utils::field_attributes& attributes() const;
|
||||
[[nodiscard]] bool is_nullable() const;
|
||||
[[nodiscard]] utils::basic_type type() const;
|
||||
[[nodiscard]] const std::string& ref_table() const;
|
||||
[[nodiscard]] const std::string& ref_column() const;
|
||||
[[nodiscard]] std::shared_ptr<attribute_definition> reference_column() const;
|
||||
[[nodiscard]] bool is_foreign_reference() const;
|
||||
|
||||
[[nodiscard]] bool is_integer() const;
|
||||
@@ -124,8 +125,9 @@ private:
|
||||
utils::field_attributes attributes_;
|
||||
null_option null_option_{null_option::NOT_NULL};
|
||||
utils::value value_;
|
||||
std::string ref_table_;
|
||||
std::string ref_column_;
|
||||
std::shared_ptr<attribute_definition> reference_column_;
|
||||
// std::string ref_table_;
|
||||
// std::string ref_column_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -156,19 +158,20 @@ template <>
|
||||
attribute_definition make_pk_column<std::string>(const std::string &name, size_t size);
|
||||
|
||||
template < typename Type >
|
||||
attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column)
|
||||
attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr<attribute_definition> &ref_column)
|
||||
{
|
||||
return {name, utils::data_type_traits<Type>::type(size), ref_table, ref_column, { size, utils::constraints::FOREIGN_KEY }};
|
||||
return {name, utils::data_type_traits<Type>::type(size), ref_column, { size, utils::constraints::FOREIGN_KEY }};
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, const std::string &ref_table, const std::string &ref_column)
|
||||
[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, const std::shared_ptr<attribute_definition> &ref_column)
|
||||
{
|
||||
return {name, utils::data_type_traits<Type>::type(0), 0, ref_table, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
|
||||
return {name, utils::data_type_traits<Type>::type(0), 0, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
|
||||
}
|
||||
|
||||
template <>
|
||||
attribute_definition make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column);
|
||||
attribute_definition make_fk_column<std::string>(const std::string &name, size_t size, const std::shared_ptr<attribute_definition> &ref_column);
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_COLUMN_DEFINITION_HPP
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
template<class Pointer>
|
||||
void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/)
|
||||
{
|
||||
const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type)));
|
||||
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_table, ref_column));
|
||||
}
|
||||
template<class Pointer>
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {}
|
||||
|
||||
private:
|
||||
std::pair<std::string, std::string> determine_foreign_ref(const std::type_index &ti);
|
||||
std::shared_ptr<attribute_definition> determine_foreign_ref(const std::type_index &ti);
|
||||
|
||||
private:
|
||||
size_t index_ = 0;
|
||||
|
||||
@@ -17,14 +17,16 @@ public:
|
||||
[[nodiscard]] std::type_index type_index() const;
|
||||
[[nodiscard]] std::string name() const;
|
||||
[[nodiscard]] const object_definition& definition() const;
|
||||
[[nodiscard]] std::shared_ptr<attribute_definition> reference_column() const;
|
||||
|
||||
protected:
|
||||
basic_object_info(schema_node &node, std::type_index type_index, object_definition &&definition);
|
||||
basic_object_info(schema_node &node, std::type_index type_index, object_definition &&definition, std::shared_ptr<attribute_definition> &&reference_column);
|
||||
|
||||
protected:
|
||||
schema_node &node_; /**< prototype node of the represented object type */
|
||||
std::type_index type_index_; /**< type index of the represented object type */
|
||||
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_;
|
||||
};
|
||||
|
||||
using basic_object_info_ref = std::reference_wrapper<const basic_object_info>;
|
||||
|
||||
@@ -5,30 +5,31 @@
|
||||
#include "matador/object/object_definition.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
class schema_node;
|
||||
|
||||
template<typename Type>
|
||||
class object_info final : public basic_object_info {
|
||||
public:
|
||||
explicit object_info(schema_node &node, object_definition &&definition)
|
||||
: basic_object_info(node, typeid(Type), std::move(definition)) {}
|
||||
explicit object_info(schema_node &node, object_definition &&definition,
|
||||
std::shared_ptr<attribute_definition> &&ref_column)
|
||||
: basic_object_info(node, typeid(Type), std::move(definition), std::move(ref_column)) {
|
||||
}
|
||||
|
||||
const Type &prototype() const { return prototype_; }
|
||||
const Type &prototype() const { return prototype_; }
|
||||
|
||||
private:
|
||||
Type prototype_;
|
||||
Type prototype_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
using object_info_ref = std::reference_wrapper<const object_info<Type>>;
|
||||
|
||||
namespace detail {
|
||||
struct null_type {};
|
||||
struct null_type {
|
||||
};
|
||||
}
|
||||
|
||||
using null_info = object_info<detail::null_type>;
|
||||
|
||||
}
|
||||
|
||||
#endif //OBJECT_INFO_HPP
|
||||
|
||||
@@ -9,11 +9,69 @@
|
||||
#include "matador/utils/error.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
utils::error make_error(error_code ec, const std::string& msg);
|
||||
|
||||
class schema;
|
||||
|
||||
template<typename Type>
|
||||
class type_analyzer final {
|
||||
public:
|
||||
using value_type = Type;
|
||||
|
||||
static void analyze(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 >
|
||||
void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, std::enable_if_t<std::is_integral_v<PrimaryKeyType> && !std::is_same_v<bool, PrimaryKeyType>>* = nullptr) {}
|
||||
void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t /*size*/) {}
|
||||
void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||
|
||||
template<typename AttributeType>
|
||||
void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
|
||||
template<typename AttributeType>
|
||||
void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
template<class ForeignPointerType>
|
||||
void on_has_one(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/);
|
||||
|
||||
template<class CollectionType>
|
||||
void on_has_many(const char * /*id*/, CollectionType &, const char *, const utils::foreign_attributes &/*attr*/) {}
|
||||
template<class CollectionType>
|
||||
void on_has_many_to_many(const char * /*id*/, CollectionType &/*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*/) {}
|
||||
|
||||
private:
|
||||
explicit type_analyzer(schema& schema)
|
||||
: schema_(schema) {};
|
||||
|
||||
|
||||
private:
|
||||
schema &schema_;
|
||||
std::unordered_set<std::type_index> known_types_;
|
||||
};
|
||||
|
||||
|
||||
class schema {
|
||||
public:
|
||||
typedef const_schema_node_iterator const_iterator; /**< Shortcut for the list const iterator. */
|
||||
@@ -24,7 +82,14 @@ public:
|
||||
explicit schema( const std::string& name = "");
|
||||
|
||||
template <typename Type>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string name, const std::string &parent = "") {
|
||||
[[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"));
|
||||
}
|
||||
|
||||
// analyze node (collect unknown types by type index)
|
||||
type_analyzer<Type>::analyze(*this);
|
||||
|
||||
auto node = schema_node::make_node<Type>(*this, name);
|
||||
|
||||
auto result = attach_node(node, parent);
|
||||
@@ -37,14 +102,13 @@ public:
|
||||
|
||||
template <typename Type, typename ParentType>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string name) {
|
||||
auto node = schema_node::make_node<Type>(*this, name);
|
||||
|
||||
auto result = attach_node(node, std::type_index(typeid(ParentType)));
|
||||
const auto ti = std::type_index(typeid(ParentType));
|
||||
auto result = find_node(ti);
|
||||
if (!result) {
|
||||
return utils::failure(result.err());
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Parent node '" + std::string(ti.name()) + "' not found"));
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
return attach<Type>(name, (*result)->name());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +167,7 @@ public:
|
||||
return utils::ok(basic_object_info_ref{result.value()->basic_info()});
|
||||
}
|
||||
|
||||
[[nodiscard]] utils::result<std::pair<std::string, std::string>, utils::error> reference(const std::type_index &type_index) const;
|
||||
[[nodiscard]] utils::result<std::shared_ptr<attribute_definition>, utils::error> reference(const std::type_index &type_index) const;
|
||||
|
||||
private:
|
||||
using node_ptr = std::shared_ptr<schema_node>;
|
||||
@@ -117,11 +181,16 @@ private:
|
||||
[[nodiscard]] utils::result<std::shared_ptr<schema_node>, utils::error> find_node(const std::string &name) const;
|
||||
[[nodiscard]] utils::result<std::shared_ptr<schema_node>, utils::error> find_node(const std::type_index &type_index) const;
|
||||
|
||||
[[nodiscard]] bool has_node(const std::string &name) const;
|
||||
[[nodiscard]] bool has_node(const std::type_index& index) const;
|
||||
[[nodiscard]] bool has_node(const std::type_index& index, const std::string &name) const;
|
||||
|
||||
static void push_back_child(const node_ptr &parent, const node_ptr &child);
|
||||
|
||||
private:
|
||||
template <typename Type>
|
||||
friend class type_analyzer;
|
||||
|
||||
std::string name_;
|
||||
std::shared_ptr<schema_node> root_;
|
||||
|
||||
@@ -129,6 +198,22 @@ private:
|
||||
t_type_index_node_map type_index_node_map_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
template<class ForeignPointerType>
|
||||
void type_analyzer<Type>::on_has_one(const char *, ForeignPointerType &, const utils::foreign_attributes &) {
|
||||
auto ti = std::type_index(typeid(typename ForeignPointerType::value_type));
|
||||
if (schema_.has_node(ti)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto info = std::make_unique<object_info<typename ForeignPointerType::value_type>>();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //SCHEMA_HPP
|
||||
|
||||
@@ -15,10 +15,7 @@ class schema_node final {
|
||||
public:
|
||||
using node_ptr = std::shared_ptr<schema_node>;
|
||||
|
||||
template < typename Type >
|
||||
static std::shared_ptr<schema_node> make_node(schema& tree, const std::string& name) {
|
||||
return std::shared_ptr<schema_node>(new schema_node(tree, name, static_cast<Type*>(nullptr)));
|
||||
}
|
||||
static std::shared_ptr<schema_node> make_node(schema& tree, const std::string& name, std::unique_ptr<basic_object_info> &&info);
|
||||
|
||||
schema_node(const schema_node& other) = delete;
|
||||
schema_node(schema_node&& other) = default;
|
||||
@@ -41,17 +38,7 @@ public:
|
||||
|
||||
private:
|
||||
explicit schema_node(schema& tree);
|
||||
template < typename Type >
|
||||
schema_node(schema& tree, std::string name, Type *obj)
|
||||
: schema_(tree)
|
||||
, info_(std::make_unique<object_info<Type>>(*this, object_definition(attribute_definition_generator::generate<Type>(schema_))))
|
||||
, first_child_(std::shared_ptr<schema_node>(new schema_node(tree)))
|
||||
, last_child_(std::shared_ptr<schema_node>(new schema_node(tree)))
|
||||
, name_(std::move(name)) {
|
||||
first_child_->next_sibling_ = last_child_;
|
||||
last_child_->previous_sibling_ = first_child_;
|
||||
}
|
||||
|
||||
schema_node(schema& tree, std::string name, std::unique_ptr<basic_object_info> &&info);
|
||||
|
||||
private:
|
||||
friend class schema;
|
||||
|
||||
Reference in New Issue
Block a user