diff --git a/include/sqlpp11/aggregate_functions/count.h b/include/sqlpp11/aggregate_functions/count.h index cf77e23a..421e8b9f 100644 --- a/include/sqlpp11/aggregate_functions/count.h +++ b/include/sqlpp11/aggregate_functions/count.h @@ -34,32 +34,8 @@ namespace sqlpp { - struct count_alias_t - { - struct _alias_t - { - static constexpr const char _literal[] = "count_"; - using _name_t = sqlpp::make_char_sequence; - template - struct _member_t - { - T count; - T& operator()() - { - return count; - } - const T& operator()() const - { - return count; - } - }; - }; - }; - template - struct count_t : public expression_operators, integral>, - public aggregate_function_operators>, - public alias_operators> + struct count_t { using _traits = make_traits; @@ -67,11 +43,6 @@ namespace sqlpp using _can_be_null = std::false_type; using _is_aggregate_expression = std::true_type; - static_assert(is_noop::value or std::is_same::value, - "count() used with flag other than 'distinct'"); - - using _auto_alias_t = count_alias_t; - count_t(const Expr expr) : _expr(expr) { } @@ -85,6 +56,12 @@ namespace sqlpp Expr _expr; }; + template + struct value_type_of> + { + using type = integral; + }; + template Context& serialize(const count_t& t, Context& context) { @@ -100,20 +77,19 @@ namespace sqlpp } template - auto count(T t) -> count_t> + using check_count_arg = + std::enable_if_t::value and not contains_aggregate_function_t::value>; + + template > + auto count(T t) -> count_t { - static_assert(not contains_aggregate_function_t>::value, - "count() cannot be used on an aggregate function"); - static_assert(is_expression_t>::value, "count() requires an expression as argument"); - return {t}; + return {std::move(t)}; } - template - auto count(const distinct_t& /*unused*/, T t) -> count_t> + template > + auto count(const distinct_t& /*unused*/, T t) -> count_t { - static_assert(not contains_aggregate_function_t>::value, - "count() cannot be used on an aggregate function"); - static_assert(is_expression_t>::value, "count() requires an expression as argument"); - return {t}; + return {std::move(t)}; } + } // namespace sqlpp diff --git a/include/sqlpp11/aggregate_functions/min.h b/include/sqlpp11/aggregate_functions/min.h index c6432bc1..1e90b2ab 100644 --- a/include/sqlpp11/aggregate_functions/min.h +++ b/include/sqlpp11/aggregate_functions/min.h @@ -31,40 +31,14 @@ namespace sqlpp { - struct min_alias_t - { - struct _alias_t - { - static constexpr const char _literal[] = "min_"; - using _name_t = sqlpp::make_char_sequence; - template - struct _member_t - { - T min; - T& operator()() - { - return min; - } - const T& operator()() const - { - return min; - } - }; - }; - }; - template - struct min_t : public expression_operators, value_type_of_t>, - public aggregate_function_operators>, - public alias_operators> + struct min_t { using _traits = make_traits, tag::is_expression, tag::is_selectable>; using _nodes = detail::type_vector; using _can_be_null = std::true_type; using _is_aggregate_expression = std::true_type; - using _auto_alias_t = min_alias_t; - min_t(Expr expr) : _expr(expr) { } @@ -78,6 +52,12 @@ namespace sqlpp Expr _expr; }; + template + struct value_type_of> + { + using type = sqlpp::force_optional_t>; + }; + template Context& serialize(const min_t& t, Context& context) { @@ -93,20 +73,18 @@ namespace sqlpp } template - auto min(T t) -> min_t> + using check_min_arg = + std::enable_if_t::value and not contains_aggregate_function_t::value>; + + template > + auto min(T t) -> min_t { - static_assert(not contains_aggregate_function_t>::value, - "min() cannot be used on an aggregate function"); - static_assert(is_expression_t>::value, "min() requires an expression as argument"); - return {t}; + return {std::move(t)}; } - template - auto min(const distinct_t& /*unused*/, T t) -> min_t> + template > + auto min(const distinct_t& /*unused*/, T t) -> min_t { - static_assert(not contains_aggregate_function_t>::value, - "min() cannot be used on an aggregate function"); - static_assert(is_expression_t>::value, "min() requires an expression as argument"); - return {t}; + return {std::move(t)}; } } // namespace sqlpp diff --git a/include/sqlpp11/operator/arithmetic_expression.h b/include/sqlpp11/operator/arithmetic_expression.h index 29d1a6ce..159a6881 100644 --- a/include/sqlpp11/operator/arithmetic_expression.h +++ b/include/sqlpp11/operator/arithmetic_expression.h @@ -66,7 +66,7 @@ namespace sqlpp }; template - using check_arithmetic_args = std::enable_if_t::value and has_numeric_value::value>; + using check_arithmetic_args = std::enable_if_t::value and is_numeric::value>; #warning: need to document that this is on purpose (not integral, or unsigned integral, or floating_point) because it is difficult to know for the library to know what the actual result type will be (it is difficult to guess in C++ already, and it is probably different from DB vendor to vendor). template diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index e5672b59..0a314a6b 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -127,7 +127,7 @@ namespace sqlpp template struct value_type_of> { - using type = sqlpp::compat::optional>>; + using type = sqlpp::force_optional_t>>; }; template @@ -232,10 +232,23 @@ namespace sqlpp struct is_unsigned_integral : public std::true_type { }; + template + struct is_floating_point : public std::is_same>, floating_point> + { + }; + + template <> + struct is_floating_point : 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_unsigned_integral::value or std::is_floating_point::value>{}; + struct is_numeric : public std::integral_constant::value or is_unsigned_integral::value or + is_floating_point::value> + { + }; template <> struct is_numeric : public std::true_type{}; @@ -244,125 +257,64 @@ namespace sqlpp struct is_numeric : public std::true_type{}; template - struct has_numeric_value : public std::integral_constant>::value or is_numeric>>::value>{}; - - struct text; - template - struct is_text : public std::false_type {}; - - template <> - struct is_text : public std::true_type {}; - - template <> - struct is_text : public std::true_type {}; - - template <> - struct is_text : public std::true_type {}; - - template <> - struct is_text : public std::true_type {}; - - template <> - struct is_text : public std::true_type {}; - - template <> - struct is_text : public std::true_type {}; - - template - struct has_text_value : public std::integral_constant>::value or - is_text>>::value>{}; - - struct blob; - template - struct is_blob : public std::false_type {}; - - template <> - struct is_blob : public std::true_type {}; - - template <> - struct is_blob> : public std::true_type {}; - - template <> - struct is_blob> : public std::true_type {}; - - template <> - struct is_blob : public std::true_type {}; - - template - struct has_blob_value : public std::integral_constant>::value or - is_blob>>::value>{}; - - struct day_point; - template - struct is_day_point : public std::false_type {}; - - template <> - struct is_day_point : public std::true_type {}; - - template <> - struct is_day_point> : public std::true_type {}; - - template <> - struct is_day_point : public std::true_type {}; - - template - struct has_day_point_value : public std::integral_constant>::value or - is_day_point>>::value>{}; - - struct time_of_day; - template - struct is_time_of_day : public std::false_type {}; - - template <> - struct is_time_of_day : public std::true_type {}; - - template - struct is_time_of_day> : public std::true_type {}; - - template <> - struct is_time_of_day : public std::true_type {}; - - template - struct has_time_of_day_value : public std::integral_constant>::value or - is_time_of_day>>::value>{}; - - struct time_point; - template - struct is_time_point : public std::false_type {}; - - template <> - struct is_time_point : public std::true_type {}; - - template - struct is_time_point> : public std::true_type {}; - - template <> - struct is_time_point : public std::true_type {}; - - template - struct has_time_point_value : public std::integral_constant>::value or - is_time_point>>::value>{}; - -#warning: Need to add float and unsigned traits? - template - struct values_are_comparable - : public std::integral_constant::value and has_blob_value::value) or - (is_boolean::value and is_boolean::value) or - (has_day_point_value::value and has_day_point_value::value) or - (has_numeric_value::value and has_numeric_value::value) or - (has_text_value::value and has_text_value::value) or - (has_time_of_day_value::value and has_time_of_day_value::value) or - (has_time_point_value::value and has_time_point_value::value)> + struct is_text : public std::is_same>, text> { }; + template <> + struct is_text : public std::true_type { + }; + + template + struct is_blob : public std::is_same>, blob> + { + }; + + template <> + struct is_blob : public std::true_type { + }; + + template + struct is_day_point : public std::is_same>, day_point> + { + }; + + template <> + struct is_day_point : public std::true_type { + }; + + template + struct is_time_point : public std::is_same>, time_point> + { + }; + + template <> + struct is_time_point : public std::true_type { + }; + + template + struct is_time_of_day : public std::is_same>, time_of_day> + { + }; + + template <> + struct is_time_of_day : public std::true_type { + }; + + template + struct values_are_comparable + : public std::integral_constant::value and is_blob::value) or + (is_boolean::value and is_boolean::value) or + (is_day_point::value and is_day_point::value) or + (is_numeric::value and is_numeric::value) or + (is_text::value and is_text::value) or + (is_time_of_day::value and is_time_of_day::value) or + (is_time_point::value and is_time_point::value)> + { + }; + +#warning: These something_t data type classifiers should be removed // data types struct blob; template @@ -400,7 +352,6 @@ namespace sqlpp using is_time_point_t = std::is_same, time_point>; // joined data type -#warning: These something_t data type classifiers should be removed template using is_numeric_t = logic::any_t::value, is_unsigned_integral_t::value, is_floating_point_t::value>; diff --git a/tests/core/types/CMakeLists.txt b/tests/core/types/CMakeLists.txt index 2dea1a04..a4f431ad 100644 --- a/tests/core/types/CMakeLists.txt +++ b/tests/core/types/CMakeLists.txt @@ -34,4 +34,10 @@ function(test_compile name) endif() endfunction() -test_compile(result_row) \ No newline at end of file +test_compile(aggregate_functions) +test_compile(comparison_expression) +test_compile(in_expression) +test_compile(logical_expression) +test_compile(result_row) +test_compile(value) + diff --git a/tests/core/types/aggregate_functions.cpp b/tests/core/types/aggregate_functions.cpp new file mode 100644 index 00000000..13c0478b --- /dev/null +++ b/tests/core/types/aggregate_functions.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016-2016, 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_aggregate_functions(Value v) +{ + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)); + + using ValueType = sqlpp::value_type_of_t; + using OptValueType = sqlpp::value_type_of_t>; + + // Aggregate of non-nullable + 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, ""); + +} + +int main() +{ + // boolean + test_aggregate_functions(bool{true}); + + // integral + test_aggregate_functions(int8_t{7}); + test_aggregate_functions(int16_t{7}); + test_aggregate_functions(int32_t{7}); + test_aggregate_functions(int64_t{7}); + + // unsigned integral + test_aggregate_functions(uint8_t{7}); + test_aggregate_functions(uint16_t{7}); + test_aggregate_functions(uint32_t{7}); + test_aggregate_functions(uint64_t{7}); + + // floating point + test_aggregate_functions(float{7.7}); + test_aggregate_functions(double{7.7}); + + // text + test_aggregate_functions('7'); + test_aggregate_functions("seven"); + test_aggregate_functions(std::string("seven")); + test_aggregate_functions(sqlpp::compat::string_view("seven")); + + // blob + test_aggregate_functions(std::vector{}); + + // date + test_aggregate_functions(::sqlpp::chrono::day_point{}); + + // timestamp + test_aggregate_functions(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_aggregate_functions(minute_point{}); + + // time_of_day + test_aggregate_functions(std::chrono::microseconds{}); +} + diff --git a/tests/core/types/comparison_expression.cpp b/tests/core/types/comparison_expression.cpp new file mode 100644 index 00000000..a8f0473c --- /dev/null +++ b/tests/core/types/comparison_expression.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016-2016, 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_bool = std::is_same, sqlpp::boolean>; + + template + using is_maybe_bool = std::is_same, sqlpp::compat::optional>; +} + +template +void test_comparison_expression(Value v) +{ + using OptValue = sqlpp::compat::optional; + + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)); + +#warning : Should also implement like, is_null, is_distinct_from as member functions. + + // Compare non-nullable with non-nullable. + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool= v_not_null)>::value, ""); + static_assert(is_bool v_not_null)>::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + + // Compare non-nullable with nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool= v_maybe_null)>::value, ""); + static_assert(is_maybe_bool v_maybe_null)>::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + + // Compare nullable with non-nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool= v_not_null)>::value, ""); + static_assert(is_maybe_bool v_not_null)>::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + + // Compare nullable with nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool= v_maybe_null)>::value, ""); + static_assert(is_maybe_bool v_maybe_null)>::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + + // Compare with null. + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); +} + +template +void test_like(Value v) +{ + auto v_not_null= sqlpp::value(v); + auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v)); + + // Compare non-nullable with non-nullable. + static_assert(is_bool::value, ""); + + // Compare non-nullable with nullable. + static_assert(is_maybe_bool::value, ""); + + // Compare nullable with non-nullable. + static_assert(is_maybe_bool::value, ""); + + // Compare nullable with nullable. + static_assert(is_maybe_bool::value, ""); +} + +int main() +{ + // boolean + test_comparison_expression(bool{true}); + + // integral + test_comparison_expression(int8_t{7}); + test_comparison_expression(int16_t{7}); + test_comparison_expression(int32_t{7}); + test_comparison_expression(int64_t{7}); + + // unsigned integral + test_comparison_expression(uint8_t{7}); + test_comparison_expression(uint16_t{7}); + test_comparison_expression(uint32_t{7}); + test_comparison_expression(uint64_t{7}); + + // floating point + test_comparison_expression(float{7.7}); + test_comparison_expression(double{7.7}); + + // text + test_comparison_expression('7'); + test_comparison_expression("seven"); + test_comparison_expression(std::string("seven")); + test_comparison_expression(sqlpp::compat::string_view("seven")); + + // blob + test_comparison_expression(std::vector{}); + + // date + test_comparison_expression(::sqlpp::chrono::day_point{}); + + // timestamp + test_comparison_expression(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_comparison_expression(minute_point{}); + + // time_of_day + test_comparison_expression(std::chrono::microseconds{}); + + // text + test_like('7'); + test_like("seven"); + test_like(std::string("seven")); + test_like(sqlpp::compat::string_view("seven")); + +} + diff --git a/tests/core/types/in_expression.cpp b/tests/core/types/in_expression.cpp new file mode 100644 index 00000000..952ae062 --- /dev/null +++ b/tests/core/types/in_expression.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016-2016, 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_bool = std::is_same, sqlpp::boolean>; + + template + using is_maybe_bool = std::is_same, sqlpp::compat::optional>; +} + +template +void test_in_expression(Value v) +{ + using OptValue = sqlpp::compat::optional; + + auto v_not_null = sqlpp::value(v); + auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)); + +#warning : Need to support in with select + // in(v_not_null, select(v_not_null.as(sqlpp::alias::a))); + + // Compare non-nullable with non-nullable. + static_assert(is_bool::value, ""); + static_assert(is_bool{}))>::value, ""); + + // Compare non-nullable with nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool{}))>::value, ""); + + // Compare nullable with non-nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool{}))>::value, ""); + + // Compare nullable with nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool{}))>::value, ""); +} + +template +void test_like(Value v) +{ + auto v_not_null= sqlpp::value(v); + auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v)); + + // Compare non-nullable with non-nullable. + static_assert(is_bool::value, ""); + + // Compare non-nullable with nullable. + static_assert(is_maybe_bool::value, ""); + + // Compare nullable with non-nullable. + static_assert(is_maybe_bool::value, ""); + + // Compare nullable with nullable. + static_assert(is_maybe_bool::value, ""); +} + +int main() +{ + // boolean + test_in_expression(bool{true}); + + // integral + test_in_expression(int8_t{7}); + test_in_expression(int16_t{7}); + test_in_expression(int32_t{7}); + test_in_expression(int64_t{7}); + + // unsigned integral + test_in_expression(uint8_t{7}); + test_in_expression(uint16_t{7}); + test_in_expression(uint32_t{7}); + test_in_expression(uint64_t{7}); + + // floating point + test_in_expression(float{7.7}); + test_in_expression(double{7.7}); + + // text + test_in_expression('7'); + test_in_expression("seven"); + test_in_expression(std::string("seven")); + test_in_expression(sqlpp::compat::string_view("seven")); + + // blob + test_in_expression(std::vector{}); + + // date + test_in_expression(::sqlpp::chrono::day_point{}); + + // timestamp + test_in_expression(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_in_expression(minute_point{}); + + // time_of_day + test_in_expression(std::chrono::microseconds{}); + + // text + test_like('7'); + test_like("seven"); + test_like(std::string("seven")); + test_like(sqlpp::compat::string_view("seven")); + +} + diff --git a/tests/core/types/logical_expression.cpp b/tests/core/types/logical_expression.cpp new file mode 100644 index 00000000..b2f538f6 --- /dev/null +++ b/tests/core/types/logical_expression.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-2016, 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_bool = std::is_same, sqlpp::boolean>; + + template + using is_maybe_bool = std::is_same, sqlpp::compat::optional>; +} + +template +void test_logical_expression(Value v) +{ + auto v_not_null= sqlpp::value(v); + auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v)); + + // Compare non-nullable with non-nullable. + static_assert(is_bool::value, ""); + static_assert(is_bool::value, ""); + + // Compare non-nullable with nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + + // Compare nullable with non-nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + + // Compare nullable with nullable. + static_assert(is_maybe_bool::value, ""); + static_assert(is_maybe_bool::value, ""); + + // not. + static_assert(is_bool::value, ""); + static_assert(is_maybe_bool::value, ""); +} + +int main() +{ + // boolean + test_logical_expression(bool{true}); +} + diff --git a/tests/core/types/result_row.cpp b/tests/core/types/result_row.cpp index 9981231b..9110476b 100644 --- a/tests/core/types/result_row.cpp +++ b/tests/core/types/result_row.cpp @@ -42,193 +42,73 @@ namespace auto db = MockDb{}; } +SQLPP_ALIAS_PROVIDER(r_not_null); +SQLPP_ALIAS_PROVIDER(r_maybe_null); +SQLPP_ALIAS_PROVIDER(r_opt_not_null); +SQLPP_ALIAS_PROVIDER(r_opt_maybe_null); + +template +void test_result_row(Value v) +{ + using OptResultType = sqlpp::compat::optional; + + // Selectable values. + auto v_not_null = sqlpp::value(v).as(r_not_null); + const auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_maybe_null); + + // Optional selectable values. + const auto v_opt_not_null = sqlpp::value(v).as(r_opt_not_null).if_(true); + const auto v_opt_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_opt_maybe_null).if_(true); + + for (const auto& row : db(select(v_not_null, v_maybe_null, v_opt_not_null, v_opt_maybe_null))) + { + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + } +} + int main() { - static_assert(not sqlpp::can_be_null::value, ""); - static_assert(sqlpp::can_be_null::value, ""); - static_assert(not sqlpp::can_be_null::value, ""); - static_assert(not sqlpp::can_be_null::value, ""); - const auto seven = sqlpp::value(7).as(sqlpp::alias::s); - static_assert(not sqlpp::can_be_null::value, ""); + // boolean + test_result_row(bool{true}); - // Select non-optional column or alias of it. - for (const auto& row : db(select(foo.id, foo.id.as(sqlpp::alias::a), foo.textNnD, foo.textNnD.as(sqlpp::alias::b)) - .from(foo) - .unconditionally())) - { - static_assert(is_same_type(), ""); - static_assert(is_same_type(), ""); - static_assert(is_same_type(), ""); - static_assert(is_same_type(), ""); - } + // integral + test_result_row(int8_t{7}); + test_result_row(int16_t{7}); + test_result_row(int32_t{7}); + test_result_row(int64_t{7}); - // Optionally select non-optional column or alias of it. - for (const auto& row : db(select(foo.id.if_(true), foo.id.as(sqlpp::alias::a).if_(true), foo.textNnD.if_(true), - foo.textNnD.as(sqlpp::alias::b).if_(true)) - .from(foo) - .unconditionally())) - { - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - } + // unsigned integral + test_result_row(uint8_t{7}); + test_result_row(uint16_t{7}); + test_result_row(uint32_t{7}); + test_result_row(uint64_t{7}); - // Select optional column or alias of it. - for (const auto& row : db(select(bar.intN, bar.intN.as(sqlpp::alias::a), bar.textN, bar.textN.as(sqlpp::alias::b)) - .from(bar) - .unconditionally())) - { - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - } + // floating point + test_result_row(float{7.7}); + test_result_row(double{7.7}); - // Optionally select optional column or alias of it. - for (const auto& row : db(select(bar.intN.if_(true), bar.intN.as(sqlpp::alias::a).if_(true), bar.textN.if_(true), - bar.textN.as(sqlpp::alias::b).if_(true)) - .from(bar) - .unconditionally())) - { - // optional optional are still represented as one level of optional - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - static_assert(is_same_type>(), ""); - } + // text + test_result_row('7'); + test_result_row("seven"); + test_result_row(std::string("seven")); + test_result_row(sqlpp::compat::string_view("seven")); - // Select value and optional value. - for (const auto& row : db(select(sqlpp::value(7).as(sqlpp::alias::a), - sqlpp::value(sqlpp::compat::optional(7)).as(sqlpp::alias::b)))) - { - static_assert(is_same_type(), ""); - static_assert(is_same_type>(), ""); - } + // blob + test_result_row>(std::vector{}); -#warning: also test with optional - static_assert(sqlpp::is_boolean::value, ""); - static_assert(sqlpp::is_boolean::value, ""); - static_assert(sqlpp::has_text_value::value, ""); - static_assert(sqlpp::has_text_value::value, ""); - static_assert(sqlpp::has_numeric_value::value, ""); - static_assert(sqlpp::has_numeric_value::value, ""); + // date + test_result_row<::sqlpp::chrono::day_point>(::sqlpp::chrono::day_point{}); -#warning: These should be moved into comparison type requirement tests, etc. - // Comparing optional value with non-optional value yields optional boolean. - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same= "hansi")>, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); + // timestamp + test_result_row<::sqlpp::chrono::microsecond_point>(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_result_row<::sqlpp::chrono::microsecond_point>(minute_point{}); - // Comparing non-optional value with non-optional value yields non-optional boolean. - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same= "hansi")>, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - - // The first exceptions are the operators is_null and is_not_null which always yield non-optional boolean -#warning: Still need to implement is_distinct_from as member function - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - - // The other exceptions are the operators is_distinct_from and is_not_distinct_from which always yield non-optional boolean -#warning: Still need to implement is_distinct_from as member function - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - - - // LIKE expressions can be NULL is one of their operands can be NULL. - static_assert(std::is_same, sqlpp::compat::optional>::value, ""); - static_assert(std::is_same, sqlpp::compat::optional>::value, ""); - static_assert(std::is_same, sqlpp::boolean>::value, ""); - -#warning: These should be moved into logical type requirement tests, etc. - // Logically combining optional value with non-optional value yields optional boolean. - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - static_assert(std::is_same, - sqlpp::compat::optional>::value, - ""); - - // Logically combining non-optional value with non-optional value yields non-optional boolean. - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); - static_assert(std::is_same, - sqlpp::boolean>::value, - ""); + // time_of_day + test_result_row(std::chrono::microseconds{}); // Arithmetically combining optional value with non-optional value yields optional boolean. static_assert(std::is_same, @@ -282,6 +162,7 @@ int main() sqlpp::compat::optional>::value, ""); + // in expression static_assert(std::is_same, sqlpp::compat::optional>::value, ""); diff --git a/tests/core/types/value.cpp b/tests/core/types/value.cpp new file mode 100644 index 00000000..3e9a6321 --- /dev/null +++ b/tests/core/types/value.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016-2016, 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{}; +} + +SQLPP_ALIAS_PROVIDER(r_not_null); +SQLPP_ALIAS_PROVIDER(r_maybe_null); +SQLPP_ALIAS_PROVIDER(r_opt_not_null); +SQLPP_ALIAS_PROVIDER(r_opt_maybe_null); + +template +using is_value_type = std::is_same, ValueType>; + +template +void test_value(Value v) +{ + using ValueType = sqlpp::value_type_of_t; + using OptValueType = sqlpp::compat::optional; + + auto v_not_null= sqlpp::value(v); + auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v)); + auto v_not_null_alias = sqlpp::value(v).as(r_not_null); + auto v_maybe_null_alias = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_maybe_null); + auto v_opt_not_null_alias = sqlpp::value(v).as(r_opt_not_null).if_(true); + auto v_opt_maybe_null_alias = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_opt_maybe_null).if_(true); + + static_assert(is_value_type::value, ""); + static_assert(is_value_type::value, ""); + static_assert(is_value_type::value, ""); + static_assert(is_value_type::value, ""); + static_assert(is_value_type::value, ""); + static_assert(is_value_type::value, ""); + + static_assert(not sqlpp::can_be_null::value, ""); + static_assert(sqlpp::can_be_null::value, ""); + static_assert(not sqlpp::can_be_null::value, ""); + static_assert(sqlpp::can_be_null::value, ""); + static_assert(sqlpp::can_be_null::value, ""); + static_assert(sqlpp::can_be_null::value, ""); +} + +int main() +{ + // boolean + test_value(bool{true}); + + // integral + test_value(int8_t{7}); + test_value(int16_t{7}); + test_value(int32_t{7}); + test_value(int64_t{7}); + + // unsigned integral + test_value(uint8_t{7}); + test_value(uint16_t{7}); + test_value(uint32_t{7}); + test_value(uint64_t{7}); + + // floating point + test_value(float{7.7}); + test_value(double{7.7}); + + // text + test_value('7'); + test_value("seven"); + test_value(std::string("seven")); + test_value(sqlpp::compat::string_view("seven")); + + // blob + test_value(std::vector{}); + + // date + test_value(::sqlpp::chrono::day_point{}); + + // timestamp + test_value(::sqlpp::chrono::microsecond_point{}); + using minute_point = std::chrono::time_point; + test_value(minute_point{}); + + // time_of_day + test_value(std::chrono::microseconds{}); + +} +