diff --git a/include/sqlpp11/avg.h b/include/sqlpp11/avg.h index 9a4aa642..1c7913d3 100644 --- a/include/sqlpp11/avg.h +++ b/include/sqlpp11/avg.h @@ -60,6 +60,7 @@ namespace sqlpp { using _traits = make_traits; using _nodes = detail::type_vector; + using _is_aggregate_expression = std::true_type; static_assert(is_noop::value or std::is_same::value, "avg() used with flag other than 'distinct'"); diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index 31353d21..6c50c599 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -62,6 +62,7 @@ namespace sqlpp using _traits = make_traits; using _nodes = detail::type_vector; + using _is_aggregate_expression = std::true_type; using _can_be_null = std::false_type; static_assert(is_noop::value or std::is_same::value, diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h index 7bd4c296..df168583 100644 --- a/include/sqlpp11/group_by.h +++ b/include/sqlpp11/group_by.h @@ -75,6 +75,9 @@ namespace sqlpp using _nodes = detail::type_vector; using _is_dynamic = is_database; + using _provided_aggregates = typename std::conditional<_is_dynamic::value, + detail::type_set<>, + detail::make_type_set_t>::type; // Data using _data_t = group_by_data_t; diff --git a/include/sqlpp11/logic.h b/include/sqlpp11/logic.h index 14f2e638..cff498c0 100644 --- a/include/sqlpp11/logic.h +++ b/include/sqlpp11/logic.h @@ -39,14 +39,14 @@ namespace sqlpp // see http://lists.boost.org/Archives/boost/2014/05/212946.php :-) template - using all_t = std::is_same, logic_helper<(B, true)...>>; + using all_t = std::is_same, logic_helper<(B or true)...>>; template using any_t = - std::integral_constant, logic_helper<(B, false)...>>::value>; + std::integral_constant, logic_helper<(B and false)...>>::value>; template - using none_t = std::is_same, logic_helper<(B, false)...>>; + using none_t = std::is_same, logic_helper<(B or false)...>>; template struct not_impl; diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index 48091ed1..27792def 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -59,6 +59,7 @@ namespace sqlpp { using _traits = make_traits, tag::is_expression, tag::is_selectable>; using _nodes = detail::type_vector; + using _is_aggregate_expression = std::true_type; using _auto_alias_t = max_alias_t; diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index 50f884bb..ea398289 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -59,6 +59,7 @@ namespace sqlpp { using _traits = make_traits, tag::is_expression, tag::is_selectable>; using _nodes = detail::type_vector; + using _is_aggregate_expression = std::true_type; using _auto_alias_t = min_alias_t; diff --git a/include/sqlpp11/select_column_list.h b/include/sqlpp11/select_column_list.h index 5322c103..7a90bdef 100644 --- a/include/sqlpp11/select_column_list.h +++ b/include/sqlpp11/select_column_list.h @@ -168,6 +168,17 @@ namespace sqlpp } }; + struct assert_aggregates_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "not all columns are made of aggregates, despite group_by or similar"); + } + }; + // SELECTED COLUMNS template struct select_column_list_t @@ -262,10 +273,16 @@ namespace sqlpp return t.selected_columns; } - using _consistency_check = + using _column_check = typename std::conditional::value, consistent_t, assert_no_unknown_tables_in_selected_columns_t>::type; + + using _aggregate_check = typename std::conditional::value, + consistent_t, + assert_aggregates_t>::type; + + using _consistency_check = detail::get_first_if; }; // Result methods diff --git a/include/sqlpp11/statement.h b/include/sqlpp11/statement.h index cf4e5c9d..b8e48769 100644 --- a/include/sqlpp11/statement.h +++ b/include/sqlpp11/statement.h @@ -103,12 +103,18 @@ namespace sqlpp using _all_provided_tables = detail::make_joined_set_t...>; using _all_provided_outer_tables = detail::make_joined_set_t...>; using _all_extra_tables = detail::make_joined_set_t...>; + using _all_provided_aggregates = detail::make_joined_set_t...>; using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>; template using _no_unknown_tables = detail::is_subset_of, _known_tables>; + template + using _no_unknown_aggregates = + logic::any_t<_all_provided_aggregates::size::value == 0, + logic::all_t::value...>::value>; + template