diff --git a/include/matador/query/insert_query_builder.hpp b/include/matador/query/insert_query_builder.hpp index cc50353..341d232 100644 --- a/include/matador/query/insert_query_builder.hpp +++ b/include/matador/query/insert_query_builder.hpp @@ -6,81 +6,9 @@ #include "matador/query/query.hpp" #include "matador/query/query_builder_exception.hpp" +#include "matador/utils/primary_key_accessor.hpp" + namespace matador::query { - -struct pk_setter { - const std::string &name; - std::uint64_t value; - - template - void on_primary_key(const char *id, V &pk, const utils::primary_key_attribute &/*attr*/) { - if (id != nullptr && name == id) { - pk = static_cast(value); - } - } - static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {} - template - static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {} - template - static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {} - template - static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {} - template - static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {} - template - static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {} - template - static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {} -}; - -struct pk_unset_checker { - const std::string &name; - bool unset{true}; - - template - void on_primary_key(const char *id, V &pk, const utils::primary_key_attribute &/*attr*/) { - if (id != nullptr && name == id) { - // Your convention: 0 means unset for integer PKs - unset = (static_cast(pk) == 0ULL); - } - } - static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {} - template - static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {} - template - static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {} - template - static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {} - template - static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {} - template - static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {} - template - static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {} -}; - -struct pk_value_extractor { - std::uint64_t value{0}; - - template - void on_primary_key(const char * /*id*/, V &pk, const utils::primary_key_attribute &/*attr*/) { - value = static_cast(pk); - } - static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {} - template - static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {} - template - static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {} - template - static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {} - template - static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {} - template - static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {} - template - static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {} -}; - class insert_query_builder { public: using step_query_t = std::variant; @@ -90,10 +18,7 @@ public: // Session uses these to handle manual/sequence/table pre-insert PKs utils::generator_type pk_generator{utils::generator_type::Manual}; - std::string pk_name; - - std::function pk_is_unset{}; - std::function set_pk{}; + utils::primary_key_accessor pk_accessor; // Identity post-insert std::function apply_returning{}; @@ -180,19 +105,18 @@ public: } // Extract FK value from the foreign object - pk_value_extractor fk{}; - access::process(fk, *obj); - if (fk.value == 0ULL) { + insert_step rel_step{}; + const auto pk = rel_step.pk_accessor.get(obj); + if (pk.is_valid()) { continue; } // Build INSERT into relation table with the 2 FK columns - insert_step rel_step{}; - rel_step.query = executable_query{ - insert() - .into(relation_table, {table_column{&relation_table, join_column}, table_column{&relation_table, inverse_join_column}}) - .values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}}) - }; + // rel_step.query = executable_query{ + // insert() + // .into(relation_table, {table_column{&relation_table, join_column}, table_column{&relation_table, inverse_join_column}}) + // .values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}}) + // }; relation_steps_.push_back(std::move(rel_step)); } } @@ -238,29 +162,18 @@ private: const auto &info = it->second.node().info(); insert_step step{}; if (info.has_primary_key()) { - step.pk_name = info.primary_key_attribute()->name(); step.pk_generator = it->second.pk_generator().type(); - - step.pk_is_unset = [ptr, name = step.pk_name]() { - pk_unset_checker chk{name}; - access::process(chk, *ptr); - return chk.unset; - }; - - step.set_pk = [ptr, name = step.pk_name](std::uint64_t v) { - pk_setter setter{name, v}; - access::process(setter, *ptr); - }; } if (info.has_primary_key() && step.pk_generator == utils::generator_type::Identity) { - const table_column pk_col(&it->second.table(), step.pk_name); + const auto pk_name = info.primary_key_attribute()->name(); + const table_column pk_col(&it->second.table(), pk_name); step.query = fetchable_query{insert().into(it->second.table()).values(*ptr).returning(pk_col)}; - step.apply_returning = [ptr, pk_name = step.pk_name](const sql::record &rec) { - if (auto v = rec.at(pk_name); v.has_value()) { - pk_setter setter{pk_name, *v}; - access::process(setter, *ptr); - } + step.apply_returning = [ptr, &step, pk_name = pk_name](const sql::record &rec) { + const auto& f = rec.at(pk_name); + utils::identifier id; + id.assign(f.value()); + step.pk_accessor.set(*ptr, id); }; } else { step.query = executable_query{insert().into(it->second.table()).values(*ptr)}; @@ -289,6 +202,7 @@ private: std::vector relation_steps_; std::unordered_set, visit_key_hash> visited_; + std::uint64_t current_entity_pk_{0}; }; }