diff --git a/include/sqlpp11/core/aggregate_function/avg.h b/include/sqlpp11/core/aggregate_function/avg.h index cd396230..69f9a805 100644 --- a/include/sqlpp11/core/aggregate_function/avg.h +++ b/include/sqlpp11/core/aggregate_function/avg.h @@ -63,6 +63,11 @@ namespace sqlpp Expr _expr; }; + template + struct is_aggregate> : public std::true_type + { + }; + template struct name_tag_of>: public name_tag_of { @@ -88,7 +93,7 @@ namespace sqlpp template using check_avg_arg = - ::sqlpp::enable_if_t<(is_numeric::value or is_boolean::value) and not contains_aggregate_function_t::value>; + ::sqlpp::enable_if_t<(is_numeric::value or is_boolean::value) and not contains_aggregate::value>; template > auto avg(T t) -> avg_t diff --git a/include/sqlpp11/core/aggregate_function/count.h b/include/sqlpp11/core/aggregate_function/count.h index 227320f2..03550926 100644 --- a/include/sqlpp11/core/aggregate_function/count.h +++ b/include/sqlpp11/core/aggregate_function/count.h @@ -63,6 +63,11 @@ namespace sqlpp Expr _expr; }; + template + struct is_aggregate> : public std::true_type + { + }; + template struct name_tag_of>: public name_tag_of { @@ -88,7 +93,7 @@ namespace sqlpp template using check_count_arg = - ::sqlpp::enable_if_t::value and not contains_aggregate_function_t::value>; + ::sqlpp::enable_if_t::value and not contains_aggregate::value>; template > auto count(T t) -> count_t diff --git a/include/sqlpp11/core/aggregate_function/max.h b/include/sqlpp11/core/aggregate_function/max.h index ffc9422b..008792ae 100644 --- a/include/sqlpp11/core/aggregate_function/max.h +++ b/include/sqlpp11/core/aggregate_function/max.h @@ -62,6 +62,11 @@ namespace sqlpp Expr _expr; }; + template + struct is_aggregate> : public std::true_type + { + }; + template struct name_tag_of>: public name_tag_of { @@ -87,7 +92,7 @@ namespace sqlpp template using check_max_arg = - ::sqlpp::enable_if_t::value and not contains_aggregate_function_t::value>; + ::sqlpp::enable_if_t::value and not contains_aggregate::value>; template > auto max(T t) -> max_t diff --git a/include/sqlpp11/core/aggregate_function/min.h b/include/sqlpp11/core/aggregate_function/min.h index e1ecdd98..78b78ee1 100644 --- a/include/sqlpp11/core/aggregate_function/min.h +++ b/include/sqlpp11/core/aggregate_function/min.h @@ -62,6 +62,11 @@ namespace sqlpp Expr _expr; }; + template + struct is_aggregate> : public std::true_type + { + }; + template struct name_tag_of>: public name_tag_of { @@ -87,7 +92,7 @@ namespace sqlpp template using check_min_arg = - ::sqlpp::enable_if_t::value and not contains_aggregate_function_t::value>; + ::sqlpp::enable_if_t::value and not contains_aggregate::value>; template > auto min(T t) -> min_t diff --git a/include/sqlpp11/core/aggregate_function/over.h b/include/sqlpp11/core/aggregate_function/over.h index 98aab2d5..776f621a 100644 --- a/include/sqlpp11/core/aggregate_function/over.h +++ b/include/sqlpp11/core/aggregate_function/over.h @@ -36,8 +36,6 @@ namespace sqlpp struct over_t : public enable_as>, public enable_comparison> { - using _traits = make_traits; - over_t(Expr expr) : _expr(expr) { @@ -52,18 +50,24 @@ namespace sqlpp Expr _expr; }; - template - struct nodes_of> + template + struct is_aggregate> : public is_aggregate + { + }; + + template + struct name_tag_of> : public name_tag_of {}; + + template + struct nodes_of>: public nodes_of { - using type = sqlpp::detail::type_vector; }; template struct value_type_of>: public value_type_of {}; -#warning: should this be "is_aggregate_function"? template - using check_over_args = ::sqlpp::enable_if_t::value>; + using check_over_args = ::sqlpp::enable_if_t::value>; template auto to_sql_string(Context& context, const over_t& t) -> std::string @@ -71,7 +75,7 @@ namespace sqlpp return operand_to_sql_string(context, t._expr) + " OVER()"; } - template + template > auto over(Expr t) -> over_t { return {std::move(t)}; diff --git a/include/sqlpp11/core/aggregate_function/sum.h b/include/sqlpp11/core/aggregate_function/sum.h index 165d5755..5d4eac34 100644 --- a/include/sqlpp11/core/aggregate_function/sum.h +++ b/include/sqlpp11/core/aggregate_function/sum.h @@ -62,7 +62,11 @@ namespace sqlpp Expr _expr; }; -#warning: test that aggregate functions can be used as result columns directly, but can also be aliased + template + struct is_aggregate> : public std::true_type + { + }; + template struct name_tag_of>: public name_tag_of { @@ -89,7 +93,7 @@ namespace sqlpp template using check_sum_arg = - ::sqlpp::enable_if_t<(is_numeric::value or is_boolean::value) and not contains_aggregate_function_t::value>; + ::sqlpp::enable_if_t<(is_numeric::value or is_boolean::value) and not contains_aggregate::value>; template > auto sum(T t) -> sum_t diff --git a/include/sqlpp11/core/clause/where.h b/include/sqlpp11/core/clause/where.h index c8117d8a..5e3a39e4 100644 --- a/include/sqlpp11/core/clause/where.h +++ b/include/sqlpp11/core/clause/where.h @@ -110,7 +110,7 @@ namespace sqlpp SQLPP_PORTABLE_STATIC_ASSERT(assert_where_arg_is_boolean_expression_t, "where() argument has to be an sqlpp boolean expression."); - SQLPP_PORTABLE_STATIC_ASSERT(assert_where_arg_contains_no_aggregate_functions_t, + SQLPP_PORTABLE_STATIC_ASSERT(assert_where_arg_contains_no_aggregate_t, "at least one aggregate function used in where()"); // workaround for msvc bugs https://connect.microsoft.com/VisualStudio/Feedback/Details/2086629 & @@ -119,15 +119,15 @@ namespace sqlpp // using check_where_t = static_combined_check_t< // static_check_t::value...>::value, // assert_where_arg_is_boolean_expression_t>, - // static_check_t::value)...>::value, - // assert_where_arg_contains_no_aggregate_functions_t>>; + // static_check_t::value)...>::value, + // assert_where_arg_contains_no_aggregate_t>>; template struct check_where { using type = static_combined_check_t< static_check_t::value, assert_where_arg_is_boolean_expression_t>, - static_check_t::value, - assert_where_arg_contains_no_aggregate_functions_t>>; + static_check_t::value, + assert_where_arg_contains_no_aggregate_t>>; }; template diff --git a/include/sqlpp11/core/type_traits.h b/include/sqlpp11/core/type_traits.h index 6d1313d6..e0e0db41 100644 --- a/include/sqlpp11/core/type_traits.h +++ b/include/sqlpp11/core/type_traits.h @@ -540,30 +540,6 @@ namespace sqlpp SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables) SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates) -#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \ - namespace detail \ - { \ - template \ - struct trait##_impl \ - { \ - using type = typename trait##_impl>::type; \ - }; \ - template \ - struct trait##_impl> \ - { \ - using type = typename T::_##trait; \ - }; \ - template \ - struct trait##_impl, void> \ - { \ - using type = logic::any_t::type::value...>; \ - }; \ - } \ - template \ - using trait##_t = typename detail::trait##_impl::type; - - SQLPP_RECURSIVE_TRAIT_GENERATOR(contains_aggregate_function) - template struct lhs { @@ -609,6 +585,13 @@ namespace sqlpp ; }; + template + struct is_aggregate : public std::false_type{}; + +#warning: Need to make this recursive! and then add tests! + template + struct contains_aggregate : public std::false_type{}; + namespace detail { template diff --git a/tests/core/types/CMakeLists.txt b/tests/core/types/CMakeLists.txt index 4471570c..58a24dbd 100644 --- a/tests/core/types/CMakeLists.txt +++ b/tests/core/types/CMakeLists.txt @@ -29,11 +29,11 @@ function(test_compile name) # conditionally bump to a higher C++ standard to test compatibility endfunction() -add_subdirectory(operator) -test_compile(aggregate_function) test_compile(case_when) test_compile(dynamic) test_compile(result_row) test_compile(select_as) test_compile(value) +add_subdirectory(aggregate_function) +add_subdirectory(operator) diff --git a/tests/core/types/aggregate_function/CMakeLists.txt b/tests/core/types/aggregate_function/CMakeLists.txt new file mode 100644 index 00000000..42a69187 --- /dev/null +++ b/tests/core/types/aggregate_function/CMakeLists.txt @@ -0,0 +1,37 @@ +# 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_aggregate_function_${name}) + add_executable(${target} ${name}.cpp) + target_link_libraries(${target} PRIVATE sqlpp11::sqlpp11 sqlpp11_testing) +endfunction() + +test_compile(avg) +test_compile(count) +test_compile(max) +test_compile(min) +test_compile(over) +test_compile(sum) + diff --git a/tests/core/types/aggregate_function/avg.cpp b/tests/core/types/aggregate_function/avg.cpp new file mode 100644 index 00000000..3b0930c3 --- /dev/null +++ b/tests/core/types/aggregate_function/avg.cpp @@ -0,0 +1,114 @@ +/* + * 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 "MockDb.h" +#include "Sample.h" +#include + +namespace +{ + auto db = MockDb{}; + + template + using is_same_type = std::is_same, V>; +} + +template +void test_avg(Value v) +{ + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v)); + + using OptFloat = sqlpp::value_type_of_t<::sqlpp::optional>; + + // avg non-nullable can be null because there could be zero result rows. + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // avg nullable + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // avg enables the `as` member function. + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + + // avg has a name + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("avg"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("avg"), ""); + + // avg enables OVER. + static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(sqlpp::has_enabled_over::value, ""); + + // avg enables comparison member functions. + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + + // avg has its argument as nodes + using L = typename std::decay::type; + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); +} + +int main() +{ + // boolean + test_avg(bool{true}); + + // integral + test_avg(int8_t{7}); + test_avg(int16_t{7}); + test_avg(int32_t{7}); + test_avg(int64_t{7}); + + // unsigned integral + test_avg(uint8_t{7}); + test_avg(uint16_t{7}); + test_avg(uint32_t{7}); + test_avg(uint64_t{7}); + + // floating point + test_avg(float{7.7}); + test_avg(double{7.7}); + +#warning: Should there be avg date time duration? +#if 0 + // date + test_avg(::sqlpp::chrono::day_point{}); + + // timestamp + test_avg(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_avg(minute_point{}); + + // time_of_day + test_avg(std::chrono::microseconds{}); +#endif +} + diff --git a/tests/core/types/aggregate_function/count.cpp b/tests/core/types/aggregate_function/count.cpp new file mode 100644 index 00000000..c68eb162 --- /dev/null +++ b/tests/core/types/aggregate_function/count.cpp @@ -0,0 +1,118 @@ +/* + * 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 "MockDb.h" +#include "Sample.h" +#include + +namespace +{ + auto db = MockDb{}; + + template + using is_same_type = std::is_same, V>; +} + +template +void test_count(Value v) +{ + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v)); + + // count of non-nullable + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // count of nullable + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // count enables the `as` member function. + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + + // count has a name + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("count"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("count"), ""); + + // count enables comparison member functions. + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + + // count enables OVER. + static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(sqlpp::has_enabled_over::value, ""); + + // count has its argument as nodes + using L = typename std::decay::type; + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); +} + +int main() +{ + // boolean + test_count(bool{true}); + + // integral + test_count(int8_t{7}); + test_count(int16_t{7}); + test_count(int32_t{7}); + test_count(int64_t{7}); + + // unsigned integral + test_count(uint8_t{7}); + test_count(uint16_t{7}); + test_count(uint32_t{7}); + test_count(uint64_t{7}); + + // floating point + test_count(float{7.7}); + test_count(double{7.7}); + + // text + test_count('7'); + test_count("seven"); + test_count(std::string("seven")); + test_count(::sqlpp::string_view("seven")); + + // blob + test_count(std::vector{}); + + // date + test_count(::sqlpp::chrono::day_point{}); + + // timestamp + test_count(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_count(minute_point{}); + + // time_of_day + test_count(std::chrono::microseconds{}); +} + diff --git a/tests/core/types/aggregate_function/max.cpp b/tests/core/types/aggregate_function/max.cpp new file mode 100644 index 00000000..936d34f7 --- /dev/null +++ b/tests/core/types/aggregate_function/max.cpp @@ -0,0 +1,120 @@ +/* + * 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 "MockDb.h" +#include "Sample.h" +#include + +namespace +{ + auto db = MockDb{}; + + template + using is_same_type = std::is_same, V>; +} + +template +void test_max(Value v) +{ + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v)); + + using OptValueType = sqlpp::value_type_of_t>; + + // max of non-nullable can be null because there could be zero result rows. + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // max of nullable + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // max enables the `as` member function. + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + + // max has a name + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("max"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("max"), ""); + + // max enables comparison member functions. + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + + // max enables OVER. + static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(sqlpp::has_enabled_over::value, ""); + + // max has its argument as nodes + using L = typename std::decay::type; + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); +} + +int main() +{ + // boolean + test_max(bool{true}); + + // integral + test_max(int8_t{7}); + test_max(int16_t{7}); + test_max(int32_t{7}); + test_max(int64_t{7}); + + // unsigned integral + test_max(uint8_t{7}); + test_max(uint16_t{7}); + test_max(uint32_t{7}); + test_max(uint64_t{7}); + + // floating point + test_max(float{7.7}); + test_max(double{7.7}); + + // text + test_max('7'); + test_max("seven"); + test_max(std::string("seven")); + test_max(::sqlpp::string_view("seven")); + + // blob + test_max(std::vector{}); + + // date + test_max(::sqlpp::chrono::day_point{}); + + // timestamp + test_max(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_max(minute_point{}); + + // time_of_day + test_max(std::chrono::microseconds{}); +} + diff --git a/tests/core/types/aggregate_function/min.cpp b/tests/core/types/aggregate_function/min.cpp new file mode 100644 index 00000000..c9af7df3 --- /dev/null +++ b/tests/core/types/aggregate_function/min.cpp @@ -0,0 +1,120 @@ +/* + * 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 "MockDb.h" +#include "Sample.h" +#include + +namespace +{ + auto db = MockDb{}; + + template + using is_same_type = std::is_same, V>; +} + +template +void test_min(Value v) +{ + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v)); + + using OptValueType = sqlpp::value_type_of_t>; + + // min of non-nullable can be null because there could be zero result rows. + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // min of nullable + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // min enables the `as` member function. + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + + // min has a name + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("min"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("min"), ""); + + // min enables comparison member functions. + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + + // min enables OVER. + static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(sqlpp::has_enabled_over::value, ""); + + // min has its argument as nodes + using L = typename std::decay::type; + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); +} + +int main() +{ + // boolean + test_min(bool{true}); + + // integral + test_min(int8_t{7}); + test_min(int16_t{7}); + test_min(int32_t{7}); + test_min(int64_t{7}); + + // unsigned integral + test_min(uint8_t{7}); + test_min(uint16_t{7}); + test_min(uint32_t{7}); + test_min(uint64_t{7}); + + // floating point + test_min(float{7.7}); + test_min(double{7.7}); + + // text + test_min('7'); + test_min("seven"); + test_min(std::string("seven")); + test_min(::sqlpp::string_view("seven")); + + // blob + test_min(std::vector{}); + + // date + test_min(::sqlpp::chrono::day_point{}); + + // timestamp + test_min(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_min(minute_point{}); + + // time_of_day + test_min(std::chrono::microseconds{}); +} + diff --git a/tests/core/types/aggregate_function.cpp b/tests/core/types/aggregate_function/over.cpp similarity index 62% rename from tests/core/types/aggregate_function.cpp rename to tests/core/types/aggregate_function/over.cpp index 1cb9d594..6f71f5e2 100644 --- a/tests/core/types/aggregate_function.cpp +++ b/tests/core/types/aggregate_function/over.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2016, Roland Bock + * Copyright (c) 2024, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -44,89 +44,87 @@ void test_aggregate_functions(Value v) using OptValueType = sqlpp::value_type_of_t<::sqlpp::optional>; // Aggregate of non-nullable - static_assert(is_same_type::value, ""); - static_assert(is_same_type::value, ""); - static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); // Aggregate of nullable - static_assert(is_same_type::value, ""); - static_assert(is_same_type::value, ""); - static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); // Aggregate functions enable the `as` member function. - static_assert(sqlpp::has_enabled_as::value, ""); - static_assert(sqlpp::has_enabled_as::value, ""); - static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); // Aggregate functions have a name - static_assert(sqlpp::has_name::value, ""); - static_assert(sqlpp::has_name::value, ""); - static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); - static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("count"), ""); - static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("max"), ""); - static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("min"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("count"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("max"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("min"), ""); // Aggregate functions enable comparison member functions. - static_assert(sqlpp::has_enabled_comparison::value, ""); - static_assert(sqlpp::has_enabled_comparison::value, ""); - static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); // Aggregate functions enable OVER. - static_assert(sqlpp::has_enabled_over::value, ""); - static_assert(sqlpp::has_enabled_over::value, ""); - static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(not sqlpp::has_enabled_over::value, ""); + static_assert(not sqlpp::has_enabled_over::value, ""); + static_assert(not sqlpp::has_enabled_over::value, ""); // Aggregate functions have their arguments as nodes using L = typename std::decay::type; - static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); - static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); - static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); } template void test_numeric_aggregate_functions(Value v) { auto v_not_null = sqlpp::value(v); - auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v)); + auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v).over()); using ValueType = typename std::conditional::value, int, Value>::type; using OptValueType = sqlpp::value_type_of_t<::sqlpp::optional>; using OptFloat = sqlpp::value_type_of_t<::sqlpp::optional>; // Aggregate of non-nullable - static_assert(is_same_type::value, ""); - static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); // Aggregate of nullable - static_assert(is_same_type::value, ""); - static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); // Aggregate functions enable the `as` member function. - static_assert(sqlpp::has_enabled_as::value, ""); - static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); // Aggregate functions have a name - static_assert(sqlpp::has_name::value, ""); - static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); - static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("sum"), ""); - static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("avg"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("sum"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("avg"), ""); // Aggregate functions enable OVER. - static_assert(sqlpp::has_enabled_over::value, ""); - static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(not sqlpp::has_enabled_over::value, ""); + static_assert(not sqlpp::has_enabled_over::value, ""); // Aggregate functions enable comparison member functions. - static_assert(sqlpp::has_enabled_comparison::value, ""); - static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); // Aggregate functions have their arguments as nodes using L = typename std::decay::type; - static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); - static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); - -#warning: test enable_over + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); } int main() diff --git a/tests/core/types/aggregate_function/sum.cpp b/tests/core/types/aggregate_function/sum.cpp new file mode 100644 index 00000000..79cb2226 --- /dev/null +++ b/tests/core/types/aggregate_function/sum.cpp @@ -0,0 +1,107 @@ +/* + * 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 "MockDb.h" +#include "Sample.h" +#include + +namespace +{ + auto db = MockDb{}; + + template + using is_same_type = std::is_same, V>; +} + +template +void test_sum(Value v) +{ + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v)); + + using ValueType = typename std::conditional::value, int, Value>::type; + using OptValueType = sqlpp::value_type_of_t<::sqlpp::optional>; + + // sum non-nullable can be null because there could be zero result rows. + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // sum nullable + static_assert(is_same_type::value, ""); + static_assert(is_same_type::value, ""); + + // sum enables the `as` member function. + static_assert(sqlpp::has_enabled_as::value, ""); + static_assert(sqlpp::has_enabled_as::value, ""); + + // sum has a name + static_assert(sqlpp::has_name::value, ""); + static_assert(sqlpp::has_name::value, ""); + + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("sum"), ""); + static_assert(sqlpp::name_tag_of_t::name == sqlpp::string_view("sum"), ""); + + // sum enables OVER. + static_assert(sqlpp::has_enabled_over::value, ""); + static_assert(sqlpp::has_enabled_over::value, ""); + + // sum enables comparison member functions. + static_assert(sqlpp::has_enabled_comparison::value, ""); + static_assert(sqlpp::has_enabled_comparison::value, ""); + + // sum has its argument as nodes + using L = typename std::decay::type; + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); + static_assert(std::is_same, sqlpp::detail::type_vector>::value, ""); +} + +int main() +{ + // boolean + test_sum(bool{true}); + + // integral + test_sum(int8_t{7}); + test_sum(int16_t{7}); + test_sum(int32_t{7}); + test_sum(int64_t{7}); + + // unsigned integral + test_sum(uint8_t{7}); + test_sum(uint16_t{7}); + test_sum(uint32_t{7}); + test_sum(uint64_t{7}); + + // floating point + test_sum(float{7.7}); + test_sum(double{7.7}); + +#warning: Should there be sum duration? +#if 0 + // time_of_day + test_sum(std::chrono::microseconds{}); +#endif +} + diff --git a/tests/core/types/value.cpp b/tests/core/types/value.cpp index ca5ed81b..b2b10815 100644 --- a/tests/core/types/value.cpp +++ b/tests/core/types/value.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2016, Roland Bock + * Copyright (c) 2024, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification,