collection_resolver progress
This commit is contained in:
parent
602b77e67b
commit
bcec740d60
|
|
@ -111,7 +111,8 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
|
||||||
|
|
||||||
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),
|
||||||
std::move(prototype),
|
std::move(prototype),
|
||||||
context.resolver));
|
context.resolver,
|
||||||
|
context.result_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
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,10 @@ 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));
|
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res),
|
||||||
|
query_.prototype,
|
||||||
|
query_.resolver,
|
||||||
|
query_.result_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<utils::attribute_writer> postgres_statement::create_binder() const {
|
std::unique_ptr<utils::attribute_writer> postgres_statement::create_binder() const {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
#include "matador/object/repository.hpp"
|
#include "matador/object/repository.hpp"
|
||||||
|
#include "matador/object/collection.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/resolver_service.hpp"
|
||||||
|
|
||||||
#include "matador/logger/log_manager.hpp"
|
#include "matador/logger/log_manager.hpp"
|
||||||
|
|
||||||
|
|
@ -131,6 +134,12 @@ int main() {
|
||||||
// logger::default_min_log_level(logger::log_level::LVL_DEBUG);
|
// logger::default_min_log_level(logger::log_level::LVL_DEBUG);
|
||||||
// logger::add_log_sink(logger::create_stdout_sink());
|
// logger::add_log_sink(logger::create_stdout_sink());
|
||||||
|
|
||||||
|
sql::resolver_service rs;
|
||||||
|
|
||||||
|
std::weak_ptr cr = rs.collection_resolver<object::object_ptr<names>>( typeid(person), "names" );
|
||||||
|
utils::identifier id{1};
|
||||||
|
|
||||||
|
object::collection_proxy cp(cr, id);
|
||||||
{
|
{
|
||||||
// has_many with builtin-type
|
// has_many with builtin-type
|
||||||
object::repository repo;
|
object::repository repo;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef MATADOR_NET_OS_HPP
|
#ifndef MATADOR_NET_OS_HPP
|
||||||
#define MATADOR_NET_OS_HPP
|
#define MATADOR_NET_OS_HPP
|
||||||
|
|
||||||
#include "matador/net/export.hpp"
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
#ifndef MATADOR_COLLECTION_PROXY_HPP
|
#ifndef MATADOR_COLLECTION_PROXY_HPP
|
||||||
#define MATADOR_COLLECTION_PROXY_HPP
|
#define MATADOR_COLLECTION_PROXY_HPP
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include "matador/object/collection_resolver.hpp"
|
#include "matador/object/collection_resolver.hpp"
|
||||||
|
|
||||||
#include "matador/utils/identifier.hpp"
|
#include "matador/utils/identifier.hpp"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace matador::object {
|
namespace matador::object {
|
||||||
|
|
@ -33,13 +34,15 @@ public:
|
||||||
return owner_id_;
|
return owner_id_;
|
||||||
}
|
}
|
||||||
const std::vector<Type>& items() const {
|
const std::vector<Type>& items() const {
|
||||||
|
resolve();
|
||||||
return items_;
|
return items_;
|
||||||
}
|
}
|
||||||
std::vector<Type>& items() {
|
std::vector<Type>& items() {
|
||||||
|
resolve();
|
||||||
return items_;
|
return items_;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void resolve() const {
|
void resolve() {
|
||||||
if (loaded_) {
|
if (loaded_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -53,6 +56,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
items_ = resolver->resolve(owner_id_);
|
items_ = resolver->resolve(owner_id_);
|
||||||
|
loaded_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class collection_resolver_factory : public abstract_collection_resolver_factory
|
||||||
public:
|
public:
|
||||||
template<class Type>
|
template<class Type>
|
||||||
[[nodiscard]] std::shared_ptr<collection_resolver<Type>> resolver(const std::type_index &root_type, const std::string &collection_name) const {
|
[[nodiscard]] std::shared_ptr<collection_resolver<Type>> resolver(const std::type_index &root_type, const std::string &collection_name) const {
|
||||||
const auto res = acquire_collection_resolver(typeid(Type), root_type, collection_name);
|
const auto res = acquire_collection_resolver(root_type, typeid(Type), collection_name);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return std::dynamic_pointer_cast<collection_resolver<Type>>(res);
|
return std::dynamic_pointer_cast<collection_resolver<Type>>(res);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
template < class Type >
|
template < class Type >
|
||||||
utils::result<sql::query_result<Type>, utils::error> fetch_all(sql::executor &exec) {
|
utils::result<sql::query_result<Type>, utils::error> fetch_all(sql::executor &exec) {
|
||||||
auto result = fetch(exec);
|
auto result = fetch(exec, typeid(Type));
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
|
|
@ -40,9 +40,8 @@ public:
|
||||||
[[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<object::object_ptr<Type>, utils::error> fetch_one(sql::executor &exec) {
|
||||||
{
|
auto result = fetch(exec, typeid(Type));
|
||||||
auto result = fetch(exec);
|
|
||||||
if (!result.is_ok()) {
|
if (!result.is_ok()) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +82,7 @@ public:
|
||||||
[[nodiscard]] sql::query_context compile(const sql::dialect &d) const;
|
[[nodiscard]] sql::query_context compile(const sql::dialect &d) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::executor &exec) const;
|
[[nodiscard]] utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::executor &exec, const std::type_index& index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@
|
||||||
#include "matador/sql/internal/identifier_statement_binder.hpp"
|
#include "matador/sql/internal/identifier_statement_binder.hpp"
|
||||||
#include "matador/sql/statement.hpp"
|
#include "matador/sql/statement.hpp"
|
||||||
|
|
||||||
#include "matador/query/table.hpp"
|
|
||||||
#include "matador/query/select_query_builder.hpp"
|
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
class executor;
|
class executor;
|
||||||
}
|
}
|
||||||
|
|
@ -17,47 +14,33 @@ namespace matador::query {
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
class query_collection_resolver : public object::collection_resolver<Type> {
|
class query_collection_resolver : public object::collection_resolver<Type> {
|
||||||
public:
|
public:
|
||||||
explicit query_collection_resolver(const basic_schema &repo, sql::executor& exec, const table &tab, std::string pk_name, const std::type_index& root_type, std::string join_column)
|
explicit query_collection_resolver(sql::statement &&stmt, const std::type_index& root_type, std::string join_column)
|
||||||
: object::collection_resolver<Type>(root_type, join_column)
|
: object::collection_resolver<Type>(root_type, join_column)
|
||||||
, executor_(exec)
|
, stmt_(std::move(stmt))
|
||||||
, schema_(repo)
|
|
||||||
, table_(tab)
|
|
||||||
, pk_name_(std::move(pk_name))
|
|
||||||
, join_column_(std::move(join_column))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::vector<Type> resolve(const utils::identifier &id) override;
|
std::vector<Type> resolve(const utils::identifier &id) override;
|
||||||
protected:
|
protected:
|
||||||
sql::executor& executor_;
|
sql::statement stmt_;
|
||||||
const basic_schema &schema_;
|
|
||||||
const table &table_;
|
|
||||||
std::string pk_name_;
|
|
||||||
std::string join_column_;
|
|
||||||
std::type_index index{typeid(Type)};
|
std::type_index index{typeid(Type)};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
std::vector<Type> query_collection_resolver<Type>::resolve(const utils::identifier &id) {
|
std::vector<Type> query_collection_resolver<Type>::resolve(const utils::identifier &id) {
|
||||||
const auto *pk_column = table_[pk_name_];
|
sql::identifier_statement_binder binder(stmt_);
|
||||||
const auto *join_column = table_[join_column_];
|
|
||||||
|
|
||||||
auto stmt = query::select({*pk_column})
|
|
||||||
.from(table_)
|
|
||||||
.where(*join_column == id)
|
|
||||||
.prepare(executor_);
|
|
||||||
|
|
||||||
if (!stmt) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
sql::identifier_statement_binder binder(*stmt);
|
|
||||||
binder.bind(id);
|
binder.bind(id);
|
||||||
|
|
||||||
auto result = stmt->template fetch_one_raw<Type>();
|
auto result = stmt_.fetch();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return {};
|
std::vector<Type> out;
|
||||||
|
for (const auto &i: *result) {
|
||||||
|
// Todo: convert the first value of record into an utils::identifier
|
||||||
|
// then create a object_proxy<Type>(resolver, identifier)
|
||||||
|
// out.emplace_back(resolver, identifier);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif //MATADOR_QUERY_CONTAINER_RESOLVER_HPP
|
#endif //MATADOR_QUERY_CONTAINER_RESOLVER_HPP
|
||||||
|
|
@ -51,7 +51,19 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::shared_ptr<object::abstract_collection_resolver> produce(sql::executor &exec) override {
|
std::shared_ptr<object::abstract_collection_resolver> produce(sql::executor &exec) override {
|
||||||
return std::make_shared<query_collection_resolver<Type>>(repo_, exec, table_, std::move(pk_name_), root_type(), collection_name());
|
const auto *pk_column = table_[pk_name_];
|
||||||
|
const auto *join_column = table_[collection_name()];
|
||||||
|
|
||||||
|
auto stmt = query::select({*pk_column})
|
||||||
|
.from(table_)
|
||||||
|
.where(*join_column == utils::_)
|
||||||
|
.prepare(exec);
|
||||||
|
|
||||||
|
if (!stmt) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<query_collection_resolver<Type>>(stmt.release(), root_type(), collection_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -201,13 +213,13 @@ public:
|
||||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto producer = std::make_unique<query_collection_resolver_producer<typename CollectionType::value_type::value_type>>(
|
auto producer = std::make_unique<query_collection_resolver_producer<typename CollectionType::value_type>>(
|
||||||
schema_,
|
schema_,
|
||||||
it->second.table(),
|
it->second.table(),
|
||||||
it->second.node().info().primary_key_attribute()->name(),
|
it->second.node().info().primary_key_attribute()->name(),
|
||||||
root_type_,
|
root_type_,
|
||||||
join_column);
|
join_column);
|
||||||
const sql::composite_key key{root_type_, typeid(typename CollectionType::value_type::value_type), join_column};
|
const sql::composite_key key{root_type_, typeid(typename CollectionType::value_type), join_column};
|
||||||
schema_.collection_resolver_producers_[key] = std::move(producer);
|
schema_.collection_resolver_producers_[key] = std::move(producer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ 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,
|
||||||
const std::shared_ptr<resolver_service>& resolver,
|
const std::shared_ptr<resolver_service>& resolver,
|
||||||
|
const std::type_index& result_type,
|
||||||
size_t column_index = 0);
|
size_t column_index = 0);
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
|
|
@ -127,13 +128,12 @@ public:
|
||||||
template<class CollectionType>
|
template<class CollectionType>
|
||||||
void on_has_many(const char * /*id*/, CollectionType &cont, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t<object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
void on_has_many(const char * /*id*/, CollectionType &cont, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t<object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
||||||
using value_type = typename CollectionType::value_type::value_type;
|
using value_type = typename CollectionType::value_type::value_type;
|
||||||
auto resolver = resolver_->collection_resolver<value_type>(type_stack_.top(), join_column);
|
auto resolver = resolver_->collection_resolver<typename CollectionType::value_type>(result_type_, join_column);
|
||||||
auto object_resolver = resolver_->object_resolver<value_type>();
|
auto object_resolver = resolver_->object_resolver<value_type>();
|
||||||
|
|
||||||
std::vector<typename CollectionType::value_type> objects;
|
std::vector<typename CollectionType::value_type> objects;
|
||||||
if (attr.fetch() == utils::fetch_type::Lazy) {
|
if (attr.fetch() == utils::fetch_type::Lazy) {
|
||||||
|
cont.reset(std::make_shared<object::collection_proxy<typename CollectionType::value_type>>(resolver, current_pk_));
|
||||||
// pk_reader_.read(*id, column_index_++);
|
|
||||||
} else {
|
} else {
|
||||||
const auto ti = std::type_index(typeid(value_type));
|
const auto ti = std::type_index(typeid(value_type));
|
||||||
auto obj = std::make_shared<typename CollectionType::value_type::value_type>();
|
auto obj = std::make_shared<typename CollectionType::value_type::value_type>();
|
||||||
|
|
@ -227,7 +227,8 @@ 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<sql::resolver_service> resolver_;
|
std::shared_ptr<resolver_service> resolver_;
|
||||||
|
const std::type_index result_type_;
|
||||||
internal::identifier_reader id_reader_;
|
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_;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ struct query_context {
|
||||||
std::vector<object::attribute> prototype{};
|
std::vector<object::attribute> prototype{};
|
||||||
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{};
|
||||||
|
// Data for resolving query result
|
||||||
std::shared_ptr<resolver_service> resolver{};
|
std::shared_ptr<resolver_service> resolver{};
|
||||||
|
std::type_index result_type = typeid(void);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "matador/utils/types.hpp"
|
#include "matador/utils/types.hpp"
|
||||||
#include "matador/utils/result.hpp"
|
#include "matador/utils/result.hpp"
|
||||||
|
#include "matador/utils/os.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
|
@ -467,18 +468,20 @@ template < typename DestType>
|
||||||
result<DestType, conversion_error> to(const timestamp_type_t &source, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = nullptr) {
|
result<DestType, conversion_error> to(const timestamp_type_t &source, std::enable_if_t<std::is_same_v<time_type_t, DestType>>* = nullptr) {
|
||||||
const std::time_t tt = std::chrono::system_clock::to_time_t(source);
|
const std::time_t tt = std::chrono::system_clock::to_time_t(source);
|
||||||
|
|
||||||
const std::tm* result = std::localtime(&tt);
|
std::tm result;
|
||||||
|
matador::os::localtime(tt, result);
|
||||||
|
|
||||||
return ok(time_type_t{static_cast<uint8_t>(result->tm_hour), static_cast<uint8_t>(result->tm_min), static_cast<uint8_t>(result->tm_sec)});
|
return ok(time_type_t{static_cast<uint8_t>(result.tm_hour), static_cast<uint8_t>(result.tm_min), static_cast<uint8_t>(result.tm_sec)});
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename DestType>
|
template < typename DestType>
|
||||||
result<DestType, conversion_error> to(const timestamp_type_t &source, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = nullptr) {
|
result<DestType, conversion_error> to(const timestamp_type_t &source, std::enable_if_t<std::is_same_v<date_type_t, DestType>>* = nullptr) {
|
||||||
const std::time_t tt = std::chrono::system_clock::to_time_t(source);
|
const std::time_t tt = std::chrono::system_clock::to_time_t(source);
|
||||||
|
|
||||||
const std::tm* result = std::localtime(&tt);
|
std::tm result;
|
||||||
|
matador::os::localtime(tt, result);
|
||||||
|
|
||||||
return ok(date_type_t{result->tm_year + 1900, static_cast<uint8_t>(result->tm_mon + 1), static_cast<uint8_t>(result->tm_mday)});
|
return ok(date_type_t{result.tm_year + 1900, static_cast<uint8_t>(result.tm_mon + 1), static_cast<uint8_t>(result.tm_mday)});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,14 @@ int sprintf(char* str, size_t s, const char* format, ARGS const&... args)
|
||||||
|
|
||||||
MATADOR_UTILS_API char* strerror(int err, char* errbuf, size_t bufsize);
|
MATADOR_UTILS_API char* strerror(int err, char* errbuf, size_t bufsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multi platform version of localtime
|
||||||
|
*
|
||||||
|
* @param in time_t value to be converted
|
||||||
|
* @param out converted value
|
||||||
|
*/
|
||||||
|
MATADOR_UTILS_API void localtime(const time_t &in, struct tm &out);
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
#include "matador/utils/os.hpp"
|
#include "matador/utils/os.hpp"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <cstring>
|
#include <ctime>
|
||||||
#include <vector>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
@ -357,4 +359,16 @@ char* strerror(int err, char* errbuf, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void localtime(const time_t &in, struct tm &out) {
|
||||||
|
#if defined(__unix__)
|
||||||
|
localtime_r(&in, &out);
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
errno_t err = localtime_s(&out, &in);
|
||||||
|
#else
|
||||||
|
static std::mutex mtx;
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
out = *std::localtime(&in);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ sql::record *create_prototype(const std::vector<object::attribute> &prototype) {
|
||||||
}
|
}
|
||||||
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const {
|
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const {
|
||||||
query_builder compiler;
|
query_builder compiler;
|
||||||
const auto ctx = compiler.compile(*context_, exec.dialect(), std::nullopt);
|
auto ctx = compiler.compile(*context_, exec.dialect(), std::nullopt);
|
||||||
|
ctx.resolver = exec.resolver();
|
||||||
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();
|
||||||
|
|
@ -67,9 +68,10 @@ sql::query_context fetchable_query::compile(const sql::dialect &d) const {
|
||||||
return compiler.compile(*context_, d, std::nullopt);
|
return compiler.compile(*context_, d, std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 std::type_index& index) const {
|
||||||
auto ctx = compile(exec.dialect());
|
auto ctx = compile(exec.dialect());
|
||||||
ctx.resolver = exec.resolver();
|
ctx.resolver = exec.resolver();
|
||||||
|
ctx.result_type = index;
|
||||||
return exec.fetch(ctx);
|
return exec.fetch(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,14 @@ 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<sql::resolver_service>& resolver,
|
const std::shared_ptr<resolver_service>& resolver,
|
||||||
|
const std::type_index& result_type,
|
||||||
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_(resolver)
|
, resolver_(resolver)
|
||||||
|
, result_type_(result_type)
|
||||||
, id_reader_(*reader_)
|
, id_reader_(*reader_)
|
||||||
, pk_reader_(*reader_) {
|
, pk_reader_(*reader_) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
todo.md
2
todo.md
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
- move `prepare_*` methods from `dialect` to `query_compiler`
|
- move `prepare_*` methods from `dialect` to `query_compiler`
|
||||||
- add `session_insert_builder` and `session_update_builder` (returning multiple statements)
|
- add `session_insert_builder` and `session_update_builder` (returning multiple statements)
|
||||||
- finish fetch eager has-many/belongs-to relations
|
- finish fetch eager many-to-many relations
|
||||||
- implement lazy loading
|
- implement lazy loading
|
||||||
- implement polymorphic class hierarchies
|
- implement polymorphic class hierarchies
|
||||||
- finish `schema_repository` classes (move add/drop from `session` to `schema`)
|
- finish `schema_repository` classes (move add/drop from `session` to `schema`)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue