0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +08:00

Unified tvin/trivial_value_is_null usage for =,==,!= and !

This commit is contained in:
rbock 2014-07-21 09:53:17 +02:00
parent 3506182ccf
commit 0f29e255d1
6 changed files with 47 additions and 140 deletions

View File

@ -43,12 +43,12 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _column_t = Lhs;
using _value_t = Rhs;
using _lhs_t = Lhs;
using _rhs_t = Rhs;
static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<_value_t, null_t>::value, "column must not be null");
static_assert(can_be_null_t<_lhs_t>::value ? true : not (std::is_same<_rhs_t, null_t>::value or is_tvin_t<_rhs_t>::value), "column must not be null");
assignment_t(_column_t lhs, _value_t rhs):
assignment_t(_lhs_t lhs, _rhs_t rhs):
_lhs(lhs),
_rhs(rhs)
{}
@ -59,8 +59,8 @@ namespace sqlpp
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
_value_t _rhs;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -70,7 +70,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
if (((trivial_value_is_null_t<typename T::_column_t>::value or is_tvin_t<typename T::_value_t>::value)
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))
{
@ -87,52 +87,6 @@ namespace sqlpp
}
};
template<typename Lhs, typename Rhs>
struct assignment_t<Lhs, tvin_t<Rhs>>
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _column_t = Lhs;
using _value_t = tvin_t<Rhs>;
static_assert(can_be_null_t<_column_t>::value, "column cannot be null");
assignment_t(_column_t lhs, _value_t rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
_value_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, assignment_t<Lhs, tvin_t<Rhs>>>
{
using T = assignment_t<Lhs, tvin_t<Rhs>>;
static Context& _(const T& t, Context& context)
{
serialize(simple_column(t._lhs), context);
if (t._rhs._value._is_trivial())
{
context << "=NULL";
}
else
{
context << "=";
serialize(t._rhs._value, context);
}
return context;
}
};
}
#endif

View File

@ -43,8 +43,10 @@ namespace sqlpp
{
using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs;
using _rhs_t = Rhs;
binary_expression_t(Lhs lhs, Rhs rhs):
binary_expression_t(_lhs_t lhs, _rhs_t rhs):
_lhs(lhs),
_rhs(rhs)
{}
@ -55,8 +57,8 @@ namespace sqlpp
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -68,7 +70,7 @@ namespace sqlpp
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
if (rhs_is_null(t))
{
context << " IS NULL";
}
@ -88,6 +90,8 @@ namespace sqlpp
{
using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs;
using _rhs_t = Rhs;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
@ -100,8 +104,8 @@ namespace sqlpp
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -113,7 +117,7 @@ namespace sqlpp
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
if (rhs_is_null(t))
{
context << " IS NOT NULL";
}
@ -155,10 +159,17 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << "(";
context << "NOT ";
if (trivial_value_is_null_t<Rhs>::value)
{
serialize(t._lhs, context);
context << " IS NULL ";
}
else
{
context << "NOT ";
serialize(t._rhs, context);
}
context << ")";
return context;
}
};

View File

@ -97,8 +97,8 @@ namespace sqlpp
~insert_list_data_t() = default;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::_value_t...> _values;
std::tuple<simple_column_t<typename Assignments::_lhs_t>...> _columns;
std::tuple<typename Assignments::_rhs_t...> _values;
interpretable_list_t<Database> _dynamic_columns;
interpretable_list_t<Database> _dynamic_values;
};
@ -107,7 +107,7 @@ namespace sqlpp
struct insert_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::insert_list>;
using _recursive_traits = make_recursive_traits<typename Assignments::_column_t..., typename Assignments::_value_t...>;
using _recursive_traits = make_recursive_traits<typename Assignments::_lhs_t..., typename Assignments::_rhs_t...>;
using _is_dynamic = is_database<Database>;
@ -134,9 +134,9 @@ namespace sqlpp
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>;
static_assert(not detail::is_element_of<typename Assignment::_column_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add() argument must not be used in insert");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<typename Assignment::_lhs_t>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using ok = ::sqlpp::detail::all_t<
@ -150,7 +150,7 @@ namespace sqlpp
template<typename Assignment>
void _add_impl(Assignment assignment, const std::true_type&)
{
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_lhs_t>{assignment._lhs});
_data._dynamic_values.emplace_back(assignment._rhs);
}
@ -233,7 +233,7 @@ namespace sqlpp
void add(Assignments... assignments)
{
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<insert_value_t<typename Assignments::_column_t>...>;
using _arg_value_tuple = std::tuple<insert_value_t<typename Assignments::_lhs_t>...>;
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
@ -248,7 +248,7 @@ namespace sqlpp
template<typename... Assignments>
void _add_impl(const std::true_type&, Assignments... assignments)
{
return _data._insert_values.emplace_back(insert_value_t<typename Assignments::_column_t>{assignments}...);
return _data._insert_values.emplace_back(insert_value_t<typename Assignments::_lhs_t>{assignments}...);
}
template<typename... Assignments>
@ -359,9 +359,9 @@ namespace sqlpp
{
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
static_assert(sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
static_assert(sqlpp::detail::none_t<must_not_insert_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
static_assert(sqlpp::detail::none_t<must_not_insert_t<typename Assignments::_lhs_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<required_tables_of<typename Assignments::_column_t>...>::type;
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<required_tables_of<typename Assignments::_lhs_t>...>::type;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables");
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_data_t<Database, Assignments...>{assignments...} };

View File

@ -58,9 +58,9 @@ namespace sqlpp
template<typename Expression>
constexpr bool rhs_is_null(const Expression& e)
{
return (((trivial_value_is_null_t<typename Expression::_column_t>::value or is_tvin_t<typename Expression::_value_t>::value)
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::_value_t, null_t>::value));
or (std::is_same<typename Expression::_rhs_t, null_t>::value));
}
}

View File

@ -77,70 +77,12 @@ namespace sqlpp
template<typename T>
using is_tvin_t = typename detail::is_tvin_impl<T>::type;
#warning: disallow tvin in other places which are not =, == or !=
template<typename Context, typename Operand>
struct serializer_t<Context, tvin_t<Operand>>
{
using T = tvin_t<Operand>;
static void _(const T& t, Context& context)
{
static_assert(wrong_t<T>::value, "tvin() must not be used with anything but =, ==, != and !");
}
};
template<typename Operand>
struct maybe_tvin_t
{
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _is_trivial()
{
return false;
}
maybe_tvin_t(Operand operand):
_value(operand)
{}
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
Operand _value;
};
template<typename Operand>
struct maybe_tvin_t<tvin_t<Operand>>
{
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
bool _is_trivial() const
{
return _value._is_trivial();
};
maybe_tvin_t(tvin_t<Operand> operand):
_value(operand._value)
{}
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
typename tvin_t<Operand>::_operand_t _value;
};
template<typename Context, typename Operand>
struct serializer_t<Context, maybe_tvin_t<Operand>>
{
using T = maybe_tvin_t<Operand>;
static Context& _(const T& t, Context& context)
{
if (t._is_trivial())

View File

@ -78,9 +78,9 @@ namespace sqlpp
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>;
static_assert(not detail::is_element_of<typename Assignment::_column_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add() argument must not be updated");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_lhs_t>::value, "add() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add()");
using ok = ::sqlpp::detail::all_t<
@ -192,9 +192,9 @@ namespace sqlpp
{
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
static_assert(::sqlpp::detail::none_t<must_not_update_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
static_assert(::sqlpp::detail::none_t<must_not_update_t<typename Assignments::_lhs_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<required_tables_of<typename Assignments::_column_t>...>::type;
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<required_tables_of<typename Assignments::_lhs_t>...>::type;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from more than one table");
return { *static_cast<typename Policies::_statement_t*>(this), update_list_data_t<Database, Assignments...>{assignments...} };