From fc0632e0b0e2cc900c519a0b1b7c73eba4406ec5 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Fri, 16 Aug 2024 14:15:08 +0200 Subject: [PATCH] more tests and more clarity for group_by --- include/sqlpp11/core/basic/column.h | 5 + include/sqlpp11/core/clause/group_by.h | 64 ++--- .../sqlpp11/core/clause/select_column_list.h | 1 + include/sqlpp11/core/group_by_column.h | 73 +++++ include/sqlpp11/core/query/statement.h | 6 + include/sqlpp11/core/type_traits.h | 253 +----------------- include/sqlpp11/core/type_traits/aggregates.h | 14 +- .../core/type_traits/group_by_column.h | 46 ++++ include/sqlpp11/core/type_traits/optional.h | 79 ++++++ include/sqlpp11/core/type_traits/value_type.h | 237 ++++++++++++++++ tests/core/types/CMakeLists.txt | 1 + tests/core/types/clause/CMakeLists.txt | 33 +++ tests/core/types/clause/group_by.cpp | 68 +++++ tests/core/types/clause/select_columns.cpp | 53 ++++ tests/core/types/type_traits/CMakeLists.txt | 2 +- 15 files changed, 647 insertions(+), 288 deletions(-) create mode 100644 include/sqlpp11/core/group_by_column.h create mode 100644 include/sqlpp11/core/type_traits/group_by_column.h create mode 100644 include/sqlpp11/core/type_traits/optional.h create mode 100644 include/sqlpp11/core/type_traits/value_type.h create mode 100644 tests/core/types/clause/CMakeLists.txt create mode 100644 tests/core/types/clause/group_by.cpp create mode 100644 tests/core/types/clause/select_columns.cpp diff --git a/include/sqlpp11/core/basic/column.h b/include/sqlpp11/core/basic/column.h index 626663d8..6f9f2463 100644 --- a/include/sqlpp11/core/basic/column.h +++ b/include/sqlpp11/core/basic/column.h @@ -85,6 +85,11 @@ namespace sqlpp } }; + template + struct is_group_by_column> : public std::true_type + { + }; + template struct value_type_of> { diff --git a/include/sqlpp11/core/clause/group_by.h b/include/sqlpp11/core/clause/group_by.h index 221e3cf7..de96ed34 100644 --- a/include/sqlpp11/core/clause/group_by.h +++ b/include/sqlpp11/core/clause/group_by.h @@ -30,15 +30,16 @@ #include #include #include +#include #include namespace sqlpp { // GROUP BY DATA - template + template 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; + std::tuple _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 + template struct group_by_t { using _traits = make_traits; - using _nodes = detail::type_vector; + using _nodes = detail::type_vector; - using _data_t = group_by_data_t; + using _data_t = group_by_data_t; // Base template to be inherited by the statement template @@ -80,22 +81,22 @@ namespace sqlpp }; }; - template - struct known_aggregate_expressions_of> + template + struct known_aggregate_columns_of> { - using type = detail::type_vector; + using type = detail::type_vector; }; - 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 + template struct check_group_by { using type = static_combined_check_t< - static_check_t::value...>::value, assert_group_by_args_have_values_t>>; + static_check_t::value...>::value, assert_group_by_args_are_columns_t>>; }; - template - using check_group_by_t = typename check_group_by::type; + template + using check_group_by_t = typename check_group_by::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 - auto group_by(Expressions... expressions) const - -> _new_statement_t, group_by_t> + template + auto group_by(Columns... columns) const + -> _new_statement_t...>, group_by_t> { - 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...); + return _group_by_impl(check_group_by_t{}, columns...); } private: - template - auto _group_by_impl(Check, Expressions... expressions) const -> inconsistent; + template + auto _group_by_impl(Check, Columns... columns) const -> inconsistent; - template - auto _group_by_impl(consistent_t /*unused*/, Expressions... expressions) const - -> _new_statement_t> + template + auto _group_by_impl(consistent_t /*unused*/, Columns... columns) const + -> _new_statement_t> { - static_assert(not detail::has_duplicates::value, + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); return {static_cast&>(*this), - group_by_data_t{expressions...}}; + group_by_data_t{columns...}}; } }; }; // Interpreters - template - auto to_sql_string(Context& context, const group_by_data_t& t) -> std::string + template + auto to_sql_string(Context& context, const group_by_data_t& t) -> std::string { - return " GROUP BY " + interpret_tuple(t._expressions, ',', context); + return " GROUP BY " + interpret_tuple(t._columns, ',', context); } template - auto group_by(T&&... t) -> decltype(statement_t().group_by(std::forward(t)...)) + auto group_by(T... t) -> decltype(statement_t().group_by(std::move(t)...)) { - return statement_t().group_by(std::forward(t)...); + return statement_t().group_by(std::move(t)...); } } // namespace sqlpp diff --git a/include/sqlpp11/core/clause/select_column_list.h b/include/sqlpp11/core/clause/select_column_list.h index 32b8f5ec..6f10a0ad 100644 --- a/include/sqlpp11/core/clause/select_column_list.h +++ b/include/sqlpp11/core/clause/select_column_list.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include diff --git a/include/sqlpp11/core/group_by_column.h b/include/sqlpp11/core/group_by_column.h new file mode 100644 index 00000000..efc48f53 --- /dev/null +++ b/include/sqlpp11/core/group_by_column.h @@ -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 +#include +#include + +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 + struct group_by_column : public enable_as> + { + 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 + struct is_group_by_column> : public std::true_type + { + }; + + template + struct value_type_of> : public value_type_of + { + }; + + template + using check_declare_group_by_column_args = ::sqlpp::enable_if_t::value and not is_group_by_column::value>; + +template > + auto declare_group_by_column(Expr expr) -> group_by_column + { + return {std::move(expr)}; + } + +#warning Add tests + +} // namespace sqlpp11 + diff --git a/include/sqlpp11/core/query/statement.h b/include/sqlpp11/core/query/statement.h index 102cfac6..7725a5b6 100644 --- a/include/sqlpp11/core/query/statement.h +++ b/include/sqlpp11/core/query/statement.h @@ -273,6 +273,12 @@ namespace sqlpp using type = typename detail::type_vector; }; + template + struct known_aggregate_columns_of> + { + using type = detail::type_vector_cat_t...>; + }; + template struct requires_parentheses> : public std::true_type {}; diff --git a/include/sqlpp11/core/type_traits.h b/include/sqlpp11/core/type_traits.h index 1f8eae67..b3abcec6 100644 --- a/include/sqlpp11/core/type_traits.h +++ b/include/sqlpp11/core/type_traits.h @@ -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 #include #include #include #include -#include #include #include #include @@ -44,55 +42,13 @@ #include #include #include +#include #include +#include +#include namespace sqlpp { - template - struct is_optional : public std::false_type - { - }; - - template - struct is_optional<::sqlpp::optional> : public std::true_type - { - }; - - template <> - struct is_optional<::sqlpp::nullopt_t> : public std::true_type - { - }; - - template - struct remove_optional - { - using type = T; - }; - - template - struct remove_optional<::sqlpp::optional> - { - using type = T; - }; - - template - using remove_optional_t = typename remove_optional::type; - - template - struct force_optional - { - using type = ::sqlpp::optional; - }; - - template - struct force_optional<::sqlpp::optional> - { - using type = ::sqlpp::optional; - }; - - template - using force_optional_t = typename force_optional::type; - template const T& get_value(const T& t) { @@ -117,26 +73,6 @@ namespace sqlpp return t.has_value(); } - struct no_value_t; - - template - struct value_type_of - { - using type = no_value_t; - }; - - template - using value_type_of_t = typename value_type_of::type; - - template - struct value_type_of<::sqlpp::optional> - { - using type = sqlpp::force_optional_t>>; - }; - - template - struct has_value_type : public std::integral_constant, no_value_t>::value> {}; - template struct has_default : public std::false_type { @@ -153,186 +89,6 @@ namespace sqlpp }; // - struct boolean{}; - template<> - struct value_type_of { using type = boolean; }; - template<> - struct value_type_of { using type = boolean; }; - - struct integral{}; - template<> - struct value_type_of { using type = integral; }; - template<> - struct value_type_of { using type = integral; }; - template<> - struct value_type_of { using type = integral; }; - template<> - struct value_type_of { using type = integral; }; - template<> - struct value_type_of { using type = integral; }; - - struct unsigned_integral{}; - template<> - struct value_type_of { using type = unsigned_integral; }; - template<> - struct value_type_of { using type = unsigned_integral; }; - template<> - struct value_type_of { using type = unsigned_integral; }; - template<> - struct value_type_of { using type = unsigned_integral; }; - template<> - struct value_type_of { using type = unsigned_integral; }; - - struct floating_point{}; - template<> - struct value_type_of { using type = floating_point; }; - template<> - struct value_type_of { using type = floating_point; }; - template<> - struct value_type_of { using type = floating_point; }; - template<> - struct value_type_of { using type = floating_point; }; - - struct text{}; - template <> - struct value_type_of { using type = text; }; - template <> - struct value_type_of { using type = text; }; - template <> - struct value_type_of { using type = text; }; - template <> - struct value_type_of { using type = text; }; - template <> - struct value_type_of<::sqlpp::string_view> { using type = text; }; - - struct blob{}; - template <> - struct value_type_of { using type = blob; }; - template - struct value_type_of> { using type = blob; }; - template <> - struct value_type_of> { using type = blob; }; - template <> - struct value_type_of<::sqlpp::span> { using type = blob; }; - - struct day_point{}; - template <> - struct value_type_of { using type = day_point; }; - template <> - struct value_type_of> { using type = day_point; }; - - struct time_of_day{}; - template <> - struct value_type_of { using type = time_of_day; }; - template - struct value_type_of> { using type = time_of_day; }; - - struct time_point{}; - template <> - struct value_type_of { using type = time_point; }; - template - struct value_type_of> { using type = time_point; }; - - - template - struct is_boolean : public std::is_same>, boolean> - { - }; - - template <> - struct is_boolean<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_integral : public std::is_same>, integral> - { - }; - - template <> - struct is_integral<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_unsigned_integral : public std::is_same>, unsigned_integral> - { - }; - - template <> - struct is_unsigned_integral<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_floating_point : public std::is_same>, 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 - struct is_numeric - : public std::integral_constant::value or is_integral::value or is_unsigned_integral::value or - is_floating_point::value or - std::is_same>, numeric>::value> - { - }; - - template <> - struct is_numeric<::sqlpp::nullopt_t> : public std::true_type{}; - - template - struct is_text : public std::is_same>, text> - { - }; - - template <> - struct is_text<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_blob : public std::is_same>, blob> - { - }; - - template <> - struct is_blob<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_day_point : public std::is_same>, day_point> - { - }; - - template <> - struct is_day_point<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_time_point : public std::is_same>, time_point> - { - }; - - template <> - struct is_time_point<::sqlpp::nullopt_t> : public std::true_type { - }; - - template - struct is_day_or_time_point : public std::integral_constant::value or is_time_point::value> { - }; - - template - struct is_time_of_day : public std::is_same>, time_of_day> - { - }; - - template <> - struct is_time_of_day<::sqlpp::nullopt_t> : public std::true_type { - }; - template struct values_are_comparable : public std::integral_constant diff --git a/include/sqlpp11/core/type_traits/aggregates.h b/include/sqlpp11/core/type_traits/aggregates.h index 6804baae..f0340d43 100644 --- a/include/sqlpp11/core/type_traits/aggregates.h +++ b/include/sqlpp11/core/type_traits/aggregates.h @@ -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 @@ -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 - struct known_aggregate_expressions_of + struct known_aggregate_columns_of { using type = detail::type_vector<>; }; template - using known_aggregate_expressions_of_t = typename known_aggregate_expressions_of::type; + using known_aggregate_columns_of_t = typename known_aggregate_columns_of::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 + // @KnownAggregateColumns: type_vector as obtained through known_aggregate_columns_of_t + template struct is_aggregate_expression : public std::integral_constant::value or - KnownAggregateExpressions::template contains::value> + KnownAggregateColumns::template contains::value> { }; diff --git a/include/sqlpp11/core/type_traits/group_by_column.h b/include/sqlpp11/core/type_traits/group_by_column.h new file mode 100644 index 00000000..2bd57542 --- /dev/null +++ b/include/sqlpp11/core/type_traits/group_by_column.h @@ -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 +#include +#include + +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 + struct is_group_by_column : public std::false_type + { + }; + +#warning Add tests + +} // namespace sqlpp11 + diff --git a/include/sqlpp11/core/type_traits/optional.h b/include/sqlpp11/core/type_traits/optional.h new file mode 100644 index 00000000..b35662c5 --- /dev/null +++ b/include/sqlpp11/core/type_traits/optional.h @@ -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 + +namespace sqlpp +{ + template + struct is_optional : public std::false_type + { + }; + + template + struct is_optional<::sqlpp::optional> : public std::true_type + { + }; + + template <> + struct is_optional<::sqlpp::nullopt_t> : public std::true_type + { + }; + + template + struct remove_optional + { + using type = T; + }; + + template + struct remove_optional<::sqlpp::optional> + { + using type = T; + }; + + template + using remove_optional_t = typename remove_optional::type; + + template + struct force_optional + { + using type = ::sqlpp::optional; + }; + + template + struct force_optional<::sqlpp::optional> + { + using type = ::sqlpp::optional; + }; + + template + using force_optional_t = typename force_optional::type; + + +} diff --git a/include/sqlpp11/core/type_traits/value_type.h b/include/sqlpp11/core/type_traits/value_type.h new file mode 100644 index 00000000..a556ffd7 --- /dev/null +++ b/include/sqlpp11/core/type_traits/value_type.h @@ -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 + +#include +#include +#include + +namespace sqlpp +{ + struct no_value_t; + + template + struct value_type_of + { + using type = no_value_t; + }; + + template + using value_type_of_t = typename value_type_of::type; + + template + struct value_type_of<::sqlpp::optional> + { + using type = sqlpp::optional>>; + }; + + template + struct has_value_type : public std::integral_constant, no_value_t>::value> {}; + + struct boolean{}; + template<> + struct value_type_of { using type = boolean; }; + template<> + struct value_type_of { using type = boolean; }; + + struct integral{}; + template<> + struct value_type_of { using type = integral; }; + template<> + struct value_type_of { using type = integral; }; + template<> + struct value_type_of { using type = integral; }; + template<> + struct value_type_of { using type = integral; }; + template<> + struct value_type_of { using type = integral; }; + + struct unsigned_integral{}; + template<> + struct value_type_of { using type = unsigned_integral; }; + template<> + struct value_type_of { using type = unsigned_integral; }; + template<> + struct value_type_of { using type = unsigned_integral; }; + template<> + struct value_type_of { using type = unsigned_integral; }; + template<> + struct value_type_of { using type = unsigned_integral; }; + + struct floating_point{}; + template<> + struct value_type_of { using type = floating_point; }; + template<> + struct value_type_of { using type = floating_point; }; + template<> + struct value_type_of { using type = floating_point; }; + template<> + struct value_type_of { using type = floating_point; }; + + struct text{}; + template <> + struct value_type_of { using type = text; }; + template <> + struct value_type_of { using type = text; }; + template <> + struct value_type_of { using type = text; }; + template <> + struct value_type_of { using type = text; }; + template <> + struct value_type_of<::sqlpp::string_view> { using type = text; }; + + struct blob{}; + template <> + struct value_type_of { using type = blob; }; + template + struct value_type_of> { using type = blob; }; + template <> + struct value_type_of> { using type = blob; }; + template <> + struct value_type_of<::sqlpp::span> { using type = blob; }; + + struct day_point{}; + template <> + struct value_type_of { using type = day_point; }; + template <> + struct value_type_of> { using type = day_point; }; + + struct time_of_day{}; + template <> + struct value_type_of { using type = time_of_day; }; + template + struct value_type_of> { using type = time_of_day; }; + + struct time_point{}; + template <> + struct value_type_of { using type = time_point; }; + template + struct value_type_of> { using type = time_point; }; + + + template + struct is_boolean : public std::is_same>, boolean> + { + }; + + template <> + struct is_boolean<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_integral : public std::is_same>, integral> + { + }; + + template <> + struct is_integral<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_unsigned_integral : public std::is_same>, unsigned_integral> + { + }; + + template <> + struct is_unsigned_integral<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_floating_point : public std::is_same>, 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 + struct is_numeric + : public std::integral_constant::value or is_integral::value or is_unsigned_integral::value or + is_floating_point::value or + std::is_same>, numeric>::value> + { + }; + + template <> + struct is_numeric<::sqlpp::nullopt_t> : public std::true_type{}; + + template + struct is_text : public std::is_same>, text> + { + }; + + template <> + struct is_text<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_blob : public std::is_same>, blob> + { + }; + + template <> + struct is_blob<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_day_point : public std::is_same>, day_point> + { + }; + + template <> + struct is_day_point<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_time_point : public std::is_same>, time_point> + { + }; + + template <> + struct is_time_point<::sqlpp::nullopt_t> : public std::true_type { + }; + + template + struct is_day_or_time_point : public std::integral_constant::value or is_time_point::value> { + }; + + template + struct is_time_of_day : public std::is_same>, time_of_day> + { + }; + + template <> + struct is_time_of_day<::sqlpp::nullopt_t> : public std::true_type { + }; + +} diff --git a/tests/core/types/CMakeLists.txt b/tests/core/types/CMakeLists.txt index 37771630..442511eb 100644 --- a/tests/core/types/CMakeLists.txt +++ b/tests/core/types/CMakeLists.txt @@ -37,4 +37,5 @@ test_compile(value) add_subdirectory(aggregate_function) add_subdirectory(operator) +add_subdirectory(clause) add_subdirectory(type_traits) diff --git a/tests/core/types/clause/CMakeLists.txt b/tests/core/types/clause/CMakeLists.txt new file mode 100644 index 00000000..a895c99c --- /dev/null +++ b/tests/core/types/clause/CMakeLists.txt @@ -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) + diff --git a/tests/core/types/clause/group_by.cpp b/tests/core/types/clause/group_by.cpp new file mode 100644 index 00000000..4d8ed5e1 --- /dev/null +++ b/tests/core/types/clause/group_by.cpp @@ -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 + +namespace +{ + template + auto known_aggregate_columns_as_expected(T... t) + -> std::is_same, + sqlpp::detail::type_vector>; +} + +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(); +} + diff --git a/tests/core/types/clause/select_columns.cpp b/tests/core/types/clause/select_columns.cpp new file mode 100644 index 00000000..d7b744ab --- /dev/null +++ b/tests/core/types/clause/select_columns.cpp @@ -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 + +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(); +} + diff --git a/tests/core/types/type_traits/CMakeLists.txt b/tests/core/types/type_traits/CMakeLists.txt index 2786010e..c40cd99d 100644 --- a/tests/core/types/type_traits/CMakeLists.txt +++ b/tests/core/types/type_traits/CMakeLists.txt @@ -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()