0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +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
{
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 _serializer_context_t = << This context is used to serialize 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>
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>;
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select>
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>;
struct _name_t

View File

@ -30,48 +30,25 @@
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/rhs_is_null.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/simple_column.h>
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>
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 _column_t = Lhs;
using _value_t = Rhs;
using _lhs_t = Lhs;
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),
_rhs(rhs)
{}
@ -82,8 +59,8 @@ namespace sqlpp
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
_value_t _rhs;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -93,7 +70,7 @@ namespace sqlpp
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))
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

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct avg_t: public floating_point::template expression_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>;
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
#include <cstdlib>
#include <cassert>
#include <ostream>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
@ -42,7 +41,8 @@ namespace sqlpp
// boolean value type
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;
struct _parameter_t
@ -96,10 +96,46 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
template<typename Db, typename FieldSpec>
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_null(true),
_value(false)
@ -119,33 +155,30 @@ namespace sqlpp
bool is_null() const
{
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_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 (connector_assert_result_validity_t<Db>::value)
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (_is_null)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
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 false;
}
}
return _value;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
@ -200,8 +233,8 @@ namespace sqlpp
};
};
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t<Db, TrivialIsNull>& e)
template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_field_t<Db, FieldSpec>& e)
{
return os << e.value();
}

View File

@ -42,25 +42,31 @@
namespace sqlpp
{
template<typename Table, typename ColumnSpec>
struct column_t: public ColumnSpec::_value_type::template expression_operators<column_t<Table, ColumnSpec>>,
public ColumnSpec::_value_type::template column_operators<column_t<Table, ColumnSpec>>
struct column_t: public value_type_of<ColumnSpec>::template expression_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
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<Table>;
using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<ColumnSpec>;
};
using _spec_t = ColumnSpec;
using _table = Table;
using _column_type = typename _spec_t::_column_type;
using _name_t = typename _spec_t::_name_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(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...>>,
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...>;
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>>,
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>;
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
{
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<>;
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>
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;
};

View File

@ -204,13 +204,30 @@ namespace sqlpp
struct make_difference_set<type_set<Minuends...>, type_set<Subtrahends...>>
{
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;
};
template<typename Minuend, typename Subtrahend>
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>
struct transform_set

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct exists_t: public boolean::template expression_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>;
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>>,
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 _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),
_rhs(rhs)
{}
@ -55,8 +57,8 @@ namespace sqlpp
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -68,7 +70,7 @@ namespace sqlpp
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
if (rhs_is_null(t))
{
context << " IS NULL";
}
@ -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>>,
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 _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),
_rhs(rhs)
{}
@ -100,8 +104,8 @@ namespace sqlpp
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -113,7 +117,7 @@ namespace sqlpp
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
if (rhs_is_null(t))
{
context << " IS NOT NULL";
}
@ -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>>,
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>;
unary_expression_t(Rhs rhs):
@ -155,10 +159,17 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << "(";
context << "NOT ";
serialize(t._lhs, context);
if (trivial_value_is_null_t<Rhs>::value)
{
serialize(t._lhs, context);
context << " IS NULL ";
}
else
{
context << "NOT ";
serialize(t._rhs, context);
}
context << ")";
return context;
}
};
@ -166,7 +177,7 @@ namespace sqlpp
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>>
{
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>;
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>>,
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>;
unary_expression_t(Rhs rhs):

View File

@ -51,13 +51,15 @@ namespace sqlpp
template<typename... Tables>
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
{
using _parameters = std::tuple<>;
using _required_tables = ::sqlpp::detail::type_set<>;
using _provided_outer_tables = ::sqlpp::detail::type_set<>;
using _provided_tables = ::sqlpp::detail::type_set<>;
using _extra_tables = ::sqlpp::detail::type_set<Tables...>;
using _can_be_null = std::false_type;
};
// FIXME: extra_tables must not require tables!
@ -104,7 +106,7 @@ namespace sqlpp
// NO EXTRA TABLES YET
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<>;
// 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
#include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -41,7 +40,8 @@ namespace sqlpp
// floating_point value type
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;
struct _parameter_t
@ -95,12 +95,46 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
using _value_type = integral;
template<typename Db, typename FieldSpec>
struct _result_field_t;
_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_null(true),
_value(0)
@ -120,33 +154,30 @@ namespace sqlpp
bool is_null() const
{
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_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 (connector_assert_result_validity_t<Db>::value)
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (_is_null)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
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 0;
}
}
return _value;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
@ -257,8 +288,8 @@ namespace sqlpp
};
};
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t<Db, TrivialIsNull>& e)
template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_field_t<Db, FieldSpec>& e)
{
return os << e.value();
}

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Tables>
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 _is_dynamic = is_database<Database>;
@ -125,7 +125,7 @@ namespace sqlpp
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<>;
// Data

View File

@ -56,8 +56,11 @@ namespace sqlpp
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>,
public alias_operators<verbatim_t<ValueType>>
{
using _traits = make_traits<ValueType, ::sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<>;
using _traits = make_traits<ValueType, ::sqlpp::tag::is_expression>;
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(const verbatim_t&) = default;
@ -99,7 +102,7 @@ namespace sqlpp
template<typename Container>
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 _container_t = Container;

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _is_dynamic = is_database<Database>;
@ -135,7 +135,7 @@ namespace sqlpp
// NO GROUP BY YET
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<>;
// Data

View File

@ -58,7 +58,7 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _is_dynamic = is_database<Database>;
@ -133,7 +133,7 @@ namespace sqlpp
// NO HAVING YET
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<>;
// Data

View File

@ -38,7 +38,7 @@ namespace sqlpp
struct in_t: public boolean::template expression_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...>;
static constexpr bool _inverted = not NotInverted;

View File

@ -42,7 +42,7 @@ namespace sqlpp
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 {};
template<typename Policies>

View File

@ -49,7 +49,7 @@ namespace sqlpp
{
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<>;
};
};
@ -61,7 +61,7 @@ namespace sqlpp
using _is_insert_value = std::true_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 _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
insert_value_t(assignment_t<Column, _wrapped_value_t> assignment):

View File

@ -97,8 +97,8 @@ namespace sqlpp
~insert_list_data_t() = default;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::_value_t...> _values;
std::tuple<simple_column_t<typename Assignments::_lhs_t>...> _columns;
std::tuple<typename Assignments::_rhs_t...> _values;
interpretable_list_t<Database> _dynamic_columns;
interpretable_list_t<Database> _dynamic_values;
};
@ -106,8 +106,8 @@ namespace sqlpp
template<typename Database, typename... Assignments>
struct insert_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::insert_list>;
using _recursive_traits = make_recursive_traits<typename Assignments::_column_t..., typename Assignments::_value_t...>;
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_insert_list>;
using _recursive_traits = make_recursive_traits<typename Assignments::_lhs_t..., typename Assignments::_rhs_t...>;
using _is_dynamic = is_database<Database>;
@ -134,9 +134,9 @@ namespace sqlpp
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>;
static_assert(not detail::is_element_of<typename Assignment::_column_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add() argument must not be used in insert");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<typename Assignment::_lhs_t>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using ok = ::sqlpp::detail::all_t<
@ -150,7 +150,7 @@ namespace sqlpp
template<typename Assignment>
void _add_impl(Assignment assignment, const std::true_type&)
{
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_lhs_t>{assignment._lhs});
_data._dynamic_values.emplace_back(assignment._rhs);
}
@ -207,7 +207,7 @@ namespace sqlpp
template<typename... Columns>
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...>;
static_assert(sizeof...(Columns), "at least one column required in columns()");
@ -233,7 +233,7 @@ namespace sqlpp
void add(Assignments... assignments)
{
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<insert_value_t<typename Assignments::_column_t>...>;
using _arg_value_tuple = std::tuple<insert_value_t<typename Assignments::_lhs_t>...>;
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
@ -248,7 +248,7 @@ namespace sqlpp
template<typename... Assignments>
void _add_impl(const std::true_type&, Assignments... assignments)
{
return _data._insert_values.emplace_back(insert_value_t<typename Assignments::_column_t>{assignments}...);
return _data._insert_values.emplace_back(insert_value_t<typename Assignments::_lhs_t>{assignments}...);
}
template<typename... Assignments>
@ -285,7 +285,7 @@ namespace sqlpp
// NO INSERT COLUMNS/VALUES YET
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<>;
// 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(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");
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
#include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -43,8 +42,8 @@ namespace sqlpp
// integral value type
struct integral
{
using _traits = make_traits<integral, ::sqlpp::tag::expression>;
using _tag = ::sqlpp::tag::integral;
using _traits = make_traits<integral, ::sqlpp::tag::is_integral, ::sqlpp::tag::is_expression>;
using _tag = ::sqlpp::tag::is_integral;
using _cpp_value_type = int64_t;
struct _parameter_t
@ -97,12 +96,46 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
using _value_type = integral;
template<typename Db, typename FieldSpec>
struct _result_field_t;
_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_null(true),
_value(0)
@ -122,33 +155,30 @@ namespace sqlpp
bool is_null() const
{
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_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 (connector_assert_result_validity_t<Db>::value)
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (_is_null)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
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 0;
}
}
return _value;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
@ -270,8 +300,8 @@ namespace sqlpp
};
};
template<typename Db, bool NullIsTrivial>
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t<Db, NullIsTrivial>& e)
template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const integral::_result_field_t<Db, FieldSpec>& e)
{
return os << e.value();
}

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table>
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>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET
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<>;
// Data

View File

@ -37,7 +37,7 @@ namespace sqlpp
struct is_null_t: public boolean::template expression_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>;
static constexpr bool _inverted = not NotInverted;

View File

@ -35,41 +35,29 @@ namespace sqlpp
{
struct inner_join_t
{
template<typename Db>
struct _is_supported
{
static constexpr bool value = Db::_supports_inner_join;
};
template<typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " INNER ";
};
struct outer_join_t
{
template<typename Db>
struct _is_supported
{
static constexpr bool value = Db::_supports_outer_join;
};
template<typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " OUTER ";
};
struct left_outer_join_t
{
template<typename Db>
struct _is_supported
{
static constexpr bool value = Db::_supports_left_outer_join;
};
template<typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " LEFT OUTER ";
};
struct right_outer_join_t
{
template<typename Db>
struct _is_supported
{
static constexpr bool value = Db::_supports_right_outer_join;
};
template<typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " RIGHT OUTER ";
};
@ -77,8 +65,17 @@ namespace sqlpp
template<typename JoinType, typename Lhs, typename Rhs, typename On = noop>
struct join_t
{
using _traits = make_traits<no_value_t, tag::table, tag::join>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
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<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>>,
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>;
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>
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>;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database>
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<>;
// Data
@ -172,7 +172,7 @@ namespace sqlpp
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<>;
// Data

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct max_t: public value_type_of<Expr>::template expression_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>;
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>>,
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>;
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>
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...>;
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
{
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<>;
struct _name_t {};

View File

@ -33,7 +33,7 @@ namespace sqlpp
{
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<>;
};

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Offset>
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>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database>
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<>;
// Data
@ -183,7 +183,7 @@ namespace sqlpp
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<>;
// Data

View File

@ -37,7 +37,7 @@ namespace sqlpp
template<typename Database, typename... Expr>
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 _is_dynamic = is_database<Database>;

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _is_dynamic = is_database<Database>;
@ -135,7 +135,7 @@ namespace sqlpp
// NO ORDER BY YET
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<>;
// Data

View File

@ -36,13 +36,15 @@ namespace sqlpp
template<typename ValueType, typename 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
{
using _parameters = std::tuple<parameter_t>;
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 = std::true_type;
};
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_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 {};
template<typename Policies>

View File

@ -28,7 +28,7 @@
#define SQLPP_RESULT_ROW_H
#include <map>
#include <sqlpp11/field.h>
#include <sqlpp11/field_spec.h>
#include <sqlpp11/text.h>
#include <sqlpp11/detail/column_index_sequence.h>
@ -36,14 +36,14 @@ namespace sqlpp
{
namespace detail
{
template<typename Db, typename IndexSequence, typename... NamedExprs>
template<typename Db, typename IndexSequence, typename... FieldSpecs>
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:
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;
@ -64,11 +64,11 @@ namespace sqlpp
}
};
template<std::size_t index, typename AliasProvider, typename Db, typename... NamedExprs>
struct result_field<Db, index, multi_field_t<AliasProvider, std::tuple<NamedExprs...>>>:
public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>>
template<std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs>
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, 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;
@ -89,9 +89,9 @@ namespace sqlpp
}
};
template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... NamedExprs>
struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, NamedExprs...>:
public result_field<Db, Is, 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...>, FieldSpecs...>:
public result_field<Db, Is, FieldSpecs>...
{
static constexpr std::size_t _last_index = LastIndex;
@ -100,29 +100,29 @@ namespace sqlpp
void _validate()
{
using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::_validate(), 0)...};
(void) swallow{(result_field<Db, Is, FieldSpecs>::_validate(), 0)...};
}
void _invalidate()
{
using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::_invalidate(), 0)...};
(void) swallow{(result_field<Db, Is, FieldSpecs>::_invalidate(), 0)...};
}
template<typename Target>
void _bind(Target& target)
{
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>
struct result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>
template<typename Db, typename... FieldSpecs>
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;
static constexpr size_t _last_static_index = _impl::_last_index;
@ -178,11 +178,18 @@ namespace sqlpp
}
};
template<typename Db, typename... NamedExprs>
struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>
template<typename Db, typename... FieldSpecs>
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 _field_type = detail::text::_result_entry_t<Db, false>;
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>;
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;
bool _is_valid;

View File

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

View File

@ -31,7 +31,7 @@
#include <sqlpp11/result_row.h>
#include <sqlpp11/table.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/field.h>
#include <sqlpp11/field_spec.h>
#include <sqlpp11/expression_fwd.h>
#include <sqlpp11/select_pseudo_table.h>
#include <sqlpp11/named_interpretable.h>
@ -47,14 +47,14 @@ namespace sqlpp
template<typename... Columns>
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 {};
};
template<typename 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;
};
}
@ -245,10 +245,19 @@ namespace sqlpp
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>
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
dynamic_result_row_t<Db, _field_t<Db, Columns>...>,
result_row_t<Db, _field_t<Db, Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
@ -317,7 +326,7 @@ namespace sqlpp
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<>;
struct _name_t {};

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Flags>
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 _is_dynamic = is_database<Database>;
@ -134,7 +134,7 @@ namespace sqlpp
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<>;
// Data

View File

@ -37,7 +37,7 @@ namespace sqlpp
// standard select flags
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<>;
};
static constexpr all_t all = {};
@ -54,7 +54,7 @@ namespace sqlpp
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<>;
};
static constexpr distinct_t distinct = {};
@ -71,7 +71,7 @@ namespace sqlpp
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<>;
};
static constexpr straight_join_t straight_join = {};

View File

@ -32,19 +32,19 @@
namespace sqlpp
{
// 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
{
using _traits = make_traits<ValueType>;
using _recursive_traits = make_recursive_traits<>;
using _value_type = ValueType; // FIXME: column specs probably should use _traits, too
using _name_t = typename NamedExpr::_name_t;
using _name_t = NameType;
struct _column_type
{
using _must_not_insert = std::true_type;
using _must_not_update = std::true_type;
};
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 _traits = make_traits<value_type_of<NamedExpr>,
tag::must_not_insert,
tag::must_not_update,
tag_if<tag::can_be_null, _can_be_null or _depends_on_outer_table>
>;
};
template<
@ -53,9 +53,9 @@ namespace sqlpp
>
struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t<
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<>;
select_pseudo_table_t(Select select):

View File

@ -37,7 +37,7 @@ namespace sqlpp
{
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<>;
};

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table>
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>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET
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<>;
// Data

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select>
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>;
struct _name_t

View File

@ -41,7 +41,7 @@ namespace sqlpp
template<typename Expression, sort_type SortType>
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>;
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_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 _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
>::type;
using _is_expression = typename std::conditional<
std::is_same<_value_type, no_value_t>::value,
std::false_type,
std::true_type>::type;
using _traits = make_traits<_value_type>;
using _traits = make_traits<_value_type, tag_if<tag::is_expression, not std::is_same<_value_type, no_value_t>::value>>;
struct _recursive_traits
{
using _required_tables = statement_policies_t::_required_tables;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
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 _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 _used_outer_tables = typename _policies_t::_all_provided_outer_tables;
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;
// Constructors
@ -192,7 +198,7 @@ namespace sqlpp
template<typename NameData>
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<>;
// Data

View File

@ -35,7 +35,7 @@ namespace sqlpp
struct sum_t: public value_type_of<Expr>::template expression_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>;
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>
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
{
using _parameters = std::tuple<>;
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<Table>;
using _provided_outer_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");

View File

@ -39,14 +39,16 @@ namespace sqlpp
struct table_alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{
//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
{
using _parameters = std::tuple<>;
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<AliasProvider>;
using _provided_outer_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");

View File

@ -27,7 +27,6 @@
#ifndef SQLPP_TEXT_H
#define SQLPP_TEXT_H
#include <cassert>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -41,7 +40,8 @@ namespace sqlpp
// text value type
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;
struct _parameter_t
@ -95,10 +95,46 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
template<typename Db, typename FieldSpec>
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),
_value_ptr(nullptr),
_len(0)
@ -121,35 +157,29 @@ namespace sqlpp
bool is_null() const
{
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _value_ptr == nullptr;
}
_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 (connector_assert_result_validity_t<Db>::value)
{
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 "";
}
if (not _is_valid)
throw exception("accessing value in non-existing row");
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>
void _bind(Target& target, size_t i)
@ -208,8 +238,8 @@ namespace sqlpp
};
};
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t<Db, TrivialIsNull>& e)
template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const text::_result_field_t<Db, FieldSpec>& e)
{
return os << e.value();
}

View File

@ -37,16 +37,66 @@
namespace sqlpp
{
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 _operand_t = Operand;
tvin_t(Operand operand):
tvin_arg_t(_operand_t 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(tvin_t&&) = default;
tvin_t& operator=(const tvin_t&) = default;
@ -58,71 +108,30 @@ namespace sqlpp
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>
struct serializer_t<Context, tvin_t<Operand>>
{
using T = tvin_t<Operand>;
static void _(const T& t, Context& context)
{
static_assert(wrong_t<T>::value, "tvin() must not be used with anything but =, ==, != and !");
}
};
template<typename Operand>
struct maybe_tvin_t
{
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _is_trivial()
{
return false;
}
maybe_tvin_t(Operand operand):
_value(operand)
{}
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
Operand _value;
};
template<typename Operand>
struct maybe_tvin_t<tvin_t<Operand>>
{
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
bool _is_trivial() const
{
return _value._is_trivial();
};
maybe_tvin_t(tvin_t<Operand> operand):
_value(operand._value)
{}
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
typename tvin_t<Operand>::_operand_t _value;
};
template<typename Context, typename Operand>
struct serializer_t<Context, maybe_tvin_t<Operand>>
{
using T = maybe_tvin_t<Operand>;
static Context& _(const T& t, Context& context)
{
if (t._is_trivial())
@ -138,7 +147,7 @@ namespace sqlpp
};
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;
static_assert(std::is_same<_operand_t, text_operand>::value

View File

@ -32,129 +32,109 @@
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\
{\
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>\
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\
{\
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\
{\
template<typename T, typename Enable = void>\
struct name##_impl { using type = std::false_type; };\
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>\
using name##_t = typename detail::name##_impl<T>::type;
#define SQLPP_TYPE_TRAIT_GENERATOR(name) \
namespace detail\
{\
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);
SQLPP_VALUE_TRAIT_GENERATOR(is_boolean);
SQLPP_VALUE_TRAIT_GENERATOR(is_integral);
SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point);
template<typename T>
using is_numeric_t = detail::any_t<
detail::is_element_of<tag::integral, typename T::_traits::_tags>::value,
detail::is_element_of<tag::floating_point, typename T::_traits::_tags>::value>;
SQLPP_IS_VALUE_TRAIT_GENERATOR(text);
SQLPP_IS_VALUE_TRAIT_GENERATOR(wrapped_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(expression);
SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression);
namespace tag
{
template<typename C>
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);
detail::is_element_of<tag::is_integral, typename T::_traits::_tags>::value,
detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>;
SQLPP_VALUE_TRAIT_GENERATOR(is_text);
SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value);
SQLPP_VALUE_TRAIT_GENERATOR(is_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_named_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_alias);
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert);
SQLPP_VALUE_TRAIT_GENERATOR(must_not_update);
SQLPP_VALUE_TRAIT_GENERATOR(require_insert);
SQLPP_VALUE_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_VALUE_TRAIT_GENERATOR(null_is_trivial_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(noop);
SQLPP_IS_VALUE_TRAIT_GENERATOR(missing);
SQLPP_IS_VALUE_TRAIT_GENERATOR(return_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(join);
SQLPP_IS_VALUE_TRAIT_GENERATOR(pseudo_table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(column);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(from);
SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(into);
SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables);
SQLPP_IS_VALUE_TRAIT_GENERATOR(on);
SQLPP_IS_VALUE_TRAIT_GENERATOR(where);
SQLPP_IS_VALUE_TRAIT_GENERATOR(group_by);
SQLPP_IS_VALUE_TRAIT_GENERATOR(having);
SQLPP_IS_VALUE_TRAIT_GENERATOR(order_by);
SQLPP_IS_VALUE_TRAIT_GENERATOR(limit);
SQLPP_IS_VALUE_TRAIT_GENERATOR(offset);
SQLPP_IS_VALUE_TRAIT_GENERATOR(using_);
SQLPP_IS_VALUE_TRAIT_GENERATOR(column_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_column);
SQLPP_IS_VALUE_TRAIT_GENERATOR(value_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(assignment);
SQLPP_IS_VALUE_TRAIT_GENERATOR(update_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(sort_order);
SQLPP_IS_VALUE_TRAIT_GENERATOR(parameter);
SQLPP_VALUE_TRAIT_GENERATOR(is_noop);
SQLPP_VALUE_TRAIT_GENERATOR(is_missing);
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value);
SQLPP_VALUE_TRAIT_GENERATOR(is_table);
SQLPP_VALUE_TRAIT_GENERATOR(is_join);
SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table);
SQLPP_VALUE_TRAIT_GENERATOR(is_column);
SQLPP_VALUE_TRAIT_GENERATOR(is_select);
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_select_column_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_from);
SQLPP_VALUE_TRAIT_GENERATOR(is_single_table);
SQLPP_VALUE_TRAIT_GENERATOR(is_into);
SQLPP_VALUE_TRAIT_GENERATOR(is_extra_tables);
SQLPP_VALUE_TRAIT_GENERATOR(is_on);
SQLPP_VALUE_TRAIT_GENERATOR(is_where);
SQLPP_VALUE_TRAIT_GENERATOR(is_group_by);
SQLPP_VALUE_TRAIT_GENERATOR(is_having);
SQLPP_VALUE_TRAIT_GENERATOR(is_order_by);
SQLPP_VALUE_TRAIT_GENERATOR(is_limit);
SQLPP_VALUE_TRAIT_GENERATOR(is_offset);
SQLPP_VALUE_TRAIT_GENERATOR(is_using_);
SQLPP_VALUE_TRAIT_GENERATOR(is_column_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_column);
SQLPP_VALUE_TRAIT_GENERATOR(is_value_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_assignment);
SQLPP_VALUE_TRAIT_GENERATOR(is_update_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value);
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value_list);
SQLPP_VALUE_TRAIT_GENERATOR(is_sort_order);
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_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
SQLPP_VALUE_TRAIT_GENERATOR(enforce_null_result_treatment);
template<typename Tag, bool Condition>
using tag_if = typename std::conditional<Condition, Tag, void>::type;
template<typename Database>
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
{
template<typename T>
@ -175,6 +155,12 @@ namespace sqlpp
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>
struct extra_table_of_impl
{
@ -211,6 +197,9 @@ namespace sqlpp
template<typename T>
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>
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 _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 _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>
{
using _traits = make_traits<no_value_t, tag::return_value>;
using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {};
template<typename Policies>

View File

@ -56,7 +56,7 @@ namespace sqlpp
template<typename Database, typename... Assignments>
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 _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_assignment_t<Assignment>::value, "invalid assignment argument in add()");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>;
static_assert(not detail::is_element_of<typename Assignment::_column_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add() argument must not be updated");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_lhs_t>::value, "add() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add()");
using ok = ::sqlpp::detail::all_t<
@ -130,7 +130,7 @@ namespace sqlpp
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<>;
// 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(::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");
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>
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 _is_dynamic = is_database<Database>;
@ -128,7 +128,7 @@ namespace sqlpp
// NO USING YET
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<>;
// Data

View File

@ -42,13 +42,17 @@ namespace sqlpp
{
};
};
using _value_type = no_value_t;
struct _column_type {};
using _traits = make_traits<no_value_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 {};
verbatim_table_t(std::string representation):

View File

@ -58,7 +58,7 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _is_dynamic = is_database<Database>;
@ -141,7 +141,7 @@ namespace sqlpp
template<>
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<>;
// Data
@ -184,7 +184,7 @@ namespace sqlpp
template<bool Required>
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<>;
// Data

View File

@ -43,7 +43,7 @@ namespace sqlpp
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 _value_t = bool;
@ -81,7 +81,7 @@ namespace sqlpp
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 _value_t = int64_t;
@ -120,7 +120,7 @@ namespace sqlpp
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 _value_t = double;
@ -158,7 +158,7 @@ namespace sqlpp
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 _value_t = std::string;

View File

@ -155,22 +155,20 @@ for tableCreation in tableCreations:
print(' };', file=header)
print(' };', file=header)
#print(sqlColumnType)
print(' using _value_type = ' + NAMESPACE + '::' + types[sqlColumnType] + ';', file=header)
print(' struct _column_type', file=header)
print(' {', file=header)
traitslist = [NAMESPACE + '::' + types[sqlColumnType]];
requireInsert = True
if column.hasAutoValue:
print(' using _must_not_insert = std::true_type;', file=header)
print(' using _must_not_update = std::true_type;', file=header)
traitslist.append(NAMESPACE + '::tag::must_not_insert');
traitslist.append(NAMESPACE + '::tag::must_not_update');
requireInsert = False
if not column.notNull:
print(' using _can_be_null = std::true_type;', file=header)
traitslist.append(NAMESPACE + '::tag::can_be_null');
requireInsert = False
if column.hasDefaultValue:
requireInsert = False
if requireInsert:
print(' using _require_insert = std::true_type;', file=header)
print(' };', file=header)
traitslist.append(NAMESPACE + '::tag::require_insert');
print(' using _traits = ' + NAMESPACE + '::make_traits<' + ', '.join(traitslist) + '>;', 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(PreparedTest)
build_and_run(Minimalistic)
build_and_run(ResultTest)
# if you want to use the generator, you can do something like this:
#find_package(PythonInterp REQUIRED)

View File

@ -36,7 +36,6 @@
MockDb db = {};
MockDb::_serializer_context_t printer;
SQLPP_ALIAS_PROVIDER(kaesekuchen);
int main()
{
@ -125,6 +124,10 @@ int main()
// join
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
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/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
{
std::ostringstream _os;
@ -156,5 +161,8 @@ struct MockDb: public sqlpp::connection
};
using MockDb = MockDbT<false>;
using EnforceDb = MockDbT<true>;
#endif

View File

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

View File

@ -36,14 +36,6 @@
MockDb db = {};
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()
{
test::TabFoo f;