mirror of
https://github.com/getml/sqlgen.git
synced 2026-01-07 01:50:09 -06:00
Implement offset support (#102)
As per discussions in [1]. [1] https://github.com/getml/sqlgen/issues/100
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
14
include/sqlgen/dynamic/Offset.hpp
Normal file
14
include/sqlgen/dynamic/Offset.hpp
Normal 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
|
||||
@@ -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
14
include/sqlgen/offset.hpp
Normal 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
|
||||
@@ -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>
|
||||
|
||||
@@ -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_));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
12
include/sqlgen/transpilation/Offset.hpp
Normal file
12
include/sqlgen/transpilation/Offset.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
|
||||
30
include/sqlgen/transpilation/to_offset.hpp
Normal file
30
include/sqlgen/transpilation/to_offset.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user