implemented lazy loading for object_ptr and belongs_to
This commit is contained in:
@@ -15,14 +15,19 @@ add_library(matador-core STATIC
|
||||
../../include/matador/net/socket_interrupter.hpp
|
||||
../../include/matador/object/attribute.hpp
|
||||
../../include/matador/object/basic_object_info.hpp
|
||||
../../include/matador/object/basic_repository.hpp
|
||||
../../include/matador/object/error_code.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/object.hpp
|
||||
../../include/matador/object/object_generator.hpp
|
||||
../../include/matador/object/object_info.hpp
|
||||
../../include/matador/object/object_proxy.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/primary_key_resolver.hpp
|
||||
../../include/matador/object/relation_completer.hpp
|
||||
@@ -31,7 +36,6 @@ add_library(matador-core STATIC
|
||||
../../include/matador/object/repository_node.hpp
|
||||
../../include/matador/object/repository_node_iterator.hpp
|
||||
../../include/matador/object/restriction.hpp
|
||||
../../include/matador/sql/statement_cache.hpp
|
||||
../../include/matador/utils/access.hpp
|
||||
../../include/matador/utils/attribute_reader.hpp
|
||||
../../include/matador/utils/attribute_writer.hpp
|
||||
@@ -53,6 +57,7 @@ add_library(matador-core STATIC
|
||||
../../include/matador/utils/file.hpp
|
||||
../../include/matador/utils/foreign_attributes.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/library.hpp
|
||||
../../include/matador/utils/macro_map.hpp
|
||||
@@ -78,6 +83,7 @@ add_library(matador-core STATIC
|
||||
logger/rotating_file_sink.cpp
|
||||
object/attribute.cpp
|
||||
object/basic_object_info.cpp
|
||||
object/basic_repository.cpp
|
||||
object/error_code.cpp
|
||||
object/foreign_node_completer.cpp
|
||||
object/object.cpp
|
||||
@@ -95,6 +101,7 @@ add_library(matador-core STATIC
|
||||
utils/file.cpp
|
||||
utils/foreign_attributes.cpp
|
||||
utils/identifier.cpp
|
||||
utils/identifier_to_value_converter.cpp
|
||||
utils/leader_follower_thread_pool.cpp
|
||||
utils/library.cpp
|
||||
utils/message_bus.cpp
|
||||
@@ -106,10 +113,6 @@ add_library(matador-core STATIC
|
||||
utils/uuid.cpp
|
||||
utils/value.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})
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#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,6 +39,14 @@ value &value::operator=(value &&x) noexcept {
|
||||
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 {
|
||||
return as<std::string>().value_or("");
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
add_library(matador-orm STATIC
|
||||
../../include/matador/orm/error_code.hpp
|
||||
../../include/matador/orm/session.hpp
|
||||
../../include/matador/orm/session_query_builder.hpp
|
||||
../../include/matador/query/attribute_string_writer.hpp
|
||||
../../include/matador/query/basic_schema.hpp
|
||||
../../include/matador/query/builder.hpp
|
||||
../../include/matador/query/criteria.hpp
|
||||
../../include/matador/query/criteria/abstract_column_criteria.hpp
|
||||
@@ -50,10 +50,13 @@ add_library(matador-orm STATIC
|
||||
../../include/matador/query/join_data.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/query.hpp
|
||||
../../include/matador/query/query_builder.hpp
|
||||
../../include/matador/query/query_compiler.hpp
|
||||
../../include/matador/query/query_data.hpp
|
||||
../../include/matador/query/query_intermediates.hpp
|
||||
../../include/matador/query/query_object_resolver.hpp
|
||||
../../include/matador/query/query_part.hpp
|
||||
../../include/matador/query/query_utils.hpp
|
||||
../../include/matador/query/schema.hpp
|
||||
@@ -76,19 +79,25 @@ add_library(matador-orm STATIC
|
||||
../../include/matador/sql/interface/query_result_reader.hpp
|
||||
../../include/matador/sql/interface/statement_impl.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/query_result_impl.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_record_result.hpp
|
||||
../../include/matador/sql/query_result.hpp
|
||||
../../include/matador/sql/record.hpp
|
||||
../../include/matador/sql/sql_functions.hpp
|
||||
../../include/matador/sql/statement.hpp
|
||||
../../include/matador/sql/statement_cache.hpp
|
||||
orm/error_code.cpp
|
||||
orm/query_builder_exception.cpp
|
||||
orm/session.cpp
|
||||
orm/session_query_builder.cpp
|
||||
query/attribute_string_writer.cpp
|
||||
query/basic_schema.cpp
|
||||
query/builder.cpp
|
||||
query/criteria/abstract_column_criteria.cpp
|
||||
query/criteria/between_criteria.cpp
|
||||
@@ -133,7 +142,10 @@ add_library(matador-orm STATIC
|
||||
query/internal/query_result_impl.cpp
|
||||
query/key_value_generator.cpp
|
||||
query/query.cpp
|
||||
query/query_builder.cpp
|
||||
query/query_builder_exception.cpp
|
||||
query/query_compiler.cpp
|
||||
query/query_object_resolver.cpp
|
||||
query/query_part.cpp
|
||||
query/query_utils.cpp
|
||||
query/schema.cpp
|
||||
@@ -153,14 +165,17 @@ add_library(matador-orm STATIC
|
||||
sql/interface/query_result_reader.cpp
|
||||
sql/interface/statement_impl.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/query_result_pk_resolver.cpp
|
||||
sql/internal/resolver_producer.cpp
|
||||
sql/object_parameter_binder.cpp
|
||||
sql/producer_resolver_factory.cpp
|
||||
sql/query_result.cpp
|
||||
sql/record.cpp
|
||||
sql/statement.cpp
|
||||
sql/statement_cache.cpp
|
||||
../../include/matador/query/meta_table_macro.hpp
|
||||
)
|
||||
|
||||
target_include_directories(matador-orm
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/query_record_result.hpp"
|
||||
|
||||
#include "matador/query/query.hpp"
|
||||
|
||||
@@ -13,9 +14,11 @@ utils::error make_error(const error_code ec, const std::string &msg) {
|
||||
}
|
||||
|
||||
session::session(session_context&& ctx, const query::schema &scm)
|
||||
: cache_(ctx.bus, ctx.pool, ctx.cache_size)
|
||||
, dialect_(sql::backend_provider::instance().connection_dialect(ctx.pool.info().type))
|
||||
, schema_(scm) {
|
||||
: pool_(ctx.dns, ctx.connection_count, [ctx](const sql::connection_info& info) { return sql::connection(info, ctx.resolver_factory); })
|
||||
, cache_(ctx.bus, pool_, ctx.cache_size)
|
||||
, dialect_(sql::backend_provider::instance().connection_dialect(pool_.info().type))
|
||||
, schema_(scm)
|
||||
, resolver_factory_(ctx.resolver_factory) {
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> session::drop_table(const std::string &table_name) const {
|
||||
@@ -54,10 +57,8 @@ utils::result<sql::query_result<sql::record>, utils::error> session::fetch_all(c
|
||||
if (!res) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
const auto prototype = res.value()->prototype();
|
||||
return utils::ok(sql::query_result<sql::record>{std::move(*res), [prototype] {
|
||||
return sql::detail::create_prototype<sql::record>(prototype);
|
||||
}});
|
||||
const auto prototype = res.value()->prototype();
|
||||
return utils::ok(sql::query_result<sql::record>{std::move(*res), prototype});
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> session::execute(const std::string &sql) const {
|
||||
@@ -84,6 +85,14 @@ const class sql::dialect &session::dialect() const {
|
||||
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 {
|
||||
if (const auto result = cache_.acquire(ctx); !result) {
|
||||
return utils::failure(result.err());
|
||||
@@ -112,7 +121,7 @@ std::string session::str(const sql::query_context& ctx) const {
|
||||
return ctx.sql;
|
||||
}
|
||||
|
||||
query::fetchable_query session::build_select_query(entity_query_data &&data) {
|
||||
query::fetchable_query session::build_select_query(query::entity_query_data &&data) {
|
||||
return query::query::select(data.columns)
|
||||
.from(*data.root_table)
|
||||
.join_left(data.joins)
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
#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)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#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,7 +5,22 @@
|
||||
#include "matador/query/criteria/logical_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 {
|
||||
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) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, p);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "matador/query/generator.hpp"
|
||||
|
||||
namespace matador::query::generator {
|
||||
column_generator::column_generator(const schema& repo, const table* tab, const column_generator_options options)
|
||||
column_generator::column_generator(const basic_schema& repo, const table* tab, const column_generator_options options)
|
||||
: repo_(std::cref(repo))
|
||||
, options_(options) {
|
||||
table_stack_.push(tab);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "matador/sql/executor.hpp"
|
||||
#include "matador/sql/field.hpp"
|
||||
#include "matador/sql/statement.hpp"
|
||||
#include "matador/sql/query_record_result.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
@@ -29,29 +30,27 @@ utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fet
|
||||
return exec.fetch(ctx)
|
||||
.and_then([](auto &&res) {
|
||||
const auto prototype = res->prototype();
|
||||
return utils::ok(sql::query_result<sql::record>(std::forward<decltype(res)>(res), [prototype] {
|
||||
return detail::create_prototype(prototype);
|
||||
}));
|
||||
return utils::ok(sql::query_result<sql::record>(std::forward<decltype(res)>(res), prototype));
|
||||
});
|
||||
}
|
||||
|
||||
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const {
|
||||
query_compiler compiler;
|
||||
auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
auto ctx = compiler.compile(*context_, exec.dialect(), std::nullopt);
|
||||
ctx.resolver_factory = exec.resolver_factory();
|
||||
auto result = exec.fetch(ctx);
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
const auto prototype = result.value()->prototype();
|
||||
sql::query_result<sql::record> records(std::move(*result), [prototype] {
|
||||
return detail::create_prototype(prototype);
|
||||
});
|
||||
sql::query_result<sql::record> records(std::move(*result), prototype);
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<sql::record>{std::nullopt});
|
||||
}
|
||||
|
||||
return utils::ok(std::optional{*first.get()});
|
||||
return utils::ok(std::optional{first.release()});
|
||||
}
|
||||
|
||||
std::string fetchable_query::str(const sql::executor &exec) const {
|
||||
@@ -64,11 +63,15 @@ 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 {
|
||||
return exec.fetch(compile(exec.dialect()));
|
||||
auto ctx = 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 {
|
||||
return exec.prepare(compile(exec.dialect()));
|
||||
auto ctx = compile(exec.dialect());
|
||||
ctx.resolver_factory = exec.resolver_factory();
|
||||
return exec.prepare(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,21 +8,15 @@ detail::pk_reader::pk_reader(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)
|
||||
: column_index_(column_index)
|
||||
, prototype_(std::move(prototype))
|
||||
, reader_(std::move(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_) {
|
||||
, prototype_(std::move(prototype))
|
||||
, reader_(std::move(reader))
|
||||
, resolver_factory_(resolver_factory)
|
||||
, id_reader_(*reader_)
|
||||
, pk_reader_(*reader_) {
|
||||
}
|
||||
|
||||
void query_result_impl::on_revision(const char *id, uint64_t &rev) {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#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)
|
||||
});
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
#include "matador/orm/query_builder_exception.hpp"
|
||||
#include "matador/query/query_builder_exception.hpp"
|
||||
|
||||
namespace matador::orm {
|
||||
namespace matador::query {
|
||||
|
||||
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_( std::move(err) ) {}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#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,26 +11,6 @@
|
||||
#include "matador/sql/dialect.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_;
|
||||
}
|
||||
|
||||
schema::schema(const std::string &name)
|
||||
: repo_(name) {
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> schema::create(const sql::connection &conn) const {
|
||||
// Step 1: Build dependency graph
|
||||
@@ -64,7 +44,7 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
|
||||
|
||||
std::vector<std::string> fk_sql_commands;
|
||||
|
||||
const auto q = query::query::create().schema(repo_.name()).compile(conn);
|
||||
const auto q = query::create().schema(repo_.name()).compile(conn);
|
||||
std::cout << q.sql << std::endl;
|
||||
|
||||
// create plain tables without constraints
|
||||
@@ -184,60 +164,6 @@ utils::result<bool, utils::error> schema::table_exists(const std::string &table_
|
||||
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 {
|
||||
repo_.dump(os);
|
||||
}
|
||||
@@ -269,11 +195,11 @@ sql::query_context schema::build_drop_constraint_context(const object::repositor
|
||||
.compile(conn);
|
||||
}
|
||||
|
||||
void schema::insert_table(const std::type_index &ti, const object::repository_node &node) {
|
||||
schema::iterator schema::insert_table(const std::type_index &ti, const object::repository_node &node) {
|
||||
std::vector<table_column> columns;
|
||||
for (const auto &attr: node.info().attributes()) {
|
||||
columns.emplace_back(nullptr, attr.name(), attr.type(), attr.attributes());
|
||||
}
|
||||
std::ignore = schema_nodes_.insert({ti, schema_node{table(node.name(), columns), node}}).first;
|
||||
return schema_nodes_.insert({ti, schema_node{table(node.name(), columns), node}}).first;
|
||||
}
|
||||
} // namespace matador::query
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/dialect_token.hpp"
|
||||
#include "matador/sql/error_code.hpp"
|
||||
#include "matador/sql/interface/connection_impl.hpp"
|
||||
|
||||
|
||||
@@ -28,16 +27,29 @@ public:
|
||||
};
|
||||
|
||||
}
|
||||
connection::connection(const connection_info& info, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||
: logger_(sql_logger)
|
||||
{
|
||||
connection::connection(const connection_info& info, logger_ptr sql_logger)
|
||||
: logger_(std::move(sql_logger)) {
|
||||
connection_.reset(backend_provider::instance().create_connection(info.type, info));
|
||||
}
|
||||
|
||||
connection::connection(const std::string& dns, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||
connection::connection(const connection_info &info,
|
||||
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(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) {
|
||||
if (x.connection_) {
|
||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||
@@ -58,11 +70,13 @@ connection &connection::operator=(const connection &x) {
|
||||
connection::connection( connection&& x ) noexcept
|
||||
: connection_(std::move(x.connection_))
|
||||
, logger_(std::move(x.logger_))
|
||||
, resolver_factory_(std::move(x.resolver_factory_))
|
||||
{}
|
||||
|
||||
connection & connection::operator=(connection &&x) noexcept {
|
||||
connection_ = std::move(x.connection_);
|
||||
logger_ = std::move(x.logger_);
|
||||
resolver_factory_ = std::move(x.resolver_factory_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -71,7 +85,7 @@ connection::~connection() {
|
||||
if (!connection_) {
|
||||
return;
|
||||
}
|
||||
if (connection_->is_open()) {
|
||||
if (const auto result = connection_->is_open(); *result) {
|
||||
connection_->close();
|
||||
}
|
||||
connection_impl* impl = connection_.release();
|
||||
@@ -219,6 +233,10 @@ const class dialect &connection::dialect() const
|
||||
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 {
|
||||
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()) {
|
||||
|
||||
@@ -53,21 +53,19 @@ bool connection_ptr::valid() const {
|
||||
return connection_ != nullptr;
|
||||
}
|
||||
|
||||
connection_pool::connection_pool(const std::string& dns, size_t count)
|
||||
: info_(connection_info::parse(dns)) {
|
||||
connection_pool::connection_pool(const std::string& dns, const size_t count)
|
||||
: connection_pool(dns, count, [](const connection_info &info) { return connection{info}; })
|
||||
{}
|
||||
|
||||
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);
|
||||
while (count) {
|
||||
// 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_});
|
||||
connection_repo_.emplace_back(count, connection_creator_(info_));
|
||||
auto &conn = connection_repo_.back();
|
||||
idle_connections_.emplace(conn.id, &conn);
|
||||
// Todo: handle result
|
||||
const auto result = conn.conn.open();
|
||||
if (!result) {
|
||||
if (const auto result = conn.conn.open(); !result) {
|
||||
throw std::runtime_error("Failed to open connection");
|
||||
}
|
||||
--count;
|
||||
|
||||
@@ -35,6 +35,17 @@ field &field::operator=(field &&x) noexcept {
|
||||
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 {
|
||||
return name_;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "matador/sql/internal/identifier_reader.hpp"
|
||||
|
||||
namespace matador::sql::internal {
|
||||
identifier_reader::identifier_reader(query_result_reader &reader)
|
||||
: reader_(reader) {}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#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 &) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#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) {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#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,12 +5,11 @@
|
||||
|
||||
namespace matador::sql::detail {
|
||||
|
||||
template<>
|
||||
record *create_prototype<record>(const std::vector<object::attribute> &prototype) {
|
||||
auto result = std::make_unique<record>();
|
||||
record create_prototype(const std::vector<object::attribute> &prototype) {
|
||||
record rec;
|
||||
int index{0};
|
||||
for (const auto &col: prototype) {
|
||||
result->append({
|
||||
rec.append({
|
||||
col.name(),
|
||||
col.type(),
|
||||
col.attributes().options(),
|
||||
@@ -18,7 +17,7 @@ record *create_prototype<record>(const std::vector<object::attribute> &prototype
|
||||
index++
|
||||
});
|
||||
}
|
||||
return result.release();
|
||||
return rec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -70,9 +70,25 @@ record::const_iterator record::find(const std::string &column_name) const {
|
||||
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) {
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
const auto [fst, snd] = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(fst->second.first));
|
||||
}
|
||||
|
||||
record::iterator record::begin()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "matador/sql/statement.hpp"
|
||||
#include "matador/sql/record.hpp"
|
||||
#include "matador/sql/field.hpp"
|
||||
#include "matador/sql/query_record_result.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
@@ -64,9 +65,7 @@ utils::result<query_result<record>, utils::error> statement::fetch() const {
|
||||
}
|
||||
// logger_.info(statement_->query_.sql);
|
||||
const auto prototype = result.value()->prototype();
|
||||
return utils::ok(query_result<record>(std::move(*result), [prototype] {
|
||||
return detail::create_prototype<record>(prototype);
|
||||
}));
|
||||
return utils::ok(query_result<record>(std::move(*result), prototype));
|
||||
}
|
||||
|
||||
utils::result<std::optional<record>, utils::error> statement::fetch_one() const {
|
||||
@@ -77,15 +76,13 @@ utils::result<std::optional<record>, utils::error> statement::fetch_one() const
|
||||
}
|
||||
|
||||
const auto prototype = result.value()->prototype();
|
||||
query_result<record> records(std::move(*result), [prototype] {
|
||||
return sql::detail::create_prototype<record>(prototype);
|
||||
});
|
||||
query_result<record> records(std::move(*result), prototype);
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<record>{std::nullopt});
|
||||
}
|
||||
|
||||
return utils::ok(std::optional{*first.get()});
|
||||
return utils::ok(std::optional{first.release()});
|
||||
}
|
||||
|
||||
void statement::reset() const {
|
||||
|
||||
Reference in New Issue
Block a user