From 2373ad9988f686b4dec80d4dfc957039f110af31 Mon Sep 17 00:00:00 2001 From: Jacyking <791026912@qq.com> Date: Thu, 14 Dec 2023 11:23:43 +0800 Subject: [PATCH 1/5] add pg get_insert_id --- include/mysql.hpp | 39 ++++++++--------- include/postgresql.hpp | 95 ++++++++++++++++++++++++------------------ include/sqlite.hpp | 39 ++++++++--------- include/utility.hpp | 14 +++++-- tests/test_ormpp.cpp | 32 +++++++++++++- 5 files changed, 136 insertions(+), 83 deletions(-) diff --git a/include/mysql.hpp b/include/mysql.hpp index 5f553a7c..199bc365 100644 --- a/include/mysql.hpp +++ b/include/mysql.hpp @@ -99,35 +99,35 @@ class mysql { } template - int insert(const T &t, bool get_insert_id = false, Args &&...args) { + constexpr int insert(const T &t, bool get_insert_id, Args &&...args) { return insert_impl(OptType::insert, t, get_insert_id, std::forward(args)...); } template - int insert(const std::vector &t, bool get_insert_id = false, - Args &&...args) { + constexpr int insert(const std::vector &t, bool get_insert_id, + Args &&...args) { return insert_impl(OptType::insert, t, get_insert_id, std::forward(args)...); } template - int replace(const T &t, Args &&...args) { + constexpr int replace(const T &t, Args &&...args) { return insert_impl(OptType::replace, t, false, std::forward(args)...); } template - int replace(const std::vector &t, Args &&...args) { + constexpr int replace(const std::vector &t, Args &&...args) { return insert_impl(OptType::replace, t, false, std::forward(args)...); } template - int update(const T &t, Args &&...args) { + constexpr int update(const T &t, Args &&...args) { return update_impl(t, std::forward(args)...); } template - int update(const std::vector &t, Args &&...args) { + constexpr int update(const std::vector &t, Args &&...args) { return update_impl(t, std::forward(args)...); } @@ -667,21 +667,21 @@ class mysql { } template - int insert_impl(OptType type, const T &t, bool get_insert_id, - Args &&...args) { + constexpr int insert_impl(OptType type, const T &t, bool get_insert_id, + Args &&...args) { std::string sql = generate_insert_sql(type == OptType::insert); return insert_or_update_impl(t, sql, type, get_insert_id); } template - int insert_impl(OptType type, const std::vector &v, bool get_insert_id, - Args &&...args) { + constexpr int insert_impl(OptType type, const std::vector &v, + bool get_insert_id, Args &&...args) { std::string sql = generate_insert_sql(type == OptType::insert); return insert_or_update_impl(v, sql, type, get_insert_id); } template - int update_impl(const T &t, Args &&...args) { + constexpr int update_impl(const T &t, Args &&...args) { bool condition = true; std::string sql = generate_update_sql(condition, std::forward(args)...); @@ -689,7 +689,7 @@ class mysql { } template - int update_impl(const std::vector &v, Args &&...args) { + constexpr int update_impl(const std::vector &v, Args &&...args) { bool condition = true; std::string sql = generate_update_sql(condition, std::forward(args)...); @@ -697,8 +697,9 @@ class mysql { } template - int insert_or_update_impl(const T &t, const std::string &sql, OptType type, - bool get_insert_id = false, bool condition = true) { + constexpr 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 @@ -716,7 +717,6 @@ class mysql { auto guard = guard_statment(stmt_); if (stmt_execute(t, type, condition) == INT_MIN) { - set_last_error(mysql_stmt_error(stmt_)); return INT_MIN; } @@ -724,9 +724,10 @@ class mysql { } template - int insert_or_update_impl(const std::vector &v, const std::string &sql, - OptType type, bool get_insert_id = false, - bool condition = true) { + constexpr int insert_or_update_impl(const std::vector &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 diff --git a/include/postgresql.hpp b/include/postgresql.hpp index 98c53603..5f0e7a27 100644 --- a/include/postgresql.hpp +++ b/include/postgresql.hpp @@ -74,23 +74,26 @@ class postgresql { } template - constexpr int insert(const T &t, Args &&...args) { - return insert_impl(OptType::insert, t, std::forward(args)...); + constexpr int insert(const T &t, bool get_insert_id, Args &&...args) { + return insert_impl(OptType::insert, t, get_insert_id, + std::forward(args)...); } template - constexpr int insert(const std::vector &v, Args &&...args) { - return insert_impl(OptType::insert, v, std::forward(args)...); + constexpr int insert(const std::vector &v, bool get_insert_id, + Args &&...args) { + return insert_impl(OptType::insert, v, get_insert_id, + std::forward(args)...); } template constexpr int replace(const T &t, Args &&...args) { - return insert_impl(OptType::replace, t, std::forward(args)...); + return insert_impl(OptType::replace, t, false, std::forward(args)...); } template constexpr int replace(const std::vector &v, Args &&...args) { - return insert_impl(OptType::replace, v, std::forward(args)...); + return insert_impl(OptType::replace, v, false, std::forward(args)...); } template @@ -107,9 +110,6 @@ class postgresql { constexpr std::enable_if_t, std::vector> query( Args &&...args) { std::string sql = generate_query_sql(args...); -#ifdef ORMPP_ENABLE_LOG - std::cout << sql << std::endl; -#endif constexpr auto SIZE = iguana::get_value(); if (!prepare(sql)) @@ -142,9 +142,6 @@ class postgresql { constexpr auto SIZE = std::tuple_size_v; std::string sql = s; -#ifdef ORMPP_ENABLE_LOG - std::cout << sql << std::endl; -#endif constexpr auto Args_Size = sizeof...(Args); if (Args_Size != 0) { if (Args_Size != std::count(sql.begin(), sql.end(), '$')) @@ -362,6 +359,9 @@ class postgresql { template bool prepare(const std::string &sql) { +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif res_ = PQprepare(con_, "", sql.data(), (int)iguana::get_value(), nullptr); auto guard = guard_statment(res_); @@ -387,8 +387,9 @@ class postgresql { }); } - if (param_values.empty()) + if (param_values.empty()) { return INT_MIN; + } std::vector param_values_buf; for (auto &item : param_values) { @@ -399,77 +400,91 @@ class postgresql { param_values_buf.data(), NULL, NULL, 0); auto guard = guard_statment(res_); - return PQresultStatus(res_) == PGRES_COMMAND_OK ? 1 : INT_MIN; + auto status = PQresultStatus(res_); + + if (status == PGRES_TUPLES_OK) { + return std::atoll(PQgetvalue(res_, 0, 0)); + } + else if (status == PGRES_COMMAND_OK) { + return 1; + } + + return INT_MIN; } template - constexpr int insert_impl(OptType type, const T &t, Args &&...args) { + constexpr int insert_impl(OptType type, const T &t, bool get_insert_id, + Args &&...args) { std::string sql = generate_insert_sql(type == OptType::insert, std::forward(args)...); - return insert_or_update_impl(t, sql, type); + return insert_or_update_impl(t, sql, type, get_insert_id); } template constexpr int insert_impl(OptType type, const std::vector &v, - Args &&...args) { + bool get_insert_id, Args &&...args) { std::string sql = generate_insert_sql(type == OptType::insert, std::forward(args)...); - return insert_or_update_impl(v, sql, type); + return insert_or_update_impl(v, sql, type, get_insert_id); } template - int update_impl(const T &t, Args &&...args) { + constexpr int update_impl(const T &t, Args &&...args) { bool condition = true; std::string sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, condition); + return insert_or_update_impl(t, sql, OptType::update, false, condition); } template - int update_impl(const std::vector &v, Args &&...args) { + constexpr int update_impl(const std::vector &v, Args &&...args) { bool condition = true; std::string sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, condition); + return insert_or_update_impl(v, sql, OptType::update, false, condition); } template - 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(sql)) { + constexpr int insert_or_update_impl(const T &t, const std::string &sql, + OptType type, bool get_insert_id = false, + bool condition = true) { + if (!prepare(get_insert_id + ? sql + "returning " + get_auto_key().data() + : sql)) { return INT_MIN; } - return stmt_execute(t, type, condition); + auto res = stmt_execute(t, type, condition); + if (res == INT_MIN) { + return INT_MIN; + } + return get_insert_id ? res : 1; } template - int insert_or_update_impl(const std::vector &v, const std::string &sql, - OptType type, bool condition = true) { -#ifdef ORMPP_ENABLE_LOG - std::cout << sql << std::endl; -#endif + constexpr int insert_or_update_impl(const std::vector &v, + const std::string &sql, OptType type, + bool get_insert_id = false, + bool condition = true) { if (!begin()) { return INT_MIN; } - if (!prepare(sql)) { + if (!prepare(get_insert_id + ? sql + "returning " + get_auto_key().data() + : sql)) { return INT_MIN; } + int res = INT_MIN; for (auto &item : v) { - if (stmt_execute(item, type, condition) == INT_MIN) { + res = stmt_execute(item, type, condition); + if (res == INT_MIN) { rollback(); return INT_MIN; } } - if (!commit()) - return INT_MIN; - - return (int)v.size(); + return commit() ? get_insert_id ? res : (int)v.size() : INT_MIN; } template diff --git a/include/sqlite.hpp b/include/sqlite.hpp index 0771f0e8..f4a5c102 100644 --- a/include/sqlite.hpp +++ b/include/sqlite.hpp @@ -72,35 +72,35 @@ class sqlite { } template - int insert(const T &t, bool get_insert_id = false, Args &&...args) { + constexpr int insert(const T &t, bool get_insert_id, Args &&...args) { return insert_impl(OptType::insert, t, get_insert_id, std::forward(args)...); } template - int insert(const std::vector &t, bool get_insert_id = false, - Args &&...args) { + constexpr int insert(const std::vector &t, bool get_insert_id, + Args &&...args) { return insert_impl(OptType::insert, t, get_insert_id, std::forward(args)...); } template - int replace(const T &t, Args &&...args) { + constexpr int replace(const T &t, Args &&...args) { return insert_impl(OptType::replace, t, false, std::forward(args)...); } template - int replace(const std::vector &t, Args &&...args) { + constexpr int replace(const std::vector &t, Args &&...args) { return insert_impl(OptType::replace, t, false, std::forward(args)...); } template - int update(const T &t, Args &&...args) { + constexpr int update(const T &t, Args &&...args) { return update_impl(t, std::forward(args)...); } template - int update(const std::vector &t, Args &&...args) { + constexpr int update(const std::vector &t, Args &&...args) { return update_impl(t, std::forward(args)...); } @@ -486,21 +486,21 @@ class sqlite { } template - int insert_impl(OptType type, const T &t, bool get_insert_id, - Args &&...args) { + constexpr int insert_impl(OptType type, const T &t, bool get_insert_id, + Args &&...args) { std::string sql = generate_insert_sql(type == OptType::insert); return insert_or_update_impl(t, sql, type, get_insert_id); } template - int insert_impl(OptType type, const std::vector &v, bool get_insert_id, - Args &&...args) { + constexpr int insert_impl(OptType type, const std::vector &v, + bool get_insert_id, Args &&...args) { std::string sql = generate_insert_sql(type == OptType::insert); return insert_or_update_impl(v, sql, type, get_insert_id); } template - int update_impl(const T &t, Args &&...args) { + constexpr int update_impl(const T &t, Args &&...args) { bool condition = true; std::string sql = generate_update_sql(condition, std::forward(args)...); @@ -508,7 +508,7 @@ class sqlite { } template - int update_impl(const std::vector &v, Args &&...args) { + constexpr int update_impl(const std::vector &v, Args &&...args) { bool condition = true; std::string sql = generate_update_sql(condition, std::forward(args)...); @@ -516,8 +516,9 @@ class sqlite { } template - int insert_or_update_impl(const T &t, const std::string &sql, OptType type, - bool get_insert_id = false, bool condition = true) { + constexpr 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 @@ -530,7 +531,6 @@ class sqlite { auto guard = guard_statment(stmt_); if (stmt_execute(t, type, condition) == INT_MIN) { - set_last_error(sqlite3_errmsg(handle_)); return INT_MIN; } @@ -538,9 +538,10 @@ class sqlite { } template - int insert_or_update_impl(const std::vector &v, const std::string &sql, - OptType type, bool get_insert_id = false, - bool condition = true) { + constexpr int insert_or_update_impl(const std::vector &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 diff --git a/include/utility.hpp b/include/utility.hpp index 7c35ec2e..491a85e2 100644 --- a/include/utility.hpp +++ b/include/utility.hpp @@ -19,6 +19,12 @@ inline int add_auto_key_field(std::string_view key, std::string_view value) { return 0; } +template +inline auto get_auto_key() { + auto it = g_ormpp_auto_key_map.find(iguana::get_name()); + return it == g_ormpp_auto_key_map.end() ? "" : it->second; +} + template inline auto is_auto_key(std::string_view field_name) { auto it = g_ormpp_auto_key_map.find(iguana::get_name()); @@ -38,7 +44,9 @@ inline int add_conflict_key_field(std::string_view key, return 0; } -inline auto get_conflict_key(std::string_view key) { +template +inline auto get_conflict_key() { + auto key = iguana::get_name(); auto it = g_ormpp_conflict_key_map.find(key); if (it == g_ormpp_conflict_key_map.end()) { auto auto_key = g_ormpp_auto_key_map.find(key); @@ -207,7 +215,7 @@ inline std::vector get_conflict_keys() { if (!res.empty()) { return res; } - std::stringstream s(get_conflict_key(iguana::get_name()).data()); + std::stringstream s(get_conflict_key().data()); while (s.good()) { std::string str; getline(s, str, ','); @@ -270,7 +278,7 @@ inline std::string generate_insert_sql(bool insert, Args &&...args) { append(conflict, args...); } else { - conflict += get_conflict_key(iguana::get_name()); + conflict += get_conflict_key(); } conflict += ")"; append(sql, fields, values, conflict, "do update set", set); diff --git a/tests/test_ormpp.cpp b/tests/test_ormpp.cpp index 7f192b69..9a543b1d 100644 --- a/tests/test_ormpp.cpp +++ b/tests/test_ormpp.cpp @@ -1027,7 +1027,22 @@ TEST_CASE("create table with unique") { CHECK(vec3.size() == 1); } #endif - +#ifdef ORMPP_ENABLE_PG + dbng postgres; + if (postgres.connect(ip, username, password, db)) { + postgres.execute("drop table if exists person"); + postgres.create_datatable(ormpp_auto_key{"id"}, + ormpp_unique{{"name", "age"}}); + postgres.insert({"purecpp"}); + auto vec1 = postgres.query("order by id"); + auto vec2 = postgres.query("limit 1"); + CHECK(vec1.size() == 1); + CHECK(vec2.size() == 1); + postgres.insert({"purecpp"}); + auto vec3 = postgres.query(); + CHECK(vec3.size() == 1); + } +#endif #ifdef ORMPP_ENABLE_SQLITE3 dbng sqlite; if (sqlite.connect(db)) { @@ -1058,7 +1073,17 @@ TEST_CASE("get insert id") { CHECK(id == 3); } #endif - +#ifdef ORMPP_ENABLE_PG + dbng postgres; + if (postgres.connect(ip, username, password, db)) { + postgres.execute("drop table if exists person"); + postgres.create_datatable(ormpp_auto_key{"id"}); + postgres.insert({"purecpp"}); + postgres.insert({"purecpp"}); + int id = postgres.insert({"purecpp"}, true); + CHECK(id == 3); + } +#endif #ifdef ORMPP_ENABLE_SQLITE3 dbng sqlite; if (sqlite.connect(db)) { @@ -1123,6 +1148,7 @@ TEST_CASE("query tuple_optional_t") { #ifdef ORMPP_ENABLE_MYSQL dbng mysql; if (mysql.connect(ip, username, password, db)) { + mysql.execute("drop table if exists tuple_optional_t"); mysql.create_datatable(ormpp_auto_key{"id"}); mysql.insert({"purecpp", 6}); mysql.insert({std::nullopt}); @@ -1152,6 +1178,7 @@ TEST_CASE("query tuple_optional_t") { #ifdef ORMPP_ENABLE_PG dbng postgres; if (postgres.connect(ip, username, password, db)) { + postgres.execute("drop table if exists tuple_optional_t"); postgres.create_datatable(ormpp_auto_key{"id"}); postgres.insert({"purecpp", 6}); postgres.insert({std::nullopt}); @@ -1181,6 +1208,7 @@ TEST_CASE("query tuple_optional_t") { #ifdef ORMPP_ENABLE_SQLITE3 dbng sqlite; if (sqlite.connect(db)) { + sqlite.execute("drop table if exists tuple_optional_t"); sqlite.create_datatable(ormpp_auto_key{"id"}); sqlite.insert({"purecpp", 6}); sqlite.insert({std::nullopt}); From 4ec114dc5470b70e61bc1efd6502decf5727e6a4 Mon Sep 17 00:00:00 2001 From: Jacyking <791026912@qq.com> Date: Thu, 14 Dec 2023 16:47:01 +0800 Subject: [PATCH 2/5] add get insert id after insert --- include/dbng.hpp | 31 +++++++---- include/mysql.hpp | 101 ++++++++++++++++++++-------------- include/postgresql.hpp | 122 ++++++++++++++++++++++++----------------- include/sqlite.hpp | 104 +++++++++++++++++++++-------------- tests/test_ormpp.cpp | 8 +-- 5 files changed, 219 insertions(+), 147 deletions(-) diff --git a/include/dbng.hpp b/include/dbng.hpp index 3f0c5193..fc1be5e5 100644 --- a/include/dbng.hpp +++ b/include/dbng.hpp @@ -34,14 +34,23 @@ class dbng { } template - int insert(const T &t, bool get_insert_id = false, Args &&...args) { - return db_.insert(t, get_insert_id, std::forward(args)...); + int insert(const T &t, Args &&...args) { + return db_.insert(t, std::forward(args)...); } template - int insert(const std::vector &t, bool get_insert_id = false, - Args &&...args) { - return db_.insert(t, get_insert_id, std::forward(args)...); + int insert(const std::vector &v, Args &&...args) { + return db_.insert(v, std::forward(args)...); + } + + template + int replace(const T &t, Args &&...args) { + return db_.replace(t, std::forward(args)...); + } + + template + int replace(const std::vector &v, Args &&...args) { + return db_.replace(v, std::forward(args)...); } template @@ -50,18 +59,18 @@ class dbng { } template - int update(const std::vector &t, Args &&...args) { - return db_.update(t, std::forward(args)...); + int update(const std::vector &v, Args &&...args) { + return db_.update(v, std::forward(args)...); } template - int replace(const T &t, Args &&...args) { - return db_.replace(t, std::forward(args)...); + uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { + return db_.get_insert_id_after_insert(t, std::forward(args)...); } template - int replace(const std::vector &t, Args &&...args) { - return db_.replace(t, std::forward(args)...); + uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { + return db_.get_insert_id_after_insert(v, std::forward(args)...); } template diff --git a/include/mysql.hpp b/include/mysql.hpp index 63d42aa8..19105845 100644 --- a/include/mysql.hpp +++ b/include/mysql.hpp @@ -99,36 +99,49 @@ class mysql { } template - constexpr int insert(const T &t, bool get_insert_id, Args &&...args) { - return insert_impl(OptType::insert, t, get_insert_id, - std::forward(args)...); + int insert(const T &t, Args &&...args) { + return insert_impl(OptType::insert, t, std::forward(args)...); } template - constexpr int insert(const std::vector &t, bool get_insert_id, - Args &&...args) { - return insert_impl(OptType::insert, t, get_insert_id, - std::forward(args)...); + int insert(const std::vector &v, Args &&...args) { + return insert_impl(OptType::insert, v, std::forward(args)...); } template - constexpr int replace(const T &t, Args &&...args) { - return insert_impl(OptType::replace, t, false, std::forward(args)...); + int replace(const T &t, Args &&...args) { + return insert_impl(OptType::replace, t, std::forward(args)...); } template - constexpr int replace(const std::vector &t, Args &&...args) { - return insert_impl(OptType::replace, t, false, std::forward(args)...); + int replace(const std::vector &v, Args &&...args) { + return insert_impl(OptType::replace, v, std::forward(args)...); } template - constexpr int update(const T &t, Args &&...args) { + int update(const T &t, Args &&...args) { return update_impl(t, std::forward(args)...); } template - constexpr int update(const std::vector &t, Args &&...args) { - return update_impl(t, std::forward(args)...); + int update(const std::vector &v, Args &&...args) { + return update_impl(v, std::forward(args)...); + } + + template + uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { + std::optional insert_id = {0}; + insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, + std::move(insert_id)); + return insert_id.value(); + } + + template + uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { + std::optional insert_id = {0}; + insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, + std::move(insert_id)); + return insert_id.value(); } template @@ -669,39 +682,37 @@ class mysql { } template - constexpr int insert_impl(OptType type, const T &t, bool get_insert_id, - Args &&...args) { - std::string sql = generate_insert_sql(type == OptType::insert); - return insert_or_update_impl(t, sql, type, get_insert_id); + int insert_impl(OptType type, const T &t, Args &&...args) { + return insert_or_update_impl( + t, generate_insert_sql(type == OptType::insert), type, std::nullopt); } template - constexpr int insert_impl(OptType type, const std::vector &v, - bool get_insert_id, Args &&...args) { - std::string sql = generate_insert_sql(type == OptType::insert); - return insert_or_update_impl(v, sql, type, get_insert_id); + int insert_impl(OptType type, const std::vector &v, Args &&...args) { + return insert_or_update_impl( + v, generate_insert_sql(type == OptType::insert), type, std::nullopt); } template - constexpr int update_impl(const T &t, Args &&...args) { + int update_impl(const T &t, Args &&...args) { bool condition = true; - std::string sql = - generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, false, condition); + auto sql = generate_update_sql(condition, std::forward(args)...); + return insert_or_update_impl(t, sql, OptType::update, std::nullopt, + condition); } template - constexpr int update_impl(const std::vector &v, Args &&...args) { + int update_impl(const std::vector &v, Args &&...args) { bool condition = true; - std::string sql = - generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, false, condition); + auto sql = generate_update_sql(condition, std::forward(args)...); + return insert_or_update_impl(v, sql, OptType::update, std::nullopt, + condition); } template - constexpr int insert_or_update_impl(const T &t, const std::string &sql, - OptType type, bool get_insert_id = false, - bool condition = true) { + int insert_or_update_impl(const T &t, const std::string &sql, OptType type, + std::optional &&insert_id, + bool condition = true) { #ifdef ORMPP_ENABLE_LOG std::cout << sql << std::endl; #endif @@ -722,14 +733,17 @@ class mysql { return INT_MIN; } - return get_insert_id ? stmt_->mysql->insert_id : 1; + if (insert_id.has_value()) { + insert_id = {stmt_->mysql->insert_id}; + } + + return 1; } template - constexpr int insert_or_update_impl(const std::vector &v, - const std::string &sql, OptType type, - bool get_insert_id = false, - bool condition = true) { + int insert_or_update_impl(const std::vector &v, const std::string &sql, + OptType type, std::optional &&insert_id, + bool condition = true) { #ifdef ORMPP_ENABLE_LOG std::cout << sql << std::endl; #endif @@ -757,8 +771,15 @@ class mysql { } } - return commit() ? get_insert_id ? stmt_->mysql->insert_id : (int)v.size() - : INT_MIN; + if (!commit()) { + return INT_MIN; + } + + if (insert_id.has_value()) { + insert_id = {stmt_->mysql->insert_id}; + } + + return (int)v.size(); } template diff --git a/include/postgresql.hpp b/include/postgresql.hpp index 5f0e7a27..e06c6543 100644 --- a/include/postgresql.hpp +++ b/include/postgresql.hpp @@ -74,40 +74,53 @@ class postgresql { } template - constexpr int insert(const T &t, bool get_insert_id, Args &&...args) { - return insert_impl(OptType::insert, t, get_insert_id, - std::forward(args)...); + int insert(const T &t, Args &&...args) { + return insert_impl(OptType::insert, t, std::forward(args)...); } template - constexpr int insert(const std::vector &v, bool get_insert_id, - Args &&...args) { - return insert_impl(OptType::insert, v, get_insert_id, - std::forward(args)...); + int insert(const std::vector &v, Args &&...args) { + return insert_impl(OptType::insert, v, std::forward(args)...); } template - constexpr int replace(const T &t, Args &&...args) { - return insert_impl(OptType::replace, t, false, std::forward(args)...); + int replace(const T &t, Args &&...args) { + return insert_impl(OptType::replace, t, std::forward(args)...); } template - constexpr int replace(const std::vector &v, Args &&...args) { - return insert_impl(OptType::replace, v, false, std::forward(args)...); + int replace(const std::vector &v, Args &&...args) { + return insert_impl(OptType::replace, v, std::forward(args)...); } template - constexpr int update(const T &t, Args &&...args) { + int update(const T &t, Args &&...args) { return update_impl(t, std::forward(args)...); } template - constexpr int update(const std::vector &v, Args &&...args) { + int update(const std::vector &v, Args &&...args) { return update_impl(v, std::forward(args)...); } template - constexpr std::enable_if_t, std::vector> query( + uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { + std::optional insert_id = {0}; + insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, + std::move(insert_id)); + return insert_id.value(); + } + + template + uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { + std::optional insert_id = {0}; + insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, + std::move(insert_id)); + return insert_id.value(); + } + + template + std::enable_if_t, std::vector> query( Args &&...args) { std::string sql = generate_query_sql(args...); constexpr auto SIZE = iguana::get_value(); @@ -369,7 +382,8 @@ class postgresql { } template - constexpr int stmt_execute(const T &t, OptType type, bool condition) { + int stmt_execute(const T &t, OptType type, bool condition, + std::optional &&insert_id) { std::vector> param_values; iguana::for_each(t, [&t, ¶m_values, type, this](auto item, auto i) { if (type == OptType::insert && @@ -403,7 +417,10 @@ class postgresql { auto status = PQresultStatus(res_); if (status == PGRES_TUPLES_OK) { - return std::atoll(PQgetvalue(res_, 0, 0)); + if (insert_id.has_value()) { + insert_id = {std::strtoull(PQgetvalue(res_, 0, 0), nullptr, 10)}; + } + return 1; } else if (status == PGRES_COMMAND_OK) { return 1; @@ -413,78 +430,83 @@ class postgresql { } template - constexpr int insert_impl(OptType type, const T &t, bool get_insert_id, - Args &&...args) { - std::string sql = generate_insert_sql(type == OptType::insert, - std::forward(args)...); - return insert_or_update_impl(t, sql, type, get_insert_id); + int insert_impl(OptType type, const T &t, Args &&...args) { + return insert_or_update_impl( + t, + generate_insert_sql(type == OptType::insert, + std::forward(args)...), + type, std::nullopt); } template - constexpr int insert_impl(OptType type, const std::vector &v, - bool get_insert_id, Args &&...args) { - std::string sql = generate_insert_sql(type == OptType::insert, - std::forward(args)...); - return insert_or_update_impl(v, sql, type, get_insert_id); + int insert_impl(OptType type, const std::vector &v, Args &&...args) { + return insert_or_update_impl( + v, + generate_insert_sql(type == OptType::insert, + std::forward(args)...), + type, std::nullopt); } template - constexpr int update_impl(const T &t, Args &&...args) { + int update_impl(const T &t, Args &&...args) { bool condition = true; - std::string sql = - generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, false, condition); + auto sql = generate_update_sql(condition, std::forward(args)...); + return insert_or_update_impl(t, sql, OptType::update, std::nullopt, + condition); } template - constexpr int update_impl(const std::vector &v, Args &&...args) { + int update_impl(const std::vector &v, Args &&...args) { bool condition = true; - std::string sql = - generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, false, condition); + auto sql = generate_update_sql(condition, std::forward(args)...); + return insert_or_update_impl(v, sql, OptType::update, std::nullopt, + condition); } template - constexpr int insert_or_update_impl(const T &t, const std::string &sql, - OptType type, bool get_insert_id = false, - bool condition = true) { - if (!prepare(get_insert_id + int insert_or_update_impl(const T &t, const std::string &sql, OptType type, + std::optional &&insert_id, + bool condition = true) { + if (!prepare(insert_id.has_value() ? sql + "returning " + get_auto_key().data() : sql)) { return INT_MIN; } - auto res = stmt_execute(t, type, condition); - if (res == INT_MIN) { + + if (stmt_execute(t, type, condition, std::move(insert_id)) == INT_MIN) { return INT_MIN; } - return get_insert_id ? res : 1; + + return 1; } template - constexpr int insert_or_update_impl(const std::vector &v, - const std::string &sql, OptType type, - bool get_insert_id = false, - bool condition = true) { + int insert_or_update_impl(const std::vector &v, const std::string &sql, + OptType type, std::optional &&insert_id, + bool condition = true) { if (!begin()) { return INT_MIN; } - if (!prepare(get_insert_id + if (!prepare(insert_id.has_value() ? sql + "returning " + get_auto_key().data() : sql)) { return INT_MIN; } - int res = INT_MIN; for (auto &item : v) { - res = stmt_execute(item, type, condition); - if (res == INT_MIN) { + if (stmt_execute(item, type, condition, std::move(insert_id)) == + INT_MIN) { rollback(); return INT_MIN; } } - return commit() ? get_insert_id ? res : (int)v.size() : INT_MIN; + if (!commit()) { + return INT_MIN; + } + + return (int)v.size(); } template diff --git a/include/sqlite.hpp b/include/sqlite.hpp index f4a5c102..e177de3d 100644 --- a/include/sqlite.hpp +++ b/include/sqlite.hpp @@ -72,36 +72,49 @@ class sqlite { } template - constexpr int insert(const T &t, bool get_insert_id, Args &&...args) { - return insert_impl(OptType::insert, t, get_insert_id, - std::forward(args)...); + int insert(const T &t, Args &&...args) { + return insert_impl(OptType::insert, t, std::forward(args)...); } template - constexpr int insert(const std::vector &t, bool get_insert_id, - Args &&...args) { - return insert_impl(OptType::insert, t, get_insert_id, - std::forward(args)...); + int insert(const std::vector &v, Args &&...args) { + return insert_impl(OptType::insert, v, std::forward(args)...); } template - constexpr int replace(const T &t, Args &&...args) { - return insert_impl(OptType::replace, t, false, std::forward(args)...); + int replace(const T &t, Args &&...args) { + return insert_impl(OptType::replace, t, std::forward(args)...); } template - constexpr int replace(const std::vector &t, Args &&...args) { - return insert_impl(OptType::replace, t, false, std::forward(args)...); + int replace(const std::vector &v, Args &&...args) { + return insert_impl(OptType::replace, v, std::forward(args)...); } template - constexpr int update(const T &t, Args &&...args) { + int update(const T &t, Args &&...args) { return update_impl(t, std::forward(args)...); } template - constexpr int update(const std::vector &t, Args &&...args) { - return update_impl(t, std::forward(args)...); + int update(const std::vector &v, Args &&...args) { + return update_impl(v, std::forward(args)...); + } + + template + uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { + std::optional insert_id = {0}; + insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, + std::move(insert_id)); + return insert_id.value(); + } + + template + uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { + std::optional insert_id = {0}; + insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, + std::move(insert_id)); + return insert_id.value(); } template @@ -369,7 +382,7 @@ class sqlite { } template - constexpr int stmt_execute(const T &t, OptType type, bool condition) { + int stmt_execute(const T &t, OptType type, bool condition) { int index = 0; bool bind_ok = true; iguana::for_each(t, [&t, &bind_ok, &index, type, this](auto item, auto i) { @@ -486,39 +499,37 @@ class sqlite { } template - constexpr int insert_impl(OptType type, const T &t, bool get_insert_id, - Args &&...args) { - std::string sql = generate_insert_sql(type == OptType::insert); - return insert_or_update_impl(t, sql, type, get_insert_id); + int insert_impl(OptType type, const T &t, Args &&...args) { + return insert_or_update_impl( + t, generate_insert_sql(type == OptType::insert), type, std::nullopt); } template - constexpr int insert_impl(OptType type, const std::vector &v, - bool get_insert_id, Args &&...args) { - std::string sql = generate_insert_sql(type == OptType::insert); - return insert_or_update_impl(v, sql, type, get_insert_id); + int insert_impl(OptType type, const std::vector &v, Args &&...args) { + return insert_or_update_impl( + v, generate_insert_sql(type == OptType::insert), type, std::nullopt); } template - constexpr int update_impl(const T &t, Args &&...args) { + int update_impl(const T &t, Args &&...args) { bool condition = true; - std::string sql = - generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, false, condition); + auto sql = generate_update_sql(condition, std::forward(args)...); + return insert_or_update_impl(t, sql, OptType::update, std::nullopt, + condition); } template - constexpr int update_impl(const std::vector &v, Args &&...args) { + int update_impl(const std::vector &v, Args &&...args) { bool condition = true; - std::string sql = - generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, false, condition); + auto sql = generate_update_sql(condition, std::forward(args)...); + return insert_or_update_impl(v, sql, OptType::update, std::nullopt, + condition); } template - constexpr int insert_or_update_impl(const T &t, const std::string &sql, - OptType type, bool get_insert_id = false, - bool condition = true) { + int insert_or_update_impl(const T &t, const std::string &sql, OptType type, + std::optional &&insert_id, + bool condition = true) { #ifdef ORMPP_ENABLE_LOG std::cout << sql << std::endl; #endif @@ -534,14 +545,17 @@ class sqlite { return INT_MIN; } - return get_insert_id ? sqlite3_last_insert_rowid(handle_) : 1; + if (insert_id.has_value()) { + insert_id = {sqlite3_last_insert_rowid(handle_)}; + } + + return 1; } template - constexpr int insert_or_update_impl(const std::vector &v, - const std::string &sql, OptType type, - bool get_insert_id = false, - bool condition = true) { + int insert_or_update_impl(const std::vector &v, const std::string &sql, + OptType type, std::optional &&insert_id, + bool condition = true) { #ifdef ORMPP_ENABLE_LOG std::cout << sql << std::endl; #endif @@ -570,9 +584,15 @@ class sqlite { } } - return commit() ? get_insert_id ? sqlite3_last_insert_rowid(handle_) - : (int)v.size() - : INT_MIN; + if (!commit()) { + return INT_MIN; + } + + if (insert_id.has_value()) { + insert_id = {sqlite3_last_insert_rowid(handle_)}; + } + + return (int)v.size(); } private: diff --git a/tests/test_ormpp.cpp b/tests/test_ormpp.cpp index fb954ced..f45fe020 100644 --- a/tests/test_ormpp.cpp +++ b/tests/test_ormpp.cpp @@ -1156,7 +1156,7 @@ TEST_CASE("create table with unique") { #endif } -TEST_CASE("get insert id") { +TEST_CASE("get insert id after insert") { #ifdef ORMPP_ENABLE_MYSQL dbng mysql; if (mysql.connect(ip, username, password, db)) { @@ -1164,7 +1164,7 @@ TEST_CASE("get insert id") { mysql.create_datatable(ormpp_auto_key{"id"}); mysql.insert({"purecpp"}); mysql.insert({"purecpp"}); - int id = mysql.insert({"purecpp"}, true); + auto id = mysql.get_insert_id_after_insert({"purecpp"}); CHECK(id == 3); } #endif @@ -1175,7 +1175,7 @@ TEST_CASE("get insert id") { postgres.create_datatable(ormpp_auto_key{"id"}); postgres.insert({"purecpp"}); postgres.insert({"purecpp"}); - int id = postgres.insert({"purecpp"}, true); + auto id = postgres.get_insert_id_after_insert({"purecpp"}); CHECK(id == 3); } #endif @@ -1186,7 +1186,7 @@ TEST_CASE("get insert id") { sqlite.create_datatable(ormpp_auto_key{"id"}); sqlite.insert({"purecpp"}); sqlite.insert({"purecpp"}); - int id = sqlite.insert({"purecpp"}, true); + auto id = sqlite.get_insert_id_after_insert({"purecpp"}); CHECK(id == 3); } #endif From 5452a1341a80fd36845ffb787ef996879cfcee3f Mon Sep 17 00:00:00 2001 From: Jacyking <791026912@qq.com> Date: Thu, 14 Dec 2023 17:14:17 +0800 Subject: [PATCH 3/5] add get insert id after insert --- include/mysql.hpp | 8 ++++---- include/postgresql.hpp | 8 ++++---- include/sqlite.hpp | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/mysql.hpp b/include/mysql.hpp index 19105845..8ee85fb7 100644 --- a/include/mysql.hpp +++ b/include/mysql.hpp @@ -130,18 +130,18 @@ class mysql { template uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { - std::optional insert_id = {0}; + uint64_t insert_id = {0}; insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, std::move(insert_id)); - return insert_id.value(); + return insert_id; } template uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { - std::optional insert_id = {0}; + uint64_t insert_id = {0}; insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, std::move(insert_id)); - return insert_id.value(); + return insert_id; } template diff --git a/include/postgresql.hpp b/include/postgresql.hpp index e06c6543..181712ef 100644 --- a/include/postgresql.hpp +++ b/include/postgresql.hpp @@ -105,18 +105,18 @@ class postgresql { template uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { - std::optional insert_id = {0}; + uint64_t insert_id = {0}; insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, std::move(insert_id)); - return insert_id.value(); + return insert_id; } template uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { - std::optional insert_id = {0}; + uint64_t insert_id = {0}; insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, std::move(insert_id)); - return insert_id.value(); + return insert_id; } template diff --git a/include/sqlite.hpp b/include/sqlite.hpp index e177de3d..ac6fdb8c 100644 --- a/include/sqlite.hpp +++ b/include/sqlite.hpp @@ -103,18 +103,18 @@ class sqlite { template uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { - std::optional insert_id = {0}; + uint64_t insert_id = {0}; insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, std::move(insert_id)); - return insert_id.value(); + return insert_id; } template uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { - std::optional insert_id = {0}; + uint64_t insert_id = {0}; insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, std::move(insert_id)); - return insert_id.value(); + return insert_id; } template From 332dec010271653c3299df5e6d4e26b182dac272 Mon Sep 17 00:00:00 2001 From: Jacyking <791026912@qq.com> Date: Thu, 14 Dec 2023 19:30:25 +0800 Subject: [PATCH 4/5] add get insert id after insert --- include/mysql.hpp | 76 +++++++++++++++++------------------- include/postgresql.hpp | 88 +++++++++++++++++++++--------------------- include/sqlite.hpp | 74 +++++++++++++++++------------------ tests/test_ormpp.cpp | 7 ++++ 4 files changed, 121 insertions(+), 124 deletions(-) diff --git a/include/mysql.hpp b/include/mysql.hpp index 8ee85fb7..a5a5c956 100644 --- a/include/mysql.hpp +++ b/include/mysql.hpp @@ -130,18 +130,16 @@ class mysql { template uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { - uint64_t insert_id = {0}; - insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, - std::move(insert_id)); - return insert_id; + auto res = insert_or_update_impl(t, generate_insert_sql(true), + OptType::insert, true); + return res.has_value() ? res.value() : 0; } template uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { - uint64_t insert_id = {0}; - insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, - std::move(insert_id)); - return insert_id; + auto res = insert_or_update_impl(v, generate_insert_sql(true), + OptType::insert, true); + return res.has_value() ? res.value() : 0; } template @@ -683,103 +681,101 @@ class mysql { template int insert_impl(OptType type, const T &t, Args &&...args) { - return insert_or_update_impl( - t, generate_insert_sql(type == OptType::insert), type, std::nullopt); + auto res = insert_or_update_impl( + t, generate_insert_sql(type == OptType::insert), type); + return res.has_value() ? res.value() : INT_MIN; } template int insert_impl(OptType type, const std::vector &v, Args &&...args) { - return insert_or_update_impl( - v, generate_insert_sql(type == OptType::insert), type, std::nullopt); + auto res = insert_or_update_impl( + v, generate_insert_sql(type == OptType::insert), type); + return res.has_value() ? res.value() : INT_MIN; } template int update_impl(const T &t, Args &&...args) { bool condition = true; auto sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, std::nullopt, - condition); + auto res = insert_or_update_impl(t, sql, OptType::update, false, condition); + return res.has_value() ? res.value() : INT_MIN; } template int update_impl(const std::vector &v, Args &&...args) { bool condition = true; auto sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, std::nullopt, - condition); + auto res = insert_or_update_impl(v, sql, OptType::update, false, condition); + return res.has_value() ? res.value() : INT_MIN; } template - int insert_or_update_impl(const T &t, const std::string &sql, OptType type, - std::optional &&insert_id, - bool condition = true) { + std::optional 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 stmt_ = mysql_stmt_init(con_); if (!stmt_) { set_last_error(mysql_error(con_)); - return INT_MIN; + return std::nullopt; } if (mysql_stmt_prepare(stmt_, sql.c_str(), (int)sql.size())) { set_last_error(mysql_stmt_error(stmt_)); - return INT_MIN; + return std::nullopt; } auto guard = guard_statment(stmt_); if (stmt_execute(t, type, condition) == INT_MIN) { - return INT_MIN; + return std::nullopt; } - if (insert_id.has_value()) { - insert_id = {stmt_->mysql->insert_id}; - } - - return 1; + return get_insert_id ? stmt_->mysql->insert_id : 1; } template - int insert_or_update_impl(const std::vector &v, const std::string &sql, - OptType type, std::optional &&insert_id, - bool condition = true) { + std::optional insert_or_update_impl(const std::vector &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 stmt_ = mysql_stmt_init(con_); if (!stmt_) { set_last_error(mysql_error(con_)); - return INT_MIN; + return std::nullopt; } if (mysql_stmt_prepare(stmt_, sql.c_str(), (int)sql.size())) { set_last_error(mysql_stmt_error(stmt_)); - return INT_MIN; + return std::nullopt; } auto guard = guard_statment(stmt_); if (!begin()) { - return INT_MIN; + return std::nullopt; } for (auto &item : v) { if (stmt_execute(item, type, condition) == INT_MIN) { rollback(); - return INT_MIN; + return std::nullopt; } } if (!commit()) { - return INT_MIN; - } - - if (insert_id.has_value()) { - insert_id = {stmt_->mysql->insert_id}; + return std::nullopt; } - return (int)v.size(); + return get_insert_id ? stmt_->mysql->insert_id : (int)v.size(); } template diff --git a/include/postgresql.hpp b/include/postgresql.hpp index 181712ef..a98be4b6 100644 --- a/include/postgresql.hpp +++ b/include/postgresql.hpp @@ -105,18 +105,16 @@ class postgresql { template uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { - uint64_t insert_id = {0}; - insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, - std::move(insert_id)); - return insert_id; + auto res = insert_or_update_impl(t, generate_insert_sql(true), + OptType::insert, true); + return res.has_value() ? res.value() : 0; } template uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { - uint64_t insert_id = {0}; - insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, - std::move(insert_id)); - return insert_id; + auto res = insert_or_update_impl(v, generate_insert_sql(true), + OptType::insert, true); + return res.has_value() ? res.value() : 0; } template @@ -382,8 +380,8 @@ class postgresql { } template - int stmt_execute(const T &t, OptType type, bool condition, - std::optional &&insert_id) { + std::optional stmt_execute(const T &t, OptType type, + bool condition) { std::vector> param_values; iguana::for_each(t, [&t, ¶m_values, type, this](auto item, auto i) { if (type == OptType::insert && @@ -402,7 +400,7 @@ class postgresql { } if (param_values.empty()) { - return INT_MIN; + return std::nullopt; } std::vector param_values_buf; @@ -417,96 +415,96 @@ class postgresql { auto status = PQresultStatus(res_); if (status == PGRES_TUPLES_OK) { - if (insert_id.has_value()) { - insert_id = {std::strtoull(PQgetvalue(res_, 0, 0), nullptr, 10)}; - } - return 1; + return std::strtoull(PQgetvalue(res_, 0, 0), nullptr, 10); } else if (status == PGRES_COMMAND_OK) { return 1; } - return INT_MIN; + return std::nullopt; } template int insert_impl(OptType type, const T &t, Args &&...args) { - return insert_or_update_impl( + auto res = insert_or_update_impl( t, generate_insert_sql(type == OptType::insert, std::forward(args)...), - type, std::nullopt); + type); + return res.has_value() ? res.value() : INT_MIN; } template int insert_impl(OptType type, const std::vector &v, Args &&...args) { - return insert_or_update_impl( + auto res = insert_or_update_impl( v, generate_insert_sql(type == OptType::insert, std::forward(args)...), - type, std::nullopt); + type); + return res.has_value() ? res.value() : INT_MIN; } template int update_impl(const T &t, Args &&...args) { bool condition = true; auto sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, std::nullopt, - condition); + auto res = insert_or_update_impl(t, sql, OptType::update, false, condition); + return res.has_value() ? res.value() : INT_MIN; } template int update_impl(const std::vector &v, Args &&...args) { bool condition = true; auto sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, std::nullopt, - condition); + auto res = insert_or_update_impl(v, sql, OptType::update, false, condition); + return res.has_value() ? res.value() : INT_MIN; } template - int insert_or_update_impl(const T &t, const std::string &sql, OptType type, - std::optional &&insert_id, - bool condition = true) { - if (!prepare(insert_id.has_value() + std::optional insert_or_update_impl(const T &t, + const std::string &sql, + OptType type, + bool get_insert_id = false, + bool condition = true) { + if (!prepare(get_insert_id ? sql + "returning " + get_auto_key().data() : sql)) { - return INT_MIN; - } - - if (stmt_execute(t, type, condition, std::move(insert_id)) == INT_MIN) { - return INT_MIN; + return std::nullopt; } - return 1; + return stmt_execute(t, type, condition); } template - int insert_or_update_impl(const std::vector &v, const std::string &sql, - OptType type, std::optional &&insert_id, - bool condition = true) { + std::optional insert_or_update_impl(const std::vector &v, + const std::string &sql, + OptType type, + bool get_insert_id = false, + bool condition = true) { if (!begin()) { - return INT_MIN; + return std::nullopt; } - if (!prepare(insert_id.has_value() + if (!prepare(get_insert_id ? sql + "returning " + get_auto_key().data() : sql)) { - return INT_MIN; + return std::nullopt; } + std::optional res = {0}; for (auto &item : v) { - if (stmt_execute(item, type, condition, std::move(insert_id)) == - INT_MIN) { + res = stmt_execute(item, type, condition); + if (!res.has_value()) { rollback(); - return INT_MIN; + return std::nullopt; } } if (!commit()) { - return INT_MIN; + return std::nullopt; } - return (int)v.size(); + return get_insert_id ? res : (int)v.size(); } template diff --git a/include/sqlite.hpp b/include/sqlite.hpp index ac6fdb8c..b08492d2 100644 --- a/include/sqlite.hpp +++ b/include/sqlite.hpp @@ -103,18 +103,16 @@ class sqlite { template uint64_t get_insert_id_after_insert(const T &t, Args &&...args) { - uint64_t insert_id = {0}; - insert_or_update_impl(t, generate_insert_sql(true), OptType::insert, - std::move(insert_id)); - return insert_id; + auto res = insert_or_update_impl(t, generate_insert_sql(true), + OptType::insert, true); + return res.has_value() ? res.value() : 0; } template uint64_t get_insert_id_after_insert(const std::vector &v, Args &&...args) { - uint64_t insert_id = {0}; - insert_or_update_impl(v, generate_insert_sql(true), OptType::insert, - std::move(insert_id)); - return insert_id; + auto res = insert_or_update_impl(v, generate_insert_sql(true), + OptType::insert, true); + return res.has_value() ? res.value() : 0; } template @@ -500,99 +498,97 @@ class sqlite { template int insert_impl(OptType type, const T &t, Args &&...args) { - return insert_or_update_impl( - t, generate_insert_sql(type == OptType::insert), type, std::nullopt); + auto res = insert_or_update_impl( + t, generate_insert_sql(type == OptType::insert), type); + return res.has_value() ? res.value() : INT_MIN; } template int insert_impl(OptType type, const std::vector &v, Args &&...args) { - return insert_or_update_impl( - v, generate_insert_sql(type == OptType::insert), type, std::nullopt); + auto res = insert_or_update_impl( + v, generate_insert_sql(type == OptType::insert), type); + return res.has_value() ? res.value() : INT_MIN; } template int update_impl(const T &t, Args &&...args) { bool condition = true; auto sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(t, sql, OptType::update, std::nullopt, - condition); + auto res = insert_or_update_impl(t, sql, OptType::update, false, condition); + return res.has_value() ? res.value() : INT_MIN; } template int update_impl(const std::vector &v, Args &&...args) { bool condition = true; auto sql = generate_update_sql(condition, std::forward(args)...); - return insert_or_update_impl(v, sql, OptType::update, std::nullopt, - condition); + auto res = insert_or_update_impl(v, sql, OptType::update, false, condition); + return res.has_value() ? res.value() : INT_MIN; } template - int insert_or_update_impl(const T &t, const std::string &sql, OptType type, - std::optional &&insert_id, - bool condition = true) { + std::optional 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 if (sqlite3_prepare_v2(handle_, sql.data(), (int)sql.size(), &stmt_, nullptr) != SQLITE_OK) { set_last_error(sqlite3_errmsg(handle_)); - return INT_MIN; + return std::nullopt; } auto guard = guard_statment(stmt_); if (stmt_execute(t, type, condition) == INT_MIN) { - return INT_MIN; + return std::nullopt; } - if (insert_id.has_value()) { - insert_id = {sqlite3_last_insert_rowid(handle_)}; - } - - return 1; + return get_insert_id ? sqlite3_last_insert_rowid(handle_) : 1; } template - int insert_or_update_impl(const std::vector &v, const std::string &sql, - OptType type, std::optional &&insert_id, - bool condition = true) { + std::optional insert_or_update_impl(const std::vector &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 if (sqlite3_prepare_v2(handle_, sql.data(), (int)sql.size(), &stmt_, nullptr) != SQLITE_OK) { set_last_error(sqlite3_errmsg(handle_)); - return INT_MIN; + return std::nullopt; } auto guard = guard_statment(stmt_); if (!begin()) { - return INT_MIN; + return std::nullopt; } for (auto &item : v) { if (stmt_execute(item, type, condition) == INT_MIN) { rollback(); - return INT_MIN; + return std::nullopt; } if (sqlite3_reset(stmt_) != SQLITE_OK) { rollback(); set_last_error(sqlite3_errmsg(handle_)); - return INT_MIN; + return std::nullopt; } } if (!commit()) { - return INT_MIN; - } - - if (insert_id.has_value()) { - insert_id = {sqlite3_last_insert_rowid(handle_)}; + return std::nullopt; } - return (int)v.size(); + return get_insert_id ? sqlite3_last_insert_rowid(handle_) : (int)v.size(); } private: diff --git a/tests/test_ormpp.cpp b/tests/test_ormpp.cpp index f45fe020..15a67e21 100644 --- a/tests/test_ormpp.cpp +++ b/tests/test_ormpp.cpp @@ -1166,6 +1166,8 @@ TEST_CASE("get insert id after insert") { mysql.insert({"purecpp"}); auto id = mysql.get_insert_id_after_insert({"purecpp"}); CHECK(id == 3); + id = mysql.get_insert_id_after_insert({{"purecpp"}, {"purecpp"}}); + CHECK(id == 5); } #endif #ifdef ORMPP_ENABLE_PG @@ -1177,6 +1179,9 @@ TEST_CASE("get insert id after insert") { postgres.insert({"purecpp"}); auto id = postgres.get_insert_id_after_insert({"purecpp"}); CHECK(id == 3); + id = + postgres.get_insert_id_after_insert({{"purecpp"}, {"purecpp"}}); + CHECK(id == 5); } #endif #ifdef ORMPP_ENABLE_SQLITE3 @@ -1188,6 +1193,8 @@ TEST_CASE("get insert id after insert") { sqlite.insert({"purecpp"}); auto id = sqlite.get_insert_id_after_insert({"purecpp"}); CHECK(id == 3); + id = sqlite.get_insert_id_after_insert({{"purecpp"}, {"purecpp"}}); + CHECK(id == 5); } #endif } From ec30788072dfb50a49f73ab4b87735436e08f23b Mon Sep 17 00:00:00 2001 From: Jacyking <791026912@qq.com> Date: Thu, 14 Dec 2023 19:47:45 +0800 Subject: [PATCH 5/5] add get insert id after insert --- include/mysql.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql.hpp b/include/mysql.hpp index a5a5c956..5824159c 100644 --- a/include/mysql.hpp +++ b/include/mysql.hpp @@ -760,7 +760,7 @@ class mysql { auto guard = guard_statment(stmt_); - if (!begin()) { + if (!get_insert_id && !begin()) { return std::nullopt; } @@ -771,7 +771,7 @@ class mysql { } } - if (!commit()) { + if (!get_insert_id && !commit()) { return std::nullopt; }