Skip to content

Commit

Permalink
Merge pull request #129 from Jacyking/master
Browse files Browse the repository at this point in the history
add REGISTER_AUTO_KEY
  • Loading branch information
Jacyking authored Dec 4, 2023
2 parents cf53076 + 47cedd8 commit 9f4d00c
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 234 deletions.
16 changes: 8 additions & 8 deletions example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ struct person {
std::optional<int> age;
int id;
};
REGISTER_AUTO_KEY(person, id)
REFLECTION(person, id, name, age)

struct student {
int id;
std::string name;
int age;
int id;
};
REGISTER_AUTO_KEY(student, id)
REFLECTION_WITH_NAME(student, "t_student", id, name, age)

int main() {
Expand All @@ -58,7 +60,6 @@ int main() {
conn->create_datatable<student>(ormpp_auto_key{"id"});
auto vec = conn->query<student>();
}

#endif

#ifdef ORMPP_ENABLE_SQLITE3
Expand All @@ -79,10 +80,10 @@ int main() {

{
sqlite.delete_records<student>();
sqlite.insert<student>({0, "purecpp", 1});
sqlite.insert<student>({0, "purecpp", 2});
sqlite.insert<student>({0, "purecpp", 3});
sqlite.insert<student>({0, "purecpp", 3});
sqlite.insert<student>({"purecpp", 1});
sqlite.insert<student>({"purecpp", 2});
sqlite.insert<student>({"purecpp", 3});
sqlite.insert<student>({"purecpp", 3});
{
auto vec = sqlite.query<student>("name='purecpp'", "order by age desc");
for (auto &[name, age, id] : vec) {
Expand All @@ -96,8 +97,7 @@ int main() {
}
}
}

#endif

return 0;
}
}
63 changes: 28 additions & 35 deletions include/mysql.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,28 +99,24 @@ class mysql {
}

template <typename T, typename... Args>
int insert(const std::vector<T> &t, bool get_insert_id = false,
Args &&...args) {
return insert_impl(generate_insert_sql<T>(false), t, get_insert_id,
std::forward<Args>(args)...);
int insert(const T &t, bool get_insert_id = false, Args &&...args) {
return insert_impl(false, t, get_insert_id, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
int update(const std::vector<T> &t, Args &&...args) {
return insert_impl(generate_insert_sql<T>(true), t, false,
std::forward<Args>(args)...);
int insert(const std::vector<T> &t, bool get_insert_id = false,
Args &&...args) {
return insert_impl(false, t, get_insert_id, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
int insert(const T &t, bool get_insert_id = false, Args &&...args) {
return insert_impl(generate_insert_sql<T>(false), t, get_insert_id,
std::forward<Args>(args)...);
int update(const T &t, Args &&...args) {
return insert_impl(true, t, false, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
int update(const T &t, Args &&...args) {
return insert_impl(generate_insert_sql<T>(true), t, false,
std::forward<Args>(args)...);
int update(const std::vector<T> &t, Args &&...args) {
return insert_impl(true, t, false, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
Expand Down Expand Up @@ -497,7 +493,6 @@ class mysql {
std::string("CREATE TABLE IF NOT EXISTS ") + name.data() + "(";
auto arr = iguana::get_array<T>();
constexpr auto SIZE = sizeof...(Args);
auto_key_map_[name.data()] = "";

// auto_increment_key and key can't exist at the same time
using U = std::tuple<std::decay_t<Args>...>;
Expand Down Expand Up @@ -548,7 +543,6 @@ class mysql {
}
append(sql, " AUTO_INCREMENT");
append(sql, " PRIMARY KEY");
auto_key_map_[name.data()] = item.fields;
has_add_field = true;
}
else if constexpr (std::is_same_v<decltype(item), ormpp_unique>) {
Expand Down Expand Up @@ -591,16 +585,17 @@ class mysql {
}

template <typename T>
int stmt_execute(const T &t) {
int stmt_execute(bool update, const T &t) {
reset_error();
std::vector<MYSQL_BIND> param_binds;
auto it = auto_key_map_.find(get_name<T>());
std::string auto_key = (it == auto_key_map_.end()) ? "" : it->second;

iguana::for_each(
t, [&t, &param_binds, &auto_key, this](const auto &v, auto /*i*/) {
set_param_bind(param_binds, t.*v);
});
iguana::for_each(t, [&t, &param_binds, update, this](auto item, auto i) {
if (is_auto_key(iguana::get_name<T>(), iguana::get_name<T>(i).data()) &&
!update) {
return;
}
set_param_bind(param_binds, t.*item);
});

if (mysql_stmt_bind_param(stmt_, &param_binds[0])) {
set_last_error(mysql_stmt_error(stmt_));
Expand All @@ -621,8 +616,9 @@ class mysql {
}

template <typename T, typename... Args>
int insert_impl(const std::string &sql, const T &t,
bool get_insert_id = false, Args &&...args) {
int insert_impl(bool update, const T &t, bool get_insert_id = false,
Args &&...args) {
std::string sql = generate_insert_sql<T>(update);
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
Expand All @@ -639,7 +635,7 @@ class mysql {

auto guard = guard_statment(stmt_);

if (stmt_execute(t) < 0) {
if (stmt_execute(update, t) == INT_MIN) {
set_last_error(mysql_stmt_error(stmt_));
return INT_MIN;
}
Expand All @@ -648,8 +644,9 @@ class mysql {
}

template <typename T, typename... Args>
int insert_impl(const std::string &sql, const std::vector<T> &t,
int insert_impl(bool update, const std::vector<T> &t,
bool get_insert_id = false, Args &&...args) {
std::string sql = generate_insert_sql<T>(update);
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
Expand All @@ -666,22 +663,19 @@ class mysql {

auto guard = guard_statment(stmt_);

// transaction
bool b = begin();
if (!b)
if (!begin()) {
return INT_MIN;
}

for (auto &item : t) {
int r = stmt_execute(item);
if (r == INT_MIN) {
if (stmt_execute(update, item) == INT_MIN) {
rollback();
return INT_MIN;
}
}
b = commit();

return b ? (get_insert_id ? stmt_->mysql->insert_id : (int)t.size())
: INT_MIN;
return commit() ? (get_insert_id ? stmt_->mysql->insert_id : (int)t.size())
: INT_MIN;
}

template <typename... Args>
Expand Down Expand Up @@ -723,7 +717,6 @@ class mysql {
MYSQL_STMT *stmt_ = nullptr;
inline static bool has_error_ = false;
inline static std::string last_error_;
inline static std::map<std::string, std::string> auto_key_map_;
};
} // namespace ormpp

Expand Down
69 changes: 30 additions & 39 deletions include/postgresql.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,22 @@ class postgresql {

template <typename T, typename... Args>
constexpr int insert(const T &t, Args &&...args) {
return insert_or_update(false, t, std::forward<Args>(args)...);
return insert_impl(false, t, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
constexpr int insert(const std::vector<T> &v, Args &&...args) {
return insert_or_update(false, v, std::forward<Args>(args)...);
return insert_impl(false, v, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
constexpr int update(const T &t, Args &&...args) {
return insert_or_update(true, t, std::forward<Args>(args)...);
return insert_impl(true, t, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
constexpr int update(const std::vector<T> &v, Args &&...args) {
return insert_or_update(true, v, std::forward<Args>(args)...);
return insert_impl(true, v, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
Expand Down Expand Up @@ -265,8 +265,6 @@ class postgresql {
std::string("CREATE TABLE IF NOT EXISTS ") + name.data() + "(";
auto arr = iguana::get_array<T>();
constexpr const size_t SIZE = sizeof...(Args);
auto_key_map_[name.data()] = "";
key_map_[name.data()] = "";

// auto_increment_key and key can't exist at the same time
using U = std::tuple<std::decay_t<Args>...>;
Expand Down Expand Up @@ -302,26 +300,23 @@ class postgresql {
if constexpr (std::is_same_v<decltype(item), ormpp_not_null>) {
if (!has_add_field) {
append(sql, field_name.data(), " ", type_name_arr[i]);
has_add_field = true;
}
append(sql, " NOT NULL");
has_add_field = true;
}
else if constexpr (std::is_same_v<decltype(item), ormpp_key>) {
if (!has_add_field) {
append(sql, field_name.data(), " ", type_name_arr[i]);
has_add_field = true;
}
append(sql, " PRIMARY KEY ");
key_map_[name.data()] = item.fields;
has_add_field = true;
}
else if constexpr (std::is_same_v<decltype(item), ormpp_auto_key>) {
if (!has_add_field) {
append(sql, field_name.data(), " ");
has_add_field = true;
}
append(sql, " serial primary key");
auto_key_map_[name.data()] = item.fields;
key_map_[name.data()] = item.fields;
has_add_field = true;
}
else if constexpr (std::is_same_v<decltype(item), ormpp_unique>) {
unique_fields.insert(field_name.data());
Expand Down Expand Up @@ -361,15 +356,12 @@ class postgresql {
return PQresultStatus(res_) == PGRES_COMMAND_OK;
}

template <typename T, typename... Args>
constexpr int insert_impl(bool update, const T &t, Args &&...args) {
template <typename T>
constexpr int stmt_execute(bool update, const T &t) {
std::vector<std::vector<char>> param_values;
auto it = auto_key_map_.find(get_name<T>());
std::string auto_key =
(update || it == auto_key_map_.end()) ? "" : it->second;
iguana::for_each(t, [&t, &param_values, auto_key, this](auto item, auto i) {
if (!auto_key.empty() &&
auto_key == iguana::get_name<T>(decltype(i)::value).data()) {
iguana::for_each(t, [&t, &param_values, update, this](auto item, auto i) {
if (is_auto_key(iguana::get_name<T>(), iguana::get_name<T>(i).data()) &&
!update) {
return;
}
set_param_values(param_values, t.*item);
Expand All @@ -391,37 +383,39 @@ class postgresql {
}

template <typename T, typename... Args>
constexpr int insert_or_update(bool update, const T &t, Args &&...args) {
constexpr int insert_impl(bool update, const T &t, Args &&...args) {
std::string sql =
update ? generate_update_sql<T>(std::forward<Args...>(args)...)
: generate_auto_insert_sql<T>(auto_key_map_, false);
: generate_insert_sql<T>(update);
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
if (!prepare<T>(sql))
if (!prepare<T>(sql)) {
return INT_MIN;
}

return insert_impl(update, t, std::forward<Args>(args)...);
return stmt_execute(update, t);
}

template <typename T, typename... Args>
constexpr int insert_or_update(bool update, const std::vector<T> &v,
Args &&...args) {
constexpr int insert_impl(bool update, const std::vector<T> &v,
Args &&...args) {
std::string sql =
update ? generate_update_sql<T>(std::forward<Args...>(args)...)
: generate_auto_insert_sql<T>(auto_key_map_, false);
: generate_insert_sql<T>(update);
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
if (!begin())
if (!begin()) {
return INT_MIN;
}

if (!prepare<T>(sql))
if (!prepare<T>(sql)) {
return INT_MIN;
}

for (auto &item : v) {
auto result = insert_impl(update, item, std::forward<Args>(args)...);
if (result == INT_MIN) {
if (stmt_execute(update, item) == INT_MIN) {
rollback();
return INT_MIN;
}
Expand All @@ -443,17 +437,16 @@ class postgresql {
std::string set;
std::string fields = "(";
std::string values = "values(";
auto it = key_map_.find(name.data());
for (auto i = 0; i < SIZE; ++i) {
std::string field_name = iguana::get_name<T>(i).data();
std::string value = "$" + std::to_string(++index);
set += field_name + "=" + value;
fields += field_name;
values += value;
if (i < SIZE - 1) {
fields += ", ";
values += ", ";
set += ", ";
fields += ",";
values += ",";
set += ",";
}
else {
fields += ")";
Expand All @@ -462,11 +455,11 @@ class postgresql {
}
}
std::string conflict = "on conflict(";
if constexpr (sizeof...(args) > 0) {
if constexpr (sizeof...(Args) > 0) {
append(conflict, args...);
}
else {
conflict += it->second;
conflict += get_conflict_key(iguana::get_name<T>());
}
conflict += ")";
append(sql, fields, values, conflict, "do update set", set);
Expand Down Expand Up @@ -571,8 +564,6 @@ class postgresql {
PGresult *res_ = nullptr;
inline static bool has_error_ = false;
inline static std::string last_error_;
inline static std::map<std::string, std::string> key_map_;
inline static std::map<std::string, std::string> auto_key_map_;
};
} // namespace ormpp
#endif // ORM_POSTGRESQL_HPP
Loading

0 comments on commit 9f4d00c

Please sign in to comment.