From 5496464de7b1c86b5d8e5234168715f85acff902 Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Mon, 5 May 2025 05:29:11 +0200 Subject: [PATCH] Added transformation to dynamic types --- include/sqlgen/dynamic/Column.hpp | 3 +- include/sqlgen/dynamic/SelectFrom.hpp | 2 + include/sqlgen/read.hpp | 3 +- include/sqlgen/transpilation/Value.hpp | 2 +- include/sqlgen/transpilation/to_condition.hpp | 10 +++- .../sqlgen/transpilation/to_select_from.hpp | 19 +++++--- include/sqlgen/where.hpp | 2 +- tests/sqlite/test_where.cpp | 47 +++++++++++++++++++ 8 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 tests/sqlite/test_where.cpp diff --git a/include/sqlgen/dynamic/Column.hpp b/include/sqlgen/dynamic/Column.hpp index e7bf5ad..259c2d5 100644 --- a/include/sqlgen/dynamic/Column.hpp +++ b/include/sqlgen/dynamic/Column.hpp @@ -6,13 +6,14 @@ #include #include "Type.hpp" +#include "types.hpp" namespace sqlgen::dynamic { struct Column { std::optional alias; std::string name; - Type type; + Type type = types::Unknown{}; }; } // namespace sqlgen::dynamic diff --git a/include/sqlgen/dynamic/SelectFrom.hpp b/include/sqlgen/dynamic/SelectFrom.hpp index aebde64..4916682 100644 --- a/include/sqlgen/dynamic/SelectFrom.hpp +++ b/include/sqlgen/dynamic/SelectFrom.hpp @@ -6,6 +6,7 @@ #include #include "Column.hpp" +#include "Condition.hpp" #include "Limit.hpp" #include "OrderBy.hpp" #include "Table.hpp" @@ -15,6 +16,7 @@ namespace sqlgen::dynamic { struct SelectFrom { Table table; std::vector columns; + std::optional where = std::nullopt; std::optional order_by = std::nullopt; std::optional limit = std::nullopt; }; diff --git a/include/sqlgen/read.hpp b/include/sqlgen/read.hpp index c8c9af7..b773ede 100644 --- a/include/sqlgen/read.hpp +++ b/include/sqlgen/read.hpp @@ -21,7 +21,8 @@ Result read_impl(const Ref& _conn, using ValueType = transpilation::value_t; if constexpr (internal::is_range_v) { const auto query = - transpilation::to_select_from(_limit); + transpilation::to_select_from(_where, _limit); return _conn->read(query).transform( [](auto&& _it) { return ContainerType(_it); }); diff --git a/include/sqlgen/transpilation/Value.hpp b/include/sqlgen/transpilation/Value.hpp index 15552c1..b12cc7c 100644 --- a/include/sqlgen/transpilation/Value.hpp +++ b/include/sqlgen/transpilation/Value.hpp @@ -12,7 +12,7 @@ struct Value { template auto make_value(T&& _t) { - return Value>{.val_ = _t}; + return Value>{.val = _t}; } } // namespace sqlgen::transpilation diff --git a/include/sqlgen/transpilation/to_condition.hpp b/include/sqlgen/transpilation/to_condition.hpp index ffb9d57..aed6b72 100644 --- a/include/sqlgen/transpilation/to_condition.hpp +++ b/include/sqlgen/transpilation/to_condition.hpp @@ -1,6 +1,7 @@ #ifndef SQLGEN_TRANSPILATION_TO_CONDITION_HPP_ #define SQLGEN_TRANSPILATION_TO_CONDITION_HPP_ +#include #include #include @@ -122,8 +123,15 @@ struct ToCondition> { } }; +template +struct ToCondition { + std::optional operator()(const Nothing&) const { + return std::nullopt; + } +}; + template -dynamic::Condition to_condition(const ConditionType& _cond) { +std::optional to_condition(const ConditionType& _cond) { return ToCondition>{}(_cond); } diff --git a/include/sqlgen/transpilation/to_select_from.hpp b/include/sqlgen/transpilation/to_select_from.hpp index 88d5e7c..29c766f 100644 --- a/include/sqlgen/transpilation/to_select_from.hpp +++ b/include/sqlgen/transpilation/to_select_from.hpp @@ -14,26 +14,31 @@ #include "get_schema.hpp" #include "get_tablename.hpp" #include "make_columns.hpp" +#include "to_condition.hpp" #include "to_limit.hpp" #include "to_order_by.hpp" namespace sqlgen::transpilation { -template +template requires std::is_class_v> && std::is_aggregate_v> -dynamic::SelectFrom to_select_from(const LimitType& _limit = LimitType{}) { +dynamic::SelectFrom to_select_from(const WhereType& _where = WhereType{}, + const LimitType& _limit = LimitType{}) { using NamedTupleType = rfl::named_tuple_t>; using Fields = typename NamedTupleType::Fields; const auto columns = make_columns( std::make_integer_sequence>()); - return dynamic::SelectFrom{.table = dynamic::Table{.name = get_tablename(), - .schema = get_schema()}, - .columns = columns, - .order_by = to_order_by(), - .limit = to_limit(_limit)}; + return dynamic::SelectFrom{ + .table = + dynamic::Table{.name = get_tablename(), .schema = get_schema()}, + .columns = columns, + .where = to_condition>(_where), + .order_by = to_order_by(), + .limit = to_limit(_limit)}; } } // namespace sqlgen::transpilation diff --git a/include/sqlgen/where.hpp b/include/sqlgen/where.hpp index 7774100..ae5bca8 100644 --- a/include/sqlgen/where.hpp +++ b/include/sqlgen/where.hpp @@ -26,7 +26,7 @@ auto operator|(const Read& _r, "You must call order_by(...) after where(...)."); static_assert(std::is_same_v, "You must call limit(...) after where(...)."); - return Read{ + return Read{ .where_ = _where.condition}; } diff --git a/tests/sqlite/test_where.cpp b/tests/sqlite/test_where.cpp new file mode 100644 index 0000000..d5b15d3 --- /dev/null +++ b/tests/sqlite/test_where.cpp @@ -0,0 +1,47 @@ +#include + +#include +#include +#include +#include +#include + +namespace test_where { + +struct Person { + sqlgen::PrimaryKey id; + std::string first_name; + std::string last_name; + int age; +}; + +TEST(sqlite, test_where) { + const auto people1 = std::vector( + {Person{ + .id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45}, + Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10}, + Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8}, + Person{ + .id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0}, + Person{ + .id = 4, .first_name = "Hugo", .last_name = "Simpson", .age = 10}}); + + const auto conn = sqlgen::sqlite::connect(); + + sqlgen::write(conn, people1); + + using namespace sqlgen; + + const auto query = sqlgen::read> | + where(col<"first_name"> != col<"last_name">) | + order_by(col<"age">, col<"first_name">.desc()); + + const auto people2 = query(conn).value(); + + const std::string expected = + R"([{"id":3,"first_name":"Maggie","last_name":"Simpson","age":0},{"id":2,"first_name":"Lisa","last_name":"Simpson","age":8},{"id":4,"first_name":"Hugo","last_name":"Simpson","age":10},{"id":1,"first_name":"Bart","last_name":"Simpson","age":10},{"id":0,"first_name":"Homer","last_name":"Simpson","age":45}])"; + + EXPECT_EQ(rfl::json::write(people2), expected); +} + +} // namespace test_where