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

Made a bunch of compile errors easier to read

Fixed a few bugs in the process, too.
Probably also created a few, need better checks for resulting
statements.
This commit is contained in:
rbock 2014-03-23 20:54:44 +01:00
parent 4a25f5bcb9
commit a38a9d6f65
30 changed files with 406 additions and 285 deletions

View File

@ -33,6 +33,9 @@ namespace sqlpp
template<typename Expression, typename AliasProvider> template<typename Expression, typename AliasProvider>
struct expression_alias_t struct expression_alias_t
{ {
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
struct _value_type: Expression::_value_type struct _value_type: Expression::_value_type
{ {
using _is_expression = std::false_type; using _is_expression = std::false_type;

View File

@ -35,14 +35,15 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Select> template<typename Select>
struct any_t: public boolean::template operators<any_t<Select>> struct any_t
{ {
static_assert(is_select_t<Select>::value, "any() requires a single column select expression as argument"); static_assert(is_select_t<Select>::value, "any() requires a single column select expression as argument");
static_assert(is_value_t<Select>::value, "any() requires a single column select expression as argument"); static_assert(is_value_t<Select>::value, "any() requires a single column select expression as argument");
struct _value_type: public Select::_value_type::_base_value_type struct _value_type: public Select::_value_type::_base_value_type
{ {
using _is_multi_expression = std::true_type; // must not be named using _is_expression = std::false_type;
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
}; };
struct _name_t struct _name_t
@ -90,8 +91,9 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
auto any(T t) -> typename vendor::any_t<typename operand_t<T, is_select_t>::type> auto any(T t) -> typename vendor::any_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "any() requires a select expression as argument");
return { t }; return { t };
} }

View File

@ -34,7 +34,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct avg_t: public floating_point::template operators<avg_t<Flag, Expr>> struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>
{ {
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
@ -93,14 +93,16 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto avg(T t) -> typename vendor::avg_t<vendor::noop, typename operand_t<T, is_value_t>::type> auto avg(T t) -> typename vendor::avg_t<vendor::noop, vendor::wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t<sqlpp::distinct_t, typename operand_t<T, is_value_t>::type> auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2013, 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_DETAIL_BASIC_EXPRESSION_OPERATORS_H
#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
#include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/in_fwd.h>
#include <sqlpp11/vendor/is_null_fwd.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace detail
{
struct boolean;
}
// basic operators
template<typename Base, template<typename> class IsCorrectValueType>
struct basic_expression_operators
{
template<typename T>
struct _is_valid_comparison_operand
{
static constexpr bool value =
(is_expression_t<T>::value // expressions are OK
or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too
and IsCorrectValueType<T>::value // the correct value type is required, of course
;
};
template<typename T>
vendor::equal_to_t<Base, vendor::wrap_operand_t<T>> operator==(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::not_equal_to_t<Base, vendor::wrap_operand_t<T>> operator!=(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::less_than_t<Base, vendor::wrap_operand_t<T>> operator<(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::less_equal_t<Base, vendor::wrap_operand_t<T>> operator<=(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::greater_than_t<Base, vendor::wrap_operand_t<T>> operator>(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::greater_equal_t<Base, vendor::wrap_operand_t<T>> operator>=(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
vendor::is_null_t<true, Base> is_null() const
{
return { *static_cast<const Base*>(this) };
}
vendor::is_null_t<false, Base> is_not_null() const
{
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::asc> asc()
{
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::desc> desc()
{
return { *static_cast<const Base*>(this) };
}
// Hint: use value_list wrapper for containers...
template<typename... T>
vendor::in_t<true, Base, vendor::wrap_operand_t<T>...> in(T... t) const
{
static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t<T>...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... };
}
template<typename... T>
vendor::in_t<false, Base, vendor::wrap_operand_t<T>...> not_in(T... t) const
{
static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t<T>...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... };
}
template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&)
{
return { *static_cast<const Base*>(this) };
}
};
}
#endif

View File

@ -1,137 +0,0 @@
/*
* Copyright (c) 2013, 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_DETAIL_BASIC_OPERATORS_H
#define SQLPP_DETAIL_BASIC_OPERATORS_H
#include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/in_fwd.h>
#include <sqlpp11/vendor/is_null_fwd.h>
namespace sqlpp
{
namespace detail
{
struct boolean;
}
// basic operators
template<typename Base, template<typename> class Constraint>
struct basic_operators
{
template<typename T>
vendor::equal_to_t<Base, typename Constraint<T>::type> operator==(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::not_equal_to_t<Base, typename Constraint<T>::type> operator!=(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::less_than_t<Base, typename Constraint<T>::type> operator<(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::less_equal_t<Base, typename Constraint<T>::type> operator<=(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::greater_than_t<Base, typename Constraint<T>::type> operator>(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::greater_equal_t<Base, typename Constraint<T>::type> operator>=(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
vendor::is_null_t<true, Base> is_null() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_null()");
return { *static_cast<const Base*>(this) };
}
vendor::is_null_t<false, Base> is_not_null() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_not_null()");
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::asc> asc()
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used for sorting");
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::desc> desc()
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used for sorting");
return { *static_cast<const Base*>(this) };
}
// Hint: use value_list wrapper for containers...
template<typename... T>
vendor::in_t<true, Base, typename Constraint<T>::type...> in(T... t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with in()");
return { *static_cast<const Base*>(this), {t}... };
}
template<typename... T>
vendor::in_t<false, Base, typename Constraint<T>::type...> not_in(T... t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot with be used with not_in()");
return { *static_cast<const Base*>(this), {t}... };
}
template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&)
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot have a name");
return { *static_cast<const Base*>(this) };
}
};
}
#endif

View File

@ -30,7 +30,7 @@
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
#include <ostream> #include <ostream>
#include <sqlpp11/basic_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -175,33 +175,45 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
using _operand_t = operand_t<T, is_boolean_t>; struct _is_valid_operand
template<typename T> {
using _constraint = is_boolean_t<T>; static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_boolean_t<T>::value // the correct value type is required, of course
;
};
template<typename Base> template<typename Base>
struct operators: public basic_operators<Base, _operand_t> struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
{ {
template<typename T> template<typename T>
vendor::logical_and_t<Base, typename _operand_t<T>::type> operator and(T t) const vendor::logical_and_t<Base, vendor::wrap_operand_t<T>> operator and(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), {t} }; static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::logical_or_t<Base, typename _operand_t<T>::type> operator or(T t) const vendor::logical_or_t<Base, vendor::wrap_operand_t<T>> operator or(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), {t} }; static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
} }
vendor::logical_not_t<Base> operator not() const vendor::logical_not_t<Base> operator not() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be as operand for operator not");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
}; };
template<typename Base>
struct column_operators
{
};
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, bool TrivialIsNull>

View File

@ -42,7 +42,8 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Table, typename ColumnSpec> template<typename Table, typename ColumnSpec>
struct column_t: public ColumnSpec::_value_type::template operators<column_t<Table, 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>>
{ {
using _is_column = std::true_type; using _is_column = std::true_type;
using _spec_t = ColumnSpec; using _spec_t = ColumnSpec;
@ -55,6 +56,8 @@ namespace sqlpp
using _is_named_expression = std::true_type; using _is_named_expression = std::true_type;
using _is_alias = std::false_type; using _is_alias = std::false_type;
}; };
template<typename T>
using _is_valid_operand = typename _value_type::template _is_valid_operand<T>;
using _name_t = typename ColumnSpec::_name_t; using _name_t = typename ColumnSpec::_name_t;
@ -77,19 +80,12 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto operator =(T t) const auto operator =(T t) const -> vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>
-> typename std::enable_if<_value_type::template _constraint<typename vendor::wrap_operand<T>::type>::value and not std::is_same<column_t, T>::value,
vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>>::type
{ {
return { *this, {t} }; using rhs = vendor::wrap_operand_t<T>;
} static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand");
template<typename T> return { *this, {t} };
auto operator =(T t) const
-> typename std::enable_if<not(_value_type::template _constraint<typename vendor::wrap_operand<T>::type>::value and not std::is_same<column_t, T>::value),
vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>>::type
{
static_assert(sqlpp::vendor::wrong_t<T>::value, "invalid assignment operand");
} }
auto operator =(sqlpp::null_t) const auto operator =(sqlpp::null_t) const

View File

@ -35,10 +35,10 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct count_t: public sqlpp::detail::integral::template operators<count_t<Flag, Expr>> struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>
{ {
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
static_assert(is_value_t<Expr>::value, "count() requires a sql value as argument"); static_assert(is_expression_t<Expr>::value, "count() requires a sql expression as argument");
struct _value_type: public sqlpp::detail::integral struct _value_type: public sqlpp::detail::integral
{ {
@ -94,14 +94,16 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto count(T t) -> typename vendor::count_t<vendor::noop, typename operand_t<T, is_value_t>::type> auto count(T t) -> typename vendor::count_t<vendor::noop, vendor::wrap_operand_t<T>>
{ {
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t<sqlpp::distinct_t, typename operand_t<T, is_value_t>::type> auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>>
{ {
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };
} }

View File

@ -34,7 +34,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Select> template<typename Select>
struct exists_t: public boolean::template operators<exists_t<Select>> struct exists_t: public boolean::template expression_operators<exists_t<Select>>
{ {
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument"); static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
@ -88,8 +88,9 @@ namespace sqlpp
template<typename T> template<typename T>
auto exists(T t) -> typename vendor::exists_t<typename operand_t<T, is_select_t>::type> auto exists(T t) -> typename vendor::exists_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "exists() requires a select expression as argument");
return { t }; return { t };
} }

View File

@ -29,7 +29,7 @@
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
#include <sqlpp11/basic_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -177,78 +177,100 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
using _operand_t = operand_t<T, is_numeric_t>; struct _is_valid_operand
template<typename T> {
using _constraint = is_numeric_t<T>; static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course
;
};
template<typename Base> template<typename Base>
struct operators: public basic_operators<Base, _operand_t> struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{ {
template<typename T> template<typename T>
vendor::plus_t<Base, floating_point, typename _operand_t<T>::type> operator +(T t) const vendor::plus_t<Base, floating_point, vendor::wrap_operand_t<T>> operator +(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), {t} }; static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::minus_t<Base, floating_point, typename _operand_t<T>::type> operator -(T t) const vendor::minus_t<Base, floating_point, vendor::wrap_operand_t<T>> operator -(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), {t} }; static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::multiplies_t<Base, floating_point, typename _operand_t<T>::type> operator *(T t) const vendor::multiplies_t<Base, floating_point, vendor::wrap_operand_t<T>> operator *(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), {t} };
return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::divides_t<Base, typename _operand_t<T>::type> operator /(T t) const vendor::divides_t<Base, vendor::wrap_operand_t<T>> operator /(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), {t} };
return { *static_cast<const Base*>(this), rhs{t} };
} }
vendor::unary_plus_t<floating_point, Base> operator +() const vendor::unary_plus_t<floating_point, Base> operator +() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
vendor::unary_minus_t<floating_point, Base> operator -() const vendor::unary_minus_t<floating_point, Base> operator -() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
};
template<typename T> template<typename Base>
auto operator +=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() + t) struct column_operators
{ {
return *static_cast<const Base*>(this) = operator +(t); template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::plus_t<Base, floating_point, vendor::wrap_operand_t<T>>>
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator -=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() - t) auto operator -=(T t) const -> vendor::assignment_t<Base, vendor::minus_t<Base, floating_point, vendor::wrap_operand_t<T>>>
{ {
return *static_cast<const Base*>(this) = operator -(t); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator /=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() / t) auto operator /=(T t) const -> vendor::assignment_t<Base, vendor::divides_t<Base, vendor::wrap_operand_t<T>>>
{ {
return *static_cast<const Base*>(this) = operator /(t); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator *=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() * t) auto operator *=(T t) const -> vendor::assignment_t<Base, vendor::multiplies_t<Base, floating_point, vendor::wrap_operand_t<T>>>
{ {
return *static_cast<const Base*>(this) = operator *(t); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
}; };
}; };

View File

@ -32,6 +32,7 @@
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
#include <sqlpp11/vendor/in.h> #include <sqlpp11/vendor/in.h>
#include <sqlpp11/vendor/is_null.h> #include <sqlpp11/vendor/is_null.h>
#include <sqlpp11/vendor/value_type.h>
#include <sqlpp11/exists.h> #include <sqlpp11/exists.h>
#include <sqlpp11/any.h> #include <sqlpp11/any.h>
#include <sqlpp11/some.h> #include <sqlpp11/some.h>
@ -45,7 +46,7 @@
namespace sqlpp namespace sqlpp
{ {
template<typename T> template<typename T>
auto value(T t) -> typename operand_t<T, is_value_t>::type auto value(T t) -> vendor::wrap_operand_t<T>
{ {
using _table_set = ::sqlpp::detail::type_set<>; using _table_set = ::sqlpp::detail::type_set<>;
static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string"); static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string");
@ -53,7 +54,7 @@ namespace sqlpp
} }
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t: public ValueType::template operators<verbatim_t<ValueType>> struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>
{ {
using _value_type = ValueType; using _value_type = ValueType;
using _table_set = ::sqlpp::detail::type_set<>; using _table_set = ::sqlpp::detail::type_set<>;
@ -103,7 +104,7 @@ namespace sqlpp
{ {
using _container_t = Container; using _container_t = Container;
using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else? using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else?
using _value_type = typename operand_t<typename _container_t::value_type, is_value_t>::type::_value_type; using _value_type = vendor::value_type_t<typename _container_t::value_type>;
value_list_t(_container_t container): value_list_t(_container_t container):
_container(container) _container(container)

View File

@ -29,7 +29,7 @@
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
#include <sqlpp11/basic_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/vendor/value_type.h> #include <sqlpp11/vendor/value_type.h>
@ -177,85 +177,111 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
using _operand_t = operand_t<T, is_numeric_t>; struct _is_valid_operand
template<typename T> {
using _constraint = is_numeric_t<T>; static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course
;
};
template<typename Base> template<typename Base>
struct operators: public basic_operators<Base, _operand_t> struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{ {
template<typename T> template<typename T>
vendor::plus_t<Base, vendor::value_type_t<T>, typename _operand_t<T>::type> operator +(T t) const vendor::plus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator +(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::minus_t<Base, vendor::value_type_t<T>, typename _operand_t<T>::type> operator -(T t) const vendor::minus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator -(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::multiplies_t<Base, vendor::value_type_t<T>, typename _operand_t<T>::type> operator *(T t) const vendor::multiplies_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator *(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::divides_t<Base, typename _operand_t<T>::type> operator /(T t) const vendor::divides_t<Base, vendor::wrap_operand_t<T>> operator /(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::modulus_t<Base, typename _operand_t<T>::type> operator %(T t) const vendor::modulus_t<Base, vendor::wrap_operand_t<T>> operator %(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
vendor::unary_plus_t<integral, Base> operator +() const vendor::unary_plus_t<integral, Base> operator +() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
vendor::unary_minus_t<integral, Base> operator -() const vendor::unary_minus_t<integral, Base> operator -() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
};
template<typename T> template<typename Base>
auto operator +=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() + t) struct column_operators
{ {
return *static_cast<const Base*>(this) = operator +(t); template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::plus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>>
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator -=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() - t) auto operator -=(T t) const -> vendor::assignment_t<Base, vendor::minus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>>
{ {
return *static_cast<const Base*>(this) = operator -(t); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator /=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() / t) auto operator /=(T t) const -> vendor::assignment_t<Base, vendor::divides_t<Base, vendor::wrap_operand_t<T>>>
{ {
return *static_cast<const Base*>(this) = operator /(t); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator *=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() * t) auto operator *=(T t) const -> vendor::assignment_t<Base, vendor::multiplies_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>>
{ {
return *static_cast<const Base*>(this) = operator *(t); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
}; };
}; };

View File

@ -34,7 +34,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct max_t: public boolean::template operators<max_t<Expr>> struct max_t: public Expr::_value_type::template expression_operators<max_t<Expr>>
{ {
static_assert(is_value_t<Expr>::value, "max() requires a value expression as argument"); static_assert(is_value_t<Expr>::value, "max() requires a value expression as argument");
@ -87,8 +87,9 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto max(T t) -> typename vendor::max_t<typename operand_t<T, is_value_t>::type> auto max(T t) -> typename vendor::max_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "max() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -34,7 +34,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct min_t: public boolean::template operators<min_t<Expr>> struct min_t: public Expr::_value_type::template expression_operators<min_t<Expr>>
{ {
static_assert(is_value_t<Expr>::value, "min() requires a value expression as argument"); static_assert(is_value_t<Expr>::value, "min() requires a value expression as argument");
@ -87,8 +87,9 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto min(T t) -> typename vendor::min_t<typename operand_t<T, is_value_t>::type> auto min(T t) -> typename vendor::min_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "min() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -36,8 +36,19 @@ namespace sqlpp
template<typename T> template<typename T>
using _constraint = std::false_type; using _constraint = std::false_type;
template<typename T>
struct _is_valid_operand
{
static constexpr bool value = false;
};
template<typename Base> template<typename Base>
struct operators struct expression_operators
{
};
template<typename Base>
struct column_operators
{ {
}; };
}; };

View File

@ -33,11 +33,15 @@
namespace sqlpp namespace sqlpp
{ {
template<typename ValueType, typename NameType> template<typename ValueType, typename NameType>
struct parameter_t: public ValueType::template operators<parameter_t<ValueType, NameType>> struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>>
{ {
using _value_type = ValueType; #warning need to check that Value Type is an SQL value type!
struct _value_type: public ValueType
{
using _is_expression = std::true_type;
using _is_alias = std::false_type;
};
using _is_parameter = std::true_type; using _is_parameter = std::true_type;
using _is_expression_t = std::true_type;
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
using _table_set = sqlpp::detail::type_set<>; using _table_set = sqlpp::detail::type_set<>;

View File

@ -80,7 +80,7 @@ namespace sqlpp
typename Limit = vendor::no_limit_t, typename Limit = vendor::no_limit_t,
typename Offset = vendor::no_offset_t typename Offset = vendor::no_offset_t
> >
struct select_t: public detail::select_helper_t<ColumnList, From>::_value_type::template operators<select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>> struct select_t: public detail::select_helper_t<ColumnList, From>::_value_type::template expression_operators<select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>>
{ {
using _database_t = Database; using _database_t = Database;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;

View File

@ -35,14 +35,15 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Select> template<typename Select>
struct some_t: public boolean::template operators<some_t<Select>> struct some_t
{ {
static_assert(is_select_t<Select>::value, "some() requires a single column select expression as argument"); static_assert(is_select_t<Select>::value, "some() requires a single column select expression as argument");
static_assert(is_value_t<Select>::value, "some() requires a single column select expression as argument"); static_assert(is_value_t<Select>::value, "some() requires a single column select expression as argument");
struct _value_type: public Select::_value_type::_base_value_type struct _value_type: public Select::_value_type::_base_value_type
{ {
using _is_multi_expression = std::true_type; // must not be named using _is_expression = std::false_type;
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
}; };
struct _name_t struct _name_t
@ -90,8 +91,9 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto some(T t) -> typename vendor::some_t<typename operand_t<T, is_select_t>::type> auto some(T t) -> typename vendor::some_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "some() requires a select expression as argument");
return { t }; return { t };
} }

View File

@ -34,7 +34,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct sum_t: public boolean::template operators<sum_t<Flag, Expr>> struct sum_t: public Expr::_value_type::template expression_operators<sum_t<Flag, Expr>>
{ {
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument"); static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument");
@ -93,14 +93,16 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto sum(T t) -> typename vendor::sum_t<vendor::noop, typename operand_t<T, is_value_t>::type> auto sum(T t) -> typename vendor::sum_t<vendor::noop, vendor::wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto sum(const sqlpp::distinct_t&, T t) -> typename vendor::sum_t<sqlpp::distinct_t, typename operand_t<T, is_value_t>::type> auto sum(const sqlpp::distinct_t&, T t) -> typename vendor::sum_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t }; return { t };
} }

View File

@ -28,7 +28,7 @@
#define SQLPP_TEXT_H #define SQLPP_TEXT_H
#include <cassert> #include <cassert>
#include <sqlpp11/basic_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/vendor/concat.h> #include <sqlpp11/vendor/concat.h>
@ -180,33 +180,47 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
using _operand_t = operand_t<T, is_text_t>; struct _is_valid_operand
template<typename T> {
using _constraint = is_text_t<T>; static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_text_t<T>::value // the correct value type is required, of course
;
};
template<typename Base> template<typename Base>
struct operators: public basic_operators<Base, _operand_t> struct expression_operators: public basic_expression_operators<Base, is_text_t>
{ {
template<typename T> template<typename T>
vendor::concat_t<Base, typename _operand_t<T>::type> operator+(T t) const vendor::concat_t<Base, vendor::wrap_operand_t<T>> operator+(T t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
auto operator +=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() + t) vendor::like_t<Base, vendor::wrap_operand_t<T>> like(T t) const
{ {
return *static_cast<const Base*>(this) = operator +(t); using rhs = vendor::wrap_operand_t<T>;
} static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()");
template<typename T>
vendor::like_t<Base, typename _operand_t<T>::type> like(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
};
template<typename Base>
struct column_operators
{
template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::concat_t<Base, vendor::wrap_operand_t<T>>>
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
}; };
}; };

View File

@ -129,16 +129,6 @@ namespace sqlpp
template<typename T, template<typename> class IsTag> template<typename T, template<typename> class IsTag>
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type; using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;
template<typename T, template<typename> class IsCorrectType>
struct operand_t
{
using type = typename vendor::wrap_operand<T>::type;
static_assert(not is_alias_t<type>::value, "expression operand must not be an alias");
static_assert(is_expression_t<type>::value, "expression required");
static_assert(IsCorrectType<type>::value, "invalid operand type");
};
} }
#endif #endif

View File

@ -36,7 +36,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename First, typename... Args> template<typename First, typename... Args>
struct concat_t: public First::_value_type::template operators<concat_t<First, Args...>> struct concat_t: public First::_value_type::template expression_operators<concat_t<First, Args...>>
{ {
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(sqlpp::detail::all_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()"); static_assert(sqlpp::detail::all_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()");

View File

@ -40,7 +40,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, tag::equal_to, Rhs>: public ::sqlpp::detail::boolean::template operators<equal_to_t<Lhs, Rhs>> struct binary_expression_t<Lhs, tag::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<equal_to_t<Lhs, Rhs>>
{ {
using _value_type = ::sqlpp::detail::boolean; using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>; using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
@ -85,7 +85,7 @@ namespace sqlpp
}; };
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, tag::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template operators<not_equal_to_t<Lhs, Rhs>> struct binary_expression_t<Lhs, tag::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<not_equal_to_t<Lhs, Rhs>>
{ {
using _value_type = ::sqlpp::detail::boolean; using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>; using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
@ -130,7 +130,7 @@ namespace sqlpp
}; };
template<typename Rhs> template<typename Rhs>
struct unary_expression_t<tag::logical_not, Rhs>: public ::sqlpp::detail::boolean::template operators<logical_not_t<Rhs>> struct unary_expression_t<tag::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<logical_not_t<Rhs>>
{ {
using _value_type = ::sqlpp::detail::boolean; using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Rhs>; using _parameter_tuple_t = std::tuple<Rhs>;
@ -165,7 +165,7 @@ namespace sqlpp
}; };
template<typename Lhs, typename O, typename Rhs> template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public O::_value_type::template operators<binary_expression_t<Lhs, O, Rhs>> struct binary_expression_t: public O::_value_type::template expression_operators<binary_expression_t<Lhs, O, Rhs>>
{ {
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = Rhs; using _rhs_t = Rhs;
@ -205,7 +205,7 @@ namespace sqlpp
}; };
template<typename O, typename Rhs> template<typename O, typename Rhs>
struct unary_expression_t: public O::_value_type::template operators<unary_expression_t<O, Rhs>> struct unary_expression_t: public O::_value_type::template expression_operators<unary_expression_t<O, Rhs>>
{ {
using _value_type = typename O::_value_type; using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<Rhs>; using _parameter_tuple_t = std::tuple<Rhs>;

View File

@ -37,7 +37,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<bool NotInverted, typename Operand, typename... Args> template<bool NotInverted, typename Operand, typename... Args>
struct in_t: public boolean::template operators<in_t<NotInverted, Operand, Args...>> struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>
{ {
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;
static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); static_assert(sizeof...(Args) > 0, "in() requires at least one argument");

View File

@ -36,7 +36,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<bool NotInverted, typename Operand> template<bool NotInverted, typename Operand>
struct is_null_t: public boolean::template operators<is_null_t<NotInverted, Operand>> struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>
{ {
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;
using _table_set = typename Operand::_table_set; using _table_set = typename Operand::_table_set;

View File

@ -36,7 +36,7 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Operand, typename Pattern> template<typename Operand, typename Pattern>
struct like_t: public boolean::template operators<like_t<Operand, Pattern>> struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>
{ {
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text"); static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text"); static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");

View File

@ -37,7 +37,11 @@ namespace sqlpp
{ {
using _name_t = typename Expr::_name_t; using _name_t = typename Expr::_name_t;
using _value_type = typename Expr::_value_type; using _value_type = typename Expr::_value_type;
struct _column_type {}; struct _column_type
{
using _must_not_insert = std::true_type;
using _must_not_update = std::true_type;
};
}; };
template< template<

View File

@ -227,6 +227,10 @@ namespace sqlpp
}; };
// FIXME: Need to allow std::ref arguments // FIXME: Need to allow std::ref arguments
template<typename T>
using wrap_operand_t = typename wrap_operand<T>::type;
} }
} }

View File

@ -40,6 +40,8 @@ int main()
test::TabFoo f; test::TabFoo f;
test::TabBar t; test::TabBar t;
//f.omega + 4 *= "";
// MEMBER FUNCTIONS // MEMBER FUNCTIONS
// ---------------- // ----------------

View File

@ -245,8 +245,8 @@ int main()
static_assert(sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement"); static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement"); static_assert(sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement"); static_assert(sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement"); static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement"); static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement"); static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
@ -261,8 +261,8 @@ int main()
static_assert(sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement"); static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement"); static_assert(sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement"); static_assert(sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement"); static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement"); static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement"); static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");