implemented lazy loading for object_ptr and belongs_to

This commit is contained in:
2026-01-15 12:40:54 +01:00
parent db8e137c11
commit 7626331866
81 changed files with 1790 additions and 927 deletions
+92
View File
@@ -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 -1
View File
@@ -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) {
+81
View File
@@ -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)
});
}
}
@@ -0,0 +1,17 @@
#include "matador/query/query_builder_exception.hpp"
namespace matador::query {
query_builder_exception::query_builder_exception(const query_build_error error, utils::error&& err)
: error_type_(error)
, error_( std::move(err) ) {}
query_build_error query_builder_exception::error_type() const {
return error_type_;
}
const utils::error& query_builder_exception::error() const {
return error_;
}
}
@@ -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);
}
}
+3 -77
View File
@@ -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