mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 12:51:13 +08:00
more tests and more clarity for group_by
This commit is contained in:
parent
843e39b3d0
commit
fc0632e0b0
@ -85,6 +85,11 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Table, typename ColumnSpec>
|
||||
struct is_group_by_column<column_t<Table, ColumnSpec>> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Table, typename ColumnSpec>
|
||||
struct value_type_of<column_t<Table, ColumnSpec>>
|
||||
{
|
||||
|
@ -30,15 +30,16 @@
|
||||
#include <sqlpp11/core/logic.h>
|
||||
#include <sqlpp11/core/query/policy_update.h>
|
||||
#include <sqlpp11/core/type_traits.h>
|
||||
#include <sqlpp11/core/group_by_column.h>
|
||||
#include <tuple>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
// GROUP BY DATA
|
||||
template <typename... Expressions>
|
||||
template <typename... Columns>
|
||||
struct group_by_data_t
|
||||
{
|
||||
group_by_data_t(Expressions... expressions) : _expressions(expressions...)
|
||||
group_by_data_t(Columns... columns) : _columns(columns...)
|
||||
{
|
||||
}
|
||||
|
||||
@ -48,7 +49,7 @@ namespace sqlpp
|
||||
group_by_data_t& operator=(group_by_data_t&&) = default;
|
||||
~group_by_data_t() = default;
|
||||
|
||||
std::tuple<Expressions...> _expressions;
|
||||
std::tuple<Columns...> _columns;
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||
@ -56,13 +57,13 @@ namespace sqlpp
|
||||
"at least one group-by expression requires a table which is otherwise not known in the statement");
|
||||
|
||||
// GROUP BY
|
||||
template <typename... Expressions>
|
||||
template <typename... Columns>
|
||||
struct group_by_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, tag::is_group_by>;
|
||||
using _nodes = detail::type_vector<Expressions...>;
|
||||
using _nodes = detail::type_vector<Columns...>;
|
||||
|
||||
using _data_t = group_by_data_t<Expressions...>;
|
||||
using _data_t = group_by_data_t<Columns...>;
|
||||
|
||||
// Base template to be inherited by the statement
|
||||
template <typename Policies>
|
||||
@ -80,22 +81,22 @@ namespace sqlpp
|
||||
};
|
||||
};
|
||||
|
||||
template <typename... Expressions>
|
||||
struct known_aggregate_expressions_of<group_by_t<Expressions...>>
|
||||
template <typename... Columns>
|
||||
struct known_aggregate_columns_of<group_by_t<Columns...>>
|
||||
{
|
||||
using type = detail::type_vector<Expressions...>;
|
||||
using type = detail::type_vector<Columns...>;
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_group_by_args_have_values_t, "all arguments for group_by() must have values");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_group_by_args_are_columns_t, "all arguments for group_by() must be columns");
|
||||
|
||||
template <typename... Exprs>
|
||||
template <typename... Columns>
|
||||
struct check_group_by
|
||||
{
|
||||
using type = static_combined_check_t<
|
||||
static_check_t<logic::all_t<has_value_type<Exprs>::value...>::value, assert_group_by_args_have_values_t>>;
|
||||
static_check_t<logic::all_t<is_group_by_column<Columns>::value...>::value, assert_group_by_args_are_columns_t>>;
|
||||
};
|
||||
template <typename... Exprs>
|
||||
using check_group_by_t = typename check_group_by<Exprs...>::type;
|
||||
template <typename... Columns>
|
||||
using check_group_by_t = typename check_group_by<Columns...>::type;
|
||||
|
||||
// NO GROUP BY YET
|
||||
struct no_group_by_t
|
||||
@ -122,44 +123,43 @@ namespace sqlpp
|
||||
|
||||
using _consistency_check = consistent_t;
|
||||
|
||||
#warning: Arguments should not be constants and not contain aggregate functions
|
||||
template <typename... Expressions>
|
||||
auto group_by(Expressions... expressions) const
|
||||
-> _new_statement_t<check_group_by_t<Expressions...>, group_by_t<Expressions...>>
|
||||
template <typename... Columns>
|
||||
auto group_by(Columns... columns) const
|
||||
-> _new_statement_t<check_group_by_t<remove_dynamic_t<Columns>...>, group_by_t<Columns...>>
|
||||
{
|
||||
static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
|
||||
static_assert(sizeof...(Columns), "at least one column required in group_by()");
|
||||
|
||||
return _group_by_impl(check_group_by_t<Expressions...>{}, expressions...);
|
||||
return _group_by_impl(check_group_by_t<Columns...>{}, columns...);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Check, typename... Expressions>
|
||||
auto _group_by_impl(Check, Expressions... expressions) const -> inconsistent<Check>;
|
||||
template <typename Check, typename... Columns>
|
||||
auto _group_by_impl(Check, Columns... columns) const -> inconsistent<Check>;
|
||||
|
||||
template <typename... Expressions>
|
||||
auto _group_by_impl(consistent_t /*unused*/, Expressions... expressions) const
|
||||
-> _new_statement_t<consistent_t, group_by_t<Expressions...>>
|
||||
template <typename... Columns>
|
||||
auto _group_by_impl(consistent_t /*unused*/, Columns... columns) const
|
||||
-> _new_statement_t<consistent_t, group_by_t<Columns...>>
|
||||
{
|
||||
static_assert(not detail::has_duplicates<Expressions...>::value,
|
||||
static_assert(not detail::has_duplicates<Columns...>::value,
|
||||
"at least one duplicate argument detected in group_by()");
|
||||
|
||||
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||
group_by_data_t<Expressions...>{expressions...}};
|
||||
group_by_data_t<Columns...>{columns...}};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Interpreters
|
||||
template <typename Context, typename... Expressions>
|
||||
auto to_sql_string(Context& context, const group_by_data_t<Expressions...>& t) -> std::string
|
||||
template <typename Context, typename... Columns>
|
||||
auto to_sql_string(Context& context, const group_by_data_t<Columns...>& t) -> std::string
|
||||
{
|
||||
return " GROUP BY " + interpret_tuple(t._expressions, ',', context);
|
||||
return " GROUP BY " + interpret_tuple(t._columns, ',', context);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
auto group_by(T&&... t) -> decltype(statement_t<no_group_by_t>().group_by(std::forward<T>(t)...))
|
||||
auto group_by(T... t) -> decltype(statement_t<no_group_by_t>().group_by(std::move(t)...))
|
||||
{
|
||||
return statement_t<no_group_by_t>().group_by(std::forward<T>(t)...);
|
||||
return statement_t<no_group_by_t>().group_by(std::move(t)...);
|
||||
}
|
||||
|
||||
} // namespace sqlpp
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sqlpp11/core/query/result_row.h>
|
||||
#include <sqlpp11/core/clause/select_as.h>
|
||||
#include <sqlpp11/core/clause/select_column_traits.h>
|
||||
#include <sqlpp11/core/group_by_column.h>
|
||||
#include <sqlpp11/core/basic/table.h>
|
||||
#include <tuple>
|
||||
|
||||
|
73
include/sqlpp11/core/group_by_column.h
Normal file
73
include/sqlpp11/core/group_by_column.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, 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 <sqlpp11/core/type_traits/group_by_column.h>
|
||||
#include <sqlpp11/core/type_traits/value_type.h>
|
||||
#include <sqlpp11/core/operator/enable_as.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
// `group_by` takes columns as parameters.
|
||||
// If you really, really want to, you can pass something else, but you have to tell the library that you are really certain by wrapping it in `declare_group_by_column`.
|
||||
|
||||
template <typename Expr>
|
||||
struct group_by_column : public enable_as<group_by_column<Expr>>
|
||||
{
|
||||
group_by_column(Expr expr) : _expr(std::move(expr)) {}
|
||||
group_by_column(const group_by_column&) = default;
|
||||
group_by_column(group_by_column&&) = default;
|
||||
group_by_column& operator=(const group_by_column&) = default;
|
||||
group_by_column& operator=(group_by_column&&) = default;
|
||||
~group_by_column() = default;
|
||||
|
||||
Expr _expr;
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct is_group_by_column<group_by_column<Expr>> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
struct value_type_of<group_by_column<Expr>> : public value_type_of<Expr>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Expr>
|
||||
using check_declare_group_by_column_args = ::sqlpp::enable_if_t<has_value_type<Expr>::value and not is_group_by_column<Expr>::value>;
|
||||
|
||||
template <typename Expr, typename = check_declare_group_by_column_args<Expr>>
|
||||
auto declare_group_by_column(Expr expr) -> group_by_column<Expr>
|
||||
{
|
||||
return {std::move(expr)};
|
||||
}
|
||||
|
||||
#warning Add tests
|
||||
|
||||
} // namespace sqlpp11
|
||||
|
@ -273,6 +273,12 @@ namespace sqlpp
|
||||
using type = typename detail::type_vector<Policies...>;
|
||||
};
|
||||
|
||||
template <typename... Policies>
|
||||
struct known_aggregate_columns_of<statement_t<Policies...>>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<known_aggregate_columns_of_t<Policies>...>;
|
||||
};
|
||||
|
||||
template <typename... Policies>
|
||||
struct requires_parentheses<statement_t<Policies...>> : public std::true_type {};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013-2017, Roland Bock, Aaron Bishop
|
||||
* Copyright (c) 2013, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,13 +26,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include <sqlpp11/core/chrono.h>
|
||||
#include <sqlpp11/core/name/name_tag.h>
|
||||
#include <sqlpp11/core/compat/optional.h>
|
||||
#include <sqlpp11/core/compat/string_view.h>
|
||||
@ -44,55 +42,13 @@
|
||||
#include <sqlpp11/core/detail/type_set.h>
|
||||
#include <sqlpp11/core/detail/get_first.h>
|
||||
#include <sqlpp11/core/type_traits/aggregates.h>
|
||||
#include <sqlpp11/core/type_traits/group_by_column.h>
|
||||
#include <sqlpp11/core/type_traits/nodes_of.h>
|
||||
#include <sqlpp11/core/type_traits/optional.h>
|
||||
#include <sqlpp11/core/type_traits/value_type.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename T>
|
||||
struct is_optional : public std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<::sqlpp::optional<T>> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_optional<::sqlpp::nullopt_t> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_optional
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_optional<::sqlpp::optional<T>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_optional_t = typename remove_optional<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct force_optional
|
||||
{
|
||||
using type = ::sqlpp::optional<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct force_optional<::sqlpp::optional<T>>
|
||||
{
|
||||
using type = ::sqlpp::optional<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using force_optional_t = typename force_optional<T>::type;
|
||||
|
||||
template <typename T>
|
||||
const T& get_value(const T& t)
|
||||
{
|
||||
@ -117,26 +73,6 @@ namespace sqlpp
|
||||
return t.has_value();
|
||||
}
|
||||
|
||||
struct no_value_t;
|
||||
|
||||
template <typename T>
|
||||
struct value_type_of
|
||||
{
|
||||
using type = no_value_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using value_type_of_t = typename value_type_of<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct value_type_of<::sqlpp::optional<T>>
|
||||
{
|
||||
using type = sqlpp::force_optional_t<value_type_of_t<remove_optional_t<T>>>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_value_type : public std::integral_constant<bool, not std::is_same<value_type_of_t<T>, no_value_t>::value> {};
|
||||
|
||||
template <typename T>
|
||||
struct has_default : public std::false_type
|
||||
{
|
||||
@ -153,186 +89,6 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
//
|
||||
struct boolean{};
|
||||
template<>
|
||||
struct value_type_of<boolean> { using type = boolean; };
|
||||
template<>
|
||||
struct value_type_of<bool> { using type = boolean; };
|
||||
|
||||
struct integral{};
|
||||
template<>
|
||||
struct value_type_of<integral> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int8_t> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int16_t> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int32_t> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int64_t> { using type = integral; };
|
||||
|
||||
struct unsigned_integral{};
|
||||
template<>
|
||||
struct value_type_of<unsigned_integral> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint8_t> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint16_t> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint32_t> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint64_t> { using type = unsigned_integral; };
|
||||
|
||||
struct floating_point{};
|
||||
template<>
|
||||
struct value_type_of<floating_point> { using type = floating_point; };
|
||||
template<>
|
||||
struct value_type_of<float> { using type = floating_point; };
|
||||
template<>
|
||||
struct value_type_of<double> { using type = floating_point; };
|
||||
template<>
|
||||
struct value_type_of<long double> { using type = floating_point; };
|
||||
|
||||
struct text{};
|
||||
template <>
|
||||
struct value_type_of<text> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<char> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<const char*> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<std::string> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<::sqlpp::string_view> { using type = text; };
|
||||
|
||||
struct blob{};
|
||||
template <>
|
||||
struct value_type_of<blob> { using type = blob; };
|
||||
template <std::size_t N>
|
||||
struct value_type_of<std::array<std::uint8_t, N>> { using type = blob; };
|
||||
template <>
|
||||
struct value_type_of<std::vector<std::uint8_t>> { using type = blob; };
|
||||
template <>
|
||||
struct value_type_of<::sqlpp::span<std::uint8_t>> { using type = blob; };
|
||||
|
||||
struct day_point{};
|
||||
template <>
|
||||
struct value_type_of<day_point> { using type = day_point; };
|
||||
template <>
|
||||
struct value_type_of<std::chrono::time_point<std::chrono::system_clock, sqlpp::chrono::days>> { using type = day_point; };
|
||||
|
||||
struct time_of_day{};
|
||||
template <>
|
||||
struct value_type_of<time_of_day> { using type = time_of_day; };
|
||||
template <typename Rep, typename Period>
|
||||
struct value_type_of<std::chrono::duration<Rep, Period>> { using type = time_of_day; };
|
||||
|
||||
struct time_point{};
|
||||
template <>
|
||||
struct value_type_of<time_point> { using type = time_point; };
|
||||
template <typename Period>
|
||||
struct value_type_of<std::chrono::time_point<std::chrono::system_clock, Period>> { using type = time_point; };
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_boolean : public std::is_same<remove_optional_t<value_type_of_t<T>>, boolean>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_boolean<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_integral : public std::is_same<remove_optional_t<value_type_of_t<T>>, integral>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_integral<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_unsigned_integral : public std::is_same<remove_optional_t<value_type_of_t<T>>, unsigned_integral>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_unsigned_integral<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_floating_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, floating_point>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_floating_point<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
// A generic numeric type which could be (unsigned) integral or floating point.
|
||||
struct numeric{};
|
||||
template <typename T>
|
||||
struct is_numeric
|
||||
: public std::integral_constant<bool,
|
||||
is_boolean<T>::value or is_integral<T>::value or is_unsigned_integral<T>::value or
|
||||
is_floating_point<T>::value or
|
||||
std::is_same<remove_optional_t<value_type_of_t<T>>, numeric>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_numeric<::sqlpp::nullopt_t> : public std::true_type{};
|
||||
|
||||
template <typename T>
|
||||
struct is_text : public std::is_same<remove_optional_t<value_type_of_t<T>>, text>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_text<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_blob : public std::is_same<remove_optional_t<value_type_of_t<T>>, blob>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_blob<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_day_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, day_point>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_day_point<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_time_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, time_point>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_time_point<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_day_or_time_point : public std::integral_constant<bool, is_day_point<T>::value or is_time_point<T>::value> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_time_of_day : public std::is_same<remove_optional_t<value_type_of_t<T>>, time_of_day>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_time_of_day<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename L, typename R>
|
||||
struct values_are_comparable
|
||||
: public std::integral_constant<bool,
|
||||
@ -579,6 +335,7 @@ namespace sqlpp
|
||||
;
|
||||
};
|
||||
|
||||
#warning: This should go away
|
||||
namespace detail
|
||||
{
|
||||
template <typename KnownAggregates, typename T, typename Leaf = void>
|
||||
|
@ -34,7 +34,7 @@ namespace sqlpp
|
||||
{
|
||||
// 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).
|
||||
// Non-aggregates are columns (unless they are aggregate columns).
|
||||
// Constant values are neutral.
|
||||
|
||||
template <typename T>
|
||||
@ -60,23 +60,23 @@ namespace sqlpp
|
||||
{
|
||||
};
|
||||
|
||||
// Obtain known aggregate expressions, i.e. GROUP BY columns.
|
||||
// Obtain known aggregate columns, i.e. GROUP BY columns.
|
||||
template <typename T>
|
||||
struct known_aggregate_expressions_of
|
||||
struct known_aggregate_columns_of
|
||||
{
|
||||
using type = detail::type_vector<>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using known_aggregate_expressions_of_t = typename known_aggregate_expressions_of<T>::type;
|
||||
using known_aggregate_columns_of_t = typename known_aggregate_columns_of<T>::type;
|
||||
|
||||
// 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>
|
||||
// @KnownAggregateColumns: type_vector as obtained through known_aggregate_columns_of_t
|
||||
template <typename KnownAggregateColumns, typename T>
|
||||
struct is_aggregate_expression
|
||||
: public std::integral_constant<bool,
|
||||
is_aggregate_function<T>::value or
|
||||
KnownAggregateExpressions::template contains<T>::value>
|
||||
KnownAggregateColumns::template contains<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
|
46
include/sqlpp11/core/type_traits/group_by_column.h
Normal file
46
include/sqlpp11/core/type_traits/group_by_column.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, 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 <sqlpp11/core/detail/type_vector.h>
|
||||
#include <sqlpp11/core/type_traits/value_type.h>
|
||||
#include <sqlpp11/core/logic.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
// `group_by` takes columns as parameters.
|
||||
// If you really, really want to, you can pass something else, but you have to tell the library that you are really certain by wrapping it in `declare_group_by_column`.
|
||||
|
||||
template <typename T>
|
||||
struct is_group_by_column : public std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
#warning Add tests
|
||||
|
||||
} // namespace sqlpp11
|
||||
|
79
include/sqlpp11/core/type_traits/optional.h
Normal file
79
include/sqlpp11/core/type_traits/optional.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, 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 <sqlpp11/core/compat/optional.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename T>
|
||||
struct is_optional : public std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<::sqlpp::optional<T>> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_optional<::sqlpp::nullopt_t> : public std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_optional
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_optional<::sqlpp::optional<T>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_optional_t = typename remove_optional<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct force_optional
|
||||
{
|
||||
using type = ::sqlpp::optional<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct force_optional<::sqlpp::optional<T>>
|
||||
{
|
||||
using type = ::sqlpp::optional<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using force_optional_t = typename force_optional<T>::type;
|
||||
|
||||
|
||||
}
|
237
include/sqlpp11/core/type_traits/value_type.h
Normal file
237
include/sqlpp11/core/type_traits/value_type.h
Normal file
@ -0,0 +1,237 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, 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 <cstdint>
|
||||
|
||||
#include <sqlpp11/core/chrono.h>
|
||||
#include <sqlpp11/core/compat/optional.h>
|
||||
#include <sqlpp11/core/type_traits/optional.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
struct no_value_t;
|
||||
|
||||
template <typename T>
|
||||
struct value_type_of
|
||||
{
|
||||
using type = no_value_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using value_type_of_t = typename value_type_of<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct value_type_of<::sqlpp::optional<T>>
|
||||
{
|
||||
using type = sqlpp::optional<value_type_of_t<remove_optional_t<T>>>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_value_type : public std::integral_constant<bool, not std::is_same<value_type_of_t<T>, no_value_t>::value> {};
|
||||
|
||||
struct boolean{};
|
||||
template<>
|
||||
struct value_type_of<boolean> { using type = boolean; };
|
||||
template<>
|
||||
struct value_type_of<bool> { using type = boolean; };
|
||||
|
||||
struct integral{};
|
||||
template<>
|
||||
struct value_type_of<integral> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int8_t> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int16_t> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int32_t> { using type = integral; };
|
||||
template<>
|
||||
struct value_type_of<int64_t> { using type = integral; };
|
||||
|
||||
struct unsigned_integral{};
|
||||
template<>
|
||||
struct value_type_of<unsigned_integral> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint8_t> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint16_t> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint32_t> { using type = unsigned_integral; };
|
||||
template<>
|
||||
struct value_type_of<uint64_t> { using type = unsigned_integral; };
|
||||
|
||||
struct floating_point{};
|
||||
template<>
|
||||
struct value_type_of<floating_point> { using type = floating_point; };
|
||||
template<>
|
||||
struct value_type_of<float> { using type = floating_point; };
|
||||
template<>
|
||||
struct value_type_of<double> { using type = floating_point; };
|
||||
template<>
|
||||
struct value_type_of<long double> { using type = floating_point; };
|
||||
|
||||
struct text{};
|
||||
template <>
|
||||
struct value_type_of<text> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<char> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<const char*> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<std::string> { using type = text; };
|
||||
template <>
|
||||
struct value_type_of<::sqlpp::string_view> { using type = text; };
|
||||
|
||||
struct blob{};
|
||||
template <>
|
||||
struct value_type_of<blob> { using type = blob; };
|
||||
template <std::size_t N>
|
||||
struct value_type_of<std::array<std::uint8_t, N>> { using type = blob; };
|
||||
template <>
|
||||
struct value_type_of<std::vector<std::uint8_t>> { using type = blob; };
|
||||
template <>
|
||||
struct value_type_of<::sqlpp::span<std::uint8_t>> { using type = blob; };
|
||||
|
||||
struct day_point{};
|
||||
template <>
|
||||
struct value_type_of<day_point> { using type = day_point; };
|
||||
template <>
|
||||
struct value_type_of<std::chrono::time_point<std::chrono::system_clock, sqlpp::chrono::days>> { using type = day_point; };
|
||||
|
||||
struct time_of_day{};
|
||||
template <>
|
||||
struct value_type_of<time_of_day> { using type = time_of_day; };
|
||||
template <typename Rep, typename Period>
|
||||
struct value_type_of<std::chrono::duration<Rep, Period>> { using type = time_of_day; };
|
||||
|
||||
struct time_point{};
|
||||
template <>
|
||||
struct value_type_of<time_point> { using type = time_point; };
|
||||
template <typename Period>
|
||||
struct value_type_of<std::chrono::time_point<std::chrono::system_clock, Period>> { using type = time_point; };
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_boolean : public std::is_same<remove_optional_t<value_type_of_t<T>>, boolean>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_boolean<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_integral : public std::is_same<remove_optional_t<value_type_of_t<T>>, integral>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_integral<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_unsigned_integral : public std::is_same<remove_optional_t<value_type_of_t<T>>, unsigned_integral>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_unsigned_integral<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_floating_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, floating_point>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_floating_point<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
// A generic numeric type which could be (unsigned) integral or floating point.
|
||||
struct numeric{};
|
||||
template <typename T>
|
||||
struct is_numeric
|
||||
: public std::integral_constant<bool,
|
||||
is_boolean<T>::value or is_integral<T>::value or is_unsigned_integral<T>::value or
|
||||
is_floating_point<T>::value or
|
||||
std::is_same<remove_optional_t<value_type_of_t<T>>, numeric>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_numeric<::sqlpp::nullopt_t> : public std::true_type{};
|
||||
|
||||
template <typename T>
|
||||
struct is_text : public std::is_same<remove_optional_t<value_type_of_t<T>>, text>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_text<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_blob : public std::is_same<remove_optional_t<value_type_of_t<T>>, blob>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_blob<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_day_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, day_point>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_day_point<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_time_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, time_point>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_time_point<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_day_or_time_point : public std::integral_constant<bool, is_day_point<T>::value or is_time_point<T>::value> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_time_of_day : public std::is_same<remove_optional_t<value_type_of_t<T>>, time_of_day>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_time_of_day<::sqlpp::nullopt_t> : public std::true_type {
|
||||
};
|
||||
|
||||
}
|
@ -37,4 +37,5 @@ test_compile(value)
|
||||
|
||||
add_subdirectory(aggregate_function)
|
||||
add_subdirectory(operator)
|
||||
add_subdirectory(clause)
|
||||
add_subdirectory(type_traits)
|
||||
|
33
tests/core/types/clause/CMakeLists.txt
Normal file
33
tests/core/types/clause/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2024, 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.
|
||||
|
||||
function(test_compile name)
|
||||
set(target sqlpp11_core_types_clause_${name})
|
||||
add_executable(${target} ${name}.cpp)
|
||||
target_link_libraries(${target} PRIVATE sqlpp11::sqlpp11 sqlpp11_testing)
|
||||
endfunction()
|
||||
|
||||
test_compile(group_by)
|
||||
test_compile(select_columns)
|
||||
|
68
tests/core/types/clause/group_by.cpp
Normal file
68
tests/core/types/clause/group_by.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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 "Sample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename... T>
|
||||
auto known_aggregate_columns_as_expected(T... t)
|
||||
-> std::is_same<sqlpp::known_aggregate_columns_of_t<decltype(group_by(std::move(t)...))>,
|
||||
sqlpp::detail::type_vector<T...>>;
|
||||
}
|
||||
|
||||
void test_group_by()
|
||||
{
|
||||
auto v = sqlpp::value(17);
|
||||
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(decltype(known_aggregate_columns_as_expected(col_int))::value, "");
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(col_int, col_txt))::value, "");
|
||||
|
||||
// Dynamic columns are listed as dynamic columns in known_aggregate_columns_of_t, since they need to be dynamic in
|
||||
// select, too, and we need to check that there.
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(dynamic(true, col_int)))::value, "");
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(col_int, dynamic(true, col_txt)))::value, "");
|
||||
|
||||
// Declared columns are listed as declared columns in known_aggregate_columns_of_t, since they need to be declared in
|
||||
// select, too, and we need to check that there.
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(declare_group_by_column(v)))::value, "");
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(col_int, declare_group_by_column(v)))::value, "");
|
||||
|
||||
// Declared columns can be dynamic, too.
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(dynamic(true, declare_group_by_column(v))))::value, "");
|
||||
static_assert(decltype(known_aggregate_columns_as_expected(col_int, dynamic(true, declare_group_by_column(v))))::value, "");
|
||||
|
||||
#warning: need to test dynamic and declared columns in select, too
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
void test_group_by();
|
||||
}
|
||||
|
53
tests/core/types/clause/select_columns.cpp
Normal file
53
tests/core/types/clause/select_columns.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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 "Sample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
SQLPP_ALIAS_PROVIDER(cheese);
|
||||
}
|
||||
|
||||
void test_select_columns()
|
||||
{
|
||||
auto v = sqlpp::value(17);
|
||||
auto col_int = test::TabFoo{}.id;
|
||||
auto col_txt = test::TabFoo{}.textNnD;
|
||||
|
||||
select_columns(col_int);
|
||||
select_columns(dynamic(true, col_int));
|
||||
select_columns(as(declare_group_by_column(v), cheese));
|
||||
select_columns(dynamic(true, declare_group_by_column(v)).as(cheese));
|
||||
|
||||
#warning: add actual tests here
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
void test_group_by();
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function(test_compile name)
|
||||
set(target sqlpp11_core_types_operator_${name})
|
||||
set(target sqlpp11_core_types_type_traits_${name})
|
||||
add_executable(${target} ${name}.cpp)
|
||||
target_link_libraries(${target} PRIVATE sqlpp11::sqlpp11 sqlpp11_testing)
|
||||
endfunction()
|
||||
|
Loading…
Reference in New Issue
Block a user