Allowing result fields to be used as arguments for queries

This commit is contained in:
rbock
2014-07-29 08:57:55 +02:00
parent 4be53d9933
commit b1f1de8a08
12 changed files with 158 additions and 15 deletions

View File

@@ -31,6 +31,7 @@
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/rhs_is_null.h>
#include <sqlpp11/rhs_is_trivial.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/simple_column.h>
@@ -70,9 +71,8 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
if (((trivial_value_is_null_t<typename T::_lhs_t>::value or is_tvin_t<typename T::_rhs_t>::value)
and is_trivial(t._rhs))
or (std::is_same<Rhs, null_t>::value))
if ((trivial_value_is_null_t<typename T::_lhs_t>::value and rhs_is_trivial(t))
or rhs_is_null(t))
{
serialize(simple_column(t._lhs), context);
context << "=NULL";

View File

@@ -123,6 +123,8 @@ namespace sqlpp
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag::is_result_field,
tag::is_expression,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
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)

View File

@@ -30,6 +30,8 @@
#include <sqlpp11/alias.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/rhs_is_null.h>
#include <sqlpp11/rhs_is_trivial.h>
#include <sqlpp11/noop.h>
#include <sqlpp11/expression_fwd.h>
#include <sqlpp11/serializer.h>
@@ -70,7 +72,8 @@ namespace sqlpp
{
context << "(";
serialize(t._lhs, context);
if (rhs_is_null(t))
if ((trivial_value_is_null_t<typename T::_lhs_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<typename T::_lhs_t>::value and rhs_is_trivial(t))
or rhs_is_null(t))
{
context << " IS NOT NULL";
}

View File

@@ -122,6 +122,8 @@ namespace sqlpp
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag::is_result_field,
tag::is_expression,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
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)

View File

@@ -123,6 +123,8 @@ namespace sqlpp
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag::is_result_field,
tag::is_expression,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
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)

View File

@@ -32,7 +32,7 @@
namespace sqlpp
{
template<typename T, typename Enable = void>
struct is_trivial_t
struct rhs_is_null_t
{
static constexpr bool _(const T&)
{
@@ -41,27 +41,29 @@ namespace sqlpp
};
template<typename T>
struct is_trivial_t<T, typename std::enable_if<std::is_member_function_pointer<decltype(&T::_is_trivial)>::value, void>::type>
struct rhs_is_null_t<T, typename std::enable_if<is_tvin_t<T>::value, void>::type>
{
static bool _(const T& t)
{
return t._is_trivial();
return t._is_null();
}
};
template<typename T>
bool is_trivial(const T& t)
struct rhs_is_null_t<T, typename std::enable_if<is_result_field_t<T>::value, void>::type>
{
return is_trivial_t<T>::_(t);
}
static bool _(const T& t)
{
return t.is_null();
}
};
template<typename Expression>
constexpr bool rhs_is_null(const Expression& e)
{
return (((trivial_value_is_null_t<typename Expression::_lhs_t>::value or is_tvin_t<typename Expression::_rhs_t>::value)
and is_trivial(e._rhs))
or (std::is_same<typename Expression::_rhs_t, null_t>::value));
return rhs_is_null_t<typename std::decay<Expression>::type::_rhs_t>::_(e._rhs);
}
}
#endif

View File

@@ -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 <sqlpp11/tvin.h>
namespace sqlpp
{
template<typename T, typename Enable = void>
struct rhs_is_trivial_t
{
static constexpr bool _(const T&)
{
return false;
}
};
template<typename T>
struct rhs_is_trivial_t<T, typename std::enable_if<is_wrapped_value_t<T>::value, void>::type>
{
static bool _(const T& t)
{
return t._is_trivial();
}
};
template<typename T>
struct rhs_is_trivial_t<T, typename std::enable_if<is_tvin_t<T>::value, void>::type>
{
static bool _(const T& t)
{
return t._is_trivial();
}
};
template<typename T>
struct rhs_is_trivial_t<T, typename std::enable_if<is_result_field_t<T>::value, void>::type>
{
static bool _(const T& t)
{
return t.is_trivial();
}
};
template<typename Expression>
constexpr bool rhs_is_trivial(const Expression& e)
{
return rhs_is_trivial_t<typename std::decay<Expression>::type::_rhs_t>::_(e._rhs);
}
}
#endif

View File

@@ -122,6 +122,8 @@ namespace sqlpp
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag::is_result_field,
tag::is_expression,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
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)

View File

@@ -108,6 +108,11 @@ namespace sqlpp
return _value._is_trivial();
}
bool _is_null() const
{
return _value._is_trivial();
}
_operand_t _value;
};

View File

@@ -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);

View File

@@ -47,6 +47,20 @@ int main()
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
static_assert(std::is_member_function_pointer<decltype(&decltype(row.alpha)::is_null)>::value, "Yikes");
using T = sqlpp::wrap_operand_t<decltype(row.alpha)>;
static_assert(sqlpp::can_be_null_t<T>::value, "row.alpha can be null");
static_assert(sqlpp::is_result_field_t<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);

View File

@@ -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;
}