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 _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _column_t = Lhs; using _lhs_t = Lhs;
using _value_t = Rhs; 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), _lhs(lhs),
_rhs(rhs) _rhs(rhs)
{} {}
@ -59,8 +59,8 @@ namespace sqlpp
assignment_t& operator=(assignment_t&&) = default; assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default; ~assignment_t() = default;
_column_t _lhs; _lhs_t _lhs;
_value_t _rhs; _rhs_t _rhs;
}; };
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
@ -70,7 +70,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) 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)) and is_trivial(t._rhs))
or (std::is_same<Rhs, null_t>::value)) 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 #endif

View File

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

View File

@ -97,8 +97,8 @@ namespace sqlpp
~insert_list_data_t() = default; ~insert_list_data_t() = default;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) 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<simple_column_t<typename Assignments::_lhs_t>...> _columns;
std::tuple<typename Assignments::_value_t...> _values; std::tuple<typename Assignments::_rhs_t...> _values;
interpretable_list_t<Database> _dynamic_columns; interpretable_list_t<Database> _dynamic_columns;
interpretable_list_t<Database> _dynamic_values; interpretable_list_t<Database> _dynamic_values;
}; };
@ -107,7 +107,7 @@ namespace sqlpp
struct insert_list_t struct insert_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::insert_list>; 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>; 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_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments"); 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...>; using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_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 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::_column_t>::value, "add() argument must not be used in insert"); 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"); 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< using ok = ::sqlpp::detail::all_t<
@ -150,7 +150,7 @@ namespace sqlpp
template<typename Assignment> template<typename Assignment>
void _add_impl(Assignment assignment, const std::true_type&) 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); _data._dynamic_values.emplace_back(assignment._rhs);
} }
@ -233,7 +233,7 @@ namespace sqlpp
void add(Assignments... assignments) void add(Assignments... assignments)
{ {
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be 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>; 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"); static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
@ -248,7 +248,7 @@ namespace sqlpp
template<typename... Assignments> template<typename... Assignments>
void _add_impl(const std::true_type&, Assignments... 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> 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(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::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"); 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...} }; 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> template<typename Expression>
constexpr bool rhs_is_null(const Expression& e) 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)) 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> template<typename T>
using is_tvin_t = typename detail::is_tvin_impl<T>::type; 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> template<typename Context, typename Operand>
struct serializer_t<Context, tvin_t<Operand>> struct serializer_t<Context, tvin_t<Operand>>
{ {
using T = 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) static Context& _(const T& t, Context& context)
{ {
if (t._is_trivial()) 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_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()"); static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>; using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_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 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::_column_t>::value, "add() argument must not be updated"); 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()"); 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< 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(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::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"); 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...} }; return { *static_cast<typename Policies::_statement_t*>(this), update_list_data_t<Database, Assignments...>{assignments...} };