From 43ec2343c3b97ebe15039ea8a88458543c37ed32 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 20 Aug 2019 10:31:54 +0200 Subject: [PATCH] Fix serialization of empty dynamic_where It was serialized with a dummy expression, which turned out to be problematic for some vendors, see #282 --- include/sqlpp11/where.h | 36 ++++++++++++++++++++-- test_serializer/CMakeLists.txt | 11 ++++--- test_serializer/DynamicWhere.cpp | 53 ++++++++++++++++++++++++++++++++ tests/Update.cpp | 3 ++ 4 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 test_serializer/DynamicWhere.cpp diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index d79d390e..2d7298d0 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -256,6 +256,10 @@ namespace sqlpp static_check_t::value, assert_where_dynamic_used_with_dynamic_statement_t>, check_where_t>; + template + using check_where_empty_dynamic_t = static_combined_check_t< + static_check_t::value, assert_where_dynamic_used_with_dynamic_statement_t>>; + // NO WHERE YET template struct no_where_t @@ -338,10 +342,11 @@ namespace sqlpp return _where_impl<_database_t>(Check{}, expression); } - auto dynamic_where() const -> _new_statement_t, - where_t<_database_t, boolean_operand>> + auto dynamic_where() const + -> _new_statement_t, where_t<_database_t, unconditional_t>> { - return dynamic_where(::sqlpp::value(true)); + return {static_cast&>(*this), + where_data_t<_database_t, unconditional_t>{unconditional_t{}}}; } private: @@ -378,6 +383,24 @@ namespace sqlpp } }; + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using T = where_data_t; + + static Context& _(const T& t, Context& context) + { + if (t._dynamic_expressions.empty()) + { + return context; + } + context << " WHERE "; + interpret_list(t._dynamic_expressions, " AND ", context); + return context; + } + }; + template struct serializer_t> { @@ -403,6 +426,13 @@ namespace sqlpp return statement_t>().dynamic_where(std::forward(t)); } + template + auto dynamic_where(const Database & /*unused*/) + -> decltype(statement_t>().dynamic_where()) + { + return statement_t>().dynamic_where(); + } + inline auto unconditionally() -> decltype(statement_t>().unconditionally()) { return statement_t>().unconditionally(); diff --git a/test_serializer/CMakeLists.txt b/test_serializer/CMakeLists.txt index 2e20950c..0db89df9 100644 --- a/test_serializer/CMakeLists.txt +++ b/test_serializer/CMakeLists.txt @@ -26,12 +26,13 @@ set(test_serializer_names As Blob CustomQuery - ForUpdate - From - In - Insert + DynamicWhere + ForUpdate + From + In + Insert TableAlias - Where + Where ) create_test_sourcelist(test_serializer_sources test_serializer_main.cpp ${test_serializer_names}) diff --git a/test_serializer/DynamicWhere.cpp b/test_serializer/DynamicWhere.cpp new file mode 100644 index 00000000..3fa9b0dc --- /dev/null +++ b/test_serializer/DynamicWhere.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016-2019, 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 "compare.h" +#include "Sample.h" +#include + +#include + +int DynamicWhere(int, char*[]) +{ + const auto bar = test::TabBar{}; + auto db = MockDb{}; + + compare(__LINE__, dynamic_where(db), ""); + compare(__LINE__, dynamic_where(db, bar.gamma), " WHERE tab_bar.gamma"); + + { + auto statement = sqlpp::dynamic_where(db); + statement.where.add(without_table_check(bar.gamma)); + compare(__LINE__, statement, " WHERE tab_bar.gamma"); + } + + { + auto statement = dynamic_where(db, bar.gamma); + statement.where.add(without_table_check(bar.gamma)); + compare(__LINE__, statement, " WHERE tab_bar.gamma AND tab_bar.gamma"); + } + + return 0; +} diff --git a/tests/Update.cpp b/tests/Update.cpp index 5f9a6345..fb4c522e 100644 --- a/tests/Update.cpp +++ b/tests/Update.cpp @@ -66,6 +66,9 @@ int Update(int, char*[]) auto values = [&t]() { return std::make_tuple(t.delta += t.alpha, t.beta = "no cake this time"); }; db(update(t).set(t.delta = sqlpp::verbatim("17+4")).unconditionally()); + db(update(t) + .set(t.delta = sqlpp::verbatim("17+4")) + .where(sqlpp::verbatim("'hansi'") == "hansi")); db(update(t).set(t.delta = sqlpp::null).unconditionally()); db(update(t).set(t.delta = sqlpp::default_value).unconditionally());