From 7e78c0d878839ae05ef717d23defd3085dee2748 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 10 Apr 2014 21:20:37 +0200 Subject: [PATCH] Migrated update to inheritance model --- include/sqlpp11/detail/logic.h | 19 ++++ include/sqlpp11/remove.h | 1 - include/sqlpp11/update.h | 157 +++++++++++---------------- include/sqlpp11/vendor/update_list.h | 53 +++++++++ 4 files changed, 136 insertions(+), 94 deletions(-) diff --git a/include/sqlpp11/detail/logic.h b/include/sqlpp11/detail/logic.h index 9fb26cb9..57e335c9 100644 --- a/include/sqlpp11/detail/logic.h +++ b/include/sqlpp11/detail/logic.h @@ -81,6 +81,25 @@ namespace sqlpp template class Predicate, typename... T> using any_t = typename any_impl::value...>::type; + template + struct not_impl; + + template<> + struct not_impl + { + using type = std::false_type; + }; + + template<> + struct not_impl + { + using type = std::true_type; + }; + + + template class Predicate, typename... T> + using not_t = typename not_impl::value...>::type; + template using identity_t = T; diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 860af2f1..06575373 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -73,7 +73,6 @@ namespace sqlpp template using _new_statement_t = typename _policies_update_t::type; - }; } diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 32e8f040..94353edd 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -39,52 +39,72 @@ namespace sqlpp { + template + struct update_t; + namespace detail { - template< - typename Table, - typename UpdateList, - typename Where - > - struct check_update_t - { - static constexpr bool value = true; - }; - } - - template - struct update_t + typename Where = vendor::no_where_t + > + struct update_policies_t + { + using _database_t = Db; + using _table_t = Table; + using _update_list_t = UpdateList; + using _where_t = Where; + + using _statement_t = update_t; + + struct _methods_t: + public _update_list_t::template _methods_t, + public _where_t::template _methods_t + {}; + + template + struct _policies_update_t + { + using type = update_t...>; + }; + + template + using _new_statement_t = typename _policies_update_t::type; + }; + } + + template + struct update_t: + public detail::update_policies_t::_methods_t { - 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"); + 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 _database_t = Database; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - template - struct _policies_update_t - { - using type = update_t...>; - }; - - template - using _new_statement_t = typename _policies_update_t::type; - - using _parameter_tuple_t = std::tuple; + 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::_(s._table, t)), - _update_list(detail::arg_selector::_(s._update_list, t)), - _where(detail::arg_selector::_(s._where, 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; @@ -93,58 +113,6 @@ namespace sqlpp update_t& operator=(update_t&&) = default; ~update_t() = default; - // type update functions - template - auto set(Args... args) - -> _new_statement_t> - { - static_assert(is_noop_t::value, "cannot call set()/dynamic_set() twice"); - return { *this, vendor::update_list_t{args...} }; - } - - template - auto dynamic_set(Args... args) - -> _new_statement_t> - { - static_assert(is_noop_t::value, "cannot call set()/dynamic_set() twice"); - static_assert(_is_dynamic::value, "dynamic_set must not be called in a static statement"); - return { *this, vendor::update_list_t<_database_t, Args...>{args...} }; - } - - template - auto where(Args... args) - -> _new_statement_t> - { - static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); - return { *this, vendor::where_t{args...} }; - } - - template - auto dynamic_where(Args... args) - -> _new_statement_t> - { - static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); - static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { *this, vendor::where_t<_database_t, Args...>{args...} }; - } - - // value adding methods - template - void add_set(Args... args) - { - static_assert(is_update_list_t::value, "cannot call add_set() before dynamic_set()"); - static_assert(is_dynamic_t::value, "cannot call add_set() before dynamic_set()"); - return _update_list.add_set(*this, args...); - } - - template - void add_where(Args... args) - { - static_assert(is_where_t::value, "cannot call add_where() before dynamic_where()"); - static_assert(is_dynamic_t::value, "cannot call add_where() before dynamic_where()"); - return _where.add_where(*this, args...); - } - // run and prepare static constexpr size_t _get_static_no_of_parameters() { @@ -156,23 +124,23 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - std::size_t _run(Db& db) const + template + std::size_t _run(Database& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); return db.update(*this); } - template - auto _prepare(Db& db) const - -> prepared_update_t + template + auto _prepare(Database& db) const + -> prepared_update_t { return {{}, db.prepare_update(*this)}; } - Table _table; - UpdateList _update_list; - Where _where; + _table_t _table; + _update_list_t _update_list; + _where_t _where; }; namespace vendor @@ -193,16 +161,19 @@ namespace sqlpp }; } + template + using make_update_t = typename detail::update_policies_t::_statement_t; + template constexpr auto update(Table table) - -> update_t> + -> make_update_t> { return { update_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_update(const Database&, Table table) - -> update_t> + -> make_update_t> { return { update_t(), vendor::single_table_t{table} }; } diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index 1fa1bdd0..9cd560d9 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -76,6 +76,36 @@ namespace sqlpp _dynamic_assignments.emplace_back(assignment); } + 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, "invalid assignment argument in add_set()"); + static_assert(sqlpp::detail::not_t::value, "set() argument must not be updated"); + + using ok = ::sqlpp::detail::all_t, + sqlpp::detail::not_t>; + + _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; }; @@ -84,6 +114,29 @@ namespace sqlpp { 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