Compare commits
No commits in common. "76263318666b9ab2094cc3eae8887b673c65a9ef" and "b9f5819be52d8f415f7c46fa316026610139451b" have entirely different histories.
7626331866
...
b9f5819be5
|
|
@ -109,9 +109,7 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
|
||||||
prototype.at(i).change_type(type);
|
prototype.at(i).change_type(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res),
|
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), prototype));
|
||||||
std::move(prototype),
|
|
||||||
context.resolver_factory));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string postgres_connection::generate_statement_name(const sql::query_context &query) {
|
std::string postgres_connection::generate_statement_name(const sql::query_context &query) {
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_st
|
||||||
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, db_, "Failed to fetch statement", query_.sql));
|
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, db_, "Failed to fetch statement", query_.sql));
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), query_.prototype, query_.resolver_factory));
|
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), query_.prototype));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<utils::attribute_writer> postgres_statement::create_binder() const {
|
std::unique_ptr<utils::attribute_writer> postgres_statement::create_binder() const {
|
||||||
|
|
|
||||||
|
|
@ -3,76 +3,92 @@
|
||||||
|
|
||||||
#include "matador/object/primary_key_resolver.hpp"
|
#include "matador/object/primary_key_resolver.hpp"
|
||||||
|
|
||||||
#include "matador/object/object_resolver.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace matador::object {
|
namespace matador::object {
|
||||||
|
|
||||||
|
class basic_object_proxy {
|
||||||
|
public:
|
||||||
|
virtual ~basic_object_proxy() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual void *get() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
class object_proxy;
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
class object_resolver {
|
||||||
|
public:
|
||||||
|
virtual ~object_resolver() = default;
|
||||||
|
|
||||||
|
virtual Type* resolve(const object_proxy<Type> &proxy) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename Type >
|
||||||
|
class static_object_resolver final : public object_resolver<Type> {
|
||||||
|
public:
|
||||||
|
static_object_resolver() = default;
|
||||||
|
explicit static_object_resolver(Type* obj)
|
||||||
|
: obj_(obj) {}
|
||||||
|
explicit static_object_resolver(std::unique_ptr<Type> obj)
|
||||||
|
: obj_(std::move(obj)) {}
|
||||||
|
|
||||||
|
Type* resolve(const object_proxy<Type> &/*proxy*/) const override {
|
||||||
|
return obj_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Type> obj_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
class object_proxy final {
|
class object_proxy final : public basic_object_proxy {
|
||||||
public:
|
public:
|
||||||
object_proxy() = default;
|
object_proxy() = default;
|
||||||
|
explicit object_proxy(Type* obj)
|
||||||
|
: resolver_(std::make_unique<static_object_resolver<Type>>(obj))
|
||||||
|
, pk_(primary_key_resolver::resolve_object(*obj).pk) {}
|
||||||
|
|
||||||
// Lazy
|
[[nodiscard]] void *get() const override { return static_cast<void*>(pointer()); }
|
||||||
object_proxy(std::weak_ptr<object_resolver<Type>> resolver, utils::identifier id)
|
|
||||||
: resolver_(resolver)
|
Type* operator->() const { return pointer(); }
|
||||||
, pk_(std::move(id)) {
|
Type& operator*() { return *pointer(); }
|
||||||
|
const Type& operator*() const { return *pointer(); }
|
||||||
|
|
||||||
|
Type* pointer() const { return resolve(); }
|
||||||
|
|
||||||
|
Type& ref() { return *pointer(); }
|
||||||
|
const Type& ref() const { return *pointer(); }
|
||||||
|
|
||||||
|
void reset(Type* obj) {
|
||||||
|
pk_ = primary_key_resolver::resolve_object(*obj).pk;
|
||||||
|
resolver_ = std::make_unique<static_object_resolver<Type>>(obj);
|
||||||
}
|
}
|
||||||
|
void reset(std::unique_ptr<Type> obj) {
|
||||||
// Eager
|
pk_ = primary_key_resolver::resolve_object(*obj).pk;
|
||||||
object_proxy(std::weak_ptr<object_resolver<Type>> resolver, std::shared_ptr<Type> obj)
|
resolver_ = std::make_unique<static_object_resolver<Type>>(std::move(obj));
|
||||||
: obj_(obj)
|
|
||||||
, resolver_(resolver)
|
|
||||||
, pk_(primary_key_resolver::resolve_object(*obj).pk) {
|
|
||||||
}
|
}
|
||||||
|
void reset(std::unique_ptr<object_resolver<Type>> &&resolver) {
|
||||||
// Transient
|
resolver_ = std::move(resolver);
|
||||||
explicit object_proxy(std::shared_ptr<Type> obj)
|
|
||||||
: obj_(obj)
|
|
||||||
, pk_(primary_key_resolver::resolve_object(*obj).pk) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] void *raw_pointer() const { return static_cast<void *>(pointer()); }
|
|
||||||
|
|
||||||
Type *operator->() { return pointer(); }
|
|
||||||
Type &operator*() { return *pointer(); }
|
|
||||||
const Type &operator*() const { return *pointer(); }
|
|
||||||
|
|
||||||
Type *pointer() const { return resolve(); }
|
|
||||||
|
|
||||||
[[nodiscard]] bool empty() const { return resolver_ == nullptr; }
|
[[nodiscard]] bool empty() const { return resolver_ == nullptr; }
|
||||||
[[nodiscard]] bool valid() const { return !empty(); }
|
[[nodiscard]] bool valid() const { return !empty(); }
|
||||||
[[nodiscard]] bool has_primary_key() const { return !pk_.is_null(); }
|
[[nodiscard]] bool has_primary_key() const { return !pk_.is_null(); }
|
||||||
[[nodiscard]] const utils::identifier &primary_key() const { return pk_; }
|
[[nodiscard]] const utils::identifier& primary_key() const { return pk_; }
|
||||||
void primary_key(const utils::identifier &pk) { pk_ = pk; }
|
void primary_key(const utils::identifier &pk) { pk_ = pk; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type* resolve() const {
|
Type* resolve() const {
|
||||||
if (obj_) {
|
return resolver_->resolve(*this);
|
||||||
return obj_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard lock(mutex_);
|
|
||||||
auto resolver = resolver_.lock();
|
|
||||||
if (!resolver) {
|
|
||||||
return nullptr;
|
|
||||||
// Todo: Add states (Detached, Attached, Transient) - if attached an no resolver is available throw runtime exception
|
|
||||||
// throw std::runtime_error("Detached proxy (session expired)");
|
|
||||||
}
|
|
||||||
|
|
||||||
const_cast<std::shared_ptr<Type>&>(obj_) = resolver->resolve(pk_);
|
|
||||||
|
|
||||||
return obj_.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Type> obj_{};
|
std::unique_ptr<object_resolver<Type>> resolver_{std::make_unique<static_object_resolver<Type>>()};
|
||||||
std::weak_ptr<object_resolver<Type>> resolver_{};
|
utils::identifier pk_{};
|
||||||
utils::identifier pk_{};
|
|
||||||
mutable std::mutex mutex_{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //OBJECT_PROXY_HPP
|
#endif //OBJECT_PROXY_HPP
|
||||||
|
|
|
||||||
|
|
@ -12,53 +12,44 @@ template <typename Type>
|
||||||
class object_ptr {
|
class object_ptr {
|
||||||
public:
|
public:
|
||||||
object_ptr()
|
object_ptr()
|
||||||
: proxy_(std::make_shared<object_proxy<Type>>()) {}
|
: ptr_(std::make_shared<object_proxy<Type>>()) {}
|
||||||
explicit object_ptr(std::shared_ptr<Type> obj)
|
explicit object_ptr(Type *obj)
|
||||||
: proxy_(std::make_shared<object_proxy<Type>>(obj)) {}
|
: ptr_(std::make_shared<object_proxy<Type>>(obj)) {}
|
||||||
explicit object_ptr(std::shared_ptr<object_proxy<Type>> obj)
|
object_ptr(const object_ptr &other) : ptr_(other.ptr_) {}
|
||||||
: proxy_(std::move(obj)) {}
|
object_ptr(object_ptr &&other) noexcept : ptr_(std::move(other.ptr_)) {}
|
||||||
object_ptr(const object_ptr &other) = default;
|
|
||||||
object_ptr(object_ptr &&other) noexcept = default;
|
|
||||||
object_ptr &operator=(const object_ptr &other) = default;
|
object_ptr &operator=(const object_ptr &other) = default;
|
||||||
object_ptr &operator=(object_ptr &&other) = default;
|
object_ptr &operator=(object_ptr &&other) = default;
|
||||||
|
|
||||||
bool operator==(const object_ptr &other) const {
|
|
||||||
return get() == other.get();
|
|
||||||
}
|
|
||||||
bool operator!=(const object_ptr &other) const { return !operator==(other); }
|
|
||||||
|
|
||||||
using value_type = Type;
|
using value_type = Type;
|
||||||
|
Type* operator->() const { return ptr_->pointer(); }
|
||||||
|
Type& operator*() { return ptr_->ref(); }
|
||||||
|
const Type& operator*() const { return ptr_->ref(); }
|
||||||
|
|
||||||
Type *operator->() const { return get(); }
|
[[nodiscard]] bool empty() const { return ptr_->pointer() == nullptr; }
|
||||||
Type &operator*() { return *get(); }
|
void reset(Type *obj) {
|
||||||
const Type &operator*() const { return *get(); }
|
ptr_->reset(obj);
|
||||||
|
|
||||||
[[nodiscard]] bool empty() const { return get() == nullptr; }
|
|
||||||
|
|
||||||
Type *get() const {
|
|
||||||
return proxy_ ? proxy_->pointer() : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() { proxy_.reset(); }
|
Type* get() const { return static_cast<Type*>(ptr_->pointer()); }
|
||||||
|
|
||||||
operator bool() { return valid(); }
|
operator bool() { return valid(); }
|
||||||
bool valid() { return proxy_ != nullptr; }
|
bool valid() { return ptr_ != nullptr; }
|
||||||
|
|
||||||
[[nodiscard]] bool has_primary_key() const { return proxy_->has_primary_key(); }
|
|
||||||
[[nodiscard]] const utils::identifier &primary_key() const { return proxy_->primary_key(); }
|
|
||||||
void primary_key(const utils::identifier &pk) { proxy_->primary_key(pk); }
|
|
||||||
|
|
||||||
|
[[nodiscard]] bool has_primary_key() const { return ptr_->has_primary_key(); }
|
||||||
|
[[nodiscard]] const utils::identifier& primary_key() const { return ptr_->primary_key(); }
|
||||||
|
void primary_key(const utils::identifier &pk) { ptr_->primary_key(pk); }
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<object_proxy<Type> > proxy_{};
|
std::shared_ptr<object_proxy<Type>> ptr_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename>
|
template<typename>
|
||||||
struct is_object_ptr : std::false_type {
|
struct is_object_ptr : std::false_type
|
||||||
};
|
{};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
struct is_object_ptr<object_ptr<Type> > : std::true_type {
|
struct is_object_ptr<object_ptr<Type>> : std::true_type
|
||||||
};
|
{};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //OBJECT_PTR_HPP
|
#endif //OBJECT_PTR_HPP
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef MATADOR_OBJECT_LOADER_HPP
|
|
||||||
#define MATADOR_OBJECT_LOADER_HPP
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <typeindex>
|
|
||||||
|
|
||||||
namespace matador::utils {
|
|
||||||
class identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace matador::object {
|
|
||||||
|
|
||||||
class abstract_object_resolver {
|
|
||||||
public:
|
|
||||||
virtual ~abstract_object_resolver() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] const std::type_index& type() const { return type_; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit abstract_object_resolver(const std::type_index& ti) : type_(ti) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
const std::type_index type_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
class object_resolver : public abstract_object_resolver {
|
|
||||||
public:
|
|
||||||
object_resolver() : abstract_object_resolver(typeid(Type)) {}
|
|
||||||
|
|
||||||
virtual std::shared_ptr<Type> resolve(const utils::identifier& id) = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //MATADOR_OBJECT_LOADER_HPP
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef MATADOR_OBJECT_RESOLVER_FACTORY_HPP
|
|
||||||
#define MATADOR_OBJECT_RESOLVER_FACTORY_HPP
|
|
||||||
|
|
||||||
#include "matador/object/object_resolver.hpp"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace matador::object {
|
|
||||||
class object_resolver_factory {
|
|
||||||
public:
|
|
||||||
virtual ~object_resolver_factory() = default;
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
std::shared_ptr<object_resolver<Type>> resolver() {
|
|
||||||
const auto res = acquire_resolver(std::type_index(typeid(Type)));
|
|
||||||
if (!res) {
|
|
||||||
return std::dynamic_pointer_cast<object_resolver<Type>>(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::dynamic_pointer_cast<object_resolver<Type>>(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::shared_ptr<abstract_object_resolver> acquire_resolver(const std::type_index &type) = 0;
|
|
||||||
virtual void register_resolver(std::shared_ptr<abstract_object_resolver> &&resolver) = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //MATADOR_OBJECT_RESOLVER_FACTORY_HPP
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "matador/object/foreign_node_completer.hpp"
|
#include "matador/object/foreign_node_completer.hpp"
|
||||||
#include "matador/object/many_to_many_relation.hpp"
|
#include "matador/object/many_to_many_relation.hpp"
|
||||||
#include "matador/object/join_columns_collector.hpp"
|
#include "matador/object/join_columns_collector.hpp"
|
||||||
|
#include "matador/object/object_ptr.hpp"
|
||||||
#include "matador/object/repository_node.hpp"
|
#include "matador/object/repository_node.hpp"
|
||||||
|
|
||||||
#include "matador/logger/log_manager.hpp"
|
#include "matador/logger/log_manager.hpp"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::orm {
|
||||||
|
|
||||||
enum class query_build_error : std::uint8_t {
|
enum class query_build_error : std::uint8_t {
|
||||||
Ok = 0,
|
Ok = 0,
|
||||||
|
|
@ -17,7 +17,7 @@ enum class query_build_error : std::uint8_t {
|
||||||
|
|
||||||
class query_builder_exception final : public std::exception {
|
class query_builder_exception final : public std::exception {
|
||||||
public:
|
public:
|
||||||
explicit query_builder_exception(query_build_error error, utils::error &&err = {});
|
explicit query_builder_exception(const query_build_error error, utils::error &&err = {});
|
||||||
|
|
||||||
[[nodiscard]] query_build_error error_type() const;
|
[[nodiscard]] query_build_error error_type() const;
|
||||||
[[nodiscard]] const utils::error &error() const;
|
[[nodiscard]] const utils::error &error() const;
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
#define QUERY_SESSION_HPP
|
#define QUERY_SESSION_HPP
|
||||||
|
|
||||||
#include "matador/orm/error_code.hpp"
|
#include "matador/orm/error_code.hpp"
|
||||||
|
#include "matador/orm/session_query_builder.hpp"
|
||||||
|
|
||||||
#include "matador/query/query_builder.hpp"
|
|
||||||
#include "matador/query/criteria.hpp"
|
#include "matador/query/criteria.hpp"
|
||||||
#include "matador/query/query.hpp"
|
#include "matador/query/query.hpp"
|
||||||
#include "matador/query/generator.hpp"
|
#include "matador/query/generator.hpp"
|
||||||
|
|
@ -18,83 +18,70 @@
|
||||||
#include "matador/object/object_ptr.hpp"
|
#include "matador/object/object_ptr.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace matador::orm {
|
namespace matador::orm {
|
||||||
|
|
||||||
utils::error make_error(error_code ec, const std::string &msg);
|
utils::error make_error(error_code ec, const std::string &msg);
|
||||||
|
|
||||||
struct session_context {
|
struct session_context {
|
||||||
session_context(utils::message_bus &bus, std::string dns, const size_t count, const size_t cache_size = 500)
|
|
||||||
: bus(bus)
|
|
||||||
, dns(std::move(dns))
|
|
||||||
, connection_count(count)
|
|
||||||
, cache_size(cache_size) {
|
|
||||||
}
|
|
||||||
utils::message_bus &bus;
|
utils::message_bus &bus;
|
||||||
std::string dns;
|
sql::connection_pool &pool;
|
||||||
size_t connection_count{};
|
|
||||||
size_t cache_size{500};
|
size_t cache_size{500};
|
||||||
std::shared_ptr<sql::producer_resolver_factory> resolver_factory = std::make_shared<sql::producer_resolver_factory>();
|
};
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
class lazy_object_resolver final : public object::object_resolver<Type> {
|
||||||
|
public:
|
||||||
|
explicit lazy_object_resolver(sql::statement &&stmt) : stmt_(std::move(stmt)) {}
|
||||||
|
|
||||||
|
Type* resolve(const object::object_proxy<Type>& proxy) const override {
|
||||||
|
return proxy.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
sql::statement stmt_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class prototype_builder final {
|
class prototype_builder final {
|
||||||
public:
|
public:
|
||||||
explicit prototype_builder(const std::unordered_map<std::string, sql::statement> &statements_per_column)
|
explicit prototype_builder(const std::unordered_map<std::string, sql::statement> &statements_per_column)
|
||||||
: statements_per_column_(statements_per_column) {
|
: statements_per_column_(statements_per_column) {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
template < typename Type >
|
||||||
Type build() const {
|
Type build() const {
|
||||||
Type obj;
|
Type obj;
|
||||||
access::process(*this, obj);
|
access::process(*this, obj);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
|
||||||
|
|
||||||
template<class V>
|
|
||||||
static void on_primary_key(const char * /*id*/, V &/*pk*/,
|
|
||||||
const utils::primary_key_attribute & /*attr*/ = utils::default_pk_attributes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < class V >
|
||||||
|
static void on_primary_key(const char * /*id*/, V &/*pk*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {}
|
||||||
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
static void on_attribute(const char * /*id*/, Type &/*obj*/,
|
static void on_attribute(const char * /*id*/, Type &/*obj*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
const utils::field_attributes &/*attr*/ = utils::null_attributes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_belongs_to(const char *id, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
void on_belongs_to(const char *id, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
||||||
const auto it = statements_per_column_.find(id);
|
const auto it = statements_per_column_.find(id);
|
||||||
if (it == statements_per_column_.end()) {
|
if (it == statements_per_column_.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_has_one(const char * /*id*/, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {
|
void on_has_one(const char * /*id*/, Pointer &/*obj*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
}
|
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
void on_has_many(const char * /*id*/, ContainerType &, const char * /*join_column*/,
|
void on_has_many(const char * /*id*/, ContainerType &, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
const utils::foreign_attributes &/*attr*/) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
void on_has_many_to_many(const char * /*id*/, ContainerType &/*cont*/, const char * /*join_column*/,
|
void on_has_many_to_many(const char * /*id*/, ContainerType &/*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
void on_has_many_to_many(const char * /*id*/, ContainerType &/*cont*/, const utils::foreign_attributes &/*attr*/) {
|
void on_has_many_to_many(const char * /*id*/, ContainerType &/*cont*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unordered_map<std::string, sql::statement> &statements_per_column_;
|
const std::unordered_map<std::string, sql::statement> &statements_per_column_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class session final : public sql::executor {
|
class session final : public sql::executor {
|
||||||
public:
|
public:
|
||||||
session(session_context &&ctx, const query::schema &scm);
|
session(session_context &&ctx, const query::schema &scm);
|
||||||
|
|
@ -108,10 +95,8 @@ public:
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
utils::result<object::object_ptr<Type>, utils::error> insert(Type *obj);
|
utils::result<object::object_ptr<Type>, utils::error> insert(Type *obj);
|
||||||
template<typename Type>
|
template< class Type, typename... Args >
|
||||||
utils::result<object::object_ptr<Type>, utils::error> insert(object::object_ptr<Type> obj);
|
utils::result<object::object_ptr<Type>, utils::error> insert(Args&&... args);
|
||||||
template<class Type, typename... Args>
|
|
||||||
utils::result<object::object_ptr<Type>, utils::error> insert(Args &&... args);
|
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
utils::result<object::object_ptr<Type>, utils::error> update(const object::object_ptr<Type> &obj);
|
utils::result<object::object_ptr<Type>, utils::error> update(const object::object_ptr<Type> &obj);
|
||||||
|
|
@ -127,40 +112,33 @@ public:
|
||||||
utils::result<void, utils::error> drop_table() const;
|
utils::result<void, utils::error> drop_table() const;
|
||||||
utils::result<void, utils::error> drop_table(const std::string &table_name) const;
|
utils::result<void, utils::error> drop_table(const std::string &table_name) const;
|
||||||
|
|
||||||
[[nodiscard]] utils::result<sql::query_result<sql::record>, utils::error>
|
[[nodiscard]] utils::result<sql::query_result<sql::record>, utils::error> fetch_all(const sql::query_context &q) const;
|
||||||
fetch_all(const sql::query_context &q) const;
|
|
||||||
[[nodiscard]] utils::result<size_t, utils::error> execute(const std::string &sql) const;
|
[[nodiscard]] utils::result<size_t, utils::error> execute(const std::string &sql) const;
|
||||||
|
|
||||||
[[nodiscard]] std::vector<object::attribute> describe_table(const std::string &table_name) const;
|
[[nodiscard]] std::vector<object::attribute> describe_table(const std::string &table_name) const;
|
||||||
[[nodiscard]] bool table_exists(const std::string &table_name) const;
|
[[nodiscard]] bool table_exists(const std::string &table_name) const;
|
||||||
|
|
||||||
[[nodiscard]] utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(
|
[[nodiscard]] utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::query_context &ctx) const override;
|
||||||
const sql::query_context &ctx) const override;
|
|
||||||
[[nodiscard]] utils::result<size_t, utils::error> execute(const sql::query_context &ctx) const override;
|
[[nodiscard]] utils::result<size_t, utils::error> execute(const sql::query_context &ctx) const override;
|
||||||
[[nodiscard]] utils::result<sql::statement, utils::error> prepare(const sql::query_context &ctx) override;
|
[[nodiscard]] utils::result<sql::statement, utils::error> prepare(const sql::query_context &ctx) override;
|
||||||
[[nodiscard]] std::string str(const sql::query_context &ctx) const override;
|
[[nodiscard]] std::string str( const sql::query_context& ctx ) const override;
|
||||||
[[nodiscard]] const sql::dialect &dialect() const override;
|
[[nodiscard]] const sql::dialect& dialect() const override;
|
||||||
[[nodiscard]] std::shared_ptr<sql::producer_resolver_factory> resolver_factory() const override;
|
|
||||||
[[nodiscard]] const class query::basic_schema &schema() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class query_select;
|
friend class query_select;
|
||||||
|
|
||||||
static query::fetchable_query build_select_query(query::entity_query_data &&data);
|
static query::fetchable_query build_select_query(entity_query_data &&data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sql::connection_pool pool_;
|
|
||||||
mutable sql::statement_cache cache_;
|
mutable sql::statement_cache cache_;
|
||||||
const sql::dialect &dialect_;
|
const sql::dialect &dialect_;
|
||||||
|
|
||||||
const query::basic_schema &schema_;
|
const query::schema& schema_;
|
||||||
mutable std::unordered_map<std::string, std::vector<object::attribute> > prototypes_;
|
mutable std::unordered_map<std::string, std::vector<object::attribute>> prototypes_;
|
||||||
std::shared_ptr<sql::producer_resolver_factory> resolver_factory_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
utils::result<object::object_ptr<Type>, utils::error> session::insert(Type *obj) {
|
utils::result<object::object_ptr<Type>, utils::error> session::insert(Type *obj) {
|
||||||
std::shared_ptr<Type> ptr(obj);
|
|
||||||
const auto it = schema_.find(typeid(Type));
|
const auto it = schema_.find(typeid(Type));
|
||||||
if (it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||||
|
|
@ -171,199 +149,171 @@ utils::result<object::object_ptr<Type>, utils::error> session::insert(Type *obj)
|
||||||
.values(query::generator::placeholders<Type>())
|
.values(query::generator::placeholders<Type>())
|
||||||
.prepare(*this);
|
.prepare(*this);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return utils::failure(res.err());
|
return utils::failure(res.err());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto insert_result = res->bind(*obj).execute(); !insert_result.is_ok()) {
|
if (const auto insert_result = res->bind(*obj).execute(); !insert_result.is_ok()) {
|
||||||
return utils::failure(insert_result.err());
|
return utils::failure(insert_result.err());
|
||||||
}
|
}
|
||||||
return utils::ok(object::object_ptr{ptr});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
utils::result<object::object_ptr<Type>, utils::error> session::insert(object::object_ptr<Type> obj) {
|
|
||||||
const auto it = schema_.find(typeid(Type));
|
|
||||||
if (it == schema_.end()) {
|
|
||||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto res = query::query::insert()
|
|
||||||
.into(it->second.name(), query::generator::columns<Type>(schema_))
|
|
||||||
.values(query::generator::placeholders<Type>())
|
|
||||||
.prepare(*this);
|
|
||||||
if (!res) {
|
|
||||||
return utils::failure(res.err());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto insert_result = res->bind(*obj).execute(); !insert_result.is_ok()) {
|
|
||||||
return utils::failure(insert_result.err());
|
|
||||||
}
|
|
||||||
return utils::ok(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Type, typename... Args>
|
|
||||||
utils::result<object::object_ptr<Type>, utils::error> session::insert(Args &&... args) {
|
|
||||||
return insert(new Type(std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
class pk_object_binder final {
|
|
||||||
public:
|
|
||||||
explicit pk_object_binder(sql::statement &stmt, const size_t position)
|
|
||||||
: stmt_(stmt)
|
|
||||||
, binding_position_(position) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
sql::statement &bind(Type &obj) {
|
|
||||||
access::process(*this, obj);
|
|
||||||
return stmt_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
void on_primary_key(const char * /*id*/, Type &x, const utils::primary_key_attribute & /*attr*/ = utils::default_pk_attributes) {
|
|
||||||
stmt_.bind(binding_position_, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
|
||||||
template<class Pointer>
|
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
|
||||||
template<class Pointer>
|
|
||||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
|
||||||
|
|
||||||
template<class ContainerType>
|
|
||||||
static void on_has_many(const char * /*id*/,
|
|
||||||
ContainerType &/*c*/,
|
|
||||||
const char * /*join_column*/,
|
|
||||||
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
|
||||||
|
|
||||||
template<class ContainerType>
|
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
|
||||||
ContainerType &/*c*/,
|
|
||||||
const char * /*join_column*/,
|
|
||||||
const char * /*inverse_join_column*/,
|
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
|
|
||||||
template<class ContainerType>
|
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
|
||||||
ContainerType &/*c*/,
|
|
||||||
const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
sql::statement &stmt_;
|
|
||||||
size_t binding_position_{0};
|
|
||||||
sql::object_pk_binder pk_binder_{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
utils::result<object::object_ptr<Type>, utils::error> session::update(const object::object_ptr<Type> &obj) {
|
|
||||||
const auto it = schema_.find(typeid(Type));
|
|
||||||
if (it == schema_.end()) {
|
|
||||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
|
||||||
}
|
|
||||||
using namespace matador::utils;
|
|
||||||
using namespace matador::query;
|
|
||||||
|
|
||||||
const auto col = table_column(it->second.node().info().primary_key_attribute()->name());
|
|
||||||
auto res = matador::query::query::update(it->second.name())
|
|
||||||
.set(generator::column_value_pairs<Type>())
|
|
||||||
.where(col == _)
|
|
||||||
.prepare(*this);
|
|
||||||
if (!res) {
|
|
||||||
return utils::failure(res.err());
|
|
||||||
}
|
|
||||||
|
|
||||||
res->bind(*obj);
|
|
||||||
pk_object_binder binder(res.value(), res->bind_pos());
|
|
||||||
if (const auto update_result = binder.bind(*obj).execute(); !update_result.is_ok()) {
|
|
||||||
return utils::failure(update_result.err());
|
|
||||||
}
|
|
||||||
return utils::ok(object::object_ptr{obj});
|
return utils::ok(object::object_ptr{obj});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Type, typename ... Args>
|
||||||
|
utils::result<object::object_ptr<Type>, utils::error> session::insert( Args&&... args ) {
|
||||||
|
return insert(new Type(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
class pk_object_binder final {
|
||||||
|
public:
|
||||||
|
explicit pk_object_binder(sql::statement &stmt, size_t position)
|
||||||
|
: stmt_(stmt)
|
||||||
|
, binding_position_(position){}
|
||||||
|
|
||||||
|
template < class Type >
|
||||||
|
sql::statement& bind(Type &obj) {
|
||||||
|
access::process(*this, obj);
|
||||||
|
return stmt_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void on_primary_key(const char * /*id*/, Type &x, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {
|
||||||
|
stmt_.bind(binding_position_, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
||||||
|
template < class Type >
|
||||||
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
|
template < class Pointer >
|
||||||
|
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
template < class Pointer >
|
||||||
|
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
|
||||||
|
template<class ContainerType>
|
||||||
|
static void on_has_many(const char * /*id*/,
|
||||||
|
ContainerType &/*c*/,
|
||||||
|
const char * /*join_column*/,
|
||||||
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
|
template<class ContainerType>
|
||||||
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
|
ContainerType &/*c*/,
|
||||||
|
const char * /*join_column*/,
|
||||||
|
const char * /*inverse_join_column*/,
|
||||||
|
const utils::foreign_attributes &/*attr*/) {}
|
||||||
|
template<class ContainerType>
|
||||||
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
|
ContainerType &/*c*/,
|
||||||
|
const utils::foreign_attributes &/*attr*/) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
sql::statement &stmt_;
|
||||||
|
size_t binding_position_{0};
|
||||||
|
sql::object_pk_binder pk_binder_;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
utils::result<void, utils::error> session::remove(const object::object_ptr<Type> &obj) {
|
utils::result<object::object_ptr<Type>, utils::error> session::update( const object::object_ptr<Type>& obj ) {
|
||||||
const auto it = schema_.find(typeid(Type));
|
const auto it = schema_.find(typeid(Type));
|
||||||
if (it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||||
}
|
}
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
using namespace matador::query;
|
using namespace matador::query;
|
||||||
|
|
||||||
const auto col = table_column(it->second.node().info().primary_key_attribute()->name());
|
const auto col = table_column(it->second.node().info().primary_key_attribute()->name());
|
||||||
auto res = matador::query::query::remove()
|
auto res = matador::query::query::update(it->second.name())
|
||||||
.from(it->second.name())
|
.set(generator::column_value_pairs<Type>())
|
||||||
.where(col == _)
|
.where(col == _)
|
||||||
.prepare(*this);
|
.prepare(*this);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return utils::failure(res.err());
|
return utils::failure(res.err());
|
||||||
}
|
}
|
||||||
|
|
||||||
pk_object_binder binder(res.value(), res->bind_pos());
|
res->bind(*obj);
|
||||||
if (const auto update_result = binder.bind(*obj).execute(); !update_result.is_ok()) {
|
pk_object_binder binder(res.value(), res->bind_pos());
|
||||||
return utils::failure(update_result.err());
|
if (const auto update_result = binder.bind(*obj).execute(); !update_result.is_ok()) {
|
||||||
}
|
return utils::failure(update_result.err());
|
||||||
return utils::ok<void>();
|
}
|
||||||
|
return utils::ok(object::object_ptr{obj});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
utils::result<void, utils::error> session::remove( const object::object_ptr<Type>& obj ) {
|
||||||
|
const auto it = schema_.find(typeid(Type));
|
||||||
|
if (it == schema_.end()) {
|
||||||
|
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||||
|
}
|
||||||
|
using namespace matador::utils;
|
||||||
|
using namespace matador::query;
|
||||||
|
|
||||||
|
const auto col = table_column(it->second.node().info().primary_key_attribute()->name());
|
||||||
|
auto res = matador::query::query::remove()
|
||||||
|
.from( it->second.name() )
|
||||||
|
.where(col == _)
|
||||||
|
.prepare(*this);
|
||||||
|
if (!res) {
|
||||||
|
return utils::failure(res.err());
|
||||||
|
}
|
||||||
|
|
||||||
|
pk_object_binder binder(res.value(), res->bind_pos());
|
||||||
|
if (const auto update_result = binder.bind(*obj).execute(); !update_result.is_ok()) {
|
||||||
|
return utils::failure(update_result.err());
|
||||||
|
}
|
||||||
|
return utils::ok<void>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type, typename PrimaryKeyType>
|
template<typename Type, typename PrimaryKeyType>
|
||||||
utils::result<object::object_ptr<Type>, utils::error> session::find(const PrimaryKeyType &pk) {
|
utils::result<object::object_ptr<Type>, utils::error> session::find(const PrimaryKeyType& pk) {
|
||||||
const auto it = schema_.find(typeid(Type));
|
const auto it = schema_.find(typeid(Type));
|
||||||
if (it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||||
}
|
}
|
||||||
const auto &info = it->second.node().info();
|
const auto& info = it->second.node().info();
|
||||||
if (!info.has_primary_key()) {
|
// if (!info) {
|
||||||
return utils::failure(make_error(error_code::NoPrimaryKey, "Type hasn't primary key."));
|
// return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||||
}
|
// }
|
||||||
|
if (!info.has_primary_key()) {
|
||||||
|
return utils::failure(make_error(error_code::NoPrimaryKey, "Type hasn't primary key."));
|
||||||
|
}
|
||||||
|
|
||||||
query::query_builder eqb(schema_, *this);
|
session_query_builder eqb(schema_, *this);
|
||||||
const query::table_column c(&it->second.table(), info.primary_key_attribute()->name());
|
const query::table_column c(&it->second.table(),info.primary_key_attribute()->name());
|
||||||
using namespace matador::query;
|
using namespace matador::query;
|
||||||
auto data = eqb.build<Type>(c == utils::_);
|
auto data = eqb.build<Type>(c == utils::_);
|
||||||
if (!data.is_ok()) {
|
if (!data.is_ok()) {
|
||||||
return utils::failure(make_error(error_code::FailedToBuildQuery,
|
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info.name() + "."));
|
||||||
"Failed to build query for type " + info.name() + "."));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto res = build_select_query(data.release()).prepare(*this);
|
auto res = build_select_query(data.release()).prepare(*this);
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return utils::failure(res.err());
|
return utils::failure(res.err());
|
||||||
}
|
}
|
||||||
auto stmt_result = res->bind(0, const_cast<PrimaryKeyType &>(pk))
|
auto stmt_result = res->bind(0, const_cast<PrimaryKeyType&>(pk)).template fetch_one<Type>();
|
||||||
.template fetch_one<Type>();
|
if (stmt_result && !stmt_result.value()) {
|
||||||
if (!stmt_result) {
|
return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info.name() + " with primary key " + std::to_string(pk) + "."));
|
||||||
return utils::failure(make_error(error_code::FailedToFindObject,
|
}
|
||||||
"Failed to find object of type " + info.name() + " with primary key " +
|
return utils::ok(object::object_ptr<Type>{ stmt_result->release() });
|
||||||
std::to_string(pk) + "."));
|
|
||||||
}
|
|
||||||
return utils::ok(*stmt_result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
utils::result<sql::query_result<Type>, utils::error> session::find(query::criteria_ptr clause) {
|
utils::result<sql::query_result<Type>, utils::error> session::find(query::criteria_ptr clause) {
|
||||||
const auto it = schema_.find(typeid(Type));
|
const auto it = schema_.find(typeid(Type));
|
||||||
if (it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||||
}
|
}
|
||||||
|
|
||||||
query::query_builder eqb(schema_, *this);
|
session_query_builder eqb(schema_, *this);
|
||||||
auto data = eqb.build<Type>(std::move(clause));
|
auto data = eqb.build<Type>(std::move(clause));
|
||||||
if (!data.is_ok()) {
|
if (!data.is_ok()) {
|
||||||
return utils::failure(make_error(error_code::FailedToBuildQuery,
|
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + it->second.name() + "."));
|
||||||
"Failed to build query for type " + it->second.name() + "."));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto result = build_select_query(data.release()).prepare(*this);
|
auto result = build_select_query(data.release()).prepare(*this);
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result->template fetch<Type>();
|
return result->template fetch<Type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
#ifndef QUERY_ENTITY_QUERY_BUILDER_HPP
|
#ifndef QUERY_ENTITY_QUERY_BUILDER_HPP
|
||||||
#define QUERY_ENTITY_QUERY_BUILDER_HPP
|
#define QUERY_ENTITY_QUERY_BUILDER_HPP
|
||||||
|
|
||||||
#include "matador/query/query_builder_exception.hpp"
|
#include "matador/orm/query_builder_exception.hpp"
|
||||||
|
|
||||||
#include "matador/query/criteria.hpp"
|
#include "matador/query/criteria.hpp"
|
||||||
#include "matador/query/query.hpp"
|
#include "matador/query/query.hpp"
|
||||||
|
#include "matador/query/schema.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/executor.hpp"
|
||||||
#include "matador/sql/statement.hpp"
|
#include "matador/sql/statement.hpp"
|
||||||
|
|
||||||
#include "matador/object/join_columns_collector.hpp"
|
#include "matador/object/join_columns_collector.hpp"
|
||||||
|
|
@ -19,45 +21,45 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::orm {
|
||||||
|
|
||||||
struct entity_query_data {
|
struct entity_query_data {
|
||||||
const table* root_table{nullptr};
|
const query::table* root_table{nullptr};
|
||||||
std::string pk_column_name{};
|
std::string pk_column_name{};
|
||||||
std::vector<table_column> columns{};
|
std::vector<query::table_column> columns{};
|
||||||
std::unordered_map<std::string, sql::statement> lazy_loading_statements{};
|
std::unordered_map<std::string, sql::statement> lazy_loading_statements{};
|
||||||
std::vector<join_data> joins{};
|
std::vector<query::join_data> joins{};
|
||||||
criteria_ptr where_clause{};
|
query::criteria_ptr where_clause{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class criteria_transformer final : public criteria_visitor {
|
class criteria_transformer final : public query::criteria_visitor {
|
||||||
public:
|
public:
|
||||||
criteria_transformer(const basic_schema &repo, const std::unordered_map<std::string, table>& tables_by_name);
|
criteria_transformer(const query::schema &repo, const std::unordered_map<std::string, query::table>& tables_by_name);
|
||||||
void visit( const between_criteria& node ) override;
|
void visit( const query::between_criteria& node ) override;
|
||||||
void visit( const binary_criteria& node ) override;
|
void visit( const query::binary_criteria& node ) override;
|
||||||
void visit( const binary_column_criteria& node ) override;
|
void visit( const query::binary_column_criteria& node ) override;
|
||||||
void visit( const collection_criteria& node ) override;
|
void visit( const query::collection_criteria& node ) override;
|
||||||
void visit( const collection_query_criteria& node ) override;
|
void visit( const query::collection_query_criteria& node ) override;
|
||||||
void visit( const like_criteria& node ) override;
|
void visit( const query::like_criteria& node ) override;
|
||||||
void visit( const logical_criteria& node ) override;
|
void visit( const query::logical_criteria& node ) override;
|
||||||
void visit( const not_criteria& node ) override;
|
void visit( const query::not_criteria& node ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_criteria_column(const abstract_column_criteria& node) const;
|
void update_criteria_column(const query::abstract_column_criteria& node) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const basic_schema &repo_;
|
const query::schema &repo_;
|
||||||
const std::unordered_map<std::string, table>& tables_by_name_;
|
const std::unordered_map<std::string, query::table>& tables_by_name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_builder final {
|
class session_query_builder final {
|
||||||
public:
|
public:
|
||||||
query_builder(const basic_schema &scm, sql::executor &exec)
|
session_query_builder(const query::schema &scm, sql::executor &exec)
|
||||||
: schema_(scm)
|
: schema_(scm)
|
||||||
, executor_(exec){}
|
, executor_(exec){}
|
||||||
|
|
||||||
template<class EntityType>
|
template<class EntityType>
|
||||||
utils::result<entity_query_data, query_build_error> build(criteria_ptr clause = {}) {
|
utils::result<entity_query_data, query_build_error> build(query::criteria_ptr clause = {}) {
|
||||||
const auto it = schema_.find(typeid(EntityType));
|
const auto it = schema_.find(typeid(EntityType));
|
||||||
if (it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
return utils::failure(query_build_error::UnknownType);
|
return utils::failure(query_build_error::UnknownType);
|
||||||
|
|
@ -142,8 +144,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
append_join(
|
append_join(
|
||||||
table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
query::table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
||||||
table_column{&next->second, join_column}
|
query::table_column{&next->second, join_column}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -157,7 +159,7 @@ public:
|
||||||
// if (next != processed_tables_.end()) {
|
// if (next != processed_tables_.end()) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// table_info_stack_.push({*result, std::make_shared<table>(info.name(), build_alias('t', ++table_index))});
|
// table_info_stack_.push({*result, std::make_shared<query::table>(info.name(), build_alias('t', ++table_index))});
|
||||||
// next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
// next = processed_tables_.insert({info.name(), table_info_stack_.top().table}).first;
|
||||||
// typename ContainerType::value_type::value_type obj;
|
// typename ContainerType::value_type::value_type obj;
|
||||||
// access::process(*this , obj);
|
// access::process(*this , obj);
|
||||||
|
|
@ -168,8 +170,8 @@ public:
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// append_join(
|
// append_join(
|
||||||
// column{table_info_stack_.top().table.get(), table_info_stack_.top().info.get().primary_key_attribute()->name()},
|
// query::column{table_info_stack_.top().table.get(), table_info_stack_.top().info.get().primary_key_attribute()->name()},
|
||||||
// column{next->second.get(), join_column}
|
// query::column{next->second.get(), join_column}
|
||||||
// );
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,12 +210,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
append_join(
|
append_join(
|
||||||
table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
query::table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
||||||
table_column{&relation->second, join_column}
|
query::table_column{&relation->second, join_column}
|
||||||
);
|
);
|
||||||
append_join(
|
append_join(
|
||||||
table_column{&relation->second, inverse_join_column},
|
query::table_column{&relation->second, inverse_join_column},
|
||||||
table_column{&next->second, result->second.node().info().primary_key_attribute()->name()}
|
query::table_column{&next->second, result->second.node().info().primary_key_attribute()->name()}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,12 +257,12 @@ public:
|
||||||
const auto join_columns = join_columns_collector_.collect<typename ContainerType::value_type::value_type>();
|
const auto join_columns = join_columns_collector_.collect<typename ContainerType::value_type::value_type>();
|
||||||
|
|
||||||
append_join(
|
append_join(
|
||||||
table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
query::table_column{&table_info_stack_.top().table, table_info_stack_.top().info.primary_key_attribute()->name()},
|
||||||
table_column{&relation->second, join_columns.inverse_join_column}
|
query::table_column{&relation->second, join_columns.inverse_join_column}
|
||||||
);
|
);
|
||||||
append_join(
|
append_join(
|
||||||
table_column{&relation->second, join_columns.join_column},
|
query::table_column{&relation->second, join_columns.join_column},
|
||||||
table_column{&next->second, result->second.node().info().primary_key_attribute()->name()}
|
query::table_column{&next->second, result->second.node().info().primary_key_attribute()->name()}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,17 +272,17 @@ private:
|
||||||
void push(const std::string &column_name);
|
void push(const std::string &column_name);
|
||||||
static std::string build_alias(char prefix, unsigned int count);
|
static std::string build_alias(char prefix, unsigned int count);
|
||||||
[[nodiscard]] bool is_root_entity() const;
|
[[nodiscard]] bool is_root_entity() const;
|
||||||
void append_join(const table_column &left, const table_column &right);
|
void append_join(const query::table_column &left, const query::table_column &right);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct table_info {
|
struct table_info {
|
||||||
const object::basic_object_info &info;
|
const object::basic_object_info &info;
|
||||||
class table table;
|
query::table table;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::stack<table_info> table_info_stack_{};
|
std::stack<table_info> table_info_stack_{};
|
||||||
std::unordered_map<std::string, table> processed_tables_{};
|
std::unordered_map<std::string, query::table> processed_tables_{};
|
||||||
const basic_schema &schema_;
|
const query::schema &schema_;
|
||||||
entity_query_data entity_query_data_{};
|
entity_query_data entity_query_data_{};
|
||||||
unsigned int column_index{0};
|
unsigned int column_index{0};
|
||||||
unsigned int table_index{0};
|
unsigned int table_index{0};
|
||||||
|
|
@ -289,7 +291,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void query_builder::on_foreign_object(const char *id, Pointer &, const utils::foreign_attributes &attr) {
|
void session_query_builder::on_foreign_object(const char *id, Pointer &, const utils::foreign_attributes &attr) {
|
||||||
const auto it = schema_.find(typeid(typename Pointer::value_type));
|
const auto it = schema_.find(typeid(typename Pointer::value_type));
|
||||||
if (it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
throw query_builder_exception{query_build_error::UnknownType};
|
throw query_builder_exception{query_build_error::UnknownType};
|
||||||
|
|
@ -313,15 +315,15 @@ void query_builder::on_foreign_object(const char *id, Pointer &, const utils::fo
|
||||||
table_info_stack_.pop();
|
table_info_stack_.pop();
|
||||||
|
|
||||||
append_join(
|
append_join(
|
||||||
table_column{&table_info_stack_.top().table, id},
|
query::table_column{&table_info_stack_.top().table, id},
|
||||||
table_column{&next->second, info.primary_key_attribute()->name()}
|
query::table_column{&next->second, info.primary_key_attribute()->name()}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
push(id);
|
push(id);
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
using namespace matador::query;
|
using namespace matador::query;
|
||||||
// create select query
|
// create select query
|
||||||
auto result = query::query::select(generator::columns<typename Pointer::value_type>(schema_, foreign_table, generator::column_generator_options::ForceLazy))
|
auto result = matador::query::query::select(generator::columns<typename Pointer::value_type>(schema_, foreign_table, generator::column_generator_options::ForceLazy))
|
||||||
.from(foreign_table)
|
.from(foreign_table)
|
||||||
.where(table_column(&foreign_table, info.primary_key_attribute()->name(), "") == _)
|
.where(table_column(&foreign_table, info.primary_key_attribute()->name(), "") == _)
|
||||||
.prepare(executor_);
|
.prepare(executor_);
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
#ifndef MATADOR_BASIC_SCHEMA_HPP
|
|
||||||
#define MATADOR_BASIC_SCHEMA_HPP
|
|
||||||
|
|
||||||
#include "matador/object/repository.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/producer_resolver_factory.hpp"
|
|
||||||
|
|
||||||
#include "matador/query/table.hpp"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <memory>
|
|
||||||
#include <typeindex>
|
|
||||||
|
|
||||||
namespace matador::query {
|
|
||||||
class schema_node final {
|
|
||||||
public:
|
|
||||||
schema_node(class table tab, const object::repository_node& node);
|
|
||||||
|
|
||||||
[[nodiscard]] const std::string& name() const;
|
|
||||||
[[nodiscard]] const class table& table() const;
|
|
||||||
[[nodiscard]] const object::repository_node& node() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class table table_;
|
|
||||||
const object::repository_node& node_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class basic_schema {
|
|
||||||
public:
|
|
||||||
using schema_node_map = std::unordered_map<std::type_index, schema_node>;
|
|
||||||
using iterator = std::unordered_map<std::type_index, schema_node>::iterator;
|
|
||||||
using const_iterator = std::unordered_map<std::type_index, schema_node>::const_iterator;
|
|
||||||
|
|
||||||
basic_schema();
|
|
||||||
explicit basic_schema(const std::string &name);
|
|
||||||
|
|
||||||
iterator begin();
|
|
||||||
iterator end();
|
|
||||||
[[nodiscard]] const_iterator begin() const;
|
|
||||||
[[nodiscard]] const_iterator end() const;
|
|
||||||
|
|
||||||
[[nodiscard]] size_t size() const;
|
|
||||||
[[nodiscard]] bool empty() const;
|
|
||||||
|
|
||||||
iterator find(const std::type_index& ti);
|
|
||||||
iterator find(const std::string& name);
|
|
||||||
|
|
||||||
[[nodiscard]] const_iterator find(const std::type_index& ti) const;
|
|
||||||
[[nodiscard]] const_iterator find(const std::string& name) const;
|
|
||||||
|
|
||||||
[[nodiscard]] bool contains(const std::type_index &index) const;
|
|
||||||
|
|
||||||
void initialize_executor(sql::executor &exec) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
template<typename Type>
|
|
||||||
friend class schema_observer;
|
|
||||||
|
|
||||||
object::repository repo_;
|
|
||||||
std::unordered_map<std::type_index, schema_node> schema_nodes_;
|
|
||||||
std::unordered_map<std::type_index, std::unique_ptr<sql::resolver_producer>> resolver_producers_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //MATADOR_BASIC_SCHEMA_HPP
|
|
||||||
|
|
@ -7,9 +7,6 @@
|
||||||
#include "matador/utils/placeholder.hpp"
|
#include "matador/utils/placeholder.hpp"
|
||||||
#include "matador/utils/value.hpp"
|
#include "matador/utils/value.hpp"
|
||||||
|
|
||||||
namespace matador::utils {
|
|
||||||
class identifier;
|
|
||||||
}
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
struct query_context;
|
struct query_context;
|
||||||
}
|
}
|
||||||
|
|
@ -60,9 +57,6 @@ criteria_ptr operator>=(const table_column &col, utils::placeholder p);
|
||||||
criteria_ptr operator<(const table_column &col, utils::placeholder p);
|
criteria_ptr operator<(const table_column &col, utils::placeholder p);
|
||||||
criteria_ptr operator<=(const table_column &col, utils::placeholder p);
|
criteria_ptr operator<=(const table_column &col, utils::placeholder p);
|
||||||
|
|
||||||
criteria_ptr operator==(const table_column &col, const utils::identifier &id);
|
|
||||||
criteria_ptr operator!=(const table_column &col, const utils::identifier &id);
|
|
||||||
|
|
||||||
criteria_ptr operator&&(criteria_ptr left, criteria_ptr right);
|
criteria_ptr operator&&(criteria_ptr left, criteria_ptr right);
|
||||||
|
|
||||||
criteria_ptr operator||(criteria_ptr left, criteria_ptr right);
|
criteria_ptr operator||(criteria_ptr left, criteria_ptr right);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include "matador/query/internal/column_value_pair.hpp"
|
#include "matador/query/internal/column_value_pair.hpp"
|
||||||
|
|
||||||
#include "matador/query/table.hpp"
|
#include "matador/query/table.hpp"
|
||||||
#include "matador/query/basic_schema.hpp"
|
#include "matador/query/schema.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ constexpr auto default_column_generator_options = column_generator_options::Forc
|
||||||
|
|
||||||
class column_generator {
|
class column_generator {
|
||||||
public:
|
public:
|
||||||
explicit column_generator(const basic_schema &repo,
|
explicit column_generator(const schema &repo,
|
||||||
const table* tab,
|
const table* tab,
|
||||||
column_generator_options options = default_column_generator_options);
|
column_generator_options options = default_column_generator_options);
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ private:
|
||||||
void push(const std::string &column_name);
|
void push(const std::string &column_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const basic_schema &repo_;
|
const schema &repo_;
|
||||||
std::vector<table_column> result_;
|
std::vector<table_column> result_;
|
||||||
std::stack<const table*> table_stack_;
|
std::stack<const table*> table_stack_;
|
||||||
std::unordered_set<std::string> seen_tables;
|
std::unordered_set<std::string> seen_tables;
|
||||||
|
|
@ -289,7 +289,7 @@ std::vector<internal::column_value_pair> column_value_pairs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::vector<table_column> columns(const basic_schema &repo,
|
std::vector<table_column> columns(const schema &repo,
|
||||||
const table &tab,
|
const table &tab,
|
||||||
const column_generator_options options = default_column_generator_options) {
|
const column_generator_options options = default_column_generator_options) {
|
||||||
column_generator generator(repo, &tab, options);
|
column_generator generator(repo, &tab, options);
|
||||||
|
|
@ -297,7 +297,7 @@ std::vector<table_column> columns(const basic_schema &repo,
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::vector<table_column> columns(const basic_schema &repo,
|
std::vector<table_column> columns(const schema &repo,
|
||||||
const column_generator_options options = default_column_generator_options) {
|
const column_generator_options options = default_column_generator_options) {
|
||||||
const auto it = repo.find(typeid(Type));
|
const auto it = repo.find(typeid(Type));
|
||||||
if (it == repo.end()) {
|
if (it == repo.end()) {
|
||||||
|
|
@ -309,7 +309,7 @@ std::vector<table_column> columns(const basic_schema &repo,
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::vector<table_column> columns(const Type &obj,
|
std::vector<table_column> columns(const Type &obj,
|
||||||
const basic_schema &repo,
|
const schema &repo,
|
||||||
const column_generator_options options = default_column_generator_options) {
|
const column_generator_options options = default_column_generator_options) {
|
||||||
const auto it = repo.find(typeid(Type));
|
const auto it = repo.find(typeid(Type));
|
||||||
if (it == repo.end()) {
|
if (it == repo.end()) {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,13 @@
|
||||||
|
|
||||||
#include "query_intermediate.hpp"
|
#include "query_intermediate.hpp"
|
||||||
|
|
||||||
#include "matador/query/query_compiler.hpp"
|
#include "../query_compiler.hpp"
|
||||||
#include "matador/sql/executor.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/query_result.hpp"
|
#include "../../sql/query_result.hpp"
|
||||||
#include "matador/sql/query_record_result.hpp"
|
#include "../../sql/record.hpp"
|
||||||
#include "matador/sql/record.hpp"
|
|
||||||
|
|
||||||
#include "matador/utils/error.hpp"
|
#include "../../utils/error.hpp"
|
||||||
#include "matador/utils/result.hpp"
|
#include "../../utils/result.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
class executor;
|
class executor;
|
||||||
|
|
@ -34,15 +32,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto prototype = result.value()->prototype();
|
const auto prototype = result.value()->prototype();
|
||||||
auto resolver = exec.resolver_factory()->resolver<Type>();
|
return utils::ok(sql::query_result<Type>(result.release(), [prototype] {
|
||||||
return utils::ok(sql::query_result<Type>(result.release(), resolver, [prototype] {
|
|
||||||
return sql::detail::create_prototype<Type>(prototype);
|
return sql::detail::create_prototype<Type>(prototype);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
[[nodiscard]] utils::result<sql::query_result<sql::record>, utils::error> fetch_all(const sql::executor &exec) const;
|
[[nodiscard]] utils::result<sql::query_result<sql::record>, utils::error> fetch_all(const sql::executor &exec) const;
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
utils::result<object::object_ptr<Type>, utils::error> fetch_one(sql::executor &exec)
|
utils::result<std::unique_ptr<Type>, utils::error> fetch_one(const sql::executor &exec)
|
||||||
{
|
{
|
||||||
auto result = fetch(exec);
|
auto result = fetch(exec);
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
|
|
@ -50,16 +47,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto prototype = result.value()->prototype();
|
const auto prototype = result.value()->prototype();
|
||||||
auto resolver = exec.resolver_factory()->resolver<Type>();
|
auto objects = sql::query_result<Type>(result.release(), [prototype] {
|
||||||
auto objects = sql::query_result<Type>(result.release(), resolver, [prototype] {
|
|
||||||
return sql::detail::create_prototype<Type>(prototype);
|
return sql::detail::create_prototype<Type>(prototype);
|
||||||
});
|
});
|
||||||
auto first = objects.begin();
|
auto first = objects.begin();
|
||||||
if (first == objects.end()) {
|
if (first == objects.end()) {
|
||||||
return utils::ok(object::object_ptr<Type>{});
|
return utils::ok(std::unique_ptr<Type>{nullptr});
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok(first.optr());
|
return utils::ok(std::unique_ptr<Type>{first.release()});
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] utils::result<std::optional<sql::record>, utils::error> fetch_one(const sql::executor &exec) const;
|
[[nodiscard]] utils::result<std::optional<sql::record>, utils::error> fetch_one(const sql::executor &exec) const;
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
#include "matador/query/intermediates/query_intermediate.hpp"
|
#include "matador/query/intermediates/query_intermediate.hpp"
|
||||||
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
||||||
|
#include "matador/query/schema.hpp"
|
||||||
#include "matador/query/generator.hpp"
|
#include "matador/query/generator.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
class schema;
|
|
||||||
|
|
||||||
class query_insert_intermediate : public query_intermediate {
|
class query_insert_intermediate : public query_intermediate {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,13 @@
|
||||||
#include "matador/query/query_intermediates.hpp"
|
#include "matador/query/query_intermediates.hpp"
|
||||||
|
|
||||||
#include "matador/query/generator.hpp"
|
#include "matador/query/generator.hpp"
|
||||||
|
#include "matador/query/schema.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
class connection;
|
class connection;
|
||||||
}
|
}
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
class schema;
|
|
||||||
table_column alias(const std::string &column, const std::string &as);
|
table_column alias(const std::string &column, const std::string &as);
|
||||||
table_column alias(table_column &&col, const std::string &as);
|
table_column alias(table_column &&col, const std::string &as);
|
||||||
table_column count(const std::string &column);
|
table_column count(const std::string &column);
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
#ifndef MATADOR_QUERY_OBJECT_LOADER_HPP
|
|
||||||
#define MATADOR_QUERY_OBJECT_LOADER_HPP
|
|
||||||
|
|
||||||
#include "matador/sql/internal/identifier_statement_binder.hpp"
|
|
||||||
#include "matador/sql/statement.hpp"
|
|
||||||
|
|
||||||
#include "matador/object/object_resolver.hpp"
|
|
||||||
|
|
||||||
#include "matador/query/table.hpp"
|
|
||||||
#include "matador/query/query_builder.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
class executor;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace matador::query {
|
|
||||||
template<typename Type>
|
|
||||||
class query_object_resolver : public object::object_resolver<Type> {
|
|
||||||
public:
|
|
||||||
explicit query_object_resolver(const basic_schema &repo, sql::executor& exec, const table &tab, std::string pk_name)
|
|
||||||
: executor_(exec)
|
|
||||||
, schema_(repo)
|
|
||||||
, table_(tab)
|
|
||||||
, pk_name_(std::move(pk_name)) {}
|
|
||||||
|
|
||||||
std::shared_ptr<Type> resolve(const utils::identifier &id) override;
|
|
||||||
protected:
|
|
||||||
sql::executor& executor_;
|
|
||||||
const basic_schema &schema_;
|
|
||||||
const table &table_;
|
|
||||||
std::string pk_name_;
|
|
||||||
std::type_index index{typeid(Type)};
|
|
||||||
};
|
|
||||||
|
|
||||||
utils::result<sql::statement, utils::error> prepare_statement(sql::executor& exec, entity_query_data &&data);
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
std::shared_ptr<Type> query_object_resolver<Type>::resolve(const utils::identifier &id) {
|
|
||||||
query_builder qb(schema_, executor_);
|
|
||||||
const auto *pk_column = table_[pk_name_];
|
|
||||||
auto builder_result = qb.build<Type>(*pk_column == utils::_);
|
|
||||||
|
|
||||||
if (!builder_result) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto stmt = prepare_statement(executor_, builder_result.release());
|
|
||||||
if (!stmt) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
sql::identifier_statement_binder binder(*stmt);
|
|
||||||
binder.bind(id);
|
|
||||||
|
|
||||||
auto result = stmt->template fetch_one_raw<Type>();
|
|
||||||
if (!result) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return *result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //MATADOR_QUERY_OBJECT_LOADER_HPP
|
|
||||||
|
|
@ -2,41 +2,19 @@
|
||||||
#define MATADOR_SCHEMA_HPP
|
#define MATADOR_SCHEMA_HPP
|
||||||
|
|
||||||
#include "matador/object/observer.hpp"
|
#include "matador/object/observer.hpp"
|
||||||
|
#include "matador/object/repository.hpp"
|
||||||
|
|
||||||
#include "matador/sql/query_context.hpp"
|
#include "matador/sql/query_context.hpp"
|
||||||
#include "matador/sql/internal/resolver_producer.hpp"
|
|
||||||
|
|
||||||
#include "matador/query/query_object_resolver.hpp"
|
#include "matador/query/table.hpp"
|
||||||
#include "matador/query/basic_schema.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
class connection_pool;
|
class connection_pool;
|
||||||
class connection;
|
class connection;
|
||||||
class executor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
class query_resolver_producer : public sql::resolver_producer {
|
|
||||||
public:
|
|
||||||
query_resolver_producer() = default;
|
|
||||||
query_resolver_producer(const basic_schema& repo, const table& tab, std::string pk_name)
|
|
||||||
: resolver_producer(typeid(Type))
|
|
||||||
, repo_(repo)
|
|
||||||
, table_(tab)
|
|
||||||
, pk_name_(std::move(pk_name)) {}
|
|
||||||
|
|
||||||
std::shared_ptr<object::abstract_object_resolver> produce(sql::executor &exec) override {
|
|
||||||
return std::make_shared<query_object_resolver<Type>>(repo_, exec, table_, std::move(pk_name_));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const basic_schema& repo_;
|
|
||||||
const table& table_;
|
|
||||||
std::string pk_name_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class schema;
|
class schema;
|
||||||
|
|
||||||
using schema_ref = std::reference_wrapper<schema>;
|
using schema_ref = std::reference_wrapper<schema>;
|
||||||
|
|
@ -74,14 +52,25 @@ private:
|
||||||
schema& schema_;
|
schema& schema_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class schema final : public basic_schema {
|
class schema_node final {
|
||||||
public:
|
public:
|
||||||
using basic_schema::basic_schema;
|
schema_node(class table tab, const object::repository_node& node);
|
||||||
using basic_schema::iterator;
|
|
||||||
using basic_schema::const_iterator;
|
|
||||||
using basic_schema::contains;
|
|
||||||
using basic_schema::find;
|
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& name() const;
|
||||||
|
[[nodiscard]] const class table& table() const;
|
||||||
|
[[nodiscard]] const object::repository_node& node() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class table table_;
|
||||||
|
const object::repository_node& node_;
|
||||||
|
};
|
||||||
|
class schema final {
|
||||||
|
public:
|
||||||
|
using iterator = std::unordered_map<std::type_index, schema_node>::iterator;
|
||||||
|
using const_iterator = std::unordered_map<std::type_index, schema_node>::const_iterator;
|
||||||
|
|
||||||
|
schema() = default;
|
||||||
|
explicit schema(const std::string &name);
|
||||||
|
|
||||||
template<typename Type, typename... Observers>
|
template<typename Type, typename... Observers>
|
||||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &name, Observers&&... observers) {
|
||||||
|
|
@ -108,15 +97,28 @@ public:
|
||||||
[[nodiscard]] static utils::result<std::vector<object::attribute>, utils::error> describe_table(const std::string &table_name, const sql::connection &conn) ;
|
[[nodiscard]] static utils::result<std::vector<object::attribute>, utils::error> describe_table(const std::string &table_name, const sql::connection &conn) ;
|
||||||
[[nodiscard]] utils::result<bool, utils::error> table_exists(const std::string &table_name, const sql::connection &conn) const;
|
[[nodiscard]] utils::result<bool, utils::error> table_exists(const std::string &table_name, const sql::connection &conn) const;
|
||||||
|
|
||||||
template<typename Type>
|
iterator begin();
|
||||||
iterator find() { return basic_schema::find(typeid(Type)); }
|
iterator end();
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
[[nodiscard]] size_t size() const;
|
||||||
|
[[nodiscard]] bool empty() const;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
const_iterator find() const { return basic_schema::find(typeid(Type)); }
|
iterator find() { return find(typeid(Type)); }
|
||||||
|
iterator find(const std::type_index& ti);
|
||||||
|
iterator find(const std::string& name);
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
const_iterator find() const { return find(typeid(Type)); }
|
||||||
|
const_iterator find(const std::type_index& ti) const;
|
||||||
|
const_iterator find(const std::string& name) const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool contains(const std::type_index &index) const;
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
[[nodiscard]] bool contains() const {
|
[[nodiscard]] bool contains() const {
|
||||||
return basic_schema::contains(std::type_index(typeid(Type)));
|
return contains(std::type_index(typeid(Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const object::repository &repo() const { return repo_; }
|
const object::repository &repo() const { return repo_; }
|
||||||
|
|
@ -128,11 +130,14 @@ private:
|
||||||
[[nodiscard]] static sql::query_context build_add_constraint_context(const object::repository_node& node, const object::restriction& cons, const sql::connection &conn) ;
|
[[nodiscard]] static sql::query_context build_add_constraint_context(const object::repository_node& node, const object::restriction& cons, const sql::connection &conn) ;
|
||||||
[[nodiscard]] static sql::query_context build_drop_constraint_context(const object::repository_node& node, const object::restriction& cons, const sql::connection &conn) ;
|
[[nodiscard]] static sql::query_context build_drop_constraint_context(const object::repository_node& node, const object::restriction& cons, const sql::connection &conn) ;
|
||||||
|
|
||||||
iterator insert_table(const std::type_index& ti, const object::repository_node &node);
|
void insert_table(const std::type_index& ti, const object::repository_node &node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
friend class schema_observer;
|
friend class schema_observer;
|
||||||
|
|
||||||
|
object::repository repo_;
|
||||||
|
std::unordered_map<std::type_index, schema_node> schema_nodes_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
|
@ -146,12 +151,7 @@ utils::result<void, utils::error> schema::drop_table(const sql::connection &conn
|
||||||
}
|
}
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
void schema_observer<Type>::on_attach(const object::repository_node &node, const Type &/*prototype*/) const {
|
void schema_observer<Type>::on_attach(const object::repository_node &node, const Type &/*prototype*/) const {
|
||||||
const auto it = schema_.insert_table(typeid(Type), node);
|
schema_.insert_table(typeid(Type), node);
|
||||||
|
|
||||||
if (it->second.node().info().has_primary_key()) {
|
|
||||||
auto producer = std::make_unique<query_resolver_producer<Type>>(schema_, it->second.table(), it->second.node().info().primary_key_attribute()->name());
|
|
||||||
schema_.resolver_producers_[typeid(Type)] = std::move(producer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
#include "matador/utils/basic_types.hpp"
|
#include "matador/utils/basic_types.hpp"
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,7 @@ public:
|
||||||
* @param info The database connection info data
|
* @param info The database connection info data
|
||||||
* @param sql_logger The logging handler
|
* @param sql_logger The logging handler
|
||||||
*/
|
*/
|
||||||
explicit connection(const connection_info& info, logger_ptr sql_logger = null_logger);
|
explicit connection(const connection_info& info, const logger_ptr &sql_logger = null_logger);
|
||||||
explicit connection(const connection_info& info, std::shared_ptr<producer_resolver_factory> resolver_factory, logger_ptr sql_logger = null_logger);
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a database connection from a connection string.
|
* @brief Creates a database connection from a connection string.
|
||||||
*
|
*
|
||||||
|
|
@ -34,7 +33,6 @@ public:
|
||||||
* @param sql_logger The logging handler
|
* @param sql_logger The logging handler
|
||||||
*/
|
*/
|
||||||
explicit connection(const std::string &dns, const logger_ptr &sql_logger = null_logger);
|
explicit connection(const std::string &dns, const logger_ptr &sql_logger = null_logger);
|
||||||
explicit connection(const std::string &dns, std::shared_ptr<producer_resolver_factory> resolver_factory, const logger_ptr &sql_logger = null_logger);
|
|
||||||
/**
|
/**
|
||||||
* Copies a given connection
|
* Copies a given connection
|
||||||
*
|
*
|
||||||
|
|
@ -140,7 +138,6 @@ public:
|
||||||
[[nodiscard]] std::string str( const query_context& ctx ) const override;
|
[[nodiscard]] std::string str( const query_context& ctx ) const override;
|
||||||
|
|
||||||
[[nodiscard]] const class dialect &dialect() const override;
|
[[nodiscard]] const class dialect &dialect() const override;
|
||||||
[[nodiscard]] std::shared_ptr<producer_resolver_factory> resolver_factory() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] utils::result<std::unique_ptr<statement_impl>, utils::error> perform_prepare(const query_context &ctx) const;
|
[[nodiscard]] utils::result<std::unique_ptr<statement_impl>, utils::error> perform_prepare(const query_context &ctx) const;
|
||||||
|
|
@ -152,7 +149,6 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<connection_impl> connection_;
|
std::unique_ptr<connection_impl> connection_;
|
||||||
std::shared_ptr<abstract_sql_logger> logger_ = std::make_shared<null_sql_logger>();
|
std::shared_ptr<abstract_sql_logger> logger_ = std::make_shared<null_sql_logger>();
|
||||||
std::shared_ptr<producer_resolver_factory> resolver_factory_ = std::make_shared<producer_resolver_factory>();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ private:
|
||||||
class connection_pool {
|
class connection_pool {
|
||||||
public:
|
public:
|
||||||
connection_pool(const std::string &dns, size_t count);
|
connection_pool(const std::string &dns, size_t count);
|
||||||
connection_pool(const std::string &dns, size_t count, std::function<connection(const connection_info &)> &&connection_creator);
|
|
||||||
|
|
||||||
connection_ptr acquire();
|
connection_ptr acquire();
|
||||||
connection_ptr try_acquire();
|
connection_ptr try_acquire();
|
||||||
|
|
@ -75,7 +74,6 @@ private:
|
||||||
connection_map idle_connections_;
|
connection_map idle_connections_;
|
||||||
|
|
||||||
const connection_info info_;
|
const connection_info info_;
|
||||||
std::function<connection(const connection_info &)> connection_creator_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef EXECUTOR_HPP
|
#ifndef EXECUTOR_HPP
|
||||||
#define EXECUTOR_HPP
|
#define EXECUTOR_HPP
|
||||||
|
|
||||||
#include "matador/sql/producer_resolver_factory.hpp"
|
|
||||||
|
|
||||||
#include "matador/utils/error.hpp"
|
#include "matador/utils/error.hpp"
|
||||||
#include "matador/utils/result.hpp"
|
#include "matador/utils/result.hpp"
|
||||||
|
|
||||||
|
|
@ -22,7 +20,6 @@ public:
|
||||||
[[nodiscard]] virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(const query_context &ctx) const = 0;
|
[[nodiscard]] virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(const query_context &ctx) const = 0;
|
||||||
[[nodiscard]] virtual utils::result<statement, utils::error> prepare(const query_context &ctx) = 0;
|
[[nodiscard]] virtual utils::result<statement, utils::error> prepare(const query_context &ctx) = 0;
|
||||||
[[nodiscard]] virtual std::string str(const query_context &ctx) const = 0;
|
[[nodiscard]] virtual std::string str(const query_context &ctx) const = 0;
|
||||||
[[nodiscard]] virtual std::shared_ptr<producer_resolver_factory> resolver_factory() const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,6 @@ public:
|
||||||
field(field &&x) noexcept;
|
field(field &&x) noexcept;
|
||||||
field& operator=(field &&x) noexcept;
|
field& operator=(field &&x) noexcept;
|
||||||
|
|
||||||
bool operator==(const field& rhs) const;
|
|
||||||
bool operator!=(const field& rhs) const;
|
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
field& operator=(Type value) {
|
field& operator=(Type value) {
|
||||||
value_ = std::move(value);
|
value_ = std::move(value);
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,11 @@
|
||||||
#include "matador/sql/object_parameter_binder.hpp"
|
#include "matador/sql/object_parameter_binder.hpp"
|
||||||
|
|
||||||
#include "matador/utils/data_type_traits.hpp"
|
#include "matador/utils/data_type_traits.hpp"
|
||||||
#include "matador/utils/error.hpp"
|
|
||||||
#include "matador/utils/result.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
class query_result_impl;
|
|
||||||
class sql_error;
|
class sql_error;
|
||||||
|
|
||||||
class statement_impl {
|
class statement_impl {
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,6 @@ public:
|
||||||
[[nodiscard]] std::unique_ptr<utils::attribute_writer> create_binder() const;
|
[[nodiscard]] std::unique_ptr<utils::attribute_writer> create_binder() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class statement;
|
|
||||||
|
|
||||||
std::unique_ptr<statement_impl> statement_;
|
std::unique_ptr<statement_impl> statement_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#ifndef MATADOR_IDENTIFIER_READER_HPP
|
|
||||||
#define MATADOR_IDENTIFIER_READER_HPP
|
|
||||||
|
|
||||||
#include "matador/utils/access.hpp"
|
|
||||||
#include "matador/utils/identifier.hpp"
|
|
||||||
#include "matador/utils/primary_key_attribute.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
class query_result_reader;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace matador::sql::internal {
|
|
||||||
class identifier_reader final {
|
|
||||||
public:
|
|
||||||
explicit identifier_reader(query_result_reader &reader);
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
utils::identifier read(const Type &obj, const size_t column_index) {
|
|
||||||
identifier_.clear();
|
|
||||||
column_index_ = column_index;
|
|
||||||
access::process(*this, obj);
|
|
||||||
return identifier_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ValueType>
|
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
|
||||||
utils::data_type_traits<ValueType>::read_value(reader_, id, column_index_, value, attr.size());
|
|
||||||
identifier_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
|
||||||
template < class Type >
|
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
|
||||||
template < class Pointer >
|
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
template < class Pointer >
|
|
||||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
template<class ContainerType>
|
|
||||||
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
template<class ContainerType>
|
|
||||||
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
template<class ContainerType>
|
|
||||||
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
query_result_reader &reader_;
|
|
||||||
size_t column_index_{};
|
|
||||||
utils::identifier identifier_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //MATADOR_IDENTIFIER_READER_HPP
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef MATADOR_IDENTIFIER_STATEMENT_BINDER_HPP
|
|
||||||
#define MATADOR_IDENTIFIER_STATEMENT_BINDER_HPP
|
|
||||||
|
|
||||||
#include "matador/utils/identifier.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
class statement;
|
|
||||||
|
|
||||||
class identifier_statement_binder : public utils::identifier_serializer {
|
|
||||||
public:
|
|
||||||
explicit identifier_statement_binder(statement &stmt, size_t index = 0);
|
|
||||||
|
|
||||||
void bind(const utils::identifier &id);
|
|
||||||
|
|
||||||
void serialize(int8_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(int16_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(int32_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(int64_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(uint8_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(uint16_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(uint32_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(uint64_t &, const utils::field_attributes &) override;
|
|
||||||
void serialize(const char *, const utils::field_attributes &) override;
|
|
||||||
void serialize(std::string &, const utils::field_attributes &) override;
|
|
||||||
void serialize(utils::null_type_t &, const utils::field_attributes &) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
statement &stmt_;
|
|
||||||
size_t index_{};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //MATADOR_IDENTIFIER_STATEMENT_BINDER_HPP
|
|
||||||
|
|
@ -10,17 +10,16 @@
|
||||||
|
|
||||||
#include "matador/sql/interface/query_result_reader.hpp"
|
#include "matador/sql/interface/query_result_reader.hpp"
|
||||||
#include "matador/sql/internal/query_result_pk_resolver.hpp"
|
#include "matador/sql/internal/query_result_pk_resolver.hpp"
|
||||||
#include "matador/sql/internal/identifier_reader.hpp"
|
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
|
|
||||||
#include "matador/object/attribute.hpp"
|
#include "matador/object/attribute.hpp"
|
||||||
#include "matador/object/object_proxy.hpp"
|
|
||||||
#include "matador/object/object_resolver_factory.hpp"
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
class value;
|
class value;
|
||||||
|
|
@ -74,9 +73,9 @@ private:
|
||||||
class query_result_impl {
|
class query_result_impl {
|
||||||
public:
|
public:
|
||||||
query_result_impl(std::unique_ptr<query_result_reader> &&reader,
|
query_result_impl(std::unique_ptr<query_result_reader> &&reader,
|
||||||
std::vector<object::attribute> prototype,
|
std::vector<object::attribute> &&prototype, size_t column_index = 0);
|
||||||
const std::shared_ptr<object::object_resolver_factory>& resolver_factory,
|
query_result_impl(std::unique_ptr<query_result_reader> &&reader,
|
||||||
size_t column_index = 0);
|
const std::vector<object::attribute> &prototype, size_t column_index = 0);
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
|
||||||
|
|
@ -123,19 +122,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
void on_has_many(const char * /*id*/, ContainerType &cont, const char * /*join_column*/, const utils::foreign_attributes &attr) {
|
void on_has_many(const char * /*id*/, ContainerType &cont, const char * /*join_column*/,
|
||||||
using value_type = typename ContainerType::value_type::value_type;
|
const utils::foreign_attributes &attr) {
|
||||||
auto resolver = resolver_factory_->resolver<value_type>();
|
|
||||||
|
|
||||||
if (attr.fetch() == utils::fetch_type::Lazy) {
|
if (attr.fetch() == utils::fetch_type::Lazy) {
|
||||||
// pk_reader_.read(*id, column_index_++);
|
// pk_reader_.read(*id, column_index_++);
|
||||||
} else {
|
} else {
|
||||||
const auto ti = std::type_index(typeid(value_type));
|
const auto ti = std::type_index(typeid(typename ContainerType::value_type::value_type));
|
||||||
auto obj = std::make_shared<typename ContainerType::value_type::value_type>();
|
auto obj = std::make_unique<typename ContainerType::value_type::value_type>();
|
||||||
type_stack_.push(ti);
|
type_stack_.push(ti);
|
||||||
access::process(*this, *obj);
|
access::process(*this, *obj);
|
||||||
type_stack_.pop();
|
type_stack_.pop();
|
||||||
auto ptr = typename ContainerType::value_type(std::make_shared<object::object_proxy<value_type>>(resolver, obj));
|
auto ptr = typename ContainerType::value_type(obj.release());
|
||||||
const auto pk = ptr.primary_key();
|
const auto pk = ptr.primary_key();
|
||||||
if (ptr.primary_key().is_valid()) {
|
if (ptr.primary_key().is_valid()) {
|
||||||
cont.push_back(ptr);
|
cont.push_back(ptr);
|
||||||
|
|
@ -197,18 +194,16 @@ private:
|
||||||
|
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
void on_foreign_key(Pointer &x, const utils::foreign_attributes &attr) {
|
void on_foreign_key(Pointer &x, const utils::foreign_attributes &attr) {
|
||||||
const auto resolver = resolver_factory_->resolver<typename Pointer::value_type>();
|
if (x.empty()) {
|
||||||
|
x.reset(new typename Pointer::value_type);
|
||||||
|
}
|
||||||
if (attr.fetch() == utils::fetch_type::Lazy) {
|
if (attr.fetch() == utils::fetch_type::Lazy) {
|
||||||
typename Pointer::value_type obj;
|
pk_reader_.read(*x, column_index_++);
|
||||||
auto pk = id_reader_.read(obj, column_index_++);
|
|
||||||
x = Pointer(std::make_shared<object::object_proxy<typename Pointer::value_type>>(resolver, pk));
|
|
||||||
} else {
|
} else {
|
||||||
auto obj = std::make_shared<typename Pointer::value_type>();
|
|
||||||
const auto ti = std::type_index(typeid(*x));
|
const auto ti = std::type_index(typeid(*x));
|
||||||
type_stack_.push(ti);
|
type_stack_.push(ti);
|
||||||
access::process(*this, *obj);
|
access::process(*this, *x);
|
||||||
type_stack_.pop();
|
type_stack_.pop();
|
||||||
x = Pointer(std::make_shared<object::object_proxy<typename Pointer::value_type>>(resolver, obj));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,8 +211,6 @@ protected:
|
||||||
size_t column_index_ = 0;
|
size_t column_index_ = 0;
|
||||||
std::vector<object::attribute> prototype_;
|
std::vector<object::attribute> prototype_;
|
||||||
std::unique_ptr<query_result_reader> reader_;
|
std::unique_ptr<query_result_reader> reader_;
|
||||||
std::shared_ptr<object::object_resolver_factory> resolver_factory_;
|
|
||||||
internal::identifier_reader id_reader_;
|
|
||||||
detail::pk_reader pk_reader_;
|
detail::pk_reader pk_reader_;
|
||||||
std::stack<std::type_index> type_stack_;
|
std::stack<std::type_index> type_stack_;
|
||||||
utils::identifier current_pk_{};
|
utils::identifier current_pk_{};
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,9 @@ public:
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
|
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, 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 &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class Type>
|
template<class Type>
|
||||||
|
|
@ -60,8 +60,8 @@ private:
|
||||||
if (fetch == utils::fetch_type::Lazy) {
|
if (fetch == utils::fetch_type::Lazy) {
|
||||||
++column_index_;
|
++column_index_;
|
||||||
} else {
|
} else {
|
||||||
const Type obj{};
|
const Type obj;
|
||||||
type_stack_.emplace(typeid(Type));
|
type_stack_.push(typeid(Type));
|
||||||
access::process(*this, obj);
|
access::process(*this, obj);
|
||||||
type_stack_.pop();
|
type_stack_.pop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef MATADOR_RESOLVER_PRODUCER_HPP
|
|
||||||
#define MATADOR_RESOLVER_PRODUCER_HPP
|
|
||||||
|
|
||||||
#include "matador/object/object_resolver.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
class executor;
|
|
||||||
class resolver_producer {
|
|
||||||
public:
|
|
||||||
virtual ~resolver_producer() = default;
|
|
||||||
virtual std::shared_ptr<object::abstract_object_resolver> produce(executor &exec) = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] const std::type_index& type() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit resolver_producer(const std::type_index &type);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::type_index type_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //MATADOR_RESOLVER_PRODUCER_HPP
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef MATADOR_STATEMENT_OBJECT_RESOLVER_HPP
|
|
||||||
#define MATADOR_STATEMENT_OBJECT_RESOLVER_HPP
|
|
||||||
|
|
||||||
#include "matador/object/object_resolver.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/statement.hpp"
|
|
||||||
#include "matador/sql/internal/identifier_statement_binder.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
template<typename Type>
|
|
||||||
class statement_object_resolver : public object::object_resolver<Type> {
|
|
||||||
public:
|
|
||||||
explicit statement_object_resolver(statement stmt)
|
|
||||||
: statement_(std::move(stmt)) {}
|
|
||||||
|
|
||||||
std::shared_ptr<Type> resolve(const utils::identifier &id) override;
|
|
||||||
protected:
|
|
||||||
statement statement_;
|
|
||||||
std::type_index index{typeid(Type)};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
std::shared_ptr<Type> statement_object_resolver<Type>::resolve(const utils::identifier &id) {
|
|
||||||
identifier_statement_binder binder(statement_);
|
|
||||||
binder.bind(id);
|
|
||||||
|
|
||||||
auto result = statement_.template fetch_one<Type>();
|
|
||||||
if (!result) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return std::make_shared<Type>(*result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //MATADOR_STATEMENT_OBJECT_RESOLVER_HPP
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#ifndef MATADOR_RESOLVER_FACTORY_HPP
|
|
||||||
#define MATADOR_RESOLVER_FACTORY_HPP
|
|
||||||
|
|
||||||
#include "matador/object/object_resolver_factory.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/internal/resolver_producer.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
class executor;
|
|
||||||
|
|
||||||
class producer_resolver_factory : public object::object_resolver_factory {
|
|
||||||
public:
|
|
||||||
|
|
||||||
std::shared_ptr<object::abstract_object_resolver> acquire_resolver(const std::type_index &type) override;
|
|
||||||
void register_resolver(std::shared_ptr<object::abstract_object_resolver> &&resolver) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::type_index, std::shared_ptr<object::abstract_object_resolver>> resolvers_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //MATADOR_RESOLVER_FACTORY_HPP
|
|
||||||
|
|
@ -2,29 +2,31 @@
|
||||||
#define QUERY_QUERY_DATA_HPP
|
#define QUERY_QUERY_DATA_HPP
|
||||||
|
|
||||||
#include "matador/object/attribute.hpp"
|
#include "matador/object/attribute.hpp"
|
||||||
#include "matador/object/object_resolver_factory.hpp"
|
|
||||||
|
|
||||||
#include "matador/utils/types.hpp"
|
#include "matador/utils/types.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
enum class sql_command {
|
enum class sql_command {
|
||||||
SQL_UNKNOWN,
|
SQL_UNKNOWN,
|
||||||
SQL_CREATE,
|
SQL_CREATE,
|
||||||
SQL_CREATE_TABLE,
|
SQL_CREATE_TABLE,
|
||||||
SQL_CREATE_SCHEMA,
|
SQL_CREATE_SCHEMA,
|
||||||
SQL_CREATE_DATABASE,
|
SQL_CREATE_DATABASE,
|
||||||
SQL_UPDATE,
|
SQL_UPDATE,
|
||||||
SQL_INSERT,
|
SQL_INSERT,
|
||||||
SQL_DELETE,
|
SQL_DELETE,
|
||||||
SQL_SELECT,
|
SQL_SELECT,
|
||||||
SQL_DROP,
|
SQL_DROP,
|
||||||
SQL_DROP_TABLE,
|
SQL_DROP_TABLE,
|
||||||
SQL_DROP_SCHEMA,
|
SQL_DROP_SCHEMA,
|
||||||
SQL_DROP_DATABASE,
|
SQL_DROP_DATABASE,
|
||||||
SQL_ALTER,
|
SQL_ALTER,
|
||||||
SQL_ALTER_TABLE,
|
SQL_ALTER_TABLE,
|
||||||
SQL_ALTER_SCHEMA
|
SQL_ALTER_SCHEMA
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sql_command_info {
|
struct sql_command_info {
|
||||||
std::string sql;
|
std::string sql;
|
||||||
|
|
@ -38,10 +40,14 @@ struct query_context {
|
||||||
std::string schema_name{};
|
std::string schema_name{};
|
||||||
std::string table_name{};
|
std::string table_name{};
|
||||||
std::vector<object::attribute> prototype{};
|
std::vector<object::attribute> prototype{};
|
||||||
|
// std::vector<std::string> result_vars{};
|
||||||
std::vector<std::string> bind_vars{};
|
std::vector<std::string> bind_vars{};
|
||||||
std::vector<utils::database_type> bind_types{};
|
std::vector<utils::database_type> bind_types{};
|
||||||
std::shared_ptr<object::object_resolver_factory> resolver_factory{};
|
|
||||||
|
// std::unordered_map<std::string, std::string> column_aliases{};
|
||||||
|
// std::unordered_map<std::string, std::string> table_aliases{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_QUERY_DATA_HPP
|
#endif //QUERY_QUERY_DATA_HPP
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
#ifndef MATADOR_QUERY_RECORD_RESULT_HPP
|
|
||||||
#define MATADOR_QUERY_RECORD_RESULT_HPP
|
|
||||||
|
|
||||||
#include "matador/sql/query_result.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class query_result<record>;
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class query_result_iterator<record> {
|
|
||||||
public:
|
|
||||||
using iterator_category = std::forward_iterator_tag;
|
|
||||||
using value_type = record;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using self = query_result_iterator; /**< Shortcut for this class. */
|
|
||||||
using pointer = value_type*; /**< Shortcut for the pointer type. */
|
|
||||||
using reference = value_type&; /**< Shortcut for the reference type */
|
|
||||||
|
|
||||||
public:
|
|
||||||
query_result_iterator() = default;
|
|
||||||
explicit query_result_iterator(query_result<record> *res)
|
|
||||||
: result_(res)
|
|
||||||
{}
|
|
||||||
query_result_iterator(query_result<record> *res, record rec)
|
|
||||||
: record_(std::move(rec))
|
|
||||||
, result_(res)
|
|
||||||
{}
|
|
||||||
query_result_iterator(query_result_iterator&& x) noexcept
|
|
||||||
: record_(std::move(x.record_))
|
|
||||||
, result_(x.result_)
|
|
||||||
{}
|
|
||||||
query_result_iterator& operator=(query_result_iterator&& x) noexcept {
|
|
||||||
result_ = x.result_;
|
|
||||||
record_ = std::move(x.record_);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~query_result_iterator() = default;
|
|
||||||
|
|
||||||
bool operator==(const query_result_iterator& rhs) const {
|
|
||||||
return record_ == rhs.record_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const query_result_iterator& rhs) const {
|
|
||||||
return !(*this == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
self& operator++();
|
|
||||||
self operator++(int);
|
|
||||||
|
|
||||||
pointer operator->() { return &record_; }
|
|
||||||
reference operator*() { return record_; }
|
|
||||||
record release() { return std::move(record_); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
record record_;
|
|
||||||
query_result<record> *result_{nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class query_result<record> final {
|
|
||||||
public:
|
|
||||||
using iterator = query_result_iterator<record>;
|
|
||||||
|
|
||||||
query_result(std::unique_ptr<query_result_impl> &&impl, const std::vector<object::attribute> &prototype)
|
|
||||||
: impl_(std::move(impl))
|
|
||||||
, prototype_(prototype) {}
|
|
||||||
|
|
||||||
iterator begin() { return std::move(++iterator(this)); }
|
|
||||||
iterator end() { return {}; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class query_result_iterator<record>;
|
|
||||||
|
|
||||||
[[nodiscard]] record create() const;
|
|
||||||
void bind(const record& obj) const;
|
|
||||||
bool fetch(record& obj) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::unique_ptr<query_result_impl> impl_;
|
|
||||||
std::vector<object::attribute> prototype_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline record query_result<record>::create() const {
|
|
||||||
record rec;
|
|
||||||
int index{0};
|
|
||||||
for (const auto &col: prototype_) {
|
|
||||||
rec.append({
|
|
||||||
col.name(),
|
|
||||||
col.type(),
|
|
||||||
col.attributes().options(),
|
|
||||||
col.attributes().size(),
|
|
||||||
index++
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return rec;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void query_result<record>::bind(const record &obj) const {
|
|
||||||
impl_->bind(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool query_result<record>::fetch(record &obj) const {
|
|
||||||
return impl_->fetch(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline query_result_iterator<record>::self & query_result_iterator<record>::operator++() {
|
|
||||||
record_ = result_->create();
|
|
||||||
result_->bind(record_);
|
|
||||||
if (!result_->fetch(record_)) {
|
|
||||||
record_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline query_result_iterator<record>::self query_result_iterator<record>::operator++(int) {
|
|
||||||
self tmp(result_, record_);
|
|
||||||
|
|
||||||
record_ = result_->create();
|
|
||||||
result_->bind(record_);
|
|
||||||
if (!result_->fetch(record_)) {
|
|
||||||
record_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif //MATADOR_QUERY_RECORD_RESULT_HPP
|
|
||||||
|
|
@ -2,24 +2,22 @@
|
||||||
#define QUERY_QUERY_RESULT_HPP
|
#define QUERY_QUERY_RESULT_HPP
|
||||||
|
|
||||||
#include "matador/object/attribute.hpp"
|
#include "matador/object/attribute.hpp"
|
||||||
#include "matador/object/object_ptr.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/internal/query_result_impl.hpp"
|
#include "matador/sql/internal/query_result_impl.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "matador/object/object.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
class record;
|
class record;
|
||||||
class query_result_impl;
|
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
class query_result;
|
class query_result;
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
class query_result_iterator {
|
class query_result_iterator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
using iterator_category = std::forward_iterator_tag;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
using value_type = Type;
|
using value_type = Type;
|
||||||
|
|
@ -33,7 +31,7 @@ public:
|
||||||
explicit query_result_iterator(query_result<Type> *res)
|
explicit query_result_iterator(query_result<Type> *res)
|
||||||
: result_(res)
|
: result_(res)
|
||||||
{}
|
{}
|
||||||
query_result_iterator(query_result<Type> *res, object::object_ptr<Type> obj)
|
query_result_iterator(query_result<Type> *res, std::unique_ptr<Type> obj)
|
||||||
: obj_(std::move(obj))
|
: obj_(std::move(obj))
|
||||||
, result_(res)
|
, result_(res)
|
||||||
{}
|
{}
|
||||||
|
|
@ -50,20 +48,19 @@ public:
|
||||||
|
|
||||||
~query_result_iterator() = default;
|
~query_result_iterator() = default;
|
||||||
|
|
||||||
bool operator==(const query_result_iterator& rhs) const {
|
bool operator==(const query_result_iterator& rhs) {
|
||||||
return obj_ == rhs.obj_;
|
return obj_ == rhs.obj_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const query_result_iterator& rhs) const {
|
bool operator!=(const query_result_iterator& rhs) {
|
||||||
return !operator==(rhs);
|
return obj_ != rhs.obj_;
|
||||||
}
|
}
|
||||||
|
|
||||||
self& operator++() {
|
self& operator++() {
|
||||||
auto obj = result_->create();
|
obj_.reset(result_->create());
|
||||||
result_->bind(*obj);
|
result_->bind(*obj_);
|
||||||
obj_.reset();
|
if (!result_->fetch(*obj_)) {
|
||||||
if (result_->fetch(*obj)) {
|
obj_.reset();
|
||||||
obj_ = object::object_ptr<Type>(std::make_shared<object::object_proxy<Type>>(result_->resolver_, std::move(obj)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -72,11 +69,10 @@ public:
|
||||||
self operator++(int) {
|
self operator++(int) {
|
||||||
const self tmp(result_, obj_);
|
const self tmp(result_, obj_);
|
||||||
|
|
||||||
auto obj = result_->create();
|
obj_.reset(result_->create());
|
||||||
result_->bind(*obj);
|
result_->bind(*obj_);
|
||||||
obj_.reset();
|
if (!result_->fetch(*obj_)) {
|
||||||
if (result_->fetch(*obj)) {
|
obj_.reset();
|
||||||
obj_ = object::object_ptr<Type>(std::make_shared<object::object_proxy<Type>>(result_->resolver_, std::move(obj)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
|
|
@ -86,37 +82,50 @@ public:
|
||||||
return obj_.get();
|
return obj_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
object::object_ptr<Type> operator*() {
|
reference operator*() {
|
||||||
return obj_;
|
return *obj_;
|
||||||
}
|
}
|
||||||
|
|
||||||
object::object_ptr<Type> optr() {
|
pointer get() {
|
||||||
return obj_;
|
return obj_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer release() {
|
||||||
|
return obj_.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
object::object_ptr<Type> obj_;
|
std::unique_ptr<Type> obj_;
|
||||||
query_result<Type> *result_{nullptr};
|
query_result<Type> *result_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
std::shared_ptr<Type> create_prototype(const std::vector<object::attribute> &/*prototype*/) {
|
Type* create_prototype(const std::vector<object::attribute> &/*prototype*/) {
|
||||||
return std::make_shared<Type>();
|
return new Type{};
|
||||||
}
|
}
|
||||||
|
|
||||||
record create_prototype(const std::vector<object::attribute> &prototype);
|
template <>
|
||||||
|
record* create_prototype<record>(const std::vector<object::attribute> &prototype);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
class query_result final {
|
class query_result final {
|
||||||
public:
|
public:
|
||||||
using iterator = query_result_iterator<Type>;
|
using iterator = query_result_iterator<Type>;
|
||||||
using creator_func = std::function<std::shared_ptr<Type>()>;
|
using creator_func = std::function<Type*()>;
|
||||||
|
|
||||||
query_result(std::unique_ptr<query_result_impl> &&impl, const std::shared_ptr<object::object_resolver<Type>> &resolver, creator_func&& creator)
|
public:
|
||||||
|
// explicit query_result(std::unique_ptr<query_result_impl> &&impl)
|
||||||
|
// : impl_(std::move(impl))
|
||||||
|
// , creator_([this] {
|
||||||
|
// return detail::create_prototype<Type>(impl_->prototype());
|
||||||
|
// }) {}
|
||||||
|
|
||||||
|
query_result(std::unique_ptr<query_result_impl> &&impl, creator_func&& creator)
|
||||||
: impl_(std::move(impl))
|
: impl_(std::move(impl))
|
||||||
, resolver_(resolver)
|
|
||||||
, creator_(std::move(creator)) {}
|
, creator_(std::move(creator)) {}
|
||||||
|
|
||||||
iterator begin() { return std::move(++iterator(this)); }
|
iterator begin() { return std::move(++iterator(this)); }
|
||||||
|
|
@ -125,18 +134,17 @@ public:
|
||||||
private:
|
private:
|
||||||
friend class query_result_iterator<Type>;
|
friend class query_result_iterator<Type>;
|
||||||
|
|
||||||
std::shared_ptr<Type> create();
|
Type* create();
|
||||||
void bind(const Type& obj);
|
void bind(const Type& obj);
|
||||||
bool fetch(Type& obj);
|
bool fetch(Type& obj);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<query_result_impl> impl_;
|
std::unique_ptr<query_result_impl> impl_;
|
||||||
std::shared_ptr<object::object_resolver<Type>> resolver_;
|
|
||||||
creator_func creator_;
|
creator_func creator_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::shared_ptr<Type> query_result<Type>::create() {
|
Type *query_result<Type>::create() {
|
||||||
return creator_();
|
return creator_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,6 +157,6 @@ template<typename Type>
|
||||||
bool query_result<Type>::fetch(Type &obj) {
|
bool query_result<Type>::fetch(Type &obj) {
|
||||||
return impl_->fetch(obj);
|
return impl_->fetch(obj);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// namespace matador::sql
|
} // namespace matador::sql
|
||||||
#endif //QUERY_QUERY_RESULT_HPP
|
#endif //QUERY_QUERY_RESULT_HPP
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,6 @@ public:
|
||||||
record& operator=(record&&) noexcept = default;
|
record& operator=(record&&) noexcept = default;
|
||||||
~record() = default;
|
~record() = default;
|
||||||
|
|
||||||
bool operator==(const record& rhs) const;
|
|
||||||
bool operator!=(const record& rhs) const;
|
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
for(auto &f : fields_) {
|
for(auto &f : fields_) {
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,20 @@
|
||||||
#define QUERY_STATEMENT_HPP
|
#define QUERY_STATEMENT_HPP
|
||||||
|
|
||||||
#include "matador/sql/abstract_sql_logger.hpp"
|
#include "matador/sql/abstract_sql_logger.hpp"
|
||||||
#include "matador/sql/error_code.hpp"
|
|
||||||
#include "matador/sql/query_result.hpp"
|
#include "matador/sql/query_result.hpp"
|
||||||
#include "matador/sql/interface/statement_proxy.hpp"
|
|
||||||
|
|
||||||
#include "matador/object/basic_repository.hpp"
|
#include "matador/sql/interface/statement_proxy.hpp"
|
||||||
|
|
||||||
#include "matador/utils/error.hpp"
|
#include "matador/utils/error.hpp"
|
||||||
#include "matador/utils/result.hpp"
|
#include "matador/utils/result.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
namespace detail {
|
||||||
|
template<class Type>
|
||||||
|
class identifier_binder;
|
||||||
|
}
|
||||||
|
|
||||||
class statement_impl;
|
class statement_impl;
|
||||||
class statement_proxy;
|
class statement_proxy;
|
||||||
|
|
@ -104,10 +104,7 @@ public:
|
||||||
* @return The query result set
|
* @return The query result set
|
||||||
*/
|
*/
|
||||||
template<class Type>
|
template<class Type>
|
||||||
utils::result<object::object_ptr<Type>, utils::error> fetch_one();
|
utils::result<std::unique_ptr<Type>, utils::error> fetch_one();
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
utils::result<std::shared_ptr<Type>, utils::error> fetch_one_raw();
|
|
||||||
/**
|
/**
|
||||||
* Fetches the first result of a prepared statement.
|
* Fetches the first result of a prepared statement.
|
||||||
* The type is a record representing an unknown variable type.
|
* The type is a record representing an unknown variable type.
|
||||||
|
|
@ -143,6 +140,10 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch_internal() const;
|
[[nodiscard]] utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch_internal() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class Type>
|
||||||
|
friend class detail::identifier_binder;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<statement_proxy> statement_proxy_;
|
std::shared_ptr<statement_proxy> statement_proxy_;
|
||||||
std::unique_ptr<utils::attribute_writer> bindings_;
|
std::unique_ptr<utils::attribute_writer> bindings_;
|
||||||
|
|
@ -164,51 +165,31 @@ statement &statement::bind(const Type &obj) {
|
||||||
template<class Type>
|
template<class Type>
|
||||||
utils::result<query_result<Type>, utils::error> statement::fetch() {
|
utils::result<query_result<Type>, utils::error> statement::fetch() {
|
||||||
std::cout << statement_proxy_->sql() << std::endl;
|
std::cout << statement_proxy_->sql() << std::endl;
|
||||||
return statement_proxy_->fetch(*bindings_).and_then([this](std::unique_ptr<query_result_impl> &&value) {
|
return statement_proxy_->fetch(*bindings_).and_then([](std::unique_ptr<query_result_impl> &&value) {
|
||||||
auto resolver = statement_proxy_->statement_->query_.resolver_factory->resolver<Type>();
|
|
||||||
const auto prototype = value->prototype();
|
const auto prototype = value->prototype();
|
||||||
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value), resolver, [prototype] {
|
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value), [prototype] {
|
||||||
return detail::create_prototype<Type>(prototype);
|
return detail::create_prototype<Type>(prototype);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
utils::result<object::object_ptr<Type>, utils::error> statement::fetch_one() {
|
utils::result<std::unique_ptr<Type>, utils::error> statement::fetch_one() {
|
||||||
std::cout << statement_proxy_->sql() << std::endl;
|
std::cout << statement_proxy_->sql() << std::endl;
|
||||||
auto result = statement_proxy_->fetch(*bindings_);
|
auto result = statement_proxy_->fetch(*bindings_);
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
auto resolver = statement_proxy_->statement_->query_.resolver_factory->resolver<Type>();
|
|
||||||
const auto prototype = result.value()->prototype();
|
const auto prototype = result.value()->prototype();
|
||||||
auto records = query_result<Type>(result.release(), resolver, [prototype] {
|
auto records = query_result<Type>(result.release(), [prototype] {
|
||||||
return detail::create_prototype<Type>(prototype);
|
return detail::create_prototype<Type>(prototype);
|
||||||
});
|
});
|
||||||
auto first = records.begin();
|
auto first = records.begin();
|
||||||
if (first == records.end()) {
|
if (first == records.end()) {
|
||||||
return utils::failure(utils::error{
|
return utils::ok(std::unique_ptr<Type>{nullptr});
|
||||||
error_code::FETCH_FAILED,
|
|
||||||
"Failed to find entity."
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok(first.optr());
|
return utils::ok(std::unique_ptr<Type>{first.release()});
|
||||||
}
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
utils::result<std::shared_ptr<Type>, utils::error> statement::fetch_one_raw() {
|
|
||||||
auto result = statement_proxy_->fetch(*bindings_);
|
|
||||||
if (!result.is_ok()) {
|
|
||||||
return utils::failure(result.err());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto obj = std::make_shared<Type>();
|
|
||||||
(*result)->bind(*obj);
|
|
||||||
if (!(*result)->fetch(*obj)) {
|
|
||||||
return utils::ok(std::shared_ptr<Type>{});
|
|
||||||
}
|
|
||||||
return utils::ok(obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ private:
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|
||||||
connection_pool &pool_;
|
connection_pool &pool_;
|
||||||
const dialect &dialect_;
|
const sql::dialect &dialect_;
|
||||||
|
|
||||||
utils::message_bus &bus_;
|
utils::message_bus &bus_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,9 @@
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
class identifier_serializer {
|
|
||||||
|
class identifier_serializer
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~identifier_serializer() = default;
|
virtual ~identifier_serializer() = default;
|
||||||
|
|
||||||
|
|
@ -23,7 +25,7 @@ public:
|
||||||
virtual void serialize(uint16_t &, const field_attributes &) = 0;
|
virtual void serialize(uint16_t &, const field_attributes &) = 0;
|
||||||
virtual void serialize(uint32_t &, const field_attributes &) = 0;
|
virtual void serialize(uint32_t &, const field_attributes &) = 0;
|
||||||
virtual void serialize(uint64_t &, const field_attributes &) = 0;
|
virtual void serialize(uint64_t &, const field_attributes &) = 0;
|
||||||
virtual void serialize(const char *, const field_attributes &) = 0;
|
virtual void serialize(const char*, const field_attributes &) = 0;
|
||||||
virtual void serialize(std::string &, const field_attributes &) = 0;
|
virtual void serialize(std::string &, const field_attributes &) = 0;
|
||||||
virtual void serialize(null_type_t &, const field_attributes &) = 0;
|
virtual void serialize(null_type_t &, const field_attributes &) = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -32,13 +34,13 @@ template<typename Type, class Enabled = void>
|
||||||
struct identifier_type_traits;
|
struct identifier_type_traits;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type> > > {
|
struct identifier_type_traits<Type, std::enable_if_t<std::is_integral_v<Type>>> {
|
||||||
static bool is_valid(Type value) { return value > 0; }
|
static bool is_valid(Type value) { return value > 0; }
|
||||||
static std::string to_string(const Type value) { return std::to_string(value); }
|
static std::string to_string(const Type value) { return std::to_string(value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
struct identifier_type_traits<Type, std::enable_if_t<std::is_same_v<Type, std::string> > > {
|
struct identifier_type_traits<Type, std::enable_if_t<std::is_same_v<Type, std::string>>> {
|
||||||
static bool is_valid(const Type &value) { return !value.empty(); }
|
static bool is_valid(const Type &value) { return !value.empty(); }
|
||||||
static std::string to_string(const Type &value) { return value; }
|
static std::string to_string(const Type &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
@ -50,23 +52,27 @@ struct identifier_type_traits<null_type_t, void> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct identifier_type_traits<const char *, void> {
|
struct identifier_type_traits<const char*, void> {
|
||||||
static bool is_valid(const char *value);
|
static bool is_valid(const char *value);
|
||||||
static std::string to_string(const char *value);
|
static std::string to_string(const char *value);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
size_t hash(const Type &value) {
|
size_t hash(const Type &value) {
|
||||||
return std::hash<Type>()(value);
|
return std::hash<Type>()(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hash(const char *value);
|
size_t hash(const char *value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class identifier {
|
class identifier
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
struct base {
|
struct base
|
||||||
|
{
|
||||||
base(const std::type_index &ti, basic_type type);
|
base(const std::type_index &ti, basic_type type);
|
||||||
base(const base &x) = delete;
|
base(const base &x) = delete;
|
||||||
base &operator=(const base &x) = delete;
|
base &operator=(const base &x) = delete;
|
||||||
|
|
@ -87,25 +93,25 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class IdType>
|
template<class IdType>
|
||||||
struct pk final : base {
|
struct pk final : base
|
||||||
|
{
|
||||||
using self = pk;
|
using self = pk;
|
||||||
|
|
||||||
explicit pk(const IdType &id)
|
explicit pk(const IdType &id)
|
||||||
: base(std::type_index(typeid(IdType)), data_type_traits<IdType>::type(1))
|
: base(std::type_index(typeid(IdType)), data_type_traits<IdType>::type(1))
|
||||||
, id_(id)
|
, id_(id)
|
||||||
, size_(sizeof(IdType)) {
|
, size_(sizeof(IdType)) {}
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] base *copy() const override {
|
[[nodiscard]] base *copy() const override {
|
||||||
return new self(id_);
|
return new self(id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool equal_to(const base &x) const override {
|
[[nodiscard]] bool equal_to(const base &x) const override {
|
||||||
return static_cast<const pk &>(x).id_ == id_;
|
return static_cast<const pk&>(x).id_ == id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool less(const base &x) const override {
|
[[nodiscard]] bool less(const base &x) const override {
|
||||||
return id_ < static_cast<const pk &>(x).id_;
|
return id_ < static_cast<const pk&>(x).id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool is_valid() const override {
|
[[nodiscard]] bool is_valid() const override {
|
||||||
|
|
@ -128,7 +134,8 @@ private:
|
||||||
size_t size_{};
|
size_t size_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct null_pk final : base {
|
struct null_pk final : base
|
||||||
|
{
|
||||||
null_pk();
|
null_pk();
|
||||||
[[nodiscard]] base *copy() const override;
|
[[nodiscard]] base *copy() const override;
|
||||||
[[nodiscard]] bool equal_to(const base &x) const override;
|
[[nodiscard]] bool equal_to(const base &x) const override;
|
||||||
|
|
@ -142,29 +149,26 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
identifier();
|
identifier();
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
explicit identifier(const Type &id)
|
explicit identifier(const Type &id)
|
||||||
: id_(std::make_shared<pk<Type> >(id)) {
|
: id_(std::make_shared<pk<Type>>(id)) {}
|
||||||
}
|
|
||||||
|
|
||||||
explicit identifier(const char *id)
|
explicit identifier(const char *id)
|
||||||
: id_(std::make_shared<pk<const char *> >(id)) {
|
: id_(std::make_shared<pk<const char*>>(id)) {}
|
||||||
}
|
|
||||||
|
|
||||||
identifier(const identifier &x);
|
identifier(const identifier &x);
|
||||||
identifier &operator=(const identifier &x);
|
identifier &operator=(const identifier &x);
|
||||||
identifier(identifier &&x) noexcept;
|
identifier(identifier &&x) noexcept ;
|
||||||
identifier &operator=(identifier &&x) noexcept;
|
identifier &operator=(identifier &&x) noexcept;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
identifier &operator=(const Type &value) {
|
identifier& operator=(const Type &value)
|
||||||
id_ = std::make_shared<pk<Type> >(value);
|
{
|
||||||
|
id_ = std::make_shared<pk<Type>>(value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier &operator=(const char *value) {
|
identifier& operator=(const char *value)
|
||||||
id_ = std::make_shared<pk<const char *> >(value);
|
{
|
||||||
|
id_ = std::make_shared<pk<const char*>>(value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,7 +208,7 @@ public:
|
||||||
friend std::ostream &operator<<(std::ostream &out, const identifier &id);
|
friend std::ostream &operator<<(std::ostream &out, const identifier &id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit identifier(const std::shared_ptr<base> &id);
|
explicit identifier(const std::shared_ptr<base>& id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<base> id_;
|
std::shared_ptr<base> id_;
|
||||||
|
|
@ -213,10 +217,10 @@ private:
|
||||||
static identifier null_identifier{};
|
static identifier null_identifier{};
|
||||||
|
|
||||||
/// @cond MATADOR_DEV
|
/// @cond MATADOR_DEV
|
||||||
struct id_pk_hash {
|
struct id_pk_hash
|
||||||
|
{
|
||||||
size_t operator()(const identifier &id) const;
|
size_t operator()(const identifier &id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef MATADOR_IDENTIFIER_TO_VALUE_CONVERTER_HPP
|
|
||||||
#define MATADOR_IDENTIFIER_TO_VALUE_CONVERTER_HPP
|
|
||||||
|
|
||||||
#include "matador/utils/identifier.hpp"
|
|
||||||
#include "matador/utils/value.hpp"
|
|
||||||
|
|
||||||
namespace matador::utils {
|
|
||||||
class identifier_to_value_converter final : public identifier_serializer {
|
|
||||||
public:
|
|
||||||
[[nodiscard]] value convert(const identifier &id);
|
|
||||||
|
|
||||||
void serialize(int8_t &, const field_attributes &) override;
|
|
||||||
void serialize(int16_t &, const field_attributes &) override;
|
|
||||||
void serialize(int32_t &, const field_attributes &) override;
|
|
||||||
void serialize(int64_t &, const field_attributes &) override;
|
|
||||||
void serialize(uint8_t &, const field_attributes &) override;
|
|
||||||
void serialize(uint16_t &, const field_attributes &) override;
|
|
||||||
void serialize(uint32_t &, const field_attributes &) override;
|
|
||||||
void serialize(uint64_t &, const field_attributes &) override;
|
|
||||||
void serialize(const char *, const field_attributes &) override;
|
|
||||||
void serialize(std::string &, const field_attributes &) override;
|
|
||||||
void serialize(null_type_t &, const field_attributes &) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
value value_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //MATADOR_IDENTIFIER_TO_VALUE_CONVERTER_HPP
|
|
||||||
|
|
@ -44,9 +44,6 @@ public:
|
||||||
value(value &&x) noexcept;
|
value(value &&x) noexcept;
|
||||||
value& operator=(value &&x) noexcept;
|
value& operator=(value &&x) noexcept;
|
||||||
|
|
||||||
bool operator==(const value& rhs) const;
|
|
||||||
bool operator!=(const value& rhs) const;
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
std::optional<Type> as() const {
|
std::optional<Type> as() const {
|
||||||
if (std::holds_alternative<Type>(value_)) {
|
if (std::holds_alternative<Type>(value_)) {
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,14 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/net/socket_interrupter.hpp
|
../../include/matador/net/socket_interrupter.hpp
|
||||||
../../include/matador/object/attribute.hpp
|
../../include/matador/object/attribute.hpp
|
||||||
../../include/matador/object/basic_object_info.hpp
|
../../include/matador/object/basic_object_info.hpp
|
||||||
../../include/matador/object/basic_repository.hpp
|
|
||||||
../../include/matador/object/error_code.hpp
|
../../include/matador/object/error_code.hpp
|
||||||
../../include/matador/object/foreign_node_completer.hpp
|
../../include/matador/object/foreign_node_completer.hpp
|
||||||
../../include/matador/object/internal/observer_list_copy_creator.hpp
|
|
||||||
../../include/matador/object/internal/observer_list_creator.hpp
|
|
||||||
../../include/matador/object/many_to_many_relation.hpp
|
../../include/matador/object/many_to_many_relation.hpp
|
||||||
../../include/matador/object/object.hpp
|
../../include/matador/object/object.hpp
|
||||||
../../include/matador/object/object_generator.hpp
|
../../include/matador/object/object_generator.hpp
|
||||||
../../include/matador/object/object_info.hpp
|
../../include/matador/object/object_info.hpp
|
||||||
../../include/matador/object/object_proxy.hpp
|
../../include/matador/object/object_proxy.hpp
|
||||||
../../include/matador/object/object_ptr.hpp
|
../../include/matador/object/object_ptr.hpp
|
||||||
../../include/matador/object/object_resolver.hpp
|
|
||||||
../../include/matador/object/object_resolver_factory.hpp
|
|
||||||
../../include/matador/object/observer.hpp
|
../../include/matador/object/observer.hpp
|
||||||
../../include/matador/object/primary_key_resolver.hpp
|
../../include/matador/object/primary_key_resolver.hpp
|
||||||
../../include/matador/object/relation_completer.hpp
|
../../include/matador/object/relation_completer.hpp
|
||||||
|
|
@ -36,6 +31,7 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/object/repository_node.hpp
|
../../include/matador/object/repository_node.hpp
|
||||||
../../include/matador/object/repository_node_iterator.hpp
|
../../include/matador/object/repository_node_iterator.hpp
|
||||||
../../include/matador/object/restriction.hpp
|
../../include/matador/object/restriction.hpp
|
||||||
|
../../include/matador/sql/statement_cache.hpp
|
||||||
../../include/matador/utils/access.hpp
|
../../include/matador/utils/access.hpp
|
||||||
../../include/matador/utils/attribute_reader.hpp
|
../../include/matador/utils/attribute_reader.hpp
|
||||||
../../include/matador/utils/attribute_writer.hpp
|
../../include/matador/utils/attribute_writer.hpp
|
||||||
|
|
@ -57,7 +53,6 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/utils/file.hpp
|
../../include/matador/utils/file.hpp
|
||||||
../../include/matador/utils/foreign_attributes.hpp
|
../../include/matador/utils/foreign_attributes.hpp
|
||||||
../../include/matador/utils/identifier.hpp
|
../../include/matador/utils/identifier.hpp
|
||||||
../../include/matador/utils/identifier_to_value_converter.hpp
|
|
||||||
../../include/matador/utils/leader_follower_thread_pool.hpp
|
../../include/matador/utils/leader_follower_thread_pool.hpp
|
||||||
../../include/matador/utils/library.hpp
|
../../include/matador/utils/library.hpp
|
||||||
../../include/matador/utils/macro_map.hpp
|
../../include/matador/utils/macro_map.hpp
|
||||||
|
|
@ -83,7 +78,6 @@ add_library(matador-core STATIC
|
||||||
logger/rotating_file_sink.cpp
|
logger/rotating_file_sink.cpp
|
||||||
object/attribute.cpp
|
object/attribute.cpp
|
||||||
object/basic_object_info.cpp
|
object/basic_object_info.cpp
|
||||||
object/basic_repository.cpp
|
|
||||||
object/error_code.cpp
|
object/error_code.cpp
|
||||||
object/foreign_node_completer.cpp
|
object/foreign_node_completer.cpp
|
||||||
object/object.cpp
|
object/object.cpp
|
||||||
|
|
@ -101,7 +95,6 @@ add_library(matador-core STATIC
|
||||||
utils/file.cpp
|
utils/file.cpp
|
||||||
utils/foreign_attributes.cpp
|
utils/foreign_attributes.cpp
|
||||||
utils/identifier.cpp
|
utils/identifier.cpp
|
||||||
utils/identifier_to_value_converter.cpp
|
|
||||||
utils/leader_follower_thread_pool.cpp
|
utils/leader_follower_thread_pool.cpp
|
||||||
utils/library.cpp
|
utils/library.cpp
|
||||||
utils/message_bus.cpp
|
utils/message_bus.cpp
|
||||||
|
|
@ -113,6 +106,10 @@ add_library(matador-core STATIC
|
||||||
utils/uuid.cpp
|
utils/uuid.cpp
|
||||||
utils/value.cpp
|
utils/value.cpp
|
||||||
utils/version.cpp
|
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})
|
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
#include "matador/utils/identifier_to_value_converter.hpp"
|
|
||||||
|
|
||||||
namespace matador::utils {
|
|
||||||
value identifier_to_value_converter::convert(const identifier &id) {
|
|
||||||
id.serialize(*this);
|
|
||||||
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(int8_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(int16_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(int32_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(int64_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(uint8_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(uint16_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(uint32_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(uint64_t &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(const char *x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(std::string &x, const field_attributes &) {
|
|
||||||
value_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_to_value_converter::serialize(null_type_t &/*x*/, const field_attributes &) {
|
|
||||||
value_.type(basic_type::Null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,14 +39,6 @@ value &value::operator=(value &&x) noexcept {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool value::operator==(const value &rhs) const {
|
|
||||||
return type_ == rhs.type_ && value_ == rhs.value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool value::operator!=(const value &rhs) const {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string value::str() const {
|
std::string value::str() const {
|
||||||
return as<std::string>().value_or("");
|
return as<std::string>().value_or("");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
add_library(matador-orm STATIC
|
add_library(matador-orm STATIC
|
||||||
../../include/matador/orm/error_code.hpp
|
../../include/matador/orm/error_code.hpp
|
||||||
../../include/matador/orm/session.hpp
|
../../include/matador/orm/session.hpp
|
||||||
|
../../include/matador/orm/session_query_builder.hpp
|
||||||
../../include/matador/query/attribute_string_writer.hpp
|
../../include/matador/query/attribute_string_writer.hpp
|
||||||
../../include/matador/query/basic_schema.hpp
|
|
||||||
../../include/matador/query/builder.hpp
|
../../include/matador/query/builder.hpp
|
||||||
../../include/matador/query/criteria.hpp
|
../../include/matador/query/criteria.hpp
|
||||||
../../include/matador/query/criteria/abstract_column_criteria.hpp
|
../../include/matador/query/criteria/abstract_column_criteria.hpp
|
||||||
|
|
@ -50,13 +50,10 @@ add_library(matador-orm STATIC
|
||||||
../../include/matador/query/join_data.hpp
|
../../include/matador/query/join_data.hpp
|
||||||
../../include/matador/query/key_value_generator.hpp
|
../../include/matador/query/key_value_generator.hpp
|
||||||
../../include/matador/query/meta_table_macro.hpp
|
../../include/matador/query/meta_table_macro.hpp
|
||||||
../../include/matador/query/meta_table_macro.hpp
|
|
||||||
../../include/matador/query/query.hpp
|
../../include/matador/query/query.hpp
|
||||||
../../include/matador/query/query_builder.hpp
|
|
||||||
../../include/matador/query/query_compiler.hpp
|
../../include/matador/query/query_compiler.hpp
|
||||||
../../include/matador/query/query_data.hpp
|
../../include/matador/query/query_data.hpp
|
||||||
../../include/matador/query/query_intermediates.hpp
|
../../include/matador/query/query_intermediates.hpp
|
||||||
../../include/matador/query/query_object_resolver.hpp
|
|
||||||
../../include/matador/query/query_part.hpp
|
../../include/matador/query/query_part.hpp
|
||||||
../../include/matador/query/query_utils.hpp
|
../../include/matador/query/query_utils.hpp
|
||||||
../../include/matador/query/schema.hpp
|
../../include/matador/query/schema.hpp
|
||||||
|
|
@ -79,25 +76,19 @@ add_library(matador-orm STATIC
|
||||||
../../include/matador/sql/interface/query_result_reader.hpp
|
../../include/matador/sql/interface/query_result_reader.hpp
|
||||||
../../include/matador/sql/interface/statement_impl.hpp
|
../../include/matador/sql/interface/statement_impl.hpp
|
||||||
../../include/matador/sql/interface/statement_proxy.hpp
|
../../include/matador/sql/interface/statement_proxy.hpp
|
||||||
../../include/matador/sql/internal/identifier_reader.hpp
|
|
||||||
../../include/matador/sql/internal/identifier_statement_binder.hpp
|
|
||||||
../../include/matador/sql/internal/object_result_binder.hpp
|
../../include/matador/sql/internal/object_result_binder.hpp
|
||||||
../../include/matador/sql/internal/query_result_impl.hpp
|
../../include/matador/sql/internal/query_result_impl.hpp
|
||||||
../../include/matador/sql/internal/query_result_pk_resolver.hpp
|
../../include/matador/sql/internal/query_result_pk_resolver.hpp
|
||||||
../../include/matador/sql/internal/resolver_producer.hpp
|
|
||||||
../../include/matador/sql/internal/statement_object_resolver.hpp
|
|
||||||
../../include/matador/sql/producer_resolver_factory.hpp
|
|
||||||
../../include/matador/sql/query_context.hpp
|
../../include/matador/sql/query_context.hpp
|
||||||
../../include/matador/sql/query_record_result.hpp
|
|
||||||
../../include/matador/sql/query_result.hpp
|
../../include/matador/sql/query_result.hpp
|
||||||
../../include/matador/sql/record.hpp
|
../../include/matador/sql/record.hpp
|
||||||
../../include/matador/sql/sql_functions.hpp
|
../../include/matador/sql/sql_functions.hpp
|
||||||
../../include/matador/sql/statement.hpp
|
../../include/matador/sql/statement.hpp
|
||||||
../../include/matador/sql/statement_cache.hpp
|
|
||||||
orm/error_code.cpp
|
orm/error_code.cpp
|
||||||
|
orm/query_builder_exception.cpp
|
||||||
orm/session.cpp
|
orm/session.cpp
|
||||||
|
orm/session_query_builder.cpp
|
||||||
query/attribute_string_writer.cpp
|
query/attribute_string_writer.cpp
|
||||||
query/basic_schema.cpp
|
|
||||||
query/builder.cpp
|
query/builder.cpp
|
||||||
query/criteria/abstract_column_criteria.cpp
|
query/criteria/abstract_column_criteria.cpp
|
||||||
query/criteria/between_criteria.cpp
|
query/criteria/between_criteria.cpp
|
||||||
|
|
@ -142,10 +133,7 @@ add_library(matador-orm STATIC
|
||||||
query/internal/query_result_impl.cpp
|
query/internal/query_result_impl.cpp
|
||||||
query/key_value_generator.cpp
|
query/key_value_generator.cpp
|
||||||
query/query.cpp
|
query/query.cpp
|
||||||
query/query_builder.cpp
|
|
||||||
query/query_builder_exception.cpp
|
|
||||||
query/query_compiler.cpp
|
query/query_compiler.cpp
|
||||||
query/query_object_resolver.cpp
|
|
||||||
query/query_part.cpp
|
query/query_part.cpp
|
||||||
query/query_utils.cpp
|
query/query_utils.cpp
|
||||||
query/schema.cpp
|
query/schema.cpp
|
||||||
|
|
@ -165,17 +153,14 @@ add_library(matador-orm STATIC
|
||||||
sql/interface/query_result_reader.cpp
|
sql/interface/query_result_reader.cpp
|
||||||
sql/interface/statement_impl.cpp
|
sql/interface/statement_impl.cpp
|
||||||
sql/interface/statement_proxy.cpp
|
sql/interface/statement_proxy.cpp
|
||||||
sql/internal/identifier_reader.cpp
|
|
||||||
sql/internal/identifier_statement_binder.cpp
|
|
||||||
sql/internal/object_result_binder.cpp
|
sql/internal/object_result_binder.cpp
|
||||||
sql/internal/query_result_pk_resolver.cpp
|
sql/internal/query_result_pk_resolver.cpp
|
||||||
sql/internal/resolver_producer.cpp
|
|
||||||
sql/object_parameter_binder.cpp
|
sql/object_parameter_binder.cpp
|
||||||
sql/producer_resolver_factory.cpp
|
|
||||||
sql/query_result.cpp
|
sql/query_result.cpp
|
||||||
sql/record.cpp
|
sql/record.cpp
|
||||||
sql/statement.cpp
|
sql/statement.cpp
|
||||||
sql/statement_cache.cpp
|
sql/statement_cache.cpp
|
||||||
|
../../include/matador/query/meta_table_macro.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(matador-orm
|
target_include_directories(matador-orm
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include "matador/query/query_builder_exception.hpp"
|
#include "matador/orm/query_builder_exception.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::orm {
|
||||||
|
|
||||||
query_builder_exception::query_builder_exception(const query_build_error error, utils::error&& err)
|
query_builder_exception::query_builder_exception( const query_build_error error, utils::error&& err )
|
||||||
: error_type_(error)
|
: error_type_(error)
|
||||||
, error_( std::move(err) ) {}
|
, error_( std::move(err) ) {}
|
||||||
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "matador/sql/backend_provider.hpp"
|
#include "matador/sql/backend_provider.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/query_record_result.hpp"
|
|
||||||
|
|
||||||
#include "matador/query/query.hpp"
|
#include "matador/query/query.hpp"
|
||||||
|
|
||||||
|
|
@ -14,11 +13,9 @@ utils::error make_error(const error_code ec, const std::string &msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
session::session(session_context&& ctx, const query::schema &scm)
|
session::session(session_context&& ctx, const query::schema &scm)
|
||||||
: pool_(ctx.dns, ctx.connection_count, [ctx](const sql::connection_info& info) { return sql::connection(info, ctx.resolver_factory); })
|
: cache_(ctx.bus, ctx.pool, ctx.cache_size)
|
||||||
, cache_(ctx.bus, pool_, ctx.cache_size)
|
, dialect_(sql::backend_provider::instance().connection_dialect(ctx.pool.info().type))
|
||||||
, dialect_(sql::backend_provider::instance().connection_dialect(pool_.info().type))
|
, schema_(scm) {
|
||||||
, schema_(scm)
|
|
||||||
, resolver_factory_(ctx.resolver_factory) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<void, utils::error> session::drop_table(const std::string &table_name) const {
|
utils::result<void, utils::error> session::drop_table(const std::string &table_name) const {
|
||||||
|
|
@ -57,8 +54,10 @@ utils::result<sql::query_result<sql::record>, utils::error> session::fetch_all(c
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return utils::failure(res.err());
|
return utils::failure(res.err());
|
||||||
}
|
}
|
||||||
const auto prototype = res.value()->prototype();
|
const auto prototype = res.value()->prototype();
|
||||||
return utils::ok(sql::query_result<sql::record>{std::move(*res), prototype});
|
return utils::ok(sql::query_result<sql::record>{std::move(*res), [prototype] {
|
||||||
|
return sql::detail::create_prototype<sql::record>(prototype);
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<size_t, utils::error> session::execute(const std::string &sql) const {
|
utils::result<size_t, utils::error> session::execute(const std::string &sql) const {
|
||||||
|
|
@ -85,14 +84,6 @@ const class sql::dialect &session::dialect() const {
|
||||||
return dialect_;
|
return dialect_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<sql::producer_resolver_factory> session::resolver_factory() const {
|
|
||||||
return resolver_factory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const query::basic_schema & session::schema() const {
|
|
||||||
return schema_;
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> session::fetch(const sql::query_context& ctx) const {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> session::fetch(const sql::query_context& ctx) const {
|
||||||
if (const auto result = cache_.acquire(ctx); !result) {
|
if (const auto result = cache_.acquire(ctx); !result) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
|
|
@ -121,7 +112,7 @@ std::string session::str(const sql::query_context& ctx) const {
|
||||||
return ctx.sql;
|
return ctx.sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
query::fetchable_query session::build_select_query(query::entity_query_data &&data) {
|
query::fetchable_query session::build_select_query(entity_query_data &&data) {
|
||||||
return query::query::select(data.columns)
|
return query::query::select(data.columns)
|
||||||
.from(*data.root_table)
|
.from(*data.root_table)
|
||||||
.join_left(data.joins)
|
.join_left(data.joins)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include "matador/orm/session_query_builder.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace matador::orm {
|
||||||
|
criteria_transformer::criteria_transformer(const query::schema& repo, const std::unordered_map<std::string, query::table>& tables_by_name)
|
||||||
|
: repo_(repo)
|
||||||
|
, tables_by_name_(tables_by_name) {}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::between_criteria& node ) {
|
||||||
|
update_criteria_column(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::binary_criteria& node ) {
|
||||||
|
update_criteria_column(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::binary_column_criteria& /*node*/ ) {}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::collection_criteria& node ) {
|
||||||
|
update_criteria_column(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::collection_query_criteria& node ) {
|
||||||
|
update_criteria_column(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::like_criteria& node ) {
|
||||||
|
update_criteria_column(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::logical_criteria& node ) {
|
||||||
|
node.left_clause()->accept(*this);
|
||||||
|
node.right_clause()->accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::visit( const query::not_criteria& node ) {
|
||||||
|
node.clause()->accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void criteria_transformer::update_criteria_column(const query::abstract_column_criteria& node) const {
|
||||||
|
if (node.col().table() == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto it = tables_by_name_.find(node.col().table()->name());
|
||||||
|
if (it == tables_by_name_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_cast<query::table_column&>(node.col()).table(&it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void session_query_builder::on_revision(const char *id, uint64_t &/*rev*/) {
|
||||||
|
push(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void session_query_builder::push(const std::string &column_name) {
|
||||||
|
const auto it = processed_tables_.find(table_info_stack_.top().info.name());
|
||||||
|
if (it == processed_tables_.end()) {
|
||||||
|
throw query_builder_exception{query_build_error::UnexpectedError};
|
||||||
|
}
|
||||||
|
entity_query_data_.columns.emplace_back(&it->second, column_name, build_alias('c', ++column_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string session_query_builder::build_alias(const char prefix, const unsigned int count) {
|
||||||
|
char str[4];
|
||||||
|
snprintf(str, 4, "%c%02d", prefix, count);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool session_query_builder::is_root_entity() const {
|
||||||
|
return table_info_stack_.size() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void session_query_builder::append_join(const query::table_column &left, const query::table_column &right) {
|
||||||
|
using namespace matador::query;
|
||||||
|
entity_query_data_.joins.push_back({
|
||||||
|
right.table(),
|
||||||
|
std::make_unique<binary_column_criteria>(left, binary_operator::EQUALS, right)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
#include "matador/query/basic_schema.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/executor.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
|
||||||
schema_node::schema_node(class table tab, const object::repository_node& node)
|
|
||||||
: table_(std::move(tab))
|
|
||||||
, node_(std::move(node)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string & schema_node::name() const {
|
|
||||||
return table_.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
const table &schema_node::table() const {
|
|
||||||
return table_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const object::repository_node& schema_node::node() const {
|
|
||||||
return node_;
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::basic_schema()
|
|
||||||
: basic_schema("") {}
|
|
||||||
|
|
||||||
basic_schema::basic_schema(const std::string &name)
|
|
||||||
: repo_(name) {
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::iterator basic_schema::begin() {
|
|
||||||
return schema_nodes_.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::iterator basic_schema::end() {
|
|
||||||
return schema_nodes_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::const_iterator basic_schema::begin() const {
|
|
||||||
return schema_nodes_.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::const_iterator basic_schema::end() const {
|
|
||||||
return schema_nodes_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t basic_schema::size() const {
|
|
||||||
return schema_nodes_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool basic_schema::empty() const {
|
|
||||||
return schema_nodes_.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::iterator basic_schema::find(const std::type_index &ti) {
|
|
||||||
return schema_nodes_.find(ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::const_iterator basic_schema::find(const std::type_index &ti) const {
|
|
||||||
return schema_nodes_.find(ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::iterator basic_schema::find(const std::string &name) {
|
|
||||||
const auto result = repo_.basic_info(name);
|
|
||||||
if (!result) {
|
|
||||||
return schema_nodes_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
return schema_nodes_.find(result->get().type_index());
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_schema::const_iterator basic_schema::find(const std::string &name) const {
|
|
||||||
const auto result = repo_.basic_info(name);
|
|
||||||
if (!result) {
|
|
||||||
return schema_nodes_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
return schema_nodes_.find(result->get().type_index());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool basic_schema::contains(const std::type_index &index) const {
|
|
||||||
return schema_nodes_.count(index) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void basic_schema::initialize_executor(sql::executor &exec) const {
|
|
||||||
auto factory = std::make_shared<sql::producer_resolver_factory>();
|
|
||||||
for (const auto &[key, producer] : resolver_producers_) {
|
|
||||||
auto resolver = producer->produce(exec);
|
|
||||||
exec.resolver_factory()->register_resolver(std::move(resolver));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -5,22 +5,7 @@
|
||||||
#include "matador/query/criteria/logical_criteria.hpp"
|
#include "matador/query/criteria/logical_criteria.hpp"
|
||||||
#include "matador/query/criteria/not_criteria.hpp"
|
#include "matador/query/criteria/not_criteria.hpp"
|
||||||
|
|
||||||
#include "matador/utils/identifier.hpp"
|
|
||||||
#include "matador/utils/identifier_to_value_converter.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
criteria_ptr operator==(const table_column &col, const utils::identifier &id) {
|
|
||||||
utils::identifier_to_value_converter conv;
|
|
||||||
|
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, conv.convert(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
criteria_ptr operator!=(const table_column &col, const utils::identifier &id) {
|
|
||||||
utils::identifier_to_value_converter conv;
|
|
||||||
|
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::NOT_EQUALS, conv.convert(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
criteria_ptr operator==(const table_column &col, utils::placeholder p) {
|
criteria_ptr operator==(const table_column &col, utils::placeholder p) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, p);
|
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, p);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "matador/query/generator.hpp"
|
#include "matador/query/generator.hpp"
|
||||||
|
|
||||||
namespace matador::query::generator {
|
namespace matador::query::generator {
|
||||||
column_generator::column_generator(const basic_schema& repo, const table* tab, const column_generator_options options)
|
column_generator::column_generator(const schema& repo, const table* tab, const column_generator_options options)
|
||||||
: repo_(std::cref(repo))
|
: repo_(std::cref(repo))
|
||||||
, options_(options) {
|
, options_(options) {
|
||||||
table_stack_.push(tab);
|
table_stack_.push(tab);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include "matador/sql/executor.hpp"
|
#include "matador/sql/executor.hpp"
|
||||||
#include "matador/sql/field.hpp"
|
#include "matador/sql/field.hpp"
|
||||||
#include "matador/sql/statement.hpp"
|
#include "matador/sql/statement.hpp"
|
||||||
#include "matador/sql/query_record_result.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
|
|
@ -30,27 +29,29 @@ utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fet
|
||||||
return exec.fetch(ctx)
|
return exec.fetch(ctx)
|
||||||
.and_then([](auto &&res) {
|
.and_then([](auto &&res) {
|
||||||
const auto prototype = res->prototype();
|
const auto prototype = res->prototype();
|
||||||
return utils::ok(sql::query_result<sql::record>(std::forward<decltype(res)>(res), prototype));
|
return utils::ok(sql::query_result<sql::record>(std::forward<decltype(res)>(res), [prototype] {
|
||||||
|
return detail::create_prototype(prototype);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const {
|
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const {
|
||||||
query_compiler compiler;
|
query_compiler compiler;
|
||||||
auto ctx = compiler.compile(*context_, exec.dialect(), std::nullopt);
|
auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||||
ctx.resolver_factory = exec.resolver_factory();
|
|
||||||
auto result = exec.fetch(ctx);
|
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto prototype = result.value()->prototype();
|
const auto prototype = result.value()->prototype();
|
||||||
sql::query_result<sql::record> records(std::move(*result), prototype);
|
sql::query_result<sql::record> records(std::move(*result), [prototype] {
|
||||||
|
return detail::create_prototype(prototype);
|
||||||
|
});
|
||||||
auto first = records.begin();
|
auto first = records.begin();
|
||||||
if (first == records.end()) {
|
if (first == records.end()) {
|
||||||
return utils::ok(std::optional<sql::record>{std::nullopt});
|
return utils::ok(std::optional<sql::record>{std::nullopt});
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::ok(std::optional{first.release()});
|
return utils::ok(std::optional{*first.get()});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fetchable_query::str(const sql::executor &exec) const {
|
std::string fetchable_query::str(const sql::executor &exec) const {
|
||||||
|
|
@ -63,15 +64,11 @@ sql::query_context fetchable_query::compile(const sql::dialect &d) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const {
|
||||||
auto ctx = compile(exec.dialect());
|
return exec.fetch(compile(exec.dialect()));
|
||||||
ctx.resolver_factory = exec.resolver_factory();
|
|
||||||
return exec.fetch(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<sql::statement, utils::error> fetchable_query::prepare(sql::executor &exec) const {
|
utils::result<sql::statement, utils::error> fetchable_query::prepare(sql::executor &exec) const {
|
||||||
auto ctx = compile(exec.dialect());
|
return exec.prepare(compile(exec.dialect()));
|
||||||
ctx.resolver_factory = exec.resolver_factory();
|
|
||||||
return exec.prepare(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -8,15 +8,21 @@ detail::pk_reader::pk_reader(query_result_reader &reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader,
|
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader,
|
||||||
std::vector<object::attribute> prototype,
|
std::vector<object::attribute> &&prototype,
|
||||||
const std::shared_ptr<object::object_resolver_factory>& resolver_factory,
|
|
||||||
const size_t column_index)
|
const size_t column_index)
|
||||||
: column_index_(column_index)
|
: column_index_(column_index)
|
||||||
, prototype_(std::move(prototype))
|
, prototype_(std::move(prototype))
|
||||||
, reader_(std::move(reader))
|
, reader_(std::move(reader))
|
||||||
, resolver_factory_(resolver_factory)
|
, pk_reader_(*reader_) {
|
||||||
, id_reader_(*reader_)
|
}
|
||||||
, pk_reader_(*reader_) {
|
|
||||||
|
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader,
|
||||||
|
const std::vector<object::attribute> &prototype,
|
||||||
|
const size_t column_index)
|
||||||
|
: column_index_(column_index)
|
||||||
|
, prototype_(prototype)
|
||||||
|
, reader_(std::move(reader))
|
||||||
|
, pk_reader_(*reader_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_result_impl::on_revision(const char *id, uint64_t &rev) {
|
void query_result_impl::on_revision(const char *id, uint64_t &rev) {
|
||||||
|
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
#include "matador/query/query_builder.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
|
||||||
criteria_transformer::criteria_transformer(const basic_schema& repo, const std::unordered_map<std::string, table>& tables_by_name)
|
|
||||||
: repo_(repo)
|
|
||||||
, tables_by_name_(tables_by_name) {}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const between_criteria& node ) {
|
|
||||||
update_criteria_column(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const binary_criteria& node ) {
|
|
||||||
update_criteria_column(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const binary_column_criteria& /*node*/ ) {}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const collection_criteria& node ) {
|
|
||||||
update_criteria_column(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const collection_query_criteria& node ) {
|
|
||||||
update_criteria_column(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const like_criteria& node ) {
|
|
||||||
update_criteria_column(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const logical_criteria& node ) {
|
|
||||||
node.left_clause()->accept(*this);
|
|
||||||
node.right_clause()->accept(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::visit( const not_criteria& node ) {
|
|
||||||
node.clause()->accept(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void criteria_transformer::update_criteria_column(const abstract_column_criteria& node) const {
|
|
||||||
if (node.col().table() == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto it = tables_by_name_.find(node.col().table()->name());
|
|
||||||
if (it == tables_by_name_.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_cast<table_column&>(node.col()).table(&it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
void query_builder::on_revision(const char *id, uint64_t &/*rev*/) {
|
|
||||||
push(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void query_builder::push(const std::string &column_name) {
|
|
||||||
const auto it = processed_tables_.find(table_info_stack_.top().info.name());
|
|
||||||
if (it == processed_tables_.end()) {
|
|
||||||
throw query_builder_exception{query_build_error::UnexpectedError};
|
|
||||||
}
|
|
||||||
entity_query_data_.columns.emplace_back(&it->second, column_name, build_alias('c', ++column_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string query_builder::build_alias(const char prefix, const unsigned int count) {
|
|
||||||
char str[4];
|
|
||||||
snprintf(str, 4, "%c%02d", prefix, count);
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool query_builder::is_root_entity() const {
|
|
||||||
return table_info_stack_.size() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void query_builder::append_join(const table_column &left, const table_column &right) {
|
|
||||||
using namespace matador::query;
|
|
||||||
entity_query_data_.joins.push_back({
|
|
||||||
right.table(),
|
|
||||||
std::make_unique<binary_column_criteria>(left, binary_operator::EQUALS, right)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#include "matador/query/query_object_resolver.hpp"
|
|
||||||
|
|
||||||
#include "matador/query/criteria.hpp"
|
|
||||||
#include "matador/query/query.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
|
||||||
utils::result<sql::statement, utils::error> prepare_statement(sql::executor &exec, entity_query_data &&data) {
|
|
||||||
return query::query::select(data.columns)
|
|
||||||
.from(*data.root_table)
|
|
||||||
.join_left(data.joins)
|
|
||||||
.where(std::move(data.where_clause))
|
|
||||||
.order_by({data.root_table, data.pk_column_name})
|
|
||||||
.asc()
|
|
||||||
.prepare(exec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,6 +11,26 @@
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
schema_node::schema_node(class table tab, const object::repository_node& node)
|
||||||
|
: table_(std::move(tab))
|
||||||
|
, node_(std::move(node)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & schema_node::name() const {
|
||||||
|
return table_.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
const table &schema_node::table() const {
|
||||||
|
return table_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const object::repository_node& schema_node::node() const {
|
||||||
|
return node_;
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::schema(const std::string &name)
|
||||||
|
: repo_(name) {
|
||||||
|
}
|
||||||
|
|
||||||
utils::result<void, utils::error> schema::create(const sql::connection &conn) const {
|
utils::result<void, utils::error> schema::create(const sql::connection &conn) const {
|
||||||
// Step 1: Build dependency graph
|
// Step 1: Build dependency graph
|
||||||
|
|
@ -44,7 +64,7 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
|
||||||
|
|
||||||
std::vector<std::string> fk_sql_commands;
|
std::vector<std::string> fk_sql_commands;
|
||||||
|
|
||||||
const auto q = query::create().schema(repo_.name()).compile(conn);
|
const auto q = query::query::create().schema(repo_.name()).compile(conn);
|
||||||
std::cout << q.sql << std::endl;
|
std::cout << q.sql << std::endl;
|
||||||
|
|
||||||
// create plain tables without constraints
|
// create plain tables without constraints
|
||||||
|
|
@ -164,6 +184,60 @@ utils::result<bool, utils::error> schema::table_exists(const std::string &table_
|
||||||
return conn.exists(repo_.name(), table_name);
|
return conn.exists(repo_.name(), table_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
schema::iterator schema::begin() {
|
||||||
|
return schema_nodes_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::iterator schema::end() {
|
||||||
|
return schema_nodes_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::const_iterator schema::begin() const {
|
||||||
|
return schema_nodes_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::const_iterator schema::end() const {
|
||||||
|
return schema_nodes_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t schema::size() const {
|
||||||
|
return schema_nodes_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool schema::empty() const {
|
||||||
|
return schema_nodes_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::iterator schema::find(const std::type_index &ti) {
|
||||||
|
return schema_nodes_.find(ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::const_iterator schema::find(const std::type_index &ti) const {
|
||||||
|
return schema_nodes_.find(ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::iterator schema::find(const std::string &name) {
|
||||||
|
const auto result = repo_.basic_info(name);
|
||||||
|
if (!result) {
|
||||||
|
return schema_nodes_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema_nodes_.find(result->get().type_index());
|
||||||
|
}
|
||||||
|
|
||||||
|
schema::const_iterator schema::find(const std::string &name) const {
|
||||||
|
const auto result = repo_.basic_info(name);
|
||||||
|
if (!result) {
|
||||||
|
return schema_nodes_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema_nodes_.find(result->get().type_index());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool schema::contains(const std::type_index &index) const {
|
||||||
|
return schema_nodes_.count(index) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
void schema::dump(std::ostream &os) const {
|
void schema::dump(std::ostream &os) const {
|
||||||
repo_.dump(os);
|
repo_.dump(os);
|
||||||
}
|
}
|
||||||
|
|
@ -195,11 +269,11 @@ sql::query_context schema::build_drop_constraint_context(const object::repositor
|
||||||
.compile(conn);
|
.compile(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
schema::iterator schema::insert_table(const std::type_index &ti, const object::repository_node &node) {
|
void schema::insert_table(const std::type_index &ti, const object::repository_node &node) {
|
||||||
std::vector<table_column> columns;
|
std::vector<table_column> columns;
|
||||||
for (const auto &attr: node.info().attributes()) {
|
for (const auto &attr: node.info().attributes()) {
|
||||||
columns.emplace_back(nullptr, attr.name(), attr.type(), attr.attributes());
|
columns.emplace_back(nullptr, attr.name(), attr.type(), attr.attributes());
|
||||||
}
|
}
|
||||||
return schema_nodes_.insert({ti, schema_node{table(node.name(), columns), node}}).first;
|
std::ignore = schema_nodes_.insert({ti, schema_node{table(node.name(), columns), node}}).first;
|
||||||
}
|
}
|
||||||
} // namespace matador::query
|
} // namespace matador::query
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "matador/sql/backend_provider.hpp"
|
#include "matador/sql/backend_provider.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/dialect_token.hpp"
|
#include "matador/sql/dialect_token.hpp"
|
||||||
|
#include "matador/sql/error_code.hpp"
|
||||||
#include "matador/sql/interface/connection_impl.hpp"
|
#include "matador/sql/interface/connection_impl.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -27,29 +28,16 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
connection::connection(const connection_info& info, logger_ptr sql_logger)
|
connection::connection(const connection_info& info, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||||
: logger_(std::move(sql_logger)) {
|
: logger_(sql_logger)
|
||||||
|
{
|
||||||
connection_.reset(backend_provider::instance().create_connection(info.type, info));
|
connection_.reset(backend_provider::instance().create_connection(info.type, info));
|
||||||
}
|
}
|
||||||
|
|
||||||
connection::connection(const connection_info &info,
|
connection::connection(const std::string& dns, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||||
std::shared_ptr<producer_resolver_factory> resolver_factory,
|
|
||||||
logger_ptr sql_logger)
|
|
||||||
: logger_(std::move(sql_logger))
|
|
||||||
, resolver_factory_(std::move(resolver_factory)) {
|
|
||||||
connection_.reset(backend_provider::instance().create_connection(info.type, info));
|
|
||||||
}
|
|
||||||
|
|
||||||
connection::connection(const std::string& dns, const logger_ptr &sql_logger)
|
|
||||||
: connection(connection_info::parse(dns), sql_logger)
|
: connection(connection_info::parse(dns), sql_logger)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
connection::connection(const std::string &dns,
|
|
||||||
std::shared_ptr<producer_resolver_factory> resolver_factory,
|
|
||||||
const logger_ptr &sql_logger)
|
|
||||||
: connection(connection_info::parse(dns), std::move(resolver_factory), sql_logger)
|
|
||||||
{}
|
|
||||||
|
|
||||||
connection::connection(const connection &x) {
|
connection::connection(const connection &x) {
|
||||||
if (x.connection_) {
|
if (x.connection_) {
|
||||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||||
|
|
@ -70,13 +58,11 @@ connection &connection::operator=(const connection &x) {
|
||||||
connection::connection( connection&& x ) noexcept
|
connection::connection( connection&& x ) noexcept
|
||||||
: connection_(std::move(x.connection_))
|
: connection_(std::move(x.connection_))
|
||||||
, logger_(std::move(x.logger_))
|
, logger_(std::move(x.logger_))
|
||||||
, resolver_factory_(std::move(x.resolver_factory_))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
connection & connection::operator=(connection &&x) noexcept {
|
connection & connection::operator=(connection &&x) noexcept {
|
||||||
connection_ = std::move(x.connection_);
|
connection_ = std::move(x.connection_);
|
||||||
logger_ = std::move(x.logger_);
|
logger_ = std::move(x.logger_);
|
||||||
resolver_factory_ = std::move(x.resolver_factory_);
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +71,7 @@ connection::~connection() {
|
||||||
if (!connection_) {
|
if (!connection_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (const auto result = connection_->is_open(); *result) {
|
if (connection_->is_open()) {
|
||||||
connection_->close();
|
connection_->close();
|
||||||
}
|
}
|
||||||
connection_impl* impl = connection_.release();
|
connection_impl* impl = connection_.release();
|
||||||
|
|
@ -233,10 +219,6 @@ const class dialect &connection::dialect() const
|
||||||
return connection_->dialect();
|
return connection_->dialect();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<class producer_resolver_factory> connection::resolver_factory() const {
|
|
||||||
return resolver_factory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::result<std::unique_ptr<statement_impl>, utils::error> connection::perform_prepare(const query_context& ctx) const {
|
utils::result<std::unique_ptr<statement_impl>, utils::error> connection::perform_prepare(const query_context& ctx) const {
|
||||||
if (ctx.command != sql_command::SQL_CREATE_TABLE && (ctx.prototype.empty() || has_unknown_columns(ctx.prototype))) {
|
if (ctx.command != sql_command::SQL_CREATE_TABLE && (ctx.prototype.empty() || has_unknown_columns(ctx.prototype))) {
|
||||||
if (const auto result = describe(ctx.table_name); result.is_ok()) {
|
if (const auto result = describe(ctx.table_name); result.is_ok()) {
|
||||||
|
|
|
||||||
|
|
@ -53,19 +53,21 @@ bool connection_ptr::valid() const {
|
||||||
return connection_ != nullptr;
|
return connection_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_pool::connection_pool(const std::string& dns, const size_t count)
|
connection_pool::connection_pool(const std::string& dns, size_t count)
|
||||||
: connection_pool(dns, count, [](const connection_info &info) { return connection{info}; })
|
: info_(connection_info::parse(dns)) {
|
||||||
{}
|
|
||||||
|
|
||||||
connection_pool::connection_pool(const std::string &dns, size_t count, std::function<connection(const connection_info &)> &&connection_creator)
|
|
||||||
: info_(connection_info::parse(dns))
|
|
||||||
, connection_creator_(std::move(connection_creator)) {
|
|
||||||
connection_repo_.reserve(count);
|
connection_repo_.reserve(count);
|
||||||
while (count) {
|
while (count) {
|
||||||
connection_repo_.emplace_back(count, connection_creator_(info_));
|
// connection c(info_);
|
||||||
|
// auto&& cc = std::move(c);
|
||||||
|
// const auto ic = identifiable_connection{count, std::move(cc)};
|
||||||
|
// connection_repo_.push_back(ic);
|
||||||
|
// connection_repo_.emplace_back(count, std::move(cc));
|
||||||
|
connection_repo_.emplace_back(count, connection{info_});
|
||||||
auto &conn = connection_repo_.back();
|
auto &conn = connection_repo_.back();
|
||||||
idle_connections_.emplace(conn.id, &conn);
|
idle_connections_.emplace(conn.id, &conn);
|
||||||
if (const auto result = conn.conn.open(); !result) {
|
// Todo: handle result
|
||||||
|
const auto result = conn.conn.open();
|
||||||
|
if (!result) {
|
||||||
throw std::runtime_error("Failed to open connection");
|
throw std::runtime_error("Failed to open connection");
|
||||||
}
|
}
|
||||||
--count;
|
--count;
|
||||||
|
|
|
||||||
|
|
@ -35,17 +35,6 @@ field &field::operator=(field &&x) noexcept {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool field::operator==(const field &rhs) const {
|
|
||||||
return name_ == rhs.name_ &&
|
|
||||||
type_ == rhs.type_ &&
|
|
||||||
index_ == rhs.index_ &&
|
|
||||||
value_ == rhs.value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool field::operator!=(const field &rhs) const {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &field::name() const {
|
const std::string &field::name() const {
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#include "matador/sql/internal/identifier_reader.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql::internal {
|
|
||||||
identifier_reader::identifier_reader(query_result_reader &reader)
|
|
||||||
: reader_(reader) {}
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
#include "matador/sql/internal/identifier_statement_binder.hpp"
|
|
||||||
|
|
||||||
#include "matador/sql/statement.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
identifier_statement_binder::identifier_statement_binder(statement &stmt, const size_t index)
|
|
||||||
: stmt_(stmt)
|
|
||||||
, index_(index) {}
|
|
||||||
|
|
||||||
void identifier_statement_binder::bind(const utils::identifier &id) {
|
|
||||||
id.serialize(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(int8_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(int16_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(int32_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(int64_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(uint8_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(uint16_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(uint32_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(uint64_t &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(const char *value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(std::string &value, const utils::field_attributes &) {
|
|
||||||
stmt_.bind(index_, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void identifier_statement_binder::serialize(utils::null_type_t &/*value*/, const utils::field_attributes &) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
#include "matador/sql/internal/resolver_producer.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
const std::type_index & resolver_producer::type() const {
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolver_producer::resolver_producer(const std::type_index &type)
|
|
||||||
: type_(type) {}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#include "matador/sql/producer_resolver_factory.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
std::shared_ptr<object::abstract_object_resolver> producer_resolver_factory::acquire_resolver(const std::type_index &type) {
|
|
||||||
if (const auto it = resolvers_.find(type); it != resolvers_.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void producer_resolver_factory::register_resolver(std::shared_ptr<object::abstract_object_resolver> &&resolver) {
|
|
||||||
resolvers_[resolver->type()] = std::move(resolver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
namespace matador::sql::detail {
|
namespace matador::sql::detail {
|
||||||
|
|
||||||
record create_prototype(const std::vector<object::attribute> &prototype) {
|
template<>
|
||||||
record rec;
|
record *create_prototype<record>(const std::vector<object::attribute> &prototype) {
|
||||||
|
auto result = std::make_unique<record>();
|
||||||
int index{0};
|
int index{0};
|
||||||
for (const auto &col: prototype) {
|
for (const auto &col: prototype) {
|
||||||
rec.append({
|
result->append({
|
||||||
col.name(),
|
col.name(),
|
||||||
col.type(),
|
col.type(),
|
||||||
col.attributes().options(),
|
col.attributes().options(),
|
||||||
|
|
@ -17,7 +18,7 @@ record create_prototype(const std::vector<object::attribute> &prototype) {
|
||||||
index++
|
index++
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return rec;
|
return result.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,25 +70,9 @@ record::const_iterator record::find(const std::string &column_name) const {
|
||||||
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool record::operator==(const record &rhs) const {
|
|
||||||
if (size() != rhs.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for(size_t i = 0; i < size(); ++i) {
|
|
||||||
if (at(i) != rhs.at(i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool record::operator!=(const record &rhs) const {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void record::append(const field &col) {
|
void record::append(const field &col) {
|
||||||
const auto [fst, snd] = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||||
fields_.push_back(std::ref(fst->second.first));
|
fields_.push_back(std::ref(it.first->second.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
record::iterator record::begin()
|
record::iterator record::begin()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "matador/sql/statement.hpp"
|
#include "matador/sql/statement.hpp"
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
#include "matador/sql/field.hpp"
|
#include "matador/sql/field.hpp"
|
||||||
#include "matador/sql/query_record_result.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
@ -65,7 +64,9 @@ utils::result<query_result<record>, utils::error> statement::fetch() const {
|
||||||
}
|
}
|
||||||
// logger_.info(statement_->query_.sql);
|
// logger_.info(statement_->query_.sql);
|
||||||
const auto prototype = result.value()->prototype();
|
const auto prototype = result.value()->prototype();
|
||||||
return utils::ok(query_result<record>(std::move(*result), prototype));
|
return utils::ok(query_result<record>(std::move(*result), [prototype] {
|
||||||
|
return detail::create_prototype<record>(prototype);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<std::optional<record>, utils::error> statement::fetch_one() const {
|
utils::result<std::optional<record>, utils::error> statement::fetch_one() const {
|
||||||
|
|
@ -76,13 +77,15 @@ utils::result<std::optional<record>, utils::error> statement::fetch_one() const
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto prototype = result.value()->prototype();
|
const auto prototype = result.value()->prototype();
|
||||||
query_result<record> records(std::move(*result), prototype);
|
query_result<record> records(std::move(*result), [prototype] {
|
||||||
|
return sql::detail::create_prototype<record>(prototype);
|
||||||
|
});
|
||||||
auto first = records.begin();
|
auto first = records.begin();
|
||||||
if (first == records.end()) {
|
if (first == records.end()) {
|
||||||
return utils::ok(std::optional<record>{std::nullopt});
|
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 {
|
void statement::reset() const {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ TEST_CASE_METHOD(QueryFixture, "Insert and select basic datatypes", "[query][dat
|
||||||
.from("types")
|
.from("types")
|
||||||
.fetch_one<types>(db);
|
.fetch_one<types>(db);
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
REQUIRE(result->get() != nullptr);
|
REQUIRE(*result != nullptr);
|
||||||
|
|
||||||
REQUIRE((*result)->id_ == 1);
|
REQUIRE((*result)->id_ == 1);
|
||||||
REQUIRE((*result)->char_ == cval);
|
REQUIRE((*result)->char_ == cval);
|
||||||
|
|
@ -356,7 +356,7 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key", "[query][primary key]") {
|
||||||
.from("pk")
|
.from("pk")
|
||||||
.fetch_one<pk>(db);
|
.fetch_one<pk>(db);
|
||||||
REQUIRE(row.is_ok());
|
REQUIRE(row.is_ok());
|
||||||
REQUIRE(row->get() != nullptr);
|
REQUIRE(*row != nullptr);
|
||||||
REQUIRE(row.value()->id > 0);
|
REQUIRE(row.value()->id > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,7 +386,7 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key prepared", "[query][primary key
|
||||||
|
|
||||||
auto row = stmt->fetch_one<pk>();
|
auto row = stmt->fetch_one<pk>();
|
||||||
REQUIRE(row.is_ok());
|
REQUIRE(row.is_ok());
|
||||||
REQUIRE(*row);
|
REQUIRE(*row != nullptr);
|
||||||
REQUIRE(row.value()->id > 0);
|
REQUIRE(row.value()->id > 0);
|
||||||
REQUIRE(row.value()->name == "george");
|
REQUIRE(row.value()->name == "george");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ TEST_CASE_METHOD(QueryFixture, "Test insert statement", "[query][statement][inse
|
||||||
.fetch_one<person>(db);
|
.fetch_one<person>(db);
|
||||||
REQUIRE(row.is_ok());
|
REQUIRE(row.is_ok());
|
||||||
|
|
||||||
REQUIRE(*row);
|
REQUIRE(*row != nullptr);
|
||||||
REQUIRE((*row)->id == 1);
|
REQUIRE((*row)->id == 1);
|
||||||
REQUIRE((*row)->name == "george");
|
REQUIRE((*row)->name == "george");
|
||||||
REQUIRE((*row)->age == 45);
|
REQUIRE((*row)->age == 45);
|
||||||
|
|
@ -101,7 +101,7 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda
|
||||||
.fetch_one<person>(db);
|
.fetch_one<person>(db);
|
||||||
REQUIRE(row.is_ok());
|
REQUIRE(row.is_ok());
|
||||||
|
|
||||||
REQUIRE(*row);
|
REQUIRE(*row != nullptr);
|
||||||
REQUIRE((*row)->id == 1);
|
REQUIRE((*row)->id == 1);
|
||||||
REQUIRE((*row)->name == "george");
|
REQUIRE((*row)->name == "george");
|
||||||
REQUIRE((*row)->age == 45);
|
REQUIRE((*row)->age == 45);
|
||||||
|
|
@ -126,7 +126,7 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda
|
||||||
.fetch_one<person>(db);
|
.fetch_one<person>(db);
|
||||||
REQUIRE(row.is_ok());
|
REQUIRE(row.is_ok());
|
||||||
|
|
||||||
REQUIRE(*row);
|
REQUIRE(*row != nullptr);
|
||||||
REQUIRE((*row)->id == 1);
|
REQUIRE((*row)->id == 1);
|
||||||
REQUIRE((*row)->name == "george");
|
REQUIRE((*row)->name == "george");
|
||||||
REQUIRE((*row)->age == 36);
|
REQUIRE((*row)->age == 36);
|
||||||
|
|
@ -170,12 +170,12 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele
|
||||||
.fetch<person>();
|
.fetch<person>();
|
||||||
REQUIRE(rows.is_ok());
|
REQUIRE(rows.is_ok());
|
||||||
|
|
||||||
for (const auto r : *rows) {
|
for (const auto &r : *rows) {
|
||||||
constexpr size_t index = 1;
|
constexpr size_t index = 1;
|
||||||
REQUIRE(r->id == peoples[index].id);
|
REQUIRE(r.id == peoples[index].id);
|
||||||
REQUIRE(r->name == peoples[index].name);
|
REQUIRE(r.name == peoples[index].name);
|
||||||
REQUIRE(r->age == peoples[index].age);
|
REQUIRE(r.age == peoples[index].age);
|
||||||
REQUIRE(r->image == peoples[index].image);
|
REQUIRE(r.image == peoples[index].image);
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = query::remove()
|
stmt = query::remove()
|
||||||
|
|
@ -192,7 +192,9 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele
|
||||||
select_stmt->reset();
|
select_stmt->reset();
|
||||||
auto row = select_stmt->bind(0, "jane")
|
auto row = select_stmt->bind(0, "jane")
|
||||||
.fetch_one<person>();
|
.fetch_one<person>();
|
||||||
REQUIRE(!row);
|
REQUIRE(row.is_ok());
|
||||||
|
|
||||||
|
REQUIRE(*row == nullptr);
|
||||||
|
|
||||||
stmt->reset();
|
stmt->reset();
|
||||||
res = stmt->bind(0, "merlin")
|
res = stmt->bind(0, "merlin")
|
||||||
|
|
@ -203,7 +205,9 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele
|
||||||
select_stmt->reset();
|
select_stmt->reset();
|
||||||
row = select_stmt->bind(0, "merlin")
|
row = select_stmt->bind(0, "merlin")
|
||||||
.fetch_one<person>();
|
.fetch_one<person>();
|
||||||
REQUIRE(!row);
|
REQUIRE(row.is_ok());
|
||||||
|
|
||||||
|
REQUIRE(*row == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][statement][reuse]") {
|
TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][statement][reuse]") {
|
||||||
|
|
@ -243,10 +247,10 @@ TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][stateme
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (const auto &r : *rows) {
|
for (const auto &r : *rows) {
|
||||||
REQUIRE(r->id == peoples[index].id);
|
REQUIRE(r.id == peoples[index].id);
|
||||||
REQUIRE(r->name == peoples[index].name);
|
REQUIRE(r.name == peoples[index].name);
|
||||||
REQUIRE(r->age == peoples[index].age);
|
REQUIRE(r.age == peoples[index].age);
|
||||||
REQUIRE(r->image == peoples[index].image);
|
REQUIRE(r.image == peoples[index].image);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,10 +261,10 @@ TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][stateme
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
for (const auto &r : *rows) {
|
for (const auto &r : *rows) {
|
||||||
REQUIRE(r->id == peoples[index].id);
|
REQUIRE(r.id == peoples[index].id);
|
||||||
REQUIRE(r->name == peoples[index].name);
|
REQUIRE(r.name == peoples[index].name);
|
||||||
REQUIRE(r->age == peoples[index].age);
|
REQUIRE(r.age == peoples[index].age);
|
||||||
REQUIRE(r->image == peoples[index].image);
|
REQUIRE(r.image == peoples[index].image);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,9 +9,6 @@
|
||||||
#include "QueryFixture.hpp"
|
#include "QueryFixture.hpp"
|
||||||
|
|
||||||
#include "models/airplane.hpp"
|
#include "models/airplane.hpp"
|
||||||
#include "models/author.hpp"
|
|
||||||
#include "models/book.hpp"
|
|
||||||
#include "models/department.hpp"
|
|
||||||
#include "models/flight.hpp"
|
#include "models/flight.hpp"
|
||||||
#include "models/person.hpp"
|
#include "models/person.hpp"
|
||||||
#include "models/recipe.hpp"
|
#include "models/recipe.hpp"
|
||||||
|
|
@ -27,7 +24,7 @@ using namespace matador::test;
|
||||||
using namespace matador::query::meta;
|
using namespace matador::query::meta;
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query][foreign][relation]") {
|
TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query][foreign][relation]") {
|
||||||
const auto result = repo.attach<airplane>("airplane")
|
auto result = repo.attach<airplane>("airplane")
|
||||||
.and_then([this] { return repo.attach<flight>("flight");})
|
.and_then([this] { return repo.attach<flight>("flight");})
|
||||||
.and_then([this] {return repo.create(db); });
|
.and_then([this] {return repo.create(db); });
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
@ -81,9 +78,9 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[q
|
||||||
REQUIRE(result_person.is_ok());
|
REQUIRE(result_person.is_ok());
|
||||||
|
|
||||||
for (const auto &i: *result_person) {
|
for (const auto &i: *result_person) {
|
||||||
REQUIRE(i->id == 7);
|
REQUIRE(i.id == 7);
|
||||||
REQUIRE(i->name == "george");
|
REQUIRE(i.name == "george");
|
||||||
REQUIRE(i->age == 45);
|
REQUIRE(i.age == 45);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,9 +140,9 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for
|
||||||
REQUIRE(db.exists(FLIGHT.table_name()));
|
REQUIRE(db.exists(FLIGHT.table_name()));
|
||||||
|
|
||||||
std::vector planes{
|
std::vector planes{
|
||||||
object_ptr(std::make_shared<airplane>(1, "Airbus", "A380")),
|
object_ptr(new airplane{1, "Airbus", "A380"}),
|
||||||
object_ptr(std::make_shared<airplane>(2, "Boeing", "707")),
|
object_ptr(new airplane{2, "Boeing", "707"}),
|
||||||
object_ptr(std::make_shared<airplane>(3, "Boeing", "747"))
|
object_ptr(new airplane{3, "Boeing", "747"})
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
|
|
@ -163,7 +160,6 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for
|
||||||
REQUIRE(count.is_ok());
|
REQUIRE(count.is_ok());
|
||||||
REQUIRE(*count == 3);
|
REQUIRE(*count == 3);
|
||||||
|
|
||||||
|
|
||||||
flight f4711{4, planes.at(1), "hans"};
|
flight f4711{4, planes.at(1), "hans"};
|
||||||
|
|
||||||
auto res = query::insert()
|
auto res = query::insert()
|
||||||
|
|
@ -193,9 +189,9 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
||||||
REQUIRE(db.exists(FLIGHT.table_name()));
|
REQUIRE(db.exists(FLIGHT.table_name()));
|
||||||
|
|
||||||
std::vector planes{
|
std::vector planes{
|
||||||
object_ptr(std::make_shared<airplane>(1, "Airbus", "A380")),
|
object_ptr(new airplane{1, "Airbus", "A380"}),
|
||||||
object_ptr(std::make_shared<airplane>(2, "Boeing", "707")),
|
object_ptr(new airplane{2, "Boeing", "707"}),
|
||||||
object_ptr(std::make_shared<airplane>(3, "Boeing", "747"))
|
object_ptr(new airplane{3, "Boeing", "747"})
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
|
|
@ -213,10 +209,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left"
|
||||||
REQUIRE(count == 3);
|
REQUIRE(count == 3);
|
||||||
|
|
||||||
std::vector flights{
|
std::vector flights{
|
||||||
object_ptr(std::make_shared<flight>(4, planes.at(0), "hans")),
|
object_ptr(new flight{4, planes.at(0), "hans"}),
|
||||||
object_ptr(std::make_shared<flight>(5, planes.at(0), "otto")),
|
object_ptr(new flight{5, planes.at(0), "otto"}),
|
||||||
object_ptr(std::make_shared<flight>(6, planes.at(1), "george")),
|
object_ptr(new flight{6, planes.at(1), "george"}),
|
||||||
object_ptr(std::make_shared<flight>(7, planes.at(2), "paul"))
|
object_ptr(new flight{7, planes.at(2), "paul"})
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &f: flights) {
|
for (const auto &f: flights) {
|
||||||
|
|
@ -268,15 +264,13 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
||||||
.and_then([this] {return repo.create(db); });
|
.and_then([this] {return repo.create(db); });
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
repo.initialize_executor(db);
|
|
||||||
|
|
||||||
REQUIRE(db.exists(AIRPLANE.table_name()));
|
REQUIRE(db.exists(AIRPLANE.table_name()));
|
||||||
REQUIRE(db.exists(FLIGHT.table_name()));
|
REQUIRE(db.exists(FLIGHT.table_name()));
|
||||||
|
|
||||||
std::vector planes{
|
std::vector planes{
|
||||||
object_ptr(std::make_shared<airplane>(1, "Airbus", "A380")),
|
object_ptr(new airplane{1, "Airbus", "A380"}),
|
||||||
object_ptr(std::make_shared<airplane>(2, "Boeing", "707")),
|
object_ptr(new airplane{2, "Boeing", "707"}),
|
||||||
object_ptr(std::make_shared<airplane>(3, "Boeing", "747"))
|
object_ptr(new airplane{3, "Boeing", "747"})
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
|
|
@ -296,10 +290,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single
|
||||||
REQUIRE(count->value() == 3);
|
REQUIRE(count->value() == 3);
|
||||||
|
|
||||||
std::vector flights{
|
std::vector flights{
|
||||||
object_ptr(std::make_shared<flight>(4, planes.at(0), "hans")),
|
object_ptr(new flight{4, planes.at(0), "hans"}),
|
||||||
object_ptr(std::make_shared<flight>(5, planes.at(0), "otto")),
|
object_ptr(new flight{5, planes.at(0), "otto"}),
|
||||||
object_ptr(std::make_shared<flight>(6, planes.at(1), "george")),
|
object_ptr(new flight{6, planes.at(1), "george"}),
|
||||||
object_ptr(std::make_shared<flight>(7, planes.at(2), "paul"))
|
object_ptr(new flight{7, planes.at(2), "paul"})
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &f: flights) {
|
for (const auto &f: flights) {
|
||||||
|
|
@ -498,8 +492,8 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with eager has many relation",
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
const std::vector shipments {
|
const std::vector shipments {
|
||||||
object_ptr{std::make_shared<shipment>(1, "4711")},
|
object_ptr{new shipment{1, "4711"}},
|
||||||
object_ptr{std::make_shared<shipment>(2, "0815")}
|
object_ptr{new shipment{2, "0815"}}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &sh: shipments) {
|
for (const auto &sh: shipments) {
|
||||||
|
|
@ -518,11 +512,11 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with eager has many relation",
|
||||||
REQUIRE(*count == 2);
|
REQUIRE(*count == 2);
|
||||||
|
|
||||||
std::vector packages {
|
std::vector packages {
|
||||||
object_ptr{std::make_shared<package>(3, 15.4, shipments.at(0))},
|
object_ptr{new package{3, 15.4, shipments.at(0)}},
|
||||||
object_ptr{std::make_shared<package>(4, 1.3, shipments.at(0))},
|
object_ptr{new package{4, 1.3, shipments.at(0)}},
|
||||||
object_ptr{std::make_shared<package>(5, 30.9, shipments.at(1))},
|
object_ptr{new package{5, 30.9, shipments.at(1)}},
|
||||||
object_ptr{std::make_shared<package>(6, 22.8, shipments.at(1))},
|
object_ptr{new package{6, 22.8, shipments.at(1)}},
|
||||||
object_ptr{std::make_shared<package>(7, 17.2, shipments.at(1))}
|
object_ptr{new package{7, 17.2, shipments.at(1)}}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &pkg: packages) {
|
for (const auto &pkg: packages) {
|
||||||
|
|
@ -579,161 +573,8 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with eager has many relation",
|
||||||
std::vector<size_t> packages_sizes{2, 3};
|
std::vector<size_t> packages_sizes{2, 3};
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
for (const auto &s : *shipment_result) {
|
for (const auto &s : *shipment_result) {
|
||||||
REQUIRE(s->id == shipments.at(index)->id);
|
REQUIRE(s.id == shipments.at(index)->id);
|
||||||
REQUIRE(s->tracking_number == shipments.at(index)->tracking_number);
|
REQUIRE(s.tracking_number == shipments.at(index)->tracking_number);
|
||||||
REQUIRE(s->packages.size() == packages_sizes.at(index++));
|
REQUIRE(s.packages.size() == packages_sizes.at(index++));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, "Test load entity with lazy belongs to relation", "[query][belongs_to][lazy]") {
|
|
||||||
auto result = repo.attach<department>("departments")
|
|
||||||
.and_then([this] { return repo.attach<employee>("employees"); })
|
|
||||||
.and_then([this] {return repo.create(db); });
|
|
||||||
REQUIRE(result.is_ok());
|
|
||||||
|
|
||||||
repo.initialize_executor(db);
|
|
||||||
|
|
||||||
const std::vector deps {
|
|
||||||
object_ptr{std::make_shared<department>(1, "Human Resources")},
|
|
||||||
object_ptr{std::make_shared<department>(2, "Invoices")}
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector emps {
|
|
||||||
object_ptr{std::make_shared<employee>(3, "Hans", "Wurst", deps[0])},
|
|
||||||
object_ptr{std::make_shared<employee>(4, "Steven", "Spielberg", deps[0])},
|
|
||||||
object_ptr{std::make_shared<employee>(5, "Julia", "Roberts", deps[0])},
|
|
||||||
object_ptr{std::make_shared<employee>(6, "Otto", "Walkes", deps[1])},
|
|
||||||
object_ptr{std::make_shared<employee>(7, "Miss", "Marple", deps[1])},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &dep: deps) {
|
|
||||||
auto res = query::insert()
|
|
||||||
.into(DEPARTMENT, {DEPARTMENT.id, DEPARTMENT.name})
|
|
||||||
.values(*dep)
|
|
||||||
.execute(db);
|
|
||||||
REQUIRE(res.is_ok());
|
|
||||||
REQUIRE(*res == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto count = query::select({count_all()})
|
|
||||||
.from(DEPARTMENT)
|
|
||||||
.fetch_value<int>(db);
|
|
||||||
REQUIRE(count.is_ok());
|
|
||||||
REQUIRE(*count == 2);
|
|
||||||
|
|
||||||
for (const auto &emp: emps) {
|
|
||||||
auto res = query::insert()
|
|
||||||
.into(EMPLOYEE, {EMPLOYEE.id, EMPLOYEE.first_name, EMPLOYEE.last_name, EMPLOYEE.dep_id})
|
|
||||||
.values(*emp)
|
|
||||||
.execute(db);
|
|
||||||
REQUIRE(res.is_ok());
|
|
||||||
REQUIRE(*res == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = query::select({count_all()})
|
|
||||||
.from(EMPLOYEE)
|
|
||||||
.fetch_value<int>(db);
|
|
||||||
REQUIRE(count.is_ok());
|
|
||||||
REQUIRE(*count == 5);
|
|
||||||
|
|
||||||
// auto emps_result = query::select({EMPLOYEE.id, EMPLOYEE.first_name, EMPLOYEE.last_name, DEPARTMENT.id, DEPARTMENT.name})
|
|
||||||
// .from(EMPLOYEE)
|
|
||||||
// .join_left(DEPARTMENT)
|
|
||||||
// .on(EMPLOYEE.dep_id == DEPARTMENT.id)
|
|
||||||
// .order_by(EMPLOYEE.id).asc()
|
|
||||||
// .fetch_all<employee>(db);
|
|
||||||
|
|
||||||
auto emps_result = query::select({EMPLOYEE.id, EMPLOYEE.first_name, EMPLOYEE.last_name, EMPLOYEE.dep_id})
|
|
||||||
.from(EMPLOYEE)
|
|
||||||
.order_by(EMPLOYEE.id).asc()
|
|
||||||
.fetch_all<employee>(db);
|
|
||||||
|
|
||||||
REQUIRE(emps_result.is_ok());
|
|
||||||
size_t index{0};
|
|
||||||
for (const auto &e : *emps_result) {
|
|
||||||
REQUIRE(e->id == emps.at(index)->id);
|
|
||||||
REQUIRE(e->first_name == emps.at(index)->first_name);
|
|
||||||
REQUIRE(e->last_name == emps.at(index)->last_name);
|
|
||||||
REQUIRE(e->dep->id == emps.at(index)->dep->id);
|
|
||||||
REQUIRE(e->dep->name == emps.at(index)->dep->name);
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, "Test load entity with eager belongs to relation", "[query][belongs_to][eager]") {
|
|
||||||
auto result = repo.attach<author>("authors")
|
|
||||||
.and_then( [this] { return repo.attach<book>("books"); } )
|
|
||||||
.and_then([this] {
|
|
||||||
return repo.create(db);
|
|
||||||
} );
|
|
||||||
|
|
||||||
const std::vector authors {
|
|
||||||
object_ptr{std::make_shared<author>(1, "Michael", "Crichton", "23.10.1942", 1975, true)},
|
|
||||||
object_ptr{std::make_shared<author>( 2, "Steven", "King", "21.9.1947", 1956, false)}
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector books {
|
|
||||||
object_ptr{std::make_shared<book>(3, "Jurassic Park", authors[0], 1990)},
|
|
||||||
object_ptr{std::make_shared<book>(4, "Timeline", authors[0], 1999)},
|
|
||||||
object_ptr{std::make_shared<book>(5, "The Andromeda Strain", authors[0], 1969)},
|
|
||||||
object_ptr{std::make_shared<book>(6, "Congo", authors[0], 1980)},
|
|
||||||
object_ptr{std::make_shared<book>(7, "Prey", authors[0], 2002)},
|
|
||||||
object_ptr{std::make_shared<book>(8, "Carrie", authors[1], 1974)},
|
|
||||||
object_ptr{std::make_shared<book>(9, "The Shining", authors[1], 1977)},
|
|
||||||
object_ptr{std::make_shared<book>(10, "It", authors[1], 1986)},
|
|
||||||
object_ptr{std::make_shared<book>(11, "Misery", authors[1], 1987)},
|
|
||||||
object_ptr{std::make_shared<book>(12, "The Dark Tower: The Gunslinger", authors[1], 1982)},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &a: authors) {
|
|
||||||
auto res = query::insert()
|
|
||||||
.into(AUTHOR, {AUTHOR.id, AUTHOR.first_name, AUTHOR.last_name, AUTHOR.date_of_birth, AUTHOR.year_of_birth, AUTHOR.distinguished})
|
|
||||||
.values(*a)
|
|
||||||
.execute(db);
|
|
||||||
REQUIRE(res.is_ok());
|
|
||||||
REQUIRE(*res == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto count = query::select({count_all()})
|
|
||||||
.from(AUTHOR)
|
|
||||||
.fetch_value<int>(db);
|
|
||||||
REQUIRE(count.is_ok());
|
|
||||||
REQUIRE(*count == 2);
|
|
||||||
|
|
||||||
for (const auto &b: books) {
|
|
||||||
auto res = query::insert()
|
|
||||||
.into(BOOK, {BOOK.id, BOOK.title, BOOK.author_id, BOOK.published_in})
|
|
||||||
.values(*b)
|
|
||||||
.execute(db);
|
|
||||||
REQUIRE(res.is_ok());
|
|
||||||
REQUIRE(*res == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = query::select({count_all()})
|
|
||||||
.from(BOOK)
|
|
||||||
.fetch_value<int>(db);
|
|
||||||
REQUIRE(count.is_ok());
|
|
||||||
REQUIRE(*count == 10);
|
|
||||||
|
|
||||||
auto books_result = query::select({BOOK.id, BOOK.title, AUTHOR.id, AUTHOR.first_name, AUTHOR.last_name, AUTHOR.date_of_birth, AUTHOR.year_of_birth, AUTHOR.distinguished, BOOK.published_in})
|
|
||||||
.from(BOOK)
|
|
||||||
.join_left(AUTHOR)
|
|
||||||
.on(BOOK.author_id == AUTHOR.id)
|
|
||||||
.order_by(BOOK.id).asc()
|
|
||||||
.fetch_all<book>(db);
|
|
||||||
|
|
||||||
REQUIRE(books_result.is_ok());
|
|
||||||
size_t index{0};
|
|
||||||
for (const auto &b : *books_result) {
|
|
||||||
REQUIRE(b->id == books.at(index)->id);
|
|
||||||
REQUIRE(b->title == books.at(index)->title);
|
|
||||||
REQUIRE(b->book_author->id == books.at(index)->book_author->id);
|
|
||||||
REQUIRE(b->book_author->first_name == books.at(index)->book_author->first_name);
|
|
||||||
REQUIRE(b->book_author->last_name == books.at(index)->book_author->last_name);
|
|
||||||
REQUIRE(b->book_author->date_of_birth == books.at(index)->book_author->date_of_birth);
|
|
||||||
REQUIRE(b->book_author->year_of_birth == books.at(index)->book_author->year_of_birth);
|
|
||||||
REQUIRE(b->book_author->distinguished == books.at(index)->book_author->distinguished);
|
|
||||||
REQUIRE(b->published_in == books.at(index)->published_in);
|
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,15 +7,13 @@
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
SessionFixture::SessionFixture()
|
SessionFixture::SessionFixture()
|
||||||
: ses({bus, connection::dns, 4}, schema)
|
: pool(connection::dns, 4)
|
||||||
, db(connection::dns) {
|
, ses({bus, pool}, schema) {}
|
||||||
REQUIRE(db.open());
|
|
||||||
}
|
|
||||||
|
|
||||||
SessionFixture::~SessionFixture() {
|
SessionFixture::~SessionFixture() {
|
||||||
const auto result = schema.drop(db);
|
const auto conn = pool.acquire();
|
||||||
|
const auto result = schema.drop(*conn);
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
REQUIRE(db.close());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionFixture::drop_table_if_exists(const std::string &table_name) const {
|
void SessionFixture::drop_table_if_exists(const std::string &table_name) const {
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ public:
|
||||||
~SessionFixture();
|
~SessionFixture();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
sql::connection_pool pool;
|
||||||
orm::session ses;
|
orm::session ses;
|
||||||
utils::message_bus bus;
|
utils::message_bus bus;
|
||||||
sql::connection db;
|
|
||||||
|
|
||||||
query::schema schema;
|
query::schema schema;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ using namespace matador::test;
|
||||||
TEST_CASE_METHOD(SessionFixture, "Session insert test", "[session][insert]") {
|
TEST_CASE_METHOD(SessionFixture, "Session insert test", "[session][insert]") {
|
||||||
const auto result = schema.attach<airplane>("airplanes")
|
const auto result = schema.attach<airplane>("airplanes")
|
||||||
.and_then([this] {
|
.and_then([this] {
|
||||||
return schema.create(db);
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
} );
|
} );
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
|
|
@ -36,7 +37,8 @@ TEST_CASE_METHOD(SessionFixture, "Session insert test", "[session][insert]") {
|
||||||
TEST_CASE_METHOD(SessionFixture, "Session update test", "[session][update]") {
|
TEST_CASE_METHOD(SessionFixture, "Session update test", "[session][update]") {
|
||||||
const auto res = schema.attach<airplane>("airplanes")
|
const auto res = schema.attach<airplane>("airplanes")
|
||||||
.and_then([this] {
|
.and_then([this] {
|
||||||
return schema.create(db);
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
} );
|
} );
|
||||||
REQUIRE(res.is_ok());
|
REQUIRE(res.is_ok());
|
||||||
|
|
||||||
|
|
@ -67,11 +69,12 @@ TEST_CASE_METHOD(SessionFixture, "Session update test", "[session][update]") {
|
||||||
|
|
||||||
TEST_CASE_METHOD(SessionFixture, "Session delete test", "[session][delete]") {
|
TEST_CASE_METHOD(SessionFixture, "Session delete test", "[session][delete]") {
|
||||||
const auto res = schema.attach<airplane>("airplanes")
|
const auto res = schema.attach<airplane>("airplanes")
|
||||||
.and_then([this] { return schema.create(db); } );
|
.and_then([this] {
|
||||||
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
|
} );
|
||||||
REQUIRE(res.is_ok());
|
REQUIRE(res.is_ok());
|
||||||
|
|
||||||
schema.initialize_executor(ses);
|
|
||||||
|
|
||||||
auto result = ses.insert<airplane>(1, "Boeing", "747");
|
auto result = ses.insert<airplane>(1, "Boeing", "747");
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
|
|
@ -91,7 +94,10 @@ TEST_CASE_METHOD(SessionFixture, "Session delete test", "[session][delete]") {
|
||||||
TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") {
|
TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") {
|
||||||
const auto result = schema.attach<airplane>("airplanes")
|
const auto result = schema.attach<airplane>("airplanes")
|
||||||
.and_then([this] { return schema.attach<flight>("flights"); } )
|
.and_then([this] { return schema.attach<flight>("flights"); } )
|
||||||
.and_then([this] { return schema.create(db); } );
|
.and_then([this] {
|
||||||
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
|
} );
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
auto plane = ses.insert<airplane>(1, "Boeing", "A380");
|
auto plane = ses.insert<airplane>(1, "Boeing", "A380");
|
||||||
|
|
@ -112,7 +118,10 @@ TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]")
|
||||||
|
|
||||||
TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session][find]") {
|
TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session][find]") {
|
||||||
const auto result = schema.attach<airplane>("airplanes")
|
const auto result = schema.attach<airplane>("airplanes")
|
||||||
.and_then([this] { return schema.create(db); } );
|
.and_then([this] {
|
||||||
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
|
} );
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
auto a380 = ses.insert<airplane>(1, "Boeing", "A380");
|
auto a380 = ses.insert<airplane>(1, "Boeing", "A380");
|
||||||
|
|
@ -132,7 +141,8 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session
|
||||||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][find]") {
|
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][find]") {
|
||||||
const auto result = schema.attach<airplane>("airplanes")
|
const auto result = schema.attach<airplane>("airplanes")
|
||||||
.and_then([this] {
|
.and_then([this] {
|
||||||
return schema.create(db);
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
} );
|
} );
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
||||||
|
|
@ -157,9 +167,9 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f
|
||||||
auto all_planes = find_result.release();
|
auto all_planes = find_result.release();
|
||||||
size_t index {0};
|
size_t index {0};
|
||||||
for (const auto &i: all_planes) {
|
for (const auto &i: all_planes) {
|
||||||
REQUIRE(i->id == std::get<0>(expected_result[index]));
|
REQUIRE(i.id == std::get<0>(expected_result[index]));
|
||||||
REQUIRE(i->brand == std::get<1>(expected_result[index]));
|
REQUIRE(i.brand == std::get<1>(expected_result[index]));
|
||||||
REQUIRE(i->model == std::get<2>(expected_result[index]));
|
REQUIRE(i.model == std::get<2>(expected_result[index]));
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,16 +177,17 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f
|
||||||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many lazy relation", "[session][find][one-to-many][eager]") {
|
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many lazy relation", "[session][find][one-to-many][eager]") {
|
||||||
auto result = schema.attach<author>("authors")
|
auto result = schema.attach<author>("authors")
|
||||||
.and_then( [this] { return schema.attach<book>("books"); } )
|
.and_then( [this] { return schema.attach<book>("books"); } )
|
||||||
.and_then([this] { return schema.create(db); } );
|
.and_then([this] {
|
||||||
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
|
} );
|
||||||
|
|
||||||
schema.initialize_executor(ses);
|
std::vector<std::unique_ptr<author>> authors;
|
||||||
std::vector authors {
|
authors.emplace_back(new author{1, "Michael", "Crichton", "23.10.1942", 1975, true, {}});
|
||||||
object_ptr{std::make_shared<author>(1, "Michael", "Crichton", "23.10.1942", 1975, true)},
|
authors.emplace_back(new author{ 2, "Steven", "King", "21.9.1947", 1956, false, {}});
|
||||||
object_ptr{std::make_shared<author>( 2, "Steven", "King", "21.9.1947", 1956, false)}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &a: authors) {
|
for (auto &&a: authors) {
|
||||||
auto res = ses.insert(a);
|
auto res = ses.insert(a.release());
|
||||||
REQUIRE(res.is_ok());
|
REQUIRE(res.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,7 +197,7 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
|
||||||
std::vector<object_ptr<author>> author_repo;
|
std::vector<object_ptr<author>> author_repo;
|
||||||
for (auto it = all_authors.begin(); it != all_authors.end(); ++it) {
|
for (auto it = all_authors.begin(); it != all_authors.end(); ++it) {
|
||||||
std::cout << "author: " << it->first_name << " (books: " << it->books.size() << ")\n";
|
std::cout << "author: " << it->first_name << " (books: " << it->books.size() << ")\n";
|
||||||
author_repo.emplace_back(it.optr());
|
author_repo.emplace_back(it.release());
|
||||||
}
|
}
|
||||||
REQUIRE(author_repo.size() == 2);
|
REQUIRE(author_repo.size() == 2);
|
||||||
|
|
||||||
|
|
@ -220,12 +231,13 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
|
||||||
auto result = schema.attach<department>("departments")
|
auto result = schema.attach<department>("departments")
|
||||||
.and_then( [this] { return schema.attach<employee>("employees"); } )
|
.and_then( [this] { return schema.attach<employee>("employees"); } )
|
||||||
.and_then([this] {
|
.and_then([this] {
|
||||||
return schema.create(db);
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
std::vector<std::unique_ptr<department>> departments;
|
std::vector<std::unique_ptr<department>> departments;
|
||||||
departments.emplace_back(new department{1, "Insurance"});
|
departments.emplace_back(new department{1, "Insurance", {}});
|
||||||
departments.emplace_back(new department{2, "Invoice"});
|
departments.emplace_back(new department{2, "Invoice", {}});
|
||||||
|
|
||||||
for (auto &&a: departments) {
|
for (auto &&a: departments) {
|
||||||
auto res = ses.insert(a.release());
|
auto res = ses.insert(a.release());
|
||||||
|
|
@ -238,7 +250,7 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
|
||||||
std::vector<object_ptr<department>> departments_repo;
|
std::vector<object_ptr<department>> departments_repo;
|
||||||
for (auto it = all_departments.begin(); it != all_departments.end(); ++it) {
|
for (auto it = all_departments.begin(); it != all_departments.end(); ++it) {
|
||||||
std::cout << "department: " << it->name << " (employees: " << it->employees.size() << ")\n";
|
std::cout << "department: " << it->name << " (employees: " << it->employees.size() << ")\n";
|
||||||
departments_repo.emplace_back(it.optr());
|
departments_repo.emplace_back(it.release());
|
||||||
}
|
}
|
||||||
REQUIRE(departments_repo.size() == 2);
|
REQUIRE(departments_repo.size() == 2);
|
||||||
|
|
||||||
|
|
@ -275,7 +287,8 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with many-to-m
|
||||||
auto result = schema.attach<recipe>("recipes")
|
auto result = schema.attach<recipe>("recipes")
|
||||||
.and_then( [this] { return schema.attach<ingredient>("ingredients"); } )
|
.and_then( [this] { return schema.attach<ingredient>("ingredients"); } )
|
||||||
.and_then([this] {
|
.and_then([this] {
|
||||||
return schema.create(db);
|
const auto conn = pool.acquire();
|
||||||
|
return schema.create(*conn);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ingredient>> ingredients;
|
std::vector<std::unique_ptr<ingredient>> ingredients;
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,24 @@ using namespace matador::query;
|
||||||
using namespace matador::test;
|
using namespace matador::test;
|
||||||
using namespace matador::query::meta;
|
using namespace matador::query::meta;
|
||||||
|
|
||||||
|
namespace matador::test::detail {
|
||||||
|
template<class Type, typename... Args>
|
||||||
|
[[maybe_unused]] object_ptr<Type> make_object_ptr(Args&&... args) {
|
||||||
|
return object_ptr(new Type(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class StatementTestFixture : public QueryFixture {
|
class StatementTestFixture : public QueryFixture {
|
||||||
public:
|
public:
|
||||||
StatementTestFixture() {
|
StatementTestFixture() {
|
||||||
REQUIRE(repo.attach<airplane>("airplanes"));
|
REQUIRE(repo.attach<airplane>("airplanes"));
|
||||||
repo.initialize_executor(db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<airplane> planes {
|
std::vector<object_ptr<airplane>> planes{
|
||||||
{1, "Airbus", "A380"},
|
matador::test::detail::make_object_ptr<airplane>(1, "Airbus", "A380"),
|
||||||
{2, "Boeing", "707"},
|
matador::test::detail::make_object_ptr<airplane>(2, "Boeing", "707"),
|
||||||
{3, "Boeing", "747"}
|
matador::test::detail::make_object_ptr<airplane>(3, "Boeing", "747")
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -47,7 +53,7 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]
|
||||||
REQUIRE(stmt.is_ok());
|
REQUIRE(stmt.is_ok());
|
||||||
|
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
auto res = stmt->bind(plane).execute();
|
auto res = stmt->bind(*plane).execute();
|
||||||
REQUIRE(res.is_ok());
|
REQUIRE(res.is_ok());
|
||||||
REQUIRE(*res == 1);
|
REQUIRE(*res == 1);
|
||||||
stmt->reset();
|
stmt->reset();
|
||||||
|
|
@ -60,9 +66,9 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
size_t index{0};
|
size_t index{0};
|
||||||
for (const auto &i: *result) {
|
for (const auto &i: *result) {
|
||||||
REQUIRE(i->id == planes[index].id);
|
REQUIRE(i.id == planes[index]->id);
|
||||||
REQUIRE(i->brand == planes[index].brand);
|
REQUIRE(i.brand == planes[index]->brand);
|
||||||
REQUIRE(i->model == planes[index++].model);
|
REQUIRE(i.model == planes[index++]->model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,13 +76,13 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]
|
||||||
for (const auto &plane: planes) {
|
for (const auto &plane: planes) {
|
||||||
auto res = query::insert()
|
auto res = query::insert()
|
||||||
.into(AIRPLANE, {AIRPLANE.id, AIRPLANE.brand, AIRPLANE.model})
|
.into(AIRPLANE, {AIRPLANE.id, AIRPLANE.brand, AIRPLANE.model})
|
||||||
.values(plane)
|
.values(*plane)
|
||||||
.execute(db);
|
.execute(db);
|
||||||
REQUIRE(res.is_ok());
|
REQUIRE(res.is_ok());
|
||||||
REQUIRE(*res == 1);
|
REQUIRE(*res == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stmt = query::select({AIRPLANE.id, AIRPLANE.brand, AIRPLANE.model})
|
auto stmt = query::select(generator::columns<airplane>(repo))
|
||||||
.from(AIRPLANE)
|
.from(AIRPLANE)
|
||||||
.where(AIRPLANE.brand == _)
|
.where(AIRPLANE.brand == _)
|
||||||
.prepare(db);
|
.prepare(db);
|
||||||
|
|
@ -87,9 +93,9 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]
|
||||||
|
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
for (const auto &i: *result) {
|
for (const auto &i: *result) {
|
||||||
REQUIRE(i->id == planes[0].id);
|
REQUIRE(i.id == planes[0]->id);
|
||||||
REQUIRE(i->brand == planes[0].brand);
|
REQUIRE(i.brand == planes[0]->brand);
|
||||||
REQUIRE(i->model == planes[0].model);
|
REQUIRE(i.model == planes[0]->model);
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt->reset();
|
stmt->reset();
|
||||||
|
|
@ -100,9 +106,9 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]
|
||||||
size_t index{1};
|
size_t index{1};
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
for (const auto &i: *result) {
|
for (const auto &i: *result) {
|
||||||
REQUIRE(i->id == planes[index].id);
|
REQUIRE(i.id == planes[index]->id);
|
||||||
REQUIRE(i->brand == planes[index].brand);
|
REQUIRE(i.brand == planes[index]->brand);
|
||||||
REQUIRE(i->model == planes[index++].model);
|
REQUIRE(i.model == planes[index++]->model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,28 +6,27 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct airplane {
|
struct airplane {
|
||||||
airplane() = default;
|
airplane() = default;
|
||||||
|
|
||||||
airplane(const unsigned int id, std::string b, std::string m)
|
airplane(const unsigned int id, std::string b, std::string m)
|
||||||
: id(id)
|
: id(id)
|
||||||
, brand(std::move(b))
|
, brand(std::move(b))
|
||||||
, model(std::move(m)) {
|
, model(std::move(m)) {}
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string brand;
|
std::string brand;
|
||||||
std::string model;
|
std::string model;
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "brand", brand, 255);
|
field::attribute(op, "brand", brand, 255);
|
||||||
field::attribute(op, "model", model, 255);
|
field::attribute(op, "model", model, 255);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// namespace matador::access {
|
// namespace matador::access {
|
||||||
|
|
|
||||||
|
|
@ -9,36 +9,31 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct book;
|
struct book;
|
||||||
|
|
||||||
struct author {
|
struct author {
|
||||||
author() = default;
|
unsigned int id{};
|
||||||
author(const unsigned int id, std::string first_name, std::string last_name, std::string date_of_birth, const unsigned short year_of_birth, const bool distinguished)
|
std::string first_name;
|
||||||
: id(id), first_name(std::move(first_name))
|
std::string last_name;
|
||||||
, last_name(std::move(last_name))
|
std::string date_of_birth;
|
||||||
, date_of_birth(std::move(date_of_birth))
|
unsigned short year_of_birth{};
|
||||||
, year_of_birth(year_of_birth)
|
bool distinguished{false};
|
||||||
, distinguished(distinguished) {}
|
std::vector<object::object_ptr<book>> books;
|
||||||
unsigned int id{};
|
|
||||||
std::string first_name;
|
|
||||||
std::string last_name;
|
|
||||||
std::string date_of_birth;
|
|
||||||
unsigned short year_of_birth{};
|
|
||||||
bool distinguished{false};
|
|
||||||
std::vector<object::object_ptr<book> > books;
|
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "first_name", first_name, 63);
|
field::attribute(op, "first_name", first_name, 63);
|
||||||
field::attribute(op, "last_name", last_name, 63);
|
field::attribute(op, "last_name", last_name, 63);
|
||||||
field::attribute(op, "date_of_birth", date_of_birth, 31);
|
field::attribute(op, "date_of_birth", date_of_birth, 31);
|
||||||
field::attribute(op, "year_of_birth", year_of_birth);
|
field::attribute(op, "year_of_birth", year_of_birth);
|
||||||
field::attribute(op, "distinguished", distinguished);
|
field::attribute(op, "distinguished", distinguished);
|
||||||
field::has_many(op, "books", books, "author_id", utils::CascadeAllFetchLazy);
|
field::has_many(op, "books", books, "author_id", utils::fetch_type::Lazy);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_AUTHOR_HPP
|
#endif //QUERY_AUTHOR_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,25 +9,24 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct author;
|
struct author;
|
||||||
|
|
||||||
struct book {
|
struct book {
|
||||||
book() = default;
|
unsigned int id{};
|
||||||
book(const unsigned int id, std::string title, object::object_ptr<author> author, unsigned short published_in)
|
std::string title;
|
||||||
: id(id), title(std::move(title)), book_author(std::move(author)), published_in(published_in) {}
|
object::object_ptr<author> book_author;
|
||||||
unsigned int id{};
|
unsigned short published_in{};
|
||||||
std::string title;
|
|
||||||
object::object_ptr<author> book_author;
|
|
||||||
unsigned short published_in{};
|
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "title", title, 511);
|
field::attribute(op, "title", title, 511);
|
||||||
field::belongs_to(op, "author_id", book_author, utils::CascadeAllFetchEager);
|
field::belongs_to(op, "author_id", book_author, utils::fetch_type::Eager);
|
||||||
field::attribute(op, "published_in", published_in);
|
field::attribute(op, "published_in", published_in);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_BOOK_HPP
|
#endif //QUERY_BOOK_HPP
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,19 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct category {
|
|
||||||
unsigned int id{};
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
template<class Operator>
|
struct category {
|
||||||
void process(Operator &op) {
|
unsigned int id{};
|
||||||
namespace field = matador::access;
|
std::string name;
|
||||||
using namespace matador::utils;
|
|
||||||
field::primary_key(op, "id", id);
|
template<class Operator>
|
||||||
field::attribute(op, "name", name, 255);
|
void process(Operator &op) {
|
||||||
}
|
namespace field = matador::access;
|
||||||
|
using namespace matador::utils;
|
||||||
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "name", name, 255);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_CATEGORY_HPP
|
#endif //QUERY_CATEGORY_HPP
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,24 @@
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct coordinate {
|
struct coordinate
|
||||||
|
{
|
||||||
int x{};
|
int x{};
|
||||||
int y{};
|
int y{};
|
||||||
int z{};
|
int z{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace matador::access {
|
namespace matador::access {
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void attribute(Operator &op, const char *id, test::coordinate &value, const utils::field_attributes &attr = utils::null_attributes) {
|
void attribute(Operator &op, const char *id, test::coordinate &value, const utils::field_attributes &attr = utils::null_attributes) {
|
||||||
attribute(op, (std::string(id) + "_x").c_str(), value.x, attr);
|
attribute(op, (std::string(id) + "_x").c_str(), value.x, attr);
|
||||||
attribute(op, (std::string(id) + "_y").c_str(), value.y, attr);
|
attribute(op, (std::string(id) + "_y").c_str(), value.y, attr);
|
||||||
attribute(op, (std::string(id) + "_z").c_str(), value.z, attr);
|
attribute(op, (std::string(id) + "_z").c_str(), value.z, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_COORDINATE_HPP
|
#endif //QUERY_COORDINATE_HPP
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,9 @@ namespace matador::test {
|
||||||
struct employee;
|
struct employee;
|
||||||
|
|
||||||
struct department {
|
struct department {
|
||||||
department() = default;
|
|
||||||
department(const unsigned int id, std::string name)
|
|
||||||
: id(id), name(std::move(name)) {}
|
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<object::object_ptr<employee>> employees{};
|
std::vector<object::object_ptr<employee>> employees;
|
||||||
// object::object_ptr<employee> manager;
|
// object::object_ptr<employee> manager;
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
|
|
@ -30,9 +27,6 @@ struct department {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct employee {
|
struct employee {
|
||||||
employee() = default;
|
|
||||||
employee(const unsigned int id, std::string first, std::string last, object::object_ptr<department> dep)
|
|
||||||
: id(id), first_name(std::move(first)), last_name(std::move(last)), dep(std::move(dep)) {}
|
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string first_name;
|
std::string first_name;
|
||||||
std::string last_name;
|
std::string last_name;
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,11 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct flight {
|
struct flight {
|
||||||
flight() = default;
|
flight() = default;
|
||||||
|
|
||||||
flight(const unsigned int id, const object::object_ptr<airplane> &plane, std::string name)
|
flight(const unsigned int id, const object::object_ptr<airplane> &plane, std::string name)
|
||||||
: id(id), plane(plane), pilot_name(std::move(name)) {
|
: id(id), plane(plane), pilot_name(std::move(name)) {}
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
object::object_ptr<airplane> plane;
|
object::object_ptr<airplane> plane;
|
||||||
|
|
@ -33,6 +32,7 @@ struct flight {
|
||||||
field::attribute(op, "pilot_name", pilot_name, 255);
|
field::attribute(op, "pilot_name", pilot_name, 255);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_FLIGHT_HPP
|
#endif //QUERY_FLIGHT_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,21 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
enum class Color : uint8_t {
|
enum class Color : uint8_t {
|
||||||
Green, Red, Blue, Yellow, Black, White, Brown
|
Green, Red, Blue, Yellow, Black, White, Brown
|
||||||
};
|
};
|
||||||
|
|
||||||
struct location {
|
struct location
|
||||||
|
{
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string name;
|
std::string name;
|
||||||
coordinate coord;
|
coordinate coord;
|
||||||
Color color{Color::Green};
|
Color color{Color::Green};
|
||||||
|
|
||||||
template<class Operator>
|
template < class Operator >
|
||||||
void process(Operator &op) {
|
void process(Operator &op)
|
||||||
|
{
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "name", name, 255);
|
field::attribute(op, "name", name, 255);
|
||||||
|
|
@ -27,6 +30,7 @@ struct location {
|
||||||
field::attribute(op, "color", color);
|
field::attribute(op, "color", color);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_LOCATION_HPP
|
#endif //QUERY_LOCATION_HPP
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,5 @@ META_TABLE(flights, FLIGHT, id, airplane_id, pilot_name);
|
||||||
META_TABLE(shipments, SHIPMENT, id, tracking_number)
|
META_TABLE(shipments, SHIPMENT, id, tracking_number)
|
||||||
META_TABLE(packages, PACKAGE, id, weight, shipment_id)
|
META_TABLE(packages, PACKAGE, id, weight, shipment_id)
|
||||||
META_TABLE(persons, PERSON, id, name, age, image)
|
META_TABLE(persons, PERSON, id, name, age, image)
|
||||||
META_TABLE(departments, DEPARTMENT, id, name)
|
|
||||||
META_TABLE(employees, EMPLOYEE, id, first_name, last_name, dep_id)
|
|
||||||
META_TABLE(authors, AUTHOR, id, first_name, last_name, date_of_birth, year_of_birth, distinguished)
|
|
||||||
META_TABLE(books, BOOK, id, title, author_id, published_in)
|
|
||||||
|
|
||||||
#endif //MATADOR_MODEL_METAS_HPP
|
#endif //MATADOR_MODEL_METAS_HPP
|
||||||
|
|
@ -8,20 +8,23 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct optional {
|
|
||||||
unsigned int id{};
|
|
||||||
std::optional<std::string> name;
|
|
||||||
std::optional<unsigned int> age{};
|
|
||||||
|
|
||||||
template<class Operator>
|
struct optional
|
||||||
void process(Operator &op) {
|
{
|
||||||
namespace field = matador::access;
|
unsigned int id{};
|
||||||
using namespace matador::utils;
|
std::optional<std::string> name;
|
||||||
field::primary_key(op, "id", id);
|
std::optional<unsigned int> age{};
|
||||||
field::attribute(op, "name", name, 255);
|
|
||||||
field::attribute(op, "age", age);
|
template<class Operator>
|
||||||
}
|
void process(Operator &op) {
|
||||||
|
namespace field = matador::access;
|
||||||
|
using namespace matador::utils;
|
||||||
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "name", name, 255);
|
||||||
|
field::attribute(op, "age", age);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_OPTIONAL_HPP
|
#endif //QUERY_OPTIONAL_HPP
|
||||||
|
|
|
||||||
|
|
@ -10,38 +10,41 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct order {
|
|
||||||
unsigned int order_id{};
|
|
||||||
std::string order_date;
|
|
||||||
std::string required_date;
|
|
||||||
std::string shipped_date;
|
|
||||||
unsigned int ship_via{};
|
|
||||||
unsigned int freight{};
|
|
||||||
std::string ship_name;
|
|
||||||
std::string ship_address;
|
|
||||||
std::string ship_city;
|
|
||||||
std::string ship_region;
|
|
||||||
std::string ship_postal_code;
|
|
||||||
std::string ship_country;
|
|
||||||
std::vector<object::object_ptr<order_details> > order_details_;
|
|
||||||
|
|
||||||
template<class Operator>
|
struct order
|
||||||
void process(Operator &op) {
|
{
|
||||||
namespace field = matador::access;
|
unsigned int order_id{};
|
||||||
field::primary_key(op, "order_id", order_id);
|
std::string order_date;
|
||||||
field::attribute(op, "order_date", order_date, 255);
|
std::string required_date;
|
||||||
field::attribute(op, "required_date", required_date, 255);
|
std::string shipped_date;
|
||||||
field::attribute(op, "shipped_date", shipped_date, 255);
|
unsigned int ship_via{};
|
||||||
field::attribute(op, "ship_via", ship_via);
|
unsigned int freight{};
|
||||||
field::attribute(op, "freight", freight);
|
std::string ship_name;
|
||||||
field::attribute(op, "ship_name", ship_name, 255);
|
std::string ship_address;
|
||||||
field::attribute(op, "ship_address", ship_address, 255);
|
std::string ship_city;
|
||||||
field::attribute(op, "ship_city", ship_city, 255);
|
std::string ship_region;
|
||||||
field::attribute(op, "ship_region", ship_region, 255);
|
std::string ship_postal_code;
|
||||||
field::attribute(op, "ship_postal_code", ship_postal_code, 255);
|
std::string ship_country;
|
||||||
field::attribute(op, "ship_country", ship_country, 255);
|
std::vector<object::object_ptr<order_details>> order_details_;
|
||||||
field::has_many(op, "order_details", order_details_, "order_id", utils::fetch_type::Eager);
|
|
||||||
}
|
template<class Operator>
|
||||||
|
void process(Operator &op) {
|
||||||
|
namespace field = matador::access;
|
||||||
|
field::primary_key(op, "order_id", order_id);
|
||||||
|
field::attribute(op, "order_date", order_date, 255);
|
||||||
|
field::attribute(op, "required_date", required_date, 255);
|
||||||
|
field::attribute(op, "shipped_date", shipped_date, 255);
|
||||||
|
field::attribute(op, "ship_via", ship_via);
|
||||||
|
field::attribute(op, "freight", freight);
|
||||||
|
field::attribute(op, "ship_name", ship_name, 255);
|
||||||
|
field::attribute(op, "ship_address", ship_address, 255);
|
||||||
|
field::attribute(op, "ship_city", ship_city, 255);
|
||||||
|
field::attribute(op, "ship_region", ship_region, 255);
|
||||||
|
field::attribute(op, "ship_postal_code", ship_postal_code, 255);
|
||||||
|
field::attribute(op, "ship_country", ship_country, 255);
|
||||||
|
field::has_many(op, "order_details", order_details_, "order_id", utils::fetch_type::Eager);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_ORDER_HPP
|
#endif //QUERY_ORDER_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,23 @@
|
||||||
#include "matador/utils/foreign_attributes.hpp"
|
#include "matador/utils/foreign_attributes.hpp"
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct order;
|
struct order;
|
||||||
|
|
||||||
struct order_details {
|
struct order_details
|
||||||
unsigned int order_details_id;
|
{
|
||||||
object::object_ptr<order> order_;
|
unsigned int order_details_id;
|
||||||
object::object_ptr<product> product_;
|
matador::object::object_ptr<order> order_;
|
||||||
|
matador::object::object_ptr<product> product_;
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "order_details_id", order_details_id);
|
field::primary_key(op, "order_details_id", order_details_id);
|
||||||
field::belongs_to(op, "order_id", order_, utils::CascadeNoneFetchLazy);
|
field::belongs_to(op, "order_id", order_, utils::CascadeNoneFetchLazy);
|
||||||
field::has_one(op, "product_id", product_, utils::CascadeNoneFetchLazy);
|
field::has_one(op, "product_id", product_, utils::CascadeNoneFetchLazy);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_ORDER_DETAILS_HPP
|
#endif //QUERY_ORDER_DETAILS_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,21 +8,23 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct person {
|
|
||||||
unsigned int id{};
|
|
||||||
std::string name;
|
|
||||||
unsigned int age{};
|
|
||||||
utils::blob_type_t image{};
|
|
||||||
|
|
||||||
template<class Operator>
|
struct person {
|
||||||
void process(Operator &op) {
|
unsigned int id{};
|
||||||
namespace field = matador::access;
|
std::string name;
|
||||||
using namespace matador::utils;
|
unsigned int age{};
|
||||||
field::primary_key(op, "id", id);
|
utils::blob_type_t image{};
|
||||||
field::attribute(op, "name", name, 255);
|
|
||||||
field::attribute(op, "age", age);
|
template<class Operator>
|
||||||
field::attribute(op, "image", image);
|
void process(Operator &op) {
|
||||||
}
|
namespace field = matador::access;
|
||||||
|
using namespace matador::utils;
|
||||||
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "name", name, 255);
|
||||||
|
field::attribute(op, "age", age);
|
||||||
|
field::attribute(op, "image", image);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_PERSON_HPP
|
#endif //QUERY_PERSON_HPP
|
||||||
|
|
|
||||||
|
|
@ -5,37 +5,40 @@
|
||||||
#include "supplier.hpp"
|
#include "supplier.hpp"
|
||||||
|
|
||||||
#include "matador/utils/access.hpp"
|
#include "matador/utils/access.hpp"
|
||||||
|
#include "matador/utils/cascade_type.hpp"
|
||||||
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
#include "matador/object/object_ptr.hpp"
|
#include "matador/object/object_ptr.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct product {
|
|
||||||
std::string product_name;
|
|
||||||
object::object_ptr<supplier> seller;
|
|
||||||
object::object_ptr<category> type;
|
|
||||||
std::string quantity_per_unit;
|
|
||||||
unsigned int unit_price;
|
|
||||||
unsigned int units_in_stock;
|
|
||||||
unsigned int units_in_order;
|
|
||||||
unsigned int reorder_level;
|
|
||||||
bool discontinued;
|
|
||||||
|
|
||||||
template<class Operator>
|
struct product {
|
||||||
void process(Operator &op) {
|
std::string product_name;
|
||||||
namespace field = matador::access;
|
object::object_ptr<test::supplier> supplier;
|
||||||
using namespace matador::utils;
|
object::object_ptr<test::category> category;
|
||||||
field::primary_key(op, "product_name", product_name, 255);
|
std::string quantity_per_unit;
|
||||||
field::belongs_to(op, "supplier_id", seller, CascadeAllFetchLazy);
|
unsigned int unit_price;
|
||||||
field::belongs_to(op, "category_id", type, CascadeAllFetchLazy);
|
unsigned int units_in_stock;
|
||||||
field::attribute(op, "quantity_per_unit", quantity_per_unit, 255);
|
unsigned int units_in_order;
|
||||||
field::attribute(op, "unit_price", unit_price);
|
unsigned int reorder_level;
|
||||||
field::attribute(op, "units_in_stock", units_in_stock);
|
bool discontinued;
|
||||||
field::attribute(op, "units_in_order", units_in_order);
|
|
||||||
field::attribute(op, "reorder_level", reorder_level);
|
template<class Operator>
|
||||||
field::attribute(op, "discontinued", discontinued);
|
void process(Operator &op) {
|
||||||
}
|
namespace field = matador::access;
|
||||||
|
using namespace matador::utils;
|
||||||
|
field::primary_key(op, "product_name", product_name, 255);
|
||||||
|
field::belongs_to(op, "supplier_id", supplier, utils::cascade_type::ALL);
|
||||||
|
field::belongs_to(op, "category_id", category, utils::cascade_type::ALL);
|
||||||
|
field::attribute(op, "quantity_per_unit", quantity_per_unit, 255);
|
||||||
|
field::attribute(op, "unit_price", unit_price);
|
||||||
|
field::attribute(op, "units_in_stock", units_in_stock);
|
||||||
|
field::attribute(op, "units_in_order", units_in_order);
|
||||||
|
field::attribute(op, "reorder_level", reorder_level);
|
||||||
|
field::attribute(op, "discontinued", discontinued);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,52 +10,51 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct recipe;
|
|
||||||
|
|
||||||
struct ingredient {
|
struct recipe;
|
||||||
|
struct ingredient
|
||||||
|
{
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<object::object_ptr<recipe> > recipes{};
|
std::vector<object::object_ptr<recipe>> recipes{};
|
||||||
|
|
||||||
ingredient() = default;
|
|
||||||
|
|
||||||
|
ingredient()= default;
|
||||||
ingredient(const unsigned int id, std::string name)
|
ingredient(const unsigned int id, std::string name)
|
||||||
: id(id), name(std::move(name)) {
|
: id(id), name(std::move(name)) {}
|
||||||
}
|
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "name", name, 255);
|
field::attribute(op, "name", name, 255);
|
||||||
field::has_many_to_many(op, "recipe_ingredients", recipes, "ingredient_id", "recipe_id", utils::CascadeAllFetchEager);
|
field::has_many_to_many(op, "recipe_ingredients", recipes, "ingredient_id", "recipe_id", utils::fetch_type::Eager);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct recipe {
|
struct recipe
|
||||||
|
{
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<object::object_ptr<ingredient> > ingredients{};
|
std::vector<object::object_ptr<ingredient>> ingredients{};
|
||||||
|
|
||||||
recipe() = default;
|
|
||||||
|
|
||||||
|
recipe()= default;
|
||||||
recipe(const unsigned int id, std::string name)
|
recipe(const unsigned int id, std::string name)
|
||||||
: id(id), name(std::move(name)) {
|
: id(id), name(std::move(name)) {}
|
||||||
}
|
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "name", name, 255);
|
field::attribute(op, "name", name, 255);
|
||||||
field::has_many_to_many(op, "recipe_ingredients", ingredients, utils::CascadeAllFetchLazy);
|
field::has_many_to_many(op, "recipe_ingredients", ingredients, utils::fetch_type::Lazy);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// class recipe_ingredient : public object::many_to_many_relation<recipe, ingredient> {
|
// class recipe_ingredient : public object::many_to_many_relation<recipe, ingredient> {
|
||||||
// public:
|
// public:
|
||||||
// recipe_ingredient() : many_to_many_relation("recipe_id", "ingredient_id") {}
|
// recipe_ingredient() : many_to_many_relation("recipe_id", "ingredient_id") {}
|
||||||
// };
|
// };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_RECIPE_HPP
|
#endif //QUERY_RECIPE_HPP
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,10 @@
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct package;
|
struct package;
|
||||||
|
|
||||||
struct shipment {
|
struct shipment {
|
||||||
shipment() = default;
|
|
||||||
shipment(const long id, std::string tracking_number)
|
|
||||||
: id(id), tracking_number(std::move(tracking_number)) {}
|
|
||||||
|
|
||||||
long id{};
|
long id{};
|
||||||
std::string tracking_number;
|
std::string tracking_number;
|
||||||
object::collection<object::object_ptr<package> > packages{};
|
object::collection<object::object_ptr<package>> packages{};
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
|
|
@ -31,10 +26,6 @@ struct shipment {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct package {
|
struct package {
|
||||||
package() = default;
|
|
||||||
package(const long id, double weight, object::object_ptr<shipment> del)
|
|
||||||
: id(id), weight(weight), delivery(std::move(del)){}
|
|
||||||
|
|
||||||
long id{};
|
long id{};
|
||||||
double weight{};
|
double weight{};
|
||||||
object::object_ptr<shipment> delivery;
|
object::object_ptr<shipment> delivery;
|
||||||
|
|
|
||||||
|
|
@ -11,54 +11,52 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct course;
|
struct course;
|
||||||
|
|
||||||
struct student {
|
struct student {
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<object::object_ptr<course> > courses;
|
std::vector<object::object_ptr<course>> courses;
|
||||||
|
|
||||||
student() = default;
|
student() = default;
|
||||||
|
explicit student(unsigned int id, std::string name)
|
||||||
|
: id(id)
|
||||||
|
, name(std::move(name)) {}
|
||||||
|
|
||||||
explicit student(unsigned int id, std::string name)
|
template < class Operator >
|
||||||
: id(id)
|
void process(Operator &op) {
|
||||||
, name(std::move(name)) {
|
namespace field = matador::access;
|
||||||
}
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "name", name, 255);
|
||||||
|
field::has_many_to_many(op, "student_courses", courses, "student_id", "course_id", utils::fetch_type::Lazy);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Operator>
|
|
||||||
void process(Operator &op) {
|
|
||||||
namespace field = matador::access;
|
|
||||||
field::primary_key(op, "id", id);
|
|
||||||
field::attribute(op, "name", name, 255);
|
|
||||||
field::has_many_to_many(op, "student_courses", courses, "student_id", "course_id", utils::CascadeAllFetchLazy);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct course {
|
struct course {
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
std::string title;
|
std::string title;
|
||||||
std::vector<object::object_ptr<student> > students;
|
std::vector<object::object_ptr<student>> students;
|
||||||
|
|
||||||
course() = default;
|
course() = default;
|
||||||
|
explicit course(unsigned int id, std::string title)
|
||||||
|
: id(id)
|
||||||
|
, title(std::move(title)) {}
|
||||||
|
|
||||||
explicit course(unsigned int id, std::string title)
|
template < class Operator >
|
||||||
: id(id)
|
void process(Operator &op) {
|
||||||
, title(std::move(title)) {
|
namespace field = matador::access;
|
||||||
}
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "title", title, 255);
|
||||||
template<class Operator>
|
field::has_many_to_many(op, "student_courses", students, utils::fetch_type::Eager);
|
||||||
void process(Operator &op) {
|
}
|
||||||
namespace field = matador::access;
|
|
||||||
field::primary_key(op, "id", id);
|
|
||||||
field::attribute(op, "title", title, 255);
|
|
||||||
field::has_many_to_many(op, "student_courses", students, utils::CascadeAllFetchEager);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class student_course : public object::many_to_many_relation<student, course> {
|
class student_course : public object::many_to_many_relation<student, course> {
|
||||||
public:
|
public:
|
||||||
student_course() : many_to_many_relation("student_id", "course_id") {
|
student_course() : many_to_many_relation("student_id", "course_id") {}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_STUDENT_HPP
|
#endif //QUERY_STUDENT_HPP
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,19 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct supplier {
|
|
||||||
unsigned int id{};
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
template<class Operator>
|
struct supplier {
|
||||||
void process(Operator &op) {
|
unsigned int id{};
|
||||||
namespace field = matador::access;
|
std::string name;
|
||||||
using namespace matador::utils;
|
|
||||||
field::primary_key(op, "id", id);
|
template<class Operator>
|
||||||
field::attribute(op, "name", name, 255);
|
void process(Operator &op) {
|
||||||
}
|
namespace field = matador::access;
|
||||||
|
using namespace matador::utils;
|
||||||
|
field::primary_key(op, "id", id);
|
||||||
|
field::attribute(op, "name", name, 255);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //QUERY_SUPPLIER_HPP
|
#endif //QUERY_SUPPLIER_HPP
|
||||||
|
|
|
||||||
|
|
@ -5,52 +5,56 @@
|
||||||
#include "matador/utils/types.hpp"
|
#include "matador/utils/types.hpp"
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
struct types {
|
|
||||||
// enum { CSTR_LEN=255 };
|
|
||||||
|
|
||||||
unsigned int id_ = 0;
|
struct types
|
||||||
int8_t char_ = 'c';
|
{
|
||||||
short short_ = -127;
|
// enum { CSTR_LEN=255 };
|
||||||
int int_ = -65000;
|
|
||||||
int64_t long64_ = -1234567890;
|
|
||||||
unsigned char unsigned_char_ = 'H';
|
|
||||||
unsigned short unsigned_short_ = 128;
|
|
||||||
unsigned int unsigned_int_ = 65000;
|
|
||||||
uint64_t unsigned_long64_ = 1234567890;
|
|
||||||
float float_ = 3.1415f;
|
|
||||||
double double_ = 1.1414;
|
|
||||||
bool bool_ = true;
|
|
||||||
// char cstr_[CSTR_LEN]{};
|
|
||||||
std::string string_ = "Welt";
|
|
||||||
std::string varchar_ = "Erde";
|
|
||||||
// matador::date date_;
|
|
||||||
// matador::time time_;
|
|
||||||
utils::blob_type_t binary_{1, 2, 3, 4};
|
|
||||||
|
|
||||||
template<class Operator>
|
unsigned int id_ = 0;
|
||||||
void process(Operator &op) {
|
int8_t char_ = 'c';
|
||||||
namespace field = matador::access;
|
short short_ = -127;
|
||||||
using namespace matador::utils;
|
int int_ = -65000;
|
||||||
field::primary_key(op, "id", id_);
|
int64_t long64_ = -1234567890;
|
||||||
field::attribute(op, "val_char", char_);
|
unsigned char unsigned_char_ = 'H';
|
||||||
field::attribute(op, "val_float", float_);
|
unsigned short unsigned_short_ = 128;
|
||||||
field::attribute(op, "val_double", double_);
|
unsigned int unsigned_int_ = 65000;
|
||||||
field::attribute(op, "val_short", short_);
|
uint64_t unsigned_long64_ = 1234567890;
|
||||||
field::attribute(op, "val_int", int_);
|
float float_ = 3.1415f;
|
||||||
field::attribute(op, "val_long_long", long64_);
|
double double_ = 1.1414;
|
||||||
field::attribute(op, "val_unsigned_char", unsigned_char_);
|
bool bool_ = true;
|
||||||
field::attribute(op, "val_unsigned_short", unsigned_short_);
|
// char cstr_[CSTR_LEN]{};
|
||||||
field::attribute(op, "val_unsigned_int", unsigned_int_);
|
std::string string_ = "Welt";
|
||||||
field::attribute(op, "val_unsigned_long_long", unsigned_long64_);
|
std::string varchar_ = "Erde";
|
||||||
field::attribute(op, "val_bool", bool_);
|
// matador::date date_;
|
||||||
// field::attribute(op, "val_cstr", cstr_, CSTR_LEN);
|
// matador::time time_;
|
||||||
field::attribute(op, "val_string", string_);
|
utils::blob_type_t binary_{ 1, 2, 3, 4 };
|
||||||
field::attribute(op, "val_varchar", varchar_, 63);
|
|
||||||
// field::attribute(op, "val_date", date_);
|
template < class Operator >
|
||||||
// field::attribute(op, "val_time", time_);
|
void process(Operator &op)
|
||||||
field::attribute(op, "val_binary", binary_);
|
{
|
||||||
}
|
namespace field = matador::access;
|
||||||
|
using namespace matador::utils;
|
||||||
|
field::primary_key(op, "id", id_);
|
||||||
|
field::attribute(op, "val_char", char_);
|
||||||
|
field::attribute(op, "val_float", float_);
|
||||||
|
field::attribute(op, "val_double", double_);
|
||||||
|
field::attribute(op, "val_short", short_);
|
||||||
|
field::attribute(op, "val_int", int_);
|
||||||
|
field::attribute(op, "val_long_long", long64_);
|
||||||
|
field::attribute(op, "val_unsigned_char", unsigned_char_);
|
||||||
|
field::attribute(op, "val_unsigned_short", unsigned_short_);
|
||||||
|
field::attribute(op, "val_unsigned_int", unsigned_int_);
|
||||||
|
field::attribute(op, "val_unsigned_long_long", unsigned_long64_);
|
||||||
|
field::attribute(op, "val_bool", bool_);
|
||||||
|
// field::attribute(op, "val_cstr", cstr_, CSTR_LEN);
|
||||||
|
field::attribute(op, "val_string", string_);
|
||||||
|
field::attribute(op, "val_varchar", varchar_, 63);
|
||||||
|
// field::attribute(op, "val_date", date_);
|
||||||
|
// field::attribute(op, "val_time", time_);
|
||||||
|
field::attribute(op, "val_binary", binary_);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // QUERY_TYPES_HPP
|
#endif // QUERY_TYPES_HPP
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,7 @@ utils::result<size_t, utils::error> test_connection::execute(const std::string &
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_connection::fetch(const sql::query_context &context) {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_connection::fetch(const sql::query_context &context) {
|
||||||
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(),
|
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(), context.prototype, context.prototype.size()));
|
||||||
context.prototype,
|
|
||||||
context.resolver_factory,
|
|
||||||
context.prototype.size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> test_connection::prepare(const sql::query_context &context) {
|
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> test_connection::prepare(const sql::query_context &context) {
|
||||||
|
|
@ -64,12 +61,12 @@ utils::result<std::vector<object::attribute>, utils::error> test_connection::des
|
||||||
return utils::ok(std::vector<object::attribute>{});
|
return utils::ok(std::vector<object::attribute>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<bool, utils::error> test_connection::exists(const std::string &/*schema_name*/,
|
utils::result<bool, utils::error> test_connection::exists(const std::string &/*schema_name*/, const std::string &/*table_name*/) {
|
||||||
const std::string &/*table_name*/) {
|
|
||||||
return utils::ok(false);
|
return utils::ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string test_connection::to_escaped_string(const utils::blob_type_t &value) const {
|
std::string test_connection::to_escaped_string(const utils::blob_type_t& value) const {
|
||||||
return utils::to_string(value);
|
return utils::to_string(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
@ -19,10 +19,7 @@ utils::result<size_t, utils::error> test_statement::execute(const sql::parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_statement::fetch(const sql::parameter_binder &/*bindings*/) {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_statement::fetch(const sql::parameter_binder &/*bindings*/) {
|
||||||
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(),
|
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(), query_.prototype, query_.prototype.size()));
|
||||||
query_.prototype,
|
|
||||||
query_.resolver_factory,
|
|
||||||
query_.prototype.size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_statement::reset() {}
|
void test_statement::reset() {}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,11 @@
|
||||||
#include "matador/query/table.hpp"
|
#include "matador/query/table.hpp"
|
||||||
#include "matador/query/schema.hpp"
|
#include "matador/query/schema.hpp"
|
||||||
|
|
||||||
#include "matador/query/query_builder.hpp"
|
#include "matador/utils/macro_map.hpp"
|
||||||
|
|
||||||
|
#include "matador/orm/session_query_builder.hpp"
|
||||||
|
|
||||||
|
#include "../backend/test_connection.hpp"
|
||||||
#include "../backend/test_backend_service.hpp"
|
#include "../backend/test_backend_service.hpp"
|
||||||
|
|
||||||
#include "../../models/airplane.hpp"
|
#include "../../models/airplane.hpp"
|
||||||
|
|
@ -26,6 +29,7 @@
|
||||||
#include "../../models/student.hpp"
|
#include "../../models/student.hpp"
|
||||||
|
|
||||||
using namespace matador::object;
|
using namespace matador::object;
|
||||||
|
using namespace matador::orm;
|
||||||
using namespace matador::query;
|
using namespace matador::query;
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
using namespace matador::sql;
|
using namespace matador::sql;
|
||||||
|
|
@ -42,7 +46,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
|
||||||
.and_then( [&scm] { return scm.attach<flight>("flights"); } );
|
.and_then( [&scm] { return scm.attach<flight>("flights"); } );
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
query_builder eqb(scm, db);
|
session_query_builder eqb(scm, db);
|
||||||
|
|
||||||
const auto it = scm.find(typeid(flight));
|
const auto it = scm.find(typeid(flight));
|
||||||
REQUIRE(it != scm.end());
|
REQUIRE(it != scm.end());
|
||||||
|
|
@ -96,7 +100,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
|
||||||
.and_then( [&scm] { return scm.attach<book>("books"); } );
|
.and_then( [&scm] { return scm.attach<book>("books"); } );
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
query_builder eqb(scm, db);
|
session_query_builder eqb(scm, db);
|
||||||
|
|
||||||
const auto it = scm.find(typeid(book));
|
const auto it = scm.find(typeid(book));
|
||||||
REQUIRE(it != scm.end());
|
REQUIRE(it != scm.end());
|
||||||
|
|
@ -168,7 +172,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
|
||||||
.and_then( [&scm] { return scm.attach<order>("orders"); } );
|
.and_then( [&scm] { return scm.attach<order>("orders"); } );
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
query_builder eqb(scm, db);
|
session_query_builder eqb(scm, db);
|
||||||
|
|
||||||
const auto it = scm.find(typeid(order));
|
const auto it = scm.find(typeid(order));
|
||||||
REQUIRE(it != scm.end());
|
REQUIRE(it != scm.end());
|
||||||
|
|
@ -232,7 +236,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e
|
||||||
.and_then( [&scm] { return scm.attach<ingredient>("ingredients"); } );
|
.and_then( [&scm] { return scm.attach<ingredient>("ingredients"); } );
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
query_builder eqb(scm, db);
|
session_query_builder eqb(scm, db);
|
||||||
|
|
||||||
const auto it = scm.find(typeid(ingredient));
|
const auto it = scm.find(typeid(ingredient));
|
||||||
REQUIRE(it != scm.end());
|
REQUIRE(it != scm.end());
|
||||||
|
|
@ -286,7 +290,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
|
||||||
.and_then( [&scm] { return scm.attach<course>("courses"); } );
|
.and_then( [&scm] { return scm.attach<course>("courses"); } );
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
query_builder eqb(scm, db);
|
session_query_builder eqb(scm, db);
|
||||||
|
|
||||||
const auto it = scm.find(typeid(course));
|
const auto it = scm.find(typeid(course));
|
||||||
REQUIRE(it != scm.end());
|
REQUIRE(it != scm.end());
|
||||||
|
|
@ -340,7 +344,7 @@ TEST_CASE("Test eager relationship", "[session][eager]") {
|
||||||
.and_then( [&scm] { return scm.attach<employee>("employees"); } );
|
.and_then( [&scm] { return scm.attach<employee>("employees"); } );
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
query_builder eqb(scm, db);
|
session_query_builder eqb(scm, db);
|
||||||
|
|
||||||
auto data = eqb.build<department>();
|
auto data = eqb.build<department>();
|
||||||
REQUIRE(data.is_ok());
|
REQUIRE(data.is_ok());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue