From 51e0db883f632b456c5c707f38e76e6464047148 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Sun, 5 Jan 2014 13:29:08 +0100 Subject: [PATCH] Added static assert to prevent automatic rivial->null conversion to happen in where/having --- include/sqlpp11/having.h | 7 +++++-- include/sqlpp11/parameter.h | 11 +++++++++-- include/sqlpp11/parameter_list.h | 22 +++++++++++++++++++++- include/sqlpp11/where.h | 8 ++++++-- tests/PreparedTest.cpp | 2 +- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index eed521d5..93db4806 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -41,11 +41,15 @@ namespace sqlpp { using _is_having = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in having()"); using _valid_expressions = typename detail::make_set_if::type; static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()"); + using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + static_assert(not _parameter_list_t::_contains_trivial_value_is_null_t::value, "must not use trivial_value_is_null in parameters of having expression, use where_parameter() instead of parameter() to turn off automatic conversion"); + template void add(E&& expr) { @@ -70,8 +74,7 @@ namespace sqlpp return set_parameter_index(_expressions, index); } - using _parameter_tuple_t = std::tuple; - _parameter_tuple_t _expressions; // FIXME: Do we need those? + _parameter_tuple_t _expressions; detail::serializable_list _dynamic_expressions; }; diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index 2563f32c..f76fded8 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -40,9 +40,9 @@ namespace sqlpp using _is_parameter = std::true_type; using _is_expression_t = std::true_type; using _instance_t = typename NameType::_name_t::template _member_t; - using _trivial_value_is_null = TrivialValueIsNull; + using _trivial_value_is_null_t = TrivialValueIsNull; - static_assert(std::is_same<_trivial_value_is_null, std::true_type>::value or std::is_same<_trivial_value_is_null, std::false_type>::value, "Invalid template parameter TrivialValueIsNull"); + static_assert(std::is_same<_trivial_value_is_null_t, std::true_type>::value or std::is_same<_trivial_value_is_null_t, std::false_type>::value, "Invalid template parameter TrivialValueIsNull"); template void serialize(std::ostream& os, Db& db) const @@ -70,6 +70,13 @@ namespace sqlpp return {}; } + template + auto where_parameter(NamedExpr&& namedExpr) + -> parameter_t::type::_value_type, typename std::decay::type, std::false_type> + { + return {}; + } + } #endif diff --git a/include/sqlpp11/parameter_list.h b/include/sqlpp11/parameter_list.h index 406d752d..51571ee9 100644 --- a/include/sqlpp11/parameter_list.h +++ b/include/sqlpp11/parameter_list.h @@ -32,6 +32,25 @@ namespace sqlpp { + namespace detail + { + template + struct or_t; + + template + struct or_t + { + static constexpr bool value = T::value or or_t::value; + }; + + template<> + struct or_t<> + { + static constexpr bool value = false; + }; + + } + template struct parameter_list_t { @@ -43,9 +62,10 @@ namespace sqlpp { using _member_tuple_t = std::tuple; using size = std::integral_constant; + using _contains_trivial_value_is_null_t = detail::or_t; parameter_list_t(): - Parameter::_instance_t({typename Parameter::_trivial_value_is_null()})... + Parameter::_instance_t({typename Parameter::_trivial_value_is_null_t()})... {} template diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index d9996d3f..bd774dd6 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace sqlpp { @@ -42,11 +43,15 @@ namespace sqlpp { using _is_where = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in where()"); using _valid_expressions = typename detail::make_set_if::type; static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in where()"); + using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + static_assert(not _parameter_list_t::_contains_trivial_value_is_null_t::value, "must not use trivial_value_is_null in parameters of where expression, use where_parameter() instead of parameter() to turn off automatic conversion"); + template void add(E&& expr) { @@ -69,8 +74,7 @@ namespace sqlpp return set_parameter_index(_expressions, index); } - using _parameter_tuple_t = std::tuple; - _parameter_tuple_t _expressions; // FIXME: Do we need those? + _parameter_tuple_t _expressions; detail::serializable_list _dynamic_expressions; }; } diff --git a/tests/PreparedTest.cpp b/tests/PreparedTest.cpp index f3c36cc1..627bcf3a 100644 --- a/tests/PreparedTest.cpp +++ b/tests/PreparedTest.cpp @@ -87,7 +87,7 @@ int main() // Wonderful, now take a look at the parameter list of a select { - auto s = select(all_of(t)).from(t).where(t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha) or t.gamma != parameter(t.gamma)); + auto s = select(all_of(t)).from(t).where(t.beta.like(where_parameter(t.beta)) and t.alpha == where_parameter(t.alpha) or t.gamma != parameter(t.gamma)); using S = decltype(s); using T = sqlpp::make_parameter_list_t::type; T npl;