From a836e8c8d8d7ad1665bde3ed94b3536b053cd7a8 Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 16 Mar 2016 07:58:12 +0100 Subject: [PATCH] Simplified where() to have one argument only --- include/sqlpp11/from.h | 2 +- include/sqlpp11/functions.h | 11 +-- include/sqlpp11/having.h | 8 +- include/sqlpp11/value.h | 43 +++++++++++ include/sqlpp11/verbatim_table.h | 3 +- include/sqlpp11/where.h | 126 +++++++++++++++---------------- test_static_asserts/where.cpp | 22 +++--- tests/Remove.cpp | 2 +- 8 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 include/sqlpp11/value.h diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index e737bd67..6a50bea8 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2016, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 1351c0d2..bb208eb3 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2016, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -42,19 +42,12 @@ #include #include // Csaba Csoma suggests: unsafe_sql instead of verbatim #include +#include #include #include namespace sqlpp { - template - auto value(T t) -> wrap_operand_t - { - static_assert(is_wrapped_value_t>::value, - "value() is to be called with non-sql-type like int, or string"); - return {t}; - } - template auto flatten(const Expression& exp, Db& db) -> verbatim_t> { diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index 6a2b397f..534cf291 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2016, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,7 @@ #define SQLPP_HAVING_H #include +#include #include #include #include @@ -234,6 +235,11 @@ namespace sqlpp return _having_impl<_database_t>(_check{}, expression); } + auto dynamic_having() const -> _new_statement_t<_check, having_t<_database_t, boolean_operand>> + { + return dynamic_having(::sqlpp::value(true)); + } + private: template auto _having_impl(const std::false_type&, Expression expression) const -> bad_statement; diff --git a/include/sqlpp11/value.h b/include/sqlpp11/value.h new file mode 100644 index 00000000..0df9a34b --- /dev/null +++ b/include/sqlpp11/value.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013-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. + */ + +#ifndef SQLPP_VALUE_H +#define SQLPP_VALUE_H + +#include + +namespace sqlpp +{ + template + auto value(T t) -> wrap_operand_t + { + static_assert(is_wrapped_value_t>::value, + "value() is to be called with non-sql-type like int, or string"); + return {t}; + } +} + +#endif diff --git a/include/sqlpp11/verbatim_table.h b/include/sqlpp11/verbatim_table.h index 1618bd07..2fb2df7a 100644 --- a/include/sqlpp11/verbatim_table.h +++ b/include/sqlpp11/verbatim_table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2016, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,6 +27,7 @@ #ifndef SQLPP_VERBATIM_TABLE_H #define SQLPP_VERBATIM_TABLE_H +#include #include namespace sqlpp diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index d9591b9e..3a8f1d39 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2016, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -39,10 +40,10 @@ namespace sqlpp { // WHERE DATA - template + template struct where_data_t { - where_data_t(Expressions... expressions) : _expressions(expressions...) + where_data_t(Expression expression) : _expression(expression) { } @@ -52,7 +53,7 @@ namespace sqlpp where_data_t& operator=(where_data_t&&) = default; ~where_data_t() = default; - std::tuple _expressions; + Expression _expression; interpretable_list_t _dynamic_expressions; }; @@ -61,16 +62,16 @@ namespace sqlpp "at least one expression in where() requires a table which is otherwise not known in the statement"); // WHERE(EXPR) - template + template struct where_t { using _traits = make_traits; - using _nodes = detail::type_vector; + using _nodes = detail::type_vector; using _is_dynamic = is_database; // Data - using _data_t = where_data_t; + using _data_t = where_data_t; // Member implementation with data and methods template @@ -82,39 +83,39 @@ namespace sqlpp { } - template - void add_ntc(Expression expression) + template + void add_ntc(Expr expression) { - add(expression); + add(expression); } - template - void add(Expression expression) + template + void add(Expr expression) { static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where"); - static_assert(is_expression_t::value, "invalid expression argument in where::add()"); - static_assert(is_boolean_t::value, "invalid expression argument in where::add()"); - static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, + static_assert(is_expression_t::value, "invalid expression argument in where::add()"); + static_assert(is_boolean_t::value, "invalid expression argument in where::add()"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in where::add()"); - static_assert(not contains_aggregate_function_t::value, + static_assert(not contains_aggregate_function_t::value, "where expression must not contain aggregate functions"); - using _serialize_check = sqlpp::serialize_check_t; + using _serialize_check = sqlpp::serialize_check_t; _serialize_check::_(); - using ok = logic::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; + using ok = logic::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } private: - template - void _add_impl(Expression expression, const std::true_type&) + template + void _add_impl(Expr expression, const std::true_type&) { return _data._dynamic_expressions.emplace_back(expression); } - template - void _add_impl(Expression expression, const std::false_type&); + template + void _add_impl(Expr expression, const std::false_type&); public: _data_t _data; @@ -124,7 +125,7 @@ namespace sqlpp template struct _base_t { - using _data_t = where_data_t; + using _data_t = where_data_t; // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269 template @@ -225,7 +226,6 @@ namespace sqlpp "where() argument has to be an sqlpp boolean expression."); SQLPP_PORTABLE_STATIC_ASSERT(assert_where_no_aggregate_functions_t, "at least one aggregate function used in where()"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_where_static_count_args_t, "missing argument in where()"); SQLPP_PORTABLE_STATIC_ASSERT(assert_where_dynamic_statement_dynamic_t, "dynamic_where() must not be called in a static statement"); @@ -240,30 +240,26 @@ namespace sqlpp // static_check_t::value...>::value, assert_where_boolean_expression_t>, // static_check_t::value)...>::value, // assert_where_no_aggregate_functions_t>>; - template + template struct check_where { using type = static_combined_check_t< - static_check_t::value...>::value, assert_where_not_cpp_bool_t>, - static_check_t::type::value...>::value, - assert_where_boolean_expression_t>, - static_check_t::value...>::value, assert_where_boolean_expression_t>, - static_check_t::type::value)...>::value, - assert_where_no_aggregate_functions_t>>; + static_check_t::value, assert_where_not_cpp_bool_t>, + static_check_t::value, assert_where_boolean_expression_t>, + static_check_t::value, assert_where_boolean_expression_t>, + static_check_t::value, assert_where_no_aggregate_functions_t>>; }; - template - using check_where_t = typename check_where::type; + template + using check_where_t = typename check_where::type; - template - using check_where_static_t = - static_combined_check_t, - static_check_t>; + template + using check_where_static_t = check_where_t; - template + template using check_where_dynamic_t = static_combined_check_t< static_check_t::value, assert_where_dynamic_statement_dynamic_t>, - check_where_t>; + check_where_t>; // NO WHERE YET template @@ -332,54 +328,58 @@ namespace sqlpp return {static_cast&>(*this), where_data_t{}}; } - template - auto where(Expressions... expressions) const - -> _new_statement_t, where_t> + template + auto where(Expression expression) const + -> _new_statement_t, where_t> { - using Check = check_where_static_t; + using Check = check_where_static_t; Check{}._(); - return _where_impl(Check{}, expressions...); + return _where_impl(Check{}, expression); } - template - auto dynamic_where(Expressions... expressions) const - -> _new_statement_t, where_t<_database_t, Expressions...>> + template + auto dynamic_where(Expression expression) const + -> _new_statement_t, where_t<_database_t, Expression>> { - using Check = check_where_dynamic_t<_database_t, Expressions...>; + using Check = check_where_dynamic_t<_database_t, Expression>; Check{}._(); - return _where_impl<_database_t>(Check{}, expressions...); + return _where_impl<_database_t>(Check{}, expression); + } + + auto dynamic_where() const -> _new_statement_t, + where_t<_database_t, boolean_operand>> + { + return dynamic_where(::sqlpp::value(true)); } private: - template - auto _where_impl(const std::false_type&, Expressions... expressions) const -> bad_statement; + template + auto _where_impl(const std::false_type&, Expression expression) const -> bad_statement; - template - auto _where_impl(const std::true_type&, Expressions... expressions) const - -> _new_statement_t> + template + auto _where_impl(const std::true_type&, Expression expression) const + -> _new_statement_t> { return {static_cast&>(*this), - where_data_t{expressions...}}; + where_data_t{expression}}; } }; }; // Interpreters - template - struct serializer_t> + template + struct serializer_t> { - using _serialize_check = serialize_check_of; - using T = where_data_t; + using _serialize_check = serialize_check_of; + using T = where_data_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) - return context; context << " WHERE "; - interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) + serialize(t._expression, context); + if (not t._dynamic_expressions.empty()) context << " AND "; interpret_list(t._dynamic_expressions, " AND ", context); return context; diff --git a/test_static_asserts/where.cpp b/test_static_asserts/where.cpp index 5694a296..186b9c9d 100644 --- a/test_static_asserts/where.cpp +++ b/test_static_asserts/where.cpp @@ -43,31 +43,31 @@ namespace T::_print_me_; } - template - void where_static_check(const Expressions&... expressions) + template + void where_static_check(const Expression& expression) { - using CheckResult = sqlpp::check_where_static_t; + using CheckResult = sqlpp::check_where_static_t; using ExpectedCheckResult = std::is_same; print_type_on_error(ExpectedCheckResult{}); static_assert(ExpectedCheckResult::value, "Unexpected check result"); - using ReturnType = decltype(remove_from(t).where(expressions...)); + using ReturnType = decltype(remove_from(t).where(expression)); using ExpectedReturnType = sqlpp::logic::all_t::value>; print_type_on_error(ExpectedReturnType{}); static_assert(ExpectedReturnType::value, "Unexpected return type"); } - template - void where_dynamic_check(const Expressions&... expressions) + template + void where_dynamic_check(const Expression& expression) { static auto db = MockDb{}; - using CheckResult = sqlpp::check_where_dynamic_t; + using CheckResult = sqlpp::check_where_dynamic_t; using ExpectedCheckResult = std::is_same; print_type_on_error(ExpectedCheckResult{}); static_assert(ExpectedCheckResult::value, "Unexpected check result"); - using ReturnType = decltype(dynamic_remove_from(db, t).dynamic_where(expressions...)); + using ReturnType = decltype(dynamic_remove_from(db, t).dynamic_where(expression)); using ExpectedReturnType = sqlpp::logic::all_t::value>; print_type_on_error(ExpectedReturnType{}); @@ -80,9 +80,6 @@ namespace where_static_check(t.gamma); where_static_check(t.gamma == true); - // Try no expression - where_static_check(); - // Try assignment as condition where_static_check(t.gamma = true); @@ -110,7 +107,6 @@ namespace void dynamic_where() { // OK - where_dynamic_check(); where_dynamic_check(t.gamma); where_dynamic_check(t.gamma == true); @@ -138,7 +134,7 @@ namespace case_when(count(t.alpha) > 0).then(t.gamma).else_(not t.gamma)); // Try dynamic_where on a non-dynamic remove - using CheckResult = sqlpp::check_where_dynamic_t; + using CheckResult = sqlpp::check_where_dynamic_t; using ExpectedCheckResult = std::is_same; print_type_on_error(ExpectedCheckResult{}); static_assert(ExpectedCheckResult::value, "Unexpected check result"); diff --git a/tests/Remove.cpp b/tests/Remove.cpp index b1442c09..679299a4 100644 --- a/tests/Remove.cpp +++ b/tests/Remove.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2016, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification,