replaced pk_is_unset, pk_setter and pk_value_extractor with pk_accessor
This commit is contained in:
parent
1806e2670c
commit
57246d8742
|
|
@ -6,81 +6,9 @@
|
||||||
#include "matador/query/query.hpp"
|
#include "matador/query/query.hpp"
|
||||||
#include "matador/query/query_builder_exception.hpp"
|
#include "matador/query/query_builder_exception.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/primary_key_accessor.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
struct pk_setter {
|
|
||||||
const std::string &name;
|
|
||||||
std::uint64_t value;
|
|
||||||
|
|
||||||
template<class V>
|
|
||||||
void on_primary_key(const char *id, V &pk, const utils::primary_key_attribute &/*attr*/) {
|
|
||||||
if (id != nullptr && name == id) {
|
|
||||||
pk = static_cast<V>(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
|
||||||
template<typename T>
|
|
||||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {}
|
|
||||||
template<class P>
|
|
||||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
|
||||||
template<class P>
|
|
||||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
|
||||||
template<class C>
|
|
||||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
|
||||||
template<class C>
|
|
||||||
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<class C>
|
|
||||||
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<class V>
|
|
||||||
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<std::uint64_t>(pk) == 0ULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
|
||||||
template<typename T>
|
|
||||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {}
|
|
||||||
template<class P>
|
|
||||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
|
||||||
template<class P>
|
|
||||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
|
||||||
template<class C>
|
|
||||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
|
||||||
template<class C>
|
|
||||||
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<class C>
|
|
||||||
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<class V>
|
|
||||||
void on_primary_key(const char * /*id*/, V &pk, const utils::primary_key_attribute &/*attr*/) {
|
|
||||||
value = static_cast<std::uint64_t>(pk);
|
|
||||||
}
|
|
||||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
|
||||||
template<typename T>
|
|
||||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes &/*attr*/) {}
|
|
||||||
template<class P>
|
|
||||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
|
||||||
template<class P>
|
|
||||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
|
||||||
template<class C>
|
|
||||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
|
||||||
template<class C>
|
|
||||||
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<class C>
|
|
||||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class insert_query_builder {
|
class insert_query_builder {
|
||||||
public:
|
public:
|
||||||
using step_query_t = std::variant<executable_query, fetchable_query>;
|
using step_query_t = std::variant<executable_query, fetchable_query>;
|
||||||
|
|
@ -90,10 +18,7 @@ public:
|
||||||
|
|
||||||
// Session uses these to handle manual/sequence/table pre-insert PKs
|
// Session uses these to handle manual/sequence/table pre-insert PKs
|
||||||
utils::generator_type pk_generator{utils::generator_type::Manual};
|
utils::generator_type pk_generator{utils::generator_type::Manual};
|
||||||
std::string pk_name;
|
utils::primary_key_accessor pk_accessor;
|
||||||
|
|
||||||
std::function<bool()> pk_is_unset{};
|
|
||||||
std::function<void(std::uint64_t)> set_pk{};
|
|
||||||
|
|
||||||
// Identity post-insert
|
// Identity post-insert
|
||||||
std::function<void(const sql::record &)> apply_returning{};
|
std::function<void(const sql::record &)> apply_returning{};
|
||||||
|
|
@ -180,19 +105,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract FK value from the foreign object
|
// Extract FK value from the foreign object
|
||||||
pk_value_extractor fk{};
|
insert_step rel_step{};
|
||||||
access::process(fk, *obj);
|
const auto pk = rel_step.pk_accessor.get(obj);
|
||||||
if (fk.value == 0ULL) {
|
if (pk.is_valid()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build INSERT into relation table with the 2 FK columns
|
// Build INSERT into relation table with the 2 FK columns
|
||||||
insert_step rel_step{};
|
// rel_step.query = executable_query{
|
||||||
rel_step.query = executable_query{
|
// insert()
|
||||||
insert()
|
// .into(relation_table, {table_column{&relation_table, join_column}, table_column{&relation_table, inverse_join_column}})
|
||||||
.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}})
|
||||||
.values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}})
|
// };
|
||||||
};
|
|
||||||
relation_steps_.push_back(std::move(rel_step));
|
relation_steps_.push_back(std::move(rel_step));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,29 +162,18 @@ private:
|
||||||
const auto &info = it->second.node().info();
|
const auto &info = it->second.node().info();
|
||||||
insert_step step{};
|
insert_step step{};
|
||||||
if (info.has_primary_key()) {
|
if (info.has_primary_key()) {
|
||||||
step.pk_name = info.primary_key_attribute()->name();
|
|
||||||
step.pk_generator = it->second.pk_generator().type();
|
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) {
|
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.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) {
|
step.apply_returning = [ptr, &step, pk_name = pk_name](const sql::record &rec) {
|
||||||
if (auto v = rec.at<std::uint64_t>(pk_name); v.has_value()) {
|
const auto& f = rec.at(pk_name);
|
||||||
pk_setter setter{pk_name, *v};
|
utils::identifier id;
|
||||||
access::process(setter, *ptr);
|
id.assign(f.value());
|
||||||
}
|
step.pk_accessor.set(*ptr, id);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
step.query = executable_query{insert().into(it->second.table()).values(*ptr)};
|
step.query = executable_query{insert().into(it->second.table()).values(*ptr)};
|
||||||
|
|
@ -289,6 +202,7 @@ private:
|
||||||
std::vector<insert_step> relation_steps_;
|
std::vector<insert_step> relation_steps_;
|
||||||
std::unordered_set<std::pair<std::type_index, const void *>, visit_key_hash> visited_;
|
std::unordered_set<std::pair<std::type_index, const void *>, visit_key_hash> visited_;
|
||||||
|
|
||||||
|
|
||||||
std::uint64_t current_entity_pk_{0};
|
std::uint64_t current_entity_pk_{0};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue