mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
more tests and more clarity for aggregates
This commit is contained in:
parent
dc38a81a8c
commit
843e39b3d0
@ -27,6 +27,16 @@ The library now offers `is_distinct_from` and `is_not_distinct_from` which safel
|
|||||||
# Selecting aggregate functions
|
# Selecting aggregate functions
|
||||||
The automatic name for selected aggregate functions drops the `_`.
|
The automatic name for selected aggregate functions drops the `_`.
|
||||||
|
|
||||||
|
# Aggregates and non-aggregates
|
||||||
|
They must not be mixed in a select.
|
||||||
|
|
||||||
|
`group_by` accepts columns only (there is an escape hatch: `group_by_column`)
|
||||||
|
`select` requires either
|
||||||
|
- all selected columns are aggregate expressions (either an aggregate function or a group by column), or
|
||||||
|
- no selected column is an aggregate expression
|
||||||
|
|
||||||
|
If group_by is specified in the select, then all columns have to be aggregate expressions.
|
||||||
|
|
||||||
# Dynamic queries
|
# Dynamic queries
|
||||||
We don't always have a completely fixed structure for our queries. For instance, there might columns that we only want to select under certain circumstances. In version 1.0, this was handled by dynamic queries. Now we introduce conditional query parts that may or may not be used at runtime:
|
We don't always have a completely fixed structure for our queries. For instance, there might columns that we only want to select under certain circumstances. In version 1.0, this was handled by dynamic queries. Now we introduce conditional query parts that may or may not be used at runtime:
|
||||||
|
|
||||||
|
@ -63,12 +63,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct contains_aggregate_function<avg_t<Flag, Expr>> : public std::true_type
|
struct is_aggregate_function<avg_t<Flag, Expr>> : public std::true_type
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
|
||||||
struct contains_non_aggregate<avg_t<Flag, Expr>> : public std::false_type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,12 +63,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct contains_aggregate_function<count_t<Flag, Expr>> : public std::true_type
|
struct is_aggregate_function<count_t<Flag, Expr>> : public std::true_type
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
|
||||||
struct contains_non_aggregate<count_t<Flag, Expr>> : public std::false_type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,12 +62,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct contains_aggregate_function<max_t<Flag, Expr>> : public std::true_type
|
struct is_aggregate_function<max_t<Flag, Expr>> : public std::true_type
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
|
||||||
struct contains_non_aggregate<max_t<Flag, Expr>> : public std::false_type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,12 +62,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct contains_aggregate_function<min_t<Flag, Expr>> : public std::true_type
|
struct is_aggregate_function<min_t<Flag, Expr>> : public std::true_type
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
|
||||||
struct contains_non_aggregate<min_t<Flag, Expr>> : public std::false_type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ namespace sqlpp
|
|||||||
struct value_type_of<over_t<Expr>>: public value_type_of<Expr> {};
|
struct value_type_of<over_t<Expr>>: public value_type_of<Expr> {};
|
||||||
|
|
||||||
template<typename Expr>
|
template<typename Expr>
|
||||||
using check_over_args = ::sqlpp::enable_if_t<contains_aggregate_function<Expr>::value>;
|
using check_over_args = ::sqlpp::enable_if_t<is_aggregate_function<Expr>::value>;
|
||||||
|
|
||||||
template <typename Context, typename Expr>
|
template <typename Context, typename Expr>
|
||||||
auto to_sql_string(Context& context, const over_t<Expr>& t) -> std::string
|
auto to_sql_string(Context& context, const over_t<Expr>& t) -> std::string
|
||||||
|
@ -62,12 +62,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct contains_aggregate_function<sum_t<Flag, Expr>> : public std::true_type
|
struct is_aggregate_function<sum_t<Flag, Expr>> : public std::true_type
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Flag, typename Expr>
|
|
||||||
struct contains_non_aggregate<sum_t<Flag, Expr>> : public std::false_type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,9 +85,6 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Table, typename ColumnSpec>
|
|
||||||
struct contains_non_aggregate<column_t<Table, ColumnSpec>> : public std::true_type {};
|
|
||||||
|
|
||||||
template<typename Table, typename ColumnSpec>
|
template<typename Table, typename ColumnSpec>
|
||||||
struct value_type_of<column_t<Table, ColumnSpec>>
|
struct value_type_of<column_t<Table, ColumnSpec>>
|
||||||
{
|
{
|
||||||
|
@ -62,8 +62,6 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<no_value_t, tag::is_group_by>;
|
using _traits = make_traits<no_value_t, tag::is_group_by>;
|
||||||
using _nodes = detail::type_vector<Expressions...>;
|
using _nodes = detail::type_vector<Expressions...>;
|
||||||
|
|
||||||
using _provided_aggregates = detail::make_type_set_t<Expressions...>;
|
|
||||||
|
|
||||||
using _data_t = group_by_data_t<Expressions...>;
|
using _data_t = group_by_data_t<Expressions...>;
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
@ -82,8 +80,14 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_group_by_args_have_values_t,
|
template <typename... Expressions>
|
||||||
"all arguments for group_by() must have values");
|
struct known_aggregate_expressions_of<group_by_t<Expressions...>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector<Expressions...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_group_by_args_have_values_t, "all arguments for group_by() must have values");
|
||||||
|
|
||||||
template <typename... Exprs>
|
template <typename... Exprs>
|
||||||
struct check_group_by
|
struct check_group_by
|
||||||
{
|
{
|
||||||
@ -118,6 +122,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
|
|
||||||
|
#warning: Arguments should not be constants and not contain aggregate functions
|
||||||
template <typename... Expressions>
|
template <typename... Expressions>
|
||||||
auto group_by(Expressions... expressions) const
|
auto group_by(Expressions... expressions) const
|
||||||
-> _new_statement_t<check_group_by_t<Expressions...>, group_by_t<Expressions...>>
|
-> _new_statement_t<check_group_by_t<Expressions...>, group_by_t<Expressions...>>
|
||||||
|
@ -55,8 +55,9 @@ namespace sqlpp
|
|||||||
// No value_type_of or name_tag_of defined for dynamic_t, to prevent its usage outside of select columns.
|
// No value_type_of or name_tag_of defined for dynamic_t, to prevent its usage outside of select columns.
|
||||||
|
|
||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
struct nodes_of<dynamic_t<Expr>> : public nodes_of<Expr>
|
struct nodes_of<dynamic_t<Expr>>
|
||||||
{
|
{
|
||||||
|
using type = Expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -32,47 +32,51 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// Finds calls to aggregate functions (avg, count, max, min, sum).
|
// We don't want to mix aggregate and non-aggregate expressions as the results are unspecified.
|
||||||
|
// Aggregates are either results of aggregate functions or GROUP BY columns.
|
||||||
|
// Non-aggregates are columns (unless they are aggregate expressions).
|
||||||
|
// Constant values are neutral.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct contains_aggregate_function : public std::integral_constant<bool, contains_aggregate_function<nodes_of_t<T>>::value>
|
struct is_aggregate_function : public std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// Finds calls to aggregate functions (avg, count, max, min, sum) in expressions.
|
||||||
|
// This is important as aggregated functions must not be nested.
|
||||||
|
template <typename T>
|
||||||
|
struct contains_aggregate_function
|
||||||
|
: public std::integral_constant<bool,
|
||||||
|
is_aggregate_function<T>::value or
|
||||||
|
contains_aggregate_function<nodes_of_t<T>>::value>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
struct contains_aggregate_function<detail::type_vector<T...>>
|
struct contains_aggregate_function<detail::type_vector<T...>>
|
||||||
: public std::integral_constant<bool, logic::any_t<contains_aggregate_function<T>::value...>::value>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// Finds group_by expression.
|
|
||||||
// @GroupByExpressions: type_vector
|
|
||||||
template <typename GroupByExpressions, typename T>
|
|
||||||
struct contains_aggregate_expression
|
|
||||||
: public std::integral_constant<bool,
|
|
||||||
GroupByExpressions::template contains<T>::value or
|
|
||||||
contains_aggregate_expression<GroupByExpressions, nodes_of_t<T>>::value>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename GroupByExpressions, typename... T>
|
|
||||||
struct contains_aggregate_expression<GroupByExpressions, detail::type_vector<T...>>
|
|
||||||
: public std::integral_constant<
|
: public std::integral_constant<
|
||||||
bool,
|
bool,
|
||||||
logic::any_t<(GroupByExpressions::template contains<T>::value or
|
logic::any_t<(is_aggregate_function<T>::value or contains_aggregate_function<T>::value)...>::value>
|
||||||
contains_aggregate_expression<GroupByExpressions, T>::value)...>::value>
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
// Finds columns.
|
// Obtain known aggregate expressions, i.e. GROUP BY columns.
|
||||||
// Note that explicit values like `value(7)` are compatible with both aggregate and non-aggregate.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct contains_non_aggregate : public std::integral_constant<bool, contains_non_aggregate<nodes_of_t<T>>::value>
|
struct known_aggregate_expressions_of
|
||||||
{
|
{
|
||||||
|
using type = detail::type_vector<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... T>
|
template <typename T>
|
||||||
struct contains_non_aggregate<detail::type_vector<T...>>
|
using known_aggregate_expressions_of_t = typename known_aggregate_expressions_of<T>::type;
|
||||||
: public std::integral_constant<bool, logic::any_t<contains_non_aggregate<T>::value...>::value>
|
|
||||||
|
// Checks if T is an aggregate expression (either an aggregate function or a known aggregate).
|
||||||
|
// @KnownAggregateExpressions: type_vector as obtained through known_aggregate_expressions_of_t
|
||||||
|
template <typename KnownAggregateExpressions, typename T>
|
||||||
|
struct is_aggregate_expression
|
||||||
|
: public std::integral_constant<bool,
|
||||||
|
is_aggregate_function<T>::value or
|
||||||
|
KnownAggregateExpressions::template contains<T>::value>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,6 +28,65 @@
|
|||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(cheese);
|
SQLPP_ALIAS_PROVIDER(cheese);
|
||||||
|
|
||||||
|
void test_is_aggregate_function()
|
||||||
|
{
|
||||||
|
auto v = sqlpp::value(17);
|
||||||
|
auto t = sqlpp::value("");
|
||||||
|
auto col_int = test::TabFoo{}.id;
|
||||||
|
auto col_txt = test::TabFoo{}.textNnD;
|
||||||
|
|
||||||
|
// Constant values are neutral and therefore considered neither aggregate and non-aggregate.
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(v)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(v + v)>::value, "");
|
||||||
|
|
||||||
|
// Columns are not aggregate functions
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(col_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(col_int + v)>::value, "");
|
||||||
|
|
||||||
|
// Normal functions of values or non-aggregates do not contain aggregate functions.
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(trim(t))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(trim(col_txt))>::value, "");
|
||||||
|
|
||||||
|
// Aggregate functions of non-aggregates and values are aggregate functions :-)
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(avg(v))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(count(v))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(min(v))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(max(v))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(sum(v))>::value, "");
|
||||||
|
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(avg(col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(count(col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(min(col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(max(col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(sum(col_int))>::value, "");
|
||||||
|
|
||||||
|
static_assert(sqlpp::is_aggregate_function<decltype(max(trim(col_txt)))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(trim(upper(lower(max(col_txt)))) + trim(col_txt))>::value, "");
|
||||||
|
|
||||||
|
// Expressions containing aggregate functions are not aggregate functions.
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(avg(col_int) + v)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(count(col_int) + v)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(min(col_int) + v)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(max(col_int) + v)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(sum(col_int) + v)>::value, "");
|
||||||
|
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(trim(max(col_txt)))>::value, "");
|
||||||
|
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(avg(col_int) + col_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(count(col_int) + col_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(min(col_int) + col_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(max(col_int) + col_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(sum(col_int) + col_int)>::value, "");
|
||||||
|
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(max(trim(col_txt)) + trim(col_txt))>::value, "");
|
||||||
|
|
||||||
|
// Clauses do not expose aggregates functions.
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(where(col_int > v))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(select_columns(v.as(cheese), col_int))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(select_columns(max(col_int), v.as(cheese), col_int))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_function<decltype(select_columns(dynamic(true, max(col_int)), v.as(cheese), col_int))>::value, "");
|
||||||
|
}
|
||||||
|
|
||||||
void test_contains_aggregate_function()
|
void test_contains_aggregate_function()
|
||||||
{
|
{
|
||||||
auto v = sqlpp::value(17);
|
auto v = sqlpp::value(17);
|
||||||
@ -35,7 +94,7 @@ void test_contains_aggregate_function()
|
|||||||
auto col_int = test::TabFoo{}.id;
|
auto col_int = test::TabFoo{}.id;
|
||||||
auto col_txt = test::TabFoo{}.textNnD;
|
auto col_txt = test::TabFoo{}.textNnD;
|
||||||
|
|
||||||
// Values are aggregate neutral and therefore considered neither aggregate and non-aggregate context.
|
// Constant values are neutral and therefore considered neither aggregate and non-aggregate.
|
||||||
static_assert(not sqlpp::contains_aggregate_function<decltype(v)>::value, "");
|
static_assert(not sqlpp::contains_aggregate_function<decltype(v)>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_function<decltype(v + v)>::value, "");
|
static_assert(not sqlpp::contains_aggregate_function<decltype(v + v)>::value, "");
|
||||||
|
|
||||||
@ -48,11 +107,11 @@ void test_contains_aggregate_function()
|
|||||||
static_assert(not sqlpp::contains_aggregate_function<decltype(trim(col_txt))>::value, "");
|
static_assert(not sqlpp::contains_aggregate_function<decltype(trim(col_txt))>::value, "");
|
||||||
|
|
||||||
// Aggregate functions of non-aggregates and values contain aggregate functions.
|
// Aggregate functions of non-aggregates and values contain aggregate functions.
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(avg(v))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(avg(v))>::value, "");
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(count(v))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(count(v))>::value, "");
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(min(v))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(min(v))>::value, "");
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(max(v))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(max(v))>::value, "");
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(sum(v))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(sum(v))>::value, "");
|
||||||
|
|
||||||
static_assert(sqlpp::contains_aggregate_function<decltype(avg(col_int))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(avg(col_int))>::value, "");
|
||||||
static_assert(sqlpp::contains_aggregate_function<decltype(count(col_int))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(count(col_int))>::value, "");
|
||||||
@ -79,140 +138,70 @@ void test_contains_aggregate_function()
|
|||||||
static_assert(sqlpp::contains_aggregate_function<decltype(trim(upper(lower(max(col_txt)))) + trim(col_txt))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(trim(upper(lower(max(col_txt)))) + trim(col_txt))>::value, "");
|
||||||
static_assert(sqlpp::contains_aggregate_function<decltype(max(trim(col_txt)) + trim(col_txt))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(max(trim(col_txt)) + trim(col_txt))>::value, "");
|
||||||
|
|
||||||
// Clauses expose non-aggregates (probably irrelevant)
|
// Clauses expose non-aggregates.
|
||||||
static_assert(not sqlpp::contains_aggregate_function<decltype(where(col_int > v))>::value, "");
|
static_assert(not sqlpp::contains_aggregate_function<decltype(where(col_int > v))>::value, "");
|
||||||
|
static_assert(not sqlpp::contains_aggregate_function<decltype(select_columns(v.as(cheese), col_int))>::value, "");
|
||||||
static_assert(sqlpp::contains_aggregate_function<decltype(select_columns(max(col_int), v.as(cheese), col_int))>::value, "");
|
static_assert(sqlpp::contains_aggregate_function<decltype(select_columns(max(col_int), v.as(cheese), col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::contains_aggregate_function<decltype(select_columns(dynamic(true, max(col_int)), v.as(cheese), col_int))>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_contains_aggregate_expression()
|
void test_is_aggregate_expression()
|
||||||
{
|
{
|
||||||
auto v_not_null = sqlpp::value(17);
|
auto v_not_null = sqlpp::value(17);
|
||||||
|
|
||||||
auto v = sqlpp::value(17);
|
auto v = sqlpp::value(17);
|
||||||
auto t = sqlpp::value("");
|
auto t = sqlpp::value("");
|
||||||
auto col_int = test::TabFoo{}.id;
|
auto agg_int = test::TabFoo{}.id;
|
||||||
auto col_txt = test::TabFoo{}.textNnD;
|
auto agg_txt = test::TabFoo{}.textNnD;
|
||||||
|
|
||||||
|
auto col_int = test::TabBar{}.id;
|
||||||
|
auto col_txt = test::TabBar{}.textN;
|
||||||
|
|
||||||
using known_aggregates = sqlpp::detail::type_vector<decltype(v), decltype(col_txt), decltype(col_int + v)>;
|
|
||||||
using unknown = sqlpp::detail::type_vector<>;
|
using unknown = sqlpp::detail::type_vector<>;
|
||||||
|
using known_aggregates = sqlpp::detail::type_vector<decltype(agg_txt), decltype(agg_int)>;
|
||||||
|
|
||||||
// ...
|
// If there are no known aggregate expressions, then only aggregate functions will be found.
|
||||||
static_assert(sqlpp::contains_aggregate_expression<known_aggregates, decltype(v)>::value, "");
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(v)>::value, "");
|
||||||
static_assert(sqlpp::contains_aggregate_expression<known_aggregates, decltype(v + v)>::value, "");
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(v + v)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(col_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(col_txt)>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_expression<unknown, decltype(count(col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_expression<unknown, decltype(count(col_txt))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_expression<unknown, decltype(max(v))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_expression<unknown, decltype(max(col_int))>::value, "");
|
||||||
|
static_assert(sqlpp::is_aggregate_expression<unknown, decltype(max(col_txt))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(dynamic(true, max(v)))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(dynamic(true, max(col_int)))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<unknown, decltype(dynamic(true, max(col_txt)))>::value, "");
|
||||||
|
|
||||||
// ...
|
// Known aggregate expressions are detected as such.
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<unknown, decltype(v)>::value, "");
|
static_assert(sqlpp::is_aggregate_expression<known_aggregates, decltype(agg_int)>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<unknown, decltype(v + v)>::value, "");
|
static_assert(sqlpp::is_aggregate_expression<known_aggregates, decltype(agg_txt)>::value, "");
|
||||||
|
|
||||||
#warning: activate
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(dynamic(true, agg_int))>::value, "");
|
||||||
#if 0
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(dynamic(true, agg_txt))>::value, "");
|
||||||
// Columns are non-aggregates.
|
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<decltype(col_int)>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<decltype(col_int + v)>::value, "");
|
|
||||||
|
|
||||||
// Normal expressions of values or non-aggregates do not contain aggregate functions.
|
// Known aggregate expressions are not detected as such in expressions.
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<decltype(trim(t))>::value, "");
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(agg_int + 17)>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<decltype(trim(col_txt))>::value, "");
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(17 + agg_int)>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(agg_txt.like("%"))>::value, "");
|
||||||
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype((agg_int + v).between(1, 10))>::value, "");
|
||||||
|
|
||||||
// Aggregate expressions of non-aggregates contain aggregate functions.
|
// Known aggregate expressions are not detected as such in aggregate functions.
|
||||||
static_assert(not sqlpp::contains_aggregate_expressions<decltype(avg(v))>::value, "");
|
static_assert(sqlpp::is_aggregate_expression<known_aggregates, decltype(max(agg_int + 17))>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_expressions<decltype(count(v))>::value, "");
|
static_assert(sqlpp::is_aggregate_expression<known_aggregates, decltype(max(17 + agg_int))>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_expressions<decltype(min(v))>::value, "");
|
static_assert(sqlpp::is_aggregate_expression<known_aggregates, decltype(count(agg_txt.like("%")))>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_expressions<decltype(max(v))>::value, "");
|
static_assert(sqlpp::is_aggregate_expression<known_aggregates, decltype(count((agg_int + v).between(1, 10)))>::value, "");
|
||||||
static_assert(not sqlpp::contains_aggregate_expressions<decltype(sum(v))>::value, "");
|
|
||||||
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(avg(col_int))>::value, "");
|
// Known aggregate expressions are not exposed as such by clauses.
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(count(col_int))>::value, "");
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(select(agg_txt))>::value, "");
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(min(col_int))>::value, "");
|
static_assert(not sqlpp::is_aggregate_expression<known_aggregates, decltype(select(agg_int))>::value, "");
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(max(col_int))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(sum(col_int))>::value, "");
|
|
||||||
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(avg(col_int) + v)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(count(col_int) + v)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(min(col_int) + v)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(max(col_int) + v)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(sum(col_int) + v)>::value, "");
|
|
||||||
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(trim(max(col_txt)))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(max(trim(col_txt)))>::value, "");
|
|
||||||
|
|
||||||
// Expressions of aggregate expressions and non-aggregates contain aggregate functions.
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(avg(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(count(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(min(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(max(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(sum(col_int) + col_int)>::value, "");
|
|
||||||
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(trim(upper(lower(max(col_txt)))) + trim(col_txt))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(max(trim(col_txt)) + trim(col_txt))>::value, "");
|
|
||||||
|
|
||||||
// Clauses expose non-aggregates (probably irrelevant)
|
|
||||||
static_assert(not sqlpp::contains_aggregate_expression<decltype(where(col_int > v))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_aggregate_expression<decltype(select_columns(max(col_int), v.as(cheese), col_int))>::value, "");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_contains_non_aggregate()
|
|
||||||
{
|
|
||||||
auto v = sqlpp::value(17);
|
|
||||||
auto t = sqlpp::value("");
|
|
||||||
auto col_int = test::TabFoo{}.id;
|
|
||||||
auto col_txt = test::TabFoo{}.textNnD;
|
|
||||||
|
|
||||||
// Values are aggregate neutral and therefore considered neither aggregate and non-aggregate context.
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(v)>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(v + v)>::value, "");
|
|
||||||
|
|
||||||
// Columns are non-aggregates.
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(col_int + v)>::value, "");
|
|
||||||
|
|
||||||
// Functions can contain non-aggregates.
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(trim(t))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(trim(col_txt))>::value, "");
|
|
||||||
|
|
||||||
// Aggregate functions of non-aggregates and values are aggregate functions.
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(avg(v))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(count(v))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(min(v))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(max(v))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(sum(v))>::value, "");
|
|
||||||
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(avg(col_int))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(count(col_int))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(min(col_int))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(max(col_int))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(sum(col_int))>::value, "");
|
|
||||||
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(avg(col_int) + v)>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(count(col_int) + v)>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(min(col_int) + v)>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(max(col_int) + v)>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(sum(col_int) + v)>::value, "");
|
|
||||||
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(trim(max(col_txt)))>::value, "");
|
|
||||||
static_assert(not sqlpp::contains_non_aggregate<decltype(max(trim(col_txt)))>::value, "");
|
|
||||||
|
|
||||||
// Expressions of aggregate functions and non-aggregates contain non-aggregates.
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(avg(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(count(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(min(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(max(col_int) + col_int)>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(sum(col_int) + col_int)>::value, "");
|
|
||||||
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(trim(max(col_txt)) + trim(col_txt))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(max(trim(col_txt)) + trim(col_txt))>::value, "");
|
|
||||||
|
|
||||||
// Clauses expose non-aggregates (probably irrelevant)
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(where(col_int > v))>::value, "");
|
|
||||||
static_assert(sqlpp::contains_non_aggregate<decltype(select_columns(max(col_int), v.as(cheese), col_int))>::value, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
void test_is_aggregate_function();
|
||||||
void test_contains_aggregate_function();
|
void test_contains_aggregate_function();
|
||||||
void test_contains_aggregate_expression();
|
void test_is_aggregate_expression();
|
||||||
void test_contains_non_aggregate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user