query/source/core/object/schema.cpp

143 lines
5.1 KiB
C++

#include <utility>
#include "matador/object/schema.hpp"
namespace matador::object {
utils::error make_error(const error_code ec, const std::string &msg) {
return utils::error(ec, msg);
}
schema::schema(std::string name)
: name_(std::move(name))
, root_(schema_node::make_null_node(*this))
, log_(logger::create_logger("schema")) {
root_->first_child_ = std::shared_ptr<schema_node>(new schema_node(*this));
root_->last_child_ = std::shared_ptr<schema_node>(new schema_node(*this));
root_->first_child_->next_sibling_ = root_->last_child_;
root_->last_child_->previous_sibling_ = root_->first_child_;
}
schema::const_iterator schema::begin() const {
return const_iterator(root_->first_child_->next_sibling_);
}
schema::const_iterator schema::end() const {
return const_iterator(root_->last_child_);
}
bool schema::empty() const {
return root_->first_child_ == root_->last_child_->previous_sibling_;
}
size_t schema::size() const {
return static_cast<size_t>(std::distance(begin(), end()));
}
std::string schema::name() const {
return name_;
}
utils::result<std::shared_ptr<attribute_definition>, utils::error> schema::reference(const std::type_index &type_index) const {
const auto result = find_node(type_index);
if (result) {
return utils::ok((*result)->basic_info().reference_column());
}
if (const auto it = expected_node_map_.find(type_index); it != expected_node_map_.end()) {
return utils::ok(it->second->basic_info().reference_column());
}
return utils::failure(result.err());
}
utils::result<std::shared_ptr<schema_node>, utils::error> schema::attach_node(const std::shared_ptr<schema_node> &node,
const std::string &parent) {
if (has_node(node->type_index(), node->name())) {
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists."));
}
// set node to root node
auto parent_node = root_;
if (!parent.empty()) {
auto result = find_node(parent);
if (!result.is_ok() && result.err().ec() != error_code::NodeNotFound) {
return result;
}
parent_node = *result;
}
push_back_child(parent_node, node);
// Todo: check return value
node_map_.insert({node->name(), node})/*.first*/;
type_index_node_map_.insert({node->type_index(), node});
return utils::ok(node);
}
utils::result<std::shared_ptr<schema_node>, utils::error> schema::attach_node(const std::shared_ptr<schema_node> &node,
const std::type_index &type_index) {
if (has_node(node->type_index(), node->name())) {
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists."));
}
auto result = find_node(type_index);
if (!result.is_ok() && result.err().ec() != error_code::NodeNotFound) {
return result;
}
push_back_child(*result, node);
// Todo: check return value
node_map_.insert({node->name(), node})/*.first*/;
type_index_node_map_.insert({node->type_index(), node});
return utils::ok(node);
}
utils::result<std::shared_ptr<schema_node>, utils::error> schema::find_node(const std::string &name) const {
// first search in the prototype map
const auto i = node_map_.find(name);
if (i == node_map_.end()) {
return utils::failure(make_error(error_code::NodeNotFound, "Couldn't find node by name '" + name + "'"));
}
return utils::ok(i->second);
}
utils::result<std::shared_ptr<schema_node>, utils::error> schema::find_node(const std::type_index &type_index) const {
const auto i = type_index_node_map_.find(type_index);
if (i == type_index_node_map_.end()) {
return utils::failure(make_error(error_code::NodeNotFound,
"Couldn't find node by type '" + std::string(type_index.name()) + "'"));
}
return utils::ok(i->second);
}
void schema::push_back_child(const node_ptr &parent, const node_ptr &child) {
child->parent_ = parent;
child->previous_sibling_ = parent->last_child_->previous_sibling_;
child->next_sibling_ = parent->last_child_;
/*
* +-----------------------------<- (first) parent (last) -> ----------------------------+
* | |
* first (next) -> <- (prev) child_1 (next) -> <- (prev) new_child (next) -> <- (prev) last
* ^^^^^^^ inserted ^^^^^^
*/
parent->last_child_->previous_sibling_->next_sibling_ = child;
parent->last_child_->previous_sibling_ = child;
// set depth
// child->depth = depth + 1;
}
bool schema::has_node(const std::string &name) const {
return node_map_.count(name) > 0;
}
bool schema::has_node(const std::type_index &index) const {
return type_index_node_map_.count(index) > 0;
}
bool schema::has_node(const std::type_index &index, const std::string &name) const {
return node_map_.count(name) > 0 || type_index_node_map_.count(index) > 0;
}
} // namespace matador::object