Make sure that sqlgen::Range is an input_range

This commit is contained in:
Dr. Patrick Urbanke
2025-04-12 06:45:25 +02:00
parent 843dc40257
commit 4004192a7d
5 changed files with 70 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
#ifndef SQLGEN_ITERATOR_HPP_
#define SQLGEN_ITERATOR_HPP_
#include <iterator>
#include <memory>
#include <ranges>
@@ -19,7 +20,15 @@ class Iterator {
using difference_type = std::ptrdiff_t;
using value_type = Result<T>;
struct End {};
struct End {
bool operator==(const Iterator<T>& _it) const noexcept {
return _it == *this;
}
bool operator!=(const Iterator<T>& _it) const noexcept {
return _it != *this;
}
};
Iterator(const Ref<IteratorBase>& _it)
: current_batch_(get_next_batch(_it)), it_(_it), ix_(0) {}
@@ -30,11 +39,11 @@ class Iterator {
Result<T>* operator->() const noexcept { return &(*current_batch_)[ix_]; }
bool operator==(const End&) noexcept {
bool operator==(const End&) const noexcept {
return ix_ >= current_batch_->size() && it_->end();
}
bool operator!=(const End& _end) noexcept { return !(*this == _end); }
bool operator!=(const End& _end) const noexcept { return !(*this == _end); }
Iterator<T>& operator++() noexcept {
if (ix_ >= current_batch_->size() && !it_->end()) {

View File

@@ -5,6 +5,7 @@
#include <ranges>
#include "Iterator.hpp"
#include "Result.hpp"
namespace sqlgen {
@@ -13,7 +14,10 @@ namespace sqlgen {
template <class T>
class Range {
public:
using value_type = T;
using value_type = Result<T>;
static_assert(std::input_iterator<Iterator<T>>,
"This must be an input iterator.");
struct End {};

View File

@@ -12,9 +12,8 @@ namespace sqlgen {
template <class ContainerType>
Result<ContainerType> read(const Ref<Connection>& _conn) noexcept {
using ValueType = typename ContainerType::value_type;
if constexpr (internal::is_range_v<ContainerType>) {
using ValueType = typename ContainerType::value_type::value_type;
const auto query = transpilation::to_select_from<ValueType>();
return _conn->read(query).transform(
[](auto&& _it) { return ContainerType(_it); });
@@ -32,6 +31,7 @@ Result<ContainerType> read(const Ref<Connection>& _conn) noexcept {
return container;
};
using ValueType = typename ContainerType::value_type;
return read<Range<ValueType>>(_conn).and_then(to_container);
}
}

View File

@@ -11,7 +11,7 @@ target_precompile_headers(sqlgen-tests PRIVATE [["sqlgen.hpp"]] <iostream> <stri
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std:c++20")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -ggdb")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -ggdb -fconcepts-diagnostics-depth=5")
endif()
target_link_libraries(

View File

@@ -0,0 +1,50 @@
#include <gtest/gtest.h>
#include <ranges>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/sqlite.hpp>
#include <vector>
namespace test_range {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(sqlite, test_range) {
static_assert(std::ranges::input_range<sqlgen::Range<Person>>,
"Must be an input range.");
using namespace std::ranges::views;
const auto people1 = std::vector<Person>(
{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}});
const auto conn = sqlgen::sqlite::connect();
sqlgen::write(conn, people1);
const auto people2 = sqlgen::read<sqlgen::Range<Person>>(conn).value();
const auto first_names =
sqlgen::internal::collect::vector(people2 | transform([](const auto& _r) {
return _r.value().first_name;
}));
EXPECT_EQ(first_names.at(0), "Homer");
EXPECT_EQ(first_names.at(1), "Bart");
EXPECT_EQ(first_names.at(2), "Lisa");
EXPECT_EQ(first_names.at(3), "Maggie");
}
} // namespace test_range