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 _nodes = detail::type_vector<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = is_database<Database>;
|
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
|
// Data
|
||||||
using _data_t = group_by_data_t<Database, Expressions...>;
|
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
|
// SELECTED COLUMNS
|
||||||
template <typename Database, typename... Columns>
|
template <typename Database, typename... Columns>
|
||||||
struct select_column_list_t
|
struct select_column_list_t
|
||||||
@ -262,10 +273,16 @@ namespace sqlpp
|
|||||||
return t.selected_columns;
|
return t.selected_columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check =
|
using _column_check =
|
||||||
typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
|
typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
|
||||||
consistent_t,
|
consistent_t,
|
||||||
assert_no_unknown_tables_in_selected_columns_t>::type;
|
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
|
// Result methods
|
||||||
|
@ -103,12 +103,18 @@ namespace sqlpp
|
|||||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
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_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_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>;
|
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
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>
|
template <template <typename> class Predicate>
|
||||||
using any_t = logic::any_t<Predicate<Policies>::value...>;
|
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_tables)
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables)
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables)
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(extra_tables)
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(extra_tables)
|
||||||
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
|
||||||
|
|
||||||
#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \
|
#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \
|
||||||
namespace detail \
|
namespace detail \
|
||||||
@ -221,6 +222,38 @@ namespace sqlpp
|
|||||||
SQLPP_RECURSIVE_TRAIT_GENERATOR(can_be_null)
|
SQLPP_RECURSIVE_TRAIT_GENERATOR(can_be_null)
|
||||||
SQLPP_RECURSIVE_TRAIT_GENERATOR(contains_aggregate_function)
|
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
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename T, typename Leaf = void>
|
template <typename T, typename Leaf = void>
|
||||||
@ -259,6 +292,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _contains_aggregate_function = std::true_type;
|
using _contains_aggregate_function = std::true_type;
|
||||||
|
using _is_aggregate_expression = std::true_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename NameProvider, typename Member>
|
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 ()
|
endif ()
|
||||||
|
|
||||||
set(test_names
|
set(test_names
|
||||||
|
Aggregates
|
||||||
BooleanExpression
|
BooleanExpression
|
||||||
CustomQuery
|
CustomQuery
|
||||||
Interpret
|
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");
|
static_assert(sqlpp::is_boolean_t<decltype(select(r.a).from(r))>::value, "select(bool) has to be a bool");
|
||||||
auto s1 = sqlpp::select()
|
auto s1 = sqlpp::select()
|
||||||
.flags(sqlpp::distinct, sqlpp::straight_join)
|
.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)
|
.from(r, t, l)
|
||||||
.where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right))
|
.where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right))
|
||||||
.group_by(l.gamma, r.a)
|
.group_by(l.gamma, r.a)
|
||||||
|
Loading…
Reference in New Issue
Block a user