diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index f9d65fc4..7b0b4883 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -33,6 +33,9 @@ namespace sqlpp template struct expression_alias_t { + static_assert(is_expression_t::value, "invalid argument for an expression alias"); + static_assert(not is_alias_t::value, "cannot create an alias of an alias"); + struct _value_type: Expression::_value_type { using _is_expression = std::false_type; diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 6bacf054..fbe4a90a 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -35,14 +35,15 @@ namespace sqlpp namespace vendor { template - struct any_t: public boolean::template operators> + struct any_t { static_assert(is_select_t::value, "any() requires a single column select expression as argument"); 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 @@ -90,8 +91,9 @@ namespace sqlpp }; template - auto any(T t) -> typename vendor::any_t::type> + auto any(T t) -> typename vendor::any_t> { + static_assert(is_select_t>::value, "any() requires a select expression as argument"); return { t }; } diff --git a/include/sqlpp11/avg.h b/include/sqlpp11/avg.h index fed9efcb..b174b5b9 100644 --- a/include/sqlpp11/avg.h +++ b/include/sqlpp11/avg.h @@ -34,7 +34,7 @@ namespace sqlpp namespace vendor { template - struct avg_t: public floating_point::template operators> + struct avg_t: public floating_point::template expression_operators> { static_assert(is_noop::value or std::is_same::value, "avg() used with flag other than 'distinct'"); static_assert(is_numeric_t::value, "avg() requires a value expression as argument"); @@ -93,14 +93,16 @@ namespace sqlpp } template - auto avg(T t) -> typename vendor::avg_t::type> + auto avg(T t) -> typename vendor::avg_t> { + static_assert(is_numeric_t>::value, "avg() requires a value expression as argument"); return { t }; } template - auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t::type> + auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t> { + static_assert(is_numeric_t>::value, "avg() requires a value expression as argument"); return { t }; } diff --git a/include/sqlpp11/basic_expression_operators.h b/include/sqlpp11/basic_expression_operators.h new file mode 100644 index 00000000..72954b38 --- /dev/null +++ b/include/sqlpp11/basic_expression_operators.h @@ -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 +#include +#include +#include +#include +#include + +namespace sqlpp +{ + + namespace detail + { + struct boolean; + } + + // basic operators + template class IsCorrectValueType> + struct basic_expression_operators + { + template + struct _is_valid_comparison_operand + { + static constexpr bool value = + (is_expression_t::value // expressions are OK + or is_multi_expression_t::value) // multi-expressions like ANY are OK for comparisons, too + and IsCorrectValueType::value // the correct value type is required, of course + ; + }; + + template + vendor::equal_to_t> operator==(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::not_equal_to_t> operator!=(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::less_than_t> operator<(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::less_equal_t> operator<=(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::greater_than_t> operator>(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::greater_equal_t> operator>=(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + vendor::is_null_t is_null() const + { + return { *static_cast(this) }; + } + + vendor::is_null_t is_not_null() const + { + return { *static_cast(this) }; + } + + sort_order_t asc() + { + return { *static_cast(this) }; + } + + sort_order_t desc() + { + return { *static_cast(this) }; + } + + // Hint: use value_list wrapper for containers... + template + vendor::in_t...> in(T... t) const + { + static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t...>::value, "at least one operand of in() is not valid"); + return { *static_cast(this), vendor::wrap_operand_t{t}... }; + } + + template + vendor::in_t...> not_in(T... t) const + { + static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t...>::value, "at least one operand of in() is not valid"); + return { *static_cast(this), vendor::wrap_operand_t{t}... }; + } + + template + expression_alias_t as(const alias_provider&) + { + return { *static_cast(this) }; + } + }; + +} +#endif diff --git a/include/sqlpp11/basic_operators.h b/include/sqlpp11/basic_operators.h deleted file mode 100644 index b832ffbf..00000000 --- a/include/sqlpp11/basic_operators.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -namespace sqlpp -{ - - namespace detail - { - struct boolean; - } - - // basic operators - template class Constraint> - struct basic_operators - { - template - vendor::equal_to_t::type> operator==(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::not_equal_to_t::type> operator!=(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - template - vendor::less_than_t::type> operator<(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::less_equal_t::type> operator<=(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::greater_than_t::type> operator>(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::greater_equal_t::type> operator>=(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - vendor::is_null_t is_null() const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with is_null()"); - return { *static_cast(this) }; - } - - vendor::is_null_t is_not_null() const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with is_not_null()"); - return { *static_cast(this) }; - } - - sort_order_t asc() - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used for sorting"); - return { *static_cast(this) }; - } - - sort_order_t desc() - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used for sorting"); - return { *static_cast(this) }; - } - - // Hint: use value_list wrapper for containers... - template - vendor::in_t::type...> in(T... t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with in()"); - return { *static_cast(this), {t}... }; - } - - template - vendor::in_t::type...> not_in(T... t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot with be used with not_in()"); - return { *static_cast(this), {t}... }; - } - - template - expression_alias_t as(const alias_provider&) - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot have a name"); - return { *static_cast(this) }; - } - }; - -} -#endif diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index 117d75b9..27f2ed5c 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -175,33 +175,45 @@ namespace sqlpp }; template - using _operand_t = operand_t; - template - using _constraint = is_boolean_t; + struct _is_valid_operand + { + static constexpr bool value = + is_expression_t::value // expressions are OK + and is_boolean_t::value // the correct value type is required, of course + ; + }; template - struct operators: public basic_operators + struct expression_operators: public basic_expression_operators { template - vendor::logical_and_t::type> operator and(T t) const + vendor::logical_and_t> operator and(T t) const { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs operand"); + + return { *static_cast(this), rhs{t} }; } template - vendor::logical_or_t::type> operator or(T t) const + vendor::logical_or_t> operator or(T t) const { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs operand"); + + return { *static_cast(this), rhs{t} }; } vendor::logical_not_t operator not() const { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be as operand for operator not"); return { *static_cast(this) }; } }; + + template + struct column_operators + { + }; }; template diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 208ae1e0..5a3bd98a 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -42,7 +42,8 @@ namespace sqlpp { template - struct column_t: public ColumnSpec::_value_type::template operators> + struct column_t: public ColumnSpec::_value_type::template expression_operators>, + public ColumnSpec::_value_type::template column_operators> { using _is_column = std::true_type; using _spec_t = ColumnSpec; @@ -55,6 +56,8 @@ namespace sqlpp using _is_named_expression = std::true_type; using _is_alias = std::false_type; }; + template + using _is_valid_operand = typename _value_type::template _is_valid_operand; using _name_t = typename ColumnSpec::_name_t; @@ -77,19 +80,12 @@ namespace sqlpp } template - auto operator =(T t) const - -> typename std::enable_if<_value_type::template _constraint::type>::value and not std::is_same::value, - vendor::assignment_t::type>>::type + auto operator =(T t) const -> vendor::assignment_t::type> { - return { *this, {t} }; - } + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs operand assignment operand"); - template - auto operator =(T t) const - -> typename std::enable_if::type>::value and not std::is_same::value), - vendor::assignment_t::type>>::type - { - static_assert(sqlpp::vendor::wrong_t::value, "invalid assignment operand"); + return { *this, {t} }; } auto operator =(sqlpp::null_t) const diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index f6253ebf..3a8de5a9 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -35,10 +35,10 @@ namespace sqlpp namespace vendor { template - struct count_t: public sqlpp::detail::integral::template operators> + struct count_t: public sqlpp::detail::integral::template expression_operators> { static_assert(is_noop::value or std::is_same::value, "count() used with flag other than 'distinct'"); - static_assert(is_value_t::value, "count() requires a sql value as argument"); + static_assert(is_expression_t::value, "count() requires a sql expression as argument"); struct _value_type: public sqlpp::detail::integral { @@ -94,14 +94,16 @@ namespace sqlpp } template - auto count(T t) -> typename vendor::count_t::type> + auto count(T t) -> typename vendor::count_t> { + static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } template - auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t::type> + auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t> { + static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } diff --git a/include/sqlpp11/exists.h b/include/sqlpp11/exists.h index 56fb925b..a63af7f0 100644 --- a/include/sqlpp11/exists.h +++ b/include/sqlpp11/exists.h @@ -34,7 +34,7 @@ namespace sqlpp namespace vendor { template - struct exists_t: public boolean::template operators> + struct exists_t: public boolean::template expression_operators> { static_assert(is_select_t::value, "some() requires a single column select expression as argument"); static_assert(is_value_t