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

Merge branch 'release/0.18'

This commit is contained in:
rbock 2014-07-28 07:46:27 +02:00
commit 229122b4db
70 changed files with 777 additions and 605 deletions

View File

@ -51,6 +51,10 @@ namespace sqlpp
class connection: public sqlpp::connection // this inheritance helps with ADL for dynamic_select, for instance class connection: public sqlpp::connection // this inheritance helps with ADL for dynamic_select, for instance
{ {
public: public:
using _traits = ::sqlpp::make_traits<::sqlpp::no_value_t,
::sqlpp::tag::enforce_null_result_treatment // If that is what you really want, leave it out otherwise
>;
using _prepared_statement_t = << handle to a prepared statement of the database >>; using _prepared_statement_t = << handle to a prepared statement of the database >>;
using _serializer_context_t = << This context is used to serialize a statement >> using _serializer_context_t = << This context is used to serialize a statement >>
using _interpreter_context_t = << This context is used interpret a statement >>; using _interpreter_context_t = << This context is used interpret a statement >>;

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Expression, typename AliasProvider> template<typename Expression, typename AliasProvider>
struct expression_alias_t struct expression_alias_t
{ {
using _traits = make_traits<value_type_of<Expression>, tag::named_expression, tag::alias>; using _traits = make_traits<value_type_of<Expression>, tag::is_named_expression, tag::is_alias>;
using _recursive_traits = make_recursive_traits<Expression>; using _recursive_traits = make_recursive_traits<Expression>;
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias"); static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select> template<typename Select>
struct any_t struct any_t
{ {
using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::multi_expression>; using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;
struct _name_t struct _name_t

View File

@ -30,48 +30,25 @@
#include <sqlpp11/default_value.h> #include <sqlpp11/default_value.h>
#include <sqlpp11/null.h> #include <sqlpp11/null.h>
#include <sqlpp11/tvin.h> #include <sqlpp11/tvin.h>
#include <sqlpp11/rhs_is_null.h>
#include <sqlpp11/serialize.h> #include <sqlpp11/serialize.h>
#include <sqlpp11/serializer.h> #include <sqlpp11/serializer.h>
#include <sqlpp11/simple_column.h> #include <sqlpp11/simple_column.h>
namespace sqlpp namespace sqlpp
{ {
template<typename T, typename Enable = void>
struct is_trivial_t
{
static constexpr bool _(const T&)
{
return false;
}
};
template<typename T>
struct is_trivial_t<T, typename std::enable_if<std::is_member_function_pointer<decltype(&T::_is_trivial)>::value, void>::type>
{
static bool _(const T& t)
{
return t._is_trivial();
}
};
template<typename T>
bool is_trivial(const T& t)
{
return is_trivial_t<T>::_(t);
}
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct assignment_t struct assignment_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_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 = allow_tvin_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)
{} {}
@ -82,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>
@ -93,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 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))
{ {
@ -110,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

@ -35,7 +35,7 @@ namespace sqlpp
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>, struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>,
public alias_operators<avg_t<Flag, Expr>> public alias_operators<avg_t<Flag, Expr>>
{ {
using _traits = make_traits<floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<floating_point, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");

View File

@ -28,7 +28,6 @@
#define SQLPP_BOOLEAN_H #define SQLPP_BOOLEAN_H
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <ostream> #include <ostream>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
@ -42,7 +41,8 @@ namespace sqlpp
// boolean value type // boolean value type
struct boolean struct boolean
{ {
using _tag = ::sqlpp::tag::boolean; using _traits = make_traits<boolean, ::sqlpp::tag::is_boolean, ::sqlpp::tag::is_expression>;
using _tag = ::sqlpp::tag::is_boolean;
using _cpp_value_type = bool; using _cpp_value_type = bool;
struct _parameter_t struct _parameter_t
@ -96,10 +96,46 @@ namespace sqlpp
bool _is_null; bool _is_null;
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_field_t;
// I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{ {
_result_entry_t(): static constexpr bool _null_is_trivial = true;
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_field_t<Db, FieldSpec>,
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
static constexpr bool _null_is_trivial = false;
};
template<typename Db, typename FieldSpec>
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
{
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
};
_result_field_t():
_is_valid(false), _is_valid(false),
_is_null(true), _is_null(true),
_value(false) _value(false)
@ -119,33 +155,30 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _is_null; return _is_null;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
if (_is_null)
{ {
assert(_is_valid); if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
assert(not null_value); {
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field"); throw exception("accessing value of NULL field");
}
else
{
return false;
}
} }
return _value; return _value;
} }
operator _cpp_value_type() const { return value(); }
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
{ {
@ -200,8 +233,8 @@ namespace sqlpp
}; };
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t<Db, TrivialIsNull>& e) inline std::ostream& operator<<(std::ostream& os, const boolean::_result_field_t<Db, FieldSpec>& e)
{ {
return os << e.value(); return os << e.value();
} }

View File

@ -42,25 +42,31 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Table, typename ColumnSpec> template<typename Table, typename ColumnSpec>
struct column_t: public ColumnSpec::_value_type::template expression_operators<column_t<Table, ColumnSpec>>, struct column_t: public value_type_of<ColumnSpec>::template expression_operators<column_t<Table, ColumnSpec>>,
public ColumnSpec::_value_type::template column_operators<column_t<Table, ColumnSpec>> public value_type_of<ColumnSpec>::template column_operators<column_t<Table, ColumnSpec>>
{ {
using _traits = make_traits<typename ColumnSpec::_value_type, tag::column, tag::expression, tag::named_expression>; struct _traits
{
using _value_type = value_type_of<ColumnSpec>;
using _tags = detail::make_joined_set_t<detail::type_set<tag::is_column, tag::is_expression, tag::is_named_expression>, typename ColumnSpec::_traits::_tags>;
};
struct _recursive_traits struct _recursive_traits
{ {
using _parameters = std::tuple<>; using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>; using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<Table>; using _required_tables = detail::type_set<Table>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<ColumnSpec>;
}; };
using _spec_t = ColumnSpec; using _spec_t = ColumnSpec;
using _table = Table; using _table = Table;
using _column_type = typename _spec_t::_column_type;
using _name_t = typename _spec_t::_name_t; using _name_t = typename _spec_t::_name_t;
template<typename T> template<typename T>
using _is_valid_operand = typename ColumnSpec::_value_type::template _is_valid_operand<T>; using _is_valid_operand = typename value_type_of<ColumnSpec>::template _is_valid_operand<T>;
column_t() = default; column_t() = default;
column_t(const column_t&) = default; column_t(const column_t&) = default;

View File

@ -39,7 +39,7 @@ namespace sqlpp
struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>, struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>,
public alias_operators<concat_t<First, Args...>> public alias_operators<concat_t<First, Args...>>
{ {
using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<First, Args...>; using _recursive_traits = make_recursive_traits<First, Args...>;
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");

View File

@ -36,7 +36,7 @@ namespace sqlpp
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>, struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>,
public alias_operators<count_t<Flag, Expr>> public alias_operators<count_t<Flag, Expr>>
{ {
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'");

View File

@ -33,7 +33,7 @@ namespace sqlpp
{ {
struct default_value_t struct default_value_t
{ {
using _traits = make_traits<no_value_t, tag::expression>; using _traits = make_traits<no_value_t, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
static constexpr bool _is_trivial() { return false; } static constexpr bool _is_trivial() { return false; }

View File

@ -49,7 +49,7 @@ namespace sqlpp
}; };
template<std::size_t LastIndex, std::size_t... Ints, typename AliasProvider, typename... Fields, typename... Rest> template<std::size_t LastIndex, std::size_t... Ints, typename AliasProvider, typename... Fields, typename... Rest>
struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>, multi_field_t<AliasProvider, Fields...>, Rest...> struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>, multi_field_spec_t<AliasProvider, Fields...>, Rest...>
{ {
using type = typename make_column_index_sequence_impl<column_index_sequence<LastIndex + sizeof...(Fields), Ints..., LastIndex + sizeof...(Fields)>, Rest...>::type; using type = typename make_column_index_sequence_impl<column_index_sequence<LastIndex + sizeof...(Fields), Ints..., LastIndex + sizeof...(Fields)>, Rest...>::type;
}; };

View File

@ -204,13 +204,30 @@ namespace sqlpp
struct make_difference_set<type_set<Minuends...>, type_set<Subtrahends...>> struct make_difference_set<type_set<Minuends...>, type_set<Subtrahends...>>
{ {
template<typename E> template<typename E>
using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>; using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>;
using type = typename make_type_set_if_not<is_subtrahend, Minuends...>::type; using type = typename make_type_set_if_not<is_subtrahend, Minuends...>::type;
}; };
template<typename Minuend, typename Subtrahend> template<typename Minuend, typename Subtrahend>
using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type; using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type;
template<typename Lhs, typename Rhs>
struct make_intersect_set
{
static_assert(::sqlpp::wrong_t<Lhs, Rhs>::value, "invalid argument for intersect set");
};
template<typename... LhsElements, typename... RhsElements>
struct make_intersect_set<type_set<LhsElements...>, type_set<RhsElements...>>
{
template<typename E>
using is_in_both = is_element_of<E, make_type_set_t<LhsElements..., RhsElements...>>;
using type = typename make_type_set_if<is_in_both, LhsElements...>::type;
};
template<typename Lhs, typename Rhs>
using make_intersect_set_t = typename make_intersect_set<Lhs, Rhs>::type;
template<template<typename> class Transformation, typename T> template<template<typename> class Transformation, typename T>
struct transform_set struct transform_set

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct exists_t: public boolean::template expression_operators<exists_t<Select>>, struct exists_t: public boolean::template expression_operators<exists_t<Select>>,
public alias_operators<exists_t<Select>> public alias_operators<exists_t<Select>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument"); static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");

View File

@ -41,10 +41,12 @@ namespace sqlpp
struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>, struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>,
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>> public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::expression>; using _traits = make_traits<boolean, sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs;
using _rhs_t = allow_tvin_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";
} }
@ -86,10 +88,12 @@ namespace sqlpp
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>, struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>,
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>> public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::expression>; using _traits = make_traits<boolean, sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs;
using _rhs_t = allow_tvin_t<Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs): binary_expression_t(Lhs lhs, _rhs_t rhs):
_lhs(lhs), _lhs(lhs),
_rhs(rhs) _rhs(rhs)
{} {}
@ -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";
} }
@ -131,7 +135,7 @@ namespace sqlpp
struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<unary_expression_t<op::logical_not, Rhs>>, struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<unary_expression_t<op::logical_not, Rhs>>,
public alias_operators<unary_expression_t<op::logical_not, Rhs>> public alias_operators<unary_expression_t<op::logical_not, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::expression>; using _traits = make_traits<boolean, sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _recursive_traits = make_recursive_traits<Rhs>;
unary_expression_t(Rhs rhs): unary_expression_t(Rhs rhs):
@ -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;
} }
}; };
@ -166,7 +177,7 @@ namespace sqlpp
struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>>, struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>>,
public alias_operators<binary_expression_t<Lhs, O, Rhs>> public alias_operators<binary_expression_t<Lhs, O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>; using _traits = make_traits<value_type_of<O>, sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs): binary_expression_t(Lhs lhs, Rhs rhs):
@ -204,7 +215,7 @@ namespace sqlpp
struct unary_expression_t: public value_type_of<O>::template expression_operators<unary_expression_t<O, Rhs>>, struct unary_expression_t: public value_type_of<O>::template expression_operators<unary_expression_t<O, Rhs>>,
public alias_operators<unary_expression_t<O, Rhs>> public alias_operators<unary_expression_t<O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>; using _traits = make_traits<value_type_of<O>, sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _recursive_traits = make_recursive_traits<Rhs>;
unary_expression_t(Rhs rhs): unary_expression_t(Rhs rhs):

View File

@ -51,13 +51,15 @@ namespace sqlpp
template<typename... Tables> template<typename... Tables>
struct extra_tables_t struct extra_tables_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::extra_tables>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_extra_tables>;
struct _recursive_traits struct _recursive_traits
{ {
using _parameters = std::tuple<>; using _parameters = std::tuple<>;
using _required_tables = ::sqlpp::detail::type_set<>; using _required_tables = ::sqlpp::detail::type_set<>;
using _provided_outer_tables = ::sqlpp::detail::type_set<>;
using _provided_tables = ::sqlpp::detail::type_set<>; using _provided_tables = ::sqlpp::detail::type_set<>;
using _extra_tables = ::sqlpp::detail::type_set<Tables...>; using _extra_tables = ::sqlpp::detail::type_set<Tables...>;
using _can_be_null = std::false_type;
}; };
// FIXME: extra_tables must not require tables! // FIXME: extra_tables must not require tables!
@ -104,7 +106,7 @@ namespace sqlpp
// NO EXTRA TABLES YET // NO EXTRA TABLES YET
struct no_extra_tables_t struct no_extra_tables_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

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_FIELD_SPEC_H
#define SQLPP_FIELD_SPEC_H
#include <sqlpp11/multi_column.h>
namespace sqlpp
{
template<typename NameType, typename ValueType, bool CanBeNull, bool NullIsTrivialValue>
struct field_spec_t
{
using _traits = make_traits<ValueType, tag::is_noop,
tag_if<tag::can_be_null, CanBeNull>,
tag_if<tag::null_is_trivial_value, NullIsTrivialValue>
>;
using _recursive_traits = make_recursive_traits<>;
using _name_t = NameType;
};
template<typename AliasProvider, typename FieldSpecTuple>
struct multi_field_spec_t
{
};
namespace detail
{
template<typename Select, typename NamedExpr>
struct make_field_spec_impl
{
static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0;
using type = field_spec_t<typename NamedExpr::_name_t,
value_type_of<NamedExpr>,
detail::any_t<_can_be_null, _depends_on_outer_table>::value,
null_is_trivial_value_t<NamedExpr>::value>;
};
template<typename Select, typename AliasProvider, typename... NamedExprs>
struct make_field_spec_impl<Select, multi_column_alias_t<AliasProvider, NamedExprs...>>
{
using type = multi_field_spec_t<AliasProvider, std::tuple<typename make_field_spec_impl<Select, NamedExprs>::type...>>;
};
}
template<typename Select, typename NamedExpr>
using make_field_spec_t = typename detail::make_field_spec_impl<Select, NamedExpr>::type;
}
#endif

View File

@ -28,7 +28,6 @@
#define SQLPP_FLOATING_POINT_H #define SQLPP_FLOATING_POINT_H
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -41,7 +40,8 @@ namespace sqlpp
// floating_point value type // floating_point value type
struct floating_point struct floating_point
{ {
using _tag = ::sqlpp::tag::floating_point; using _traits = make_traits<floating_point, ::sqlpp::tag::is_floating_point, ::sqlpp::tag::is_expression>;
using _tag = ::sqlpp::tag::is_floating_point;
using _cpp_value_type = double; using _cpp_value_type = double;
struct _parameter_t struct _parameter_t
@ -95,12 +95,46 @@ namespace sqlpp
bool _is_null; bool _is_null;
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_field_t;
{
using _value_type = integral;
_result_entry_t(): // I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{
static constexpr bool _null_is_trivial = true;
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_field_t<Db, FieldSpec>,
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
static constexpr bool _null_is_trivial = false;
};
template<typename Db, typename FieldSpec>
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
{
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
};
_result_field_t():
_is_valid(false), _is_valid(false),
_is_null(true), _is_null(true),
_value(0) _value(0)
@ -120,33 +154,30 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _is_null; return _is_null;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
if (_is_null)
{ {
assert(_is_valid); if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
assert(not null_value); {
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field"); throw exception("accessing value of NULL field");
}
else
{
return 0;
}
} }
return _value; return _value;
} }
operator _cpp_value_type() const { return value(); }
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
{ {
@ -257,8 +288,8 @@ namespace sqlpp
}; };
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t<Db, TrivialIsNull>& e) inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_field_t<Db, FieldSpec>& e)
{ {
return os << e.value(); return os << e.value();
} }

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct from_t struct from_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::from>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_from>;
using _recursive_traits = make_recursive_traits<Tables...>; using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -125,7 +125,7 @@ namespace sqlpp
struct no_from_t struct no_from_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -56,8 +56,11 @@ namespace sqlpp
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>, struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>,
public alias_operators<verbatim_t<ValueType>> public alias_operators<verbatim_t<ValueType>>
{ {
using _traits = make_traits<ValueType, ::sqlpp::tag::expression>; using _traits = make_traits<ValueType, ::sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; struct _recursive_traits : public make_recursive_traits<>
{
using _can_be_null = std::true_type; // since we do not know what's going on inside the verbatim, we assume it can be null
};
verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(std::string verbatim): _verbatim(verbatim) {}
verbatim_t(const verbatim_t&) = default; verbatim_t(const verbatim_t&) = default;
@ -99,7 +102,7 @@ namespace sqlpp
template<typename Container> template<typename Container>
struct value_list_t // to be used in .in() method struct value_list_t // to be used in .in() method
{ {
using _traits = make_traits<value_type_t<typename Container::value_type>, ::sqlpp::tag::expression>; using _traits = make_traits<value_type_t<typename Container::value_type>, ::sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _container_t = Container; using _container_t = Container;

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct group_by_t struct group_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::group_by>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_group_by>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -135,7 +135,7 @@ namespace sqlpp
// NO GROUP BY YET // NO GROUP BY YET
struct no_group_by_t struct no_group_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -58,7 +58,7 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct having_t struct having_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::having>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_having>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -133,7 +133,7 @@ namespace sqlpp
// NO HAVING YET // NO HAVING YET
struct no_having_t struct no_having_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -38,7 +38,7 @@ namespace sqlpp
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>, struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>,
public alias_operators<in_t<NotInverted, Operand, Args...>> public alias_operators<in_t<NotInverted, Operand, Args...>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Operand, Args...>; using _recursive_traits = make_recursive_traits<Operand, Args...>;
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;

View File

@ -42,7 +42,7 @@ namespace sqlpp
struct insert_t: public statement_name_t<insert_name_t> struct insert_t: public statement_name_t<insert_name_t>
{ {
using _traits = make_traits<no_value_t, tag::return_value>; using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {}; struct _name_t {};
template<typename Policies> template<typename Policies>

View File

@ -49,7 +49,7 @@ namespace sqlpp
{ {
struct type struct type
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };
}; };
@ -61,7 +61,7 @@ namespace sqlpp
using _is_insert_value = std::true_type; using _is_insert_value = std::true_type;
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 = typename wrap_operand<_pure_value_t>::type; using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type;
using _tvin_t = typename detail::type_if<tvin_t<_wrapped_value_t>, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together using _tvin_t = typename detail::type_if<tvin_arg_t<_wrapped_value_t>, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
using _null_t = typename detail::type_if<null_t, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together using _null_t = typename detail::type_if<null_t, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
insert_value_t(assignment_t<Column, _wrapped_value_t> assignment): insert_value_t(assignment_t<Column, _wrapped_value_t> assignment):

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;
}; };
@ -106,8 +106,8 @@ namespace sqlpp
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
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::is_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);
} }
@ -207,7 +207,7 @@ namespace sqlpp
template<typename... Columns> template<typename... Columns>
struct column_list_t struct column_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::column_list>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_column_list>;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
static_assert(sizeof...(Columns), "at least one column required in columns()"); static_assert(sizeof...(Columns), "at least one column required in columns()");
@ -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>
@ -285,7 +285,7 @@ namespace sqlpp
// NO INSERT COLUMNS/VALUES YET // NO INSERT COLUMNS/VALUES YET
struct no_insert_value_list_t struct no_insert_value_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -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 = ::sqlpp::detail::make_joined_set_t<required_tables_of<typename Assignments::_lhs_t>...>;
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

@ -28,7 +28,6 @@
#define SQLPP_INTEGRAL_H #define SQLPP_INTEGRAL_H
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -43,8 +42,8 @@ namespace sqlpp
// integral value type // integral value type
struct integral struct integral
{ {
using _traits = make_traits<integral, ::sqlpp::tag::expression>; using _traits = make_traits<integral, ::sqlpp::tag::is_integral, ::sqlpp::tag::is_expression>;
using _tag = ::sqlpp::tag::integral; using _tag = ::sqlpp::tag::is_integral;
using _cpp_value_type = int64_t; using _cpp_value_type = int64_t;
struct _parameter_t struct _parameter_t
@ -97,12 +96,46 @@ namespace sqlpp
bool _is_null; bool _is_null;
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_field_t;
{
using _value_type = integral;
_result_entry_t(): // I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{
static constexpr bool _null_is_trivial = true;
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_field_t<Db, FieldSpec>,
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
static constexpr bool _null_is_trivial = false;
};
template<typename Db, typename FieldSpec>
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
{
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
};
_result_field_t():
_is_valid(false), _is_valid(false),
_is_null(true), _is_null(true),
_value(0) _value(0)
@ -122,33 +155,30 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _is_null; return _is_null;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
if (_is_null)
{ {
assert(_is_valid); if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
assert(not null_value); {
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field"); throw exception("accessing value of NULL field");
}
else
{
return 0;
}
} }
return _value; return _value;
} }
operator _cpp_value_type() const { return value(); }
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
{ {
@ -270,8 +300,8 @@ namespace sqlpp
}; };
}; };
template<typename Db, bool NullIsTrivial> template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t<Db, NullIsTrivial>& e) inline std::ostream& operator<<(std::ostream& os, const integral::_result_field_t<Db, FieldSpec>& e)
{ {
return os << e.value(); return os << e.value();
} }

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table> template<typename Database, typename Table>
struct into_t struct into_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::into>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_into>;
using _recursive_traits = make_recursive_traits<Table>; using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table"); static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET // NO INTO YET
struct no_into_t struct no_into_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -37,7 +37,7 @@ namespace sqlpp
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>, struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>,
public alias_operators<is_null_t<NotInverted, Operand>> public alias_operators<is_null_t<NotInverted, Operand>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Operand>; using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;

View File

@ -35,41 +35,29 @@ namespace sqlpp
{ {
struct inner_join_t struct inner_join_t
{ {
template<typename Db> template<typename Lhs, typename Rhs>
struct _is_supported using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
{
static constexpr bool value = Db::_supports_inner_join;
};
static constexpr const char* _name = " INNER "; static constexpr const char* _name = " INNER ";
}; };
struct outer_join_t struct outer_join_t
{ {
template<typename Db> template<typename Lhs, typename Rhs>
struct _is_supported using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
{
static constexpr bool value = Db::_supports_outer_join;
};
static constexpr const char* _name = " OUTER "; static constexpr const char* _name = " OUTER ";
}; };
struct left_outer_join_t struct left_outer_join_t
{ {
template<typename Db> template<typename Lhs, typename Rhs>
struct _is_supported using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
{
static constexpr bool value = Db::_supports_left_outer_join;
};
static constexpr const char* _name = " LEFT OUTER "; static constexpr const char* _name = " LEFT OUTER ";
}; };
struct right_outer_join_t struct right_outer_join_t
{ {
template<typename Db> template<typename Lhs, typename Rhs>
struct _is_supported using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
{
static constexpr bool value = Db::_supports_right_outer_join;
};
static constexpr const char* _name = " RIGHT OUTER "; static constexpr const char* _name = " RIGHT OUTER ";
}; };
@ -77,8 +65,17 @@ namespace sqlpp
template<typename JoinType, typename Lhs, typename Rhs, typename On = noop> template<typename JoinType, typename Lhs, typename Rhs, typename On = noop>
struct join_t struct join_t
{ {
using _traits = make_traits<no_value_t, tag::table, tag::join>; using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; struct _recursive_traits
{
using _required_tables = detail::make_joined_set_t<required_tables_of<Lhs>, required_tables_of<Rhs>>;
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Lhs>, extra_tables_of<Rhs>>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Lhs>, parameters_of<Rhs>>;
using _can_be_null = std::false_type;
};
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join"); static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table"); static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");

View File

@ -37,7 +37,7 @@ namespace sqlpp
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>, struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>,
public alias_operators<like_t<Operand, Pattern>> public alias_operators<like_t<Operand, Pattern>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Operand, Pattern>; using _recursive_traits = make_recursive_traits<Operand, Pattern>;
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text"); static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Limit> template<typename Limit>
struct limit_t struct limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_limit>;
using _recursive_traits = make_recursive_traits<Limit>; using _recursive_traits = make_recursive_traits<Limit>;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter"); static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database> template<typename Database>
struct dynamic_limit_t struct dynamic_limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_limit>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -172,7 +172,7 @@ namespace sqlpp
struct no_limit_t struct no_limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>, struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>,
public alias_operators<max_t<Expr>> public alias_operators<max_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_expression_t<Expr>::value, "max() requires a value expression as argument"); static_assert(is_expression_t<Expr>::value, "max() requires a value expression as argument");

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>>, struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>>,
public alias_operators<min_t<Expr>> public alias_operators<min_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_expression_t<Expr>::value, "min() requires a value expression as argument"); static_assert(is_expression_t<Expr>::value, "min() requires a value expression as argument");

View File

@ -76,7 +76,7 @@ namespace sqlpp
template<typename AliasProvider, typename... Columns> template<typename AliasProvider, typename... Columns>
struct multi_column_alias_t struct multi_column_alias_t
{ {
using _traits = make_traits<no_value_t, tag::alias, tag::multi_column, tag::named_expression>; using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");

View File

@ -35,7 +35,7 @@ namespace sqlpp
{ {
struct noop struct noop
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
struct _name_t {}; struct _name_t {};

View File

@ -33,7 +33,7 @@ namespace sqlpp
{ {
struct null_t struct null_t
{ {
using _traits = make_traits<no_value_t, tag::expression>; using _traits = make_traits<no_value_t, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Offset> template<typename Offset>
struct offset_t struct offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_offset>;
using _recursive_traits = make_recursive_traits<Offset>; using _recursive_traits = make_recursive_traits<Offset>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter"); static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database> template<typename Database>
struct dynamic_offset_t struct dynamic_offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_offset>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -183,7 +183,7 @@ namespace sqlpp
struct no_offset_t struct no_offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -37,7 +37,7 @@ namespace sqlpp
template<typename Database, typename... Expr> template<typename Database, typename... Expr>
struct on_t struct on_t
{ {
using _traits = make_traits<no_value_t, tag::on>; using _traits = make_traits<no_value_t, tag::is_on>;
using _recursive_traits = make_recursive_traits<Expr...>; using _recursive_traits = make_recursive_traits<Expr...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct order_by_t struct order_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::order_by>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_order_by>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -135,7 +135,7 @@ namespace sqlpp
// NO ORDER BY YET // NO ORDER BY YET
struct no_order_by_t struct no_order_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -36,13 +36,15 @@ namespace sqlpp
template<typename ValueType, typename NameType> template<typename ValueType, typename NameType>
struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>> struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>>
{ {
using _traits = make_traits<ValueType, tag::parameter, tag::expression>; using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
struct _recursive_traits struct _recursive_traits
{ {
using _parameters = std::tuple<parameter_t>; using _parameters = std::tuple<parameter_t>;
using _provided_tables = detail::type_set<>; using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>; using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = std::true_type;
}; };
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;

View File

@ -42,7 +42,7 @@ namespace sqlpp
struct remove_name_t {}; struct remove_name_t {};
struct remove_t: public statement_name_t<remove_name_t> struct remove_t: public statement_name_t<remove_name_t>
{ {
using _traits = make_traits<no_value_t, tag::return_value>; using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {}; struct _name_t {};
template<typename Policies> template<typename Policies>

View File

@ -28,7 +28,7 @@
#define SQLPP_RESULT_ROW_H #define SQLPP_RESULT_ROW_H
#include <map> #include <map>
#include <sqlpp11/field.h> #include <sqlpp11/field_spec.h>
#include <sqlpp11/text.h> #include <sqlpp11/text.h>
#include <sqlpp11/detail/column_index_sequence.h> #include <sqlpp11/detail/column_index_sequence.h>
@ -36,14 +36,14 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
template<typename Db, typename IndexSequence, typename... NamedExprs> template<typename Db, typename IndexSequence, typename... FieldSpecs>
struct result_row_impl; struct result_row_impl;
template<typename Db, std::size_t index, typename NamedExpr> template<typename Db, std::size_t index, typename FieldSpec>
struct result_field: struct result_field:
public NamedExpr::_name_t::template _member_t<typename value_type_of<NamedExpr>::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>> public FieldSpec::_name_t::template _member_t<typename value_type_of<FieldSpec>::template _result_field_t<Db, FieldSpec>>
{ {
using _field = typename NamedExpr::_name_t::template _member_t<typename value_type_of<NamedExpr>::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>; using _field = typename FieldSpec::_name_t::template _member_t<typename value_type_of<FieldSpec>::template _result_field_t<Db, FieldSpec>>;
result_field() = default; result_field() = default;
@ -64,11 +64,11 @@ namespace sqlpp
} }
}; };
template<std::size_t index, typename AliasProvider, typename Db, typename... NamedExprs> template<std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs>
struct result_field<Db, index, multi_field_t<AliasProvider, std::tuple<NamedExprs...>>>: struct result_field<Db, index, multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>>:
public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>> public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, FieldSpecs...>, FieldSpecs...>>
{ {
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>>; using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, FieldSpecs...>, FieldSpecs...>>;
result_field() = default; result_field() = default;
@ -89,9 +89,9 @@ namespace sqlpp
} }
}; };
template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... NamedExprs> template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... FieldSpecs>
struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, NamedExprs...>: struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, FieldSpecs...>:
public result_field<Db, Is, NamedExprs>... public result_field<Db, Is, FieldSpecs>...
{ {
static constexpr std::size_t _last_index = LastIndex; static constexpr std::size_t _last_index = LastIndex;
@ -100,29 +100,29 @@ namespace sqlpp
void _validate() void _validate()
{ {
using swallow = int[]; using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::_validate(), 0)...}; (void) swallow{(result_field<Db, Is, FieldSpecs>::_validate(), 0)...};
} }
void _invalidate() void _invalidate()
{ {
using swallow = int[]; using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::_invalidate(), 0)...}; (void) swallow{(result_field<Db, Is, FieldSpecs>::_invalidate(), 0)...};
} }
template<typename Target> template<typename Target>
void _bind(Target& target) void _bind(Target& target)
{ {
using swallow = int[]; using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::_bind(target), 0)...}; (void) swallow{(result_field<Db, Is, FieldSpecs>::_bind(target), 0)...};
} }
}; };
} }
template<typename Db, typename... NamedExprs> template<typename Db, typename... FieldSpecs>
struct result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...> struct result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>
{ {
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>; using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>;
bool _is_valid; bool _is_valid;
static constexpr size_t _last_static_index = _impl::_last_index; static constexpr size_t _last_static_index = _impl::_last_index;
@ -178,11 +178,18 @@ namespace sqlpp
} }
}; };
template<typename Db, typename... NamedExprs> template<typename Db, typename... FieldSpecs>
struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...> struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>
{ {
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>; using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>;
using _field_type = detail::text::_result_entry_t<Db, false>; struct _field_spec_t
{
using _traits = make_traits<detail::text, tag::is_noop, tag::can_be_null, tag::null_is_trivial_value>;
using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
};
using _field_type = detail::text::_result_field_t<Db, _field_spec_t>;
static constexpr size_t _last_static_index = _impl::_last_index; static constexpr size_t _last_static_index = _impl::_last_index;
bool _is_valid; bool _is_valid;

View File

@ -24,48 +24,44 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_FIELD_H #ifndef SQLPP_RHS_IS_NULL_H
#define SQLPP_FIELD_H #define SQLPP_RHS_IS_NULL_H
#include <sqlpp11/multi_column.h> #include <sqlpp11/tvin.h>
namespace sqlpp namespace sqlpp
{ {
template<typename NameType, typename ValueType, bool TrivialValueIsNull> template<typename T, typename Enable = void>
struct field_t struct is_trivial_t
{ {
using _traits = make_traits<ValueType, tag::noop>; static constexpr bool _(const T&)
using _recursive_traits = make_recursive_traits<>; {
return false;
using _name_t = NameType; }
static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
}; };
template<typename AliasProvider, typename FieldTuple> template<typename T>
struct multi_field_t struct is_trivial_t<T, typename std::enable_if<std::is_member_function_pointer<decltype(&T::_is_trivial)>::value, void>::type>
{ {
static bool _(const T& t)
{
return t._is_trivial();
}
}; };
namespace detail template<typename T>
{ bool is_trivial(const T& t)
template<typename NamedExpr> {
struct make_field_t_impl return is_trivial_t<T>::_(t);
{ }
using type = field_t<typename NamedExpr::_name_t,
value_type_of<NamedExpr>,
trivial_value_is_null_t<NamedExpr>::value>;
};
template<typename AliasProvider, typename... NamedExpr>
struct make_field_t_impl<multi_column_alias_t<AliasProvider, NamedExpr...>>
{
using type = multi_field_t<AliasProvider, std::tuple<typename make_field_t_impl<NamedExpr>::type...>>;
};
}
template<typename NamedExpr>
using make_field_t = typename detail::make_field_t_impl<NamedExpr>::type;
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));
}
} }
#endif #endif

View File

@ -31,7 +31,7 @@
#include <sqlpp11/result_row.h> #include <sqlpp11/result_row.h>
#include <sqlpp11/table.h> #include <sqlpp11/table.h>
#include <sqlpp11/no_value.h> #include <sqlpp11/no_value.h>
#include <sqlpp11/field.h> #include <sqlpp11/field_spec.h>
#include <sqlpp11/expression_fwd.h> #include <sqlpp11/expression_fwd.h>
#include <sqlpp11/select_pseudo_table.h> #include <sqlpp11/select_pseudo_table.h>
#include <sqlpp11/named_interpretable.h> #include <sqlpp11/named_interpretable.h>
@ -47,14 +47,14 @@ namespace sqlpp
template<typename... Columns> template<typename... Columns>
struct select_traits struct select_traits
{ {
using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>; using _traits = make_traits<no_value_t, tag::is_select_column_list, tag::is_return_value>;
struct _name_t {}; struct _name_t {};
}; };
template<typename Column> template<typename Column>
struct select_traits<Column> struct select_traits<Column>
{ {
using _traits = make_traits<value_type_of<Column>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>; using _traits = make_traits<value_type_of<Column>, tag::is_select_column_list, tag::is_return_value, tag::is_expression, tag::is_named_expression>;
using _name_t = typename Column::_name_t; using _name_t = typename Column::_name_t;
}; };
} }
@ -245,10 +245,19 @@ namespace sqlpp
return static_cast<const _statement_t&>(*this); return static_cast<const _statement_t&>(*this);
} }
template<typename Db, typename Column>
struct _deferred_field_t
{
using type = make_field_spec_t<_statement_t, Column>;
};
template<typename Db, typename Column>
using _field_t = typename _deferred_field_t<Db, Column>::type;
template<typename Db> template<typename Db>
using _result_row_t = typename std::conditional<_is_dynamic::value, using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<Db, make_field_t<Columns>...>, dynamic_result_row_t<Db, _field_t<Db, Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type; result_row_t<Db, _field_t<Db, Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t; using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
@ -317,7 +326,7 @@ namespace sqlpp
struct no_select_column_list_t struct no_select_column_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop, ::sqlpp::tag::is_missing>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
struct _name_t {}; struct _name_t {};

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Flags> template<typename Database, typename... Flags>
struct select_flag_list_t struct select_flag_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::select_flag_list>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_select_flag_list>;
using _recursive_traits = make_recursive_traits<Flags...>; using _recursive_traits = make_recursive_traits<Flags...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -134,7 +134,7 @@ namespace sqlpp
struct no_select_flag_list_t struct no_select_flag_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -37,7 +37,7 @@ namespace sqlpp
// standard select flags // standard select flags
struct all_t struct all_t
{ {
using _traits = make_traits<no_value_t, tag::select_flag>; using _traits = make_traits<no_value_t, tag::is_select_flag>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };
static constexpr all_t all = {}; static constexpr all_t all = {};
@ -54,7 +54,7 @@ namespace sqlpp
struct distinct_t struct distinct_t
{ {
using _traits = make_traits<no_value_t, tag::select_flag>; using _traits = make_traits<no_value_t, tag::is_select_flag>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };
static constexpr distinct_t distinct = {}; static constexpr distinct_t distinct = {};
@ -71,7 +71,7 @@ namespace sqlpp
struct straight_join_t struct straight_join_t
{ {
using _traits = make_traits<no_value_t, tag::select_flag>; using _traits = make_traits<no_value_t, tag::is_select_flag>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };
static constexpr straight_join_t straight_join = {}; static constexpr straight_join_t straight_join = {};

View File

@ -32,19 +32,19 @@
namespace sqlpp namespace sqlpp
{ {
// provide type information for sub-selects that are used as named expressions or tables // provide type information for sub-selects that are used as named expressions or tables
template<typename ValueType, typename NameType> template<typename Select, typename NamedExpr>
struct select_column_spec_t struct select_column_spec_t
{ {
using _traits = make_traits<ValueType>; using _name_t = typename NamedExpr::_name_t;
using _recursive_traits = make_recursive_traits<>;
using _value_type = ValueType; // FIXME: column specs probably should use _traits, too
using _name_t = NameType; static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
struct _column_type static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0;
{
using _must_not_insert = std::true_type; using _traits = make_traits<value_type_of<NamedExpr>,
using _must_not_update = std::true_type; tag::must_not_insert,
}; tag::must_not_update,
tag_if<tag::can_be_null, _can_be_null or _depends_on_outer_table>
>;
}; };
template< template<
@ -53,9 +53,9 @@ namespace sqlpp
> >
struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t< struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t<
Select, Select,
NamedExpr...>, select_column_spec_t<value_type_of<NamedExpr>, typename NamedExpr::_name_t>...> NamedExpr...>, select_column_spec_t<Select, NamedExpr>...>
{ {
using _traits = make_traits<no_value_t, tag::table, tag::pseudo_table>; using _traits = make_traits<no_value_t, tag::is_table, tag::is_pseudo_table>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
select_pseudo_table_t(Select select): select_pseudo_table_t(Select select):

View File

@ -37,7 +37,7 @@ namespace sqlpp
{ {
Column _column; Column _column;
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table> template<typename Database, typename Table>
struct single_table_t struct single_table_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_single_table>;
using _recursive_traits = make_recursive_traits<Table>; using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table"); static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET // NO INTO YET
struct no_single_table_t struct no_single_table_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select> template<typename Select>
struct some_t struct some_t
{ {
using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::multi_expression>; using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;
struct _name_t struct _name_t

View File

@ -41,7 +41,7 @@ namespace sqlpp
template<typename Expression, sort_type SortType> template<typename Expression, sort_type SortType>
struct sort_order_t struct sort_order_t
{ {
using _traits = make_traits<no_value_t, tag::sort_order, sqlpp::tag::expression>; using _traits = make_traits<no_value_t, tag::is_sort_order, sqlpp::tag::is_expression>;
using _recursive_traits = make_recursive_traits<Expression>; using _recursive_traits = make_recursive_traits<Expression>;
Expression _expression; Expression _expression;

View File

@ -63,6 +63,7 @@ namespace sqlpp
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>; using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>; using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>; using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>; using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
@ -97,19 +98,21 @@ namespace sqlpp
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
>::type; >::type;
using _is_expression = typename std::conditional< using _traits = make_traits<_value_type, tag_if<tag::is_expression, not std::is_same<_value_type, no_value_t>::value>>;
std::is_same<_value_type, no_value_t>::value,
std::false_type,
std::true_type>::type;
using _traits = make_traits<_value_type>;
struct _recursive_traits struct _recursive_traits
{ {
using _required_tables = statement_policies_t::_required_tables; using _required_tables = statement_policies_t::_required_tables;
using _provided_tables = detail::type_set<>; using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Policies>...>; using _parameters = detail::make_parameter_tuple_t<parameters_of<Policies>...>;
using _can_be_null = detail::any_t<
can_be_null_t<_result_type_provider>::value,
::sqlpp::detail::make_intersect_set_t<
required_tables_of<_result_type_provider>,
provided_outer_tables_of<statement_policies_t>
>::size::value>;
}; };
}; };
} }
@ -125,13 +128,16 @@ namespace sqlpp
{ {
using _policies_t = typename detail::statement_policies_t<Db, Policies...>; using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>; using _traits = make_traits<value_type_of<_policies_t>,
::sqlpp::tag::is_select,
tag_if<tag::is_expression, is_expression_t<_policies_t>::value>,
tag_if<tag::is_named_expression, is_expression_t<_policies_t>::value>,
tag::requires_braces>;
using _recursive_traits = typename _policies_t::_recursive_traits; using _recursive_traits = typename _policies_t::_recursive_traits;
using _used_outer_tables = typename _policies_t::_all_provided_outer_tables;
using _result_type_provider = typename _policies_t::_result_type_provider; using _result_type_provider = typename _policies_t::_result_type_provider;
using _requires_braces = std::true_type;
using _name_t = typename _result_type_provider::_name_t; using _name_t = typename _result_type_provider::_name_t;
// Constructors // Constructors
@ -192,7 +198,7 @@ namespace sqlpp
template<typename NameData> template<typename NameData>
struct statement_name_t struct statement_name_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>, struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>,
public alias_operators<sum_t<Flag, Expr>> public alias_operators<sum_t<Flag, Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'");

View File

@ -42,14 +42,16 @@ namespace sqlpp
template<typename Table, typename... ColumnSpec> template<typename Table, typename... ColumnSpec>
struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>... struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>...
{ {
using _traits = make_traits<no_value_t, tag::table>; using _traits = make_traits<no_value_t, tag::is_table>;
struct _recursive_traits struct _recursive_traits
{ {
using _parameters = std::tuple<>; using _parameters = std::tuple<>;
using _required_tables = detail::type_set<>; using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<Table>; using _provided_tables = detail::type_set<Table>;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = std::false_type;
}; };
static_assert(sizeof...(ColumnSpec), "at least one column required per table"); static_assert(sizeof...(ColumnSpec), "at least one column required per table");

View File

@ -39,14 +39,16 @@ namespace sqlpp
struct table_alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>... struct table_alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{ {
//FIXME: Need to add join functionality //FIXME: Need to add join functionality
using _traits = make_traits<value_type_of<Table>, tag::table, tag::alias, tag::named_expression_if<is_expression_t<Table>>>; using _traits = make_traits<value_type_of<Table>, tag::is_table, tag::is_alias, tag_if<tag::is_named_expression, is_expression_t<Table>::value>>;
struct _recursive_traits struct _recursive_traits
{ {
using _parameters = std::tuple<>; using _parameters = std::tuple<>;
using _required_tables = detail::type_set<>; using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<AliasProvider>; using _provided_tables = detail::type_set<AliasProvider>;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = std::false_type;
}; };
static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables"); static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables");

View File

@ -27,7 +27,6 @@
#ifndef SQLPP_TEXT_H #ifndef SQLPP_TEXT_H
#define SQLPP_TEXT_H #define SQLPP_TEXT_H
#include <cassert>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -41,7 +40,8 @@ namespace sqlpp
// text value type // text value type
struct text struct text
{ {
using _tag = ::sqlpp::tag::text; using _traits = make_traits<text, ::sqlpp::tag::is_text, ::sqlpp::tag::is_expression>;
using _tag = ::sqlpp::tag::is_text;
using _cpp_value_type = std::string; using _cpp_value_type = std::string;
struct _parameter_t struct _parameter_t
@ -95,10 +95,46 @@ namespace sqlpp
bool _is_null; bool _is_null;
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_field_t;
// I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{ {
_result_entry_t(): static constexpr bool _null_is_trivial = true;
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_field_t<Db, FieldSpec>,
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
static constexpr bool _null_is_trivial = false;
};
template<typename Db, typename FieldSpec>
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
{
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
using _traits = make_traits<integral,
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
};
_result_field_t():
_is_valid(false), _is_valid(false),
_value_ptr(nullptr), _value_ptr(nullptr),
_len(0) _len(0)
@ -121,35 +157,29 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _value_ptr == nullptr; return _value_ptr == nullptr;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _value_ptr == nullptr and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
if (_value_ptr)
return std::string(_value_ptr, _value_ptr + _len);
else
return "";
}
operator _cpp_value_type() const { return value(); } if (not _value_ptr)
{
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
{
throw exception("accessing value of NULL field");
}
else
{
return "";
}
}
return std::string(_value_ptr, _value_ptr + _len);
}
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
@ -208,8 +238,8 @@ namespace sqlpp
}; };
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t<Db, TrivialIsNull>& e) inline std::ostream& operator<<(std::ostream& os, const text::_result_field_t<Db, FieldSpec>& e)
{ {
return os << e.value(); return os << e.value();
} }

View File

@ -37,16 +37,66 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Operand> template<typename Operand>
struct tvin_t struct tvin_arg_t
{ {
using _traits = make_traits<value_type_of<Operand>, tag::expression>; using _traits = make_traits<value_type_of<Operand>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Operand>; using _recursive_traits = make_recursive_traits<Operand>;
using _operand_t = Operand; using _operand_t = Operand;
tvin_t(Operand operand): tvin_arg_t(_operand_t operand):
_value(operand) _value(operand)
{} {}
tvin_arg_t(const tvin_arg_t&) = default;
tvin_arg_t(tvin_arg_t&&) = default;
tvin_arg_t& operator=(const tvin_arg_t&) = default;
tvin_arg_t& operator=(tvin_arg_t&&) = default;
~tvin_arg_t() = default;
_operand_t _value;
};
template<typename Context, typename Operand>
struct serializer_t<Context, tvin_arg_t<Operand>>
{
using T = tvin_arg_t<Operand>;
static Context& _(const T& t, Context& context)
{
static_assert(wrong_t<Context, Operand>::value, "tvin may only be used with operators =, == and !=");
}
};
template<typename T>
struct tvin_t;
namespace detail
{
template<typename T>
struct allow_tvin_impl
{
using type = T;
};
template <typename T>
struct allow_tvin_impl<tvin_arg_t<T>>
{
using type = tvin_t<T>;
};
}
template<typename T>
using allow_tvin_t = typename detail::allow_tvin_impl<T>::type;
template<typename Operand>
struct tvin_t
{
using _traits = make_traits<value_type_of<Operand>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Operand>;
using _operand_t = Operand;
tvin_t(tvin_arg_t<Operand> arg):
_value(arg._value)
{}
tvin_t(const tvin_t&) = default; tvin_t(const tvin_t&) = default;
tvin_t(tvin_t&&) = default; tvin_t(tvin_t&&) = default;
tvin_t& operator=(const tvin_t&) = default; tvin_t& operator=(const tvin_t&) = default;
@ -58,71 +108,30 @@ namespace sqlpp
return _value._is_trivial(); return _value._is_trivial();
} }
Operand _value; _operand_t _value;
}; };
namespace detail
{
template<typename T>
struct is_tvin_impl
{
using type = std::false_type;
};
template<typename T>
struct is_tvin_impl<tvin_t<T>>
{
using type = std::true_type;
};
}
template<typename T>
using is_tvin_t = typename detail::is_tvin_impl<T>::type;
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())
@ -138,7 +147,7 @@ namespace sqlpp
}; };
template<typename Operand> template<typename Operand>
auto tvin(Operand operand) -> tvin_t<typename wrap_operand<Operand>::type> auto tvin(Operand operand) -> tvin_arg_t<typename wrap_operand<Operand>::type>
{ {
using _operand_t = typename wrap_operand<Operand>::type; using _operand_t = typename wrap_operand<Operand>::type;
static_assert(std::is_same<_operand_t, text_operand>::value static_assert(std::is_same<_operand_t, text_operand>::value

View File

@ -32,129 +32,109 @@
namespace sqlpp namespace sqlpp
{ {
#define SQLPP_IS_VALUE_TRAIT_GENERATOR(name) \ namespace detail
{
template<typename T, typename Enable = void>
struct can_be_null_impl { using type = std::false_type; };
template<typename T>
struct can_be_null_impl<T, typename std::enable_if<T::_recursive_traits::_can_be_null::value>::type> { using type = std::true_type; };
}
template<typename T>
using can_be_null_t = typename detail::can_be_null_impl<T>::type;
namespace tag\
{\
struct can_be_null{};\
};\
namespace detail\ namespace detail\
{\ {\
template<typename T, typename Enable = void>\ template<typename T, typename Enable = void>\
struct is_##name##_impl: std::false_type {};\ struct column_spec_can_be_null_impl { using type = std::false_type; };\
template<typename T>\ template<typename T>\
struct is_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_value_type::_is_##name, std::true_type>::value>::type>: std::true_type {};\ struct column_spec_can_be_null_impl<T, typename std::enable_if<detail::is_element_of<tag::can_be_null, typename T::_traits::_tags>::value>::type> { using type = std::true_type; };\
}\ }\
template<typename T>\
using column_spec_can_be_null_t = typename detail::column_spec_can_be_null_impl<T>::type;
#define SQLPP_VALUE_TRAIT_GENERATOR(name) \
namespace tag\ namespace tag\
{\ {\
struct name{};\ struct name{};\
};\ };\
template<typename T>\
using is_##name##_t = detail::is_element_of<tag::name, typename T::_traits::_tags>;
#define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \
namespace detail\ namespace detail\
{\ {\
template<typename T, typename Enable = void>\ template<typename T, typename Enable = void>\
struct name##_impl { using type = std::false_type; };\ struct name##_impl { using type = std::false_type; };\
template<typename T>\ template<typename T>\
struct name##_impl<T, typename std::enable_if<std::is_same<typename T::_column_type::_##name, std::true_type>::value>::type> { using type = std::true_type; };\ struct name##_impl<T, typename std::enable_if<detail::is_element_of<tag::name, typename T::_traits::_tags>::value>::type> { using type = std::true_type; };\
}\ }\
template<typename T>\ template<typename T>\
using name##_t = typename detail::name##_impl<T>::type; using name##_t = typename detail::name##_impl<T>::type;
#define SQLPP_TYPE_TRAIT_GENERATOR(name) \ SQLPP_VALUE_TRAIT_GENERATOR(is_boolean);
namespace detail\ SQLPP_VALUE_TRAIT_GENERATOR(is_integral);
{\ SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point);
template<typename T, typename Enable = void>\
struct name##_impl: std::false_type {};\
template<typename T>\
struct name##_impl<T, typename std::enable_if<std::is_same<typename T::_##name, std::true_type>::value>::type>: std::true_type {};\
}\
template<typename T>\
struct name##_t: detail::name##_impl<T> {};
#define SQLPP_CONNECTOR_TRAIT_GENERATOR(name) \
namespace detail\
{\
template<typename T, typename Enable = void>\
struct connector_##name##_impl: std::false_type {};\
template<typename T>\
struct connector_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_tags::_##name, std::true_type>::value>::type>: std::true_type {};\
}\
template<typename T>\
struct connector_##name##_t: detail::connector_##name##_impl<T> {};
SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean);
SQLPP_IS_VALUE_TRAIT_GENERATOR(integral);
SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point);
template<typename T> template<typename T>
using is_numeric_t = detail::any_t< using is_numeric_t = detail::any_t<
detail::is_element_of<tag::integral, typename T::_traits::_tags>::value, detail::is_element_of<tag::is_integral, typename T::_traits::_tags>::value,
detail::is_element_of<tag::floating_point, typename T::_traits::_tags>::value>; detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>;
SQLPP_IS_VALUE_TRAIT_GENERATOR(text); SQLPP_VALUE_TRAIT_GENERATOR(is_text);
SQLPP_IS_VALUE_TRAIT_GENERATOR(wrapped_value); SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(expression); SQLPP_VALUE_TRAIT_GENERATOR(is_expression);
SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); SQLPP_VALUE_TRAIT_GENERATOR(is_named_expression);
namespace tag SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression);
{ SQLPP_VALUE_TRAIT_GENERATOR(is_alias);
template<typename C> SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag);
using named_expression_if = typename std::conditional<C::value, tag::named_expression, void>::type;
}
namespace tag
{
template<typename C>
using expression_if = typename std::conditional<C::value, tag::expression, void>::type;
}
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression);
SQLPP_IS_VALUE_TRAIT_GENERATOR(alias);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_insert); SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update); SQLPP_VALUE_TRAIT_GENERATOR(must_not_update);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert); SQLPP_VALUE_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_VALUE_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null); SQLPP_VALUE_TRAIT_GENERATOR(null_is_trivial_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(noop); SQLPP_VALUE_TRAIT_GENERATOR(is_noop);
SQLPP_IS_VALUE_TRAIT_GENERATOR(missing); SQLPP_VALUE_TRAIT_GENERATOR(is_missing);
SQLPP_IS_VALUE_TRAIT_GENERATOR(return_value); SQLPP_VALUE_TRAIT_GENERATOR(is_return_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(table); SQLPP_VALUE_TRAIT_GENERATOR(is_table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(join); SQLPP_VALUE_TRAIT_GENERATOR(is_join);
SQLPP_IS_VALUE_TRAIT_GENERATOR(pseudo_table); SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(column); SQLPP_VALUE_TRAIT_GENERATOR(is_column);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select); SQLPP_VALUE_TRAIT_GENERATOR(is_select);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list); SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list); SQLPP_VALUE_TRAIT_GENERATOR(is_select_column_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(from); SQLPP_VALUE_TRAIT_GENERATOR(is_from);
SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table); SQLPP_VALUE_TRAIT_GENERATOR(is_single_table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(into); SQLPP_VALUE_TRAIT_GENERATOR(is_into);
SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables); SQLPP_VALUE_TRAIT_GENERATOR(is_extra_tables);
SQLPP_IS_VALUE_TRAIT_GENERATOR(on); SQLPP_VALUE_TRAIT_GENERATOR(is_on);
SQLPP_IS_VALUE_TRAIT_GENERATOR(where); SQLPP_VALUE_TRAIT_GENERATOR(is_where);
SQLPP_IS_VALUE_TRAIT_GENERATOR(group_by); SQLPP_VALUE_TRAIT_GENERATOR(is_group_by);
SQLPP_IS_VALUE_TRAIT_GENERATOR(having); SQLPP_VALUE_TRAIT_GENERATOR(is_having);
SQLPP_IS_VALUE_TRAIT_GENERATOR(order_by); SQLPP_VALUE_TRAIT_GENERATOR(is_order_by);
SQLPP_IS_VALUE_TRAIT_GENERATOR(limit); SQLPP_VALUE_TRAIT_GENERATOR(is_limit);
SQLPP_IS_VALUE_TRAIT_GENERATOR(offset); SQLPP_VALUE_TRAIT_GENERATOR(is_offset);
SQLPP_IS_VALUE_TRAIT_GENERATOR(using_); SQLPP_VALUE_TRAIT_GENERATOR(is_using_);
SQLPP_IS_VALUE_TRAIT_GENERATOR(column_list); SQLPP_VALUE_TRAIT_GENERATOR(is_column_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_column); SQLPP_VALUE_TRAIT_GENERATOR(is_multi_column);
SQLPP_IS_VALUE_TRAIT_GENERATOR(value_list); SQLPP_VALUE_TRAIT_GENERATOR(is_value_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(assignment); SQLPP_VALUE_TRAIT_GENERATOR(is_assignment);
SQLPP_IS_VALUE_TRAIT_GENERATOR(update_list); SQLPP_VALUE_TRAIT_GENERATOR(is_update_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_list); SQLPP_VALUE_TRAIT_GENERATOR(is_insert_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value); SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value_list); SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(sort_order); SQLPP_VALUE_TRAIT_GENERATOR(is_sort_order);
SQLPP_IS_VALUE_TRAIT_GENERATOR(parameter); SQLPP_VALUE_TRAIT_GENERATOR(is_parameter);
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); SQLPP_VALUE_TRAIT_GENERATOR(requires_braces);
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value); SQLPP_VALUE_TRAIT_GENERATOR(enforce_null_result_treatment);
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
template<typename Tag, bool Condition>
using tag_if = typename std::conditional<Condition, Tag, void>::type;
template<typename Database> template<typename Database>
using is_database = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using is_database = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template<typename T, template<typename> class IsTag>
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;
namespace detail namespace detail
{ {
template<typename T> template<typename T>
@ -175,6 +155,12 @@ namespace sqlpp
using type = typename T::_recursive_traits::_provided_tables; using type = typename T::_recursive_traits::_provided_tables;
}; };
template<typename T>
struct provided_outer_table_of_impl
{
using type = typename T::_recursive_traits::_provided_outer_tables;
};
template<typename T> template<typename T>
struct extra_table_of_impl struct extra_table_of_impl
{ {
@ -211,6 +197,9 @@ namespace sqlpp
template<typename T> template<typename T>
using provided_tables_of = typename detail::provided_table_of_impl<T>::type; using provided_tables_of = typename detail::provided_table_of_impl<T>::type;
template<typename T>
using provided_outer_tables_of = typename detail::provided_outer_table_of_impl<T>::type;
template<typename T> template<typename T>
using extra_tables_of = typename detail::extra_table_of_impl<T>::type; using extra_tables_of = typename detail::extra_table_of_impl<T>::type;
@ -231,8 +220,10 @@ namespace sqlpp
{ {
using _required_tables = detail::make_joined_set_t<required_tables_of<Arguments>...>; using _required_tables = detail::make_joined_set_t<required_tables_of<Arguments>...>;
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Arguments>...>; using _provided_tables = detail::make_joined_set_t<provided_tables_of<Arguments>...>;
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Arguments>...>;
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Arguments>...>; using _extra_tables = detail::make_joined_set_t<extra_tables_of<Arguments>...>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Arguments>...>; using _parameters = detail::make_parameter_tuple_t<parameters_of<Arguments>...>;
using _can_be_null = detail::any_t<can_be_null_t<Arguments>::value...>;
}; };
} }

View File

@ -43,7 +43,7 @@ namespace sqlpp
struct update_t: public statement_name_t<update_name_t> struct update_t: public statement_name_t<update_name_t>
{ {
using _traits = make_traits<no_value_t, tag::return_value>; using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {}; struct _name_t {};
template<typename Policies> template<typename Policies>

View File

@ -56,7 +56,7 @@ namespace sqlpp
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
struct update_list_t struct update_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::update_list>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_update_list>;
using _recursive_traits = make_recursive_traits<Assignments...>; using _recursive_traits = make_recursive_traits<Assignments...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -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<
@ -130,7 +130,7 @@ namespace sqlpp
struct no_update_list_t struct no_update_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -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 = ::sqlpp::detail::make_joined_set_t<required_tables_of<typename Assignments::_lhs_t>...>;
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...} };

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct using_t struct using_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::using_>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_using_>;
using _recursive_traits = make_recursive_traits<Tables...>; using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -128,7 +128,7 @@ namespace sqlpp
// NO USING YET // NO USING YET
struct no_using_t struct no_using_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -42,13 +42,17 @@ namespace sqlpp
{ {
}; };
}; };
using _value_type = no_value_t; using _traits = make_traits<no_value_t>;
struct _column_type {};
}; };
} }
struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t> struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>
{ {
struct _recursive_traits: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>::_recursive_traits
{
using _provided_outer_tables = detail::type_set<verbatim_table_t>;
};
struct _name_t {}; struct _name_t {};
verbatim_table_t(std::string representation): verbatim_table_t(std::string representation):

View File

@ -58,7 +58,7 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct where_t struct where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -141,7 +141,7 @@ namespace sqlpp
template<> template<>
struct where_t<void, bool> struct where_t<void, bool>
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -184,7 +184,7 @@ namespace sqlpp
template<bool Required> template<bool Required>
struct no_where_t struct no_where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -43,7 +43,7 @@ namespace sqlpp
struct boolean_operand struct boolean_operand
{ {
using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = bool; using _value_t = bool;
@ -81,7 +81,7 @@ namespace sqlpp
struct integral_operand struct integral_operand
{ {
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = int64_t; using _value_t = int64_t;
@ -120,7 +120,7 @@ namespace sqlpp
struct floating_point_operand struct floating_point_operand
{ {
using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = double; using _value_t = double;
@ -158,7 +158,7 @@ namespace sqlpp
struct text_operand struct text_operand
{ {
using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = std::string; using _value_t = std::string;

View File

@ -155,22 +155,20 @@ for tableCreation in tableCreations:
print(' };', file=header) print(' };', file=header)
print(' };', file=header) print(' };', file=header)
#print(sqlColumnType) #print(sqlColumnType)
print(' using _value_type = ' + NAMESPACE + '::' + types[sqlColumnType] + ';', file=header) traitslist = [NAMESPACE + '::' + types[sqlColumnType]];
print(' struct _column_type', file=header)
print(' {', file=header)
requireInsert = True requireInsert = True
if column.hasAutoValue: if column.hasAutoValue:
print(' using _must_not_insert = std::true_type;', file=header) traitslist.append(NAMESPACE + '::tag::must_not_insert');
print(' using _must_not_update = std::true_type;', file=header) traitslist.append(NAMESPACE + '::tag::must_not_update');
requireInsert = False requireInsert = False
if not column.notNull: if not column.notNull:
print(' using _can_be_null = std::true_type;', file=header) traitslist.append(NAMESPACE + '::tag::can_be_null');
requireInsert = False requireInsert = False
if column.hasDefaultValue: if column.hasDefaultValue:
requireInsert = False requireInsert = False
if requireInsert: if requireInsert:
print(' using _require_insert = std::true_type;', file=header) traitslist.append(NAMESPACE + '::tag::require_insert');
print(' };', file=header) print(' using _traits = ' + NAMESPACE + '::make_traits<' + ', '.join(traitslist) + '>;', file=header)
print(' };', file=header) print(' };', file=header)
print(' }', file=header) print(' }', file=header)
print('', file=header) print('', file=header)

View File

@ -15,6 +15,7 @@ build_and_run(SelectTypeTest)
build_and_run(FunctionTest) build_and_run(FunctionTest)
build_and_run(PreparedTest) build_and_run(PreparedTest)
build_and_run(Minimalistic) build_and_run(Minimalistic)
build_and_run(ResultTest)
# if you want to use the generator, you can do something like this: # if you want to use the generator, you can do something like this:
#find_package(PythonInterp REQUIRED) #find_package(PythonInterp REQUIRED)

View File

@ -36,7 +36,6 @@
MockDb db = {}; MockDb db = {};
MockDb::_serializer_context_t printer; MockDb::_serializer_context_t printer;
SQLPP_ALIAS_PROVIDER(kaesekuchen);
int main() int main()
{ {
@ -125,6 +124,10 @@ int main()
// join // join
serialize(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).str(); serialize(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).str();
{
auto inner = t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta);
serialize(select(t.alpha).from(inner), printer).str();
}
// multi_column // multi_column
serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).str(); serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).str();

View File

@ -30,8 +30,13 @@
#include <sqlpp11/serializer_context.h> #include <sqlpp11/serializer_context.h>
#include <sqlpp11/connection.h> #include <sqlpp11/connection.h>
struct MockDb: public sqlpp::connection template<bool enforceNullResultTreatment>
struct MockDbT: public sqlpp::connection
{ {
using _traits = ::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
{ {
std::ostringstream _os; std::ostringstream _os;
@ -156,5 +161,8 @@ struct MockDb: public sqlpp::connection
}; };
using MockDb = MockDbT<false>;
using EnforceDb = MockDbT<true>;
#endif #endif

View File

@ -21,11 +21,7 @@ namespace test
const T& operator()() const { return delta; } const T& operator()() const { return delta; }
}; };
}; };
using _value_type = sqlpp::varchar; using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
struct _column_type
{
using _can_be_null = std::true_type;
};
}; };
struct Epsilon struct Epsilon
{ {
@ -40,11 +36,7 @@ namespace test
const T& operator()() const { return epsilon; } const T& operator()() const { return epsilon; }
}; };
}; };
using _value_type = sqlpp::bigint; using _traits = sqlpp::make_traits<sqlpp::bigint, sqlpp::tag::can_be_null>;
struct _column_type
{
using _can_be_null = std::true_type;
};
}; };
struct Omega struct Omega
{ {
@ -59,11 +51,7 @@ namespace test
const T& operator()() const { return omega; } const T& operator()() const { return omega; }
}; };
}; };
using _value_type = sqlpp::floating_point; using _traits = sqlpp::make_traits<sqlpp::floating_point, sqlpp::tag::can_be_null>;
struct _column_type
{
using _can_be_null = std::true_type;
};
}; };
} }
@ -100,13 +88,7 @@ namespace test
const T& operator()() const { return alpha; } const T& operator()() const { return alpha; }
}; };
}; };
using _value_type = sqlpp::bigint; using _traits = sqlpp::make_traits<sqlpp::bigint, sqlpp::tag::must_not_insert, sqlpp::tag::must_not_update, sqlpp::tag::can_be_null>;
struct _column_type
{
using _must_not_insert = std::true_type;
using _must_not_update = std::true_type;
using _can_be_null = std::true_type;
};
}; };
struct Beta struct Beta
{ {
@ -121,11 +103,7 @@ namespace test
const T& operator()() const { return beta; } const T& operator()() const { return beta; }
}; };
}; };
using _value_type = sqlpp::varchar; using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
struct _column_type
{
using _can_be_null = std::true_type;
};
}; };
struct Gamma struct Gamma
{ {
@ -140,11 +118,7 @@ namespace test
const T& operator()() const { return gamma; } const T& operator()() const { return gamma; }
}; };
}; };
using _value_type = sqlpp::boolean; using _traits = sqlpp::make_traits<sqlpp::boolean, sqlpp::tag::require_insert>;
struct _column_type
{
using _require_insert = std::true_type;
};
}; };
struct Delta struct Delta
{ {
@ -159,11 +133,7 @@ namespace test
const T& operator()() const { return delta; } const T& operator()() const { return delta; }
}; };
}; };
using _value_type = sqlpp::integer; using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::can_be_null>;
struct _column_type
{
using _can_be_null = std::true_type;
};
}; };
} }

View File

@ -36,14 +36,6 @@
MockDb db = {}; MockDb db = {};
MockDb::_serializer_context_t printer; MockDb::_serializer_context_t printer;
namespace alias
{
SQLPP_ALIAS_PROVIDER(a);
SQLPP_ALIAS_PROVIDER(b);
SQLPP_ALIAS_PROVIDER(left);
SQLPP_ALIAS_PROVIDER(right);
}
int main() int main()
{ {
test::TabFoo f; test::TabFoo f;