diff --git a/include/sqlpp11/for_update.h b/include/sqlpp11/for_update.h new file mode 100644 index 00000000..4d84f9b6 --- /dev/null +++ b/include/sqlpp11/for_update.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017, Serge Robyns + * 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_FOR_UPDATE_H +#define SQLPP_FOR_UPDATE_H + +#include +#include +#include + +namespace sqlpp +{ + // FOR_UPDATE DATA + struct for_update_data_t + { + }; + + // FOR_UPDATE + struct for_update_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + + // Data + using _data_t = for_update_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 + _impl_t() = default; + _impl_t(const _data_t& data) : _data(data) + { + } + + _data_t _data; + }; + + // Base template to be inherited by the statement + template + struct _base_t + { + using _data_t = for_update_data_t; + + // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 + template + _base_t(Args&&... args) : for_update{std::forward(args)...} + { + } + + _impl_t for_update; + _impl_t& operator()() + { + return for_update; + } + const _impl_t& operator()() const + { + return for_update; + } + + template + static auto _get_member(T t) -> decltype(t.for_update) + { + return t.for_update; + } + + using _consistency_check = consistent_t; + }; + }; + + struct no_for_update_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 + _impl_t() = default; + _impl_t(const _data_t& data) : _data(data) + { + } + + _data_t _data; + }; + + // Base template to be inherited by the statement + template + struct _base_t + { + using _data_t = no_data_t; + + // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 + template + _base_t(Args&&... args) : no_for_update{std::forward(args)...} + { + } + + _impl_t no_for_update; + _impl_t& operator()() + { + return no_for_update; + } + const _impl_t& operator()() const + { + return no_for_update; + } + + template + static auto _get_member(T t) -> decltype(t.no_for_update) + { + return t.no_for_update; + } + + using _database_t = typename Policies::_database_t; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; + + auto for_update() const -> _new_statement_t + { + return {static_cast&>(*this), for_update_data_t{}}; + } + }; + }; + + // Interpreters + template + struct serializer_t + { + using _serialize_check = serialize_check_of; + using T = for_update_data_t; + + static Context& _(const T& t, Context& context) + { + context << " FOR UPDATE "; + return context; + } + }; + + template + auto for_update(T&& t) -> decltype(statement_t().for_update(std::forward(t))) + { + return statement_t().for_update(std::forward(t)); + } +} + +#endif diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 824645c4..0a1b301f 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,8 @@ namespace sqlpp no_order_by_t, no_limit_t, no_offset_t, - no_union_t>; + no_union_t, + no_for_update_t>; inline blank_select_t select() // FIXME: These should be constexpr { diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index cf377f07..427308c6 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -200,6 +200,7 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(is_having) SQLPP_VALUE_TRAIT_GENERATOR(is_order_by) SQLPP_VALUE_TRAIT_GENERATOR(is_limit) + SQLPP_VALUE_TRAIT_GENERATOR(is_for_update) SQLPP_VALUE_TRAIT_GENERATOR(is_offset) SQLPP_VALUE_TRAIT_GENERATOR(is_using_) SQLPP_VALUE_TRAIT_GENERATOR(is_column_list) diff --git a/tests/Select.cpp b/tests/Select.cpp index 74edacfc..81307846 100644 --- a/tests/Select.cpp +++ b/tests/Select.cpp @@ -107,6 +107,14 @@ int Select(int, char* []) std::cout << a << ", " << b << ", " << g << std::endl; } + for (const auto& row : db(select(all_of(t).as(t), t.gamma).from(t).where(t.alpha > 7).for_update())) + { + 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; + } + for (const auto& row : db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).unconditionally())) {