Implement offset support (#102)

As per discussions in [1].

[1] https://github.com/getml/sqlgen/issues/100
This commit is contained in:
Marco Craveiro
2025-12-03 21:55:59 +00:00
committed by GitHub
parent cd42a4e4cf
commit 657a9fd4ee
29 changed files with 449 additions and 74 deletions

View File

@@ -36,6 +36,7 @@
#include "sqlgen/is_connection.hpp"
#include "sqlgen/joins.hpp"
#include "sqlgen/limit.hpp"
#include "sqlgen/offset.hpp"
#include "sqlgen/literals.hpp"
#include "sqlgen/operations.hpp"
#include "sqlgen/order_by.hpp"

View File

@@ -18,12 +18,12 @@ namespace sqlgen {
template <class ValueType, class TableOrQueryType, class AliasType,
class FieldsType, class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType, class Connection>
class OrderByType, class LimitType, class OffsetType, class ToType, class Connection>
requires is_connection<Connection>
Result<Ref<Connection>> create_as_impl(
const Ref<Connection>& _conn, const dynamic::CreateAs::What _what,
const SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>&
WhereType, GroupByType, OrderByType, LimitType, OffsetType, ToType>&
_as,
const bool _or_replace, const bool _if_not_exists) {
using TableTupleType =
@@ -31,9 +31,9 @@ Result<Ref<Connection>> create_as_impl(
const auto query = transpilation::to_create_as<
ValueType, TableTupleType, AliasType, FieldsType, TableOrQueryType,
JoinsType, WhereType, GroupByType, OrderByType, LimitType>(
JoinsType, WhereType, GroupByType, OrderByType, LimitType, OffsetType>(
_what, _or_replace, _if_not_exists, _as.fields_, _as.from_, _as.joins_,
_as.where_, _as.limit_);
_as.where_, _as.limit_, _as.offset_);
return _conn->execute(_conn->to_sql(query)).transform([&](const auto&) {
return _conn;
@@ -42,12 +42,12 @@ Result<Ref<Connection>> create_as_impl(
template <class ValueType, class TableOrQueryType, class AliasType,
class FieldsType, class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType, class Connection>
class OrderByType, class LimitType, class OffsetType, class ToType, class Connection>
requires is_connection<Connection>
Result<Ref<Connection>> create_as_impl(
const Result<Ref<Connection>>& _res, const dynamic::CreateAs::What _what,
const SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>&
WhereType, GroupByType, OrderByType, LimitType, OffsetType, ToType>&
_as,
const bool _or_replace, const bool _if_not_exists) {
return _res.and_then([&](const auto& _conn) {
@@ -58,10 +58,10 @@ Result<Ref<Connection>> create_as_impl(
template <class ValueType, class TableOrQueryType, class AliasType,
class FieldsType, class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType>
class OrderByType, class LimitType, class OffsetType, class ToType>
struct CreateAs {
using As = SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>;
WhereType, GroupByType, OrderByType, LimitType, OffsetType, ToType>;
static_assert(
requires(transpilation::extract_table_t<As, false> a) {
@@ -108,4 +108,3 @@ inline auto create_or_replace_view_as(const SelectFrom<Args...>& _as) {
}; // namespace sqlgen
#endif

View File

@@ -139,7 +139,7 @@ class SQLGEN_API Connection {
}));
const auto select_from = dynamic::SelectFrom{
.table_or_query = _table, .fields = fields, .limit = dynamic::Limit{0}};
.table_or_query = _table, .fields = fields, .limit = dynamic::Limit{0}, .offset = dynamic::Offset{0}};
return DuckDBResult::make(to_sql(select_from), conn_)
.transform([&](const auto &_res) {

View File

@@ -0,0 +1,14 @@
#ifndef SQLGEN_DYNAMIC_OFFSET_HPP_
#define SQLGEN_DYNAMIC_OFFSET_HPP_
#include <cstddef>
namespace sqlgen::dynamic {
struct Offset {
size_t val;
};
} // namespace sqlgen::dynamic
#endif

View File

@@ -11,6 +11,7 @@
#include "GroupBy.hpp"
#include "JoinType.hpp"
#include "Limit.hpp"
#include "Offset.hpp"
#include "Operation.hpp"
#include "OrderBy.hpp"
#include "Table.hpp"
@@ -46,6 +47,7 @@ struct SelectFrom {
std::optional<GroupBy> group_by = std::nullopt;
std::optional<OrderBy> order_by = std::nullopt;
std::optional<Limit> limit = std::nullopt;
std::optional<Offset> offset = std::nullopt;
};
} // namespace sqlgen::dynamic

14
include/sqlgen/offset.hpp Normal file
View File

@@ -0,0 +1,14 @@
#ifndef SQLGEN_OFFSET_HPP_
#define SQLGEN_OFFSET_HPP_
#include "transpilation/Offset.hpp"
namespace sqlgen {
using Offset = transpilation::Offset;
inline auto offset(const size_t _val) { return Offset{_val}; };
} // namespace sqlgen
#endif

View File

@@ -9,6 +9,7 @@
#include "internal/is_range.hpp"
#include "is_connection.hpp"
#include "limit.hpp"
#include "offset.hpp"
#include "order_by.hpp"
#include "transpilation/order_by_t.hpp"
#include "transpilation/read_to_select_from.hpp"
@@ -18,40 +19,40 @@
namespace sqlgen {
template <class ContainerType, class WhereType, class OrderByType,
class LimitType, class Connection>
class LimitType, class OffsetType, class Connection>
requires is_connection<Connection>
auto read_impl(const Ref<Connection>& _conn, const WhereType& _where,
const LimitType& _limit) {
const LimitType& _limit, const OffsetType& _offset) {
using ValueType = transpilation::value_t<ContainerType>;
const auto query =
transpilation::read_to_select_from<ValueType, WhereType, OrderByType,
LimitType>(_where, _limit);
LimitType, OffsetType>(_where, _limit, _offset);
return _conn->template read<ContainerType>(query);
}
template <class ContainerType, class WhereType, class OrderByType,
class LimitType, class Connection>
class LimitType, class OffsetType, class Connection>
requires is_connection<Connection>
auto read_impl(const Result<Ref<Connection>>& _res, const WhereType& _where,
const LimitType& _limit) {
const LimitType& _limit, const OffsetType& _offset) {
return _res.and_then([&](const auto& _conn) {
return read_impl<ContainerType, WhereType, OrderByType, LimitType>(
_conn, _where, _limit);
return read_impl<ContainerType, WhereType, OrderByType, LimitType, OffsetType>(
_conn, _where, _limit, _offset);
});
}
template <class Type, class WhereType = Nothing, class OrderByType = Nothing,
class LimitType = Nothing>
class LimitType = Nothing, class OffsetType = Nothing>
struct Read {
auto operator()(const auto& _conn) const {
if constexpr (std::ranges::input_range<std::remove_cvref_t<Type>> ||
internal::is_range_v<Type>) {
return read_impl<Type, WhereType, OrderByType, LimitType>(_conn, where_,
limit_);
return read_impl<Type, WhereType, OrderByType, LimitType, OffsetType>(_conn, where_,
limit_, offset_);
} else {
return read_impl<std::vector<Type>, WhereType, OrderByType, LimitType>(
_conn, where_, limit_)
return read_impl<std::vector<Type>, WhereType, OrderByType, LimitType, OffsetType>(
_conn, where_, limit_, offset_)
.and_then([](auto&& _vec) -> Result<Type> {
if (_vec.size() != 1) {
return error(
@@ -73,7 +74,9 @@ struct Read {
"You cannot call order_by(...) before where(...).");
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) before where(...).");
return Read<Type, ConditionType, OrderByType, LimitType>{
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) before where(...).");
return Read<Type, ConditionType, OrderByType, LimitType, OffsetType>{
.where_ = _where.condition};
}
@@ -85,25 +88,38 @@ struct Read {
"than one column).");
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) before order_by.");
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) before order_by.");
static_assert(sizeof...(ColTypes) != 0,
"You must assign at least one column to order by(...).");
return Read<Type, WhereType,
transpilation::order_by_t<
transpilation::value_t<Type>, Nothing,
typename std::remove_cvref_t<ColTypes>::ColType...>,
LimitType>{.where_ = _r.where_};
LimitType, OffsetType>{.where_ = _r.where_};
}
friend auto operator|(const Read& _r, const Limit& _limit) {
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) twice.");
return Read<Type, WhereType, OrderByType, Limit>{.where_ = _r.where_,
.limit_ = _limit};
return Read<Type, WhereType, OrderByType, Limit, OffsetType>{.where_ = _r.where_,
.limit_ = _limit,
.offset_ = _r.offset_};
}
friend auto operator|(const Read& _r, const Offset& _offset) {
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) twice.");
return Read<Type, WhereType, OrderByType, LimitType, Offset>{.where_ = _r.where_,
.limit_ = _r.limit_,
.offset_ = _offset};
}
WhereType where_;
LimitType limit_;
OffsetType offset_;
};
template <class ContainerType>

View File

@@ -17,6 +17,7 @@
#include "internal/iterator_t.hpp"
#include "is_connection.hpp"
#include "limit.hpp"
#include "offset.hpp"
#include "order_by.hpp"
#include "to.hpp"
#include "transpilation/Join.hpp"
@@ -36,10 +37,10 @@ template <class SelectFromT, class ContainerType, class Connection>
requires is_connection<Connection>
auto select_from_impl(const Ref<Connection>& _conn, const auto& _fields,
const auto& _table_or_query, const auto& _joins,
const auto& _where, const auto& _limit) {
const auto& _where, const auto& _limit, const auto& _offset) {
if constexpr (internal::is_range_v<ContainerType>) {
const auto query = transpilation::to_select_from<SelectFromT>(
_fields, _table_or_query, _joins, _where, _limit);
_fields, _table_or_query, _joins, _where, _limit, _offset);
return _conn->template read<ContainerType>(query);
} else {
@@ -66,7 +67,7 @@ auto select_from_impl(const Ref<Connection>& _conn, const auto& _fields,
using RangeType = Range<IteratorType>;
return select_from_impl<SelectFromT, RangeType>(
_conn, _fields, _table_or_query, _joins, _where, _limit)
_conn, _fields, _table_or_query, _joins, _where, _limit, _offset)
.and_then(to_container);
}
}
@@ -75,17 +76,17 @@ template <class SelectFromT, class ContainerType, class Connection>
requires is_connection<Connection>
auto select_from_impl(const Result<Ref<Connection>>& _res, const auto& _fields,
const auto& _table_or_query, const auto& _joins,
const auto& _where, const auto& _limit) {
const auto& _where, const auto& _limit, const auto& _offset) {
return _res.and_then([&](const auto& _conn) {
return select_from_impl<SelectFromT, ContainerType>(
_conn, _fields, _table_or_query, _joins, _where, _limit);
_conn, _fields, _table_or_query, _joins, _where, _limit, _offset);
});
}
template <class TableOrQueryT, class AliasT, class FieldsT,
class JoinsT = Nothing, class WhereT = Nothing,
class GroupByT = Nothing, class OrderByT = Nothing,
class LimitT = Nothing, class ToT = Nothing>
class LimitT = Nothing, class OffsetT = Nothing, class ToT = Nothing>
struct SelectFrom {
using TableOrQueryType = TableOrQueryT;
using AliasType = AliasT;
@@ -95,12 +96,13 @@ struct SelectFrom {
using GroupByType = GroupByT;
using OrderByType = OrderByT;
using LimitType = LimitT;
using OffsetType = OffsetT;
using ToType = ToT;
using SelectFromTypes =
transpilation::SelectFromTypes<AliasType, FieldsType, TableOrQueryType,
JoinsType, WhereType, GroupByType,
OrderByType, LimitType>;
OrderByType, LimitType, OffsetType>;
auto operator()(const auto& _conn) const {
using TableTupleType =
@@ -115,7 +117,7 @@ struct SelectFrom {
using ContainerType = std::conditional_t<std::is_same_v<ToType, Nothing>,
Range<IteratorType>, ToType>;
return select_from_impl<SelectFromTypes, ContainerType>(
_conn, fields_, from_, joins_, where_, limit_);
_conn, fields_, from_, joins_, where_, limit_, offset_);
} else {
const auto extract_result = [](auto&& _vec) -> Result<ToType> {
@@ -130,7 +132,7 @@ struct SelectFrom {
return select_from_impl<SelectFromTypes,
std::vector<std::remove_cvref_t<ToType>>>(
_conn, fields_, from_, joins_, where_, limit_)
_conn, fields_, from_, joins_, where_, limit_, offset_)
.and_then(extract_result);
}
}
@@ -149,6 +151,8 @@ struct SelectFrom {
"You cannot call order_by(...) before a join.");
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) before a join.");
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) before a join.");
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> before a join.");
@@ -158,7 +162,7 @@ struct SelectFrom {
_alias, _how>>;
return SelectFrom<TableOrQueryType, AliasType, FieldsType, NewJoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>{
WhereType, GroupByType, OrderByType, LimitType, OffsetType, ToType>{
.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = NewJoinsType(_join)};
@@ -173,7 +177,7 @@ struct SelectFrom {
using NewJoinsType = std::remove_cvref_t<decltype(joins)>;
return SelectFrom<TableOrQueryType, AliasType, FieldsType, NewJoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>{
WhereType, GroupByType, OrderByType, LimitType, OffsetType, ToType>{
.fields_ = _s.fields_, .from_ = _s.from_, .joins_ = joins};
}
}
@@ -190,10 +194,12 @@ struct SelectFrom {
"You cannot call order_by(...) before where(...).");
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) before where(...).");
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) before where(...).");
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> before where(...).");
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
ConditionType, GroupByType, OrderByType, LimitType,
ConditionType, GroupByType, OrderByType, LimitType, OffsetType,
ToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
@@ -210,6 +216,8 @@ struct SelectFrom {
"You cannot call order_by(...) before group_by(...).");
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) before group_by(...).");
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) before group_by(...).");
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> before group_by(...).");
static_assert(sizeof...(ColTypes) != 0,
@@ -220,7 +228,7 @@ struct SelectFrom {
WhereType,
transpilation::group_by_t<TableTupleType,
typename ColTypes::ColType...>,
OrderByType, LimitType, ToType>{.fields_ = _s.fields_,
OrderByType, LimitType, OffsetType, ToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_};
@@ -234,6 +242,8 @@ struct SelectFrom {
"than one column).");
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit(...) before order_by(...).");
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset(...) before order_by(...).");
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> before order_by(...).");
static_assert(sizeof...(ColTypes) != 0,
@@ -247,7 +257,7 @@ struct SelectFrom {
typename std::remove_cvref_t<ColTypes>::ColType...>;
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, NewOrderByType, LimitType,
WhereType, GroupByType, NewOrderByType, LimitType, OffsetType,
ToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
@@ -257,13 +267,27 @@ struct SelectFrom {
friend auto operator|(const SelectFrom& _s, const Limit& _limit) {
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit twice.");
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, Limit, ToType>{
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, Limit, OffsetType, ToType>{
.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_,
.limit_ = _limit};
.limit_ = _limit,
.offset_ = _s.offset_};
}
friend auto operator|(const SelectFrom& _s, const Offset& _offset) {
static_assert(std::is_same_v<OffsetType, Nothing>,
"You cannot call offset twice.");
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType, Offset, ToType>{
.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_,
.limit_ = _s.limit_,
.offset_ = _offset};
}
template <class NewToType>
@@ -271,12 +295,13 @@ struct SelectFrom {
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> twice.");
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType,
WhereType, GroupByType, OrderByType, LimitType, OffsetType,
NewToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_,
.limit_ = _s.limit_};
.limit_ = _s.limit_,
.offset_ = _s.offset_};
}
FieldsType fields_;
@@ -288,6 +313,8 @@ struct SelectFrom {
WhereType where_;
LimitType limit_;
OffsetType offset_;
};
namespace transpilation {
@@ -303,16 +330,16 @@ struct ExtractTable<
template <class TableOrQueryType, class AliasType, class FieldsType,
class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType>
class OrderByType, class LimitType, class OffsetType, class ToType>
struct ToTableOrQuery<
SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType, ToType>> {
GroupByType, OrderByType, LimitType, OffsetType, ToType>> {
dynamic::SelectFrom::TableOrQueryType operator()(const auto& _query) {
using QueryType = std::remove_cvref_t<decltype(_query)>;
return Ref<dynamic::SelectFrom>::make(
transpilation::to_select_from<typename QueryType::SelectFromTypes>(
_query.fields_, _query.from_, _query.joins_, _query.where_,
_query.limit_));
_query.limit_, _query.offset_));
}
};

View File

@@ -0,0 +1,12 @@
#ifndef SQLGEN_TRANSPILATION_OFFSET_HPP_
#define SQLGEN_TRANSPILATION_OFFSET_HPP_
#include "../dynamic/Offset.hpp"
namespace sqlgen::transpilation {
using Offset = dynamic::Offset;
} // namespace sqlgen::transpilation
#endif

View File

@@ -18,16 +18,18 @@
#include "make_columns.hpp"
#include "to_condition.hpp"
#include "to_limit.hpp"
#include "to_offset.hpp"
#include "to_order_by.hpp"
namespace sqlgen::transpilation {
template <class T, class WhereType = Nothing, class OrderByType = Nothing,
class LimitType = Nothing>
class LimitType = Nothing, class OffsetType = Nothing>
requires std::is_class_v<std::remove_cvref_t<T>> &&
std::is_aggregate_v<std::remove_cvref_t<T>>
dynamic::SelectFrom read_to_select_from(const WhereType& _where = WhereType{},
const LimitType& _limit = LimitType{}) {
const LimitType& _limit = LimitType{},
const OffsetType& _offset = OffsetType{}) {
using namespace std::ranges::views;
using NamedTupleType = rfl::named_tuple_t<std::remove_cvref_t<T>>;
@@ -48,7 +50,8 @@ dynamic::SelectFrom read_to_select_from(const WhereType& _where = WhereType{},
.fields = fields,
.where = to_condition<std::remove_cvref_t<T>>(_where),
.order_by = to_order_by<OrderByType>(),
.limit = to_limit(_limit)};
.limit = to_limit(_limit),
.offset = to_offset(_offset)};
}
} // namespace sqlgen::transpilation

View File

@@ -17,7 +17,7 @@ namespace sqlgen::transpilation {
template <class T, class TableTupleType, class AliasType, class FieldsType,
class TableOrQueryType, class JoinsType, class WhereType,
class GroupByType, class OrderByType, class LimitType>
class GroupByType, class OrderByType, class LimitType, class OffsetType>
requires std::is_class_v<std::remove_cvref_t<T>> &&
std::is_aggregate_v<std::remove_cvref_t<T>>
dynamic::CreateAs to_create_as(const dynamic::CreateAs::What _what,
@@ -26,11 +26,11 @@ dynamic::CreateAs to_create_as(const dynamic::CreateAs::What _what,
const FieldsType& _fields,
const TableOrQueryType& _table_or_query,
const JoinsType& _joins, const WhereType& _where,
const LimitType& _limit) {
const LimitType& _limit, const OffsetType& _offset) {
using SelectFromTypes =
transpilation::SelectFromTypes<AliasType, FieldsType, TableOrQueryType,
JoinsType, WhereType, GroupByType,
OrderByType, LimitType>;
OrderByType, LimitType, OffsetType>;
return dynamic::CreateAs{
.what = _what,
@@ -38,7 +38,7 @@ dynamic::CreateAs to_create_as(const dynamic::CreateAs::What _what,
.name = get_tablename<T>(),
.schema = get_schema<T>()},
.query = to_select_from<SelectFromTypes>(_fields, _table_or_query, _joins,
_where, _limit),
_where, _limit, _offset),
.or_replace = _or_replace,
.if_not_exists = _if_not_exists};
}

View File

@@ -0,0 +1,30 @@
#ifndef SQLGEN_TRANSPILATION_TO_OFFSET_HPP_
#define SQLGEN_TRANSPILATION_TO_OFFSET_HPP_
#include <rfl.hpp>
#include <type_traits>
#include <vector>
#include "../Result.hpp"
#include "../dynamic/Offset.hpp"
#include "Offset.hpp"
#include "order_by_t.hpp"
namespace sqlgen::transpilation {
template <class OffsetType>
std::optional<dynamic::Offset> to_offset(const OffsetType& _offset) {
if constexpr (std::is_same_v<std::remove_cvref_t<OffsetType>, Nothing>) {
return std::nullopt;
} else if constexpr (std::is_same_v<std::remove_cvref_t<OffsetType>, Offset>) {
return _offset;
} else {
static_assert(rfl::always_false_v<OffsetType>, "Unsupported type");
}
}
} // namespace sqlgen::transpilation
#endif

View File

@@ -26,13 +26,14 @@
#include "to_group_by.hpp"
#include "to_joins.hpp"
#include "to_limit.hpp"
#include "to_offset.hpp"
#include "to_order_by.hpp"
#include "to_table_or_query.hpp"
namespace sqlgen::transpilation {
template <class AliasT, class FieldsT, class TableOrQueryT, class JoinsT,
class WhereT, class GroupByT, class OrderByT, class LimitT>
class WhereT, class GroupByT, class OrderByT, class LimitT, class OffsetT>
struct SelectFromTypes {
using AliasType = AliasT;
using FieldsType = FieldsT;
@@ -42,6 +43,7 @@ struct SelectFromTypes {
using GroupByType = GroupByT;
using OrderByType = OrderByT;
using LimitType = LimitT;
using OffsetType = OffsetT;
using TableTupleType = table_tuple_t<TableOrQueryType, AliasType, JoinsType>;
};
@@ -50,7 +52,7 @@ template <class SelectFromT>
dynamic::SelectFrom to_select_from(const auto& _fields,
const auto& _table_or_query,
const auto& _joins, const auto& _where,
const auto& _limit) {
const auto& _limit, const auto& _offset) {
using TableTupleType = typename SelectFromT::TableTupleType;
using AliasType = typename SelectFromT::AliasType;
using FieldsType = typename SelectFromT::FieldsType;
@@ -75,7 +77,8 @@ dynamic::SelectFrom to_select_from(const auto& _fields,
.where = to_condition<std::remove_cvref_t<TableTupleType>>(_where),
.group_by = to_group_by<GroupByType>(),
.order_by = to_order_by<OrderByType>(),
.limit = to_limit(_limit)};
.limit = to_limit(_limit),
.offset = to_offset(_offset)};
}
} // namespace sqlgen::transpilation

View File

@@ -34,10 +34,10 @@ struct ToSQL;
template <class ValueType, class TableOrQueryType, class AliasType,
class FieldsType, class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType>
class OrderByType, class LimitType, class OffsetType, class ToType>
struct ToSQL<
CreateAs<ValueType, TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>> {
WhereType, GroupByType, OrderByType, LimitType, OffsetType, ToType>> {
dynamic::Statement operator()(const auto& _create_as) const {
using TableTupleType =
transpilation::table_tuple_t<ValueType, AliasType, JoinsType>;
@@ -46,7 +46,7 @@ struct ToSQL<
OrderByType, LimitType>(
_create_as.what_, _create_as.or_replace_, _create_as.if_not_exists_,
_create_as.as_.fields_, _create_as.as_.from_, _create_as.as_.joins_,
_create_as.as_.where_, _create_as.as_.limit_);
_create_as.as_.where_, _create_as.as_.limit_, _create_as.as_.offset_);
}
};
@@ -90,11 +90,11 @@ struct ToSQL<Insert<T>> {
};
template <class ContainerType, class WhereType, class OrderByType,
class LimitType>
struct ToSQL<Read<ContainerType, WhereType, OrderByType, LimitType>> {
class LimitType, class OffsetType>
struct ToSQL<Read<ContainerType, WhereType, OrderByType, LimitType, OffsetType>> {
dynamic::Statement operator()(const auto& _read) const {
return read_to_select_from<value_t<ContainerType>, WhereType, OrderByType,
LimitType>(_read.where_, _read.limit_);
LimitType, OffsetType>(_read.where_, _read.limit_, _read.offset_);
}
};
@@ -104,7 +104,7 @@ struct ToSQL<SelectFrom<Ts...>> {
using SelectFromTypes = typename SelectFrom<Ts...>::SelectFromTypes;
return to_select_from<SelectFromTypes>(
_select_from.fields_, _select_from.from_, _select_from.joins_,
_select_from.where_, _select_from.limit_);
_select_from.where_, _select_from.limit_, _select_from.offset_);
}
};

View File

@@ -27,7 +27,7 @@ dynamic::Union to_union(const rfl::Tuple<Ts...>& _stmts,
auto vec = std::vector<dynamic::SelectFrom>(
{to_select_from<typename StmtTs::SelectFromTypes>(
_stmt.fields_, _stmt.from_, _stmt.joins_, _stmt.where_,
_stmt.limit_)...});
_stmt.limit_, _stmt.offset_)...});
return Ref<std::vector<dynamic::SelectFrom>>::make(std::move(vec));
},
_stmts);