diff --git a/include/sqlpp11/assignment.h b/include/sqlpp11/assignment.h index 36938311..4594f663 100644 --- a/include/sqlpp11/assignment.h +++ b/include/sqlpp11/assignment.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -70,9 +71,8 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (((trivial_value_is_null_t::value or is_tvin_t::value) - and is_trivial(t._rhs)) - or (std::is_same::value)) + if ((trivial_value_is_null_t::value and rhs_is_trivial(t)) + or rhs_is_null(t)) { serialize(simple_column(t._lhs), context); context << "=NULL"; diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index 0ed43af3..be7b195d 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -123,6 +123,8 @@ namespace sqlpp using _field_methods_t = field_methods_t<_result_field_t>; using _traits = make_traits>; struct _recursive_traits @@ -160,6 +162,14 @@ namespace sqlpp return _is_null; } + bool is_trivial() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + + return value() == false; + } + _cpp_value_type value() const { if (not _is_valid) diff --git a/include/sqlpp11/expression.h b/include/sqlpp11/expression.h index c856b56f..cb221ccd 100644 --- a/include/sqlpp11/expression.h +++ b/include/sqlpp11/expression.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -70,7 +72,8 @@ namespace sqlpp { context << "("; serialize(t._lhs, context); - if (rhs_is_null(t)) + if ((trivial_value_is_null_t::value and rhs_is_trivial(t)) + or rhs_is_null(t)) { context << " IS NULL"; } @@ -117,7 +120,8 @@ namespace sqlpp { context << "("; serialize(t._lhs, context); - if (rhs_is_null(t)) + if ((trivial_value_is_null_t::value and rhs_is_trivial(t)) + or rhs_is_null(t)) { context << " IS NOT NULL"; } diff --git a/include/sqlpp11/floating_point.h b/include/sqlpp11/floating_point.h index da5f3943..37c69207 100644 --- a/include/sqlpp11/floating_point.h +++ b/include/sqlpp11/floating_point.h @@ -122,6 +122,8 @@ namespace sqlpp using _field_methods_t = field_methods_t<_result_field_t>; using _traits = make_traits>; struct _recursive_traits @@ -159,6 +161,14 @@ namespace sqlpp return _is_null; } + bool is_trivial() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + + return value() == 0; + } + _cpp_value_type value() const { if (not _is_valid) diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index 8dad0912..c1441fd3 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -123,6 +123,8 @@ namespace sqlpp using _field_methods_t = field_methods_t<_result_field_t>; using _traits = make_traits>; struct _recursive_traits @@ -160,6 +162,14 @@ namespace sqlpp return _is_null; } + bool is_trivial() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + + return value() == 0; + } + _cpp_value_type value() const { if (not _is_valid) diff --git a/include/sqlpp11/rhs_is_null.h b/include/sqlpp11/rhs_is_null.h index 1eda20d9..aa6d8ed0 100644 --- a/include/sqlpp11/rhs_is_null.h +++ b/include/sqlpp11/rhs_is_null.h @@ -32,7 +32,7 @@ namespace sqlpp { template - struct is_trivial_t + struct rhs_is_null_t { static constexpr bool _(const T&) { @@ -41,27 +41,29 @@ namespace sqlpp }; template - struct is_trivial_t::value, void>::type> + struct rhs_is_null_t::value, void>::type> { static bool _(const T& t) { - return t._is_trivial(); + return t._is_null(); } }; template - bool is_trivial(const T& t) + struct rhs_is_null_t::value, void>::type> { - return is_trivial_t::_(t); - } + static bool _(const T& t) + { + return t.is_null(); + } + }; template constexpr bool rhs_is_null(const Expression& e) { - return (((trivial_value_is_null_t::value or is_tvin_t::value) - and is_trivial(e._rhs)) - or (std::is_same::value)); + return rhs_is_null_t::type::_rhs_t>::_(e._rhs); } + } #endif diff --git a/include/sqlpp11/rhs_is_trivial.h b/include/sqlpp11/rhs_is_trivial.h new file mode 100644 index 00000000..14de2675 --- /dev/null +++ b/include/sqlpp11/rhs_is_trivial.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013-2014, 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_RHS_IS_TRIVIAL_H +#define SQLPP_RHS_IS_TRIVIAL_H + +#include + +namespace sqlpp +{ + template + struct rhs_is_trivial_t + { + static constexpr bool _(const T&) + { + return false; + } + }; + + template + struct rhs_is_trivial_t::value, void>::type> + { + static bool _(const T& t) + { + return t._is_trivial(); + } + }; + + template + struct rhs_is_trivial_t::value, void>::type> + { + static bool _(const T& t) + { + return t._is_trivial(); + } + }; + + template + struct rhs_is_trivial_t::value, void>::type> + { + static bool _(const T& t) + { + return t.is_trivial(); + } + }; + + template + constexpr bool rhs_is_trivial(const Expression& e) + { + return rhs_is_trivial_t::type::_rhs_t>::_(e._rhs); + } +} + +#endif diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index e90d5e6c..d45544f3 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -122,6 +122,8 @@ namespace sqlpp using _field_methods_t = field_methods_t<_result_field_t>; using _traits = make_traits>; struct _recursive_traits @@ -162,6 +164,14 @@ namespace sqlpp return _value_ptr == nullptr; } + bool is_trivial() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + + return value() == ""; + } + _cpp_value_type value() const { if (not _is_valid) diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index 0b80cc44..7f3cce23 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -108,6 +108,11 @@ namespace sqlpp return _value._is_trivial(); } + bool _is_null() const + { + return _value._is_trivial(); + } + _operand_t _value; }; diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 659d7bab..79e3f22a 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -85,6 +85,7 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression); SQLPP_VALUE_TRAIT_GENERATOR(is_alias); SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag); + SQLPP_VALUE_TRAIT_GENERATOR(is_result_field); SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert); SQLPP_VALUE_TRAIT_GENERATOR(must_not_update); diff --git a/tests/ResultTest.cpp b/tests/ResultTest.cpp index 1353c791..c54d7686 100644 --- a/tests/ResultTest.cpp +++ b/tests/ResultTest.cpp @@ -47,6 +47,20 @@ int main() { static_assert(sqlpp::can_be_null_t::value, "row.alpha can be null"); static_assert(sqlpp::null_is_trivial_value_t::value, "row.alpha interprets null_is_trivial"); + static_assert(std::is_member_function_pointer::value, "Yikes"); + using T = sqlpp::wrap_operand_t; + static_assert(sqlpp::can_be_null_t::value, "row.alpha can be null"); + static_assert(sqlpp::is_result_field_t::value, "row.alpha can be null"); + + bool x = sqlpp::rhs_is_null(t.alpha == row.alpha); + bool y = sqlpp::rhs_is_trivial(t.alpha == row.alpha); + std::cerr << x << std::endl; + std::cerr << y << std::endl; + + for (const auto& sub : db(select(all_of(t)).from(t).where(t.alpha == row.alpha))) + { + std::cerr << sub.alpha << std::endl; + } } sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t); diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 5ccc94e4..1e97562c 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -64,7 +64,7 @@ int main() std::cout << a << ", " << b << ", " << g << std::endl; } - for (const auto& row : db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega)).where(true))) + for (const auto& row : db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).where(true))) { std::cout << row.alpha << std::endl; }