Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions dev/column_result_proxy.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#pragma once

#ifndef SQLITE_ORM_IMPORT_STD_MODULE
#include <type_traits>
#endif

#include "functional/cxx_type_traits_polyfill.h"
#include "tuple_helper/tuple_transformer.h"
#include "type_traits.h"
#include "table_reference.h"

Expand All @@ -20,22 +26,30 @@ namespace sqlite_orm {
namespace sqlite_orm {
namespace internal {

/*
* Determine the actual and final result type of an intermediate column result produced by `column_result_t`,
* unwrapping `table_reference` and `structure`, and transforming tuples element-wise.
*/
template<class T, class SFINAE = void>
struct column_result_proxy : std::remove_const<T> {};

template<class T>
using column_result_proxy_t = typename column_result_proxy<T>::type;

/*
* Unwrap `table_reference`
* Unwrap `table_reference`, `structure`.
*/
template<class P>
struct column_result_proxy<P, match_if<is_table_reference, P>> : decay_table_ref<P> {};
struct column_result_proxy<
P,
std::enable_if_t<
polyfill::disjunction_v<is_table_reference<P>, polyfill::is_specialization_of<P, structure>>>> : P {};

/*
* Pass through `structure`
* Calculate result of multiple columns.
*/
template<class P>
struct column_result_proxy<P, match_specialization_of<P, structure>> : P {};

template<class T>
using column_result_proxy_t = typename column_result_proxy<T>::type;
template<class Tpl>
struct column_result_proxy<Tpl, match_specialization_of<Tpl, std::tuple>>
: tuple_transformer<Tpl, column_result_proxy_t> {};
}
}
12 changes: 4 additions & 8 deletions dev/mapped_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@ namespace sqlite_orm {
namespace internal {

/**
* A C++ view-like class which is returned
* by `storage_t::iterate()` function. This class contains STL functions:
* - size_t size()
* - bool empty()
* - iterator end()
* - iterator begin()
* All these functions are not right const cause all of them may open SQLite connections.
* A C++ view over a result set of objects mapped as tables, returned by `storage_t::iterate<>()`.
*
* `mapped_view` is also a 'borrowed range',
* Models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*
* Its `begin()` and `end()` methods are non-const to leave room for different implementation details.
*/
template<class T, class S, class... Args>
struct mapped_view {
Expand Down
4 changes: 3 additions & 1 deletion dev/result_set_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ namespace sqlite_orm::internal {
/*
* A C++ view over a result set of a select statement, returned by `storage_t::iterate()`.
*
* `result_set_view` is also a 'borrowed range',
* Models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*
* Its `begin()` and `end()` methods are non-const to leave room for different implementation details.
*/
template<class Select, class DBOs>
struct result_set_view
Expand Down
24 changes: 24 additions & 0 deletions dev/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@ namespace sqlite_orm {
}

public:
/*
* Iterate over objects of a type mapped as a table, lazily fetched from a result set.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<class T, class O = mapped_type_proxy_t<T>, class... Args>
mapped_view<O, self_type, Args...> iterate(Args&&... args) {
this->assert_mapped_type<O>();
Expand All @@ -277,13 +283,25 @@ namespace sqlite_orm {
}

#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
/*
* Iterate over objects of a type mapped as a table, lazily fetched from a result set.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<orm_refers_to_table auto mapped, class... Args>
auto iterate(Args&&... args) {
return this->iterate<decltype(mapped)>(std::forward<Args>(args)...);
}
#endif

#ifdef SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED
/*
* Iterate over a result set of a select statement.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<class Select>
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
requires (is_select_v<Select>)
Expand All @@ -295,6 +313,12 @@ namespace sqlite_orm {
}

#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
/*
* Iterate over a result set of a select statement involving a common table expression.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<class... CTEs, class E>
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
requires (is_select_v<E>)
Expand Down
72 changes: 55 additions & 17 deletions include/sqlite_orm/sqlite_orm.h
Original file line number Diff line number Diff line change
Expand Up @@ -10662,6 +10662,14 @@ namespace sqlite_orm {

// #include "column_result_proxy.h"

#ifndef SQLITE_ORM_IMPORT_STD_MODULE
#include <type_traits>
#endif

// #include "functional/cxx_type_traits_polyfill.h"

// #include "tuple_helper/tuple_transformer.h"

// #include "type_traits.h"

// #include "table_reference.h"
Expand All @@ -10683,23 +10691,31 @@ namespace sqlite_orm {
namespace sqlite_orm {
namespace internal {

/*
* Determine the actual and final result type of an intermediate column result produced by `column_result_t`,
* unwrapping `table_reference` and `structure`, and transforming tuples element-wise.
*/
template<class T, class SFINAE = void>
struct column_result_proxy : std::remove_const<T> {};

template<class T>
using column_result_proxy_t = typename column_result_proxy<T>::type;

/*
* Unwrap `table_reference`
* Unwrap `table_reference`, `structure`.
*/
template<class P>
struct column_result_proxy<P, match_if<is_table_reference, P>> : decay_table_ref<P> {};
struct column_result_proxy<
P,
std::enable_if_t<
polyfill::disjunction_v<is_table_reference<P>, polyfill::is_specialization_of<P, structure>>>> : P {};

/*
* Pass through `structure`
* Calculate result of multiple columns.
*/
template<class P>
struct column_result_proxy<P, match_specialization_of<P, structure>> : P {};

template<class T>
using column_result_proxy_t = typename column_result_proxy<T>::type;
template<class Tpl>
struct column_result_proxy<Tpl, match_specialization_of<Tpl, std::tuple>>
: tuple_transformer<Tpl, column_result_proxy_t> {};
}
}

Expand Down Expand Up @@ -16335,16 +16351,12 @@ namespace sqlite_orm {
namespace internal {

/**
* A C++ view-like class which is returned
* by `storage_t::iterate()` function. This class contains STL functions:
* - size_t size()
* - bool empty()
* - iterator end()
* - iterator begin()
* All these functions are not right const cause all of them may open SQLite connections.
* A C++ view over a result set of objects mapped as tables, returned by `storage_t::iterate<>()`.
*
* `mapped_view` is also a 'borrowed range',
* Models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*
* Its `begin()` and `end()` methods are non-const to leave room for different implementation details.
*/
template<class T, class S, class... Args>
struct mapped_view {
Expand Down Expand Up @@ -16509,8 +16521,10 @@ namespace sqlite_orm::internal {
/*
* A C++ view over a result set of a select statement, returned by `storage_t::iterate()`.
*
* `result_set_view` is also a 'borrowed range',
* Models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*
* Its `begin()` and `end()` methods are non-const to leave room for different implementation details.
*/
template<class Select, class DBOs>
struct result_set_view
Expand Down Expand Up @@ -23359,6 +23373,12 @@ namespace sqlite_orm {
}

public:
/*
* Iterate over objects of a type mapped as a table, lazily fetched from a result set.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<class T, class O = mapped_type_proxy_t<T>, class... Args>
mapped_view<O, self_type, Args...> iterate(Args&&... args) {
this->assert_mapped_type<O>();
Expand All @@ -23368,13 +23388,25 @@ namespace sqlite_orm {
}

#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
/*
* Iterate over objects of a type mapped as a table, lazily fetched from a result set.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<orm_refers_to_table auto mapped, class... Args>
auto iterate(Args&&... args) {
return this->iterate<decltype(mapped)>(std::forward<Args>(args)...);
}
#endif

#ifdef SQLITE_ORM_DEFAULT_COMPARISONS_SUPPORTED
/*
* Iterate over a result set of a select statement.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<class Select>
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
requires (is_select_v<Select>)
Expand All @@ -23386,6 +23418,12 @@ namespace sqlite_orm {
}

#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
/*
* Iterate over a result set of a select statement involving a common table expression.
*
* The returned C++ view models a C++ input range and is also a 'borrowed range',
* meaning that iterators obtained from it are not tied to the lifetime of the view instance.
*/
template<class... CTEs, class E>
#ifdef SQLITE_ORM_CONCEPTS_SUPPORTED
requires (is_select_v<E>)
Expand Down
12 changes: 8 additions & 4 deletions tests/static_tests/iterator_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,24 @@ TEST_CASE("can view and iterate result set") {
STATIC_REQUIRE(
can_iterate_result_set<result_set_iterator<structure<Object, empty_db_objects_type>, empty_db_objects_type>,
Object>);
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
STATIC_REQUIRE(can_iterate_result_set<result_set_iterator<table_reference<Object>, db_objects_type>, Object>);
#endif
STATIC_REQUIRE(can_iterate_result_set<
result_set_iterator<std::tuple<table_reference<Object>, structure<Object, std::tuple<>>, int>,
db_objects_type>,
std::tuple<Object, Object, int>>);

STATIC_REQUIRE(storage_iterate_result_set<empty_storage_type, decltype(select(42)), int>);
STATIC_REQUIRE(
storage_iterate_result_set<empty_storage_type, decltype(select(columns(1, 42))), std::tuple<int, int>>);
STATIC_REQUIRE(storage_iterate_result_set<empty_storage_type,
decltype(select(struct_<Object>())),
structure<Object, std::tuple<>>>);
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
STATIC_REQUIRE(
storage_iterate_result_set<storage_type, decltype(select(object<Object>())), table_reference<Object>>);
#endif
STATIC_REQUIRE(
storage_iterate_result_set<storage_type,
decltype(select(columns(object<Object>(), struct_<Object>(), 42))),
std::tuple<table_reference<Object>, structure<Object, std::tuple<>>, int>>);

#if (SQLITE_VERSION_NUMBER >= 3008003) && defined(SQLITE_ORM_WITH_CTE)
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
Expand Down