added date_type_t, time_type_t and timestamp, ensure allocated postgres resources are released, split repository into basic_repository and repository.
This commit is contained in:
@@ -17,7 +17,6 @@ add_library(matador-core STATIC
|
||||
../../include/matador/object/basic_object_info.hpp
|
||||
../../include/matador/object/error_code.hpp
|
||||
../../include/matador/object/foreign_node_completer.hpp
|
||||
../../include/matador/object/internal/shadow_repository.hpp
|
||||
../../include/matador/object/many_to_many_relation.hpp
|
||||
../../include/matador/object/object.hpp
|
||||
../../include/matador/object/object_generator.hpp
|
||||
@@ -81,7 +80,6 @@ add_library(matador-core STATIC
|
||||
object/basic_object_info.cpp
|
||||
object/error_code.cpp
|
||||
object/foreign_node_completer.cpp
|
||||
object/internal/shadow_repository.cpp
|
||||
object/object.cpp
|
||||
object/object_generator.cpp
|
||||
object/observer.cpp
|
||||
@@ -110,6 +108,8 @@ add_library(matador-core STATIC
|
||||
utils/version.cpp
|
||||
../../include/matador/object/internal/observer_list_creator.hpp
|
||||
../../include/matador/object/internal/observer_list_copy_creator.hpp
|
||||
../../include/matador/object/basic_repository.hpp
|
||||
object/basic_repository.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
||||
|
||||
@@ -28,7 +28,8 @@ void attribute::name( const std::string& n ) {
|
||||
}
|
||||
|
||||
std::string attribute::full_name() const {
|
||||
return owner_ ? owner_->name() + "." + name_ : name_;
|
||||
const auto owner = owner_.lock();
|
||||
return owner ? owner->name() + "." + name_ : name_;
|
||||
}
|
||||
|
||||
const utils::field_attributes &attribute::attributes() const {
|
||||
@@ -48,7 +49,7 @@ utils::basic_type attribute::type() const {
|
||||
}
|
||||
|
||||
std::shared_ptr<object> attribute::owner() const {
|
||||
return owner_;
|
||||
return owner_.lock();
|
||||
}
|
||||
|
||||
void attribute::change_type(const utils::basic_type type, const utils::field_attributes& attr) {
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace matador::object {
|
||||
basic_object_info::basic_object_info(std::shared_ptr<repository_node> node, std::shared_ptr<class object>&& obj)
|
||||
: object_(std::move(obj))
|
||||
, node_(std::move(node)) {}
|
||||
basic_object_info::basic_object_info(const repository_node& node, const std::shared_ptr<class object>& obj)
|
||||
: object_(obj)
|
||||
, node_(node) {}
|
||||
|
||||
std::type_index basic_object_info::type_index() const {
|
||||
return node_->type_index();
|
||||
return node_.type_index();
|
||||
}
|
||||
|
||||
std::string basic_object_info::name() const {
|
||||
return node_->name();
|
||||
return node_.name();
|
||||
}
|
||||
|
||||
std::shared_ptr<class object> basic_object_info::object() const {
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
#include "matador/object/basic_repository.hpp"
|
||||
#include "matador/object/repository_node.hpp"
|
||||
#include "matador/object/repository_node_iterator.hpp"
|
||||
|
||||
#include "matador/logger/log_manager.hpp"
|
||||
|
||||
#include <stack>
|
||||
|
||||
namespace matador::object {
|
||||
utils::error make_error(const error_code ec, const std::string &msg) {
|
||||
return utils::error(ec, msg);
|
||||
}
|
||||
|
||||
basic_repository::basic_repository(std::string name)
|
||||
: name_(std::move(name))
|
||||
, root_(new repository_node(*this))
|
||||
, log_(logger::create_logger("schema")) {
|
||||
root_->first_child_ = std::make_unique<repository_node>(*this);
|
||||
root_->last_child_ = std::make_unique<repository_node>(*this);
|
||||
root_->first_child_->next_sibling_ = root_->last_child_.get();
|
||||
root_->last_child_->previous_sibling_ = root_->first_child_.get();
|
||||
root_->info_ = std::make_unique<null_info>(*root_);
|
||||
}
|
||||
|
||||
basic_repository::~basic_repository() {
|
||||
if (!root_) {
|
||||
return;
|
||||
}
|
||||
while (root_->first_child_->next_sibling_ != root_->last_child_.get()) {
|
||||
remove_node(root_->first_child_->next_sibling_);
|
||||
}
|
||||
delete root_;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> basic_repository::detach(repository_node *node) {
|
||||
log_.debug("detach node '%s' (type: %s)", node->name().c_str(), node->type_index().name());
|
||||
|
||||
remove_node(node);
|
||||
|
||||
node->on_detach();
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
basic_repository::const_iterator basic_repository::begin() const {
|
||||
return const_iterator(root_->first_child_->next_sibling_);
|
||||
}
|
||||
|
||||
basic_repository::const_iterator basic_repository::end() const {
|
||||
return const_iterator(root_->last_child_.get());
|
||||
}
|
||||
|
||||
bool basic_repository::empty() const {
|
||||
return root_->first_child_.get() == root_->last_child_->previous_sibling_;
|
||||
}
|
||||
|
||||
size_t basic_repository::size() const {
|
||||
return static_cast<size_t>(std::distance(begin(), end()));
|
||||
}
|
||||
|
||||
std::string basic_repository::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
bool basic_repository::contains( const std::string& name ) const {
|
||||
return nodes_by_name_.count(name) > 0;
|
||||
}
|
||||
|
||||
bool basic_repository::contains( const std::type_index& index ) const {
|
||||
return nodes_by_type_.count(index) > 0;
|
||||
}
|
||||
|
||||
utils::result<basic_object_info_ref, utils::error> basic_repository::basic_info(const std::type_index &ti) const {
|
||||
const auto it = find_node(ti);
|
||||
if (it == end()) {
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Node '" + std::string(ti.name()) + "' not found."));
|
||||
}
|
||||
|
||||
return utils::ok(basic_object_info_ref{it->info()});
|
||||
}
|
||||
|
||||
utils::result<basic_object_info_ref, utils::error> basic_repository::basic_info(const std::string& name) const {
|
||||
const auto it = find_node(name);
|
||||
if (it == end()) {
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Node '" + name + "' not found."));
|
||||
}
|
||||
|
||||
return utils::ok(basic_object_info_ref{it->info()});
|
||||
}
|
||||
|
||||
utils::result<attribute*, utils::error> basic_repository::primary_key_attribute(const std::type_index &ti) const {
|
||||
const auto it = find_node(ti);
|
||||
if (it == end()) {
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Node '" + std::string(ti.name()) + "' not found."));
|
||||
}
|
||||
|
||||
if (!it->info().has_primary_key()) {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Object '" + it->name() + "' does not have a primary key."));
|
||||
}
|
||||
return utils::ok(it->info().primary_key_attribute());
|
||||
}
|
||||
|
||||
void basic_repository::dump(std::ostream &os) const {
|
||||
for (const auto &node : *this) {
|
||||
dump(os, node);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void basic_repository::dump( std::ostream& os, const repository_node& node ) {
|
||||
os << "node [" << node.name() << "] (" << node.type_index().name() << ")\n";
|
||||
for (auto it = node.info().endpoint_begin(); it != node.info().endpoint_end(); ++it) {
|
||||
os << " " << node.name() << "::" << it->second->field_name() << " (" << it->second->type_name() << ")";
|
||||
if (it->second->foreign_endpoint()) {
|
||||
os << " <---> " << it->second->node().name() << "::" << it->second->foreign_endpoint()->field_name() << " (" << it->second->foreign_endpoint()->type_name() << ")\n";
|
||||
} else {
|
||||
os << " -> " << it->second->node().name() << " (type: " << it->second->node().type_index().name() << ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils::result<repository_node*, utils::error> basic_repository::attach_node(repository_node *node, const std::string &parent) {
|
||||
if (has_node(node)) {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists."));
|
||||
}
|
||||
|
||||
log_.info("attach: insert node '%s' (type: %s)", node->name().c_str(), node->type_index().name());
|
||||
|
||||
// set node to root node
|
||||
auto parent_node = root_;
|
||||
if (!parent.empty()) {
|
||||
const auto result = find_node(parent);
|
||||
if (result == end()) {
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Parent node '" + parent + "' not found."));
|
||||
}
|
||||
parent_node = result.get();
|
||||
}
|
||||
|
||||
insert_node(parent_node, node);
|
||||
|
||||
// Todo: check return value
|
||||
nodes_by_name_.insert({node->name(), node});
|
||||
nodes_by_type_.insert({node->type_index(), node});
|
||||
|
||||
node->on_attach();
|
||||
|
||||
return utils::ok(node);
|
||||
}
|
||||
|
||||
basic_repository::const_iterator basic_repository::find_node(const std::string &name) const {
|
||||
// first search in the prototype map
|
||||
const auto i = nodes_by_name_.find(name);
|
||||
if (i == nodes_by_name_.end()) {
|
||||
return end();
|
||||
}
|
||||
return const_iterator(i->second);
|
||||
}
|
||||
|
||||
basic_repository::const_iterator basic_repository::find_node(const std::type_index &type_index) const {
|
||||
const auto i = nodes_by_type_.find(type_index);
|
||||
if (i == nodes_by_type_.end()) {
|
||||
return end();
|
||||
}
|
||||
return const_iterator(i->second);
|
||||
}
|
||||
|
||||
void basic_repository::insert_node(repository_node *parent, repository_node *child) {
|
||||
child->parent_ = parent;
|
||||
child->previous_sibling_ = parent->last_child_->previous_sibling_;
|
||||
child->next_sibling_ = parent->last_child_.get();
|
||||
/*
|
||||
* +-----------------------------<- (first) parent (last) -> ----------------------------+
|
||||
* | |
|
||||
* first (next) -> <- (prev) child_1 (next) -> <- (prev) new_child (next) -> <- (prev) last
|
||||
* ^^^^^^^ inserted ^^^^^^
|
||||
*/
|
||||
if (const auto prev_sib = parent->last_child_->previous_sibling_) {
|
||||
prev_sib->next_sibling_ = child;
|
||||
}
|
||||
parent->last_child_->previous_sibling_ = child;
|
||||
// set depth
|
||||
// child->depth = depth + 1;
|
||||
}
|
||||
|
||||
void basic_repository::remove_node(repository_node *node) {
|
||||
// auto next = node->next();
|
||||
|
||||
std::stack<repository_node*> nodes_to_remove;
|
||||
nodes_to_remove.push(node);
|
||||
|
||||
while (!nodes_to_remove.empty()) {
|
||||
const auto current = nodes_to_remove.top();
|
||||
|
||||
if (current->has_children()) {
|
||||
// Push all children to the stack (from right to left to maintain order)
|
||||
auto child = current->last_child_->previous_sibling_;
|
||||
while (child && child != current->first_child_.get()) {
|
||||
nodes_to_remove.push(child);
|
||||
child = child->previous_sibling_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// No children left, safe to remove this node
|
||||
nodes_to_remove.pop();
|
||||
current->unlink();
|
||||
nodes_by_name_.erase(current->name());
|
||||
nodes_by_type_.erase(current->type_index());
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
|
||||
bool basic_repository::has_node(const std::string &name) const {
|
||||
return nodes_by_name_.count(name) > 0;
|
||||
}
|
||||
|
||||
bool basic_repository::has_node(const std::type_index &index) const {
|
||||
return nodes_by_type_.count(index) > 0;
|
||||
}
|
||||
|
||||
bool basic_repository::has_node(const repository_node* node) const {
|
||||
return nodes_by_name_.count(node->name()) > 0 || nodes_by_type_.count(node->type_index()) > 0;
|
||||
}
|
||||
|
||||
bool basic_repository::expecting_relation_node( const std::string& name ) const {
|
||||
return expected_relation_nodes_.count(name) > 0;
|
||||
}
|
||||
|
||||
void basic_repository::expect_relation_node(const std::string &name, const std::type_index &ti) {
|
||||
expected_relation_nodes_.insert({name, ti});
|
||||
}
|
||||
|
||||
void basic_repository::remove_expected_relation_node( const std::string& name ) {
|
||||
expected_relation_nodes_.erase(name);
|
||||
}
|
||||
|
||||
std::shared_ptr<object> basic_repository::provide_object_in_advance(const std::type_index &ti, const std::shared_ptr<object>& obj) {
|
||||
return object_by_type_.insert({ti, obj}).first->second;
|
||||
}
|
||||
|
||||
bool basic_repository::has_object_for_type(const std::type_index &ti) const {
|
||||
return object_by_type_.count(ti) > 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<object> basic_repository::object_for_type(const std::type_index &ti) const {
|
||||
return object_by_type_.at(ti);
|
||||
}
|
||||
|
||||
void basic_repository::remove_object_for_type(const std::type_index &ti) {
|
||||
object_by_type_.erase(ti);
|
||||
}
|
||||
|
||||
bool basic_repository::is_node_announced(const std::type_index &ti) const {
|
||||
return announced_node_.count(ti) > 0;
|
||||
}
|
||||
|
||||
void basic_repository::push_announce_node(const std::type_index &ti, std::unique_ptr<repository_node> &&node) {
|
||||
announced_node_.insert({ti, std::move(node)});
|
||||
}
|
||||
|
||||
repository_node* basic_repository::announce_node(const std::type_index &ti) const {
|
||||
return announced_node_.find(ti)->second.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<repository_node> basic_repository::pop_announce_node(const std::type_index &ti) {
|
||||
const auto it = announced_node_.find(ti);
|
||||
if (it == announced_node_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto node = std::move(it->second);
|
||||
announced_node_.erase(it);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
#include "matador/object/internal/shadow_repository.hpp"
|
||||
|
||||
#include "matador/object/repository.hpp"
|
||||
#include "matador/object/repository_node.hpp"
|
||||
|
||||
namespace matador::object::internal {
|
||||
shadow_repository::shadow_repository(repository& s)
|
||||
: repo_(s) {}
|
||||
|
||||
repository& shadow_repository::repo() const {
|
||||
return repo_;
|
||||
}
|
||||
|
||||
bool shadow_repository::contains( const std::type_index& ti ) const {
|
||||
return repo_.contains(ti);
|
||||
}
|
||||
|
||||
utils::result<basic_object_info_ref, utils::error> shadow_repository::basic_info(const std::type_index& ti) const {
|
||||
return repo_.basic_info(ti);
|
||||
}
|
||||
|
||||
utils::result<shadow_repository::node_ptr, utils::error> shadow_repository::find_node( const std::type_index& type_index ) const {
|
||||
return repo_.find_node(type_index);
|
||||
}
|
||||
|
||||
utils::result<shadow_repository::node_ptr, utils::error> shadow_repository::find_node( const std::string& name ) const {
|
||||
return repo_.find_node(name);
|
||||
}
|
||||
|
||||
utils::result<shadow_repository::node_ptr, utils::error> shadow_repository::attach_node( const std::shared_ptr<repository_node>& node ) const {
|
||||
return repo_.attach_node(node, "");
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> shadow_repository::detach_node( const std::shared_ptr<repository_node>& node ) const {
|
||||
return repo_.detach(node);
|
||||
}
|
||||
|
||||
bool shadow_repository::expecting_relation_node(const std::string &name) const {
|
||||
return repo_.expecting_relation_node(name);
|
||||
}
|
||||
|
||||
void shadow_repository::expect_relation_node(const std::string &name, const std::type_index &ti) const {
|
||||
repo_.expect_relation_node(name, ti);
|
||||
}
|
||||
|
||||
void shadow_repository::remove_expected_relation_node(const std::string &name) const {
|
||||
repo_.remove_expected_relation_node(name);
|
||||
}
|
||||
|
||||
std::shared_ptr<object> shadow_repository::provide_object_in_advance(const std::type_index& ti, const std::shared_ptr<object>& obj) const {
|
||||
return repo_.provide_object_in_advance(ti, obj);
|
||||
}
|
||||
|
||||
bool shadow_repository::has_object_for_type(const std::type_index& ti) const {
|
||||
return repo_.has_object_for_type(ti);
|
||||
}
|
||||
|
||||
std::shared_ptr<object> shadow_repository::object_for_type(const std::type_index& ti) const {
|
||||
return repo_.object_for_type(ti);
|
||||
}
|
||||
|
||||
void shadow_repository::remove_object_for_type(const std::type_index& ti) const {
|
||||
repo_.remove_object_for_type(ti);
|
||||
}
|
||||
|
||||
bool shadow_repository::is_node_announced(const std::type_index &ti) const {
|
||||
return repo_.is_node_announced(ti);
|
||||
}
|
||||
|
||||
void shadow_repository::push_announce_node(const std::type_index &ti, const node_ptr &node) const {
|
||||
repo_.push_announce_node(ti, node);
|
||||
}
|
||||
|
||||
shadow_repository::node_ptr shadow_repository::announce_node(const std::type_index &ti) const {
|
||||
return repo_.announce_node(ti);
|
||||
}
|
||||
|
||||
shadow_repository::node_ptr shadow_repository::pop_announce_node(const std::type_index &ti) const {
|
||||
return repo_.pop_announce_node(ti);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace matador::object {
|
||||
object_generator::object_generator(const repository& repo, const std::shared_ptr<object>& object)
|
||||
object_generator::object_generator(basic_repository& repo, const std::shared_ptr<object>& object)
|
||||
: repo_(repo)
|
||||
, object_(object) {}
|
||||
|
||||
std::shared_ptr<object> object_generator::acquire_object(repository &repo, const std::type_index &ti, const std::string& name) {
|
||||
std::shared_ptr<object> object_generator::acquire_object(basic_repository &repo, const std::type_index &ti, const std::string& name) {
|
||||
if (repo.has_object_for_type(ti)) {
|
||||
auto obj = repo.object_for_type(ti);
|
||||
repo.remove_object_for_type(ti);
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
#include "matador/object/repository_node.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
relation_endpoint::relation_endpoint(std::string field_name, const relation_type type, const std::shared_ptr<repository_node> &node)
|
||||
relation_endpoint::relation_endpoint(std::string field_name, const relation_type type, repository_node &node)
|
||||
: field_name_(std::move(field_name))
|
||||
, type_(type)
|
||||
, node_(node) {
|
||||
, node_(&node) {
|
||||
}
|
||||
|
||||
std::string relation_endpoint::field_name() const {
|
||||
@@ -25,10 +25,6 @@ const repository_node &relation_endpoint::node() const {
|
||||
return *node_;
|
||||
}
|
||||
|
||||
std::shared_ptr<repository_node> relation_endpoint::node_ptr() const {
|
||||
return node_;
|
||||
}
|
||||
|
||||
bool relation_endpoint::is_has_one() const {
|
||||
return type_ == relation_type::HasOne;
|
||||
}
|
||||
@@ -42,7 +38,7 @@ bool relation_endpoint::is_belongs_to() const {
|
||||
}
|
||||
|
||||
std::shared_ptr<relation_endpoint> relation_endpoint::foreign_endpoint() const {
|
||||
return foreign_endpoint_;
|
||||
return foreign_endpoint_.lock();
|
||||
}
|
||||
|
||||
void relation_endpoint::link_foreign_endpoint( const std::shared_ptr<relation_endpoint>& endpoint ) {
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
#include <utility>
|
||||
|
||||
#include "matador/object/repository.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
utils::error make_error(const error_code ec, const std::string &msg) {
|
||||
return utils::error(ec, msg);
|
||||
}
|
||||
|
||||
repository::repository(std::string name)
|
||||
: name_(std::move(name))
|
||||
, root_(repository_node::make_null_node(*this))
|
||||
, log_(logger::create_logger("schema")) {
|
||||
root_->first_child_ = std::shared_ptr<repository_node>(new repository_node(*this));
|
||||
root_->last_child_ = std::shared_ptr<repository_node>(new repository_node(*this));
|
||||
root_->first_child_->next_sibling_ = root_->last_child_;
|
||||
root_->last_child_->previous_sibling_ = root_->first_child_;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> repository::detach(const node_ptr &node) {
|
||||
log_.debug("detach node '%s' (type: %s)", node->name().c_str(), node->type_index().name());
|
||||
|
||||
remove_node(node);
|
||||
|
||||
node->on_detach();
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
repository::const_iterator repository::begin() const {
|
||||
return const_iterator(root_->first_child_->next_sibling_);
|
||||
}
|
||||
|
||||
repository::const_iterator repository::end() const {
|
||||
return const_iterator(root_->last_child_);
|
||||
}
|
||||
|
||||
bool repository::empty() const {
|
||||
return root_->first_child_ == root_->last_child_->previous_sibling_;
|
||||
}
|
||||
|
||||
size_t repository::size() const {
|
||||
return static_cast<size_t>(std::distance(begin(), end()));
|
||||
}
|
||||
|
||||
std::string repository::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
bool repository::contains( const std::string& name ) const {
|
||||
return nodes_by_name_.count(name) > 0;
|
||||
}
|
||||
|
||||
bool repository::contains( const std::type_index& index ) const {
|
||||
return nodes_by_type_.count(index) > 0;
|
||||
}
|
||||
|
||||
utils::result<basic_object_info_ref, utils::error> repository::basic_info(const std::type_index &ti) const {
|
||||
auto result = find_node(ti);
|
||||
if (!result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
return utils::ok(basic_object_info_ref{result.value()->info()});
|
||||
}
|
||||
|
||||
utils::result<basic_object_info_ref, utils::error> repository::basic_info(const std::string& name) const {
|
||||
auto result = find_node(name);
|
||||
if (!result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
return utils::ok(basic_object_info_ref{result.value()->info()});
|
||||
}
|
||||
|
||||
utils::result<attribute*, utils::error> repository::primary_key_attribute(const std::type_index &type_index) const {
|
||||
const auto result = find_node(type_index);
|
||||
if (!result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
if (!result.value()->info().has_primary_key()) {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Object '" + result.value()->name() + "' does not have a primary key."));
|
||||
}
|
||||
return utils::ok((*result)->info().primary_key_attribute());
|
||||
}
|
||||
|
||||
void repository::dump(std::ostream &os) const {
|
||||
for (const auto &node : *this) {
|
||||
dump(os, node);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void repository::dump( std::ostream& os, const node_ptr& node ) {
|
||||
os << "node [" << node->name() << "] (" << node->type_index().name() << ")\n";
|
||||
for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) {
|
||||
os << " " << node->name() << "::" << it->second->field_name() << " (" << it->second->type_name() << ")";
|
||||
if (it->second->foreign_endpoint()) {
|
||||
os << " <---> " << it->second->node().name() << "::" << it->second->foreign_endpoint()->field_name() << " (" << it->second->foreign_endpoint()->type_name() << ")\n";
|
||||
} else {
|
||||
os << " -> " << it->second->node().name() << " (type: " << it->second->node().type_index().name() << ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils::result<repository::node_ptr, utils::error> repository::attach_node(const std::shared_ptr<repository_node> &node, const std::string &parent) {
|
||||
if (has_node(node)) {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists."));
|
||||
}
|
||||
|
||||
log_.info("attach: insert node '%s' (type: %s)", node->name().c_str(), node->type_index().name());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
insert_node(parent_node, node);
|
||||
|
||||
// Todo: check return value
|
||||
nodes_by_name_.insert({node->name(), node});
|
||||
nodes_by_type_.insert({node->type_index(), node});
|
||||
|
||||
node->on_attach();
|
||||
|
||||
return utils::ok(node);
|
||||
}
|
||||
|
||||
utils::result<repository::node_ptr, utils::error> repository::find_node(const std::string &name) const {
|
||||
// first search in the prototype map
|
||||
const auto i = nodes_by_name_.find(name);
|
||||
if (i == nodes_by_name_.end()) {
|
||||
return utils::failure(make_error(error_code::NodeNotFound, "Couldn't find node by name '" + name + "'"));
|
||||
}
|
||||
return utils::ok(i->second);
|
||||
}
|
||||
|
||||
utils::result<repository::node_ptr, utils::error> repository::find_node(const std::type_index &type_index) const {
|
||||
const auto i = nodes_by_type_.find(type_index);
|
||||
if (i == nodes_by_type_.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 repository::insert_node(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;
|
||||
}
|
||||
|
||||
void repository::remove_node(const node_ptr &node) {
|
||||
auto next = node->next();
|
||||
|
||||
std::stack<node_ptr> nodes_to_remove;
|
||||
nodes_to_remove.push(node);
|
||||
|
||||
while (!nodes_to_remove.empty()) {
|
||||
const auto current = nodes_to_remove.top();
|
||||
|
||||
if (current->has_children()) {
|
||||
// Push all children to the stack (from right to left to maintain order)
|
||||
auto child = current->last_child_->previous_sibling_;
|
||||
while (child != current->first_child_) {
|
||||
nodes_to_remove.push(child);
|
||||
child = child->previous_sibling_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// No children left, safe to remove this node
|
||||
nodes_to_remove.pop();
|
||||
current->unlink();
|
||||
nodes_by_name_.erase(current->name());
|
||||
nodes_by_type_.erase(current->type_index());
|
||||
}
|
||||
}
|
||||
|
||||
bool repository::has_node(const std::string &name) const {
|
||||
return nodes_by_name_.count(name) > 0;
|
||||
}
|
||||
|
||||
bool repository::has_node(const std::type_index &index) const {
|
||||
return nodes_by_type_.count(index) > 0;
|
||||
}
|
||||
|
||||
bool repository::has_node(const node_ptr& node) const {
|
||||
return nodes_by_name_.count(node->name()) > 0 || nodes_by_type_.count(node->type_index()) > 0;
|
||||
}
|
||||
|
||||
bool repository::expecting_relation_node( const std::string& name ) const {
|
||||
return expected_relation_nodes_.count(name) > 0;
|
||||
}
|
||||
|
||||
void repository::expect_relation_node(const std::string &name, const std::type_index &ti) {
|
||||
expected_relation_nodes_.insert({name, ti});
|
||||
}
|
||||
|
||||
void repository::remove_expected_relation_node( const std::string& name ) {
|
||||
expected_relation_nodes_.erase(name);
|
||||
}
|
||||
|
||||
std::shared_ptr<object> repository::provide_object_in_advance(const std::type_index &ti, const std::shared_ptr<object>& obj) {
|
||||
return object_by_type_.insert({ti, obj}).first->second;
|
||||
}
|
||||
|
||||
bool repository::has_object_for_type(const std::type_index &ti) const {
|
||||
return object_by_type_.count(ti) > 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<object> repository::object_for_type(const std::type_index &ti) const {
|
||||
return object_by_type_.at(ti);
|
||||
}
|
||||
|
||||
void repository::remove_object_for_type(const std::type_index &ti) {
|
||||
object_by_type_.erase(ti);
|
||||
}
|
||||
|
||||
bool repository::is_node_announced(const std::type_index &ti) const {
|
||||
return announced_node_.count(ti) > 0;
|
||||
}
|
||||
|
||||
void repository::push_announce_node(const std::type_index &ti, const node_ptr &node) {
|
||||
announced_node_.insert({ti, node});
|
||||
}
|
||||
|
||||
repository::node_ptr repository::announce_node(const std::type_index &ti) {
|
||||
return announced_node_.find(ti)->second;
|
||||
}
|
||||
|
||||
repository::node_ptr repository::pop_announce_node(const std::type_index &ti) {
|
||||
const auto it = announced_node_.find(ti);
|
||||
if (it != announced_node_.end()) {
|
||||
announced_node_.erase(it);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
} // namespace matador::object
|
||||
|
||||
@@ -1,34 +1,28 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "matador/object/repository.hpp"
|
||||
#include "matador/object/basic_repository.hpp"
|
||||
#include "matador/object/repository_node.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
repository_node::repository_node(repository &repo)
|
||||
repository_node::repository_node(basic_repository &repo)
|
||||
: repo_(repo)
|
||||
, type_index_(typeid(detail::null_type)){
|
||||
}
|
||||
|
||||
repository_node::repository_node(repository &repo, const std::type_index& ti)
|
||||
repository_node::repository_node(basic_repository &repo, const std::type_index& ti)
|
||||
: repo_(repo)
|
||||
, type_index_(ti) {
|
||||
}
|
||||
|
||||
repository_node::repository_node(repository &repo, std::string name, const std::type_index& ti)
|
||||
repository_node::repository_node(basic_repository &repo, std::string name, const std::type_index& ti)
|
||||
: repo_(repo)
|
||||
, type_index_(ti)
|
||||
, first_child_(std::shared_ptr<repository_node>(new repository_node(repo)))
|
||||
, last_child_(std::shared_ptr<repository_node>(new repository_node(repo)))
|
||||
, first_child_(std::make_unique<repository_node>(repo))
|
||||
, last_child_(std::make_unique<repository_node>(repo))
|
||||
, name_(std::move(name)) {
|
||||
first_child_->next_sibling_ = last_child_;
|
||||
last_child_->previous_sibling_ = first_child_;
|
||||
}
|
||||
|
||||
std::shared_ptr<repository_node> repository_node::make_null_node(repository &repo) {
|
||||
auto node = std::shared_ptr<repository_node>(new repository_node(repo));
|
||||
node->info_ = std::make_unique<null_info>(node);
|
||||
|
||||
return node;
|
||||
first_child_->next_sibling_ = last_child_.get();
|
||||
last_child_->previous_sibling_ = first_child_.get();
|
||||
}
|
||||
|
||||
std::string repository_node::name() const {
|
||||
@@ -48,32 +42,35 @@ void repository_node::update_name(const std::string& name) {
|
||||
info_->update_name(name);
|
||||
}
|
||||
|
||||
const repository& repository_node::schema() const {
|
||||
const basic_repository& repository_node::schema() const {
|
||||
return repo_;
|
||||
}
|
||||
|
||||
bool repository_node::has_children() const {
|
||||
return first_child_->next_sibling_ != last_child_;
|
||||
return first_child_->next_sibling_ != last_child_.get();
|
||||
}
|
||||
void repository_node::on_attach() const {
|
||||
info_->on_attach();
|
||||
}
|
||||
|
||||
void repository_node::on_detach() const {}
|
||||
void repository_node::on_detach() const {
|
||||
info_->on_detach();
|
||||
}
|
||||
|
||||
repository_node::node_ptr repository_node::next() const {
|
||||
// if we have a child, child is the next iterator to return
|
||||
// (if we don't iterate over the siblings)
|
||||
if (first_child_ && first_child_->next_sibling_ != last_child_) {
|
||||
if (first_child_ && first_child_->next_sibling_ != last_child_.get()) {
|
||||
return first_child_->next_sibling_;
|
||||
}
|
||||
// if there is no child, we check for sibling
|
||||
// if there is a sibling, this is our next iterator to return
|
||||
// if not, we go back to the parent
|
||||
auto *node = this;
|
||||
while (node->parent_ && node->next_sibling_ == node->parent_->last_child_) {
|
||||
node = node->parent_.get();
|
||||
while (node->parent_ && node->next_sibling_ == node->parent_->last_child_.get()) {
|
||||
node = node->parent_;
|
||||
}
|
||||
return node->parent_ ? node->next_sibling_ : node->last_child_;
|
||||
return node->parent_ ? node->next_sibling_ : node->last_child_.get();
|
||||
}
|
||||
|
||||
repository_node::node_ptr repository_node::prev() const {
|
||||
@@ -83,7 +80,7 @@ repository_node::node_ptr repository_node::prev() const {
|
||||
// child as our iterator
|
||||
if (previous_sibling_ && previous_sibling_->previous_sibling_) {
|
||||
auto node = previous_sibling_;
|
||||
while (node->last_child_ && node->first_child_->next_sibling_ != node->last_child_) {
|
||||
while (node->last_child_ && node->first_child_->next_sibling_ != node->last_child_.get()) {
|
||||
node = node->last_child_->previous_sibling_;
|
||||
}
|
||||
return node;
|
||||
@@ -96,7 +93,7 @@ repository_node::node_ptr repository_node::prev() const {
|
||||
void repository_node::unlink() {
|
||||
previous_sibling_->next_sibling_ = next_sibling_;
|
||||
next_sibling_->previous_sibling_ = previous_sibling_;
|
||||
next_sibling_.reset();
|
||||
previous_sibling_.reset();
|
||||
next_sibling_ = nullptr;
|
||||
previous_sibling_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +1,66 @@
|
||||
#include <utility>
|
||||
|
||||
#include "matador/object/repository_node_iterator.hpp"
|
||||
#include "matador/object/repository_node.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
const_repository_node_iterator::const_repository_node_iterator(value_type* node)
|
||||
: node_(node) {
|
||||
}
|
||||
|
||||
const_repository_node_iterator::const_repository_node_iterator(const value_type& node)
|
||||
: node_(node)
|
||||
{}
|
||||
|
||||
bool const_repository_node_iterator::operator==(const const_repository_node_iterator &i) const
|
||||
{
|
||||
bool const_repository_node_iterator::operator==(const const_repository_node_iterator &i) const {
|
||||
return (node_ == i.node_);
|
||||
}
|
||||
|
||||
bool const_repository_node_iterator::operator!=(const const_repository_node_iterator &i) const
|
||||
{
|
||||
bool const_repository_node_iterator::operator!=(const const_repository_node_iterator &i) const {
|
||||
return !operator==(i);
|
||||
}
|
||||
|
||||
const_repository_node_iterator& const_repository_node_iterator::operator++()
|
||||
{
|
||||
const_repository_node_iterator &const_repository_node_iterator::operator++() {
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_repository_node_iterator const_repository_node_iterator::operator++( int ) {
|
||||
const value_type tmp = node_;
|
||||
const_repository_node_iterator const_repository_node_iterator::operator++(int) {
|
||||
value_type* tmp = node_;
|
||||
increment();
|
||||
return const_repository_node_iterator(tmp);
|
||||
}
|
||||
|
||||
const_repository_node_iterator& const_repository_node_iterator::operator--()
|
||||
{
|
||||
const_repository_node_iterator &const_repository_node_iterator::operator--() {
|
||||
decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_repository_node_iterator const_repository_node_iterator::operator--(int)
|
||||
{
|
||||
const value_type tmp = node_;
|
||||
const_repository_node_iterator const_repository_node_iterator::operator--(int) {
|
||||
value_type* tmp = node_;
|
||||
decrement();
|
||||
return const_repository_node_iterator(tmp);
|
||||
}
|
||||
|
||||
const_repository_node_iterator::pointer const_repository_node_iterator::operator->() const
|
||||
{
|
||||
return node_.get();
|
||||
}
|
||||
|
||||
const_repository_node_iterator::reference const_repository_node_iterator::operator*() const
|
||||
{
|
||||
const_repository_node_iterator::pointer const_repository_node_iterator::operator->() const {
|
||||
return node_;
|
||||
}
|
||||
|
||||
const_repository_node_iterator::pointer const_repository_node_iterator::get() const
|
||||
{
|
||||
return node_.get();
|
||||
const_repository_node_iterator::reference const_repository_node_iterator::operator*() const {
|
||||
return *node_;
|
||||
}
|
||||
|
||||
void const_repository_node_iterator::increment()
|
||||
{
|
||||
const_repository_node_iterator::pointer const_repository_node_iterator::get() const {
|
||||
return node_;
|
||||
}
|
||||
|
||||
void const_repository_node_iterator::increment() {
|
||||
if (!node_) {
|
||||
return;
|
||||
}
|
||||
|
||||
node_ = node_->next();
|
||||
}
|
||||
void const_repository_node_iterator::decrement()
|
||||
{
|
||||
|
||||
void const_repository_node_iterator::decrement() {
|
||||
if (!node_) {
|
||||
return;
|
||||
}
|
||||
|
||||
node_ = node_->prev();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ std::string restriction::column_name() const {
|
||||
return attr_.name();
|
||||
}
|
||||
std::shared_ptr<object> restriction::owner() const {
|
||||
return owner_;
|
||||
return owner_.lock();
|
||||
}
|
||||
|
||||
bool restriction::is_primary_key_constraint() const {
|
||||
@@ -30,12 +30,14 @@ bool restriction::is_unique_constraint() const {
|
||||
return utils::is_constraint_set(options_, utils::constraints::Unique);
|
||||
}
|
||||
|
||||
const std::string& restriction::ref_table_name() const {
|
||||
return reference_->name();
|
||||
std::string restriction::ref_table_name() const {
|
||||
const auto ref = reference_.lock();
|
||||
return ref ? ref->name() : "";
|
||||
}
|
||||
|
||||
const std::string& restriction::ref_column_name() const {
|
||||
return reference_->primary_key_attribute()->name();
|
||||
std::string restriction::ref_column_name() const {
|
||||
const auto ref = reference_.lock();
|
||||
return ref ? ref->primary_key_attribute()->name() : "";
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream &os, const class restriction &c) {
|
||||
@@ -58,43 +60,4 @@ std::string restriction::type_string() const {
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
// constraint_builder & constraint_builder::constraint(std::string name) {
|
||||
// constraint_name = std::move(name);
|
||||
// return *this;
|
||||
// }
|
||||
//
|
||||
// constraint_builder & constraint_builder::primary_key(std::string name) {
|
||||
// column_name = std::move(name);
|
||||
// options_ |= utils::constraints::PrimaryKey;
|
||||
// return *this;
|
||||
// }
|
||||
//
|
||||
// constraint_builder & constraint_builder::foreign_key(std::string name) {
|
||||
// column_name = std::move(name);
|
||||
// options_ |= utils::constraints::ForeignKey;
|
||||
// return *this;
|
||||
// }
|
||||
//
|
||||
// constraint_builder & constraint_builder::references(std::string table, std::string column) {
|
||||
// ref_table_name = std::move(table);
|
||||
// ref_column_name = std::move(column);
|
||||
//
|
||||
// return *this;
|
||||
// }
|
||||
//
|
||||
// constraint_builder::operator class restriction() const {
|
||||
// class restriction c;
|
||||
// c.name_ = constraint_name;
|
||||
// c.attr_ = column_name;
|
||||
// c.options_ = options_;
|
||||
// c.ref_column_name_ = ref_column_name;
|
||||
// c.ref_table_name_ = ref_table_name;
|
||||
// return c;
|
||||
// }
|
||||
//
|
||||
// constraint_builder constraint(std::string name) {
|
||||
// constraint_builder builder;
|
||||
// return builder.constraint(std::move(name));
|
||||
// }
|
||||
}
|
||||
|
||||
+58
-10
@@ -2,9 +2,55 @@
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
// constexpr bool operator==(const date_type_t& a, const date_type_t& b) noexcept
|
||||
|
||||
void initialize_by_basic_type(const basic_type type, database_type &val)
|
||||
{
|
||||
constexpr bool operator!=(const date_type_t &a, const date_type_t &b) noexcept {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
constexpr bool operator<(const date_type_t &a, const date_type_t &b) noexcept {
|
||||
return (a.year < b.year) ||
|
||||
(a.year == b.year && a.month < b.month) ||
|
||||
(a.year == b.year && a.month == b.month && a.day < b.day);
|
||||
}
|
||||
|
||||
constexpr bool operator>(const date_type_t &a, const date_type_t &b) noexcept {
|
||||
return b < a;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const date_type_t &a, const date_type_t &b) noexcept {
|
||||
return !(b < a);
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const date_type_t &a, const date_type_t &b) noexcept {
|
||||
return !(a < b);
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const time_type_t &a, const time_type_t &b) noexcept {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
constexpr bool operator<(const time_type_t &a, const time_type_t &b) noexcept {
|
||||
return (a.hour < b.hour) ||
|
||||
(a.hour == b.hour && a.minute < b.minute) ||
|
||||
(a.hour == b.hour && a.minute == b.minute && a.second < b.second) ||
|
||||
(a.hour == b.hour && a.minute == b.minute && a.second == b.second &&
|
||||
a.microsecond < b.microsecond);
|
||||
}
|
||||
|
||||
constexpr bool operator>(const time_type_t &a, const time_type_t &b) noexcept {
|
||||
return b < a;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const time_type_t &a, const time_type_t &b) noexcept {
|
||||
return !(b < a);
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const time_type_t &a, const time_type_t &b) noexcept {
|
||||
return !(a < b);
|
||||
}
|
||||
|
||||
void initialize_by_basic_type(const basic_type type, database_type &val) {
|
||||
switch (type) {
|
||||
case basic_type::Int8:
|
||||
val.emplace<int8_t>();
|
||||
@@ -43,19 +89,21 @@ void initialize_by_basic_type(const basic_type type, database_type &val)
|
||||
case basic_type::Text:
|
||||
val.emplace<std::string>();
|
||||
break;
|
||||
// case basic_type::type_date:
|
||||
// val.emplace<date>();
|
||||
// break;
|
||||
// case basic_type::type_time:
|
||||
// val.emplace<time>();
|
||||
// break;
|
||||
case basic_type::Date:
|
||||
val.emplace<date_type_t>();
|
||||
break;
|
||||
case basic_type::Time:
|
||||
val.emplace<time_type_t>();
|
||||
break;
|
||||
case basic_type::DateTime:
|
||||
val.emplace<timestamp>();
|
||||
break;
|
||||
case basic_type::Blob:
|
||||
val.emplace<utils::blob>();
|
||||
val.emplace<blob>();
|
||||
break;
|
||||
default:
|
||||
val.emplace<nullptr_t>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+18
-91
@@ -4,9 +4,6 @@
|
||||
|
||||
namespace matador::utils {
|
||||
namespace detail {
|
||||
|
||||
void initialize_by_basic_type(basic_type type, database_type &val);
|
||||
|
||||
size_t determine_size(const std::string &val) {
|
||||
return val.size();
|
||||
}
|
||||
@@ -18,25 +15,22 @@ size_t determine_size(const char *val) {
|
||||
size_t determine_size(const blob &val) {
|
||||
return val.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
value::value(const basic_type data_type, const size_t size)
|
||||
: size_(size)
|
||||
, type_(data_type)
|
||||
{
|
||||
, type_(data_type) {
|
||||
initialize_by_basic_type(type_, value_);
|
||||
}
|
||||
|
||||
value::value(value &&x) noexcept
|
||||
: value_(std::move(x.value_))
|
||||
, type_(x.type_)
|
||||
{
|
||||
: value_(std::move(x.value_))
|
||||
, type_(x.type_) {
|
||||
x.value_ = nullptr;
|
||||
x.type_ = basic_type::Null;
|
||||
}
|
||||
|
||||
value &value::operator=(value &&x) noexcept
|
||||
{
|
||||
value &value::operator=(value &&x) noexcept {
|
||||
value_ = std::move(x.value_);
|
||||
type_ = x.type_;
|
||||
x.value_ = nullptr;
|
||||
@@ -45,13 +39,11 @@ value &value::operator=(value &&x) noexcept
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string value::str() const
|
||||
{
|
||||
std::string value::str() const {
|
||||
return as<std::string>().value_or("");
|
||||
}
|
||||
|
||||
size_t value::size() const
|
||||
{
|
||||
size_t value::size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
@@ -60,108 +52,43 @@ basic_type value::type() const {
|
||||
}
|
||||
|
||||
void value::type(const basic_type t) {
|
||||
type_ = t;
|
||||
detail::initialize_by_basic_type(type_, value_);
|
||||
type_ = t;
|
||||
initialize_by_basic_type(type_, value_);
|
||||
}
|
||||
|
||||
bool value::is_integer() const
|
||||
{
|
||||
bool value::is_integer() const {
|
||||
return type_ >= basic_type::Int8 && type_ <= basic_type::UInt64;
|
||||
}
|
||||
|
||||
bool value::is_floating_point() const
|
||||
{
|
||||
bool value::is_floating_point() const {
|
||||
return type_ == basic_type::Float || type_ == basic_type::Double;
|
||||
}
|
||||
|
||||
bool value::is_bool() const
|
||||
{
|
||||
bool value::is_bool() const {
|
||||
return type_ == basic_type::Boolean;
|
||||
}
|
||||
|
||||
bool value::is_string() const
|
||||
{
|
||||
bool value::is_string() const {
|
||||
return type_ == basic_type::Text;
|
||||
}
|
||||
|
||||
bool value::is_varchar() const
|
||||
{
|
||||
bool value::is_varchar() const {
|
||||
return type_ == basic_type::Varchar;
|
||||
}
|
||||
|
||||
bool value::is_date() const
|
||||
{
|
||||
bool value::is_date() const {
|
||||
return type_ == basic_type::Date;
|
||||
}
|
||||
|
||||
bool value::is_time() const
|
||||
{
|
||||
bool value::is_time() const {
|
||||
return type_ == basic_type::Time;
|
||||
}
|
||||
|
||||
bool value::is_blob() const
|
||||
{
|
||||
bool value::is_blob() const {
|
||||
return type_ == basic_type::Blob;
|
||||
}
|
||||
|
||||
bool value::is_null() const
|
||||
{
|
||||
bool value::is_null() const {
|
||||
return type_ == basic_type::Null;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
void initialize_by_basic_type(const basic_type type, database_type &val) {
|
||||
switch (type) {
|
||||
case basic_type::Int8:
|
||||
val.emplace<int8_t>();
|
||||
break;
|
||||
case basic_type::Int16:
|
||||
val.emplace<int16_t>();
|
||||
break;
|
||||
case basic_type::Int32:
|
||||
val.emplace<int32_t>();
|
||||
break;
|
||||
case basic_type::Int64:
|
||||
val.emplace<int64_t>();
|
||||
break;
|
||||
case basic_type::UInt8:
|
||||
val.emplace<uint8_t>();
|
||||
break;
|
||||
case basic_type::UInt16:
|
||||
val.emplace<uint16_t>();
|
||||
break;
|
||||
case basic_type::UInt32:
|
||||
val.emplace<uint32_t>();
|
||||
break;
|
||||
case basic_type::UInt64:
|
||||
val.emplace<uint64_t>();
|
||||
break;
|
||||
case basic_type::Boolean:
|
||||
val.emplace<bool>();
|
||||
break;
|
||||
case basic_type::Float:
|
||||
val.emplace<float>();
|
||||
break;
|
||||
case basic_type::Double:
|
||||
val.emplace<double>();
|
||||
break;
|
||||
case basic_type::Varchar:
|
||||
case basic_type::Text:
|
||||
val.emplace<std::string>();
|
||||
break;
|
||||
// case basic_type::type_date:
|
||||
// val.emplace<date>();
|
||||
// break;
|
||||
// case basic_type::type_time:
|
||||
// val.emplace<time>();
|
||||
// break;
|
||||
case basic_type::Blob:
|
||||
val.emplace<utils::blob>();
|
||||
break;
|
||||
default:
|
||||
val.emplace<nullptr_t>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,12 +67,15 @@ void attribute_string_writer::write_value(size_t /*pos*/, const double& x ) {
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const time& /*x*/ ) {
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::date_type_t& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::time_type_t& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x, "%F %T.%f")) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const date& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'";
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::timestamp &/*x*/) {
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t pos, const char* x ) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "matador/query/generator.hpp"
|
||||
|
||||
namespace matador::query::generator {
|
||||
column_generator::column_generator(const schema& repo, const std::string& table_name, const column_generator_options options)
|
||||
column_generator::column_generator(const schema& repo, const table* tab, const column_generator_options options)
|
||||
: repo_(std::cref(repo))
|
||||
, options_(options) {
|
||||
table_stack_.push(table_name.empty() ? std::make_shared<table>() : std::make_shared<table>(table_name));
|
||||
table_stack_.push(tab);
|
||||
}
|
||||
|
||||
void column_generator::on_revision(const char* id, uint64_t&) {
|
||||
@@ -15,9 +15,9 @@ void column_generator::push( const std::string& column_name ) {
|
||||
if (is_column_generator_option_set(options_, column_generator_options::GenerateAlias)) {
|
||||
char str[4];
|
||||
snprintf(str, 4, "c%02d", ++column_index);
|
||||
result_.emplace_back(table_stack_.top().get(), column_name, str);
|
||||
result_.emplace_back(table_stack_.top(), column_name, str);
|
||||
} else {
|
||||
result_.emplace_back(table_stack_.top().get(), column_name);
|
||||
result_.emplace_back(table_stack_.top(), column_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ query_insert_intermediate::query_insert_intermediate() {
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, const std::initializer_list<table_column> columns) {
|
||||
return into(tab, std::move(std::vector<table_column>{columns}));
|
||||
return into(tab, {columns});
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, std::vector<table_column> &&columns) {
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab, const std::vector<table_column> &columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_into_part>(tab, columns));
|
||||
return {context_};
|
||||
}
|
||||
@@ -25,7 +25,7 @@ query_into_intermediate query_insert_intermediate::into(const table &tab, const
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
}
|
||||
return into(tab, std::move(columns));
|
||||
return into(tab, columns);
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const table &tab) {
|
||||
|
||||
@@ -9,8 +9,8 @@ column_value_pair::column_value_pair(std::string name, utils::database_type valu
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
column_value_pair::column_value_pair(const table_column &col, utils::database_type value)
|
||||
: column_(col)
|
||||
column_value_pair::column_value_pair(table_column col, utils::database_type value)
|
||||
: column_(std::move(col))
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ bool operator==( const column_value_pair& lhs, const column_value_pair& rhs ) {
|
||||
}
|
||||
|
||||
bool operator!=( const column_value_pair& lhs, const column_value_pair& rhs ) {
|
||||
using namespace matador::utils;
|
||||
return !( lhs == rhs );
|
||||
}
|
||||
}
|
||||
+13
-19
@@ -70,8 +70,8 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
|
||||
// create plain tables without constraints
|
||||
for (const auto &node: repo_) {
|
||||
auto ctx = query::query::create()
|
||||
.table(node->name())
|
||||
.columns(node->info().attributes())
|
||||
.table(node.name())
|
||||
.columns(node.info().attributes())
|
||||
// .constraints(node->info().constraints())
|
||||
.compile(conn);
|
||||
|
||||
@@ -83,11 +83,11 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
|
||||
|
||||
// create primary key constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
for (const auto &cons: node.info().constraints()) {
|
||||
if (!cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = build_add_constraint_context(*node, cons, conn);
|
||||
auto ctx = build_add_constraint_context(node, cons, conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
@@ -97,11 +97,11 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
|
||||
}
|
||||
// create table constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
for (const auto &cons: node.info().constraints()) {
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = build_add_constraint_context(*node, cons, conn);
|
||||
auto ctx = build_add_constraint_context(node, cons, conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
if (auto result = conn.execute(ctx.sql); !result) {
|
||||
@@ -115,12 +115,12 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
|
||||
utils::result<void, utils::error> schema::drop(const sql::connection &conn) const {
|
||||
// drop table primary key constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
for (const auto &cons: node.info().constraints()) {
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.table(node.name())
|
||||
.drop_constraint(cons)
|
||||
.compile(conn);
|
||||
|
||||
@@ -133,12 +133,12 @@ utils::result<void, utils::error> schema::drop(const sql::connection &conn) cons
|
||||
|
||||
// drop table constraints
|
||||
for (const auto &node: repo_) {
|
||||
for (const auto &cons: node->info().constraints()) {
|
||||
for (const auto &cons: node.info().constraints()) {
|
||||
if (!cons.is_primary_key_constraint()) {
|
||||
continue;
|
||||
}
|
||||
auto ctx = query::query::alter()
|
||||
.table(node->name())
|
||||
.table(node.name())
|
||||
.drop_constraint(cons)
|
||||
.compile(conn);
|
||||
|
||||
@@ -152,7 +152,7 @@ utils::result<void, utils::error> schema::drop(const sql::connection &conn) cons
|
||||
// drop table
|
||||
for (const auto &node: repo_) {
|
||||
auto ctx = query::query::drop()
|
||||
.table(node->name())
|
||||
.table(node.name())
|
||||
.compile(conn);
|
||||
|
||||
std::cout << ctx.sql << std::endl;
|
||||
@@ -164,7 +164,7 @@ utils::result<void, utils::error> schema::drop(const sql::connection &conn) cons
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> schema::drop_table(const std::string &table_name, const sql::connection &conn) const {
|
||||
utils::result<void, utils::error> schema::drop_table(const std::string &table_name, const sql::connection &conn) {
|
||||
auto result = query::query::drop()
|
||||
.table(table_name)
|
||||
.execute(conn);
|
||||
@@ -176,17 +176,11 @@ utils::result<void, utils::error> schema::drop_table(const std::string &table_na
|
||||
}
|
||||
|
||||
utils::result<std::vector<object::attribute>, utils::error>
|
||||
schema::describe_table(const std::string &table_name, const sql::connection &conn) const {
|
||||
// if (!conn.valid()) {
|
||||
// return utils::failure(utils::error(sql::error_code::FAILURE, "Failed to acquire connection."));
|
||||
// }
|
||||
schema::describe_table(const std::string &table_name, const sql::connection &conn) {
|
||||
return utils::ok(conn.describe(table_name).release());
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> schema::table_exists(const std::string &table_name, const sql::connection &conn) const {
|
||||
// if (!c.valid()) {
|
||||
// return utils::failure(utils::error(sql::error_code::FAILURE, "Failed to acquire connection."));
|
||||
// }
|
||||
return conn.exists(repo_.name(), table_name);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,119 +1,98 @@
|
||||
#include "matador/query/value_extractor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
value_extractor::value_extractor(std::vector<utils::database_type> &values)
|
||||
: values_(values)
|
||||
{}
|
||||
: values_(values) {
|
||||
}
|
||||
|
||||
void value_extractor::on_revision(const char *, uint64_t &rev)
|
||||
{
|
||||
void value_extractor::on_revision(const char *, uint64_t &rev) {
|
||||
utils::data_type_traits<uint64_t>::bind_value(*this, 0, rev);
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, char *x, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<char*>::bind_value(*this, 0, x, attr.size());
|
||||
void value_extractor::on_attribute(const char *, char *x, const utils::field_attributes &attr) {
|
||||
utils::data_type_traits<char *>::bind_value(*this, 0, x, attr.size());
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, std::string &x, const utils::field_attributes &attr)
|
||||
{
|
||||
void value_extractor::on_attribute(const char *, std::string &x, const utils::field_attributes &attr) {
|
||||
utils::data_type_traits<std::string>::bind_value(*this, 0, x, attr.size());
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int8_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const int8_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int16_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const int16_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int32_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const int32_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int64_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const int64_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint8_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint8_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint16_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint16_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint32_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint32_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint64_t &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint64_t &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const bool &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const bool &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const float &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const float &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const double &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const double &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const time &/*x*/)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::date_type_t &/*x*/) {
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const date &/*x*/)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::time_type_t &/*x*/) {
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::timestamp &/*x*/) {
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x, size_t /*size*/)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x, size_t /*size*/) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x, size_t /*size*/)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x, size_t /*size*/) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::blob &x)
|
||||
{
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::blob &x) {
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/) {
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,7 +85,7 @@ utils::result<std::optional<record>, utils::error> statement::fetch_one() const
|
||||
return utils::ok(std::optional<record>{std::nullopt});
|
||||
}
|
||||
|
||||
return utils::ok(std::optional{*first.release()});
|
||||
return utils::ok(std::optional{*first.get()});
|
||||
}
|
||||
|
||||
void statement::reset() const {
|
||||
|
||||
Reference in New Issue
Block a user