From b3bff2dd1b497094362faea7505ca5bf812cc7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Mon, 10 Nov 2025 16:12:53 +0100 Subject: [PATCH] column, placeholder and column_value generator progress --- include/matador/query/fk_value_extractor.hpp | 5 +- include/matador/query/generator.hpp | 190 ++++++++++++++++++ .../query_update_intermediate.hpp | 6 +- ...y_value_pair.hpp => column_value_pair.hpp} | 10 +- .../matador/query/internal/query_parts.hpp | 8 +- include/matador/query/key_value_generator.hpp | 10 +- include/matador/sql/column_generator.hpp | 19 +- source/orm/CMakeLists.txt | 6 +- source/orm/query/generator.cpp | 11 + .../query_update_intermediate.cpp | 6 +- .../orm/query/internal/column_value_pair.cpp | 33 +++ source/orm/query/internal/key_value_pair.cpp | 33 --- source/orm/query/internal/query_parts.cpp | 4 +- source/orm/query/key_value_generator.cpp | 2 +- source/orm/sql/column_generator.cpp | 7 +- 15 files changed, 267 insertions(+), 83 deletions(-) create mode 100644 include/matador/query/generator.hpp rename include/matador/query/internal/{key_value_pair.hpp => column_value_pair.hpp} (63%) create mode 100644 source/orm/query/generator.cpp create mode 100644 source/orm/query/internal/column_value_pair.cpp delete mode 100644 source/orm/query/internal/key_value_pair.cpp diff --git a/include/matador/query/fk_value_extractor.hpp b/include/matador/query/fk_value_extractor.hpp index 7627bfc..a54fb32 100644 --- a/include/matador/query/fk_value_extractor.hpp +++ b/include/matador/query/fk_value_extractor.hpp @@ -3,10 +3,13 @@ #include "matador/utils/access.hpp" #include "matador/utils/field_attributes.hpp" -#include "matador/utils/foreign_attributes.hpp" #include "matador/utils/primary_key_attribute.hpp" #include "matador/utils/types.hpp" +namespace matador::utils { +class foreign_attributes; +} + namespace matador::query::detail { class fk_value_extractor diff --git a/include/matador/query/generator.hpp b/include/matador/query/generator.hpp new file mode 100644 index 0000000..e4a0796 --- /dev/null +++ b/include/matador/query/generator.hpp @@ -0,0 +1,190 @@ +#ifndef MATADOR_GENERATOR_HPP +#define MATADOR_GENERATOR_HPP + +#include +#include +#include +#include + +#include "matador/query/fk_value_extractor.hpp" +#include "matador/query/internal/column_value_pair.hpp" + +#include + +namespace matador::query::generator { +class column_generator final { +public: + template < class V > + void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) { + if (has_many_to_many_) { + return; + } + push(id); + } + void on_revision(const char *id, uint64_t &/*rev*/); + + template + void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) { + if (has_many_to_many_) { + return; + } + push(id); + } + + template + void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &attr) { + on_foreign_key(id, x, attr); + } + template + void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &attr) { + on_foreign_key(id, x, attr); + } + + template + void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &attr) { + if (has_many_to_many_) { + return; + } + if (attr.fetch() == utils::fetch_type::LAZY || force_lazy_) { + return; + } + const auto info = table_schema_.info(); + if (!info) { + return; + } + + if (seen_tables.count(info->get().name()) == 0) { + auto it = seen_tables.insert(info->get().name()).first; + table_name_stack_.push(info.value().get().name()); + typename ContainerType::value_type::value_type obj; + access::process(*this, obj); + table_name_stack_.pop(); + seen_tables.erase(it); + } + } + + template + 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*/) { + if (!has_many_to_many_) { + return; + } + push(join_column); + push(inverse_join_column); + } + + template + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} + +}; +class placeholder_generator final { +public: + template< class Type > + std::vector generate() { + Type obj; + return generate(obj); + } + + template< class Type > + std::vector generate(const Type &obj) { + result_.clear(); + access::process(*this, obj); + + return result_; + } + + template < class V > + void on_primary_key(const char * /*id*/, V &/*x*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) { + result_.emplace_back(utils::_); + } + void on_revision(const char *id, uint64_t &/*rev*/); + + template + void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) { + result_.emplace_back(utils::_); + } + + template class Pointer> + void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) { + result_.emplace_back(utils::_); + } + template class Pointer> + void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) { + result_.emplace_back(utils::_); + } + template + static void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} + +private: + std::vector result_; +}; + +class column_value_generator final { +public: + template< class Type > + std::vector generate() { + Type obj; + return generate(obj); + } + + template< class Type > + std::vector generate(const Type &obj) { + result_.clear(); + access::process(*this, obj); + + return result_; + } + + template < class V > + void on_primary_key(const char *id, V &x, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) { + result_.emplace_back(id, x); + } + void on_revision(const char *id, uint64_t &/*rev*/); + + template + void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes) { + result_.emplace_back(id, x); + } + + template class Pointer> + void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { + result_.emplace_back(id, fk_value_extractor_.extract(*x)); + } + template class Pointer> + void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { + result_.emplace_back(id, fk_value_extractor_.extract(*x)); + } + template + static void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} + +private: + detail::fk_value_extractor fk_value_extractor_{}; + std::vector result_; + +}; + +template +std::vector placeholders() { + placeholder_generator generator; + return generator.generate(); +} + +template +std::vector placeholders(const Type &obj) { + placeholder_generator generator; + return generator.generate(obj); +} + +template +std::vector column_value_pairs() { + column_value_generator generator; + return generator.generate(); +} + +template +std::vector column_value_pairs(const Type &obj) { + column_value_generator generator; + return generator.generate(obj); +} + +} +#endif //MATADOR_GENERATOR_HPP \ No newline at end of file diff --git a/include/matador/query/intermediates/query_update_intermediate.hpp b/include/matador/query/intermediates/query_update_intermediate.hpp index 208526f..d09ea93 100644 --- a/include/matador/query/intermediates/query_update_intermediate.hpp +++ b/include/matador/query/intermediates/query_update_intermediate.hpp @@ -7,7 +7,7 @@ #include "matador/query/key_value_generator.hpp" -#include "matador/query/internal/key_value_pair.hpp" +#include "matador/query/internal/column_value_pair.hpp" namespace matador::query { @@ -15,8 +15,8 @@ class query_update_intermediate : public query_intermediate { public: explicit query_update_intermediate(const sql::table& table); - query_set_intermediate set(std::initializer_list columns); - query_set_intermediate set(std::vector &&columns); + query_set_intermediate set(std::initializer_list columns); + query_set_intermediate set(std::vector &&columns); template query_set_intermediate set() { Type obj; diff --git a/include/matador/query/internal/key_value_pair.hpp b/include/matador/query/internal/column_value_pair.hpp similarity index 63% rename from include/matador/query/internal/key_value_pair.hpp rename to include/matador/query/internal/column_value_pair.hpp index 19bc41d..2fcfa48 100644 --- a/include/matador/query/internal/key_value_pair.hpp +++ b/include/matador/query/internal/column_value_pair.hpp @@ -8,12 +8,12 @@ namespace matador::query::internal { -class key_value_pair { +class column_value_pair { public: - key_value_pair(const sql::column &col, utils::database_type value); - key_value_pair(std::string name, utils::database_type value); - key_value_pair(const char *name, utils::database_type value); - key_value_pair(const char *name, utils::placeholder p); + column_value_pair(const sql::column &col, utils::database_type value); + column_value_pair(std::string name, utils::database_type value); + column_value_pair(const char *name, utils::database_type value); + column_value_pair(const char *name, utils::placeholder p); [[nodiscard]] const std::string& name() const; [[nodiscard]] const std::variant& value() const; diff --git a/include/matador/query/internal/query_parts.hpp b/include/matador/query/internal/query_parts.hpp index 0eb68c8..84e219f 100644 --- a/include/matador/query/internal/query_parts.hpp +++ b/include/matador/query/internal/query_parts.hpp @@ -4,7 +4,7 @@ #include "matador/query/query_part_visitor.hpp" #include "matador/query/criteria.hpp" -#include "matador/query/internal/key_value_pair.hpp" +#include "matador/query/internal/column_value_pair.hpp" #include "matador/query/query_part.hpp" #include "matador/sql/column.hpp" @@ -318,15 +318,15 @@ private: class query_set_part final : public query_part { public: - explicit query_set_part(const std::vector& key_value_pairs); + explicit query_set_part(const std::vector& key_value_pairs); - [[nodiscard]] const std::vector& key_values() const; + [[nodiscard]] const std::vector& key_values() const; private: void accept(query_part_visitor &visitor) override; private: - std::vector key_value_pairs_; + std::vector key_value_pairs_; }; class query_delete_part final : public query_part diff --git a/include/matador/query/key_value_generator.hpp b/include/matador/query/key_value_generator.hpp index bf55e90..b31f9d9 100644 --- a/include/matador/query/key_value_generator.hpp +++ b/include/matador/query/key_value_generator.hpp @@ -2,7 +2,7 @@ #define QUERY_KEY_VALUE_GENERATOR_HPP #include "matador/query/fk_value_extractor.hpp" -#include "matador/query/internal/key_value_pair.hpp" +#include "matador/query/internal/column_value_pair.hpp" #include "matador/utils/foreign_attributes.hpp" #include "matador/utils/primary_key_attribute.hpp" @@ -15,12 +15,12 @@ class key_value_generator { private: public: - explicit key_value_generator(std::vector &result); + explicit key_value_generator(std::vector &result); public: template < class Type > - static std::vector generate(const Type &obj) { - std::vector result; + static std::vector generate(const Type &obj) { + std::vector result; key_value_generator generator(result); access::process(generator, obj); @@ -51,7 +51,7 @@ public: private: detail::fk_value_extractor fk_value_extractor_{}; - std::vector &result_; + std::vector &result_; }; } diff --git a/include/matador/sql/column_generator.hpp b/include/matador/sql/column_generator.hpp index bc3b8c8..c4f92ab 100644 --- a/include/matador/sql/column_generator.hpp +++ b/include/matador/sql/column_generator.hpp @@ -22,8 +22,7 @@ private: column_generator(std::vector &column_infos, const object::repository &ts, const std::string &table_name, - bool force_lazy, - bool has_many_to_many = false); + bool force_lazy); public: template < class Type > @@ -56,18 +55,12 @@ public: template < class V > void on_primary_key(const char *id, V &, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) { - if (has_many_to_many_) { - return; - } push(id); } void on_revision(const char *id, uint64_t &/*rev*/); template void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) { - if (has_many_to_many_) { - return; - } push(id); } @@ -82,9 +75,6 @@ public: template void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &attr) { - if (has_many_to_many_) { - return; - } if (attr.fetch() == utils::fetch_type::LAZY || force_lazy_) { return; } @@ -105,9 +95,6 @@ public: template 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*/) { - if (!has_many_to_many_) { - return; - } push(join_column); push(inverse_join_column); } @@ -118,9 +105,6 @@ public: private: template void on_foreign_key(const char *id, Pointer &, const utils::foreign_attributes &attr) { - if (has_many_to_many_) { - return; - } if (attr.fetch() == utils::fetch_type::LAZY || force_lazy_) { push(id); } else { @@ -148,7 +132,6 @@ private: const object::repository &table_schema_; int column_index{0}; bool force_lazy_{false}; - bool has_many_to_many_{false}; }; } diff --git a/source/orm/CMakeLists.txt b/source/orm/CMakeLists.txt index 222449b..b96a863 100644 --- a/source/orm/CMakeLists.txt +++ b/source/orm/CMakeLists.txt @@ -44,7 +44,7 @@ add_library(matador-orm STATIC ../../include/matador/query/intermediates/query_update_intermediate.hpp ../../include/matador/query/intermediates/query_where_intermediate.hpp ../../include/matador/query/internal/basic_type_to_string_visitor.hpp - ../../include/matador/query/internal/key_value_pair.hpp + ../../include/matador/query/internal/column_value_pair.hpp ../../include/matador/query/internal/query_parts.hpp ../../include/matador/query/join_data.hpp ../../include/matador/query/key_value_generator.hpp @@ -123,7 +123,7 @@ add_library(matador-orm STATIC query/intermediates/query_update_intermediate.cpp query/intermediates/query_where_intermediate.cpp query/internal/basic_type_to_string_visitor.cpp - query/internal/key_value_pair.cpp + query/internal/column_value_pair.cpp query/internal/query_parts.cpp query/internal/query_result_impl.cpp query/key_value_generator.cpp @@ -154,6 +154,8 @@ add_library(matador-orm STATIC sql/statement.cpp sql/statement_cache.cpp sql/table.cpp + ../../include/matador/query/generator.hpp + query/generator.cpp ) target_include_directories(matador-orm diff --git a/source/orm/query/generator.cpp b/source/orm/query/generator.cpp new file mode 100644 index 0000000..0024e7d --- /dev/null +++ b/source/orm/query/generator.cpp @@ -0,0 +1,11 @@ +#include "matador/query/generator.hpp" + +namespace matador::query::generator { +void placeholder_generator::on_revision(const char* /*id*/, uint64_t&) { + result_.emplace_back(utils::_); +} + +void column_value_generator::on_revision(const char* id, uint64_t& x) { + result_.emplace_back(id, x); +} +} \ No newline at end of file diff --git a/source/orm/query/intermediates/query_update_intermediate.cpp b/source/orm/query/intermediates/query_update_intermediate.cpp index 06e39fd..0d1b369 100644 --- a/source/orm/query/intermediates/query_update_intermediate.cpp +++ b/source/orm/query/intermediates/query_update_intermediate.cpp @@ -9,12 +9,12 @@ query_update_intermediate::query_update_intermediate(const sql::table& table) context_->parts.push_back(std::make_unique(table)); } -query_set_intermediate query_update_intermediate::set(const std::initializer_list columns) +query_set_intermediate query_update_intermediate::set(const std::initializer_list columns) { - return set(std::vector{columns}); + return set(std::vector{columns}); } -query_set_intermediate query_update_intermediate::set(std::vector &&columns) +query_set_intermediate query_update_intermediate::set(std::vector &&columns) { context_->parts.push_back(std::make_unique(std::move(columns))); return {context_}; diff --git a/source/orm/query/internal/column_value_pair.cpp b/source/orm/query/internal/column_value_pair.cpp new file mode 100644 index 0000000..35ce1e5 --- /dev/null +++ b/source/orm/query/internal/column_value_pair.cpp @@ -0,0 +1,33 @@ +#include "matador/query/internal/column_value_pair.hpp" + +#include + +namespace matador::query::internal { + +column_value_pair::column_value_pair(std::string name, utils::database_type value) +: name_(std::move(name)) +, value_(std::move(value)) { +} + +column_value_pair::column_value_pair(const sql::column &col, utils::database_type value) +: name_(col.name) +, value_(std::move(value)) { +} + +column_value_pair::column_value_pair(const char *name, utils::database_type value) +: name_(name) +, value_(std::move(value)) { +} + +column_value_pair::column_value_pair( const char* name, utils::placeholder p ) +: name_(name) +, value_(p) {} + +const std::string &column_value_pair::name() const { + return name_; +} + +const std::variant& column_value_pair::value() const { + return value_; +} +} \ No newline at end of file diff --git a/source/orm/query/internal/key_value_pair.cpp b/source/orm/query/internal/key_value_pair.cpp deleted file mode 100644 index 97ef1df..0000000 --- a/source/orm/query/internal/key_value_pair.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "matador/query/internal/key_value_pair.hpp" - -#include - -namespace matador::query::internal { - -key_value_pair::key_value_pair(std::string name, utils::database_type value) -: name_(std::move(name)) -, value_(std::move(value)) { -} - -key_value_pair::key_value_pair(const sql::column &col, utils::database_type value) -: name_(col.name) -, value_(std::move(value)) { -} - -key_value_pair::key_value_pair(const char *name, utils::database_type value) -: name_(name) -, value_(std::move(value)) { -} - -key_value_pair::key_value_pair( const char* name, utils::placeholder p ) -: name_(name) -, value_(p) {} - -const std::string &key_value_pair::name() const { - return name_; -} - -const std::variant& key_value_pair::value() const { - return value_; -} -} \ No newline at end of file diff --git a/source/orm/query/internal/query_parts.cpp b/source/orm/query/internal/query_parts.cpp index 9466cbf..b64413f 100644 --- a/source/orm/query/internal/query_parts.cpp +++ b/source/orm/query/internal/query_parts.cpp @@ -300,11 +300,11 @@ void query_update_part::accept(query_part_visitor &visitor) visitor.visit(*this); } -query_set_part::query_set_part(const std::vector& key_value_pairs) +query_set_part::query_set_part(const std::vector& key_value_pairs) : query_part(sql::dialect_token::Set) , key_value_pairs_(key_value_pairs) {} -const std::vector &query_set_part::key_values() const +const std::vector &query_set_part::key_values() const { return key_value_pairs_; } diff --git a/source/orm/query/key_value_generator.cpp b/source/orm/query/key_value_generator.cpp index 2fc59ac..5c02233 100644 --- a/source/orm/query/key_value_generator.cpp +++ b/source/orm/query/key_value_generator.cpp @@ -3,7 +3,7 @@ #include "matador/query/value_extractor.hpp" namespace matador::query { -key_value_generator::key_value_generator(std::vector &result) +key_value_generator::key_value_generator(std::vector &result) : result_(result) {} void key_value_generator::on_revision(const char *id, uint64_t &x) { diff --git a/source/orm/sql/column_generator.cpp b/source/orm/sql/column_generator.cpp index fa3da86..2bfd9b8 100644 --- a/source/orm/sql/column_generator.cpp +++ b/source/orm/sql/column_generator.cpp @@ -7,12 +7,10 @@ namespace matador::sql { column_generator::column_generator(std::vector &column_infos, const object::repository &scm, const std::string &table_name, - const bool force_lazy, - const bool has_many_to_many) + const bool force_lazy) : column_infos_(column_infos) , table_schema_(scm) , force_lazy_(force_lazy) -, has_many_to_many_(has_many_to_many) { table_name_stack_.push(table_name); seen_tables.insert(table_name); @@ -33,9 +31,6 @@ std::vector column_generator::generate( const object::repository& scm, c void column_generator::on_revision(const char *id, uint64_t &) { - if (has_many_to_many_) { - return; - } push(id); }