mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Added check if all selected columns are aggregates if group_by is present
This commit is contained in:
parent
25ff700c01
commit
bd385f7377
@ -75,6 +75,9 @@ namespace sqlpp
|
||||
using _nodes = detail::type_vector<Expressions...>;
|
||||
|
||||
using _is_dynamic = is_database<Database>;
|
||||
using _provided_aggregates = typename std::conditional<_is_dynamic::value,
|
||||
detail::type_set<>,
|
||||
detail::make_type_set_t<Expressions...>>::type;
|
||||
|
||||
// Data
|
||||
using _data_t = group_by_data_t<Database, Expressions...>;
|
||||
|
@ -168,6 +168,17 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
struct assert_aggregates_t
|
||||
{
|
||||
using type = std::false_type;
|
||||
|
||||
template <typename T = void>
|
||||
static void _()
|
||||
{
|
||||
static_assert(wrong_t<T>::value, "not all columns are made of aggregates, despite group_by or similar");
|
||||
}
|
||||
};
|
||||
|
||||
// SELECTED COLUMNS
|
||||
template <typename Database, typename... Columns>
|
||||
struct select_column_list_t
|
||||
@ -262,10 +273,16 @@ namespace sqlpp
|
||||
return t.selected_columns;
|
||||
}
|
||||
|
||||
using _consistency_check =
|
||||
using _column_check =
|
||||
typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
|
||||
consistent_t,
|
||||
assert_no_unknown_tables_in_selected_columns_t>::type;
|
||||
|
||||
using _aggregate_check = typename std::conditional<Policies::template _no_unknown_aggregates<Columns...>::value,
|
||||
consistent_t,
|
||||
assert_aggregates_t>::type;
|
||||
|
||||
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _column_check, _aggregate_check>;
|
||||
};
|
||||
|
||||
// Result methods
|
||||
|
@ -103,12 +103,18 @@ namespace sqlpp
|
||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||
using _all_provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
|
||||
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||
using _all_provided_aggregates = detail::make_joined_set_t<provided_aggregates_of<Policies>...>;
|
||||
|
||||
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||
|
||||
template <typename Expression>
|
||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||
|
||||
template <typename... Expressions>
|
||||
using _no_unknown_aggregates =
|
||||
logic::any_t<_all_provided_aggregates::size::value == 0,
|
||||
logic::all_t<is_aggregate_expression_t<_all_provided_aggregates, Expressions>::value...>::value>;
|
||||
|
||||
template <template <typename> class Predicate>
|
||||
using any_t = logic::any_t<Predicate<Policies>::value...>;
|
||||
|
||||
|
@ -195,6 +195,7 @@ namespace sqlpp
|
||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_tables)
|
||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables)
|
||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(extra_tables)
|
||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
|
||||
|
||||
#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \
|
||||
namespace detail \
|
||||
@ -221,6 +222,38 @@ namespace sqlpp
|
||||
SQLPP_RECURSIVE_TRAIT_GENERATOR(can_be_null)
|
||||
SQLPP_RECURSIVE_TRAIT_GENERATOR(contains_aggregate_function)
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename KnownAggregates, typename T, typename Leaf = void>
|
||||
struct is_aggregate_expression_impl
|
||||
{
|
||||
using type = typename is_aggregate_expression_impl<KnownAggregates, typename T::_nodes>::type;
|
||||
};
|
||||
template <typename KnownAggregates, typename T>
|
||||
struct is_aggregate_expression_impl<
|
||||
KnownAggregates,
|
||||
T,
|
||||
typename std::enable_if<std::is_class<typename T::_is_aggregate_expression>::value>::type>
|
||||
{
|
||||
using type = typename T::_is_aggregate_expression;
|
||||
};
|
||||
template <typename KnownAggregates, typename T>
|
||||
struct is_aggregate_expression_impl<KnownAggregates,
|
||||
T,
|
||||
typename std::enable_if<detail::is_element_of<T, KnownAggregates>::value>::type>
|
||||
{
|
||||
using type = std::true_type;
|
||||
};
|
||||
template <typename KnownAggregates, typename... Nodes>
|
||||
struct is_aggregate_expression_impl<KnownAggregates, type_vector<Nodes...>, void>
|
||||
{
|
||||
using type =
|
||||
logic::all_t<sizeof...(Nodes) != 0, is_aggregate_expression_impl<KnownAggregates, Nodes>::type::value...>;
|
||||
};
|
||||
}
|
||||
template <typename KnownAggregates, typename T>
|
||||
using is_aggregate_expression_t = typename detail::is_aggregate_expression_impl<KnownAggregates, T>::type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, typename Leaf = void>
|
||||
@ -259,6 +292,7 @@ namespace sqlpp
|
||||
{
|
||||
using _nodes = detail::type_vector<>;
|
||||
using _contains_aggregate_function = std::true_type;
|
||||
using _is_aggregate_expression = std::true_type;
|
||||
};
|
||||
|
||||
template <typename NameProvider, typename Member>
|
||||
|
45
tests/Aggregates.cpp
Normal file
45
tests/Aggregates.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2015, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "Sample.h"
|
||||
#include "MockDb.h"
|
||||
#include <sqlpp11/alias_provider.h>
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/connection.h>
|
||||
|
||||
int Aggregates(int, char**)
|
||||
{
|
||||
MockDb db = {};
|
||||
MockDb::_serializer_context_t printer;
|
||||
|
||||
// test::TabFoo f;
|
||||
test::TabBar t;
|
||||
|
||||
db(select(t.alpha).from(t).where(true).group_by(t.alpha));
|
||||
|
||||
return 0;
|
||||
}
|
@ -30,6 +30,7 @@ target_compile_options(sqlpp11_testing INTERFACE -Wall -Wextra -pedantic)
|
||||
endif ()
|
||||
|
||||
set(test_names
|
||||
Aggregates
|
||||
BooleanExpression
|
||||
CustomQuery
|
||||
Interpret
|
||||
|
@ -375,7 +375,7 @@ int SelectType(int, char**)
|
||||
static_assert(sqlpp::is_boolean_t<decltype(select(r.a).from(r))>::value, "select(bool) has to be a bool");
|
||||
auto s1 = sqlpp::select()
|
||||
.flags(sqlpp::distinct, sqlpp::straight_join)
|
||||
.columns(l.alpha, l.beta, select(r.a).from(r))
|
||||
.columns(l.gamma, r.a)
|
||||
.from(r, t, l)
|
||||
.where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right))
|
||||
.group_by(l.gamma, r.a)
|
||||
|
Loading…
Reference in New Issue
Block a user