From 18b36bf46a3361767186dbcc41d669f29dc062e9 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 12 Feb 2015 18:05:19 +0100 Subject: [PATCH] recursive ctes seem to be basically working --- include/sqlpp11/cte.h | 101 ++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/include/sqlpp11/cte.h b/include/sqlpp11/cte.h index d1c3432f..f84f3816 100644 --- a/include/sqlpp11/cte.h +++ b/include/sqlpp11/cte.h @@ -28,7 +28,6 @@ #define SQLPP_CTE_H #include -#include #include #include #include @@ -41,20 +40,70 @@ namespace sqlpp { - template + template + struct cte_union_t + { + struct _recursive_traits + { + using _required_ctes = detail::make_joined_set_t, required_ctes_of>; + using _provided_ctes = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _provided_tables = detail::type_set<>; + using _provided_outer_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + using _parameters = detail::make_parameter_tuple_t, parameters_of>; + using _tags = detail::type_set<>; + }; + + cte_union_t(Lhs lhs, Rhs rhs): + _lhs(lhs), + _rhs(rhs) + {} + + cte_union_t(const cte_union_t&) = default; + cte_union_t(cte_union_t&&) = default; + cte_union_t& operator=(const cte_union_t&) = default; + cte_union_t& operator=(cte_union_t&&) = default; + ~cte_union_t() = default; + + Lhs _lhs; + Rhs _rhs; + }; + + // Interpreters + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = cte_union_t; + + static Context& _(const T& t, Context& context) + { + context << '('; + serialize(t._lhs, context); + context << ") UNION "; + serialize(Flag{}, context); + context << " ("; + serialize(t._rhs, context); + context << ')'; + return context; + } + }; + + template struct cte_t; template struct cte_ref_t; - template - auto from_table(cte_t t) -> cte_ref_t + template + auto from_table(cte_t t) -> cte_ref_t { return cte_ref_t{}; } - template - struct from_table_impl> + template + struct from_table_impl> { using type = cte_ref_t; }; @@ -81,50 +130,45 @@ namespace sqlpp template struct make_cte_impl> { - using type = cte_t; + using type = cte_t; }; template using make_cte_t = typename make_cte_impl>::type; - template - struct cte_union_is_recursive - { - static constexpr bool value = Lhs or detail::is_element_of>::value; - }; - - template + template struct cte_t: public member_t, column_t>>... { using _traits = make_traits; // FIXME: is table? really? struct _recursive_traits { - using _required_ctes = detail::make_joined_set_t, detail::make_type_set_t>; + using _required_ctes = detail::make_joined_set_t, detail::type_set>; using _provided_ctes = detail::type_set<>; using _required_tables = detail::type_set<>; - using _provided_tables = detail::type_set; + using _provided_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>; using _extra_tables = detail::type_set<>; using _parameters = parameters_of; using _tags = detail::type_set<>; }; using _alias_t = typename AliasProvider::_alias_t; - constexpr static bool _is_recursive = Recursive; + constexpr static bool _is_recursive = detail::is_element_of>::value; using _column_tuple_t = std::tuple>...>; template using _check = logic::all_t::value...>; + using _result_row_t = result_row_t; + template auto union_distinct(Rhs rhs) const - -> typename std::conditional<_check::value, cte_t::value, union_data_t, FieldSpecs...>, bad_statement>::type + -> typename std::conditional<_check::value, cte_t, FieldSpecs...>, bad_statement>::type { 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"); - using _result_row_t = result_row_t; static_assert(std::is_same<_result_row_t, get_result_row_t>::value, "both select statements in a union have to have the same result columns (type and name)"); return _union_impl(_check{}, rhs); @@ -132,28 +176,27 @@ namespace sqlpp template auto union_all(Rhs rhs) const - -> typename std::conditional<_check::value, cte_t::value, union_data_t, FieldSpecs...>, bad_statement>::type + -> typename std::conditional<_check::value, cte_t, FieldSpecs...>, bad_statement>::type { 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"); - using _result_row_t = result_row_t; static_assert(std::is_same<_result_row_t, get_result_row_t>::value, "both select statements in a union have to have the same result columns (type and name)"); - return _union_impl(_check{}, rhs); + return _union_impl(_check{}, rhs); } private: - template + template auto _union_impl(const std::false_type&, Rhs rhs) const -> bad_statement; - template + template auto _union_impl(const std::true_type&, Rhs rhs) const - -> cte_t::value, union_data_t, FieldSpecs...> + -> cte_t, FieldSpecs...> { - return union_data_t{_statement, rhs}; + return cte_union_t{_statement, rhs}; } public: @@ -168,11 +211,11 @@ namespace sqlpp Statement _statement; }; - template - struct serializer_t> + template + struct serializer_t> { using _serialize_check = serialize_check_of; - using T = cte_t; + using T = cte_t; static Context& _(const T& t, Context& context) {