diff --git a/include/sqlpp11/detail/basic_operators.h b/include/sqlpp11/detail/basic_operators.h index 1b60933a..41425f96 100644 --- a/include/sqlpp11/detail/basic_operators.h +++ b/include/sqlpp11/detail/basic_operators.h @@ -138,13 +138,13 @@ namespace sqlpp // Hint: use value_list wrapper for containers... template - in_t::type...> in(T&&... t) const + in_t::type...> in(T&&... t) const { return { *static_cast(this), std::forward(t)... }; } template - in_t::type...> not_in(T&&... t) const + in_t::type...> not_in(T&&... t) const { return { *static_cast(this), std::forward(t)... }; } diff --git a/include/sqlpp11/in.h b/include/sqlpp11/in.h index f7345ecf..660787df 100644 --- a/include/sqlpp11/in.h +++ b/include/sqlpp11/in.h @@ -35,13 +35,14 @@ namespace sqlpp { namespace detail { - template - struct in_t: public Operand::_value_type::template operators> + // The ValueType should be boolean, this is a hack because boolean is not fully defined when the compiler first gets here... + template + struct in_t: public ValueType::_base_value_type::template operators> { static constexpr bool _inverted = not NotInverted; static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); - struct _value_type: public Operand::_value_type::_base_value_type + struct _value_type: public ValueType::_base_value_type // we requite fully defined boolean here { using _is_named_expression = std::true_type; }; diff --git a/include/sqlpp11/like.h b/include/sqlpp11/like.h index 4213841e..51e7698c 100644 --- a/include/sqlpp11/like.h +++ b/include/sqlpp11/like.h @@ -35,13 +35,14 @@ namespace sqlpp { namespace detail { - template - struct like_t: public Operand::_value_type::template operators> + // The ValueType should be boolean, this is a hack because boolean is not fully defined when the compiler first gets here... + template + struct like_t: public ValueType::_base_value_type::template operators> { static_assert(is_text_t::value, "Operand for like() has to be a text"); static_assert(is_text_t::value, "Pattern for like() has to be a text"); - struct _value_type: public Operand::_value_type::_base_value_type + struct _value_type: public ValueType::_base_value_type // we requite fully defined boolean here { using _is_named_expression = std::true_type; }; @@ -87,12 +88,6 @@ namespace sqlpp Pattern _pattern; }; } - - template - auto like(T&&... t) -> typename detail::like_t::type...> - { - return { std::forward(t)... }; - } } #endif diff --git a/include/sqlpp11/sum.h b/include/sqlpp11/sum.h index 6b8d7c2b..1f9b3ef4 100644 --- a/include/sqlpp11/sum.h +++ b/include/sqlpp11/sum.h @@ -24,8 +24,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_MAX_H -#define SQLPP_MAX_H +#ifndef SQLPP_SUM_H +#define SQLPP_SUM_H #include #include @@ -35,7 +35,7 @@ namespace sqlpp namespace detail { template - struct max_t: public boolean::template operators> + struct sum_t: public boolean::template operators> { static_assert(is_numeric_t::value, "sum() requires a numeric expression as argument"); @@ -50,23 +50,23 @@ namespace sqlpp template struct _member_t { - T max; + T sum; }; }; - max_t(Expr&& expr): + sum_t(Expr&& expr): _expr(std::move(expr)) {} - max_t(const Expr& expr): + sum_t(const Expr& expr): _expr(expr) {} - max_t(const max_t&) = default; - max_t(max_t&&) = default; - max_t& operator=(const max_t&) = default; - max_t& operator=(max_t&&) = default; - ~max_t() = default; + sum_t(const sum_t&) = default; + sum_t(sum_t&&) = default; + sum_t& operator=(const sum_t&) = default; + sum_t& operator=(sum_t&&) = default; + ~sum_t() = default; template void serialize(std::ostream& os, Db& db) const @@ -83,7 +83,7 @@ namespace sqlpp } template - auto max(T&& t) -> typename detail::max_t::type> + auto sum(T&& t) -> typename detail::sum_t::type> { return { std::forward(t) }; } diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index e7b2473a..33faec34 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -110,7 +110,7 @@ namespace sqlpp } template - detail::like_t::type> like(T&& t) const + detail::like_t::type> like(T&& t) const { return { *static_cast(this), std::forward(t) }; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c0d709dd..abc1625f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,4 +7,5 @@ build_and_run(InsertTest) build_and_run(RemoveTest) build_and_run(UpdateTest) build_and_run(SelectTest) +build_and_run(FunctionTest) diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp new file mode 100644 index 00000000..7d94f21b --- /dev/null +++ b/tests/FunctionTest.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2013, 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 "TabSample.h" +#include "MockDb.h" +#include +#include +#include + +#include + +DbMock db = {}; + +int main() +{ + TabSample t; + TabFoo f; + + // MEMBER FUNCTIONS + // ---------------- + + // Test in + { + using TI = decltype(t.alpha.in(1, 2, 3)); + using TF = decltype(f.omega.in(1.0, 2.0, 3.0)); + using TT = decltype(t.beta.in("a", "b", "c")); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + } + + // Test not_in + { + using TI = decltype(t.alpha.not_in(1, 2, 3)); + using TF = decltype(f.omega.not_in(1.0, 2.0, 3.0)); + using TT = decltype(t.beta.not_in("a", "b", "c")); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + } + + // Test like + { + using TT = decltype(t.beta.like("%c%")); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + } + + // SUB_SELECT_FUNCTIONS + // -------------------- + + // Test exists + { + using TI = decltype(exists(select(t.alpha).from(t))); + using TT = decltype(exists(select(t.beta).from(t))); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + } + + // Test any + { + using TI = decltype(any(select(t.alpha).from(t))); + using TT = decltype(any(select(t.beta).from(t))); + using TF = decltype(any(select(f.omega).from(t))); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_text_t::value, "type requirement"); + } + + // Test some + { + using TI = decltype(some(select(t.alpha).from(t))); + using TT = decltype(some(select(t.beta).from(t))); + using TF = decltype(some(select(f.omega).from(t))); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_text_t::value, "type requirement"); + } + + // NUMERIC FUNCTIONS + // ----------------- + + // Test avg + { + using TI = decltype(avg(t.alpha)); + using TF = decltype(avg(f.omega)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + } + + // Test count + { + using TI = decltype(count(t.alpha)); + using TT = decltype(count(t.beta)); + using TF = decltype(count(f.omega)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + } + + // Test max + { + using TI = decltype(max(t.alpha)); + using TF = decltype(max(f.omega)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + } + + // Test min + { + using TI = decltype(min(t.alpha)); + using TF = decltype(min(f.omega)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + } + + // Test sum + { + using TI = decltype(sum(t.alpha)); + using TF = decltype(sum(f.omega)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + } + + return 0; +} diff --git a/tests/MockDb.h b/tests/MockDb.h new file mode 100644 index 00000000..b558a5ae --- /dev/null +++ b/tests/MockDb.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 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. + */ + +#ifndef SQLPP_MOCK_DB_H +#define SQLPP_MOCK_DB_H + +#include + +class DbMock: public sqlpp::connection +{ +public: + // join types + static constexpr bool _supports_inner_join = true; + static constexpr bool _supports_outer_join = true; + static constexpr bool _supports_left_outer_join = true; + static constexpr bool _supports_right_outer_join = true; + + // functions + static constexpr bool _supports_avg = true; + static constexpr bool _supports_count = true; + static constexpr bool _supports_exists = true; + static constexpr bool _supports_like = true; + static constexpr bool _supports_in = true; + static constexpr bool _supports_max = true; + static constexpr bool _supports_min = true; + static constexpr bool _supports_not_in = true; + static constexpr bool _supports_sum = true; + + // select + static constexpr bool _supports_group_by = true; + static constexpr bool _supports_having = true; + static constexpr bool _supports_limit = true; + static constexpr bool _supports_order_by = true; + static constexpr bool _supports_select_as_table = true; + + static constexpr bool _supports_some = true; + static constexpr bool _supports_any = true; + static constexpr bool _use_concat_operator = true; + static constexpr bool _use_concat_function = true; + + const std::string& escape(const std::string& text) { return text; } +}; + +#endif +