/* * Copyright (c) 2013-2015, 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_WITH_H #define SQLPP_WITH_H #include #include #include #include #include #include #include #include #include #include #include #include namespace sqlpp { template struct with_data_t { using _is_recursive = logic::any_t; with_data_t(Expressions... expressions): _expressions(expressions...) {} with_data_t(const with_data_t&) = default; with_data_t(with_data_t&&) = default; with_data_t& operator=(const with_data_t&) = default; with_data_t& operator=(with_data_t&&) = default; ~with_data_t() = default; std::tuple _expressions; }; template struct with_t { using _traits = make_traits; using _nodes = detail::type_vector<>; using _provided_ctes = detail::make_joined_set_t...>; // WITH provides common table expressions using _parameters = detail::type_vector_cat_t...>; using _is_dynamic = is_database; // Data using _data_t = with_data_t; // Member implementation with data and methods template struct _impl_t { public: _data_t _data; }; // Base template to be inherited by the statement template struct _base_t { using _data_t = with_data_t; _impl_t with; _impl_t& operator()() { return with; } const _impl_t& operator()() const { return with; } template static auto _get_member(T t) -> decltype(t.with) { return t.with; } // FIXME: Need real checks here using _consistency_check = consistent_t; }; }; struct no_with_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 { _data_t _data; }; // Base template to be inherited by the statement template struct _base_t { using _data_t = no_data_t; _impl_t no_with; _impl_t& operator()() { return no_with; } const _impl_t& operator()() const { return no_with; } template static auto _get_member(T t) -> decltype(t.no_with) { return t.no_with; } using _consistency_check = consistent_t; }; }; template struct blank_with_t { with_data_t _data; template auto operator()(Statement statement) -> new_statement_t> { // FIXME need checks here // check that no cte refers to any of the ctes to the right return { statement, _data }; } }; // Interpreters template struct serializer_t> { using _serialize_check = serialize_check_of; using T = with_data_t; static Context& _(const T& t, Context& context) { // FIXME: If there is a recursive CTE, add a "RECURSIVE" here context << " WITH "; if (T::_is_recursive::value) context << "RECURSIVE "; interpret_tuple(t._expressions, ',', context); context << ' '; return context; } }; template auto with(Expressions... cte) -> blank_with_t { static_assert(logic::all_t::value...>::value, "at least one expression in with is not a common table expression"); static_assert(logic::none_t::value...>::value, "at least one expression in with is an incomplete common table expression"); return { {cte...} }; } } #endif