0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

Remove null_is_trivial_value

Unless you have null_is_trivial_value or trivial_value_is_null somewhere in your code, this should not affect you.
This commit is contained in:
Roland Bock 2020-09-29 08:42:37 +02:00
parent 54cf48b7ed
commit 9203e3818f
27 changed files with 82 additions and 193 deletions

View File

@ -42,7 +42,7 @@ namespace sqlpp
{ {
using _traits = make_traits<no_value_t, tag::is_assignment>; using _traits = make_traits<no_value_t, tag::is_assignment>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>; using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>>;
using _nodes = detail::type_vector<_lhs_t, _rhs_t>; using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
static_assert(can_be_null_t<_lhs_t>::value ? true static_assert(can_be_null_t<_lhs_t>::value ? true

View File

@ -37,9 +37,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, blob, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, blob, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, blob, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, blob, CanBeNull>>
{ {
const uint8_t* blob{nullptr}; // Non-owning const uint8_t* blob{nullptr}; // Non-owning
size_t len{}; size_t len{};
@ -67,11 +67,11 @@ namespace sqlpp
} }
}; };
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, blob, CanBeNull, NullIsTrivialValue>>& e) std::ostream& os, const result_field_t<Db, field_spec_t<NameType, blob, CanBeNull>>& e)
{ {
if (e.is_null() and not NullIsTrivialValue) if (e.is_null())
{ {
return os << "NULL"; return os << "NULL";
} }

View File

@ -35,9 +35,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, boolean, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, boolean, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, boolean, CanBeNull, NullIsTrivialValue>, signed char> : public result_field_base<Db, field_spec_t<NameType, boolean, CanBeNull>, signed char>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t index) void _bind(Target& target, size_t index)

View File

@ -36,9 +36,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, day_point, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, day_point, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, day_point, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, day_point, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t index) void _bind(Target& target, size_t index)
@ -53,11 +53,11 @@ namespace sqlpp
} }
}; };
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, day_point, CanBeNull, NullIsTrivialValue>>& e) std::ostream& os, const result_field_t<Db, field_spec_t<NameType, day_point, CanBeNull>>& e)
{ {
if (e.is_null() and not NullIsTrivialValue) if (e.is_null())
{ {
os << "NULL"; os << "NULL";
} }

View File

@ -36,9 +36,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, floating_point, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, floating_point, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, floating_point, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, floating_point, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t index) void _bind(Target& target, size_t index)

View File

@ -35,9 +35,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, integral, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, integral, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, integral, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, integral, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t index) void _bind(Target& target, size_t index)

View File

@ -33,8 +33,8 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, no_value_t, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, no_value_t, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& /*unused*/, size_t /*unused*/) void _bind(Target& /*unused*/, size_t /*unused*/)
@ -60,10 +60,10 @@ namespace sqlpp
} }
}; };
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, std::ostream& os,
const result_field_t<Db, field_spec_t<NameType, no_value_t, CanBeNull, NullIsTrivialValue>>& /*unused*/) const result_field_t<Db, field_spec_t<NameType, no_value_t, CanBeNull>>& /*unused*/)
{ {
os << "NULL"; os << "NULL";
return os; return os;

View File

@ -36,9 +36,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, text, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, text, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, text, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, text, CanBeNull>>
{ {
const char* text{nullptr}; // Non-owning const char* text{nullptr}; // Non-owning
size_t len{}; size_t len{};
@ -74,11 +74,11 @@ namespace sqlpp
} }
}; };
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, text, CanBeNull, NullIsTrivialValue>>& e) std::ostream& os, const result_field_t<Db, field_spec_t<NameType, text, CanBeNull>>& e)
{ {
if (e.is_null() and not NullIsTrivialValue) if (e.is_null())
{ {
return os << "NULL"; return os << "NULL";
} }

View File

@ -37,9 +37,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, time_of_day, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, time_of_day, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, time_of_day, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, time_of_day, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
@ -54,11 +54,11 @@ namespace sqlpp
} }
}; };
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, time_of_day, CanBeNull, NullIsTrivialValue>>& e) std::ostream& os, const result_field_t<Db, field_spec_t<NameType, time_of_day, CanBeNull>>& e)
{ {
if (e.is_null() and not NullIsTrivialValue) if (e.is_null())
{ {
os << "NULL"; os << "NULL";
} }

View File

@ -37,9 +37,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, time_point, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, time_point, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, time_point, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, time_point, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
@ -54,11 +54,11 @@ namespace sqlpp
} }
}; };
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
inline std::ostream& operator<<( inline std::ostream& operator<<(
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, time_point, CanBeNull, NullIsTrivialValue>>& e) std::ostream& os, const result_field_t<Db, field_spec_t<NameType, time_point, CanBeNull>>& e)
{ {
if (e.is_null() and not NullIsTrivialValue) if (e.is_null())
{ {
os << "NULL"; os << "NULL";
} }

View File

@ -35,9 +35,9 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename NameType, bool CanBeNull, bool NullIsTrivialValue> template <typename Db, typename NameType, bool CanBeNull>
struct result_field_t<Db, field_spec_t<NameType, unsigned_integral, CanBeNull, NullIsTrivialValue>> struct result_field_t<Db, field_spec_t<NameType, unsigned_integral, CanBeNull>>
: public result_field_base<Db, field_spec_t<NameType, unsigned_integral, CanBeNull, NullIsTrivialValue>> : public result_field_base<Db, field_spec_t<NameType, unsigned_integral, CanBeNull>>
{ {
template <typename Target> template <typename Target>
void _bind(Target& target, size_t index) void _bind(Target& target, size_t index)

View File

@ -51,10 +51,9 @@ namespace sqlpp
typename NameType, typename NameType,
typename ValueType, typename ValueType,
bool CanBeNull, bool CanBeNull,
bool NullIsTrivialValue,
typename... Rest> typename... Rest>
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>, struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>,
field_spec_t<NameType, ValueType, CanBeNull, NullIsTrivialValue>, field_spec_t<NameType, ValueType, CanBeNull>,
Rest...> Rest...>
{ {
using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + 1, Ints..., NextIndex>, using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + 1, Ints..., NextIndex>,

View File

@ -44,7 +44,7 @@ namespace sqlpp
"Expression cannot be used in eval because it requires tables"); "Expression cannot be used in eval because it requires tables");
using _name_type = alias::a_t::_alias_t; using _name_type = alias::a_t::_alias_t;
using _value_type = value_type_of<Expr>; using _value_type = value_type_of<Expr>;
using _field_spec = field_spec_t<_name_type, _value_type, true, false>; using _field_spec = field_spec_t<_name_type, _value_type, true>;
using type = result_field_t<Db, _field_spec>; using type = result_field_t<Db, _field_spec>;
}; };

View File

@ -45,7 +45,7 @@ namespace sqlpp
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>; using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>>;
using _nodes = detail::type_vector<_lhs_t, _rhs_t>; using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs) binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
@ -93,7 +93,7 @@ namespace sqlpp
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>; using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>>;
using _nodes = detail::type_vector<_lhs_t, _rhs_t>; using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs) binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
@ -164,16 +164,8 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "("; context << "(";
if (trivial_value_is_null_t<Rhs>::value)
{
serialize_operand(t._rhs, context);
context << " IS NULL ";
}
else
{
context << "NOT "; context << "NOT ";
serialize_operand(t._rhs, context); serialize_operand(t._rhs, context);
}
context << ")"; context << ")";
return context; return context;

View File

@ -31,13 +31,12 @@
namespace sqlpp namespace sqlpp
{ {
template <typename NameType, typename ValueType, bool CanBeNull, bool NullIsTrivialValue> template <typename NameType, typename ValueType, bool CanBeNull>
struct field_spec_t struct field_spec_t
{ {
using _traits = make_traits<ValueType, using _traits = make_traits<ValueType,
tag::is_noop, tag::is_noop,
tag_if<tag::can_be_null, CanBeNull>, tag_if<tag::can_be_null, CanBeNull>>;
tag_if<tag::null_is_trivial_value, NullIsTrivialValue>>;
using _nodes = detail::type_vector<>; using _nodes = detail::type_vector<>;
using _alias_t = NameType; using _alias_t = NameType;
@ -64,20 +63,17 @@ namespace sqlpp
template <typename LeftName, template <typename LeftName,
typename LeftValue, typename LeftValue,
bool LeftCanBeNull, bool LeftCanBeNull,
bool LeftNullIsTrivial,
typename RightName, typename RightName,
typename RightValue, typename RightValue,
bool RightCanBeNull, bool RightCanBeNull>
bool RightNullIsTrivial> struct is_field_compatible<field_spec_t<LeftName, LeftValue, LeftCanBeNull>,
struct is_field_compatible<field_spec_t<LeftName, LeftValue, LeftCanBeNull, LeftNullIsTrivial>, field_spec_t<RightName, RightValue, RightCanBeNull>>
field_spec_t<RightName, RightValue, RightCanBeNull, RightNullIsTrivial>>
{ {
static constexpr auto value = static constexpr auto value =
std::is_same<typename LeftName::_name_t, typename RightName::_name_t>::value and std::is_same<typename LeftName::_name_t, typename RightName::_name_t>::value and
std::is_same<LeftValue, RightValue>::value and // Same value type std::is_same<LeftValue, RightValue>::value and // Same value type
(LeftCanBeNull or !RightCanBeNull) and // The left hand side determines the result row and therefore must allow (LeftCanBeNull or !RightCanBeNull); // The left hand side determines the result row and therefore must allow
// NULL if the right hand side allows it // NULL if the right hand side allows it
(LeftNullIsTrivial or !RightNullIsTrivial); // as above
}; };
template <typename LeftAlias, typename... LeftFields, typename RightAlias, typename... RightFields> template <typename LeftAlias, typename... LeftFields, typename RightAlias, typename... RightFields>
@ -100,8 +96,7 @@ namespace sqlpp
using type = field_spec_t<typename NamedExpr::_alias_t, using type = field_spec_t<typename NamedExpr::_alias_t,
value_type_of<NamedExpr>, value_type_of<NamedExpr>,
logic::any_t<_can_be_null, _depends_on_outer_table>::value, logic::any_t<_can_be_null, _depends_on_outer_table>::value>;
null_is_trivial_value_t<NamedExpr>::value>;
}; };
template <typename Select, typename AliasProvider, typename... NamedExprs> template <typename Select, typename AliasProvider, typename... NamedExprs>

View File

@ -61,33 +61,32 @@ namespace sqlpp
{ {
using _is_insert_value = std::true_type; using _is_insert_value = std::true_type;
using _column_t = Column; using _column_t = Column;
static constexpr bool _trivial_value_is_null = trivial_value_is_null_t<Column>::value;
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type; using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
using _wrapped_value_t = wrap_operand_t<_pure_value_t>; using _wrapped_value_t = wrap_operand_t<_pure_value_t>;
using _tvin_t = tvin_t<_wrapped_value_t>; using _tvin_t = tvin_t<_wrapped_value_t>;
using _value_or_null_t = value_or_null_t<typename Column::_traits::_value_type>; using _value_or_null_t = value_or_null_t<typename Column::_traits::_value_type>;
insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs) insert_value_t(rhs_wrap_t<_wrapped_value_t> rhs)
: _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._t) : _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._t)
{ {
} }
insert_value_t(rhs_wrap_t<_tvin_t, _trivial_value_is_null> rhs) insert_value_t(rhs_wrap_t<_tvin_t> rhs)
: _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._value) : _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._value)
{ {
} }
insert_value_t(const rhs_wrap_t<null_t, _trivial_value_is_null>& /*unused*/) insert_value_t(const rhs_wrap_t<null_t>& /*unused*/)
: _is_null(true), _is_default(false), _value{} : _is_null(true), _is_default(false), _value{}
{ {
} }
insert_value_t(const rhs_wrap_t<default_value_t, _trivial_value_is_null>& /*unused*/) insert_value_t(const rhs_wrap_t<default_value_t>& /*unused*/)
: _is_null(false), _is_default(true), _value{} : _is_null(false), _is_default(true), _value{}
{ {
} }
insert_value_t(const rhs_wrap_t<_value_or_null_t, _trivial_value_is_null>& rhs) insert_value_t(const rhs_wrap_t<_value_or_null_t>& rhs)
: _is_null(rhs._expr._is_null), _is_default(false), _value{rhs._expr._value} : _is_null(rhs._expr._is_null), _is_default(false), _value{rhs._expr._value}
{ {
} }
@ -111,7 +110,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 and t._value._is_trivial()) or t._is_null) if (t._is_null)
{ {
context << "NULL"; context << "NULL";
} }

View File

@ -49,7 +49,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
if (t.is_null() and not null_is_trivial_value_t<T>::value) if (t.is_null())
{ {
context << "NULL"; context << "NULL";
} }

View File

@ -47,13 +47,9 @@ namespace sqlpp
using _cpp_value_type = typename value_type_of<FieldSpec>::_cpp_value_type; using _cpp_value_type = typename value_type_of<FieldSpec>::_cpp_value_type;
using _cpp_storage_type = StorageType; using _cpp_storage_type = StorageType;
static constexpr bool _null_is_trivial =
column_spec_can_be_null_t<_field_spec_t>::value and
(null_is_trivial_value_t<_field_spec_t>::value or not enforce_null_result_treatment_t<_db_t>::value);
using _traits = make_traits<value_type_of<_field_spec_t>, using _traits = make_traits<value_type_of<_field_spec_t>,
tag::is_result_field, tag::is_result_field,
tag::is_expression, tag::is_expression>;
tag_if<tag::null_is_trivial_value, _null_is_trivial>>;
using _nodes = detail::type_vector<>; using _nodes = detail::type_vector<>;
using _can_be_null = column_spec_can_be_null_t<_field_spec_t>; using _can_be_null = column_spec_can_be_null_t<_field_spec_t>;
@ -111,22 +107,13 @@ namespace sqlpp
} }
if (_is_null) if (_is_null)
{
if (not _null_is_trivial)
{
throw exception("accessing value of NULL field");
}
else
{ {
return {}; return {};
} }
}
return _value; return _value;
} }
operator typename std::conditional<_null_is_trivial or (not _can_be_null::value), operator _cpp_value_type() const
_cpp_value_type,
assert_result_field_value_is_safe_t>::type() const
{ {
return value(); return value();
} }

View File

@ -272,7 +272,7 @@ namespace sqlpp
{ {
using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>; using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>;
using _impl = detail::result_row_impl<Db, _field_index_sequence, FieldSpecs...>; using _impl = detail::result_row_impl<Db, _field_index_sequence, FieldSpecs...>;
using _field_type = result_field_t<Db, field_spec_t<no_name_t, text, true, true>>; using _field_type = result_field_t<Db, field_spec_t<no_name_t, text, true>>;
bool _is_valid{false}; bool _is_valid{false};
std::vector<std::string> _dynamic_field_names; std::vector<std::string> _dynamic_field_names;

View File

@ -67,11 +67,6 @@ namespace sqlpp
{ {
static bool _(const Expr& t) static bool _(const Expr& t)
{ {
if (null_is_trivial_value_t<Expr>::value)
{
return t.is_null();
}
if (t.is_null()) if (t.is_null())
{ {
return false; return false;
@ -109,7 +104,7 @@ namespace sqlpp
}; };
} // namespace detail } // namespace detail
template <typename Expr, bool TrivialValueIsNull> template <typename Expr>
struct rhs_wrap_t struct rhs_wrap_t
{ {
using _traits = typename Expr::_traits; using _traits = typename Expr::_traits;
@ -127,7 +122,7 @@ namespace sqlpp
bool _is_null() const bool _is_null() const
{ {
return (TrivialValueIsNull and detail::rhs_is_trivial_t<Expr>::_(_expr)) or detail::rhs_is_null_t<Expr>::_(_expr); return detail::rhs_is_null_t<Expr>::_(_expr);
} }
static constexpr bool _is_default() static constexpr bool _is_default()
@ -138,11 +133,11 @@ namespace sqlpp
Expr _expr; Expr _expr;
}; };
template <typename Context, typename Expr, bool TrivialValueIsNull> template <typename Context, typename Expr>
struct serializer_t<Context, rhs_wrap_t<Expr, TrivialValueIsNull>> struct serializer_t<Context, rhs_wrap_t<Expr>>
{ {
using _serialize_check = serialize_check_of<Context, Expr>; using _serialize_check = serialize_check_of<Context, Expr>;
using T = rhs_wrap_t<Expr, TrivialValueIsNull>; using T = rhs_wrap_t<Expr>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -173,8 +173,6 @@ namespace sqlpp
SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert) SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert)
SQLPP_VALUE_TRAIT_GENERATOR(must_not_update) SQLPP_VALUE_TRAIT_GENERATOR(must_not_update)
SQLPP_VALUE_TRAIT_GENERATOR(require_insert) SQLPP_VALUE_TRAIT_GENERATOR(require_insert)
SQLPP_VALUE_TRAIT_GENERATOR(trivial_value_is_null)
SQLPP_VALUE_TRAIT_GENERATOR(null_is_trivial_value)
SQLPP_VALUE_TRAIT_GENERATOR(is_statement) SQLPP_VALUE_TRAIT_GENERATOR(is_statement)
SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement) SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement)

View File

@ -42,7 +42,6 @@ endfunction()
# Compiling these is required to fail (testing some static_assert) # Compiling these is required to fail (testing some static_assert)
test_constraint(count_of_count "count\\(\\) cannot be used on an aggregate function") test_constraint(count_of_count "count\\(\\) cannot be used on an aggregate function")
test_constraint(max_of_max "max\\(\\) cannot be used on an aggregate function") test_constraint(max_of_max "max\\(\\) cannot be used on an aggregate function")
test_constraint(no_conversion_operator_if_null_not_trivial "cannot convert|no viable conversion")
test_constraint(require_insert "required column is missing") test_constraint(require_insert "required column is missing")
test_constraint(must_not_insert "one assignment is prohibited") test_constraint(must_not_insert "one assignment is prohibited")
test_constraint(must_not_update "one assignment is prohibited") test_constraint(must_not_update "one assignment is prohibited")

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2013-2015, 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.
*/
/*
* NOTE:
* This code must not compile (it is used to test the absence of a conversion operator)
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
EnforceDb edb{};
int main()
{
const auto t = test::TabBar{};
static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
"row.alpha does not interpret null_is_trivial");
int i = row.alpha;
}
return 0;
}

View File

@ -45,6 +45,8 @@ int Insert(int, char* [])
compare(__LINE__, insert_into(bar).default_values(), "INSERT INTO tab_bar DEFAULT VALUES"); compare(__LINE__, insert_into(bar).default_values(), "INSERT INTO tab_bar DEFAULT VALUES");
compare(__LINE__, insert_into(bar).set(bar.beta = "cheesecake", bar.gamma = true), compare(__LINE__, insert_into(bar).set(bar.beta = "cheesecake", bar.gamma = true),
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")"); "INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
compare(__LINE__, insert_into(bar).set(bar.beta = ::sqlpp::tvin(""), bar.gamma = true),
"INSERT INTO tab_bar (beta,gamma) VALUES(NULL," + getTrue() + ")");
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
// string_view argument // string_view argument
std::string_view cheeseCake = "cheesecake"; std::string_view cheeseCake = "cheesecake";

View File

@ -63,6 +63,7 @@ int Where(int, char*[])
// Sometimes // Sometimes
compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma"); compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma");
compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")"); compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")");
compare(__LINE__, where(bar.gamma == ::sqlpp::tvin(false)), " WHERE (tab_bar.gamma IS NULL)");
compare(__LINE__, where(bar.beta == "SQL"), " WHERE (tab_bar.beta='SQL')"); compare(__LINE__, where(bar.beta == "SQL"), " WHERE (tab_bar.beta='SQL')");
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
// string_view argument // string_view argument

View File

@ -42,12 +42,10 @@ struct InternalMockData
sqlpp::isolation_level _default_isolation_level; sqlpp::isolation_level _default_isolation_level;
}; };
template <bool enforceNullResultTreatment> struct MockDb : public sqlpp::connection
struct MockDbT : public sqlpp::connection
{ {
using _traits = using _traits =
::sqlpp::make_traits<::sqlpp::no_value_t, ::sqlpp::make_traits<::sqlpp::no_value_t>;
::sqlpp::tag_if<::sqlpp::tag::enforce_null_result_treatment, enforceNullResultTreatment>>;
struct _serializer_context_t struct _serializer_context_t
{ {
@ -289,9 +287,6 @@ struct MockDbT : public sqlpp::connection
InternalMockData _mock_data; InternalMockData _mock_data;
}; };
using MockDb = MockDbT<false>;
using EnforceDb = MockDbT<true>;
struct MockSizeDb : public sqlpp::connection struct MockSizeDb : public sqlpp::connection
{ {
using _traits = MockDb::_traits; using _traits = MockDb::_traits;
@ -500,7 +495,4 @@ struct MockSizeDb : public sqlpp::connection
InternalMockData _mock_data; InternalMockData _mock_data;
}; };
using MockDb = MockDbT<false>;
using EnforceDb = MockDbT<true>;
#endif #endif

View File

@ -28,24 +28,18 @@
#include "MockDb.h" #include "MockDb.h"
#include <sqlpp11/sqlpp11.h> #include <sqlpp11/sqlpp11.h>
static_assert(not sqlpp::enforce_null_result_treatment_t<MockDb>::value, "MockDb interprets NULL as trivial");
static_assert(sqlpp::enforce_null_result_treatment_t<EnforceDb>::value, "MockDb does not interpret NULL as trivial");
int Result(int, char* []) int Result(int, char* [])
{ {
MockDb db = {}; MockDb db = {};
EnforceDb edb{};
const auto t = test::TabBar{}; const auto t = test::TabBar{};
static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
// Using a non-enforcing db // Using a non-enforcing db
for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).unconditionally())) for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); 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_same<bool, decltype(row.alpha.is_null())>::value, "Yikes"); static_assert(std::is_same<bool, decltype(row.alpha.is_null())>::value, "Yikes");
using T = sqlpp::wrap_operand_t<decltype(row.alpha)>; 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::can_be_null_t<T>::value, "row.alpha can be null");
@ -67,24 +61,14 @@ int Result(int, char* [])
for (const auto& row : db(select(all_of(t)).from(t).unconditionally())) for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); 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");
} }
// Using a non-enforcing db for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
"row.alpha interprets null_is_trivial");
} }
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t); sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
"row.alpha interprets null_is_trivial");
}
return 0; return 0;
} }