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
2 changes: 1 addition & 1 deletion include/sqlgen/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct Read {
"You must assign at least one column to order by(...).");
return Read<Type, WhereType,
transpilation::order_by_t<
transpilation::value_t<Type>,
transpilation::value_t<Type>, Nothing,
typename std::remove_cvref_t<ColTypes>::ColType...>,
LimitType>{.where_ = _r.where_};
}
Expand Down
15 changes: 10 additions & 5 deletions include/sqlgen/select_from.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,16 @@ struct SelectFrom {
"You cannot call to<...> before order_by(...).");
static_assert(sizeof...(ColTypes) != 0,
"You must assign at least one column to order_by.");
return SelectFrom<
StructType, AliasType, FieldsType, JoinsType, WhereType, GroupByType,
transpilation::order_by_t<
StructType, typename std::remove_cvref_t<ColTypes>::ColType...>,
LimitType, ToType>{

using TableTupleType =
transpilation::table_tuple_t<StructType, AliasType, JoinsType>;

using NewOrderByType = transpilation::order_by_t<
TableTupleType, GroupByType,
typename std::remove_cvref_t<ColTypes>::ColType...>;

return SelectFrom<StructType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, NewOrderByType, LimitType, ToType>{
.fields_ = _s.fields_, .joins_ = _s.joins_, .where_ = _s.where_};
}

Expand Down
32 changes: 16 additions & 16 deletions include/sqlgen/transpilation/check_aggregations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@

namespace sqlgen::transpilation {

template <class StructType, class FieldsType, class GroupByType>
template <class TablesType, class FieldsType, class GroupByType>
struct CheckAggregation;

/// Case: No aggregation, no group by.
template <class StructType, class... FieldTypes>
requires(true && ... && !MakeField<StructType, FieldTypes>::is_aggregation)
struct CheckAggregation<StructType, rfl::Tuple<FieldTypes...>, Nothing> {
template <class TablesType, class... FieldTypes>
requires(true && ... && !MakeField<TablesType, FieldTypes>::is_aggregation)
struct CheckAggregation<TablesType, rfl::Tuple<FieldTypes...>, Nothing> {
static constexpr bool value = true;
};

/// Case: At least one aggregation, no group by.
template <class StructType, class... FieldTypes>
requires(false || ... || MakeField<StructType, FieldTypes>::is_aggregation)
struct CheckAggregation<StructType, rfl::Tuple<FieldTypes...>, Nothing> {
template <class TablesType, class... FieldTypes>
requires(false || ... || MakeField<TablesType, FieldTypes>::is_aggregation)
struct CheckAggregation<TablesType, rfl::Tuple<FieldTypes...>, Nothing> {
static constexpr bool value =
(true && ... &&
(MakeField<StructType, FieldTypes>::is_aggregation ||
!MakeField<StructType, FieldTypes>::is_column));
(MakeField<TablesType, FieldTypes>::is_aggregation ||
!MakeField<TablesType, FieldTypes>::is_column));
static_assert(
value,
"If any column is aggregated and there is no GROUP BY, then all columns "
"must be aggregated.");
};

/// Case: There is a group by.
template <class StructType, class... FieldTypes, class... ColTypes>
struct CheckAggregation<StructType, rfl::Tuple<FieldTypes...>,
template <class TablesType, class... FieldTypes, class... ColTypes>
struct CheckAggregation<TablesType, rfl::Tuple<FieldTypes...>,
GroupBy<ColTypes...>> {
template <class F>
static constexpr bool included_in_group_by =
Expand All @@ -48,19 +48,19 @@ struct CheckAggregation<StructType, rfl::Tuple<FieldTypes...>,

static constexpr bool value =
(true && ... &&
(MakeField<StructType, FieldTypes>::is_aggregation ||
(!MakeField<StructType, FieldTypes>::is_column &&
!MakeField<StructType, FieldTypes>::is_operation) ||
(MakeField<TablesType, FieldTypes>::is_aggregation ||
(!MakeField<TablesType, FieldTypes>::is_column &&
!MakeField<TablesType, FieldTypes>::is_operation) ||
included_in_group_by<FieldTypes>));

static_assert(value,
"If there is a GROUP BY, then all columns "
"must either be aggregated or included inside the GROUP BY.");
};

template <class StructType, class FieldsType, class GroupByType>
template <class TablesType, class FieldsType, class GroupByType>
consteval bool check_aggregations() {
return CheckAggregation<std::remove_cvref_t<StructType>,
return CheckAggregation<std::remove_cvref_t<TablesType>,
std::remove_cvref_t<FieldsType>,
std::remove_cvref_t<GroupByType>>::value;
}
Expand Down
18 changes: 14 additions & 4 deletions include/sqlgen/transpilation/order_by_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Col.hpp"
#include "Desc.hpp"
#include "all_columns_exist.hpp"
#include "check_aggregations.hpp"

namespace sqlgen::transpilation {

Expand All @@ -31,17 +32,26 @@ struct OrderByWrapper<Desc<transpilation::Col<_name, _alias>>> {
template <class... WrapperTypes>
struct OrderBy {};

template <class T, class... ColTypes>
template <class TablesType, class GroupByType, class... ColTypes>
auto make_order_by() {
static_assert(
all_columns_exist<T, typename OrderByWrapper<ColTypes>::ColType...>(),
all_columns_exist<TablesType,
typename OrderByWrapper<ColTypes>::ColType...>(),
"A column in order_by does not exist.");
static_assert(
check_aggregations<
TablesType, rfl::Tuple<typename OrderByWrapper<ColTypes>::ColType...>,
GroupByType>(),
"The columns in the ORDER BY clause have not been properly "
"aggregated. Please refer to the stack trace for details.");

return OrderBy<OrderByWrapper<ColTypes>...>{};
}

template <class T, class... ColTypes>
template <class TablesType, class GroupByType, class... ColTypes>
using order_by_t = std::invoke_result_t<
decltype(make_order_by<T, typename ColTypes::ColType...>)>;
decltype(make_order_by<TablesType, GroupByType,
typename ColTypes::ColType...>)>;

} // namespace sqlgen::transpilation

Expand Down
2 changes: 1 addition & 1 deletion tests/postgres/test_joins_nested_grouped.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct Relationship {
sqlgen::PrimaryKey<uint32_t> child_id;
};

TEST(postgres, test_joins_nested) {
TEST(postgres, test_joins_nested_grouped) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Expand Down
Loading