diff --git a/CMakeLists.txt b/CMakeLists.txt index a3d8eeaf..3dd3e7ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,9 +28,9 @@ enable_testing() message(STATUS "Using ${CMAKE_CXX_COMPILER} (compiler id: ${CMAKE_CXX_COMPILER_ID})") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall ${CMAKE_CXX_FLAGS}") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}") endif () set(include_dir "${PROJECT_SOURCE_DIR}/include") diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 39f3bb52..eeb9e2b6 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -28,45 +28,39 @@ #define SQLPP_ALIAS_H #include +#include + namespace sqlpp { template struct expression_alias_t { + using _traits = make_traits, tag::named_expression, tag::alias>; + using _recursive_traits = make_recursive_traits; + 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; - using _is_named_expression = std::true_type; - using _is_alias = std::true_type; - }; - using _name_t = typename AliasProvider::_name_t; - using _table_set = typename Expression::_table_set; Expression _expression; }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = expression_alias_t; + + static Context& _(const T& t, Context& context) { - using T = expression_alias_t; + context << '('; + serialize(t._expression, context); + context << ") AS "; + context << T::_name_t::_get_name(); + return context; + } + }; - static Context& _(const T& t, Context& context) - { - context << '('; - serialize(t._expression, context); - context << ") AS "; - context << T::_name_t::_get_name(); - return context; - } - }; - - } } #endif diff --git a/include/sqlpp11/alias_provider.h b/include/sqlpp11/alias_provider.h index 6949933b..78dcf1e3 100644 --- a/include/sqlpp11/alias_provider.h +++ b/include/sqlpp11/alias_provider.h @@ -31,20 +31,20 @@ #define SQLPP_ALIAS_PROVIDER(name) \ struct name##_t\ +{\ + struct _name_t\ {\ - struct _name_t\ + static constexpr const char* _get_name() { return #name; }\ + template\ + struct _member_t\ {\ - static constexpr const char* _get_name() { return #name; }\ - template\ - struct _member_t\ - {\ - T name;\ - T& operator()() { return name; }\ - const T& operator()() const { return name; }\ - };\ + T name;\ + T& operator()() { return name; }\ + const T& operator()() const { return name; }\ };\ };\ - constexpr name##_t name = {}; +};\ +constexpr name##_t name = {}; namespace sqlpp { diff --git a/include/sqlpp11/all_of.h b/include/sqlpp11/all_of.h index 270dea20..b4d90fae 100644 --- a/include/sqlpp11/all_of.h +++ b/include/sqlpp11/all_of.h @@ -34,36 +34,33 @@ namespace sqlpp { template - struct all_of_t - { - using _column_tuple_t = typename Table::_column_tuple_t; + struct all_of_t + { + using _column_tuple_t = typename Table::_column_tuple_t; - template - detail::copy_tuple_args_t as(const AliasProvider& alias) - { - return ::sqlpp::multi_column(_column_tuple_t{}).as(alias); - } - }; + template + detail::copy_tuple_args_t as(const AliasProvider& alias) + { + return ::sqlpp::multi_column(_column_tuple_t{}).as(alias); + } + }; template - auto all_of(Table t) -> all_of_t - { - return {}; - } + auto all_of(Table t) -> all_of_t
+ { + return {}; + } - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = all_of_t
; + + static Context& _(const T& t, const Context&) { - using T = all_of_t
; - - static Context& _(const T& t, const Context&) - { - static_assert(wrong_t::value, "all_of(table) does not seem to be used in select"); - } - }; - } + static_assert(wrong_t::value, "all_of(table) does not seem to be used in select"); + } + }; } diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 1f8a55b5..a193b825 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -32,16 +32,11 @@ namespace sqlpp { - namespace vendor - { - template + template struct any_t { - struct _value_type: public Select::_value_type::_base_value_type - { - using _is_expression = std::false_type; - using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc - }; + using _traits = make_traits, ::sqlpp::tag::multi_expression>; + using _recursive_traits = make_recursive_traits; + + static Context& _(const T& t, Context& context) { - using T = vendor::any_t
; + using _extra_tables = detail::type_set<>; + }; + using _spec_t = ColumnSpec; using _table = Table; - using _table_set = detail::type_set<_table>; - using _column_type = typename ColumnSpec::_column_type; - struct _value_type: ColumnSpec::_value_type - { - using _is_expression = std::true_type; - 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 _column_type = typename _spec_t::_column_type; + using _name_t = typename _spec_t::_name_t; - using _name_t = typename ColumnSpec::_name_t; + template + using _is_valid_operand = typename ColumnSpec::_value_type::template _is_valid_operand; column_t() = default; column_t(const column_t&) = default; @@ -80,43 +81,40 @@ namespace sqlpp } template - auto operator =(T t) const -> vendor::assignment_t::type> + auto operator =(T t) const -> assignment_t> { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand assignment operand"); - return { *this, {t} }; + return { *this, rhs{t} }; } auto operator =(sqlpp::null_t) const - ->vendor::assignment_t + ->assignment_t { static_assert(can_be_null_t::value, "column cannot be null"); return { *this, {} }; } auto operator =(sqlpp::default_value_t) const - ->vendor::assignment_t + ->assignment_t { return { *this, {} }; } }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = column_t; + + static Context& _(const T& t, Context& context) { - using T = column_t; + context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name(); + return context; + } + }; - static Context& _(const T& t, Context& context) - { - context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name(); - return context; - } - }; - - } } #endif diff --git a/include/sqlpp11/column_fwd.h b/include/sqlpp11/column_fwd.h index d378aa6a..634bbe0b 100644 --- a/include/sqlpp11/column_fwd.h +++ b/include/sqlpp11/column_fwd.h @@ -31,7 +31,7 @@ namespace sqlpp { template - class column_t; + struct column_t; } #endif diff --git a/include/sqlpp11/vendor/concat.h b/include/sqlpp11/concat.h similarity index 50% rename from include/sqlpp11/vendor/concat.h rename to include/sqlpp11/concat.h index 332c17fc..2670f64f 100644 --- a/include/sqlpp11/vendor/concat.h +++ b/include/sqlpp11/concat.h @@ -28,62 +28,58 @@ #define SQLPP_CONCAT_H #include -#include +#include +#include #include namespace sqlpp { - namespace vendor + // FIXME: Remove First, inherit from text_t + template + struct concat_t: public value_type_of::template expression_operators>, + public alias_operators> { - template - struct concat_t: public First::_value_type::template expression_operators> + using _traits = make_traits, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; + using _recursive_traits = make_recursive_traits; + + static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); + static_assert(sqlpp::detail::all_t::value, is_text_t::value...>::value, "at least one non-text argument detected in concat()"); + struct _name_t { - static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); - static_assert(sqlpp::detail::all_t::value, is_text_t::value...>::value, "at least one non-text argument detected in concat()"); - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - struct _value_type: public First::_value_type::_base_value_type - { - using _is_named_expression = std::true_type; - }; - - struct _name_t - { - static constexpr const char* _get_name() { return "CONCAT"; } - template - struct _member_t - { - T concat; - }; - }; - - concat_t(First first, Args... args): - _args(first, args...) - {} - - concat_t(const concat_t&) = default; - concat_t(concat_t&&) = default; - concat_t& operator=(const concat_t&) = default; - concat_t& operator=(concat_t&&) = default; - ~concat_t() = default; - - std::tuple _args; + static constexpr const char* _get_name() { return "CONCAT"; } + template + struct _member_t + { + T concat; + }; }; - template - struct serializer_t> - { - using T = concat_t; + concat_t(First first, Args... args): + _args(first, args...) + {} - static Context& _(const T& t, Context& context) - { - context << "("; - interpret_tuple(t._args, "||", context); - context << ")"; - return context; - } - }; - } + concat_t(const concat_t&) = default; + concat_t(concat_t&&) = default; + concat_t& operator=(const concat_t&) = default; + concat_t& operator=(concat_t&&) = default; + ~concat_t() = default; + + std::tuple _args; + }; + + template + struct serializer_t> + { + using T = concat_t; + + static Context& _(const T& t, Context& context) + { + context << "("; + interpret_tuple(t._args, "||", context); + context << ")"; + return context; + } + }; } #endif diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index dc54437f..af24e47b 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -32,80 +32,71 @@ namespace sqlpp { - namespace vendor + template + struct count_t: public sqlpp::detail::integral::template expression_operators>, + public alias_operators> { - template - struct count_t: public sqlpp::detail::integral::template expression_operators> + using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; + using _recursive_traits = make_recursive_traits; + + static_assert(is_noop::value or std::is_same::value, "count() used with flag other than 'distinct'"); + static_assert(is_expression_t::value, "count() requires a sql expression as argument"); + + struct _name_t { - static_assert(is_noop::value or std::is_same::value, "count() used with flag other than 'distinct'"); - static_assert(is_expression_t::value, "count() requires a sql expression as argument"); - - struct _value_type: public sqlpp::detail::integral - { - using _is_named_expression = std::true_type; - }; - - using _table_set = typename Expr::_table_set; - - struct _name_t - { - static constexpr const char* _get_name() { return "COUNT"; } - template - struct _member_t - { - T count; - T& operator()() { return count; } - const T& operator()() const { return count; } - }; - }; - - count_t(const Expr expr): - _expr(expr) - {} - - count_t(const count_t&) = default; - count_t(count_t&&) = default; - count_t& operator=(const count_t&) = default; - count_t& operator=(count_t&&) = default; - ~count_t() = default; - - Expr _expr; - }; - } - - namespace vendor - { - template - struct serializer_t> - { - using T = vendor::count_t; - - static Context& _(const T& t, Context& context) + static constexpr const char* _get_name() { return "COUNT"; } + template + struct _member_t { - context << "COUNT("; - if (std::is_same::value) - { - serialize(Flag(), context); - context << ' '; - } - serialize(t._expr, context); - context << ")"; - return context; + T count; + T& operator()() { return count; } + const T& operator()() const { return count; } + }; + }; + + count_t(const Expr expr): + _expr(expr) + {} + + count_t(const count_t&) = default; + count_t(count_t&&) = default; + count_t& operator=(const count_t&) = default; + count_t& operator=(count_t&&) = default; + ~count_t() = default; + + Expr _expr; + }; + + template + struct serializer_t> + { + using T = count_t; + + static Context& _(const T& t, Context& context) + { + context << "COUNT("; + if (std::is_same::value) + { + serialize(Flag(), context); + context << ' '; } - }; - } + serialize(t._expr, context); + context << ")"; + return context; + } + }; template - auto count(T t) -> typename vendor::count_t> + auto count(T t) -> count_t> { - static_assert(is_expression_t>::value, "count() requires an expression as argument"); + 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> + auto count(const sqlpp::distinct_t&, T t) -> count_t> { - static_assert(is_expression_t>::value, "count() requires an expression as argument"); + static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } diff --git a/include/sqlpp11/default_value.h b/include/sqlpp11/default_value.h index 10dde6f1..bb8fce6d 100644 --- a/include/sqlpp11/default_value.h +++ b/include/sqlpp11/default_value.h @@ -33,27 +33,23 @@ namespace sqlpp { struct default_value_t { - static constexpr bool _is_expression = true; - using _value_type = no_value_t; - using _table_set = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; static constexpr bool _is_trivial() { return false; } }; - namespace vendor - { - template - struct serializer_t - { - using Operand = default_value_t; + template + struct serializer_t + { + using Operand = default_value_t; - static Context& _(const Operand& t, Context& context) - { - context << "DEFAULT"; - return context; - } - }; - } + static Context& _(const Operand& t, Context& context) + { + context << "DEFAULT"; + return context; + } + }; constexpr default_value_t default_value = {}; diff --git a/include/sqlpp11/detail/column_index_sequence.h b/include/sqlpp11/detail/column_index_sequence.h index 277e85e2..be5a2c49 100644 --- a/include/sqlpp11/detail/column_index_sequence.h +++ b/include/sqlpp11/detail/column_index_sequence.h @@ -49,7 +49,7 @@ namespace sqlpp }; template - struct make_column_index_sequence_impl, vendor::multi_field_t, Rest...> + struct make_column_index_sequence_impl, multi_field_t, Rest...> { using type = typename make_column_index_sequence_impl, Rest...>::type; }; diff --git a/include/sqlpp11/detail/copy_tuple_args.h b/include/sqlpp11/detail/copy_tuple_args.h index 0891e6ac..3496a2be 100644 --- a/include/sqlpp11/detail/copy_tuple_args.h +++ b/include/sqlpp11/detail/copy_tuple_args.h @@ -57,7 +57,7 @@ namespace sqlpp template class Target, typename First, typename T> struct copy_tuple_args_impl { - static_assert(vendor::wrong_t::value, "copy_tuple_args must be called with a tuple"); + static_assert(wrong_t::value, "copy_tuple_args must be called with a tuple"); }; template class Target, typename First, typename... Args> diff --git a/include/sqlpp11/detail/get_last.h b/include/sqlpp11/detail/get_last.h new file mode 100644 index 00000000..02bacd4b --- /dev/null +++ b/include/sqlpp11/detail/get_last.h @@ -0,0 +1,60 @@ +/* + * 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_DETAIL_GET_LAST_H +#define SQLPP_DETAIL_GET_LAST_H + +#include + +namespace sqlpp +{ + namespace detail + { + template class Predicate, typename Default, typename... T> + struct get_last_if_impl; + + template class Predicate, typename Default> + struct get_last_if_impl + { + using type = Default; + }; + + template class Predicate, typename Default, typename T, typename... Rest> + struct get_last_if_impl + { + using rest = typename get_last_if_impl::type; + using type = typename std::conditional::value and Predicate::value, + T, + rest>::type; + }; + + template class Predicate, typename Default, typename... T> + using get_last_if = typename get_last_if_impl::type; + } +} + + +#endif diff --git a/include/sqlpp11/vendor/policy_update.h b/include/sqlpp11/detail/pick_arg.h similarity index 62% rename from include/sqlpp11/vendor/policy_update.h rename to include/sqlpp11/detail/pick_arg.h index a65c332b..10cd512b 100644 --- a/include/sqlpp11/vendor/policy_update.h +++ b/include/sqlpp11/detail/pick_arg.h @@ -24,36 +24,35 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_VENDOR_POLICY_UPDATE_H -#define SQLPP_VENDOR_POLICY_UPDATE_H +#ifndef SQLPP_DETAIL_PICK_ARG_H +#define SQLPP_DETAIL_PICK_ARG_H -#include +#include namespace sqlpp { - namespace vendor + namespace detail { - template - struct policy_update_impl + template + typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::true_type&) { - template - using _policy_t = typename std::conditional::value, Replacement, T>::type; + return term; }; - template - using policy_update_t = typename policy_update_impl::template _policy_t; - - template - struct update_policies_impl + template + typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::false_type&) { - using type = typename Original::template _policy_update_t; + return Target::_get_member(statement)._data; }; - template - using update_policies_t = typename update_policies_impl::type; - + // Returns a statement's term either by picking the term from the statement or using the new term + template + typename Target::_data_t pick_arg(Statement statement, Term term) + { + return pick_arg_impl(statement, term, std::is_same()); + }; } - } + #endif diff --git a/include/sqlpp11/detail/arg_selector.h b/include/sqlpp11/detail/sum.h similarity index 74% rename from include/sqlpp11/detail/arg_selector.h rename to include/sqlpp11/detail/sum.h index e2922920..9296b498 100644 --- a/include/sqlpp11/detail/arg_selector.h +++ b/include/sqlpp11/detail/sum.h @@ -24,26 +24,39 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_DETAIL_ARG_SELECTOR_H -#define SQLPP_DETAIL_ARG_SELECTOR_H +#ifndef SQLPP_DETAIL_SUM_H +#define SQLPP_DETAIL_SUM_H namespace sqlpp { namespace detail { - template - struct arg_selector + + /** a non-recursive C++14 version + template + constexpr std::size_t sum(Args... args) { - static Target _(Target, Target t) { return t; } + std::size_t result = 0; - template - static Target _(X, Target t) { return t; } + using swallow = int[]; + (void) swallow{(result += args, 0)...}; - template - static Target _(Target t, X) { return t; } - }; + return result; + } + */ + + constexpr std::size_t sum() + { + return 0; + } + + template + constexpr std::size_t sum(Arg arg, Rest... rest) + { + return arg + sum(rest...); + } } } - #endif + diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index 64a2b005..a46ffb9b 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include namespace sqlpp @@ -73,7 +73,7 @@ namespace sqlpp template struct is_element_of { - static_assert(::sqlpp::vendor::wrong_t::value, "SET has to be a type set"); + static_assert(::sqlpp::wrong_t::value, "SET has to be a type set"); }; template @@ -85,7 +85,7 @@ namespace sqlpp template struct joined_set { - static_assert(::sqlpp::vendor::wrong_t::value, "L and R have to be type sets"); + static_assert(::sqlpp::wrong_t::value, "L and R have to be type sets"); }; template @@ -100,7 +100,7 @@ namespace sqlpp template struct is_superset_of { - static_assert(::sqlpp::vendor::wrong_t::value, "L and R have to be type sets"); + static_assert(::sqlpp::wrong_t::value, "L and R have to be type sets"); }; template @@ -118,7 +118,7 @@ namespace sqlpp template struct is_disjunct_from { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for is_disjunct_from"); + static_assert(::sqlpp::wrong_t::value, "invalid argument for is_disjunct_from"); }; template @@ -157,6 +157,9 @@ namespace sqlpp using type = typename make_type_set_if::type::template insert_if::type; }; + template class Predicate, typename... T> + using make_type_set_if_t = typename make_type_set_if::type; + template class Predicate, typename... T> struct make_type_set_if_not { @@ -171,7 +174,7 @@ namespace sqlpp template struct make_joined_set { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for joined set"); + static_assert(::sqlpp::wrong_t::value, "invalid argument for joined set"); }; template<> @@ -194,7 +197,7 @@ namespace sqlpp template struct make_difference_set { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for difference set"); + static_assert(::sqlpp::wrong_t::value, "invalid argument for difference set"); }; template @@ -208,6 +211,24 @@ namespace sqlpp template using make_difference_set_t = typename make_difference_set::type; + + template class Transformation, typename T> + struct transform_set + { + static_assert(::sqlpp::wrong_t::value, "invalid argument for transform_set"); + }; + + template class Transformation, typename... E> + struct transform_set> + { + using type = typename make_type_set...>::type; + }; + + template class Transformation, typename T> + using transform_set_t = typename transform_set::type; + + + } } diff --git a/include/sqlpp11/exists.h b/include/sqlpp11/exists.h index ac69461e..54f28208 100644 --- a/include/sqlpp11/exists.h +++ b/include/sqlpp11/exists.h @@ -31,68 +31,59 @@ namespace sqlpp { - namespace vendor + template + struct exists_t: public boolean::template expression_operators>, + public alias_operators> { - template - struct exists_t: public boolean::template expression_operators> + using _traits = make_traits; + using _recursive_traits = make_recursive_traits::value, "exists() requires a select expression as argument"); + + struct _name_t { - static_assert(is_select_t; - - static Context& _(const T& t, Context& context) + static constexpr const char* _get_name() { return "EXISTS"; } + template + struct _member_t { - context << "EXISTS("; - serialize(t._select, context); - context << ")"; - return context; - } - }; - } + T exists; + T& operator()() { return exists; } + const T& operator()() const { return exists; } + }; + }; + + exists_t(Select select): + _select(select) + {} + + exists_t(const exists_t&) = default; + exists_t(exists_t&&) = default; + exists_t& operator=(const exists_t&) = default; + exists_t& operator=(exists_t&&) = default; + ~exists_t() = default; + + Select _select; + }; + + template + struct serializer_t> + { + using T = exists_t
::value, "invalid table argument in from::add()"); + using _known_tables = detail::make_joined_set_t...>; // Hint: Joins contain more than one table + using _known_table_names = detail::transform_set_t; + static_assert(not detail::is_element_of::value, "Must not use the same table name twice in from()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t
::value>; + + _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Table table, const std::true_type&) + { + return _data._dynamic_tables.emplace_back(table); + } + + template + void _add_impl(Table table, const std::false_type&); + + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = from_data_t; + + _impl_t from; + _impl_t& operator()() { return from; } + const _impl_t& operator()() const { return from; } + + template + static auto _get_member(T t) -> decltype(t.from) + { + return t.from; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + struct no_from_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_from; + _impl_t& operator()() { return no_from; } + const _impl_t& operator()() const { return no_from; } + + template + static auto _get_member(T t) -> decltype(t.no_from) + { + return t.no_from; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto from(Tables... tables) + -> _new_statement_t> + { + static_assert(sizeof...(Tables), "at least one table or join argument required in from()"); + return _from_impl(tables...); + } + + template + auto dynamic_from(Tables... tables) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); + return _from_impl<_database_t>(tables...); + } + + private: + template + auto _from_impl(Tables... tables) + -> _new_statement_t> + { + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a table or join in from()"); + static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table"); + + static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of::size::value...); + using _unique_tables = detail::make_joined_set_t...>; + using _unique_table_names = detail::transform_set_t; + static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()"); + static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()"); + + return { *static_cast(this), from_data_t{tables...} }; + } + + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = from_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Tables) == 0 and t._dynamic_tables.empty()) + return context; + context << " FROM "; + interpret_tuple(t._tables, ',', context); + if (sizeof...(Tables) and not t._dynamic_tables.empty()) + context << ','; + interpret_list(t._dynamic_tables, ',', context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 6e85caaf..65c05a2e 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -30,9 +30,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -46,18 +46,18 @@ namespace sqlpp { template - auto value(T t) -> vendor::wrap_operand_t + auto value(T t) -> wrap_operand_t { - using _table_set = ::sqlpp::detail::type_set<>; - static_assert(not is_value_t::value, "value() is to be called with non-sql-type like int, or string"); + static_assert(is_wrapped_value_t>::value, "value() is to be called with non-sql-type like int, or string"); return { t }; } template // Csaba Csoma suggests: unsafe_sql instead of verbatim - struct verbatim_t: public ValueType::template expression_operators> + struct verbatim_t: public ValueType::template expression_operators>, + public alias_operators> { - using _value_type = ValueType; - using _table_set = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(const verbatim_t&) = default; @@ -69,20 +69,17 @@ namespace sqlpp std::string _verbatim; }; - namespace vendor - { - template - struct serializer_t> - { - using T = verbatim_t; + template + struct serializer_t> + { + using T = verbatim_t; - static Context& _(const T& t, Context& context) - { - context << t._verbatim; - return context; - } - }; - } + static Context& _(const T& t, Context& context) + { + context << t._verbatim; + return context; + } + }; template auto verbatim(StringType s) -> verbatim_t @@ -91,7 +88,7 @@ namespace sqlpp } template - auto flatten(const Expression& exp, const Context& context) -> verbatim_t + auto flatten(const Expression& exp, const Context& context) -> verbatim_t> { static_assert(not make_parameter_list_t::type::size::value, "parameters not supported in flattened expressions"); context.clear(); @@ -102,9 +99,10 @@ namespace sqlpp template struct value_list_t // to be used in .in() method { + using _traits = make_traits, ::sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits<>; + using _container_t = Container; - using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else? - using _value_type = vendor::value_type_t; value_list_t(_container_t container): _container(container) @@ -119,34 +117,31 @@ namespace sqlpp _container_t _container; }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = value_list_t; + + static Context& _(const T& t, Context& context) { - using T = value_list_t; - - static Context& _(const T& t, Context& context) + bool first = true; + for (const auto& entry: t._container) { - bool first = true; - for (const auto& entry: t._container) - { - if (first) - first = false; - else - context << ','; + if (first) + first = false; + else + context << ','; - serialize(value(entry), context); - } - return context; + serialize(value(entry), context); } - }; - } + return context; + } + }; template auto value_list(Container c) -> value_list_t { - static_assert(not is_value_t::value, "value_list() is to be called with a container of non-sql-type like std::vector, or std::list(string)"); + static_assert(is_wrapped_value_t>::value, "value_list() is to be called with a container of non-sql-type like std::vector, or std::list(string)"); return { c }; } diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h new file mode 100644 index 00000000..6aa72724 --- /dev/null +++ b/include/sqlpp11/group_by.h @@ -0,0 +1,214 @@ +/* + * 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_GROUP_BY_H +#define SQLPP_GROUP_BY_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // GROUP BY DATA + template + struct group_by_data_t + { + group_by_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + group_by_data_t(const group_by_data_t&) = default; + group_by_data_t(group_by_data_t&&) = default; + group_by_data_t& operator=(const group_by_data_t&) = default; + group_by_data_t& operator=(group_by_data_t&&) = default; + ~group_by_data_t() = default; + + std::tuple _expressions; + interpretable_list_t _dynamic_expressions; + }; + + // GROUP BY + template + struct group_by_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; + + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); + + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in group_by()"); + + // Data + using _data_t = group_by_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Expression expression) + { + add(expression); + } + + template + void add(Expression expression) + { + static_assert(_is_dynamic::value, "add() must not be called for static group_by"); + static_assert(is_expression_t::value, "invalid expression argument in group_by::add()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in group_by::add()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; + + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Expression expression, const std::true_type&) + { + return _data._dynamic_expressions.emplace_back(expression); + } + + template + void _add_impl(Expression expression, const std::false_type&); + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = group_by_data_t; + + _impl_t group_by; + _impl_t& operator()() { return group_by; } + const _impl_t& operator()() const { return group_by; } + + template + static auto _get_member(T t) -> decltype(t.group_by) + { + return t.group_by; + } + }; + + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // NO GROUP BY YET + struct no_group_by_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_group_by; + _impl_t& operator()() { return no_group_by; } + const _impl_t& operator()() const { return no_group_by; } + + template + static auto _get_member(T t) -> decltype(t.no_group_by) + { + return t.no_group_by; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto group_by(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), group_by_data_t{args...} }; + } + + template + auto dynamic_group_by(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); + return { *static_cast(this), group_by_data_t<_database_t, Args...>{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = group_by_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) + return context; + context << " GROUP BY "; + interpret_tuple(t._expressions, ',', context); + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) + context << ','; + interpret_list(t._dynamic_expressions, ',', context); + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h new file mode 100644 index 00000000..7eceee0c --- /dev/null +++ b/include/sqlpp11/having.h @@ -0,0 +1,212 @@ +/* + * 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_HAVING_H +#define SQLPP_HAVING_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // HAVING DATA + template + struct having_data_t + { + having_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + having_data_t(const having_data_t&) = default; + having_data_t(having_data_t&&) = default; + having_data_t& operator=(const having_data_t&) = default; + having_data_t& operator=(having_data_t&&) = default; + ~having_data_t() = default; + + std::tuple _expressions; + interpretable_list_t _dynamic_expressions; + }; + + // HAVING + template + struct having_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; + + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in having()"); + + // Data + using _data_t = having_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Expression expression) + { + add(expression); + } + + template + void add(Expression expression) + { + static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having"); + static_assert(is_expression_t::value, "invalid expression argument in having::add()"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in having::add()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; + + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Expression expression, const std::true_type&) + { + return _data._dynamic_expressions.emplace_back(expression); + } + + template + void _add_impl(Expression expression, const std::false_type&); + + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = having_data_t; + + _impl_t having; + _impl_t& operator()() { return having; } + const _impl_t& operator()() const { return having; } + + template + static auto _get_member(T t) -> decltype(t.having) + { + return t.having; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // NO HAVING YET + struct no_having_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_having; + _impl_t& operator()() { return no_having; } + const _impl_t& operator()() const { return no_having; } + + template + static auto _get_member(T t) -> decltype(t.no_having) + { + return t.no_having; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto having(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), having_data_t{args...} }; + } + + template + auto dynamic_having(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); + return { *static_cast(this), having_data_t<_database_t, Args...>{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = having_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) + return context; + context << " HAVING "; + interpret_tuple(t._expressions, " AND ", context); + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) + context << " AND "; + interpret_list(t._dynamic_expressions, " AND ", context); + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/vendor/in.h b/include/sqlpp11/in.h similarity index 50% rename from include/sqlpp11/vendor/in.h rename to include/sqlpp11/in.h index 1979264b..5ec661b4 100644 --- a/include/sqlpp11/vendor/in.h +++ b/include/sqlpp11/in.h @@ -29,65 +29,60 @@ #include #include -#include +#include #include namespace sqlpp { - namespace vendor + template + struct in_t: public boolean::template expression_operators>, + public alias_operators> { - template - struct in_t: public boolean::template expression_operators> + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + static constexpr bool _inverted = not NotInverted; + static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); + + struct _name_t { - static constexpr bool _inverted = not NotInverted; - static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); - - struct _value_type: public boolean - { - using _is_named_expression = std::true_type; - }; - - struct _name_t - { - static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; } - template - struct _member_t - { - T in; - }; - }; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - in_t(Operand operand, Args... args): - _operand(operand), - _args(args...) - {} - - in_t(const in_t&) = default; - in_t(in_t&&) = default; - in_t& operator=(const in_t&) = default; - in_t& operator=(in_t&&) = default; - ~in_t() = default; - - Operand _operand; - std::tuple _args; + static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; } + template + struct _member_t + { + T in; + }; }; - template - struct serializer_t> - { - using T = vendor::in_t; + in_t(Operand operand, Args... args): + _operand(operand), + _args(args...) + {} - static Context& _(const T& t, Context& context) - { - serialize(t._operand, context); - context << (t._inverted ? " NOT IN(" : " IN("); - interpret_tuple(t._args, ',', context); - context << ')'; - return context; - } - }; - } + in_t(const in_t&) = default; + in_t(in_t&&) = default; + in_t& operator=(const in_t&) = default; + in_t& operator=(in_t&&) = default; + ~in_t() = default; + + Operand _operand; + std::tuple _args; + }; + + template + struct serializer_t> + { + using T = in_t; + + static Context& _(const T& t, Context& context) + { + serialize(t._operand, context); + context << (t._inverted ? " NOT IN(" : " IN("); + interpret_tuple(t._args, ',', context); + context << ')'; + return context; + } + }; } diff --git a/include/sqlpp11/vendor/in_fwd.h b/include/sqlpp11/in_fwd.h similarity index 94% rename from include/sqlpp11/vendor/in_fwd.h rename to include/sqlpp11/in_fwd.h index 809c4cc2..3b464307 100644 --- a/include/sqlpp11/vendor/in_fwd.h +++ b/include/sqlpp11/in_fwd.h @@ -29,11 +29,8 @@ namespace sqlpp { - namespace vendor - { - template + template struct in_t; - } } diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index c24f236f..b6ca7ff2 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -27,172 +27,99 @@ #ifndef SQLPP_INSERT_H #define SQLPP_INSERT_H +#include #include #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include namespace sqlpp { - template - struct insert_t; + struct insert_name_t {}; - namespace detail + struct insert_t: public statement_name_t { - template - struct insert_policies_t + using _traits = make_traits; + struct _name_t {}; + + template + struct _result_methods_t { - using _database_t = Db; - using _table_t = Table; - using _insert_value_list_t = InsertValueList; + using _statement_t = typename Policies::_statement_t; - using _statement_t = insert_t; + const _statement_t& _get_statement() const + { + return static_cast(*this); + } - struct _methods_t: - public _insert_value_list_t::template _methods_t - {}; - - template - struct _policies_insert_t + template + auto _run(Db& db) const -> decltype(db.insert(this->_get_statement())) { - using type = insert_t...>; - }; + _statement_t::_check_consistency(); - template - using _new_statement_t = typename _policies_insert_t::type; + static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); + return db.insert(_get_statement()); + } - using _table_set = typename _table_t::_table_set; + template + auto _prepare(Db& db) const + -> prepared_insert_t + { + _statement_t::_check_consistency(); - using _known_tables = detail::make_joined_set_t; - - template - using _no_unknown_tables = detail::is_subset_of; + return {{}, db.prepare_insert(_get_statement())}; + } }; - } + }; - // INSERT - template - struct insert_t: - public detail::insert_policies_t::_methods_t + template + struct serializer_t { - using _policies_t = typename detail::insert_policies_t; - using _database_t = typename _policies_t::_database_t; - using _table_t = typename _policies_t::_table_t; - using _insert_value_list_t = typename _policies_t::_insert_value_list_t; + using T = insert_name_t; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - - using _parameter_tuple_t = std::tuple; - using _parameter_list_t = typename make_parameter_list_t::type; - - static_assert(::sqlpp::detail::is_superset_of::value, "columns do not match the table they are to be inserted into"); - - // Constructors - insert_t() - {} - - template - insert_t(Statement s, T t): - _table(detail::arg_selector<_table_t>::_(s._table, t)), - _insert_value_list(detail::arg_selector<_insert_value_list_t>::_(s._insert_value_list, t)) - {} - - insert_t(const insert_t&) = default; - insert_t(insert_t&&) = default; - insert_t& operator=(const insert_t&) = default; - insert_t& operator=(insert_t&&) = default; - ~insert_t() = default; - - // run and prepare - static constexpr size_t _get_static_no_of_parameters() + static Context& _(const T& t, Context& context) { - return _parameter_list_t::size::value; + context << "INSERT "; + + return context; } - - size_t _get_no_of_parameters() const - { - return _parameter_list_t::size::value; - } - - template - struct is_table_subset_of_table - { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; - }; - - void _check_consistency() const - { - // FIXME: Read up on what is allowed/prohibited in INSERT - } - - template - std::size_t _run(Database& db) const - { - _check_consistency(); - - static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); - return db.insert(*this); - } - - template - auto _prepare(Database& db) const - -> prepared_insert_t - { - _check_consistency(); - - return {{}, db.prepare_insert(*this)}; - } - - _insert_value_list_t _insert_value_list; - _table_t _table; }; - namespace vendor - { - template - struct serializer_t> - { - using T = insert_t; + template + using blank_insert_t = statement_t; - static Context& _(const T& t, Context& context) - { - context << "INSERT INTO "; - serialize(t._table, context); - serialize(t._insert_value_list, context); - return context; - } - }; - } - - template - using make_insert_t = typename detail::insert_policies_t::_statement_t; + auto insert() + -> blank_insert_t + { + return { blank_insert_t() }; + } template constexpr auto insert_into(Table table) - -> make_insert_t> + -> decltype(blank_insert_t().into(table)) { - return { make_insert_t(), vendor::single_table_t{table} }; + return { blank_insert_t().into(table) }; + } + + template + constexpr auto dynamic_insert(const Database&) + -> decltype(blank_insert_t()) + { + return { blank_insert_t() }; } template constexpr auto dynamic_insert_into(const Database&, Table table) - -> make_insert_t> + -> decltype(blank_insert_t().into(table)) { - return { make_insert_t(), vendor::single_table_t{table} }; + return { blank_insert_t().into(table) }; } - } #endif diff --git a/include/sqlpp11/insert_value.h b/include/sqlpp11/insert_value.h new file mode 100644 index 00000000..1be64b10 --- /dev/null +++ b/include/sqlpp11/insert_value.h @@ -0,0 +1,121 @@ +/* + * 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_INSERT_VALUE_H +#define SQLPP_INSERT_VALUE_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + namespace detail + { + template + struct type_if + { + using type = Type; + }; + + template + struct type_if + { + struct type + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + }; + }; + } + + template + struct insert_value_t + { + using _is_insert_value = std::true_type; + using _pure_value_t = typename value_type_of::_cpp_value_type; + using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type; + using _tvin_t = typename detail::type_if, can_be_null_t::value>::type; // static asserts and SFINAE do not work together + using _null_t = typename detail::type_if::value>::type; // static asserts and SFINAE do not work together + + insert_value_t(assignment_t assignment): + _is_null(false), + _is_default(false), + _value(assignment._rhs) + {} + + insert_value_t(assignment_t assignment): + _is_null(assignment._rhs._is_trivial()), + _is_default(false), + _value(assignment._rhs._value) + {} + + insert_value_t(const assignment_t&): + _is_null(true), + _is_default(false), + _value() + {} + + insert_value_t(const assignment_t&): + _is_null(false), + _is_default(true), + _value() + {} + + insert_value_t(const insert_value_t&) = default; + insert_value_t(insert_value_t&&) = default; + insert_value_t& operator=(const insert_value_t&) = default; + insert_value_t& operator=(insert_value_t&&) = default; + ~insert_value_t() = default; + + bool _is_null; + bool _is_default; + _wrapped_value_t _value; + }; + + template + struct serializer_t> + { + using T = insert_value_t; + + static Context& _(const T& t, Context& context) + { + if (t._is_null) + context << "NULL"; + else if (t._is_default) + context << "DEFAULT"; + else + serialize(t._value, context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/insert_value_list.h b/include/sqlpp11/insert_value_list.h new file mode 100644 index 00000000..513085d5 --- /dev/null +++ b/include/sqlpp11/insert_value_list.h @@ -0,0 +1,443 @@ +/* + * 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_INSERT_VALUE_LIST_H +#define SQLPP_INSERT_VALUE_LIST_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + struct insert_default_values_data_t + {}; + + // COLUMN AND VALUE LIST + struct insert_default_values_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = insert_default_values_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = insert_default_values_data_t; + + _impl_t default_values; + _impl_t& operator()() { return default_values; } + const _impl_t& operator()() const { return default_values; } + + template + static auto _get_member(T t) -> decltype(t.default_values) + { + return t.default_values; + } + }; + + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + template + struct insert_list_data_t + { + insert_list_data_t(Assignments... assignments): + _assignments(assignments...), + _columns({assignments._lhs}...), + _values(assignments._rhs...) + {} + + insert_list_data_t(const insert_list_data_t&) = default; + insert_list_data_t(insert_list_data_t&&) = default; + insert_list_data_t& operator=(const insert_list_data_t&) = default; + insert_list_data_t& operator=(insert_list_data_t&&) = default; + ~insert_list_data_t() = default; + + std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) + std::tuple...> _columns; + std::tuple _values; + interpretable_list_t _dynamic_columns; + interpretable_list_t _dynamic_values; + }; + + template + struct insert_list_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; + + template class Target> + using copy_assignments_t = Target; // FIXME: Nice idea to copy variadic template arguments? + template class Target, template class Wrap> + using copy_wrapped_assignments_t = Target...>; + + // Data + using _data_t = insert_list_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Assignment assignment) + { + add(assignment); + } + + template + void add(Assignment assignment) + { + static_assert(_is_dynamic::value, "add must not be called for static from()"); + static_assert(is_assignment_t::value, "add() arguments require to be assigments"); + using _assigned_columns = detail::make_type_set_t; + static_assert(not detail::is_element_of::value, "Must not assign value to column twice"); + static_assert(not must_not_insert_t::value, "add() argument must not be used in insert"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "add() contains a column from a foreign table"); + + using ok = ::sqlpp::detail::all_t< + _is_dynamic::value, + is_assignment_t::value>; + + _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Assignment assignment, const std::true_type&) + { + _data._dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); + _data._dynamic_values.emplace_back(assignment._rhs); + } + + template + void _add_impl(Assignment assignment, const std::false_type&); + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = insert_list_data_t; + + _impl_t insert_list; + _impl_t& operator()() { return insert_list; } + const _impl_t& operator()() const { return insert_list; } + + template + static auto _get_member(T t) -> decltype(t.insert_list) + { + return t.insert_list; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + + }; + + template + struct column_list_data_t + { + column_list_data_t(Columns... columns): + _columns(simple_column_t{columns}...) + {} + + column_list_data_t(const column_list_data_t&) = default; + column_list_data_t(column_list_data_t&&) = default; + column_list_data_t& operator=(const column_list_data_t&) = default; + column_list_data_t& operator=(column_list_data_t&&) = default; + ~column_list_data_t() = default; + + using _value_tuple_t = std::tuple...>; + std::tuple...> _columns; + std::vector<_value_tuple_t> _insert_values; + }; + + template + struct column_list_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + static_assert(sizeof...(Columns), "at least one column required in columns()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); + + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a column in columns()"); + + static_assert(::sqlpp::detail::none_t::value...>::value, "at least one column argument has a must_not_insert flag in its definition"); + + using _value_tuple_t = typename column_list_data_t::_value_tuple_t; + + static_assert(required_tables_of::size::value == 1, "columns from multiple tables in columns()"); + + // Data + using _data_t = column_list_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add(Assignments... assignments) + { + static_assert(::sqlpp::detail::all_t::value...>::value, "add_values() arguments have to be assignments"); + using _arg_value_tuple = std::tuple...>; + 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"); + + using ok = ::sqlpp::detail::all_t< + ::sqlpp::detail::all_t::value...>::value, + _args_correct::value>; + + _add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(const std::true_type&, Assignments... assignments) + { + return _data._insert_values.emplace_back(insert_value_t{assignments}...); + } + + template + void _add_impl(const std::false_type&, Assignments... assignments); + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = column_list_data_t; + + _impl_t values; + _impl_t& operator()() { return values; } + const _impl_t& operator()() const { return values; } + + template + static auto _get_member(T t) -> decltype(t.values) + { + return t.values; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // NO INSERT COLUMNS/VALUES YET + struct no_insert_value_list_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_insert_values; + _impl_t& operator()() { return no_insert_values; } + const _impl_t& operator()() const { return no_insert_values; } + + template + static auto _get_member(T t) -> decltype(t.no_insert_values) + { + return t.no_insert_values; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + auto default_values() + -> _new_statement_t + { + return { *static_cast(this), insert_default_values_data_t{} }; + } + + template + auto columns(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), column_list_data_t{args...} }; + } + + template + auto set(Assignments... assignments) + -> _new_statement_t> + { + static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); + return _set_impl(assignments...); + } + + template + auto dynamic_set(Assignments... assignments) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); + return _set_impl<_database_t>(assignments...); + } + private: + template + auto _set_impl(Assignments... assignments) + -> _new_statement_t> + { + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); + static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); + static_assert(sqlpp::detail::none_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...>::type; + static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables"); + + return { *static_cast(this), insert_list_data_t{assignments...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t + { + using T = insert_default_values_data_t; + + static Context& _(const T& t, Context& context) + { + context << " DEFAULT VALUES"; + return context; + } + }; + + template + struct serializer_t> + { + using T = column_list_data_t; + + static Context& _(const T& t, Context& context) + { + context << " ("; + interpret_tuple(t._columns, ",", context); + context << ")"; + context << " VALUES "; + bool first = true; + for (const auto& row : t._insert_values) + { + if (not first) + context << ','; + else + first = false; + context << '('; + interpret_tuple(row, ",", context); + context << ')'; + } + + return context; + } + }; + + template + struct serializer_t> + { + using T = insert_list_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Assignments) + t._dynamic_columns.size() == 0) + { + serialize(insert_default_values_data_t(), context); + } + else + { + context << " ("; + interpret_tuple(t._columns, ",", context); + if (sizeof...(Assignments) and not t._dynamic_columns.empty()) + context << ','; + interpret_list(t._dynamic_columns, ',', context); + context << ") VALUES("; + interpret_tuple(t._values, ",", context); + if (sizeof...(Assignments) and not t._dynamic_values.empty()) + context << ','; + interpret_list(t._dynamic_values, ',', context); + context << ")"; + } + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index 2e8ea407..c1ab26bf 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include namespace sqlpp { @@ -42,15 +43,10 @@ namespace sqlpp // integral value type struct integral { - using _value_type = integral; - using _base_value_type = integral; - using _is_numeric = std::true_type; - using _is_integral = std::true_type; - using _is_value = std::true_type; - using _is_expression = std::true_type; + using _traits = make_traits; + using _tag = ::sqlpp::tag::integral; using _cpp_value_type = int64_t; - struct _parameter_t { using _value_type = integral; @@ -58,12 +54,12 @@ namespace sqlpp _parameter_t(): _value(0), _is_null(true) - {} + {} explicit _parameter_t(const _cpp_value_type& value): _value(value), _is_null(false) - {} + {} _parameter_t& operator=(const _cpp_value_type& value) { @@ -79,7 +75,7 @@ namespace sqlpp } bool is_null() const - { + { return _is_null; } @@ -102,145 +98,132 @@ namespace sqlpp }; template - struct _result_entry_t - { - using _value_type = integral; + struct _result_entry_t + { + using _value_type = integral; - _result_entry_t(): - _is_valid(false), - _is_null(true), - _value(0) + _result_entry_t(): + _is_valid(false), + _is_null(true), + _value(0) {} - _result_entry_t(const char* data, size_t): - _is_valid(true), - _is_null(data == nullptr), - _value(_is_null ? 0 : std::strtoll(data, nullptr, 10)) - {} - - void assign(const char* data, size_t) - { - _is_valid = true; - _is_null = data == nullptr; - _value = _is_null ? 0 : std::strtoll(data, nullptr, 10); - } - - void invalidate() - { - _is_valid = false; - _is_null = true; - _value = 0; - } - - void validate() - { - _is_valid = true; - } - - bool is_null() const - { - if (connector_assert_result_validity_t::value) - assert(_is_valid); - else 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::value; - if (connector_assert_result_validity_t::value) + void _invalidate() { - 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"); - } - return _value; - } - - operator _cpp_value_type() const { return value(); } - - template - void _bind(Target& target, size_t i) - { - target._bind_integral_result(i, &_value, &_is_null); + _is_valid = false; + _is_null = true; + _value = 0; } - private: - bool _is_valid; - bool _is_null; - _cpp_value_type _value; - }; + void _validate() + { + _is_valid = true; + } + + bool is_null() const + { + if (connector_assert_result_validity_t::value) + assert(_is_valid); + else 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::value; + if (connector_assert_result_validity_t::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"); + } + return _value; + } + + operator _cpp_value_type() const { return value(); } + + template + void _bind(Target& target, size_t i) + { + target._bind_integral_result(i, &_value, &_is_null); + } + + private: + bool _is_valid; + bool _is_null; + _cpp_value_type _value; + }; template struct _is_valid_operand - { - static constexpr bool value = - is_expression_t::value // expressions are OK - and is_numeric_t::value // the correct value type is required, of course - ; - }; + { + static constexpr bool value = + is_expression_t::value // expressions are OK + and is_numeric_t::value // the correct value type is required, of course + ; + }; template struct expression_operators: public basic_expression_operators { template - vendor::plus_t, vendor::wrap_operand_t> operator +(T t) const + plus_t, wrap_operand_t> operator +(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand"); return { *static_cast(this), {t} }; } template - vendor::minus_t, vendor::wrap_operand_t> operator -(T t) const + minus_t, wrap_operand_t> operator -(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand"); return { *static_cast(this), {t} }; } template - vendor::multiplies_t, vendor::wrap_operand_t> operator *(T t) const + multiplies_t, wrap_operand_t> operator *(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand"); return { *static_cast(this), {t} }; } template - vendor::divides_t> operator /(T t) const + divides_t> operator /(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand"); return { *static_cast(this), {t} }; } template - vendor::modulus_t> operator %(T t) const + modulus_t> operator %(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand"); return { *static_cast(this), {t} }; } - vendor::unary_plus_t operator +() const + unary_plus_t operator +() const { return { *static_cast(this) }; } - vendor::unary_minus_t operator -() const + unary_minus_t operator -() const { return { *static_cast(this) }; } @@ -248,50 +231,50 @@ namespace sqlpp template struct column_operators - { - template - auto operator +=(T t) const -> vendor::assignment_t, vendor::wrap_operand_t>> - { - using rhs = vendor::wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + { + template + auto operator +=(T t) const -> assignment_t, wrap_operand_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - return { *static_cast(this), { *static_cast(this), rhs{t} } }; - } + return { *static_cast(this), { *static_cast(this), rhs{t} } }; + } - template - auto operator -=(T t) const -> vendor::assignment_t, vendor::wrap_operand_t>> - { - using rhs = vendor::wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + template + auto operator -=(T t) const -> assignment_t, wrap_operand_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - return { *static_cast(this), { *static_cast(this), rhs{t} } }; - } + return { *static_cast(this), { *static_cast(this), rhs{t} } }; + } - template - auto operator /=(T t) const -> vendor::assignment_t>> - { - using rhs = vendor::wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + template + auto operator /=(T t) const -> assignment_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - return { *static_cast(this), { *static_cast(this), rhs{t} } }; - } + return { *static_cast(this), { *static_cast(this), rhs{t} } }; + } - template - auto operator *=(T t) const -> vendor::assignment_t, vendor::wrap_operand_t>> - { - using rhs = vendor::wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + template + auto operator *=(T t) const -> assignment_t, wrap_operand_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - return { *static_cast(this), { *static_cast(this), rhs{t} } }; - } - }; + return { *static_cast(this), { *static_cast(this), rhs{t} } }; + } + }; }; template - inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t& e) - { - return os << e.value(); - } + inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t& e) + { + return os << e.value(); + } } using tinyint = detail::integral; diff --git a/include/sqlpp11/interpret.h b/include/sqlpp11/interpret.h index 42cc1524..4d1b2c20 100644 --- a/include/sqlpp11/interpret.h +++ b/include/sqlpp11/interpret.h @@ -27,15 +27,15 @@ #ifndef SQLPP_INTERPRET_H #define SQLPP_INTERPRET_H -#include +#include namespace sqlpp { template auto interpret(const T& t, Context& context) - -> decltype(vendor::interpreter_t::_(t, context)) + -> decltype(interpreter_t::_(t, context)) { - return vendor::interpreter_t::_(t, context); + return interpreter_t::_(t, context); } } diff --git a/include/sqlpp11/vendor/interpret_tuple.h b/include/sqlpp11/interpret_tuple.h similarity index 94% rename from include/sqlpp11/vendor/interpret_tuple.h rename to include/sqlpp11/interpret_tuple.h index aa12c9b8..04ac5d4a 100644 --- a/include/sqlpp11/vendor/interpret_tuple.h +++ b/include/sqlpp11/interpret_tuple.h @@ -50,7 +50,7 @@ namespace sqlpp auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const ::sqlpp::detail::index_sequence&) -> Context& { - // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. + // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. // See for example: "http://en.cppreference.com/w/cpp/utility/integer_sequence" // See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777" // Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used diff --git a/include/sqlpp11/interpretable.h b/include/sqlpp11/interpretable.h new file mode 100644 index 00000000..c93bcaea --- /dev/null +++ b/include/sqlpp11/interpretable.h @@ -0,0 +1,128 @@ +/* + * 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_INTERPRETABLE_H +#define SQLPP_INTERPRETABLE_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct interpretable_t + { + using _serializer_context_t = typename Db::_serializer_context_t; + using _interpreter_context_t = typename Db::_interpreter_context_t; + + template + interpretable_t(T t): + _impl(std::make_shared<_impl_t>(t)) + {} + + interpretable_t(const interpretable_t&) = default; + interpretable_t(interpretable_t&&) = default; + interpretable_t& operator=(const interpretable_t&) = default; + interpretable_t& operator=(interpretable_t&&) = default; + ~interpretable_t() = default; + + sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const + { + return _impl->serialize(context); + } + + // This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same + template + auto serialize(Context& context) const + -> typename std::enable_if::value + and not std::is_same::value, Context&>::type + { + return _impl->db_serialize(context); + } + + _interpreter_context_t& interpret(_interpreter_context_t& context) const + { + return _impl->interpret(context); + } + + private: + struct _impl_base + { + virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0; + virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0; + virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0; + }; + + template + struct _impl_t: public _impl_base + { + static_assert(not make_parameter_list_t::size::value, "parameters not supported in dynamic statement parts"); + _impl_t(T t): + _t(t) + {} + + sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const + { + sqlpp::serialize(_t, context); + return context; + } + + _serializer_context_t& db_serialize(_serializer_context_t& context) const + { + Db::_serialize_interpretable(_t, context); + return context; + } + + _interpreter_context_t& interpret(_interpreter_context_t& context) const + { + Db::_interpret_interpretable(_t, context); + return context; + } + + T _t; + }; + + std::shared_ptr _impl; + }; + + template + struct serializer_t> + { + using T = interpretable_t; + + static Context& _(const T& t, Context& context) + { + t.serialize(context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/vendor/interpretable_list.h b/include/sqlpp11/interpretable_list.h similarity index 51% rename from include/sqlpp11/vendor/interpretable_list.h rename to include/sqlpp11/interpretable_list.h index a6b2d27e..e3641972 100644 --- a/include/sqlpp11/vendor/interpretable_list.h +++ b/include/sqlpp11/interpretable_list.h @@ -28,92 +28,89 @@ #define SQLPP_INTERPRETABLE_LIST_H #include -#include +#include namespace sqlpp { - namespace vendor - { - template - struct interpretable_list_t + template + struct interpretable_list_t + { + std::vector> _serializables; + + std::size_t size() const { - std::vector> _serializables; + return _serializables.size(); + } - std::size_t size() const - { - return _serializables.size(); - } + bool empty() const + { + return _serializables.empty(); + } - bool empty() const - { - return _serializables.empty(); - } - - template + template void emplace_back(Expr expr) { _serializables.emplace_back(expr); } - }; + }; - template<> - struct interpretable_list_t + template<> + struct interpretable_list_t + { + static constexpr std::size_t size() { - static constexpr std::size_t size() - { - return 0; - } - - static constexpr bool empty() - { - return true; - } - - }; - - template - struct serializable_list_interpreter_t - { - using T = List; - - template - static Context& _(const T& t, const Separator& separator, Context& context) - { - bool first = true; - for (const auto entry : t._serializables) - { - if (not first) - { - context << separator; - first = false; - } - serialize(entry, context); - } - return context; - } - }; - - template - struct serializable_list_interpreter_t> - { - using T = interpretable_list_t; - - template - static Context& _(const T& t, const Separator& separator, Context& context) - { - return context; - } - }; - - template - auto interpret_list(const T& t, const Separator& separator, Context& context) - -> decltype(serializable_list_interpreter_t::_(t, separator, context)) - { - return serializable_list_interpreter_t::_(t, separator, context); + return 0; } - } + static constexpr bool empty() + { + return true; + } + + }; + + template + struct serializable_list_interpreter_t + { + using T = List; + + template + static Context& _(const T& t, const Separator& separator, Context& context) + { + bool first = true; + for (const auto entry : t._serializables) + { + if (not first) + { + context << separator; + first = false; + } + serialize(entry, context); + } + return context; + } + }; + + template + struct serializable_list_interpreter_t> + { + using T = interpretable_list_t; + + template + static Context& _(const T& t, const Separator& separator, Context& context) + { + return context; + } + }; + + template + auto interpret_list(const T& t, const Separator& separator, Context& context) + -> decltype(serializable_list_interpreter_t::_(t, separator, context)) + { + return serializable_list_interpreter_t::_(t, separator, context); + } + } #endif diff --git a/include/sqlpp11/vendor/interpreter.h b/include/sqlpp11/interpreter.h similarity index 79% rename from include/sqlpp11/vendor/interpreter.h rename to include/sqlpp11/interpreter.h index 17dd6075..cd7c9690 100644 --- a/include/sqlpp11/vendor/interpreter.h +++ b/include/sqlpp11/interpreter.h @@ -24,24 +24,21 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_VENDOR_INTERPRETER_H -#define SQLPP_VENDOR_INTERPRETER_H +#ifndef SQLPP_INTERPRETER_H +#define SQLPP_INTERPRETER_H -#include +#include namespace sqlpp { - namespace vendor - { - template - struct interpreter_t + template + struct interpreter_t + { + static void _(const T& t, Context& context) { - static void _(const T& t, Context& context) - { - static_assert(wrong_t::value, "missing interpreter specialization"); - } - }; - } + static_assert(wrong_t::value, "missing interpreter specialization"); + } + }; } diff --git a/include/sqlpp11/into.h b/include/sqlpp11/into.h new file mode 100644 index 00000000..3e8ba6b4 --- /dev/null +++ b/include/sqlpp11/into.h @@ -0,0 +1,173 @@ +/* + * 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_INTO_H +#define SQLPP_INTO_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // A SINGLE TABLE DATA + template + struct into_data_t + { + into_data_t(Table table): + _table(table) + {} + + into_data_t(const into_data_t&) = default; + into_data_t(into_data_t&&) = default; + into_data_t& operator=(const into_data_t&) = default; + into_data_t& operator=(into_data_t&&) = default; + ~into_data_t() = default; + + Table _table; + }; + + // A SINGLE TABLE + template + struct into_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits
; + + static_assert(is_table_t
::value, "argument has to be a table"); + static_assert(required_tables_of
::size::value == 0, "table depends on another table"); + + using _data_t = into_data_t; + + struct _name_t {}; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = into_data_t; + + _impl_t into; + _impl_t& operator()() { return into; } + const _impl_t& operator()() const { return into; } + + template + static auto _get_member(T t) -> decltype(t.into) + { + return t.into; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + + }; + + // NO INTO YET + struct no_into_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_into; + _impl_t& operator()() { return no_into; } + const _impl_t& operator()() const { return no_into; } + + template + static auto _get_member(T t) -> decltype(t.no_into) + { + return t.no_into; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() + { + static_assert(wrong_t::value, "into() required"); + } + + template + auto into(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), into_data_t{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = into_data_t; + + static Context& _(const T& t, Context& context) + { + context << " INTO "; + serialize(t._table, context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/vendor/is_null.h b/include/sqlpp11/is_null.h similarity index 56% rename from include/sqlpp11/vendor/is_null.h rename to include/sqlpp11/is_null.h index 2b963134..1aedf49a 100644 --- a/include/sqlpp11/vendor/is_null.h +++ b/include/sqlpp11/is_null.h @@ -33,55 +33,55 @@ namespace sqlpp { - namespace vendor + template + struct is_null_t: public boolean::template expression_operators>, + public alias_operators> { - template - struct is_null_t: public boolean::template expression_operators> + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + static constexpr bool _inverted = not NotInverted; + + struct _value_type: public boolean { - static constexpr bool _inverted = not NotInverted; - using _table_set = typename Operand::_table_set; - - struct _value_type: public boolean - { - using _is_named_expression = std::true_type; - }; - - struct _name_t - { - static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; } - template - struct _member_t - { - T in; - }; - }; - - is_null_t(Operand operand): - _operand(operand) - {} - - is_null_t(const is_null_t&) = default; - is_null_t(is_null_t&&) = default; - is_null_t& operator=(const is_null_t&) = default; - is_null_t& operator=(is_null_t&&) = default; - ~is_null_t() = default; - - Operand _operand; + using _is_named_expression = std::true_type; }; - template - struct serializer_t> - { - using T = ::sqlpp::vendor::is_null_t; - - static Context& _(const T& t, Context& context) + struct _name_t + { + static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; } + template + struct _member_t { - serialize(t._operand, context); - context << (t._inverted ? " IS NOT NULL" : " IS NULL"); - return context; - } - }; - } + T in; + }; + }; + + is_null_t(Operand operand): + _operand(operand) + {} + + is_null_t(const is_null_t&) = default; + is_null_t(is_null_t&&) = default; + is_null_t& operator=(const is_null_t&) = default; + is_null_t& operator=(is_null_t&&) = default; + ~is_null_t() = default; + + Operand _operand; + }; + + template + struct serializer_t> + { + using T = ::sqlpp::is_null_t; + + static Context& _(const T& t, Context& context) + { + serialize(t._operand, context); + context << (t._inverted ? " IS NOT NULL" : " IS NULL"); + return context; + } + }; } diff --git a/include/sqlpp11/vendor/is_null_fwd.h b/include/sqlpp11/is_null_fwd.h similarity index 95% rename from include/sqlpp11/vendor/is_null_fwd.h rename to include/sqlpp11/is_null_fwd.h index 0c8e62f0..8d53cc01 100644 --- a/include/sqlpp11/vendor/is_null_fwd.h +++ b/include/sqlpp11/is_null_fwd.h @@ -29,11 +29,8 @@ namespace sqlpp { - namespace vendor - { - template + template struct is_null_t; - } } #endif diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index 1c959ba3..9d0a92f4 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -29,7 +29,7 @@ #include #include -#include +#include namespace sqlpp { @@ -74,19 +74,20 @@ namespace sqlpp static constexpr const char* _name = " RIGHT OUTER "; }; - template + template struct join_t { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static_assert(is_table_t::value, "lhs argument for join() has to be a table or join"); static_assert(is_table_t::value, "rhs argument for join() has to be a table"); static_assert(not is_join_t::value, "rhs argument for join must not be a join"); - static_assert(vendor::is_noop::value or is_on_t::value, "invalid on expression in join().on()"); + static_assert(is_noop::value or is_on_t::value, "invalid on expression in join().on()"); - static_assert(::sqlpp::detail::is_disjunct_from::value, "joined tables must not be identical"); + static_assert(::sqlpp::detail::is_disjunct_from, provided_tables_of>::value, "joined tables must not be identical"); - using _is_table = std::true_type; - using _is_join = std::true_type; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; + static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables"); template using set_on_t = join_t; @@ -95,7 +96,7 @@ namespace sqlpp auto on(Expr... expr) -> set_on_t> { - static_assert(vendor::is_noop::value, "cannot call on() twice for a single join()"); + static_assert(is_noop::value, "cannot call on() twice for a single join()"); return { _lhs, _rhs, {std::tuple{expr...}} @@ -105,35 +106,35 @@ namespace sqlpp template join_t join(T t) { - static_assert(not vendor::is_noop::value, "join type requires on()"); + static_assert(not is_noop::value, "join type requires on()"); return { *this, t }; } template join_t inner_join(T t) { - static_assert(not vendor::is_noop::value, "join type requires on()"); + static_assert(not is_noop::value, "join type requires on()"); return { *this, t }; } template join_t outer_join(T t) { - static_assert(not vendor::is_noop::value, "join type requires on()"); + static_assert(not is_noop::value, "join type requires on()"); return { *this, t }; } template join_t left_outer_join(T t) { - static_assert(not vendor::is_noop::value, "join type requires on()"); + static_assert(not is_noop::value, "join type requires on()"); return { *this, t }; } template join_t right_outer_join(T t) { - static_assert(not vendor::is_noop::value, "join type requires on()"); + static_assert(not is_noop::value, "join type requires on()"); return { *this, t }; } @@ -142,26 +143,23 @@ namespace sqlpp On _on; }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = join_t; + + static Context& _(const T& t, Context& context) { - using T = join_t; + static_assert(not is_noop::value, "joined tables require on()"); + serialize(t._lhs, context); + context << JoinType::_name; + context << " JOIN "; + serialize(t._rhs, context); + serialize(t._on, context); + return context; + } + }; - static Context& _(const T& t, Context& context) - { - static_assert(not vendor::is_noop::value, "joined tables require on()"); - serialize(t._lhs, context); - context << JoinType::_name; - context << " JOIN "; - serialize(t._rhs, context); - serialize(t._on, context); - return context; - } - }; - - } } #endif diff --git a/include/sqlpp11/vendor/like.h b/include/sqlpp11/like.h similarity index 51% rename from include/sqlpp11/vendor/like.h rename to include/sqlpp11/like.h index ca756cbb..46f1572a 100644 --- a/include/sqlpp11/vendor/like.h +++ b/include/sqlpp11/like.h @@ -33,61 +33,55 @@ namespace sqlpp { - namespace vendor + template + struct like_t: public boolean::template expression_operators>, + public alias_operators> { - template - struct like_t: public boolean::template expression_operators> + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + static_assert(is_text_t::value, "Operand for like() has to be a text"); + static_assert(is_text_t::value, "Pattern for like() has to be a text"); + + struct _name_t { - static_assert(is_text_t::value, "Operand for like() has to be a text"); - static_assert(is_text_t::value, "Pattern for like() has to be a text"); - using _parameter_tuple_t = std::tuple; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - struct _value_type: public boolean - { - using _is_named_expression = std::true_type; - }; - - struct _name_t - { - static constexpr const char* _get_name() { return "LIKE"; } - template - struct _member_t - { - T like; - }; - }; - - like_t(Operand operand, Pattern pattern): - _operand(operand), - _pattern(pattern) - {} - - like_t(const like_t&) = default; - like_t(like_t&&) = default; - like_t& operator=(const like_t&) = default; - like_t& operator=(like_t&&) = default; - ~like_t() = default; - - Operand _operand; - Pattern _pattern; + static constexpr const char* _get_name() { return "LIKE"; } + template + struct _member_t + { + T like; + }; }; - template - struct serializer_t> - { - using T = like_t; + like_t(Operand operand, Pattern pattern): + _operand(operand), + _pattern(pattern) + {} - static Context& _(const T& t, Context& context) - { - serialize(t._operand, context); - context << " LIKE("; - serialize(t._pattern, context); - context << ")"; - return context; - } - }; - } + like_t(const like_t&) = default; + like_t(like_t&&) = default; + like_t& operator=(const like_t&) = default; + like_t& operator=(like_t&&) = default; + ~like_t() = default; + + Operand _operand; + Pattern _pattern; + }; + + template + struct serializer_t> + { + using T = like_t; + + static Context& _(const T& t, Context& context) + { + serialize(t._operand, context); + context << " LIKE("; + serialize(t._pattern, context); + context << ")"; + return context; + } + }; } #endif diff --git a/include/sqlpp11/limit.h b/include/sqlpp11/limit.h new file mode 100644 index 00000000..e38b3919 --- /dev/null +++ b/include/sqlpp11/limit.h @@ -0,0 +1,261 @@ +/* + * 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_LIMIT_H +#define SQLPP_LIMIT_H + +#include +#include +#include + +namespace sqlpp +{ + // LIMIT DATA + template + struct limit_data_t + { + limit_data_t(Limit value): + _value(value) + {} + + limit_data_t(const limit_data_t&) = default; + limit_data_t(limit_data_t&&) = default; + limit_data_t& operator=(const limit_data_t&) = default; + limit_data_t& operator=(limit_data_t&&) = default; + ~limit_data_t() = default; + + Limit _value; + }; + + // LIMIT + template + struct limit_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); + + // Data + using _data_t = limit_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = limit_data_t; + + _impl_t limit; + _impl_t& operator()() { return limit; } + const _impl_t& operator()() const { return limit; } + + template + static auto _get_member(T t) -> decltype(t.limit) + { + return t.limit; + } + }; + + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // DYNAMIC LIMIT DATA + template + struct dynamic_limit_data_t + { + dynamic_limit_data_t(): + _value(noop()) + { + } + + template + dynamic_limit_data_t(Limit value): + _initialized(true), + _value(typename wrap_operand::type(value)) + { + } + + dynamic_limit_data_t(const dynamic_limit_data_t&) = default; + dynamic_limit_data_t(dynamic_limit_data_t&&) = default; + dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default; + dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default; + ~dynamic_limit_data_t() = default; + + bool _initialized = false; + interpretable_t _value; + }; + + // DYNAMIC LIMIT + template + struct dynamic_limit_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = dynamic_limit_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void set(Limit value) + { + // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL + using arg_t = typename wrap_operand::type; + _data._value = arg_t{value}; + _data._initialized = true; + } + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = dynamic_limit_data_t; + + _impl_t limit; + _impl_t& operator()() { return limit; } + const _impl_t& operator()() const { return limit; } + + template + static auto _get_member(T t) -> decltype(t.limit) + { + return t.limit; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + struct no_limit_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_limit; + _impl_t& operator()() { return no_limit; } + const _impl_t& operator()() const { return no_limit; } + + template + static auto _get_member(T t) -> decltype(t.no_limit) + { + return t.no_limit; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto limit(Arg arg) + -> _new_statement_t::type>> + { + return { *static_cast(this), limit_data_t::type>{{arg}} }; + } + + auto dynamic_limit() + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); + return { *static_cast(this), dynamic_limit_data_t<_database_t>{} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = dynamic_limit_data_t; + + static Context& _(const T& t, Context& context) + { + if (t._initialized) + { + context << " LIMIT "; + serialize(t._value, context); + } + return context; + } + }; + + template + struct serializer_t> + { + using T = limit_data_t; + + static Context& _(const T& t, Context& context) + { + context << " LIMIT "; + serialize(t._value, context); + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index a86c4b22..a96dfe4d 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -31,67 +31,58 @@ namespace sqlpp { - namespace vendor + template + struct max_t: public value_type_of::template expression_operators>, + public alias_operators> { - template - struct max_t: public Expr::_value_type::template expression_operators> + using _traits = make_traits, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; + using _recursive_traits = make_recursive_traits; + + static_assert(is_expression_t::value, "max() requires a value expression as argument"); + + struct _name_t { - static_assert(is_value_t::value, "max() requires a value expression as argument"); - - struct _value_type: public Expr::_value_type::_base_value_type - { - using _is_named_expression = std::true_type; - }; - - using _table_set = typename Expr::_table_set; - - struct _name_t - { - static constexpr const char* _get_name() { return "MAX"; } - template - struct _member_t - { - T max; - T& operator()() { return max; } - const T& operator()() const { return max; } - }; - }; - - max_t(Expr expr): - _expr(expr) - {} - - max_t(const max_t&) = default; - max_t(max_t&&) = default; - max_t& operator=(const max_t&) = default; - max_t& operator=(max_t&&) = default; - ~max_t() = default; - - Expr _expr; - }; - } - - namespace vendor - { - template - struct serializer_t> - { - using T = vendor::max_t; - - static Context& _(const T& t, Context& context) + static constexpr const char* _get_name() { return "MAX"; } + template + struct _member_t { - context << "MAX("; - serialize(t._expr, context); - context << ")"; - return context; - } - }; - } + T max; + T& operator()() { return max; } + const T& operator()() const { return max; } + }; + }; + + max_t(Expr expr): + _expr(expr) + {} + + max_t(const max_t&) = default; + max_t(max_t&&) = default; + max_t& operator=(const max_t&) = default; + max_t& operator=(max_t&&) = default; + ~max_t() = default; + + Expr _expr; + }; + + template + struct serializer_t> + { + using T = max_t; + + static Context& _(const T& t, Context& context) + { + context << "MAX("; + serialize(t._expr, context); + context << ")"; + return context; + } + }; template - auto max(T t) -> typename vendor::max_t> + auto max(T t) -> max_t> { - static_assert(is_value_t>::value, "max() requires a value expression as argument"); + static_assert(is_expression_t>::value, "max() requires a value expression as argument"); return { t }; } diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index c7d9f9e0..3993bf81 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -31,67 +31,58 @@ namespace sqlpp { - namespace vendor + template + struct min_t: public value_type_of::template expression_operators>, + public alias_operators> { - template - struct min_t: public Expr::_value_type::template expression_operators> + using _traits = make_traits, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; + using _recursive_traits = make_recursive_traits; + + static_assert(is_expression_t::value, "min() requires a value expression as argument"); + + struct _name_t { - static_assert(is_value_t::value, "min() requires a value expression as argument"); - - struct _value_type: public Expr::_value_type::_base_value_type - { - using _is_named_expression = std::true_type; - }; - - using _table_set = typename Expr::_table_set; - - struct _name_t - { - static constexpr const char* _get_name() { return "MIN"; } - template - struct _member_t - { - T min; - T& operator()() { return min; } - const T& operator()() const { return min; } - }; - }; - - min_t(Expr expr): - _expr(expr) - {} - - min_t(const min_t&) = default; - min_t(min_t&&) = default; - min_t& operator=(const min_t&) = default; - min_t& operator=(min_t&&) = default; - ~min_t() = default; - - Expr _expr; - }; - } - - namespace vendor - { - template - struct serializer_t> - { - using T = vendor::min_t; - - static Context& _(const T& t, Context& context) + static constexpr const char* _get_name() { return "MIN"; } + template + struct _member_t { - context << "MIN("; - serialize(t._expr, context); - context << ")"; - return context; - } - }; - } + T min; + T& operator()() { return min; } + const T& operator()() const { return min; } + }; + }; + + min_t(Expr expr): + _expr(expr) + {} + + min_t(const min_t&) = default; + min_t(min_t&&) = default; + min_t& operator=(const min_t&) = default; + min_t& operator=(min_t&&) = default; + ~min_t() = default; + + Expr _expr; + }; + + template + struct serializer_t> + { + using T = min_t; + + static Context& _(const T& t, Context& context) + { + context << "MIN("; + serialize(t._expr, context); + context << ")"; + return context; + } + }; template - auto min(T t) -> typename vendor::min_t> + auto min(T t) -> min_t> { - static_assert(is_value_t>::value, "min() requires a value expression as argument"); + static_assert(is_expression_t>::value, "min() requires a value expression as argument"); return { t }; } diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 89fdc464..ac09881c 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -41,9 +41,10 @@ namespace sqlpp template struct multi_column_t { - static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; - using _table_set = sqlpp::detail::make_joined_set_t; + static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); multi_column_t(std::tuple columns): _columns(columns) @@ -75,10 +76,12 @@ namespace sqlpp template struct multi_column_alias_t { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); using _name_t = typename AliasProvider::_name_t; - using _table_set = sqlpp::detail::make_joined_set_t; multi_column_alias_t(multi_column_t multi_column): _columns(multi_column._columns) @@ -107,31 +110,28 @@ namespace sqlpp std::tuple _columns; }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = multi_column_t; + + static void _(const T& t, Context& context) { - using T = multi_column_t; + static_assert(wrong_t::value, "multi_column must be used with an alias"); + } + }; - static void _(const T& t, Context& context) - { - static_assert(wrong_t::value, "multi_column must be used with an alias"); - } - }; + template + struct serializer_t> + { + using T = multi_column_alias_t; - template - struct serializer_t> + static Context& _(const T& t, Context& context) { - using T = multi_column_alias_t; - - static Context& _(const T& t, Context& context) - { - interpret_tuple(t._columns, ',', context); - return context; - } - }; - } + interpret_tuple(t._columns, ',', context); + return context; + } + }; namespace detail { diff --git a/include/sqlpp11/named_interpretable.h b/include/sqlpp11/named_interpretable.h new file mode 100644 index 00000000..dcbffbdb --- /dev/null +++ b/include/sqlpp11/named_interpretable.h @@ -0,0 +1,137 @@ +/* + * 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_NAMED_SERIALIZABLE_H +#define SQLPP_NAMED_SERIALIZABLE_H + +#include +#include +#include + +namespace sqlpp +{ + template + struct named_interpretable_t + { + using _serializer_context_t = typename Db::_serializer_context_t; + using _interpreter_context_t = typename Db::_interpreter_context_t; + + template + named_interpretable_t(T t): + _impl(std::make_shared<_impl_t>(t)) + {} + + named_interpretable_t(const named_interpretable_t&) = default; + named_interpretable_t(named_interpretable_t&&) = default; + named_interpretable_t& operator=(const named_interpretable_t&) = default; + named_interpretable_t& operator=(named_interpretable_t&&) = default; + ~named_interpretable_t() = default; + + sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const + { + return _impl->serialize(context); + } + + // This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same + template + auto serialize(Context& context) const + -> typename std::enable_if::value + and not std::is_same::value, Context&>::type + { + return _impl->db_serialize(context); + } + + _interpreter_context_t& interpret(_interpreter_context_t& context) const + { + return _impl->interpret(context); + } + + std::string _get_name() const + { + return _impl->_get_name(); + } + + private: + struct _impl_base + { + virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0; + virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0; + virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0; + virtual std::string _get_name() const = 0; + }; + + template + struct _impl_t: public _impl_base + { + static_assert(not make_parameter_list_t::size::value, "parameters not supported in dynamic statement parts"); + _impl_t(T t): + _t(t) + {} + + sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const + { + sqlpp::serialize(_t, context); + return context; + } + + _serializer_context_t& db_serialize(_serializer_context_t& context) const + { + Db::_serialize_interpretable(_t, context); + return context; + } + + _interpreter_context_t& interpret(_interpreter_context_t& context) const + { + Db::_interpret_interpretable(_t, context); + return context; + } + + std::string _get_name() const + { + return T::_name_t::_get_name(); + } + + T _t; + }; + + std::shared_ptr _impl; + }; + + template + struct serializer_t> + { + using T = named_interpretable_t; + + static Context& _(const T& t, Context& context) + { + t.serialize(context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/vendor/char_result_row.h b/include/sqlpp11/no_data.h similarity index 82% rename from include/sqlpp11/vendor/char_result_row.h rename to include/sqlpp11/no_data.h index 3cf09c12..e94a9289 100644 --- a/include/sqlpp11/vendor/char_result_row.h +++ b/include/sqlpp11/no_data.h @@ -24,21 +24,25 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_CHAR_RESULT_ROW_H -#define SQLPP_CHAR_RESULT_ROW_H +#ifndef SQLPP_NO_DATA_H +#define SQLPP_NO_DATA_H + +#include +#include namespace sqlpp { - struct char_result_row_t - { - const char** data; - size_t* len; + struct no_data_t {}; - bool operator==(const char_result_row_t& rhs) const + template + struct serializer_t { - return data == rhs.data and len == rhs.len; - } - }; -} + using T = no_data_t; + static Context& _(const T& t, Context& context) + { + return context; + } + }; +} #endif diff --git a/include/sqlpp11/no_value.h b/include/sqlpp11/no_value.h index 2079c5d7..c5ec11fa 100644 --- a/include/sqlpp11/no_value.h +++ b/include/sqlpp11/no_value.h @@ -33,11 +33,7 @@ namespace sqlpp { struct no_value_t { - template - using _constraint = std::false_type; - - using _base_value_type = no_value_t; - + using _tag = void; template struct _is_valid_operand { diff --git a/include/sqlpp11/vendor/noop.h b/include/sqlpp11/noop.h similarity index 74% rename from include/sqlpp11/vendor/noop.h rename to include/sqlpp11/noop.h index e0c28ef1..e28ae330 100644 --- a/include/sqlpp11/vendor/noop.h +++ b/include/sqlpp11/noop.h @@ -28,30 +28,36 @@ #define SQLPP_NOOP_H #include +#include +#include namespace sqlpp { - namespace vendor + struct noop { - struct noop + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + struct _name_t {}; + + template + struct _result_methods_t + {}; + }; + + template + struct serializer_t { - using is_noop = std::true_type; + using T = noop; + + static Context& _(const T& t, Context& context) + { + return context; + } }; - template - struct serializer_t - { - using T = noop; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - template - struct is_noop: std::is_same {}; - } + template + struct is_noop: std::is_same {}; } #endif diff --git a/include/sqlpp11/vendor/noop_fwd.h b/include/sqlpp11/noop_fwd.h similarity index 94% rename from include/sqlpp11/vendor/noop_fwd.h rename to include/sqlpp11/noop_fwd.h index 243f77a2..0c87c75e 100644 --- a/include/sqlpp11/vendor/noop_fwd.h +++ b/include/sqlpp11/noop_fwd.h @@ -29,12 +29,9 @@ namespace sqlpp { - namespace vendor - { - struct noop; + struct noop; - template - struct is_noop; - } + template + struct is_noop; } #endif diff --git a/include/sqlpp11/null.h b/include/sqlpp11/null.h index d8bcd0bd..a3309b15 100644 --- a/include/sqlpp11/null.h +++ b/include/sqlpp11/null.h @@ -33,25 +33,21 @@ namespace sqlpp { struct null_t { - static constexpr bool _is_expression = true; - using _value_type = no_value_t; - using _table_set = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; - namespace vendor - { - template - struct serializer_t - { - using Operand = null_t; + template + struct serializer_t + { + using Operand = null_t; - static Context& _(const Operand& t, Context& context) - { - context << "NULL"; - return context; - } - }; - } + static Context& _(const Operand& t, Context& context) + { + context << "NULL"; + return context; + } + }; constexpr null_t null = {}; diff --git a/include/sqlpp11/offset.h b/include/sqlpp11/offset.h new file mode 100644 index 00000000..7221f4e1 --- /dev/null +++ b/include/sqlpp11/offset.h @@ -0,0 +1,272 @@ +/* + * 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_OFFSET_H +#define SQLPP_OFFSET_H + +#include +#include +#include + +namespace sqlpp +{ + // OFFSET DATA + template + struct offset_data_t + { + offset_data_t(Offset value): + _value(value) + {} + + offset_data_t(const offset_data_t&) = default; + offset_data_t(offset_data_t&&) = default; + offset_data_t& operator=(const offset_data_t&) = default; + offset_data_t& operator=(offset_data_t&&) = default; + ~offset_data_t() = default; + + Offset _value; + }; + + // OFFSET + template + struct offset_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); + + // Data + using _data_t = offset_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = offset_data_t; + + _impl_t offset; + _impl_t& operator()() { return offset; } + const _impl_t& operator()() const { return offset; } + + template + static auto _get_member(T t) -> decltype(t.offset) + { + return t.offset; + } + }; + + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // DYNAMIC OFFSET DATA + template + struct dynamic_offset_data_t + { + dynamic_offset_data_t(): + _value(noop()) + { + } + + template + dynamic_offset_data_t(Offset value): + _initialized(true), + _value(typename wrap_operand::type(value)) + { + } + + dynamic_offset_data_t(const dynamic_offset_data_t&) = default; + dynamic_offset_data_t(dynamic_offset_data_t&&) = default; + dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default; + dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default; + ~dynamic_offset_data_t() = default; + + bool _initialized = false; + interpretable_t _value; + }; + + // DYNAMIC OFFSET + template + struct dynamic_offset_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = dynamic_offset_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void set(Offset value) + { + // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL + using arg_t = typename wrap_operand::type; + _data._value = arg_t{value}; + _data._initialized = true; + } + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = dynamic_offset_data_t; + + _impl_t offset; + _impl_t& operator()() { return offset; } + const _impl_t& operator()() const { return offset; } + + template + static auto _get_member(T t) -> decltype(t.offset) + { + return t.offset; + } + }; + + template + struct _methods_t + { + static void _check_consistency() {} + + template + void set_offset(Offset value) + { + // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL + using arg_t = typename wrap_operand::type; + static_cast(this)->_offset()._value = arg_t{value}; + static_cast(this)->_offset()._initialized = true; + } + }; + + bool _initialized = false; + interpretable_t _value; + }; + + struct no_offset_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_offset; + _impl_t& operator()() { return no_offset; } + const _impl_t& operator()() const { return no_offset; } + + template + static auto _get_member(T t) -> decltype(t.no_offset) + { + return t.no_offset; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto offset(Arg arg) + -> _new_statement_t::type>> + { + return { *static_cast(this), offset_data_t::type>{{arg}} }; + } + + auto dynamic_offset() + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); + return { *static_cast(this), dynamic_offset_data_t<_database_t>{} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = offset_data_t; + + static Context& _(const T& t, Context& context) + { + context << " OFFSET "; + serialize(t._value, context); + return context; + } + }; + + template + struct serializer_t> + { + using T = dynamic_offset_data_t; + + static Context& _(const T& t, Context& context) + { + if (t._initialized) + { + context << " OFFSET "; + serialize(t._value, context); + } + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/on.h b/include/sqlpp11/on.h index 25fc7e94..69f91c11 100644 --- a/include/sqlpp11/on.h +++ b/include/sqlpp11/on.h @@ -28,8 +28,8 @@ #define SQLPP_ON_H #include -#include -#include +#include +#include #include namespace sqlpp @@ -37,8 +37,10 @@ namespace sqlpp template struct on_t { - using _is_on = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()"); static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in on()"); @@ -51,30 +53,27 @@ namespace sqlpp } std::tuple _expressions; - vendor::interpretable_list_t _dynamic_expressions; + interpretable_list_t _dynamic_expressions; }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = on_t; + + static Context& _(const T& t, Context& context) { - using T = on_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) - return context; - context << " ON "; - interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) - context << " AND "; - interpret_list(t._dynamic_expressions, " AND ", context); + if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) return context; - } - }; + context << " ON "; + interpret_tuple(t._expressions, " AND ", context); + if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + context << " AND "; + interpret_list(t._dynamic_expressions, " AND ", context); + return context; + } + }; - } } #endif diff --git a/include/sqlpp11/order_by.h b/include/sqlpp11/order_by.h new file mode 100644 index 00000000..e23422d1 --- /dev/null +++ b/include/sqlpp11/order_by.h @@ -0,0 +1,214 @@ +/* + * 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_ORDER_BY_H +#define SQLPP_ORDER_BY_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // ORDER BY DATA + template + struct order_by_data_t + { + order_by_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + order_by_data_t(const order_by_data_t&) = default; + order_by_data_t(order_by_data_t&&) = default; + order_by_data_t& operator=(const order_by_data_t&) = default; + order_by_data_t& operator=(order_by_data_t&&) = default; + ~order_by_data_t() = default; + + std::tuple _expressions; + interpretable_list_t _dynamic_expressions; + }; + + // ORDER BY + template + struct order_by_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; + + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in order_by()"); + + // Data + using _data_t = order_by_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Expression expression) + { + add(expression); + } + + template + void add(Expression expression) + { + static_assert(_is_dynamic::value, "add() must not be called for static order_by"); + static_assert(is_expression_t::value, "invalid expression argument in order_by::add()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in order_by::add()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; + + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Expression expression, const std::true_type&) + { + return _data._dynamic_expressions.emplace_back(expression); + } + + template + void _add_impl(Expression expression, const std::false_type&); + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = order_by_data_t; + + _impl_t order_by; + _impl_t& operator()() { return order_by; } + const _impl_t& operator()() const { return order_by; } + + template + static auto _get_member(T t) -> decltype(t.order_by) + { + return t.order_by; + } + }; + + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // NO ORDER BY YET + struct no_order_by_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_order_by; + _impl_t& operator()() { return no_order_by; } + const _impl_t& operator()() const { return no_order_by; } + + template + static auto _get_member(T t) -> decltype(t.no_order_by) + { + return t.no_order_by; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto order_by(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), order_by_data_t{args...} }; + } + + template + auto dynamic_order_by(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); + return { *static_cast(this), order_by_data_t<_database_t, Args...>{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = order_by_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) + return context; + context << " ORDER BY "; + interpret_tuple(t._expressions, ',', context); + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) + context << ','; + interpret_list(t._dynamic_expressions, ',', context); + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index de550e15..3cf45236 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -34,16 +34,18 @@ namespace sqlpp { template - struct parameter_t: public ValueType::template expression_operators> + struct parameter_t: public ValueType::template expression_operators> { - struct _value_type: public ValueType + using _traits = make_traits; + struct _recursive_traits { - using _is_expression = std::true_type; - using _is_alias = std::false_type; + using _parameters = std::tuple; + using _provided_tables = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; }; - using _is_parameter = std::true_type; + using _instance_t = typename NameType::_name_t::template _member_t; - using _table_set = sqlpp::detail::type_set<>; parameter_t() {} @@ -55,24 +57,21 @@ namespace sqlpp ~parameter_t() = default; }; - namespace vendor - { - template - struct serializer_t> - { - using T = parameter_t; + template + struct serializer_t> + { + using T = parameter_t; - static Context& _(const T& t, Context& context) - { - context << "?"; - return context; - } - }; - } + static Context& _(const T& t, Context& context) + { + context << "?"; + return context; + } + }; template auto parameter(const NamedExpr&) - -> parameter_t + -> parameter_t, NamedExpr> { static_assert(is_named_expression_t::value, "not a named expression"); return {}; @@ -80,9 +79,9 @@ namespace sqlpp template auto parameter(const ValueType&, const AliasProvider&) - -> parameter_t + -> parameter_t, AliasProvider> { - static_assert(is_value_t::value, "first argument is not a value type"); + static_assert(is_expression_t::value, "first argument is not a value type"); static_assert(is_alias_provider_t::value, "second argument is not an alias provider"); return {}; } diff --git a/include/sqlpp11/parameter_list.h b/include/sqlpp11/parameter_list.h index 1201159e..c023e3f7 100644 --- a/include/sqlpp11/parameter_list.h +++ b/include/sqlpp11/parameter_list.h @@ -28,7 +28,8 @@ #define SQLPP_PARAMETER_LIST_H #include -#include +#include +#include #include namespace sqlpp @@ -36,7 +37,7 @@ namespace sqlpp template struct parameter_list_t { - static_assert(vendor::wrong_t::value, "Template parameter for parameter_list_t has to be a tuple"); + static_assert(wrong_t::value, "Template parameter for parameter_list_t has to be a tuple"); }; template @@ -63,40 +64,8 @@ namespace sqlpp } }; - namespace detail - { - template - struct get_parameter_tuple - { - using type = std::tuple<>; - }; - - template - struct get_parameter_tuple::value, void>::type> - { - using type = std::tuple; - }; - - template - struct get_parameter_tuple, void> - { - // cat together parameter tuples - using type = decltype(std::tuple_cat(std::declval::type>()...)); - }; - - template - struct get_parameter_tuple::value, void>::type> - { - using type = typename get_parameter_tuple::type; - }; - - } - template - struct make_parameter_list_t - { - using type = parameter_list_t::type>; - }; + using make_parameter_list_t = parameter_list_t>; } diff --git a/include/sqlpp11/policy_update.h b/include/sqlpp11/policy_update.h new file mode 100644 index 00000000..ecb61181 --- /dev/null +++ b/include/sqlpp11/policy_update.h @@ -0,0 +1,56 @@ +/* + * 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_POLICY_UPDATE_H +#define SQLPP_POLICY_UPDATE_H + +#include + +namespace sqlpp +{ + template + struct policy_update_impl + { + template + using _policy_t = typename std::conditional::value, Replacement, T>::type; + }; + + template + using policy_update_t = typename policy_update_impl::template _policy_t; + + template + struct update_policies_impl + { + using type = typename Original::template _policy_update_t; + }; + + template + using update_policies_t = typename update_policies_impl::type; + + +} + +#endif diff --git a/include/sqlpp11/prepared_insert.h b/include/sqlpp11/prepared_insert.h index 63a995df..e32c73c8 100644 --- a/include/sqlpp11/prepared_insert.h +++ b/include/sqlpp11/prepared_insert.h @@ -35,14 +35,14 @@ namespace sqlpp template struct prepared_insert_t { - using _parameter_list_t = typename Insert::_parameter_list_t; + using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; auto _run(Db& db) const -> size_t - { - return db.run_prepared_insert(*this); - } + { + return db.run_prepared_insert(*this); + } void _bind_params() const { diff --git a/include/sqlpp11/prepared_remove.h b/include/sqlpp11/prepared_remove.h index 21e72986..672ab5a6 100644 --- a/include/sqlpp11/prepared_remove.h +++ b/include/sqlpp11/prepared_remove.h @@ -35,14 +35,14 @@ namespace sqlpp template struct prepared_remove_t { - using _parameter_list_t = typename Remove::_parameter_list_t; + using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; auto _run(Db& db) const -> size_t - { - return db.run_prepared_insert(*this); - } + { + return db.run_prepared_insert(*this); + } void _bind_params() const { diff --git a/include/sqlpp11/prepared_select.h b/include/sqlpp11/prepared_select.h index 0cdb56b4..2c74e9a2 100644 --- a/include/sqlpp11/prepared_select.h +++ b/include/sqlpp11/prepared_select.h @@ -36,15 +36,15 @@ namespace sqlpp struct prepared_select_t { using _result_row_t = typename Select::template _result_row_t; - using _parameter_list_t = typename Select::_parameter_list_t; + using _parameter_list_t = make_parameter_list_t
; + + static_assert(is_table_t
::value, "argument has to be a table"); + static_assert(required_tables_of
::size::value == 0, "table depends on another table"); + + using _data_t = single_table_data_t; + + struct _name_t {}; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = single_table_data_t; + + _impl_t from; + _impl_t& operator()() { return from; } + const _impl_t& operator()() const { return from; } + + template + static auto _get_member(T t) -> decltype(t.from) + { + return t.from; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + + }; + + // NO INTO YET + struct no_single_table_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_from; + _impl_t& operator()() { return no_from; } + const _impl_t& operator()() const { return no_from; } + + template + static auto _get_member(T t) -> decltype(t.no_from) + { + return t.no_from; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto from(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), single_table_data_t{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = single_table_data_t; + + static Context& _(const T& t, Context& context) + { + serialize(t._table, context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index cd5e63cc..41519e5e 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -32,16 +32,11 @@ namespace sqlpp { - namespace vendor - { - template + template struct some_t { - struct _value_type: public Select::_value_type::_base_value_type - { - using _is_expression = std::false_type; - using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc - }; + using _traits = make_traits, ::sqlpp::tag::multi_expression>; + using _recursive_traits = make_recursive_traits; + + static Context& _(const T& t, Context& context) { - using T = vendor::some_t
; // Hint need a type_set here to be similar to a join (which always represents more than one table) + using _traits = make_traits; + + struct _recursive_traits + { + using _parameters = std::tuple<>; + using _required_tables = detail::type_set<>; + using _provided_tables = detail::type_set
; + using _extra_tables = detail::type_set<>; + }; + static_assert(sizeof...(ColumnSpec), "at least one column required per table"); using _required_insert_columns = typename detail::make_type_set_if...>::type; using _column_tuple_t = std::tuple...>; template using _alias_t = table_alias_t; - using _is_table = std::true_type; template join_t join(T t) @@ -93,22 +101,19 @@ namespace sqlpp } }; - namespace vendor - { - template - struct serializer_t::value and not is_pseudo_table_t::value, void>::type> + template + struct serializer_t::value and not is_pseudo_table_t::value, void>::type> + { + using T = X; + + static Context& _(const T& t, Context& context) { - using T = X; - - static Context& _(const T& t, Context& context) - { - context << T::_name_t::_get_name(); - return context; - } - }; + context << T::_name_t::_get_name(); + return context; + } + }; - } } #endif diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index 273b2d90..ff1a3e19 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -35,22 +35,22 @@ namespace sqlpp { - struct table_alias_base_t {}; - template - struct table_alias_t: public table_alias_base_t, public ColumnSpec::_name_t::template _member_t>... + struct table_alias_t: public ColumnSpec::_name_t::template _member_t>... { //FIXME: Need to add join functionality - using _is_table = std::true_type; - using _table_set = detail::type_set; + using _traits = make_traits, tag::table, tag::alias, tag::named_expression_if>>; - struct _value_type: Table::_value_type + struct _recursive_traits { - using _is_expression = std::false_type; - using _is_named_expression = copy_type_trait; - using _is_alias = std::true_type; + using _parameters = std::tuple<>; + using _required_tables = detail::type_set<>; + using _provided_tables = detail::type_set; + using _extra_tables = detail::type_set<>; }; + static_assert(required_tables_of
::size::value == 0, "table aliases must not depend on external tables"); + using _name_t = typename AliasProvider::_name_t; using _column_tuple_t = std::tuple...>; @@ -61,23 +61,20 @@ namespace sqlpp Table _table; }; - namespace vendor - { - template - struct serializer_t::value, void>::type> + template + struct serializer_t> + { + using T = table_alias_t; + + static Context& _(const T& t, Context& context) { - using T = X; + context << "("; + serialize(t._table, context); + context << ") AS " << T::_name_t::_get_name(); + return context; + } + }; - static Context& _(const T& t, Context& context) - { - context << "("; - serialize(t._table, context); - context << ") AS " << T::_name_t::_get_name(); - return context; - } - }; - - } } #endif diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index 8a41fa24..6cce5aea 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -31,8 +31,8 @@ #include #include #include -#include -#include +#include +#include namespace sqlpp { @@ -41,11 +41,7 @@ namespace sqlpp // text value type struct text { - using _value_type = text; - using _base_value_type = text; - using _is_text = std::true_type; - using _is_value = std::true_type; - using _is_expression = std::true_type; + using _tag = ::sqlpp::tag::text; using _cpp_value_type = std::string; struct _parameter_t @@ -55,12 +51,12 @@ namespace sqlpp _parameter_t(): _value(""), _is_null(true) - {} + {} _parameter_t(const _cpp_value_type& value): _value(value), _is_null(false) - {} + {} _parameter_t& operator=(const _cpp_value_type& value) { @@ -77,7 +73,7 @@ namespace sqlpp } bool is_null() const - { + { return _is_null; } @@ -100,111 +96,98 @@ namespace sqlpp }; template - struct _result_entry_t - { - _result_entry_t(): - _is_valid(false), - _value_ptr(nullptr), - _len(0) + struct _result_entry_t + { + _result_entry_t(): + _is_valid(false), + _value_ptr(nullptr), + _len(0) {} - _result_entry_t(char* data, size_t len): - _is_valid(true), - _value_ptr(data), - _len(_value_ptr ? 0 : len) - {} - - void assign(const char* data, size_t len) - { - _is_valid = true; - _value_ptr = data; - _len = _value_ptr ? len: 0; - } - - void validate() - { - _is_valid = true; - } - - void invalidate() - { - _is_valid = false; - _value_ptr = nullptr; - _len = 0; - } - - bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; } - bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); } - - bool is_null() const - { - if (connector_assert_result_validity_t::value) - assert(_is_valid); - else 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::value; - if (connector_assert_result_validity_t::value) + void _validate() { - assert(_is_valid); - assert(not null_value); - } - else - { - if (not _is_valid) - throw exception("accessing value in non-existing row"); - if (null_value) - throw exception("accessing value of NULL field"); - } - if (_value_ptr) - return std::string(_value_ptr, _value_ptr + _len); - else - return ""; - } - - operator _cpp_value_type() const { return value(); } - - template - void _bind(Target& target, size_t i) - { - target._bind_text_result(i, &_value_ptr, &_len); + _is_valid = true; } - private: - bool _is_valid; - const char* _value_ptr; - size_t _len; - }; + void _invalidate() + { + _is_valid = false; + _value_ptr = nullptr; + _len = 0; + } + + bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; } + bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); } + + bool is_null() const + { + if (connector_assert_result_validity_t::value) + assert(_is_valid); + else 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::value; + if (connector_assert_result_validity_t::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 ""; + } + + operator _cpp_value_type() const { return value(); } + + template + void _bind(Target& target, size_t i) + { + target._bind_text_result(i, &_value_ptr, &_len); + } + + private: + bool _is_valid; + const char* _value_ptr; + size_t _len; + }; template struct _is_valid_operand - { - static constexpr bool value = - is_expression_t::value // expressions are OK - and is_text_t::value // the correct value type is required, of course - ; - }; + { + static constexpr bool value = + is_expression_t::value // expressions are OK + and is_text_t::value // the correct value type is required, of course + ; + }; template struct expression_operators: public basic_expression_operators { template - vendor::concat_t> operator+(T t) const + concat_t> operator+(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand"); return { *static_cast(this), {t} }; } template - vendor::like_t> like(T t) const + like_t> like(T t) const { - using rhs = vendor::wrap_operand_t; + using rhs = wrap_operand_t; static_assert(_is_valid_operand::value, "invalid argument for like()"); return { *static_cast(this), {t} }; @@ -213,23 +196,23 @@ namespace sqlpp template struct column_operators - { - template - auto operator +=(T t) const -> vendor::assignment_t>> - { - using rhs = vendor::wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + { + template + auto operator +=(T t) const -> assignment_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - return { *static_cast(this), { *static_cast(this), rhs{t} } }; - } - }; + return { *static_cast(this), { *static_cast(this), rhs{t} } }; + } + }; }; template - inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t& e) - { - return os << e.value(); - } + inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t& e) + { + return os << e.value(); + } } using text = detail::text; diff --git a/include/sqlpp11/transaction.h b/include/sqlpp11/transaction.h index a2b1dfbc..b0d456cc 100644 --- a/include/sqlpp11/transaction.h +++ b/include/sqlpp11/transaction.h @@ -35,56 +35,56 @@ namespace sqlpp static constexpr bool report_auto_rollback = true; template - class transaction_t - { - Db& _db; - const bool _report_unfinished_transaction; - bool _finished = false; - - public: - transaction_t(Db& db, bool report_unfinished_transaction): - _db(db), - _report_unfinished_transaction(report_unfinished_transaction) + class transaction_t { - _db.start_transaction(); - } + Db& _db; + const bool _report_unfinished_transaction; + bool _finished = false; - transaction_t(const transaction_t&) = delete; - transaction_t(transaction_t&&) = default; - transaction_t& operator=(const transaction_t&) = delete; - transaction_t& operator=(transaction_t&&) = delete; - - ~transaction_t() - { - if (not _finished) + public: + transaction_t(Db& db, bool report_unfinished_transaction): + _db(db), + _report_unfinished_transaction(report_unfinished_transaction) { - try + _db.start_transaction(); + } + + transaction_t(const transaction_t&) = delete; + transaction_t(transaction_t&&) = default; + transaction_t& operator=(const transaction_t&) = delete; + transaction_t& operator=(transaction_t&&) = delete; + + ~transaction_t() + { + if (not _finished) { - _db.rollback_transaction(_report_unfinished_transaction); - } - catch(const std::exception& e) - { - _db.report_rollback_failure(std::string("auto rollback failed: ") + e.what()); - } - catch(...) - { - _db.report_rollback_failure("auto rollback failed with unknown exception"); + try + { + _db.rollback_transaction(_report_unfinished_transaction); + } + catch(const std::exception& e) + { + _db.report_rollback_failure(std::string("auto rollback failed: ") + e.what()); + } + catch(...) + { + _db.report_rollback_failure("auto rollback failed with unknown exception"); + } } } - } - void commit() - { - _finished = true; - _db.commit_transaction(); - } + void commit() + { + _finished = true; + _db.commit_transaction(); + } - void rollback() - { - _finished = true; - _db.rollback_transaction(false); - } - }; + void rollback() + { + _finished = true; + _db.rollback_transaction(false); + } + }; template transaction_t start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback) diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index be1bf137..82e23b3d 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -31,16 +31,18 @@ #include #include -#include +#include +#include namespace sqlpp { template struct tvin_t { + using _traits = make_traits, tag::expression>; + using _recursive_traits = make_recursive_traits; + using _operand_t = Operand; - using _value_type = typename _operand_t::_value_type; - using _table_set = typename _operand_t::_table_set; tvin_t(Operand operand): _value(operand) @@ -56,34 +58,33 @@ namespace sqlpp return _value._is_trivial(); } - _operand_t _value; + Operand _value; }; - namespace vendor - { - template - struct serializer_t> + template + struct serializer_t> + { + using T = tvin_t; + + static void _(const T& t, Context& context) { - using T = tvin_t; + static_assert(wrong_t::value, "tvin() must not be used with anything but =, ==, != and !"); + } + }; - static void _(const T& t, Context& context) - { - static_assert(vendor::wrong_t::value, "tvin() must not be used with anything but =, ==, != and !"); - } - }; - } - - template + template struct maybe_tvin_t { - using _table_set = typename T::_table_set; + using _traits = make_traits, tag::expression>; + using _recursive_traits = make_recursive_traits; + static constexpr bool _is_trivial() { return false; } - maybe_tvin_t(T t): - _value(t) + maybe_tvin_t(Operand operand): + _value(operand) {} maybe_tvin_t(const maybe_tvin_t&) = default; maybe_tvin_t(maybe_tvin_t&&) = default; @@ -91,20 +92,22 @@ namespace sqlpp maybe_tvin_t& operator=(maybe_tvin_t&&) = default; ~maybe_tvin_t() = default; - T _value; + Operand _value; }; - template - struct maybe_tvin_t> + template + struct maybe_tvin_t> { - using _table_set = typename T::_table_set; + using _traits = make_traits, tag::expression>; + using _recursive_traits = make_recursive_traits; + bool _is_trivial() const { return _value._is_trivial(); }; - maybe_tvin_t(tvin_t t): - _value(t._value) + maybe_tvin_t(tvin_t operand): + _value(operand._value) {} maybe_tvin_t(const maybe_tvin_t&) = default; maybe_tvin_t(maybe_tvin_t&&) = default; @@ -112,38 +115,35 @@ namespace sqlpp maybe_tvin_t& operator=(maybe_tvin_t&&) = default; ~maybe_tvin_t() = default; - typename tvin_t::_operand_t _value; + typename tvin_t::_operand_t _value; }; - namespace vendor - { - template - struct serializer_t> - { - using T = maybe_tvin_t; - - static Context& _(const T& t, Context& context) - { - if (t._is_trivial()) - { - context << "NULL"; - } - else - { - serialize(t._value, context); - } - return context; - } - }; - } - - template - auto tvin(T t) -> tvin_t::type> + template + struct serializer_t> { - using _operand_t = typename vendor::wrap_operand::type; - static_assert(std::is_same<_operand_t, vendor::text_operand>::value - or not std::is_same<_operand_t, T>::value, "tvin() used with invalid type (only string and primitive types allowed)"); - return {{t}}; + using T = maybe_tvin_t; + + static Context& _(const T& t, Context& context) + { + if (t._is_trivial()) + { + context << "NULL"; + } + else + { + serialize(t._value, context); + } + return context; + } + }; + + template + auto tvin(Operand operand) -> tvin_t::type> + { + using _operand_t = typename wrap_operand::type; + static_assert(std::is_same<_operand_t, text_operand>::value + or not std::is_same<_operand_t, Operand>::value, "tvin() used with invalid type (only string and primitive types allowed)"); + return {{operand}}; } } diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index b4d39bf8..f74eea08 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -28,7 +28,7 @@ #define SQLPP_TYPE_TRAITS_H #include -#include +#include namespace sqlpp { @@ -36,54 +36,71 @@ namespace sqlpp namespace detail\ {\ template\ - struct is_##name##_impl: std::false_type {};\ + struct is_##name##_impl: std::false_type {};\ template\ - struct is_##name##_impl::value>::type>: std::true_type {};\ + struct is_##name##_impl::value>::type>: std::true_type {};\ }\ + namespace tag\ + {\ + struct name{};\ + };\ template\ - struct is_##name##_t: detail::is_##name##_impl {}; + using is_##name##_t = detail::is_element_of; #define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \ namespace detail\ {\ template\ - struct name##_impl { using type = std::false_type; };\ + struct name##_impl { using type = std::false_type; };\ template\ - struct name##_impl::value>::type> { using type = std::true_type; };\ + struct name##_impl::value>::type> { using type = std::true_type; };\ }\ template\ - using name##_t = typename detail::name##_impl::type; + using name##_t = typename detail::name##_impl::type; #define SQLPP_TYPE_TRAIT_GENERATOR(name) \ namespace detail\ {\ template\ - struct name##_impl: std::false_type {};\ + struct name##_impl: std::false_type {};\ template\ - struct name##_impl::value>::type>: std::true_type {};\ + struct name##_impl::value>::type>: std::true_type {};\ }\ template\ - struct name##_t: detail::name##_impl {}; + struct name##_t: detail::name##_impl {}; #define SQLPP_CONNECTOR_TRAIT_GENERATOR(name) \ namespace detail\ {\ template\ - struct connector_##name##_impl: std::false_type {};\ + struct connector_##name##_impl: std::false_type {};\ template\ - struct connector_##name##_impl::value>::type>: std::true_type {};\ + struct connector_##name##_impl::value>::type>: std::true_type {};\ }\ template\ - struct connector_##name##_t: detail::connector_##name##_impl {}; + struct connector_##name##_t: detail::connector_##name##_impl {}; SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean); - SQLPP_IS_VALUE_TRAIT_GENERATOR(numeric); SQLPP_IS_VALUE_TRAIT_GENERATOR(integral); SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point); + template + using is_numeric_t = detail::any_t< + detail::is_element_of::value, + detail::is_element_of::value>; SQLPP_IS_VALUE_TRAIT_GENERATOR(text); - SQLPP_IS_VALUE_TRAIT_GENERATOR(value); + SQLPP_IS_VALUE_TRAIT_GENERATOR(wrapped_value); SQLPP_IS_VALUE_TRAIT_GENERATOR(expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); + namespace tag + { + template + using named_expression_if = typename std::conditional::type; + } + namespace tag + { + template + using expression_if = typename std::conditional::type; + } SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(alias); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag); @@ -94,41 +111,130 @@ namespace sqlpp SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null); - SQLPP_TYPE_TRAIT_GENERATOR(is_noop); - SQLPP_TYPE_TRAIT_GENERATOR(is_table); - SQLPP_TYPE_TRAIT_GENERATOR(is_join); - SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); - SQLPP_TYPE_TRAIT_GENERATOR(is_column); - SQLPP_TYPE_TRAIT_GENERATOR(is_select); - SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_select_column_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_from); - SQLPP_TYPE_TRAIT_GENERATOR(is_on); - SQLPP_TYPE_TRAIT_GENERATOR(is_dynamic); - SQLPP_TYPE_TRAIT_GENERATOR(is_where); - SQLPP_TYPE_TRAIT_GENERATOR(is_group_by); - SQLPP_TYPE_TRAIT_GENERATOR(is_having); - SQLPP_TYPE_TRAIT_GENERATOR(is_order_by); - SQLPP_TYPE_TRAIT_GENERATOR(is_limit); - SQLPP_TYPE_TRAIT_GENERATOR(is_offset); - SQLPP_TYPE_TRAIT_GENERATOR(is_using); - SQLPP_TYPE_TRAIT_GENERATOR(is_column_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column); - SQLPP_TYPE_TRAIT_GENERATOR(is_value_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_assignment); - SQLPP_TYPE_TRAIT_GENERATOR(is_update_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value); - SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order); + 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_TYPE_TRAIT_GENERATOR(requires_braces); - SQLPP_TYPE_TRAIT_GENERATOR(is_parameter); SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value); SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity); + template + using is_database = typename std::conditional::value, std::false_type, std::true_type>::type; + template class IsTag> using copy_type_trait = typename std::conditional::value, std::true_type, std::false_type>::type; + + namespace detail + { + template + struct value_type_of_impl + { + using type = typename T::_traits::_value_type; + }; + + template + struct required_table_of_impl + { + using type = typename T::_recursive_traits::_required_tables; + }; + + template + struct provided_table_of_impl + { + using type = typename T::_recursive_traits::_provided_tables; + }; + + template + struct extra_table_of_impl + { + using type = typename T::_recursive_traits::_extra_tables; + }; + + template + struct parameters_of_impl + { + using type = typename T::_recursive_traits::_parameters; + }; + + template + struct name_of_impl + { + using type = typename T::_name_t; + }; + + template + struct make_parameter_tuple_impl + { + using type = decltype(std::tuple_cat(std::declval()...)); + }; + + template + using make_parameter_tuple_t = typename make_parameter_tuple_impl::type; + } + template + using value_type_of = typename detail::value_type_of_impl::type; + + template + using required_tables_of = typename detail::required_table_of_impl::type; + + template + using provided_tables_of = typename detail::provided_table_of_impl::type; + + template + using extra_tables_of = typename detail::extra_table_of_impl::type; + + template + using parameters_of = typename detail::parameters_of_impl::type; + + template + using name_of = typename detail::name_of_impl::type; + + template + struct make_traits + { + using _value_type = ValueType; + using _tags = detail::make_type_set_t; + }; + template + struct make_recursive_traits + { + using _required_tables = detail::make_joined_set_t...>; + using _provided_tables = detail::make_joined_set_t...>; + using _extra_tables = detail::make_joined_set_t...>; + using _parameters = detail::make_parameter_tuple_t...>; + }; + } #endif diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 5865651a..215200d6 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -27,181 +27,90 @@ #ifndef SQLPP_UPDATE_H #define SQLPP_UPDATE_H +#include + #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include namespace sqlpp { - template - struct update_t; + struct update_name_t {}; - namespace detail + struct update_t: public statement_name_t { - template - struct update_policies_t + using _traits = make_traits; + struct _name_t {}; + + template + struct _result_methods_t { - using _database_t = Db; - using _table_t = Table; - using _update_list_t = UpdateList; - using _where_t = Where; + using _statement_t = typename Policies::_statement_t; - using _statement_t = update_t; + const _statement_t& _get_statement() const + { + return static_cast(*this); + } - struct _methods_t: - public _update_list_t::template _methods_t, - public _where_t::template _methods_t - {}; - - template - struct _policies_update_t + template + auto _run(Db& db) const -> decltype(db.update(this->_get_statement())) { - using type = update_t...>; - }; + _statement_t::_check_consistency(); - template - using _new_statement_t = typename _policies_update_t::type; + static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); + return db.update(_get_statement()); + } - using _known_tables = detail::make_joined_set_t; - - template - using _no_unknown_tables = detail::is_subset_of; + template + auto _prepare(Db& db) const + -> prepared_update_t + { + _statement_t::_check_consistency(); + return {{}, db.prepare_update(_get_statement())}; + } }; - } + }; - template - struct update_t: - public detail::update_policies_t::_methods_t + + template + struct serializer_t { - using _policies_t = typename detail::update_policies_t; - using _database_t = typename _policies_t::_database_t; - using _table_t = typename _policies_t::_table_t; - using _update_list_t = typename _policies_t::_update_list_t; - using _where_t = typename _policies_t::_where_t; + using T = update_name_t; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - - using _parameter_tuple_t = std::tuple; - using _parameter_list_t = typename make_parameter_list_t::type; - - static_assert(::sqlpp::detail::is_superset_of::value, "updated columns do not match the table"); - static_assert(::sqlpp::detail::is_superset_of::value, "where condition does not match updated table"); - - // Constructors - update_t() - {} - - template - update_t(Statement s, T t): - _table(detail::arg_selector<_table_t>::_(s._table, t)), - _update_list(detail::arg_selector<_update_list_t>::_(s._update_list, t)), - _where(detail::arg_selector<_where_t>::_(s._where, t)) - {} - - update_t(const update_t&) = default; - update_t(update_t&&) = default; - update_t& operator=(const update_t&) = default; - update_t& operator=(update_t&&) = default; - ~update_t() = default; - - // run and prepare - static constexpr size_t _get_static_no_of_parameters() + static Context& _(const T& t, Context& context) { - return _parameter_list_t::size::value; + context << "UPDATE "; + + return context; } - - size_t _get_no_of_parameters() const - { - return _parameter_list_t::size::value; - } - - template - struct is_table_subset_of_table - { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; - }; - - void _check_consistency() const - { - static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows"); - - static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables"); - static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables"); - } - - template - std::size_t _run(Database& db) const - { - _check_consistency(); - - static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); - return db.update(*this); - } - - template - auto _prepare(Database& db) const - -> prepared_update_t - { - _check_consistency(); - - return {{}, db.prepare_update(*this)}; - } - - _table_t _table; - _update_list_t _update_list; - _where_t _where; }; - namespace vendor - { - template - struct serializer_t> - { - using T = update_t; - - static Context& _(const T& t, Context& context) - { - context << "UPDATE "; - serialize(t._table, context); - serialize(t._update_list, context); - serialize(t._where, context); - return context; - } - }; - } - - template - using make_update_t = typename detail::update_policies_t::_statement_t; + template + using blank_update_t = statement_t + >; template constexpr auto update(Table table) - -> make_update_t> + -> decltype(blank_update_t().from(table)) { - return { update_t(), vendor::single_table_t{table} }; + return { blank_update_t().from(table) }; } template constexpr auto dynamic_update(const Database&, Table table) - -> make_update_t> + -> decltype(blank_update_t().from(table)) { - return { update_t(), vendor::single_table_t{table} }; + return { blank_update_t().from(table) }; } - } #endif diff --git a/include/sqlpp11/update_list.h b/include/sqlpp11/update_list.h new file mode 100644 index 00000000..903bac66 --- /dev/null +++ b/include/sqlpp11/update_list.h @@ -0,0 +1,223 @@ +/* + * 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_UPDATE_LIST_H +#define SQLPP_UPDATE_LIST_H + +#include +#include +#include +#include + +namespace sqlpp +{ + // UPDATE ASSIGNMENTS DATA + template + struct update_list_data_t + { + update_list_data_t(Assignments... assignments): + _assignments(assignments...) + {} + + update_list_data_t(const update_list_data_t&) = default; + update_list_data_t(update_list_data_t&&) = default; + update_list_data_t& operator=(const update_list_data_t&) = default; + update_list_data_t& operator=(update_list_data_t&&) = default; + ~update_list_data_t() = default; + + std::tuple _assignments; + interpretable_list_t _dynamic_assignments; + }; + + // UPDATE ASSIGNMENTS + template + struct update_list_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + using _is_dynamic = is_database; + + // Data + using _data_t = update_list_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Assignment assignment) + { + add(assignment); + } + + template + void add(Assignment assignment) + { + static_assert(_is_dynamic::value, "add must not be called for static from()"); + static_assert(is_assignment_t::value, "invalid assignment argument in add()"); + using _assigned_columns = detail::make_type_set_t; + static_assert(not detail::is_element_of::value, "Must not assign value to column twice"); + static_assert(sqlpp::detail::not_t::value, "add() argument must not be updated"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "assignment uses tables unknown to this statement in add()"); + + using ok = ::sqlpp::detail::all_t< + _is_dynamic::value, + is_assignment_t::value>; + + _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Assignment assignment, const std::true_type&) + { + return _data._dynamic_assignments.emplace_back(assignment); + } + + template + void _add_impl(Assignment assignment, const std::false_type&); + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = update_list_data_t; + + _impl_t assignments; + _impl_t& operator()() { return assignments; } + const _impl_t& operator()() const { return assignments; } + + template + static auto _get_member(T t) -> decltype(t.assignments) + { + return t.assignments; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + struct no_update_list_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_assignments; + _impl_t& operator()() { return no_assignments; } + const _impl_t& operator()() const { return no_assignments; } + + template + static auto _get_member(T t) -> decltype(t.no_assignments) + { + return t.no_assignments; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto set(Assignments... assignments) + -> _new_statement_t> + { + static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); + return _set_impl(assignments...); + } + + template + auto dynamic_set(Assignments... assignments) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_set() must not be called in a static statement"); + return _set_impl<_database_t>(assignments...); + } + + private: + template + auto _set_impl(Assignments... assignments) + -> _new_statement_t> + { + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); + static_assert(::sqlpp::detail::none_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...>::type; + static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from more than one table"); + + return { *static_cast(this), update_list_data_t{assignments...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = update_list_data_t; + + static Context& _(const T& t, Context& context) + { + context << " SET "; + interpret_tuple(t._assignments, ",", context); + if (sizeof...(Assignments) and not t._dynamic_assignments.empty()) + context << ','; + interpret_list(t._dynamic_assignments, ',', context); + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/using.h b/include/sqlpp11/using.h new file mode 100644 index 00000000..0214851b --- /dev/null +++ b/include/sqlpp11/using.h @@ -0,0 +1,207 @@ +/* + * 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_USING_H +#define SQLPP_USING_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // USING DATA + template + struct using_data_t + { + using_data_t(Tables... tables): + _tables(tables...) + {} + + using_data_t(const using_data_t&) = default; + using_data_t(using_data_t&&) = default; + using_data_t& operator=(const using_data_t&) = default; + using_data_t& operator=(using_data_t&&) = default; + ~using_data_t() = default; + + std::tuple _tables; + interpretable_list_t _dynamic_tables; + }; + + // USING + template + struct using_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; + + static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in using()"); + + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an table in using()"); + + // Data + using _data_t = using_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add(Table table) + { + static_assert(_is_dynamic::value, "add must not be called for static using()"); + static_assert(is_table_t
::value, "invalid table argument in add()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t
::value>; + + _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Table table, const std::true_type&) + { + return _data._dynamic_tables.emplace_back(table); + } + + template + void _add_impl(Table table, const std::false_type&); + + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = using_data_t; + + _impl_t using_; + _impl_t& operator()() { return using_; } + const _impl_t& operator()() const { return using_; } + + template + static auto _get_member(T t) -> decltype(t.using_) + { + return t.using_; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + // NO USING YET + struct no_using_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_using; + _impl_t& operator()() { return no_using; } + const _impl_t& operator()() const { return no_using; } + + template + static auto _get_member(T t) -> decltype(t.no_using) + { + return t.no_using; + } + }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() {} + + template + auto using_(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), using_data_t{args...} }; + } + + template + auto dynamic_using(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); + return { *static_cast(this), using_data_t<_database_t, Args...>{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = using_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Tables) == 0 and t._dynamic_tables.empty()) + return context; + context << " USING "; + interpret_tuple(t._tables, ',', context); + if (sizeof...(Tables) and not t._dynamic_tables.empty()) + context << ','; + interpret_list(t._dynamic_tables, ',', context); + return context; + } + }; +} + +#endif diff --git a/include/sqlpp11/vendor/value_type.h b/include/sqlpp11/value_type.h similarity index 90% rename from include/sqlpp11/vendor/value_type.h rename to include/sqlpp11/value_type.h index 06738c36..2fa3bee1 100644 --- a/include/sqlpp11/vendor/value_type.h +++ b/include/sqlpp11/value_type.h @@ -28,14 +28,11 @@ #define SQLPP_VALUE_TYPE_H #include -#include +#include namespace sqlpp { - namespace vendor - { - template - using value_type_t = typename wrap_operand::type::_value_type; - } + template + using value_type_t = value_type_of>; } #endif diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h deleted file mode 100644 index d8f8ac6b..00000000 --- a/include/sqlpp11/vendor/assignment.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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_ASSIGNMENT_H -#define SQLPP_ASSIGNMENT_H - -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct is_trivial_t - { - static constexpr bool _(const T&) - { - return false; - } - }; - - template - struct is_trivial_t::value, void>::type> - { - static bool _(const T& t) - { - return t._is_trivial(); - } - }; - - template - bool is_trivial(const T& t) - { - return is_trivial_t::_(t); - } - - template - struct assignment_t - { - using _is_assignment = std::true_type; - using _column_t = Lhs; - using value_type = Rhs; - using _parameter_tuple_t = std::tuple<_column_t, Rhs>; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same::value, "column must not be null"); - - assignment_t(_column_t lhs, value_type 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_type _rhs; - }; - - template - struct serializer_t> - { - using T = assignment_t; - - static Context& _(const T& t, Context& context) - { - if ((trivial_value_is_null_t::value - and is_trivial_t::_(t._rhs)) - or (std::is_same::value)) - { - serialize(simple_column(t._lhs), context); - context << "=NULL"; - } - else - { - serialize(simple_column(t._lhs), context); - context << "="; - serialize(t._rhs, context); - } - return context; - } - }; - - template - struct assignment_t> - { - using _is_assignment = std::true_type; - using _column_t = Lhs; - using value_type = tvin_t; - using _parameter_tuple_t = std::tuple<_column_t, Rhs>; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - static_assert(can_be_null_t<_column_t>::value, "column cannot be null"); - - assignment_t(_column_t lhs, value_type 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_type _rhs; - }; - - template - struct serializer_t>> - { - using T = assignment_t>; - - 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 diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h deleted file mode 100644 index e156a84b..00000000 --- a/include/sqlpp11/vendor/expression.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * 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_EXPRESSION_H -#define SQLPP_EXPRESSION_H - -#include -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> - { - using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - binary_expression_t(Lhs lhs, Rhs rhs): - _lhs(lhs), - _rhs(rhs) - {} - - binary_expression_t(const binary_expression_t&) = default; - binary_expression_t(binary_expression_t&&) = default; - binary_expression_t& operator=(const binary_expression_t&) = default; - binary_expression_t& operator=(binary_expression_t&&) = default; - ~binary_expression_t() = default; - - Lhs _lhs; - maybe_tvin_t _rhs; - }; - - template - struct serializer_t> - { - using T = equal_to_t; - - static Context& _(const T& t, Context& context) - { - context << "("; - serialize(t._lhs, context); - if (t._rhs._is_trivial()) - { - context << " IS NULL"; - } - else - { - context << "="; - serialize(t._rhs, context); - } - context << ")"; - return context; - } - }; - - template - struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> - { - using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - binary_expression_t(Lhs lhs, Rhs rhs): - _lhs(lhs), - _rhs(rhs) - {} - - binary_expression_t(const binary_expression_t&) = default; - binary_expression_t(binary_expression_t&&) = default; - binary_expression_t& operator=(const binary_expression_t&) = default; - binary_expression_t& operator=(binary_expression_t&&) = default; - ~binary_expression_t() = default; - - Lhs _lhs; - maybe_tvin_t _rhs; - }; - - template - struct serializer_t> - { - using T = not_equal_to_t; - - static Context& _(const T& t, Context& context) - { - context << "("; - serialize(t._lhs, context); - if (t._rhs._is_trivial()) - { - context << " IS NOT NULL"; - } - else - { - context << "!="; - serialize(t._rhs, context); - } - context << ")"; - return context; - } - }; - - template - struct unary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> - { - using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _table_set = typename Rhs::_table_set; - - unary_expression_t(Rhs rhs): - _rhs(rhs) - {} - - unary_expression_t(const unary_expression_t&) = default; - unary_expression_t(unary_expression_t&&) = default; - unary_expression_t& operator=(const unary_expression_t&) = default; - unary_expression_t& operator=(unary_expression_t&&) = default; - ~unary_expression_t() = default; - - Rhs _rhs; - }; - - template - struct serializer_t> - { - using T = logical_not_t; - - static Context& _(const T& t, Context& context) - { - context << "("; - context << "NOT "; - serialize(t._lhs, context); - context << ")"; - return context; - } - }; - - template - struct binary_expression_t: public O::_value_type::template expression_operators> - { - using _lhs_t = Lhs; - using _rhs_t = Rhs; - using _value_type = typename O::_value_type; - using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - binary_expression_t(_lhs_t lhs, _rhs_t rhs): - _lhs(lhs), - _rhs(rhs) - {} - - binary_expression_t(const binary_expression_t&) = default; - binary_expression_t(binary_expression_t&&) = default; - binary_expression_t& operator=(const binary_expression_t&) = default; - binary_expression_t& operator=(binary_expression_t&&) = default; - ~binary_expression_t() = default; - - _lhs_t _lhs; - _rhs_t _rhs; - }; - - template - struct serializer_t> - { - using T = binary_expression_t; - - static Context& _(const T& t, Context& context) - { - context << "("; - serialize(t._lhs, context); - context << O::_name; - serialize(t._rhs, context); - context << ")"; - return context; - } - }; - - template - struct unary_expression_t: public O::_value_type::template expression_operators> - { - using _value_type = typename O::_value_type; - using _parameter_tuple_t = std::tuple; - using _table_set = typename Rhs::_table_set; - - unary_expression_t(Rhs rhs): - _rhs(rhs) - {} - - unary_expression_t(const unary_expression_t&) = default; - unary_expression_t(unary_expression_t&&) = default; - unary_expression_t& operator=(const unary_expression_t&) = default; - unary_expression_t& operator=(unary_expression_t&&) = default; - ~unary_expression_t() = default; - - Rhs _rhs; - }; - - template - struct serializer_t> - { - using T = unary_expression_t; - - static Context& _(const T& t, Context& context) - { - context << "("; - context << O::_name; - serialize(t._rhs, context); - context << ")"; - return context; - } - }; - } -} - -#endif diff --git a/include/sqlpp11/vendor/expression_fwd.h b/include/sqlpp11/vendor/expression_fwd.h deleted file mode 100644 index 66b446c5..00000000 --- a/include/sqlpp11/vendor/expression_fwd.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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_EXPRESSION_FWD_H -#define SQLPP_EXPRESSION_FWD_H - -namespace sqlpp -{ - namespace vendor - { - namespace tag - { - struct less - { - using _value_type = ::sqlpp::detail::boolean; - static constexpr const char* _name = "<"; - }; - - struct less_equal - { - using _value_type = ::sqlpp::detail::boolean; - static constexpr const char* _name = "<="; - }; - - struct equal_to - { - using _value_type = ::sqlpp::detail::boolean; - }; - - struct not_equal_to - { - using _value_type = ::sqlpp::detail::boolean; - }; - - struct greater_equal - { - using _value_type = ::sqlpp::detail::boolean; - static constexpr const char* _name = ">="; - }; - - struct greater - { - using _value_type = ::sqlpp::detail::boolean; - static constexpr const char* _name = ">"; - }; - - struct logical_or - { - using _value_type = ::sqlpp::detail::boolean; - static constexpr const char* _name = " OR "; - }; - - struct logical_and - { - using _value_type = ::sqlpp::detail::boolean; - static constexpr const char* _name = " AND "; - }; - - struct logical_not - { - using _value_type = ::sqlpp::detail::boolean; - }; - - template - struct plus - { - using _value_type = ValueType; - static constexpr const char* _name = "+"; - }; - - template - struct minus - { - using _value_type = ValueType; - static constexpr const char* _name = "-"; - }; - - template - struct multiplies - { - using _value_type = ValueType; - static constexpr const char* _name = "*"; - }; - - struct divides - { - using _value_type = ::sqlpp::detail::floating_point; - static constexpr const char* _name = "/"; - }; - - struct modulus - { - using _value_type = ::sqlpp::detail::integral; - static constexpr const char* _name = "%"; - }; - - template - struct unary_minus - { - using _value_type = ValueType; - static constexpr const char* _name = "-"; - }; - - template - struct unary_plus - { - using _value_type = ValueType; - static constexpr const char* _name = "+"; - }; - } - - template - struct binary_expression_t; - - template - struct unary_expression_t; - - template - using less_than_t = binary_expression_t; - - template - using less_equal_t = binary_expression_t; - - template - using equal_to_t = binary_expression_t; - - template - using not_equal_to_t = binary_expression_t; - - template - using greater_than_t = binary_expression_t; - - template - using greater_equal_t = binary_expression_t; - - template - using logical_and_t = binary_expression_t; - - template - using logical_or_t = binary_expression_t; - - template - using plus_t = binary_expression_t, Rhs>; - - template - using minus_t = binary_expression_t, Rhs>; - - template - using multiplies_t = binary_expression_t, Rhs>; - - template - using divides_t = binary_expression_t; - - template - using modulus_t = binary_expression_t; - - template - using logical_not_t = unary_expression_t; - - template - using unary_plus_t = unary_expression_t, Rhs>; - - template - using unary_minus_t = unary_expression_t, Rhs>; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/extra_tables.h b/include/sqlpp11/vendor/extra_tables.h deleted file mode 100644 index c9fceb77..00000000 --- a/include/sqlpp11/vendor/extra_tables.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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_EXTRA_TABLES_H -#define SQLPP_EXTRA_TABLES_H - -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // EXTRA_TABLES - template - struct extra_tables_t - { - using _is_extra_tables = std::true_type; - - static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in extra_tables()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a table or join in extra_tables()"); - - using _table_set = ::sqlpp::detail::make_joined_set_t; - - - extra_tables_t() - {} - - extra_tables_t(const extra_tables_t&) = default; - extra_tables_t(extra_tables_t&&) = default; - extra_tables_t& operator=(const extra_tables_t&) = default; - extra_tables_t& operator=(extra_tables_t&&) = default; - ~extra_tables_t() = default; - - template - struct _methods_t - { - }; - }; - - struct no_extra_tables_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto extra_tables(Args...) - -> _new_statement_t> - { - return { *static_cast(this), extra_tables_t{} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = extra_tables_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - template - struct serializer_t - { - using T = no_extra_tables_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h deleted file mode 100644 index ca9c1d8f..00000000 --- a/include/sqlpp11/vendor/from.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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_FROM_H -#define SQLPP_FROM_H - -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // FROM - template - struct from_t - { - using _is_from = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - - static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()"); - - // FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in from()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a table or join in from()"); - - using _table_set = ::sqlpp::detail::make_joined_set_t; - - - from_t(Tables... tables): - _tables(tables...) - {} - - from_t(const from_t&) = default; - from_t(from_t&&) = default; - from_t& operator=(const from_t&) = default; - from_t& operator=(from_t&&) = default; - ~from_t() = default; - - template - struct _methods_t - { - template - void add_from(Table table) - { - static_assert(_is_dynamic::value, "add_from must not be called for static from()"); - static_assert(is_table_t
::value, "invalid table argument in add_from()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t
::value>; - - _add_from_impl(table, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_from_impl(Table table, const std::true_type&) - { - return static_cast(this)->_from._dynamic_tables.emplace_back(table); - } - - template - void _add_from_impl(Table table, const std::false_type&); - }; - - std::tuple _tables; - vendor::interpretable_list_t _dynamic_tables; - }; - - struct no_from_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto from(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), from_t{args...} }; - } - - template - auto dynamic_from(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); - return { *static_cast(this), vendor::from_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = from_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Tables) == 0 and t._dynamic_tables.empty()) - return context; - context << " FROM "; - interpret_tuple(t._tables, ',', context); - if (sizeof...(Tables) and not t._dynamic_tables.empty()) - context << ','; - interpret_list(t._dynamic_tables, ',', context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_from_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h deleted file mode 100644 index 3bbc7049..00000000 --- a/include/sqlpp11/vendor/group_by.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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_GROUP_BY_H -#define SQLPP_GROUP_BY_H - -#include -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // GROUP BY - template - struct group_by_t - { - using _is_group_by = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in group_by()"); - - group_by_t(Expressions... expressions): - _expressions(expressions...) - {} - - group_by_t(const group_by_t&) = default; - group_by_t(group_by_t&&) = default; - group_by_t& operator=(const group_by_t&) = default; - group_by_t& operator=(group_by_t&&) = default; - ~group_by_t() = default; - - template - struct _methods_t - { - template - void add_group_by_ntc(Expression expression) - { - add_group_by(expression); - } - - template - void add_group_by(Expression expression) - { - static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by"); - static_assert(is_expression_t::value, "invalid expression argument in add_group_by()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_group_by()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; - - _add_group_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_group_by_impl(Expression expression, const std::true_type&) - { - return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); - } - - template - void _add_group_by_impl(Expression expression, const std::false_type&); - }; - - const group_by_t& _group_by() const { return *this; } - _parameter_tuple_t _expressions; - vendor::interpretable_list_t _dynamic_expressions; - }; - - struct no_group_by_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto group_by(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), group_by_t{args...} }; - } - - template - auto dynamic_group_by(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); - return { *static_cast(this), vendor::group_by_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = group_by_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) - return context; - context << " GROUP BY "; - interpret_tuple(t._expressions, ',', context); - if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) - context << ','; - interpret_list(t._dynamic_expressions, ',', context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_group_by_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h deleted file mode 100644 index 51447187..00000000 --- a/include/sqlpp11/vendor/having.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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_HAVING_H -#define SQLPP_HAVING_H - -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // HAVING - template - struct having_t - { - using _is_having = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in having()"); - - using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - having_t(Expressions... expressions): - _expressions(expressions...) - {} - - having_t(const having_t&) = default; - having_t(having_t&&) = default; - having_t& operator=(const having_t&) = default; - having_t& operator=(having_t&&) = default; - ~having_t() = default; - - template - struct _methods_t - { - template - void add_having_ntc(Expression expression) - { - add_having(expression); - } - - template - void add_having(Expression expression) - { - static_assert(_is_dynamic::value, "add_having must not be called for static having"); - static_assert(is_expression_t::value, "invalid expression argument in add_having()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_having()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; - - _add_having_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_having_impl(Expression expression, const std::true_type&) - { - return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); - } - - template - void _add_having_impl(Expression expression, const std::false_type&); - }; - - _parameter_tuple_t _expressions; - vendor::interpretable_list_t _dynamic_expressions; - }; - - struct no_having_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto having(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), having_t{args...} }; - } - - template - auto dynamic_having(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); - return { *static_cast(this), vendor::having_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = having_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) - return context; - context << " HAVING "; - interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) - context << " AND "; - interpret_list(t._dynamic_expressions, " AND ", context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_having_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/insert_value.h b/include/sqlpp11/vendor/insert_value.h deleted file mode 100644 index dfcc97ba..00000000 --- a/include/sqlpp11/vendor/insert_value.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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_INSERT_VALUE_H -#define SQLPP_INSERT_VALUE_H - -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - namespace detail - { - template - struct type_if - { - using type = Type; - using _table_set = typename Type::_table_set; - }; - - template - struct type_if - { - struct type - { - using _table_set = sqlpp::detail::type_set<>; - }; - }; - } - - template - struct insert_value_t - { - using _is_insert_value = std::true_type; - using _pure_value_t = typename Column::_value_type::_cpp_value_type; - using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type; - using _tvin_t = typename detail::type_if, can_be_null_t::value>::type; // static asserts and SFINAE do not work together - using _null_t = typename detail::type_if::value>::type; // static asserts and SFINAE do not work together - - insert_value_t(assignment_t assignment): - _is_null(false), - _is_default(false), - _value(assignment._rhs) - {} - - insert_value_t(assignment_t assignment): - _is_null(assignment._rhs._is_trivial()), - _is_default(false), - _value(assignment._rhs._value) - {} - - insert_value_t(const assignment_t&): - _is_null(true), - _is_default(false), - _value() - {} - - insert_value_t(const assignment_t&): - _is_null(false), - _is_default(true), - _value() - {} - - insert_value_t(const insert_value_t&) = default; - insert_value_t(insert_value_t&&) = default; - insert_value_t& operator=(const insert_value_t&) = default; - insert_value_t& operator=(insert_value_t&&) = default; - ~insert_value_t() = default; - - bool _is_null; - bool _is_default; - _wrapped_value_t _value; - }; - - template - struct serializer_t> - { - using T = insert_value_t; - - static Context& _(const T& t, Context& context) - { - if (t._is_null) - context << "NULL"; - else if (t._is_default) - context << "DEFAULT"; - else - serialize(t._value, context); - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h deleted file mode 100644 index 8b70f9db..00000000 --- a/include/sqlpp11/vendor/insert_value_list.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * 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_INSERT_VALUE_LIST_H -#define SQLPP_INSERT_VALUE_LIST_H - -#include -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // COLUMN AND VALUE LIST - struct insert_default_values_t - { - using _table_set = ::sqlpp::detail::type_set<>; - using _is_dynamic = std::false_type; - - template - struct _methods_t - {}; - }; - - template - struct insert_list_t - { - using _is_insert_list = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - template class Target> - using copy_assignments_t = Target; // FIXME: Nice idea to copy variadic template arguments? - template class Target, template class Wrap> - using copy_wrapped_assignments_t = Target...>; - - static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - - static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); - - static_assert(sqlpp::detail::none_t::value...>::value, "at least one assignment is prohibited by its column definition in set()"); - - using _column_table_set = typename ::sqlpp::detail::make_joined_set::type; - using _value_table_set = typename ::sqlpp::detail::make_joined_set::type; - using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type; - static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns"); - static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables"); - - insert_list_t(Assignments... assignment): - _assignments(assignment...), - _columns({assignment._lhs}...), - _values(assignment._rhs...) - {} - - insert_list_t(const insert_list_t&) = default; - insert_list_t(insert_list_t&&) = default; - insert_list_t& operator=(const insert_list_t&) = default; - insert_list_t& operator=(insert_list_t&&) = default; - ~insert_list_t() = default; - - template - struct _methods_t - { - template - void add_set(Assignment assignment) - { - static_assert(_is_dynamic::value, "add_set must not be called for static from()"); - static_assert(is_assignment_t::value, "add_set() arguments require to be assigments"); - static_assert(not must_not_insert_t::value, "add_set() argument must not be used in insert"); - using _column_table_set = typename Assignment::_column_t::_table_set; - using _value_table_set = typename Assignment::value_type::_table_set; - static_assert(::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, "add_set() contains a column from a foreign table"); - static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value, "add_set() contains a value from a foreign table"); - - using ok = ::sqlpp::detail::all_t< - _is_dynamic::value, - is_assignment_t::value, - not must_not_insert_t::value, - ::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, - ::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value>; - - _add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_set_impl(Assignment assignment, const std::true_type&) - { - static_cast(this)->_insert_value_list._dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); - static_cast(this)->_insert_value_list._dynamic_values.emplace_back(assignment._rhs); - } - - template - void _add_set_impl(Assignment assignment, const std::false_type&); - }; - - - - std::tuple...> _columns; - std::tuple _values; - std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) - typename vendor::interpretable_list_t _dynamic_columns; - typename vendor::interpretable_list_t _dynamic_values; - }; - - template - struct column_list_t - { - using _is_column_list = std::true_type; - using _parameter_tuple_t = std::tuple; - - static_assert(sizeof...(Columns), "at least one column required in columns()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a column in columns()"); - - static_assert(::sqlpp::detail::none_t::value...>::value, "at least one column argument has a must_not_insert flag in its definition"); - - using _value_tuple_t = std::tuple...>; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - static_assert(_table_set::size::value == 1, "columns from multiple tables in columns()"); - - column_list_t(Columns... columns): - _columns(simple_column_t{columns}...) - {} - - column_list_t(const column_list_t&) = default; - column_list_t(column_list_t&&) = default; - column_list_t& operator=(const column_list_t&) = default; - column_list_t& operator=(column_list_t&&) = default; - ~column_list_t() = default; - - template - struct _methods_t - { - template - void add_values(Assignments... assignments) - { - static_assert(::sqlpp::detail::all_t::value...>::value, "add_values() arguments have to be assignments"); - using _arg_value_tuple = std::tuple...>; - 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"); - - using ok = ::sqlpp::detail::all_t< - ::sqlpp::detail::all_t::value...>::value, - _args_correct::value>; - - _add_values_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_values_impl(const std::true_type&, Assignments... assignments) - { - return static_cast(this)->_insert_value_list._insert_values.emplace_back(vendor::insert_value_t{assignments}...); - } - - template - void _add_values_impl(const std::false_type&, Assignments... assignments); - }; - - bool empty() const - { - return _insert_values.empty(); - } - - std::tuple...> _columns; - std::vector<_value_tuple_t> _insert_values; - - }; - - struct no_insert_value_list_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - auto default_values() - -> _new_statement_t - { - return { *static_cast(this), insert_default_values_t{} }; - } - - template - auto columns(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), column_list_t{args...} }; - } - - template - auto set(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), insert_list_t{args...} }; - } - - template - auto dynamic_set(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); - return { *static_cast(this), vendor::insert_list_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t - { - using T = insert_default_values_t; - - static Context& _(const T& t, Context& context) - { - context << " DEFAULT VALUES"; - return context; - } - }; - - template - struct serializer_t> - { - using T = column_list_t; - - static Context& _(const T& t, Context& context) - { - context << " ("; - interpret_tuple(t._columns, ",", context); - context << ")"; - context << " VALUES "; - bool first = true; - for (const auto& row : t._insert_values) - { - if (not first) - context << ','; - else - first = false; - context << '('; - interpret_tuple(row, ",", context); - context << ')'; - } - - return context; - } - }; - - template - struct serializer_t> - { - using T = insert_list_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Assignments) + t._dynamic_columns.size() == 0) - { - serialize(insert_default_values_t(), context); - } - else - { - context << " ("; - interpret_tuple(t._columns, ",", context); - if (sizeof...(Assignments) and not t._dynamic_columns.empty()) - context << ','; - interpret_list(t._dynamic_columns, ',', context); - context << ") VALUES("; - interpret_tuple(t._values, ",", context); - if (sizeof...(Assignments) and not t._dynamic_values.empty()) - context << ','; - interpret_list(t._dynamic_values, ',', context); - context << ")"; - } - return context; - } - }; - - template - struct serializer_t - { - using T = no_insert_value_list_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/interpretable.h b/include/sqlpp11/vendor/interpretable.h deleted file mode 100644 index a190f04e..00000000 --- a/include/sqlpp11/vendor/interpretable.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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_INTERPRETABLE_H -#define SQLPP_INTERPRETABLE_H - -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct interpretable_t - { - using _serializer_context_t = typename Db::_serializer_context_t; - using _interpreter_context_t = typename Db::_interpreter_context_t; - - template - interpretable_t(T t): - _impl(std::make_shared<_impl_t>(t)) - {} - - interpretable_t(const interpretable_t&) = default; - interpretable_t(interpretable_t&&) = default; - interpretable_t& operator=(const interpretable_t&) = default; - interpretable_t& operator=(interpretable_t&&) = default; - ~interpretable_t() = default; - - sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const - { - return _impl->serialize(context); - } - - // This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same - template - auto serialize(Context& context) const - -> typename std::enable_if::value - and not std::is_same::value, Context&>::type - { - return _impl->db_serialize(context); - } - - _interpreter_context_t& interpret(_interpreter_context_t& context) const - { - return _impl->interpret(context); - } - - private: - struct _impl_base - { - virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0; - virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0; - virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0; - }; - - template - struct _impl_t: public _impl_base - { - static_assert(not make_parameter_list_t::type::size::value, "parameters not supported in dynamic statement parts"); - _impl_t(T t): - _t(t) - {} - - sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const - { - sqlpp::serialize(_t, context); - return context; - } - - _serializer_context_t& db_serialize(_serializer_context_t& context) const - { - Db::_serialize_interpretable(_t, context); - return context; - } - - _interpreter_context_t& interpret(_interpreter_context_t& context) const - { - Db::_interpret_interpretable(_t, context); - return context; - } - - T _t; - }; - - std::shared_ptr _impl; - }; - - template - struct serializer_t> - { - using T = interpretable_t; - - static Context& _(const T& t, Context& context) - { - t.serialize(context); - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h deleted file mode 100644 index 2d77760a..00000000 --- a/include/sqlpp11/vendor/limit.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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_LIMIT_H -#define SQLPP_LIMIT_H - -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // LIMIT - template - struct limit_t - { - using _is_limit = std::true_type; - static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - // FIXME: Is this really always empty? - using _table_set = ::sqlpp::detail::type_set<>; - - limit_t(Limit value): - _value(value) - {} - - limit_t(const limit_t&) = default; - limit_t(limit_t&&) = default; - limit_t& operator=(const limit_t&) = default; - limit_t& operator=(limit_t&&) = default; - ~limit_t() = default; - - template - struct _methods_t - { - }; - - Limit _value; - }; - - template - struct dynamic_limit_t - { - using _is_limit = std::true_type; - using _is_dynamic = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - dynamic_limit_t(): - _value(noop()) - { - } - - template - dynamic_limit_t(Limit value): - _initialized(true), - _value(typename wrap_operand::type(value)) - { - } - - dynamic_limit_t(const dynamic_limit_t&) = default; - dynamic_limit_t(dynamic_limit_t&&) = default; - dynamic_limit_t& operator=(const dynamic_limit_t&) = default; - dynamic_limit_t& operator=(dynamic_limit_t&&) = default; - ~dynamic_limit_t() = default; - - template - struct _methods_t - { - template - void set_limit(Limit value) - { - // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL - using arg_t = typename wrap_operand::type; - static_cast(this)->_limit._value = arg_t{value}; - static_cast(this)->_limit._initialized = true; - } - }; - - bool _initialized = false; - interpretable_t _value; - }; - - struct no_limit_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto limit(Arg arg) - -> _new_statement_t::type>> - { - return { *static_cast(this), limit_t::type>{{arg}} }; - } - - auto dynamic_limit() - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); - return { *static_cast(this), dynamic_limit_t<_database_t>{} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = dynamic_limit_t; - - static Context& _(const T& t, Context& context) - { - if (t._initialized) - { - context << " LIMIT "; - serialize(t._value, context); - } - return context; - } - }; - - template - struct serializer_t> - { - using T = limit_t; - - static Context& _(const T& t, Context& context) - { - context << " LIMIT "; - serialize(t._value, context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_limit_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/named_interpretable.h b/include/sqlpp11/vendor/named_interpretable.h deleted file mode 100644 index 08e4ed68..00000000 --- a/include/sqlpp11/vendor/named_interpretable.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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_NAMED_SERIALIZABLE_H -#define SQLPP_NAMED_SERIALIZABLE_H - -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct named_interpretable_t - { - using _serializer_context_t = typename Db::_serializer_context_t; - using _interpreter_context_t = typename Db::_interpreter_context_t; - - template - named_interpretable_t(T t): - _impl(std::make_shared<_impl_t>(t)) - {} - - named_interpretable_t(const named_interpretable_t&) = default; - named_interpretable_t(named_interpretable_t&&) = default; - named_interpretable_t& operator=(const named_interpretable_t&) = default; - named_interpretable_t& operator=(named_interpretable_t&&) = default; - ~named_interpretable_t() = default; - - sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const - { - return _impl->serialize(context); - } - - // This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same - template - auto serialize(Context& context) const - -> typename std::enable_if::value - and not std::is_same::value, Context&>::type - { - return _impl->db_serialize(context); - } - - _interpreter_context_t& interpret(_interpreter_context_t& context) const - { - return _impl->interpret(context); - } - - std::string _get_name() const - { - _impl->_get_name(); - } - - private: - struct _impl_base - { - virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0; - virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0; - virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0; - virtual std::string _get_name() const = 0; - }; - - template - struct _impl_t: public _impl_base - { - static_assert(not make_parameter_list_t::type::size::value, "parameters not supported in dynamic statement parts"); - _impl_t(T t): - _t(t) - {} - - sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const - { - sqlpp::serialize(_t, context); - return context; - } - - _serializer_context_t& db_serialize(_serializer_context_t& context) const - { - Db::_serialize_interpretable(_t, context); - return context; - } - - _interpreter_context_t& interpret(_interpreter_context_t& context) const - { - Db::_interpret_interpretable(_t, context); - return context; - } - - std::string _get_name() const - { - return T::_name_t::_get_name(); - } - - T _t; - }; - - std::shared_ptr _impl; - }; - - template - struct serializer_t> - { - using T = named_interpretable_t; - - static Context& _(const T& t, Context& context) - { - t.serialize(context); - return context; - } - }; - } - -} - -#endif diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h deleted file mode 100644 index c8611ce0..00000000 --- a/include/sqlpp11/vendor/offset.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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_OFFSET_H -#define SQLPP_OFFSET_H - -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // OFFSET - template - struct offset_t - { - using _is_offset = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); - - offset_t(Offset value): - _value(value) - {} - - offset_t(const offset_t&) = default; - offset_t(offset_t&&) = default; - offset_t& operator=(const offset_t&) = default; - offset_t& operator=(offset_t&&) = default; - ~offset_t() = default; - - template - struct _methods_t - { - }; - - Offset _value; - }; - - template - struct dynamic_offset_t - { - using _is_offset = std::true_type; - using _is_dynamic = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - dynamic_offset_t(): - _value(noop()) - { - } - - template - dynamic_offset_t(Offset value): - _initialized(true), - _value(typename wrap_operand::type(value)) - { - } - - dynamic_offset_t(const dynamic_offset_t&) = default; - dynamic_offset_t(dynamic_offset_t&&) = default; - dynamic_offset_t& operator=(const dynamic_offset_t&) = default; - dynamic_offset_t& operator=(dynamic_offset_t&&) = default; - ~dynamic_offset_t() = default; - - template - struct _methods_t - { - template - void set_offset(Offset value) - { - // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL - using arg_t = typename wrap_operand::type; - static_cast(this)->_offset._value = arg_t{value}; - static_cast(this)->_offset._initialized = true; - } - }; - - bool _initialized = false; - interpretable_t _value; - }; - - struct no_offset_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto offset(Arg arg) - -> _new_statement_t::type>> - { - return { *static_cast(this), offset_t::type>{{arg}} }; - } - - auto dynamic_offset() - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); - return { *static_cast(this), dynamic_offset_t<_database_t>{} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = offset_t; - - static Context& _(const T& t, Context& context) - { - context << " OFFSET "; - serialize(t._value, context); - return context; - } - }; - - template - struct serializer_t> - { - using T = dynamic_offset_t; - - static Context& _(const T& t, Context& context) - { - if (t._initialized) - { - context << " OFFSET "; - serialize(t._value, context); - } - return context; - } - }; - - template - struct serializer_t - { - using T = no_offset_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - } -} - -#endif diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h deleted file mode 100644 index 724239b0..00000000 --- a/include/sqlpp11/vendor/order_by.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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_ORDER_BY_H -#define SQLPP_ORDER_BY_H - -#include -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct order_by_t - { - using _is_order_by = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a sort order expression in order_by()"); - - order_by_t(Expressions... expressions): - _expressions(expressions...) - {} - - order_by_t(const order_by_t&) = default; - order_by_t(order_by_t&&) = default; - order_by_t& operator=(const order_by_t&) = default; - order_by_t& operator=(order_by_t&&) = default; - ~order_by_t() = default; - - template - struct _methods_t - { - template - void add_order_by_ntc(Expression expression) - { - add_order_by(expression); - } - - template - void add_order_by(Expression expression) - { - static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by"); - static_assert(is_sort_order_t::value, "invalid expression argument in add_order_by()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_order_by()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_sort_order_t::value>; - - _add_order_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_order_by_impl(Expression expression, const std::true_type&) - { - return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); - } - - template - void _add_order_by_impl(Expression expression, const std::false_type&); - }; - - _parameter_tuple_t _expressions; - vendor::interpretable_list_t _dynamic_expressions; - }; - - struct no_order_by_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto order_by(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), order_by_t{args...} }; - } - - template - auto dynamic_order_by(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); - return { *static_cast(this), vendor::order_by_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = order_by_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) - return context; - context << " ORDER BY "; - interpret_tuple(t._expressions, ',', context); - if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) - context << ','; - interpret_list(t._dynamic_expressions, ',', context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_order_by_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h deleted file mode 100644 index 5c06710f..00000000 --- a/include/sqlpp11/vendor/select_column_list.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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_SELECT_COLUMN_LIST_H -#define SQLPP_SELECT_COLUMN_LIST_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace detail - { - template - struct get_first_argument_if_unique - { - using _value_type = no_value_t; - struct _name_t {}; - }; - - template - struct get_first_argument_if_unique - { - using _value_type = typename T::_value_type; - using _name_t = typename T::_name_t; - }; - } - - namespace vendor - { - template - struct dynamic_select_column_list - { - using _names_t = std::vector; - std::vector> _dynamic_columns; - _names_t _dynamic_expression_names; - - template - void emplace_back(Expr expr) - { - _dynamic_expression_names.push_back(Expr::_name_t::_get_name()); - _dynamic_columns.emplace_back(expr); - } - - bool empty() const - { - return _dynamic_columns.empty(); - } - }; - - template<> - struct dynamic_select_column_list - { - struct _names_t - { - static constexpr size_t size() { return 0; } - }; - _names_t _dynamic_expression_names; - - static constexpr bool empty() - { - return true; - } - }; - - template - struct serializer_t> - { - using T = dynamic_select_column_list; - - static Context& _(const T& t, Context& context) - { - bool first = true; - for (const auto column : t._dynamic_columns) - { - if (first) - first = false; - else - context << ','; - serialize(column, context); - } - return context; - } - }; - - template - struct serializer_t> - { - using T = dynamic_select_column_list; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - - // SELECT COLUMNS - template - struct select_column_list_t - { - using _is_select_column_list = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - using size = std::tuple_size<_parameter_tuple_t>; - - using _table_set = sqlpp::detail::make_joined_set_t; - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); - - template - using is_valid_expression_t = std::integral_constant::value or is_multi_column_t::value>; - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a named expression"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); - - struct _column_type {}; - struct _value_type: ::sqlpp::detail::get_first_argument_if_unique::_value_type - { - using _is_expression = typename std::conditional::type; - using _is_named_expression = typename std::conditional::type; - using _is_alias = std::false_type; - }; - using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; - - template - using _result_row_t = typename std::conditional<_is_dynamic::value, - dynamic_result_row_t...>, - result_row_t...>>::type; - - using _dynamic_names_t = typename dynamic_select_column_list::_names_t; - - template - using _pseudo_table_t = select_pseudo_table_t; - - template - using _dynamic_t = select_column_list_t>; - - select_column_list_t(std::tuple columns): - _columns(columns) - {} - - select_column_list_t(Columns... columns): - _columns(columns...) - {} - - select_column_list_t(const select_column_list_t&) = default; - select_column_list_t(select_column_list_t&&) = default; - select_column_list_t& operator=(const select_column_list_t&) = default; - select_column_list_t& operator=(select_column_list_t&&) = default; - ~select_column_list_t() = default; - - static constexpr size_t static_size() - { - return size::value; - } - - template - struct _methods_t - { - template - void add_column_ntc(NamedExpression namedExpression) - { - add_column(namedExpression); - } - - template - void add_column(NamedExpression namedExpression) - { - static_assert(_is_dynamic::value, "add_column can only be called for dynamic_column"); - static_assert(is_named_expression_t::value, "invalid named expression argument in add_column()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "named expression uses tables unknown to this statement in add_column()"); - using column_names = ::sqlpp::detail::make_type_set_t; - static_assert(not ::sqlpp::detail::is_element_of::value, "a column of this name is present in the select already"); - - using ok = ::sqlpp::detail::all_t< - _is_dynamic::value, - is_named_expression_t::value - >; - - _add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_column_impl(NamedExpression namedExpression, const std::true_type&) - { - return static_cast(this)->_column_list._dynamic_columns.emplace_back(namedExpression); - } - - template - void _add_column_impl(NamedExpression namedExpression, const std::false_type&); - }; - - - const select_column_list_t& _column_list() const { return *this; } - _parameter_tuple_t _columns; - dynamic_select_column_list _dynamic_columns; - }; - } - - namespace detail - { - template - using make_select_column_list_t = - copy_tuple_args_t::_(std::declval())...))>; - } - - namespace vendor - { - struct no_select_column_list_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - template - using _result_row_t = ::sqlpp::result_row_t; - using _dynamic_names_t = typename dynamic_select_column_list::_names_t; - using _value_type = no_value_t; - struct _name_t {}; - - template - struct _pseudo_table_t - { - static_assert(wrong_t::value, "Cannot use a select as a table when no columns have been selected yet"); - }; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto columns(Args... args) - -> _new_statement_t<::sqlpp::detail::make_select_column_list_t> - { - return { *static_cast(this), ::sqlpp::detail::make_select_column_list_t{std::tuple_cat(::sqlpp::detail::as_tuple::_(args)...)} }; - } - - template - auto dynamic_columns(Args... args) - -> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); - return { *static_cast(this), ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple::_(args)...)} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = select_column_list_t; - - static Context& _(const T& t, Context& context) - { - // check for at least one expression - static_assert(T::_is_dynamic::value or T::size::value, "at least one select expression required"); - - interpret_tuple(t._columns, ',', context); - if (T::size::value and not t._dynamic_columns.empty()) - context << ','; - serialize(t._dynamic_columns, context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_select_column_list_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - } -} - -#endif diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h deleted file mode 100644 index a5e9036b..00000000 --- a/include/sqlpp11/vendor/select_flag_list.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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_VENDOR_SELECT_FLAG_LIST_H -#define SQLPP_VENDOR_SELECT_FLAG_LIST_H - -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // SELECT FLAGS - template - struct select_flag_list_t - { - using _is_select_flag_list = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - using size = std::tuple_size<_parameter_tuple_t>; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a select flag in select flag list"); - - select_flag_list_t(Flags... flags): - _flags(flags...) - {} - - select_flag_list_t(const select_flag_list_t&) = default; - select_flag_list_t(select_flag_list_t&&) = default; - select_flag_list_t& operator=(const select_flag_list_t&) = default; - select_flag_list_t& operator=(select_flag_list_t&&) = default; - ~select_flag_list_t() = default; - - template - struct _methods_t - { - template - void add_flag_ntc(Flag flag) - { - add_flag(flag); - } - - template - void add_flag(Flag flag) - { - static_assert(_is_dynamic::value, "add_flag must not be called for static select flags"); - static_assert(is_select_flag_t::value, "invalid select flag argument in add_flag()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "flag uses tables unknown to this statement in add_flag()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_select_flag_t::value>; - - _add_flag_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_flag_impl(Flag flag, const std::true_type&) - { - return static_cast(this)->_flag_list._dynamic_flags.emplace_back(flag); - } - - template - void _add_flag_impl(Flag flag, const std::false_type&); - }; - - const select_flag_list_t& _flag_list() const { return *this; } - _parameter_tuple_t _flags; - vendor::interpretable_list_t _dynamic_flags; - }; - - struct no_select_flag_list_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto flags(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), select_flag_list_t{args...} }; - } - - template - auto dynamic_flags(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); - return { *static_cast(this), vendor::select_flag_list_t<_database_t, Args...>{args...} }; - } - }; - }; - - - // Interpreters - template - struct serializer_t> - { - using T = select_flag_list_t; - - static Context& _(const T& t, Context& context) - { - interpret_tuple(t._flags, ' ', context); - if (sizeof...(Flags)) - context << ' '; - interpret_list(t._dynamic_flags, ',', context); - if (not t._dynamic_flags.empty()) - context << ' '; - return context; - } - }; - - template - struct serializer_t - { - using T = no_select_flag_list_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - } - -} - -#endif diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h deleted file mode 100644 index 99cf8eea..00000000 --- a/include/sqlpp11/vendor/single_table.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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_VENDOR_SINGLE_TABLE_H -#define SQLPP_VENDOR_SINGLE_TABLE_H - -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // A SINGLE TABLE - template - struct single_table_t - { - using _is_single_table = std::true_type; - - static_assert(is_table_t
::value, "argument has to be a table"); - - single_table_t(Table table): - _table(table) - {} - - single_table_t(const single_table_t&) = default; - single_table_t(single_table_t&&) = default; - single_table_t& operator=(const single_table_t&) = default; - single_table_t& operator=(single_table_t&&) = default; - ~single_table_t() = default; - - using _table_set = typename Table::_table_set; - Table _table; - }; - - struct no_single_table_t - { - using _table_set = ::sqlpp::detail::type_set<>; - }; - - // Interpreters - template - struct serializer_t> - { - using T = single_table_t; - - static Context& _(const T& t, Context& context) - { - serialize(t._table, context); - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h deleted file mode 100644 index 9b0c808c..00000000 --- a/include/sqlpp11/vendor/update_list.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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_UPDATE_LIST_H -#define SQLPP_UPDATE_LIST_H - -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // UPDATE ASSIGNMENTS - template - struct update_list_t - { - using _is_update_list = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - - static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); - - static_assert(::sqlpp::detail::none_t::value...>::value, "at least one assignment is prohibited by its column definition in set()"); - - using _column_table_set = typename ::sqlpp::detail::make_joined_set::type; - using _value_table_set = typename ::sqlpp::detail::make_joined_set::type; - using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type; - static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns"); - static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables"); - - update_list_t(Assignments... assignments): - _assignments(assignments...) - {} - - update_list_t(const update_list_t&) = default; - update_list_t(update_list_t&&) = default; - update_list_t& operator=(const update_list_t&) = default; - update_list_t& operator=(update_list_t&&) = default; - ~update_list_t() = default; - - template - struct _methods_t - { - template - void add_set_ntc(Assignment assignment) - { - add_set(assignment); - } - - template - void add_set(Assignment assignment) - { - static_assert(_is_dynamic::value, "add_set must not be called for static from()"); - static_assert(is_assignment_t::value, "invalid assignment argument in add_set()"); - static_assert(sqlpp::detail::not_t::value, "add_set() argument must not be updated"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "assignment uses tables unknown to this statement in add_set()"); - - using ok = ::sqlpp::detail::all_t< - _is_dynamic::value, - is_assignment_t::value, - not must_not_update_t::value>; - - _add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_set_impl(Assignment assignment, const std::true_type&) - { - return static_cast(this)->_update_list._dynamic_assignments.emplace_back(assignment); - } - - template - void _add_set_impl(Assignment assignment, const std::false_type&); - }; - - - _parameter_tuple_t _assignments; - typename vendor::interpretable_list_t _dynamic_assignments; - }; - - struct no_update_list_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto set(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), update_list_t{args...} }; - } - - template - auto dynamic_set(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); - return { *static_cast(this), vendor::update_list_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = update_list_t; - - static Context& _(const T& t, Context& context) - { - context << " SET "; - interpret_tuple(t._assignments, ",", context); - if (sizeof...(Assignments) and not t._dynamic_assignments.empty()) - context << ','; - interpret_list(t._dynamic_assignments, ',', context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_update_list_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h deleted file mode 100644 index 64415e9d..00000000 --- a/include/sqlpp11/vendor/using.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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_USING_H -#define SQLPP_USING_H - -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // USING - template - struct using_t - { - using _is_using = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - - static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in using()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an table in using()"); - - using _table_set = ::sqlpp::detail::make_joined_set_t; - - using_t(Tables... tables): - _tables(tables...) - {} - - using_t(const using_t&) = default; - using_t(using_t&&) = default; - using_t& operator=(const using_t&) = default; - using_t& operator=(using_t&&) = default; - ~using_t() = default; - - template - struct _methods_t - { - template - void add_using(Table table) - { - static_assert(_is_dynamic::value, "add_using must not be called for static using()"); - static_assert(is_table_t
::value, "invalid table argument in add_using()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t
::value>; - - _add_using_impl(table, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_using_impl(Table table, const std::true_type&) - { - return static_cast(this)->_using._dynamic_tables.emplace_back(table); - } - - template - void _add_using_impl(Table table, const std::false_type&); - }; - - - _parameter_tuple_t _tables; - vendor::interpretable_list_t _dynamic_tables; - }; - - struct no_using_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto using_(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), using_t{args...} }; - } - - template - auto dynamic_using(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); - return { *static_cast(this), vendor::using_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = using_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Tables) == 0 and t._dynamic_tables.empty()) - return context; - context << " USING "; - interpret_tuple(t._tables, ',', context); - if (sizeof...(Tables) and not t._dynamic_tables.empty()) - context << ','; - interpret_list(t._dynamic_tables, ',', context); - return context; - } - }; - - template - struct serializer_t - { - using T = no_using_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - } -} - -#endif diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h deleted file mode 100644 index 63882e0a..00000000 --- a/include/sqlpp11/vendor/where.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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_WHERE_H -#define SQLPP_WHERE_H - -#include -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - // WHERE - template - struct where_t - { - using _is_where = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); - static_assert(sqlpp::detail::none_t::value...>::value, "at least one argument is an assignment in where()"); - static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not valid expression in where()"); - - using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - - where_t(Expressions... expressions): - _expressions(expressions...) - {} - - where_t(const where_t&) = default; - where_t(where_t&&) = default; - where_t& operator=(const where_t&) = default; - where_t& operator=(where_t&&) = default; - ~where_t() = default; - - template - struct _methods_t - { - template - void add_where_ntc(Expression expression) - { - add_where(expression); - } - - template - void add_where(Expression expression) - { - static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); - static_assert(is_expression_t::value, "invalid expression argument in add_where()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_where()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; - - _add_where_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_where_impl(Expression expression, const std::true_type&) - { - return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); - } - - template - void _add_where_impl(Expression expression, const std::false_type&); - }; - - _parameter_tuple_t _expressions; - vendor::interpretable_list_t _dynamic_expressions; - }; - - template<> - struct where_t - { - using _is_where = std::true_type; - using _is_dynamic = std::false_type; - using _table_set = ::sqlpp::detail::type_set<>; - - where_t(bool condition): - _condition(condition) - {} - - where_t(const where_t&) = default; - where_t(where_t&&) = default; - where_t& operator=(const where_t&) = default; - where_t& operator=(where_t&&) = default; - ~where_t() = default; - - template - struct _methods_t - { - }; - - bool _condition; - }; - - struct no_where_t - { - using _is_noop = std::true_type; - using _table_set = ::sqlpp::detail::type_set<>; - - template - struct _methods_t - { - using _database_t = typename Policies::_database_t; - template - using _new_statement_t = typename Policies::template _new_statement_t; - - template - auto where(Args... args) - -> _new_statement_t> - { - return { *static_cast(this), where_t{args...} }; - } - - template - auto dynamic_where(Args... args) - -> _new_statement_t> - { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { *static_cast(this), vendor::where_t<_database_t, Args...>{args...} }; - } - }; - }; - - // Interpreters - template - struct serializer_t> - { - using T = where_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) - return context; - context << " WHERE "; - interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) - context << " AND "; - interpret_list(t._dynamic_expressions, " AND ", context); - return context; - } - }; - - template - struct serializer_t> - { - using T = where_t; - - static Context& _(const T& t, Context& context) - { - if (not t._condition) - context << " WHERE NULL"; - return context; - } - }; - - template - struct serializer_t - { - using T = no_where_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - - } -} - -#endif diff --git a/include/sqlpp11/vendor/wrap_operand.h b/include/sqlpp11/vendor/wrap_operand.h deleted file mode 100644 index 96092e57..00000000 --- a/include/sqlpp11/vendor/wrap_operand.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * 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_DETAIL_WRAP_OPERAND_H -#define SQLPP_DETAIL_WRAP_OPERAND_H - -#include -#include -#include - -namespace sqlpp -{ - namespace detail - { - struct boolean; - struct integral; - struct floating_point; - struct text; - } - - namespace vendor - { - struct boolean_operand - { - static constexpr bool _is_expression = true; - using _value_type = sqlpp::detail::boolean; - using _value_t = bool; - using _table_set = ::sqlpp::detail::type_set<>; - - boolean_operand(): - _t{} - {} - - boolean_operand(_value_t t): - _t(t) - {} - - boolean_operand(const boolean_operand&) = default; - boolean_operand(boolean_operand&&) = default; - boolean_operand& operator=(const boolean_operand&) = default; - boolean_operand& operator=(boolean_operand&&) = default; - ~boolean_operand() = default; - - bool _is_trivial() const { return _t == false; } - - _value_t _t; - }; - - template - struct serializer_t - { - using Operand = boolean_operand; - - static Context& _(const Operand& t, Context& context) - { - context << t._t; - return context; - } - }; - - struct integral_operand - { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::integral; - using _value_t = int64_t; - using _table_set = ::sqlpp::detail::type_set<>; - - integral_operand(): - _t{} - {} - - integral_operand(_value_t t): - _t(t) - {} - - integral_operand(const integral_operand&) = default; - integral_operand(integral_operand&&) = default; - integral_operand& operator=(const integral_operand&) = default; - integral_operand& operator=(integral_operand&&) = default; - ~integral_operand() = default; - - bool _is_trivial() const { return _t == 0; } - - _value_t _t; - }; - - template - struct serializer_t - { - using Operand = integral_operand; - - static Context& _(const Operand& t, Context& context) - { - context << t._t; - return context; - } - }; - - - struct floating_point_operand - { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::floating_point; - using _value_t = double; - using _table_set = ::sqlpp::detail::type_set<>; - - floating_point_operand(): - _t{} - {} - - floating_point_operand(_value_t t): - _t(t) - {} - - floating_point_operand(const floating_point_operand&) = default; - floating_point_operand(floating_point_operand&&) = default; - floating_point_operand& operator=(const floating_point_operand&) = default; - floating_point_operand& operator=(floating_point_operand&&) = default; - ~floating_point_operand() = default; - - bool _is_trivial() const { return _t == 0; } - - _value_t _t; - }; - - template - struct serializer_t - { - using Operand = floating_point_operand; - - static Context& _(const Operand& t, Context& context) - { - context << t._t; - return context; - } - }; - - struct text_operand - { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::text; - using _value_t = std::string; - using _table_set = ::sqlpp::detail::type_set<>; - - text_operand(): - _t{} - {} - - text_operand(_value_t t): - _t(t) - {} - - text_operand(const text_operand&) = default; - text_operand(text_operand&&) = default; - text_operand& operator=(const text_operand&) = default; - text_operand& operator=(text_operand&&) = default; - ~text_operand() = default; - - bool _is_trivial() const { return _t.empty(); } - - _value_t _t; - }; - - template - struct serializer_t - { - using Operand = text_operand; - - static Context& _(const Operand& t, Context& context) - { - context << '\'' << context.escape(t._t) << '\''; - return context; - } - }; - - template - struct wrap_operand - { - using type = T; - }; - - template<> - struct wrap_operand - { - using type = boolean_operand; - }; - - template - struct wrap_operand::value>::type> - { - using type = integral_operand; - }; - - template - struct wrap_operand::value>::type> - { - using type = floating_point_operand; - }; - - template - struct wrap_operand::value>::type> - { - using type = text_operand; - }; - - // FIXME: Need to allow std::ref arguments - - template - using wrap_operand_t = typename wrap_operand::type; - - } -} - -#endif diff --git a/include/sqlpp11/verbatim_table.h b/include/sqlpp11/verbatim_table.h index 2ad79190..dbacdb9d 100644 --- a/include/sqlpp11/verbatim_table.h +++ b/include/sqlpp11/verbatim_table.h @@ -49,10 +49,10 @@ namespace sqlpp struct verbatim_table_t: public sqlpp::table_t { - using _value_type = no_value_t; + struct _name_t {}; - verbatim_table_t(std::string name): - _name(name) + verbatim_table_t(std::string representation): + _representation(representation) { } @@ -62,23 +62,20 @@ namespace sqlpp verbatim_table_t& operator=(verbatim_table_t&& rhs) = default; ~verbatim_table_t() = default; - std::string _name; + std::string _representation; }; - namespace vendor - { - template - struct serializer_t - { - using T = verbatim_table_t; + template + struct serializer_t + { + using T = verbatim_table_t; - static Context& _(const T& t, Context& context) - { - context << t._name; - return context; - } - }; - } + static Context& _(const T& t, Context& context) + { + context << t._representation; + return context; + } + }; verbatim_table_t verbatim_table(std::string name) diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h new file mode 100644 index 00000000..0a8d704d --- /dev/null +++ b/include/sqlpp11/where.h @@ -0,0 +1,281 @@ +/* + * 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_WHERE_H +#define SQLPP_WHERE_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // WHERE DATA + template + struct where_data_t + { + where_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + where_data_t(const where_data_t&) = default; + where_data_t(where_data_t&&) = default; + where_data_t& operator=(const where_data_t&) = default; + where_data_t& operator=(where_data_t&&) = default; + ~where_data_t() = default; + + std::tuple _expressions; + interpretable_list_t _dynamic_expressions; + }; + + // WHERE(EXPR) + template + struct where_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = is_database; + + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); + static_assert(sqlpp::detail::none_t::value...>::value, "at least one argument is an assignment in where()"); + static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not valid expression in where()"); + + // Data + using _data_t = where_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Expression expression) + { + add(expression); + } + + template + void add(Expression expression) + { + static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where"); + static_assert(is_expression_t::value, "invalid expression argument in where::add()"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in where::add()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; + + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Expression expression, const std::true_type&) + { + return _data._dynamic_expressions.emplace_back(expression); + } + + template + void _add_impl(Expression expression, const std::false_type&); + + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = where_data_t; + + _impl_t where; + _impl_t& operator()() { return where; } + const _impl_t& operator()() const { return where; } + + template + static auto _get_member(T t) -> decltype(t.where) + { + return t.where; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + }; + + template<> + struct where_data_t + { + bool _condition; + }; + + // WHERE(BOOL) + template<> + struct where_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = where_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = where_data_t; + + _impl_t where; + _impl_t& operator()() { return where; } + const _impl_t& operator()() const { return where; } + + template + static auto _get_member(T t) -> decltype(t.where) + { + return t.where; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + static void _check_consistency() {} + }; + + }; + + // NO WHERE YET + template + struct no_where_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_where; + _impl_t& operator()() { return no_where; } + const _impl_t& operator()() const { return no_where; } + + template + static auto _get_member(T t) -> decltype(t.no_where) + { + return t.no_where; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + static void _check_consistency() + { + static_assert(Required ? wrong_t::value : true, "where expression required, e.g. where(true)"); + } + + template + auto where(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), where_data_t{args...} }; + } + + template + auto dynamic_where(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); + return { *static_cast(this), where_data_t<_database_t, Args...>{args...} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = where_data_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) + return context; + context << " WHERE "; + interpret_tuple(t._expressions, " AND ", context); + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) + context << " AND "; + interpret_list(t._dynamic_expressions, " AND ", context); + return context; + } + }; + + template + struct serializer_t> + { + using T = where_data_t; + + static Context& _(const T& t, Context& context) + { + if (not t._condition) + context << " WHERE NULL"; + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/wrap_operand.h b/include/sqlpp11/wrap_operand.h new file mode 100644 index 00000000..177f9294 --- /dev/null +++ b/include/sqlpp11/wrap_operand.h @@ -0,0 +1,234 @@ +/* + * 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_DETAIL_WRAP_OPERAND_H +#define SQLPP_DETAIL_WRAP_OPERAND_H + +#include +#include +#include + +namespace sqlpp +{ + namespace detail + { + struct boolean; + struct integral; + struct floating_point; + struct text; + } + + struct boolean_operand + { + using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; + using _recursive_traits = make_recursive_traits<>; + + using _value_t = bool; + + boolean_operand(): + _t{} + {} + + boolean_operand(_value_t t): + _t(t) + {} + + boolean_operand(const boolean_operand&) = default; + boolean_operand(boolean_operand&&) = default; + boolean_operand& operator=(const boolean_operand&) = default; + boolean_operand& operator=(boolean_operand&&) = default; + ~boolean_operand() = default; + + bool _is_trivial() const { return _t == false; } + + _value_t _t; + }; + + template + struct serializer_t + { + using Operand = boolean_operand; + + static Context& _(const Operand& t, Context& context) + { + context << t._t; + return context; + } + }; + + struct integral_operand + { + using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; + using _recursive_traits = make_recursive_traits<>; + + using _value_t = int64_t; + + integral_operand(): + _t{} + {} + + integral_operand(_value_t t): + _t(t) + {} + + integral_operand(const integral_operand&) = default; + integral_operand(integral_operand&&) = default; + integral_operand& operator=(const integral_operand&) = default; + integral_operand& operator=(integral_operand&&) = default; + ~integral_operand() = default; + + bool _is_trivial() const { return _t == 0; } + + _value_t _t; + }; + + template + struct serializer_t + { + using Operand = integral_operand; + + static Context& _(const Operand& t, Context& context) + { + context << t._t; + return context; + } + }; + + + struct floating_point_operand + { + using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; + using _recursive_traits = make_recursive_traits<>; + + using _value_t = double; + + floating_point_operand(): + _t{} + {} + + floating_point_operand(_value_t t): + _t(t) + {} + + floating_point_operand(const floating_point_operand&) = default; + floating_point_operand(floating_point_operand&&) = default; + floating_point_operand& operator=(const floating_point_operand&) = default; + floating_point_operand& operator=(floating_point_operand&&) = default; + ~floating_point_operand() = default; + + bool _is_trivial() const { return _t == 0; } + + _value_t _t; + }; + + template + struct serializer_t + { + using Operand = floating_point_operand; + + static Context& _(const Operand& t, Context& context) + { + context << t._t; + return context; + } + }; + + struct text_operand + { + using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>; + using _recursive_traits = make_recursive_traits<>; + + using _value_t = std::string; + + text_operand(): + _t{} + {} + + text_operand(_value_t t): + _t(t) + {} + + text_operand(const text_operand&) = default; + text_operand(text_operand&&) = default; + text_operand& operator=(const text_operand&) = default; + text_operand& operator=(text_operand&&) = default; + ~text_operand() = default; + + bool _is_trivial() const { return _t.empty(); } + + _value_t _t; + }; + + template + struct serializer_t + { + using Operand = text_operand; + + static Context& _(const Operand& t, Context& context) + { + context << '\'' << context.escape(t._t) << '\''; + return context; + } + }; + + template + struct wrap_operand + { + using type = T; + }; + + template<> + struct wrap_operand + { + using type = boolean_operand; + }; + + template + struct wrap_operand::value>::type> + { + using type = integral_operand; + }; + + template + struct wrap_operand::value>::type> + { + using type = floating_point_operand; + }; + + template + struct wrap_operand::value>::type> + { + using type = text_operand; + }; + + // FIXME: Need to allow std::ref arguments + + template + using wrap_operand_t = typename wrap_operand::type; + +} + +#endif diff --git a/include/sqlpp11/vendor/wrong.h b/include/sqlpp11/wrong.h similarity index 78% rename from include/sqlpp11/vendor/wrong.h rename to include/sqlpp11/wrong.h index 65a4d181..9249673e 100644 --- a/include/sqlpp11/vendor/wrong.h +++ b/include/sqlpp11/wrong.h @@ -24,28 +24,25 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_VENDOR_WRONG_H -#define SQLPP_VENDOR_WRONG_H +#ifndef SQLPP_WRONG_H +#define SQLPP_WRONG_H #include namespace sqlpp { - namespace vendor + namespace detail { - namespace detail - { - // A template that always returns false - // To be used with static assert, for instance, to ensure it - // fires only when the template is instantiated. - template - struct wrong - { - using type = std::false_type; - }; - } + // A template that always returns false + // To be used with static assert, for instance, to ensure it + // fires only when the template is instantiated. template - using wrong_t = typename detail::wrong::type; + struct wrong + { + using type = std::false_type; + }; } + template + using wrong_t = typename detail::wrong::type; } #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 350602ec..b7109ae7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,6 +14,7 @@ build_and_run(SelectTest) build_and_run(SelectTypeTest) build_and_run(FunctionTest) build_and_run(PreparedTest) +build_and_run(Minimalistic) find_package(PythonInterp REQUIRED) diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index 04aa8f52..e668a668 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -188,6 +188,8 @@ int main() // Test any { + using S = decltype(select(t.alpha).from(t)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); using TI = decltype(any(select(t.alpha).from(t))); using TT = decltype(any(select(t.beta).from(t))); diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index 67e2efe7..68b06d82 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -35,13 +35,7 @@ MockDb::_serializer_context_t printer; int main() { test::TabBar t; - test::TabFoo f; - - auto x = t.alpha = 7; - auto y = t.beta = "kaesekuchen"; - auto z = t.gamma = true; - auto a = t.alpha; - a = t.alpha; + //test::TabFoo f; { using T = decltype(insert_into(t)); @@ -67,11 +61,12 @@ int main() serialize(insert_into(t).set(t.beta = "kirschauflauf"), printer).str(); serialize(insert_into(t).columns(t.beta), printer).str(); auto multi_insert = insert_into(t).columns(t.beta, t.delta); - multi_insert.add_values(t.beta = "cheesecake", t.delta = 1); - multi_insert.add_values(t.beta = sqlpp::default_value, t.delta = sqlpp::default_value); + multi_insert.values.add(t.beta = "cheesecake", t.delta = 1); + multi_insert.values.add(t.beta = sqlpp::default_value, t.delta = sqlpp::default_value); auto i = dynamic_insert_into(db, t).dynamic_set(); - i.add_set(t.beta = "kirschauflauf"); - serialize(i, printer).str(); + i.insert_list.add(t.beta = "kirschauflauf"); + printer.reset(); + std::cerr << serialize(i, printer).str() << std::endl; db(multi_insert); diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 2fd5c3a3..528bf21f 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -46,12 +46,12 @@ int main() serialize(insert_into(t).columns(t.beta, t.gamma), printer).str(); { auto i = insert_into(t).columns(t.gamma, t.beta); - i.add_values(t.gamma = true, t.beta = "cheesecake"); + i.values.add(t.gamma = true, t.beta = "cheesecake"); serialize(i, printer).str(); - i.add_values(t.gamma = false, t.beta = sqlpp::tvin("coffee")); - i.add_values(t.gamma = false, t.beta = sqlpp::tvin(std::string())); + i.values.add(t.gamma = false, t.beta = sqlpp::tvin("coffee")); + i.values.add(t.gamma = false, t.beta = sqlpp::tvin(std::string())); serialize(i, printer).str(); - i.add_values(t.gamma = sqlpp::default_value, t.beta = sqlpp::null); + i.values.add(t.gamma = sqlpp::default_value, t.beta = sqlpp::null); serialize(i, printer).str(); } @@ -101,7 +101,7 @@ int main() serialize(remove_from(t).using_(t).where(t.alpha == sqlpp::tvin(0)), printer).str(); // functions - sqlpp::serialize(sqlpp::value(7), printer).str();// FIXME: Maybe the vendor namespace is not a good idea? argument lives in namespace vendor + serialize(sqlpp::value(7), printer).str(); serialize(sqlpp::verbatim("irgendwas integrales"), printer).str(); serialize(sqlpp::value_list(std::vector({1,2,3,4,5,6,8})), printer).str(); serialize(exists(select(t.alpha).from(t)), printer).str(); @@ -134,22 +134,22 @@ int main() // dynamic select { auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); - s.add_column(t.beta); - s.add_column(t.gamma); + s.selected_columns.add(t.beta); + s.selected_columns.add(t.gamma); serialize(s, printer).str(); } { auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); - s.add_flag(sqlpp::distinct); - s.add_column(t.beta); - s.add_column(t.gamma); + s.select_flags.add(sqlpp::distinct); + s.selected_columns.add(t.beta); + s.selected_columns.add(t.gamma); serialize(s, printer).str(); } { auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha).extra_tables(t); // Would fail to run() - s.add_flag(sqlpp::all); - s.add_column(t.beta); - s.add_column(t.gamma); + s.select_flags.add(sqlpp::all); + s.selected_columns.add(t.beta); + s.selected_columns.add(t.gamma); serialize(s, printer).str(); } diff --git a/tests/Minimalistic.cpp b/tests/Minimalistic.cpp new file mode 100644 index 00000000..c30384c0 --- /dev/null +++ b/tests/Minimalistic.cpp @@ -0,0 +1,5 @@ +#include + +int main() +{ +} diff --git a/tests/MockDb.h b/tests/MockDb.h index fd114baf..9c4dafd9 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -43,7 +43,7 @@ struct MockDb: public sqlpp::connection void reset() { - _os.clear(); + _os.str(""); } template @@ -85,7 +85,7 @@ struct MockDb: public sqlpp::connection template void next(ResultRow& result_row) { - result_row.invalidate(); + result_row._invalidate(); }; }; diff --git a/tests/PreparedTest.cpp b/tests/PreparedTest.cpp index 7e6103ae..ae4cc16e 100644 --- a/tests/PreparedTest.cpp +++ b/tests/PreparedTest.cpp @@ -35,67 +35,69 @@ MockDb db = {}; int main() { - test::TabFoo f; + //test::TabFoo f; test::TabBar t; // empty parameter lists { - using T = typename sqlpp::detail::get_parameter_tuple::type; + using T = sqlpp::parameters_of; static_assert(std::is_same>::value, "type requirement"); } // single parameter { - using T = typename sqlpp::detail::get_parameter_tuple::type; + using T = sqlpp::parameters_of; static_assert(std::is_same>::value, "type requirement"); } // single parameter { - using T = typename sqlpp::detail::get_parameter_tuple::type; + using T = sqlpp::parameters_of; static_assert(std::is_same>::value, "type requirement"); } // single parameter in expression { - using T = typename sqlpp::detail::get_parameter_tuple::type; + using T = sqlpp::parameters_of; static_assert(std::is_same>::value, "type requirement"); } + // single parameter in larger expression { - using T = typename sqlpp::detail::get_parameter_tuple::type; + using T = sqlpp::parameters_of; static_assert(std::is_same>::value, "type requirement"); } // three parameters in expression { - using T = typename sqlpp::detail::get_parameter_tuple::type; + using T = sqlpp::parameters_of; static_assert(std::tuple_size::value == 3, "type requirement"); static_assert(std::is_same>::value, "type requirement"); } // OK, fine, now create a named parameter list from an expression { - using Exp = decltype(t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha) or t.gamma != parameter(t.gamma)); - using T = sqlpp::make_parameter_list_t::type; + using Exp = decltype((t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha)) or t.gamma != parameter(t.gamma)); + using T = sqlpp::make_parameter_list_t; T npl; - static_assert(std::is_same::value, "type requirement"); - static_assert(std::is_same::value, "type requirement"); - static_assert(std::is_same::value, "type requirement"); + static_assert(std::is_same::_parameter_t, decltype(npl.alpha)>::value, "type requirement"); + static_assert(std::is_same::_parameter_t, decltype(npl.beta)>::value, "type requirement"); + static_assert(std::is_same::_parameter_t, decltype(npl.gamma)>::value, "type requirement"); } // Wonderful, now take a look at the parameter list of a select { - auto s = select(all_of(t)).from(t).where(t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha) or t.gamma != parameter(t.gamma)); + auto s = select(all_of(t)).from(t).where((t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha)) or t.gamma != parameter(t.gamma)); auto p = db.prepare(s); + p.params.alpha = 7; using S = decltype(s); - using T = sqlpp::make_parameter_list_t::type; + using T = sqlpp::make_parameter_list_t; T npl; - static_assert(std::is_same::value, "type requirement"); - static_assert(std::is_same::value, "type requirement"); - static_assert(std::is_same::value, "type requirement"); + static_assert(std::is_same::_parameter_t, decltype(npl.alpha)>::value, "type requirement"); + static_assert(std::is_same::_parameter_t, decltype(npl.beta)>::value, "type requirement"); + static_assert(std::is_same::_parameter_t, decltype(npl.gamma)>::value, "type requirement"); npl.alpha = 7; auto x = npl; x = npl; @@ -104,6 +106,5 @@ int main() std::cerr << x.alpha << std::endl; } - return 0; } diff --git a/tests/RemoveTest.cpp b/tests/RemoveTest.cpp index f4ce1302..0ea34df1 100644 --- a/tests/RemoveTest.cpp +++ b/tests/RemoveTest.cpp @@ -37,10 +37,6 @@ int main() { test::TabBar t; - auto x = t.alpha = 7; - auto y = t.beta = "kaesekuchen"; - auto z = t.gamma = true; - { using T = decltype(remove_from(t)); static_assert(sqlpp::is_regular::value, "type requirement"); @@ -60,9 +56,12 @@ int main() serialize(remove_from(t).where(t.beta != "transparent"), printer).str(); serialize(remove_from(t).using_(t), printer).str(); auto r = dynamic_remove_from(db, t).dynamic_using().dynamic_where(); - r.add_using(t); - r.add_where(t.beta != "transparent"); - serialize(r, printer).str(); + r.using_.add(t); + r.where.add(t.beta != "transparent"); + printer.reset(); + std::cerr << serialize(r, printer).str() << std::endl; + printer.reset(); + std::cerr << serialize(remove_from(t).where(true), printer).str() << std::endl; db(r); diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index c82f1dc2..9a94694b 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -49,16 +49,19 @@ int main() test::TabFoo f; test::TabBar t; + sqlpp::select(t.alpha).flags(sqlpp::all).from(t); for (const auto& row : db(select(all_of(t)).from(t).where(true))) { int64_t a = row.alpha; const std::string b = row.beta; + std::cout << a << ", " << b << std::endl; } for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true))) { int64_t a = row.tabBar.alpha; const std::string b = row.tabBar.beta; + std::cout << a << ", " << b << std::endl; } for (const auto& row : db(select(all_of(t).as(t), t.gamma).from(t).where(t.alpha > 7))) @@ -66,22 +69,31 @@ int main() int64_t a = row.tabBar.alpha; const std::string b = row.tabBar.beta; const bool g = row.gamma; + std::cout << a << ", " << b << ", " << g << std::endl; } + auto stat = sqlpp::select().columns(all_of(t)).flags(sqlpp::all).from(t).extra_tables(f,t).where(t.alpha > 0).group_by(t.alpha).order_by(t.gamma.asc()).having(t.gamma).limit(7).offset(19); + auto s = dynamic_select(db).dynamic_columns(all_of(t)).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); - s.add_flag(sqlpp::distinct); - s.add_column(f.omega); - s.add_from(f); - s.add_where(t.alpha > 7); - s.add_having(t.alpha > 7); - s.set_limit(3); - s.set_offset(3); - s.add_group_by(t.beta); - s.add_order_by(t.beta.asc()); + s.select_flags.add(sqlpp::distinct); + s.selected_columns.add(f.omega); + s.from.add(f); + s.where.add(t.alpha > 7); + s.having.add(t.alpha > 7); + s.limit.set(3); + s.offset.set(3); + s.group_by.add(t.beta); + s.order_by.add(t.beta.asc()); for (const auto& row : db(s)) { int64_t a = row.alpha; + std::cout << a << std::endl; } + printer.reset(); + std::cerr << serialize(s, printer).str() << std::endl; + printer.reset(); + std::cerr << serialize(stat, printer).str() << std::endl; + return 0; } diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp index 12cf9c56..f709947a 100644 --- a/tests/SelectTypeTest.cpp +++ b/tests/SelectTypeTest.cpp @@ -158,10 +158,10 @@ int main() // Test a select of a single column without a from { - using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + using T = decltype(select(t.alpha)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); static_assert(not sqlpp::require_insert_t::value, "type requirement"); static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); static_assert(not sqlpp::must_not_update_t::value, "type requirement"); @@ -175,8 +175,8 @@ int main() // Test a select of a single numeric table column { using T = decltype(select(t.alpha).from(t)); - static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); - static_assert(sqlpp::is_from_t::value, "Must not be noop"); + //static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); + //static_assert(sqlpp::is_from_t::value, "Must not be noop"); static_assert(sqlpp::is_numeric_t::value, "type requirement"); static_assert(sqlpp::is_expression_t::value, "type requirement"); static_assert(sqlpp::is_named_expression_t::value, "type requirement"); @@ -289,9 +289,9 @@ int main() // Test that a multicolumn is not a value { auto m = multi_column(t.alpha, t.beta).as(alias::a); - auto a = select(m).from(t).as(alias::b).a; - static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); + static_assert(not sqlpp::is_expression_t::value, "a multi_column is not a value"); } + // Test that result sets with identical name/value combinations have identical types { auto a = select(t.alpha); @@ -299,22 +299,23 @@ int main() using A = typename decltype(a)::_result_row_t; using B = typename decltype(b)::_result_row_t; static_assert(std::is_same< - decltype(t.alpha)::_value_type::_base_value_type, - decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type"); + sqlpp::value_type_of, + sqlpp::value_type_of>::value, "Two bigint columns must have identical base_value_type"); static_assert(std::is_same::value, "select with identical columns(name/value_type) need to have identical result_types"); } for (const auto& row : db(select(all_of(t)).from(t).where(true))) { int64_t a = row.alpha; + std::cout << a << std::endl; } { auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset(); - s.add_from(t); - s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); - s.set_limit(30); - s.set_limit(3); + s.from.add(t); + s.where.add_ntc(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); + s.limit.set(30); + s.limit.set(3); std::cerr << "------------------------\n"; serialize(s, printer).str(); std::cerr << "------------------------\n"; @@ -325,7 +326,7 @@ int main() // Test that select can be called with zero columns if it is used with dynamic columns. { auto s = dynamic_select(db).dynamic_columns().extra_tables(t); - s.add_column(t.alpha); + s.selected_columns.add(t.alpha); serialize(s, printer).str(); } @@ -337,44 +338,26 @@ int main() static_assert(sqlpp::is_select_flag_t::value, "sqlpp::all has to be a select_flag"); - using T = sqlpp::vendor::wrap_operand::type; + using T = sqlpp::wrap_operand::type; static_assert(sqlpp::is_regular::value, "type requirement"); - static_assert(T::_is_expression, "T has to be an expression"); - static_assert(std::is_same::value, "T has to be a numeric"); - static_assert(sqlpp::is_numeric_t::value, "T has to be a numeric"); + static_assert(sqlpp::is_expression_t::value, "T has to be an expression"); + static_assert(sqlpp::is_numeric_t::value, "T has to be numeric"); static_assert(sqlpp::is_numeric_t::value, "TabBar.alpha has to be a numeric"); ((t.alpha + 7) + 4).asc(); static_assert(sqlpp::is_boolean_t::value, "Comparison expression have to be boolean"); - auto x = (t.gamma == true) and (t.alpha == 7); - auto y = t.gamma and true and t.gamma; !t.gamma; t.beta < "kaesekuchen"; serialize(t.beta + "hallenhalma", printer).str(); static_assert(sqlpp::must_not_insert_t::value, "alpha must not be inserted"); serialize(t.alpha, printer).str(); std::cerr << "\n" << sizeof(test::TabBar) << std::endl; - static_assert(std::is_same::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); - auto z = select(t.alpha).from(t) == 7; auto l = t.as(alias::left); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); - using R = decltype(r); static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); - auto s = select(r.a).from(r); - using RA = decltype(r.a); - using S = decltype(s); - using SCL = typename S::_column_list_t; - using SF = typename S::_from_t; - static_assert(sqlpp::is_select_column_list_t::value, "no column list"); - static_assert(sqlpp::is_from_t::value, "no from list"); - using SCL_T = typename SCL::_table_set; - using SF_T = typename SF::_table_set; - static_assert(SCL_T::size::value == 1, "unexpected table_set in column_list"); - static_assert(SF_T::size::value == 1, "unexpected table_set in from"); - static_assert(std::is_same::value, "should be the same"); static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); auto s1 = sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) .from(r,t,l) @@ -387,6 +370,5 @@ int main() .as(alias::a) ; - return 0; } diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index fcf0c6d3..e3f8de62 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -35,11 +35,7 @@ MockDb::_serializer_context_t printer; int main() { test::TabBar t; - test::TabFoo f; - - auto x = t.alpha = 7; - auto y = t.beta = "kaesekuchen"; - auto z = t.gamma = true; + //test::TabFoo f; { using T = decltype(update(t)); @@ -61,9 +57,10 @@ int main() serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).str(); serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); - u.add_set(t.gamma = false); - u.add_where(t.gamma != false); - serialize(u, printer).str(); + u.assignments.add(t.beta = "cannot update gamma a second time"); + u.where.add(t.gamma != false); + printer.reset(); + std::cerr << serialize(u, printer).str() << std::endl; db(u);