/* * Copyright (c) 2013-2016, 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 SQLPP11_UNION_H #define SQLPP11_UNION_H #include #include #include #include #include #include #include #include #include #include namespace sqlpp { struct no_union_t; using blank_union_t = statement_t; // There is no order by or limit or offset in union, use it as a pseudo table to do that. template struct union_statement_impl { using type = Check; }; template struct union_statement_impl { using type = statement_t; }; template using union_statement_t = typename union_statement_impl::type; // UNION(EXPR) template struct union_t { using _traits = make_traits; using _nodes = detail::type_vector; using _alias_t = struct { }; // Data using _data_t = union_data_t; // Member implementation with data and methods template struct _impl_t { // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269 _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 = union_data_t; // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269 template _base_t(Args&&... args) : union_{std::forward(args)...} { } _impl_t union_; _impl_t& operator()() { return union_; } const _impl_t& operator()() const { return union_; } using _selected_columns_t = typename std::decay::type; _selected_columns_t& get_selected_columns() { return union_._data._lhs.get_selected_columns(); } const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.get_selected_columns(); } template static auto _get_member(T t) -> decltype(t.union_) { return t.union_; } using _consistency_check = detail::get_first_if; }; template using _result_methods_t = typename Lhs::template _result_methods_t; }; SQLPP_PORTABLE_STATIC_ASSERT(assert_union_args_are_statements_t, "arguments for union() must be statements"); template struct check_union { using type = static_combined_check_t< static_check_t::value...>::value, assert_union_args_are_statements_t>>; }; template using check_union_t = typename check_union::type; // NO UNION YET struct no_union_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/2173269 _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/2173269 template _base_t(Args&&... args) : no_union{std::forward(args)...} { } _impl_t no_union; _impl_t& operator()() { return no_union; } const _impl_t& operator()() const { return no_union; } template static auto _get_member(T t) -> decltype(t.no_union) { return t.no_union; } using _database_t = typename Policies::_database_t; template using _new_statement_t = union_statement_t; using _consistency_check = consistent_t; template auto union_distinct(Rhs rhs) const -> _new_statement_t, Rhs>, union_t, Rhs>> { static_assert(is_statement_t::value, "argument of union call has to be a statement"); static_assert(has_policy_t::value, "argument of union call has to be a select"); static_assert(has_result_row_t::value, "argument of a union has to be a complete select statement"); static_assert(has_result_row_t>::value, "left hand side argument of a union has to be a complete select statement or union"); using lhs_result_row_t = get_result_row_t>; using rhs_result_row_t = get_result_row_t; static_assert(is_result_compatible::value, "both arguments in a union have to have the same result columns (type and name)"); return _union_impl(check_union_t, Rhs>{}, rhs); } template auto union_all(Rhs rhs) const -> _new_statement_t, Rhs>, union_t, Rhs>> { static_assert(is_statement_t::value, "argument of union call has to be a statement"); static_assert(has_policy_t::value, "argument of union call has to be a select"); static_assert(has_result_row_t::value, "argument of a union has to be a (complete) select statement"); static_assert(has_result_row_t>::value, "left hand side argument of a union has to be a (complete) select statement"); using lhs_result_row_t = get_result_row_t>; using rhs_result_row_t = get_result_row_t; static_assert(is_result_compatible::value, "both arguments in a union have to have the same result columns (type and name)"); return _union_impl(check_union_t, Rhs>{}, rhs); } private: template auto _union_impl(Check, Rhs rhs) const -> inconsistent; template auto _union_impl(consistent_t /*unused*/, Rhs rhs) const -> _new_statement_t, Rhs>> { return {blank_union_t{}, union_data_t, Rhs>{ static_cast&>(*this), rhs}}; } }; }; /* template auto union_all(T&& t) -> decltype(statement_t().union_all(std::forward(t))) { return statement_t().union_all(std::forward(t)); } template auto union_distinct(T&& t) -> decltype(statement_t().union_distinct(std::forward(t))) { return statement_t().union_distinct(std::forward(t)); } */ } // namespace sqlpp #endif