From 3736fcc29ce4b63ea186486fc0a071f4f3db4241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dr=2E=20Patrick=20Urbanke=20=28=E5=8A=89=E8=87=AA=E6=88=90?= =?UTF-8?q?=29?= Date: Tue, 14 Oct 2025 23:11:08 +0200 Subject: [PATCH] Better implementation for value_t; fixes #64 (#65) --- include/sqlgen/insert.hpp | 29 +++++----------- include/sqlgen/transpilation/value_t.hpp | 24 ++++++++++--- tests/postgres/test_read_to_sql.cpp | 31 +++++++++++++++++ tests/sqlite/test_insert_or_replace.cpp | 44 +++++++++++++++--------- 4 files changed, 87 insertions(+), 41 deletions(-) create mode 100644 tests/postgres/test_read_to_sql.cpp diff --git a/include/sqlgen/insert.hpp b/include/sqlgen/insert.hpp index 2c9bf48..ee897a5 100644 --- a/include/sqlgen/insert.hpp +++ b/include/sqlgen/insert.hpp @@ -15,6 +15,7 @@ #include "internal/to_str_vec.hpp" #include "is_connection.hpp" #include "transpilation/to_insert_or_write.hpp" +#include "transpilation/value_t.hpp" namespace sqlgen { @@ -84,31 +85,19 @@ auto insert(const Args&... args) { template auto insert_or_replace(const auto& _conn, const ContainerType& _data) { - if constexpr (std::ranges::input_range>) { - static_assert( - internal::has_constraint_v, - "The table must have a primary key or unique column for " - "insert_or_replace(...) to work."); - } else { - static_assert(internal::has_constraint_v, - "The table must have a primary key or unique column for " - "insert_or_replace(...) to work."); - } + static_assert( + internal::has_constraint_v>, + "The table must have a primary key or unique column for " + "insert_or_replace(...) to work."); return insert_impl(_conn, _data, true); } template auto insert_or_replace(const ContainerType& _data) { - if constexpr (std::ranges::input_range>) { - static_assert( - internal::has_constraint_v, - "The table must have a primary key or unique column for " - "insert_or_replace(...) to work."); - } else { - static_assert(internal::has_constraint_v, - "The table must have a primary key or unique column for " - "insert_or_replace(...) to work."); - } + static_assert( + internal::has_constraint_v>, + "The table must have a primary key or unique column for " + "insert_or_replace(...) to work."); return insert_impl(_data, true); } diff --git a/include/sqlgen/transpilation/value_t.hpp b/include/sqlgen/transpilation/value_t.hpp index 8bdb1ba..cf9ba11 100644 --- a/include/sqlgen/transpilation/value_t.hpp +++ b/include/sqlgen/transpilation/value_t.hpp @@ -1,6 +1,10 @@ #ifndef SQLGEN_TRANSPILATION_VALUET_HPP_ #define SQLGEN_TRANSPILATION_VALUET_HPP_ +#include +#include +#include + #include "../Range.hpp" namespace sqlgen::transpilation { @@ -8,18 +12,30 @@ namespace sqlgen::transpilation { template struct ValueType; +template + requires(!std::ranges::input_range) +struct ValueType { + using Type = std::remove_cvref_t; +}; + template -struct ValueType { - using Type = typename ContainerType::value_type; + requires std::ranges::input_range +struct ValueType { + using Type = std::remove_cvref_t; }; template struct ValueType> { - using Type = typename Range::value_type::value_type; + using Type = std::remove_cvref_t::value_type::value_type>; }; template -using value_t = typename ValueType::Type; +struct ValueType> { + using Type = typename ValueType>::Type; +}; + +template +using value_t = typename ValueType>::Type; } // namespace sqlgen::transpilation diff --git a/tests/postgres/test_read_to_sql.cpp b/tests/postgres/test_read_to_sql.cpp new file mode 100644 index 0000000..7cedfbf --- /dev/null +++ b/tests/postgres/test_read_to_sql.cpp @@ -0,0 +1,31 @@ +#include + +#include +#include +#include +#include + +namespace test_write_and_read_dry { + +struct Person { + sqlgen::PrimaryKey id; + std::string first_name; + std::string last_name; + int age; +}; + +TEST(postgres, test_write_and_read_dry) { + using namespace sqlgen; + using namespace sqlgen::literals; + + const auto query1 = + postgres::to_sql(sqlgen::read> | where("id"_c == 1)); + const auto query2 = + postgres::to_sql(sqlgen::read | where("id"_c == 1)); + + std::cout << query1 << std::endl; + std::cout << query2 << std::endl; +} + +} // namespace test_write_and_read_dry + diff --git a/tests/sqlite/test_insert_or_replace.cpp b/tests/sqlite/test_insert_or_replace.cpp index 7da48c8..eddce8a 100644 --- a/tests/sqlite/test_insert_or_replace.cpp +++ b/tests/sqlite/test_insert_or_replace.cpp @@ -24,32 +24,42 @@ TEST(sqlite, test_insert_or_replace) { Person{ .id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0}}); - const auto people2 = std::vector( - {Person{.id = 1, .first_name = "Bartholomew", .last_name = "Simpson", .age = 10}, - Person{ - .id = 3, .first_name = "Margaret", .last_name = "Simpson", .age = 1}}); + const auto people2 = std::vector({Person{.id = 1, + .first_name = "Bartholomew", + .last_name = "Simpson", + .age = 10}, + Person{.id = 3, + .first_name = "Margaret", + .last_name = "Simpson", + .age = 1}}); const auto people3 = std::vector( {Person{ .id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45}, - Person{.id = 1, .first_name = "Bartholomew", .last_name = "Simpson", .age = 10}, + Person{.id = 1, + .first_name = "Bartholomew", + .last_name = "Simpson", + .age = 10}, Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8}, - Person{ - .id = 3, .first_name = "Margaret", .last_name = "Simpson", .age = 1}}); + Person{.id = 3, + .first_name = "Margaret", + .last_name = "Simpson", + .age = 1}}); using namespace sqlgen; using namespace sqlgen::literals; - const auto people4 = sqlite::connect() - .and_then(begin_transaction) - .and_then(create_table | if_not_exists) - .and_then(insert(people1)) - .and_then(commit) - .and_then(begin_transaction) - .and_then(insert_or_replace(people2)) - .and_then(commit) - .and_then(sqlgen::read> | order_by("id"_c)) - .value(); + const auto people4 = + sqlite::connect() + .and_then(begin_transaction) + .and_then(create_table | if_not_exists) + .and_then(insert(people1)) + .and_then(commit) + .and_then(begin_transaction) + .and_then(insert_or_replace(std::ref(people2))) + .and_then(commit) + .and_then(sqlgen::read> | order_by("id"_c)) + .value(); const auto json3 = rfl::json::write(people3); const auto json4 = rfl::json::write(people4);