diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index ee359f2d..97a7d525 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -47,6 +47,7 @@ #include #include #include +#include #include namespace sqlpp diff --git a/include/sqlpp11/is_equal_to_or_null.h b/include/sqlpp11/is_equal_to_or_null.h new file mode 100644 index 00000000..4f29f1fc --- /dev/null +++ b/include/sqlpp11/is_equal_to_or_null.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 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 SQLPP11_IS_EQUAL_TO_OR_NULL_H +#define SQLPP11_IS_EQUAL_TO_OR_NULL_H + +#include + +namespace sqlpp +{ + template + struct is_equal_to_or_null_t: public expression_operators, boolean>, + public alias_operators> + { + using _traits = make_traits; + using _nodes = detail::type_vector>; + + is_equal_to_or_null_t(Expr expr, value_or_null_t value) : _expr(expr), _value(value) + { + } + + is_equal_to_or_null_t(const is_equal_to_or_null_t&) = default; + is_equal_to_or_null_t(is_equal_to_or_null_t&&) = default; + is_equal_to_or_null_t& operator=(const is_equal_to_or_null_t&) = default; + is_equal_to_or_null_t& operator=(is_equal_to_or_null_t&&) = default; + ~is_equal_to_or_null_t() = default; + + + Expr _expr; + value_or_null_t _value; + }; + + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using Operand = is_equal_to_or_null_t; + + static Context& _(const Operand& t, Context& context) + { + if (t._value._is_null) + serialize(t._expr.is_null(), context); + else + serialize(t._expr == t._value, context); + + return context; + } + }; + + template + auto is_equal_to_or_null(Expr expr, value_or_null_t value) -> is_equal_to_or_null_t + { + static_assert(is_expression_t::value, + "is_equal_to_or_null() is to be called an expression (e.g. a column) and a value_or_null expression"); + static_assert(std::is_same, ValueType>::value, + "is_equal_to_or_null() arguments need to have the same value type"); + return {expr, value}; + } + +} // namespace sqlpp + +#endif diff --git a/include/sqlpp11/is_not_null.h b/include/sqlpp11/is_not_null.h index de763f7b..164bf639 100644 --- a/include/sqlpp11/is_not_null.h +++ b/include/sqlpp11/is_not_null.h @@ -78,8 +78,9 @@ namespace sqlpp static Context& _(const T& t, Context& context) { + context << "("; serialize_operand(t._operand, context); - context << " IS NOT NULL"; + context << " IS NOT NULL)"; return context; } }; diff --git a/include/sqlpp11/is_null.h b/include/sqlpp11/is_null.h index 38275d4b..9396a234 100644 --- a/include/sqlpp11/is_null.h +++ b/include/sqlpp11/is_null.h @@ -78,8 +78,9 @@ namespace sqlpp static Context& _(const T& t, Context& context) { + context << "("; serialize_operand(t._operand, context); - context << " IS NULL"; + context << " IS NULL)"; return context; } }; diff --git a/test_serializer/Where.cpp b/test_serializer/Where.cpp index d3f5761b..cbb1a7fe 100644 --- a/test_serializer/Where.cpp +++ b/test_serializer/Where.cpp @@ -63,8 +63,11 @@ int Where(int, char*[]) // Sometimes compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma"); compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")"); - compare(__LINE__, where(bar.beta.is_null()), " WHERE tab_bar.beta IS NULL"); + compare(__LINE__, where(bar.beta.is_null()), " WHERE (tab_bar.beta IS NULL)"); compare(__LINE__, where(bar.beta == "SQL"), " WHERE (tab_bar.beta='SQL')"); + compare(__LINE__, where(is_equal_to_or_null(bar.beta, ::sqlpp::value_or_null("SQL"))), " WHERE (tab_bar.beta='SQL')"); + compare(__LINE__, where(is_equal_to_or_null(bar.beta, ::sqlpp::value_or_null(::sqlpp::null))), + " WHERE (tab_bar.beta IS NULL)"); #if __cplusplus >= 201703L // string_view argument std::string_view sqlString = "SQL";