Skip to content

Commit

Permalink
Merge pull request #131 from Jacyking/master
Browse files Browse the repository at this point in the history
add update&replace api
  • Loading branch information
Jacyking authored Dec 14, 2023
2 parents 899f2e6 + e140556 commit df75b98
Show file tree
Hide file tree
Showing 6 changed files with 436 additions and 105 deletions.
10 changes: 10 additions & 0 deletions include/dbng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ class dbng {
return db_.update(t, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
int replace(const T &t, Args &&...args) {
return db_.replace(t, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
int replace(const std::vector<T> &t, Args &&...args) {
return db_.replace(t, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
bool delete_records(Args &&...where_conditon) {
return db_.template delete_records<T>(
Expand Down
90 changes: 70 additions & 20 deletions include/mysql.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,35 @@ class mysql {

template <typename T, typename... 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)...);
return insert_impl(OptType::insert, t, get_insert_id,
std::forward<Args>(args)...);
}

template <typename T, typename... 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)...);
return insert_impl(OptType::insert, t, get_insert_id,
std::forward<Args>(args)...);
}

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

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

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

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

template <typename T, typename... Args>
Expand Down Expand Up @@ -617,18 +629,27 @@ class mysql {
}

template <typename T>
int stmt_execute(bool update, const T &t) {
reset_error();
int stmt_execute(const T &t, OptType type, bool condition) {
std::vector<MYSQL_BIND> param_binds;

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) {
iguana::for_each(t, [&t, &param_binds, type, this](auto item, auto i) {
if (type == OptType::insert &&
is_auto_key<T>(iguana::get_name<T>(i).data())) {
return;
}
set_param_bind(param_binds, t.*item);
});

if (condition && type == OptType::update) {
iguana::for_each(t, [&t, &param_binds, this](auto item, auto i) {
std::string field_name = "`";
field_name += iguana::get_name<T>(i).data();
field_name += "`";
if (is_conflict_key<T>(field_name)) {
set_param_bind(param_binds, t.*item);
}
});
}

if (mysql_stmt_bind_param(stmt_, &param_binds[0])) {
set_last_error(mysql_stmt_error(stmt_));
return INT_MIN;
Expand All @@ -648,9 +669,38 @@ class mysql {
}

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

template <typename T, typename... Args>
int insert_impl(OptType type, const std::vector<T> &v, bool get_insert_id,
Args &&...args) {
std::string sql = generate_insert_sql<T>(type == OptType::insert);
return insert_or_update_impl(v, sql, type, get_insert_id);
}

template <typename T, typename... Args>
int update_impl(const T &t, Args &&...args) {
bool condition = true;
std::string sql =
generate_update_sql<T>(condition, std::forward<Args>(args)...);
return insert_or_update_impl(t, sql, OptType::update, false, condition);
}

template <typename T, typename... Args>
int update_impl(const std::vector<T> &v, Args &&...args) {
bool condition = true;
std::string sql =
generate_update_sql<T>(condition, std::forward<Args>(args)...);
return insert_or_update_impl(v, sql, OptType::update, false, condition);
}

template <typename T>
int insert_or_update_impl(const T &t, const std::string &sql, OptType type,
bool get_insert_id = false, bool condition = true) {
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
Expand All @@ -667,18 +717,18 @@ class mysql {

auto guard = guard_statment(stmt_);

if (stmt_execute(update, t) == INT_MIN) {
if (stmt_execute(t, type, condition) == INT_MIN) {
set_last_error(mysql_stmt_error(stmt_));
return INT_MIN;
}

return get_insert_id ? stmt_->mysql->insert_id : 1;
}

template <typename T, typename... Args>
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);
template <typename T>
int insert_or_update_impl(const std::vector<T> &v, const std::string &sql,
OptType type, bool get_insert_id = false,
bool condition = true) {
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
Expand All @@ -699,14 +749,14 @@ class mysql {
return INT_MIN;
}

for (auto &item : t) {
if (stmt_execute(update, item) == INT_MIN) {
for (auto &item : v) {
if (stmt_execute(item, type, condition) == INT_MIN) {
rollback();
return INT_MIN;
}
}

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

Expand Down
122 changes: 63 additions & 59 deletions include/postgresql.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,32 @@ class postgresql {

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

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

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

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

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

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

template <typename T, typename... Args>
Expand Down Expand Up @@ -359,16 +369,24 @@ class postgresql {
}

template <typename T>
constexpr int stmt_execute(bool update, const T &t) {
constexpr int stmt_execute(const T &t, OptType type, bool condition) {
std::vector<std::vector<char>> param_values;
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) {
iguana::for_each(t, [&t, &param_values, type, this](auto item, auto i) {
if (type == OptType::insert &&
is_auto_key<T>(iguana::get_name<T>(i).data())) {
return;
}
set_param_values(param_values, t.*item);
});

if (condition && type == OptType::update) {
iguana::for_each(t, [&t, &param_values, this](auto item, auto i) {
if (is_conflict_key<T>(iguana::get_name<T>(i).data())) {
set_param_values(param_values, t.*item);
}
});
}

if (param_values.empty())
return INT_MIN;

Expand All @@ -385,26 +403,51 @@ class postgresql {
}

template <typename T, typename... Args>
constexpr int insert_impl(bool update, const T &t, Args &&...args) {
constexpr int insert_impl(OptType type, const T &t, Args &&...args) {
std::string sql = generate_insert_sql<T>(type == OptType::insert,
std::forward<Args>(args)...);
return insert_or_update_impl(t, sql, type);
}

template <typename T, typename... Args>
constexpr int insert_impl(OptType type, const std::vector<T> &v,
Args &&...args) {
std::string sql = generate_insert_sql<T>(type == OptType::insert,
std::forward<Args>(args)...);
return insert_or_update_impl(v, sql, type);
}

template <typename T, typename... Args>
int update_impl(const T &t, Args &&...args) {
bool condition = true;
std::string sql =
generate_update_sql<T>(condition, std::forward<Args>(args)...);
return insert_or_update_impl(t, sql, OptType::update, condition);
}

template <typename T, typename... Args>
int update_impl(const std::vector<T> &v, Args &&...args) {
bool condition = true;
std::string sql =
update ? generate_update_sql<T>(std::forward<Args...>(args)...)
: generate_insert_sql<T>(update);
generate_update_sql<T>(condition, std::forward<Args>(args)...);
return insert_or_update_impl(v, sql, OptType::update, condition);
}

template <typename T>
int insert_or_update_impl(const T &t, const std::string &sql, OptType type,
bool condition = true) {
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
if (!prepare<T>(sql)) {
return INT_MIN;
}

return stmt_execute(update, t);
return stmt_execute(t, type, condition);
}

template <typename T, typename... 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_insert_sql<T>(update);
template <typename T>
int insert_or_update_impl(const std::vector<T> &v, const std::string &sql,
OptType type, bool condition = true) {
#ifdef ORMPP_ENABLE_LOG
std::cout << sql << std::endl;
#endif
Expand All @@ -417,7 +460,7 @@ class postgresql {
}

for (auto &item : v) {
if (stmt_execute(update, item) == INT_MIN) {
if (stmt_execute(item, type, condition) == INT_MIN) {
rollback();
return INT_MIN;
}
Expand All @@ -429,45 +472,6 @@ class postgresql {
return (int)v.size();
}

template <typename T, typename... Args>
inline std::string generate_update_sql(Args &&...args) {
constexpr auto SIZE = iguana::get_value<T>();
std::string sql = "insert into ";
auto name = get_name<T>();
append(sql, name.data());
int index = 0;
std::string set;
std::string fields = "(";
std::string values = "values(";
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 += ",";
}
else {
fields += ")";
values += ")";
set += ";";
}
}
std::string conflict = "on conflict(";
if constexpr (sizeof...(Args) > 0) {
append(conflict, args...);
}
else {
conflict += get_conflict_key(iguana::get_name<T>());
}
conflict += ")";
append(sql, fields, values, conflict, "do update set", set);
return sql;
}

template <typename T>
constexpr void set_param_values(std::vector<std::vector<char>> &param_values,
T &&value) {
Expand Down
Loading

0 comments on commit df75b98

Please sign in to comment.