mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Allow parameter in having clause, see #443
Disallow mixing aggregate and non-aggregate columns in select, too.
This commit is contained in:
parent
1e7f4b98c7
commit
f5be4095ae
@ -39,7 +39,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<blob, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<blob, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = std::vector<std::uint8_t>;
|
using _value_t = std::vector<std::uint8_t>;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = bool;
|
using _value_t = bool;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<day_point, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<day_point, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = ::sqlpp::chrono::day_point;
|
using _value_t = ::sqlpp::chrono::day_point;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<floating_point, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<floating_point, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = double;
|
using _value_t = double;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<integral, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<integral, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = int64_t;
|
using _value_t = int64_t;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<text, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<text, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = std::string;
|
using _value_t = std::string;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<time_of_day, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<time_of_day, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = std::chrono::microseconds;
|
using _value_t = std::chrono::microseconds;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<time_point, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<time_point, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = std::chrono::time_point<std::chrono::system_clock, Period>;
|
using _value_t = std::chrono::time_point<std::chrono::system_clock, Period>;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<unsigned_integral, tag::is_expression, tag::is_wrapped_value>;
|
using _traits = make_traits<unsigned_integral, tag::is_expression, tag::is_wrapped_value>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _is_aggregate_expression = std::true_type;
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _value_t = uint64_t;
|
using _value_t = uint64_t;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ namespace sqlpp
|
|||||||
assert_having_no_unknown_tables_t,
|
assert_having_no_unknown_tables_t,
|
||||||
"at least one having-expression requires a table which is otherwise not known in the statement");
|
"at least one having-expression requires a table which is otherwise not known in the statement");
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_having_no_non_aggregates_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_having_all_aggregates_t,
|
||||||
"having expression not built out of aggregate expressions");
|
"having expression not built out of aggregate expressions");
|
||||||
|
|
||||||
// HAVING
|
// HAVING
|
||||||
@ -142,9 +142,9 @@ namespace sqlpp
|
|||||||
consistent_t,
|
consistent_t,
|
||||||
assert_having_no_unknown_tables_t>::type;
|
assert_having_no_unknown_tables_t>::type;
|
||||||
|
|
||||||
using _aggregate_check = typename std::conditional<Policies::template _no_non_aggregates<Expression>::value,
|
using _aggregate_check = typename std::conditional<Policies::template _all_aggregates<Expression>::value,
|
||||||
consistent_t,
|
consistent_t,
|
||||||
assert_having_no_non_aggregates_t>::type;
|
assert_having_all_aggregates_t>::type;
|
||||||
|
|
||||||
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _table_check, _aggregate_check>;
|
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _table_check, _aggregate_check>;
|
||||||
};
|
};
|
||||||
|
@ -44,6 +44,7 @@ namespace sqlpp
|
|||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _parameters = detail::type_vector<parameter_t>;
|
using _parameters = detail::type_vector<parameter_t>;
|
||||||
using _can_be_null = std::true_type;
|
using _can_be_null = std::true_type;
|
||||||
|
using _is_literal_expression = std::true_type;
|
||||||
|
|
||||||
using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
|
using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
|
||||||
|
|
||||||
|
@ -92,6 +92,9 @@ namespace sqlpp
|
|||||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||||
assert_no_unknown_tables_in_selected_columns_t,
|
assert_no_unknown_tables_in_selected_columns_t,
|
||||||
"at least one selected column requires a table which is otherwise not known in the statement");
|
"at least one selected column requires a table which is otherwise not known in the statement");
|
||||||
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_no_aggregate_mix_t,
|
||||||
|
"selected columns contain a mix of aggregates and non-aggregates");
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_no_unknown_aggregates_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_no_unknown_aggregates_t,
|
||||||
"not all selected columns are made of aggregates, despite group_by or similar");
|
"not all selected columns are made of aggregates, despite group_by or similar");
|
||||||
|
|
||||||
@ -196,11 +199,19 @@ namespace sqlpp
|
|||||||
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,
|
using _unknown_aggregate_check =
|
||||||
|
typename std::conditional<Policies::template _no_unknown_aggregates<Columns...>::value,
|
||||||
consistent_t,
|
consistent_t,
|
||||||
assert_no_unknown_aggregates_t>::type;
|
assert_no_unknown_aggregates_t>::type;
|
||||||
|
|
||||||
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _table_check, _aggregate_check>;
|
using _no_aggregate_mix_check =
|
||||||
|
typename std::conditional<Policies::template _all_aggregates<Columns...>::value ||
|
||||||
|
Policies::template _no_aggregates<Columns...>::value,
|
||||||
|
consistent_t,
|
||||||
|
assert_no_aggregate_mix_t>::type;
|
||||||
|
|
||||||
|
using _consistency_check = detail::
|
||||||
|
get_first_if<is_inconsistent_t, consistent_t, _table_check, _no_aggregate_mix_check, _unknown_aggregate_check>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Result methods
|
// Result methods
|
||||||
|
@ -99,9 +99,13 @@ namespace sqlpp
|
|||||||
Expressions>::type::value...>::value>;
|
Expressions>::type::value...>::value>;
|
||||||
|
|
||||||
template <typename... Expressions>
|
template <typename... Expressions>
|
||||||
using _no_non_aggregates = logic::any_t<logic::all_t<
|
using _all_aggregates = logic::any_t<logic::all_t<
|
||||||
detail::is_aggregate_expression_impl<_all_provided_aggregates, Expressions>::type::value...>::value>;
|
detail::is_aggregate_expression_impl<_all_provided_aggregates, Expressions>::type::value...>::value>;
|
||||||
|
|
||||||
|
template <typename... Expressions>
|
||||||
|
using _no_aggregates = logic::any_t<logic::all_t<
|
||||||
|
detail::is_non_aggregate_expression_impl<_all_provided_aggregates, Expressions>::type::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...>;
|
||||||
|
|
||||||
|
@ -63,7 +63,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
using _nodes = detail::type_vector<Expr>;
|
using _nodes = detail::type_vector<Expr>;
|
||||||
using _can_be_null = can_be_null_t<Expr>;
|
using _can_be_null = can_be_null_t<Expr>;
|
||||||
using _is_aggregate_expression = std::false_type;
|
|
||||||
|
|
||||||
using _auto_alias_t = trim_alias_t;
|
using _auto_alias_t = trim_alias_t;
|
||||||
|
|
||||||
|
@ -320,9 +320,17 @@ namespace sqlpp
|
|||||||
struct is_aggregate_expression_impl<
|
struct is_aggregate_expression_impl<
|
||||||
KnownAggregates,
|
KnownAggregates,
|
||||||
T,
|
T,
|
||||||
typename std::enable_if<std::is_class<typename T::_is_aggregate_expression>::value>::type>
|
typename std::enable_if<T::_is_aggregate_expression::value>::type>
|
||||||
{
|
{
|
||||||
using type = typename T::_is_aggregate_expression;
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
template <typename KnownAggregates, typename T>
|
||||||
|
struct is_aggregate_expression_impl<
|
||||||
|
KnownAggregates,
|
||||||
|
T,
|
||||||
|
typename std::enable_if<T::_is_literal_expression::value>::type>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
};
|
};
|
||||||
template <typename KnownAggregates, typename T>
|
template <typename KnownAggregates, typename T>
|
||||||
struct is_aggregate_expression_impl<KnownAggregates,
|
struct is_aggregate_expression_impl<KnownAggregates,
|
||||||
@ -341,6 +349,48 @@ namespace sqlpp
|
|||||||
template <typename KnownAggregates, typename T>
|
template <typename KnownAggregates, typename T>
|
||||||
using is_aggregate_expression_t = typename detail::is_aggregate_expression_impl<KnownAggregates, T>::type;
|
using is_aggregate_expression_t = typename detail::is_aggregate_expression_impl<KnownAggregates, T>::type;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename KnownAggregates, typename T, typename Leaf = void>
|
||||||
|
struct is_non_aggregate_expression_impl
|
||||||
|
{
|
||||||
|
using type = typename is_non_aggregate_expression_impl<KnownAggregates, nodes_of<T>>::type;
|
||||||
|
};
|
||||||
|
template <typename KnownAggregates, typename T>
|
||||||
|
struct is_non_aggregate_expression_impl<
|
||||||
|
KnownAggregates,
|
||||||
|
T,
|
||||||
|
typename std::enable_if<T::_is_aggregate_expression::value>::type>
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
template <typename KnownAggregates, typename T>
|
||||||
|
struct is_non_aggregate_expression_impl<
|
||||||
|
KnownAggregates,
|
||||||
|
T,
|
||||||
|
typename std::enable_if<T::_is_literal_expression::value>::type>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
template <typename KnownAggregates, typename T>
|
||||||
|
struct is_non_aggregate_expression_impl<KnownAggregates,
|
||||||
|
T,
|
||||||
|
typename std::enable_if<detail::is_element_of<T, KnownAggregates>::value>::type>
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
template <typename KnownAggregates, typename... Nodes>
|
||||||
|
struct is_non_aggregate_expression_impl<KnownAggregates, type_vector<Nodes...>, void>
|
||||||
|
{
|
||||||
|
using type =
|
||||||
|
logic::any_t<sizeof...(Nodes) == 0,
|
||||||
|
logic::all_t<sizeof...(Nodes) != 0,
|
||||||
|
is_non_aggregate_expression_impl<KnownAggregates, Nodes>::type::value...>::value>;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
template <typename KnownAggregates, typename T>
|
||||||
|
using is_non_aggregate_expression_t = typename detail::is_non_aggregate_expression_impl<KnownAggregates, T>::type;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename T, typename Leaf = void>
|
template <typename T, typename Leaf = void>
|
||||||
|
@ -109,9 +109,13 @@ namespace
|
|||||||
void static_group_by_nok()
|
void static_group_by_nok()
|
||||||
{
|
{
|
||||||
static_run_check<sqlpp::assert_no_unknown_aggregates_t>(select(t.beta).from(t).unconditionally().group_by(t.alpha));
|
static_run_check<sqlpp::assert_no_unknown_aggregates_t>(select(t.beta).from(t).unconditionally().group_by(t.alpha));
|
||||||
static_run_check<sqlpp::assert_no_unknown_aggregates_t>(
|
static_run_check<sqlpp::assert_no_aggregate_mix_t>(
|
||||||
|
select(t.alpha, t.delta).from(t).unconditionally().group_by(t.alpha));
|
||||||
|
static_run_check<sqlpp::assert_no_aggregate_mix_t>(
|
||||||
|
select(t.alpha, t.beta).from(t).unconditionally().group_by(t.alpha));
|
||||||
|
static_run_check<sqlpp::assert_no_aggregate_mix_t>(
|
||||||
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha));
|
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha));
|
||||||
static_run_check<sqlpp::assert_no_unknown_aggregates_t>(
|
static_run_check<sqlpp::assert_no_aggregate_mix_t>(
|
||||||
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
|
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,10 +158,11 @@ namespace
|
|||||||
|
|
||||||
// OK
|
// OK
|
||||||
static_consistency_check<sqlpp::consistent_t>(select_without_group_by, avg(t.alpha) > 17);
|
static_consistency_check<sqlpp::consistent_t>(select_without_group_by, avg(t.alpha) > 17);
|
||||||
|
static_consistency_check<sqlpp::consistent_t>(select_without_group_by, avg(t.alpha) > parameter(t.alpha));
|
||||||
|
|
||||||
// Try non aggregate
|
// Try non aggregate
|
||||||
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_without_group_by, t.alpha > 17);
|
static_consistency_check<sqlpp::assert_having_all_aggregates_t>(select_without_group_by, t.alpha > 17);
|
||||||
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_without_group_by,
|
static_consistency_check<sqlpp::assert_having_all_aggregates_t>(select_without_group_by,
|
||||||
count(t.alpha) > 3 and t.alpha > 17);
|
count(t.alpha) > 3 and t.alpha > 17);
|
||||||
|
|
||||||
// Try foreign table
|
// Try foreign table
|
||||||
@ -175,8 +176,8 @@ namespace
|
|||||||
static_consistency_check<sqlpp::consistent_t>(select_with_group_by, count(t.alpha) > 3 and t.alpha > 17);
|
static_consistency_check<sqlpp::consistent_t>(select_with_group_by, count(t.alpha) > 3 and t.alpha > 17);
|
||||||
|
|
||||||
// Try non aggregate
|
// Try non aggregate
|
||||||
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_with_group_by, t.beta > "17");
|
static_consistency_check<sqlpp::assert_having_all_aggregates_t>(select_with_group_by, t.beta > "17");
|
||||||
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_with_group_by,
|
static_consistency_check<sqlpp::assert_having_all_aggregates_t>(select_with_group_by,
|
||||||
count(t.beta) > 3 and t.beta > "17");
|
count(t.beta) > 3 and t.beta > "17");
|
||||||
|
|
||||||
// Try foreign table
|
// Try foreign table
|
||||||
|
@ -159,7 +159,7 @@ int Select(int, char*[])
|
|||||||
.dynamic_where()
|
.dynamic_where()
|
||||||
.dynamic_group_by(t.alpha)
|
.dynamic_group_by(t.alpha)
|
||||||
.dynamic_order_by()
|
.dynamic_order_by()
|
||||||
.dynamic_having(sum(t.alpha) > 17)
|
.dynamic_having(sum(t.alpha) > parameter(t.delta))
|
||||||
.dynamic_limit()
|
.dynamic_limit()
|
||||||
.dynamic_offset();
|
.dynamic_offset();
|
||||||
s.select_flags.add(sqlpp::distinct);
|
s.select_flags.add(sqlpp::distinct);
|
||||||
@ -172,7 +172,7 @@ int Select(int, char*[])
|
|||||||
s.group_by.add(t.beta);
|
s.group_by.add(t.beta);
|
||||||
s.order_by.add(t.beta.asc());
|
s.order_by.add(t.beta.asc());
|
||||||
s.order_by.add(t.delta.order(sqlpp::sort_type::desc));
|
s.order_by.add(t.delta.order(sqlpp::sort_type::desc));
|
||||||
for (const auto& row : db(s))
|
for (const auto& row : db(db.prepare(s)))
|
||||||
{
|
{
|
||||||
int64_t a = row.alpha;
|
int64_t a = row.alpha;
|
||||||
std::cout << a << std::endl;
|
std::cout << a << std::endl;
|
||||||
|
@ -35,8 +35,6 @@
|
|||||||
#include "TabFoo.h"
|
#include "TabFoo.h"
|
||||||
#include "make_test_connection.h"
|
#include "make_test_connection.h"
|
||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(returnVal)
|
|
||||||
|
|
||||||
namespace sql = sqlpp::postgresql;
|
namespace sql = sqlpp::postgresql;
|
||||||
int Exceptions(int, char*[])
|
int Exceptions(int, char*[])
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user