mirror of
https://github.com/getml/sqlgen.git
synced 2026-01-10 03:20:00 -06:00
Make sure that sqlgen::Range is an input_range
This commit is contained in:
@@ -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()) {
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
50
tests/sqlite/test_range.cpp
Normal file
50
tests/sqlite/test_range.cpp
Normal 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
|
||||
Reference in New Issue
Block a user