diff --git a/ormpp/dbng.hpp b/ormpp/dbng.hpp index eaa7d41b..aae2859c 100644 --- a/ormpp/dbng.hpp +++ b/ormpp/dbng.hpp @@ -74,7 +74,17 @@ class dbng { } template - bool delete_records(Args &&...where_condition) { + bool delete_records_s(const std::string &str = "", Args &&...args) { + return db_.template delete_records_s(str, std::forward(args)...); + } + + template + std::vector query_s(const std::string &str = "", Args &&...args) { + return db_.template query_s(str, std::forward(args)...); + } + + template + [[deprecated]] bool delete_records(Args &&...where_condition) { return db_.template delete_records( std::forward(where_condition)...); } @@ -82,20 +92,21 @@ class dbng { // restriction, all the args are string, the first is the where condition, // rest are append conditions template - std::vector query(Args &&...args) { + [[deprecated]] std::vector query(Args &&...args) { return db_.template query(std::forward(args)...); } // support member variable, such as: query(FID(simple::id), "<", 5) template - auto query(Pair pair, std::string_view oper, U &&val) { + [[deprecated]] auto query(Pair pair, std::string_view oper, U &&val) { auto sql = build_condition(pair, oper, std::forward(val)); using T = typename ormpp::field_attribute::type; return query(sql); } template - bool delete_records(Pair pair, std::string_view oper, U &&val) { + [[deprecated]] bool delete_records(Pair pair, std::string_view oper, + U &&val) { auto sql = build_condition(pair, oper, std::forward(val)); using T = typename ormpp::field_attribute::type; return delete_records(sql); diff --git a/ormpp/mysql.hpp b/ormpp/mysql.hpp index e934be00..2e9a61e7 100644 --- a/ormpp/mysql.hpp +++ b/ormpp/mysql.hpp @@ -142,12 +142,6 @@ class mysql { return res.has_value() ? res.value() : 0; } - template - bool delete_records(Args &&...where_conditon) { - auto sql = generate_delete_sql(std::forward(where_conditon)...); - return execute(sql); - } - int get_last_affect_rows() { return (int)mysql_affected_rows(con_); } template @@ -278,27 +272,141 @@ class mysql { } } - // for tuple and string with args... - template - std::enable_if_t, std::vector> query( - const Arg &s, Args &&...args) { - static_assert(iguana::is_tuple::value); - constexpr auto SIZE = std::tuple_size_v; + template + bool delete_records(Args &&...where_conditon) { + auto sql = generate_delete_sql(std::forward(where_conditon)...); + return execute(sql); + } - std::string sql = s; + template + bool delete_records_s(const std::string &str, Args &&...args) { + auto sql = generate_delete_sql(str); #ifdef ORMPP_ENABLE_LOG std::cout << sql << std::endl; #endif - constexpr auto Args_Size = sizeof...(Args); - if constexpr (Args_Size != 0) { - if (Args_Size != std::count(sql.begin(), sql.end(), '?')) { - set_last_error("arg size error"); + stmt_ = mysql_stmt_init(con_); + if (!stmt_) { + set_last_error(mysql_error(con_)); + return false; + } + + auto guard = guard_statment(stmt_); + if (mysql_stmt_prepare(stmt_, sql.c_str(), (unsigned long)sql.size())) { + set_last_error(mysql_stmt_error(stmt_)); + return false; + } + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + std::vector param_binds; + (set_param_bind(param_binds, args), ...); + if (mysql_stmt_bind_param(stmt_, ¶m_binds[0])) { + set_last_error(mysql_stmt_error(stmt_)); + return false; + } + } + + if (mysql_stmt_execute(stmt_)) { + set_last_error(mysql_stmt_error(stmt_)); + return false; + } + return true; + } + + template + std::enable_if_t, std::vector> query_s( + const std::string &str, Args &&...args) { + std::string sql = generate_query_sql(str); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + constexpr auto SIZE = iguana::get_value(); + + stmt_ = mysql_stmt_init(con_); + if (!stmt_) { + set_last_error(mysql_error(con_)); + return {}; + } + + auto guard = guard_statment(stmt_); + + if (mysql_stmt_prepare(stmt_, sql.c_str(), (unsigned long)sql.size())) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; + } + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + std::vector param_binds; + (set_param_bind(param_binds, args), ...); + if (mysql_stmt_bind_param(stmt_, ¶m_binds[0])) { + set_last_error(mysql_stmt_error(stmt_)); return {}; } + } - sql = get_sql(sql, std::forward(args)...); + std::array().is_null), SIZE> nulls = {}; + std::array param_binds = {}; + std::map> mp; + + std::vector v; + T t{}; + + int index = 0; + iguana::for_each(t, [¶m_binds, &index, &nulls, &mp, &t, this]( + auto item, auto /*i*/) { + set_param_bind(param_binds[index], t.*item, index, mp, nulls[index]); + index++; + }); + + if (index == 0) { + return {}; + } + + if (mysql_stmt_bind_result(stmt_, ¶m_binds[0])) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; + } + + if (mysql_stmt_execute(stmt_)) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; } + while (mysql_stmt_fetch(stmt_) == 0) { + iguana::for_each(t, [¶m_binds, &mp, &t, this](auto item, auto i) { + constexpr auto Idx = decltype(i)::value; + set_value(param_binds.at(Idx), t.*item, Idx, mp); + }); + + for (auto &p : mp) { + p.second.assign(p.second.size(), 0); + } + + iguana::for_each(t, [nulls, &t](auto item, auto i) { + constexpr auto Idx = decltype(i)::value; + if (nulls.at(Idx)) { + using U = std::remove_reference_t().*item)>; + if constexpr (is_optional_v::value || std::is_arithmetic_v) { + t.*item = {}; + } + } + }); + + v.push_back(std::move(t)); + } + + return v; + } + + template + std::enable_if_t, std::vector> query_s( + const std::string &sql, Args &&...args) { + static_assert(iguana::is_tuple::value); + constexpr auto SIZE = std::tuple_size_v; +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif stmt_ = mysql_stmt_init(con_); if (!stmt_) { set_last_error(mysql_error(con_)); @@ -312,6 +420,16 @@ class mysql { return {}; } + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + std::vector param_binds; + (set_param_bind(param_binds, args), ...); + if (mysql_stmt_bind_param(stmt_, ¶m_binds[0])) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; + } + } + std::array().is_null), result_size::value> nulls = {}; @@ -339,7 +457,7 @@ class mysql { index++; } }, - std::make_index_sequence{}); + std::make_index_sequence>{}); if (index == 0) { return {}; @@ -490,6 +608,141 @@ class mysql { return v; } + // for tuple and string with args... + template + std::enable_if_t, std::vector> query( + const Arg &s, Args &&...args) { + static_assert(iguana::is_tuple::value); + 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 constexpr (Args_Size != 0) { + if (Args_Size != std::count(sql.begin(), sql.end(), '?')) { + set_last_error("arg size error"); + return {}; + } + + sql = get_sql(sql, std::forward(args)...); + } + + stmt_ = mysql_stmt_init(con_); + if (!stmt_) { + set_last_error(mysql_error(con_)); + return {}; + } + + auto guard = guard_statment(stmt_); + + if (mysql_stmt_prepare(stmt_, sql.c_str(), (int)sql.size())) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; + } + + std::array().is_null), + result_size::value> + nulls = {}; + std::array::value> param_binds = {}; + std::map> mp; + + std::vector v; + T tp{}; + + int index = 0; + iguana::for_each( + tp, + [¶m_binds, &index, &nulls, &mp, &tp, this](auto &t, auto /*i*/) { + using U = std::remove_reference_t; + if constexpr (iguana::is_reflection_v) { + iguana::for_each(t, [¶m_binds, &index, &nulls, &mp, &t, this]( + auto &item, auto /*i*/) { + set_param_bind(param_binds[index], t.*item, index, mp, + nulls[index]); + index++; + }); + } + else { + set_param_bind(param_binds[index], t, index, mp, nulls[index]); + index++; + } + }, + std::make_index_sequence{}); + + if (index == 0) { + return {}; + } + + if (mysql_stmt_bind_result(stmt_, ¶m_binds[0])) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; + } + + if (mysql_stmt_execute(stmt_)) { + set_last_error(mysql_stmt_error(stmt_)); + return {}; + } + + while (mysql_stmt_fetch(stmt_) == 0) { + index = 0; + iguana::for_each( + tp, + [¶m_binds, &index, &mp, &tp, this](auto &t, auto /*i*/) { + using U = std::remove_reference_t; + if constexpr (iguana::is_reflection_v) { + iguana::for_each(t, [¶m_binds, &index, &mp, &t, this]( + auto ele, auto /*i*/) { + set_value(param_binds.at(index), t.*ele, index, mp); + index++; + }); + } + else { + set_value(param_binds.at(index), t, index, mp); + index++; + } + }, + std::make_index_sequence{}); + + for (auto &p : mp) { + p.second.assign(p.second.size(), 0); + } + + index = 0; + iguana::for_each( + tp, + [&index, nulls, &tp](auto &t, auto /*i*/) { + using U = std::remove_reference_t; + if constexpr (iguana::is_reflection_v) { + iguana::for_each(t, [&index, nulls, &t](auto ele, auto /*i*/) { + if (nulls.at(index++)) { + using W = + std::remove_reference_t().*ele)>; + if constexpr (is_optional_v::value || + std::is_arithmetic_v) { + t.*ele = {}; + } + } + }); + } + else { + if (nulls.at(index++)) { + if constexpr (is_optional_v::value || + std::is_arithmetic_v) { + t = {}; + } + } + } + }, + std::make_index_sequence{}); + + v.push_back(std::move(tp)); + } + + return v; + } + int get_blob_len(int column) { reset_error(); unsigned long data_len = 0; @@ -513,17 +766,18 @@ class mysql { #ifdef ORMPP_ENABLE_LOG std::cout << sql << std::endl; #endif - reset_error(); stmt_ = mysql_stmt_init(con_); if (!stmt_) { set_last_error(mysql_error(con_)); return false; } + auto guard = guard_statment(stmt_); if (mysql_stmt_prepare(stmt_, sql.c_str(), (unsigned long)sql.size())) { set_last_error(mysql_stmt_error(stmt_)); return false; } + if (mysql_stmt_execute(stmt_)) { set_last_error(mysql_stmt_error(stmt_)); return false; diff --git a/ormpp/postgresql.hpp b/ormpp/postgresql.hpp index e5514d8b..41fd69cf 100644 --- a/ormpp/postgresql.hpp +++ b/ormpp/postgresql.hpp @@ -118,12 +118,153 @@ class postgresql { return res.has_value() ? res.value() : 0; } + template + constexpr bool delete_records(Args &&...where_conditon) { + auto sql = generate_delete_sql(std::forward(where_conditon)...); + return execute(sql); + } + + template + bool delete_records_s(const std::string &str, Args &&...args) { + auto sql = generate_delete_sql(str); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + if (!prepare(sql)) + return false; + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + std::vector param_values_buf; + std::vector> param_values; + (set_param_values(param_values, args), ...); + for (auto &item : param_values) { + param_values_buf.push_back(item.data()); + } + res_ = PQexecPrepared(con_, "", (int)param_values.size(), + param_values_buf.data(), NULL, NULL, 0); + } + else { + res_ = PQexec(con_, sql.data()); + } + + auto guard = guard_statment(res_); + if (PQresultStatus(res_) != PGRES_COMMAND_OK) { + return false; + } + return true; + } + + template + std::enable_if_t, std::vector> query_s( + const std::string &str, Args &&...args) { + std::string sql = generate_query_sql(str); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + if (!prepare(sql)) + return {}; + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + std::vector param_values_buf; + std::vector> param_values; + (set_param_values(param_values, args), ...); + for (auto &item : param_values) { + param_values_buf.push_back(item.data()); + } + res_ = PQexecPrepared(con_, "", (int)param_values.size(), + param_values_buf.data(), NULL, NULL, 0); + } + else { + res_ = PQexec(con_, sql.data()); + } + + auto guard = guard_statment(res_); + if (PQresultStatus(res_) != PGRES_TUPLES_OK) { + return {}; + } + + std::vector v; + auto ntuples = PQntuples(res_); + + for (auto i = 0; i < ntuples; i++) { + T t = {}; + iguana::for_each(t, [this, i, &t](auto item, auto I) { + assign(t.*item, i, (int)decltype(I)::value); + }); + v.push_back(std::move(t)); + } + + return v; + } + + template + constexpr std::enable_if_t, std::vector> + query_s(const std::string &sql, Args &&...args) { + static_assert(iguana::is_tuple::value); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + if (!prepare(sql)) + return {}; + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + std::vector param_values_buf; + std::vector> param_values; + (set_param_values(param_values, args), ...); + for (auto &item : param_values) { + param_values_buf.push_back(item.data()); + } + res_ = PQexecPrepared(con_, "", (int)param_values.size(), + param_values_buf.data(), NULL, NULL, 0); + } + else { + res_ = PQexec(con_, sql.data()); + } + + auto guard = guard_statment(res_); + if (PQresultStatus(res_) != PGRES_TUPLES_OK) { + return {}; + } + + std::vector v; + auto ntuples = PQntuples(res_); + + for (auto i = 0; i < ntuples; i++) { + T tp = {}; + int index = 0; + iguana::for_each( + tp, + [this, i, &index](auto &item, auto I) { + if constexpr (iguana::is_reflection_v) { + std::remove_reference_t t = {}; + iguana::for_each(t, [this, &index, &t, i](auto ele, auto /*i*/) { + assign(t.*ele, (int)i, index++); + }); + item = std::move(t); + } + else { + assign(item, (int)i, index++); + } + }, + std::make_index_sequence>{}); + + if (index > 0) + v.push_back(std::move(tp)); + } + + return v; + } + template std::enable_if_t, std::vector> query( Args &&...args) { std::string sql = generate_query_sql(args...); - constexpr auto SIZE = iguana::get_value(); - +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif if (!prepare(sql)) return {}; @@ -200,12 +341,6 @@ class postgresql { return v; } - template - constexpr bool delete_records(Args &&...where_conditon) { - auto sql = generate_delete_sql(std::forward(where_conditon)...); - return execute(sql); - } - // just support execute string sql without placeholders auto execute(const std::string &sql) { #ifdef ORMPP_ENABLE_LOG diff --git a/ormpp/sqlite.hpp b/ormpp/sqlite.hpp index c741b9ba..a2083e7d 100644 --- a/ormpp/sqlite.hpp +++ b/ormpp/sqlite.hpp @@ -123,6 +123,128 @@ class sqlite { return execute(sql); } + template + bool delete_records_s(const std::string &str, Args &&...args) { + auto sql = generate_delete_sql(str); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + int result = sqlite3_prepare_v2(handle_, sql.data(), (int)sql.size(), + &stmt_, nullptr); + if (result != SQLITE_OK) { + set_last_error(sqlite3_errmsg(handle_)); + return false; + } + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + (set_param_bind(args, ++index), ...); + } + + auto guard = guard_statment(stmt_); + if (sqlite3_step(stmt_) != SQLITE_DONE) { + set_last_error(sqlite3_errmsg(handle_)); + return false; + } + return true; + } + + template + std::enable_if_t, std::vector> query_s( + const std::string &str, Args &&...args) { + std::string sql = generate_query_sql(str); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + int result = sqlite3_prepare_v2(handle_, sql.data(), (int)sql.size(), + &stmt_, nullptr); + if (result != SQLITE_OK) { + set_last_error(sqlite3_errmsg(handle_)); + return {}; + } + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + (set_param_bind(args, ++index), ...); + } + + auto guard = guard_statment(stmt_); + + std::vector v; + while (true) { + result = sqlite3_step(stmt_); + if (result == SQLITE_DONE) + break; + + if (result != SQLITE_ROW) + break; + + T t = {}; + iguana::for_each(t, [this, &t](auto item, auto I) { + assign(t.*item, (int)decltype(I)::value); + }); + + v.push_back(std::move(t)); + } + + return v; + } + + template + std::enable_if_t, std::vector> query_s( + const std::string &sql, Args &&...args) { + static_assert(iguana::is_tuple::value); +#ifdef ORMPP_ENABLE_LOG + std::cout << sql << std::endl; +#endif + int result = sqlite3_prepare_v2(handle_, sql.data(), (int)sql.size(), + &stmt_, nullptr); + if (result != SQLITE_OK) { + set_last_error(sqlite3_errmsg(handle_)); + return {}; + } + + if constexpr (sizeof...(Args) > 0) { + size_t index = 0; + (set_param_bind(args, ++index), ...); + } + + auto guard = guard_statment(stmt_); + + std::vector v; + while (true) { + result = sqlite3_step(stmt_); + if (result == SQLITE_DONE) + break; + + if (result != SQLITE_ROW) + break; + + T tp = {}; + int index = 0; + iguana::for_each( + tp, + [this, &index](auto &item, auto /*I*/) { + if constexpr (iguana::is_reflection_v) { + std::remove_reference_t t = {}; + iguana::for_each(t, [this, &index, &t](auto ele, auto /*i*/) { + assign(t.*ele, index++); + }); + item = std::move(t); + } + else { + assign(item, index++); + } + }, + std::make_index_sequence>{}); + + if (index > 0) + v.push_back(std::move(tp)); + } + + return v; + } + // restriction, all the args are string, the first is the where condition, // rest are append conditions template @@ -432,13 +554,24 @@ class sqlite { return SQLITE_OK == sqlite3_bind_double(stmt_, i, value); } else if constexpr (std::is_same_v) { - return SQLITE_OK == sqlite3_bind_text(stmt_, i, value.data(), - (int)value.size(), nullptr); + return SQLITE_OK == + sqlite3_bind_text(stmt_, i, value.data(), value.size(), nullptr); + } + else if constexpr (std::is_same_v>>) { + return SQLITE_OK == + sqlite3_bind_text(stmt_, i, value, strlen(value), nullptr); } else if constexpr (is_char_array_v) { return SQLITE_OK == sqlite3_bind_text(stmt_, i, value, sizeof(U), nullptr); } +#ifdef ORMPP_WITH_CSTRING + else if constexpr (std::is_same_v) { + return SQLITE_OK == sqlite3_bind_text(stmt_, i, value.GetString(), + (int)value.GetLength(), nullptr); + } +#endif else { static_assert(!sizeof(U), "this type has not supported yet"); } @@ -446,11 +579,11 @@ class sqlite { template void assign(T &&value, int i) { + using U = std::remove_const_t>; if (sqlite3_column_type(stmt_, i) == SQLITE_NULL) { - value = {}; + value = U{}; return; } - using U = std::remove_const_t>; if constexpr (is_optional_v::value) { using value_type = typename U::value_type; value_type item; @@ -482,6 +615,11 @@ class sqlite { else if constexpr (is_char_array_v) { memcpy(value, sqlite3_column_text(stmt_, i), sizeof(U)); } +#ifdef ORMPP_WITH_CSTRING + else if constexpr (std::is_same_v) { + value.SetString((const char *)sqlite3_column_text(stmt_, i)); + } +#endif else { static_assert(!sizeof(U), "this type has not supported yet"); } diff --git a/ormpp/utility.hpp b/ormpp/utility.hpp index 1455b805..e04c80d7 100644 --- a/ormpp/utility.hpp +++ b/ormpp/utility.hpp @@ -162,6 +162,11 @@ inline constexpr auto get_type_names(DBType type) { else if constexpr (is_optional_v::value) { s = ormpp_sqlite::type_to_name(identity{}); } +#ifdef ORMPP_WITH_CSTRING + else if constexpr (std::is_same_v) { + s = "TEXT"sv; + } +#endif else { s = ormpp_sqlite::type_to_name(identity{}); } @@ -402,8 +407,8 @@ inline std::string generate_delete_sql(Args &&...where_conditon) { auto name = get_name(); append(sql, name.data()); if constexpr (sizeof...(Args) > 0) { - if (!is_empty(std::forward(where_conditon)...)) // fix for vs2017 - append(sql, " where ", std::forward(where_conditon)...); + if (!is_empty(std::forward(where_conditon)...)) + append(sql, "where", std::forward(where_conditon)...); } return sql; } @@ -441,18 +446,18 @@ inline void get_sql_conditions(std::string &sql, const std::string &arg, template inline std::string generate_query_sql(Args &&...args) { - constexpr size_t param_size = sizeof...(Args); - static_assert(param_size == 0 || param_size > 0); - std::string sql = "select "; + bool where = false; auto name = get_name(); + std::string sql = "select "; auto fields = get_fields(); append(sql, fields.data(), "from", name.data()); - - std::string where_sql = ""; - if constexpr (param_size > 0) { - where_sql = " where 1=1 and "; + if constexpr (sizeof...(Args) > 0) { + using expander = int[]; + expander{0, (where = where ? where : !is_empty(args), 0)...}; + } + if (where) { + append(sql, "where 1=1 and "); } - sql.append(where_sql); get_sql_conditions(sql, std::forward(args)...); return sql; } diff --git a/tests/test_ormpp.cpp b/tests/test_ormpp.cpp index a365b008..4132ccec 100644 --- a/tests/test_ormpp.cpp +++ b/tests/test_ormpp.cpp @@ -1199,30 +1199,94 @@ TEST_CASE("get insert id after insert") { #endif } -TEST_CASE("delete records") { +TEST_CASE("query_s delete_records_s") { #ifdef ORMPP_ENABLE_MYSQL dbng mysql; if (mysql.connect(ip, username, password, db)) { mysql.execute("drop table if exists person"); mysql.create_datatable(ormpp_auto_key{"id"}); mysql.insert({"other"}); - mysql.insert({"purecpp"}); - mysql.delete_records("name = 'other';drop table person"); - auto vec = mysql.query(); - CHECK(vec.size() == 2); + mysql.insert({"purecpp", 200}); + auto v_tp1 = mysql.query_s>( + "select * from person where name=?", "purecpp"); + auto v_tp2 = mysql.query_s>( + "select * from person where name=?", "purecpp' or '1=1"); + auto v_tp3 = mysql.query_s>("select * from person"); + auto vec1 = mysql.query_s(); + auto vec2 = mysql.query_s("name=?", "purecpp"); + auto vec3 = mysql.query_s("select * from person"); + auto vec4 = mysql.query_s("name=?", std::string("purecpp")); + auto vec5 = mysql.query_s("name=? and age=?", "purecpp", 200); + auto vec6 = + mysql.query_s("select * from person where name=?", "purecpp"); + auto vec7 = mysql.query_s("name=?", "purecpp' or '1=1"); + mysql.delete_records_s("name=?", "purecpp' or '1=1"); + auto vec8 = mysql.query_s(); + mysql.delete_records_s("name=?", "purecpp"); + auto vec9 = mysql.query_s(); + mysql.delete_records_s(); + auto vec10 = mysql.query_s(); + CHECK(vec1.front().name == "other"); + CHECK(vec1.back().name == "purecpp"); + CHECK(vec3.front().name == "other"); + CHECK(vec3.back().name == "purecpp"); + CHECK(std::get<0>(v_tp3.front()).name == "other"); + CHECK(std::get<0>(v_tp3.back()).name == "purecpp"); + CHECK(vec2.front().age == 200); + CHECK(vec4.front().age == 200); + CHECK(vec5.front().age == 200); + CHECK(vec6.front().age == 200); + CHECK(std::get<0>(v_tp1.front()).age == 200); + CHECK(v_tp2.size() == 0); + CHECK(vec7.size() == 0); + CHECK(vec8.size() == 2); + CHECK(vec9.size() == 1); + CHECK(vec10.size() == 0); } #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({"other"}); - // postgres.insert({"purecpp"}); - // postgres.delete_records("name = 'other';drop table person"); - // auto vec = postgres.query(); - // CHECK(vec.size() == 2); - // } + 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({"other"}); + postgres.insert({"purecpp", 200}); + auto v_tp1 = postgres.query_s>( + "select * from person where name=$1", "purecpp"); + auto v_tp2 = postgres.query_s>( + "select * from person where name=$1", "purecpp' or '1=1"); + auto v_tp3 = postgres.query_s>("select * from person"); + auto vec1 = postgres.query_s(); + auto vec2 = postgres.query_s("name=$1", "purecpp"); + auto vec3 = postgres.query_s("select * from person"); + auto vec4 = postgres.query_s("name=$1", std::string("purecpp")); + auto vec5 = postgres.query_s("name=$1 and age=$2", "purecpp", 200); + auto vec6 = postgres.query_s("select * from person where name=$1", + "purecpp"); + auto vec7 = postgres.query_s("name=$1", "purecpp' or '1=1"); + postgres.delete_records_s("name=$1", "purecpp' or '1=1"); + auto vec8 = postgres.query_s(); + postgres.delete_records_s("name=$1", "purecpp"); + auto vec9 = postgres.query_s(); + postgres.delete_records_s(); + auto vec10 = postgres.query_s(); + CHECK(vec1.front().name == "other"); + CHECK(vec1.back().name == "purecpp"); + CHECK(vec3.front().name == "other"); + CHECK(vec3.back().name == "purecpp"); + CHECK(std::get<0>(v_tp3.front()).name == "other"); + CHECK(std::get<0>(v_tp3.back()).name == "purecpp"); + CHECK(vec2.front().age == 200); + CHECK(vec4.front().age == 200); + CHECK(vec5.front().age == 200); + CHECK(vec6.front().age == 200); + CHECK(std::get<0>(v_tp1.front()).age == 200); + CHECK(v_tp2.size() == 0); + CHECK(vec7.size() == 0); + CHECK(vec8.size() == 2); + CHECK(vec9.size() == 1); + CHECK(vec10.size() == 0); + } #endif #ifdef ORMPP_ENABLE_SQLITE3 dbng sqlite; @@ -1230,10 +1294,42 @@ TEST_CASE("delete records") { sqlite.execute("drop table if exists person"); sqlite.create_datatable(ormpp_auto_key{"id"}); sqlite.insert({"other"}); - sqlite.insert({"purecpp"}); - sqlite.delete_records("name = 'other';drop table person"); - auto vec = sqlite.query(); - CHECK(vec.size() == 1); + sqlite.insert({"purecpp", 200}); + auto v_tp1 = sqlite.query_s>( + "select * from person where name=?", "purecpp"); + auto v_tp2 = sqlite.query_s>( + "select * from person where name=?", "purecpp' or '1=1"); + auto v_tp3 = sqlite.query_s>("select * from person"); + auto vec1 = sqlite.query_s(); + auto vec2 = sqlite.query_s("name=?", "purecpp"); + auto vec3 = sqlite.query_s("select * from person"); + auto vec4 = sqlite.query_s("name=?", std::string("purecpp")); + auto vec5 = sqlite.query_s("name=? and age=?", "purecpp", 200); + auto vec6 = + sqlite.query_s("select * from person where name=?", "purecpp"); + auto vec7 = sqlite.query_s("name=?", "purecpp' or '1=1"); + sqlite.delete_records_s("name=?", "purecpp' or '1=1"); + auto vec8 = sqlite.query_s(); + sqlite.delete_records_s("name=?", "purecpp"); + auto vec9 = sqlite.query_s(); + sqlite.delete_records_s(); + auto vec10 = sqlite.query_s(); + CHECK(vec1.front().name == "other"); + CHECK(vec1.back().name == "purecpp"); + CHECK(vec3.front().name == "other"); + CHECK(vec3.back().name == "purecpp"); + CHECK(std::get<0>(v_tp3.front()).name == "other"); + CHECK(std::get<0>(v_tp3.back()).name == "purecpp"); + CHECK(vec2.front().age == 200); + CHECK(vec4.front().age == 200); + CHECK(vec5.front().age == 200); + CHECK(vec6.front().age == 200); + CHECK(std::get<0>(v_tp1.front()).age == 200); + CHECK(v_tp2.size() == 0); + CHECK(vec7.size() == 0); + CHECK(vec8.size() == 2); + CHECK(vec9.size() == 1); + CHECK(vec10.size() == 0); } #endif }