88#include " Ref.hpp"
99#include " Result.hpp"
1010#include " dynamic/Union.hpp"
11- #include " internal/all_same_v.hpp"
1211#include " internal/is_range.hpp"
1312#include " internal/iterator_t.hpp"
1413#include " is_connection.hpp"
1514#include " transpilation/fields_to_named_tuple_t.hpp"
16- #include " transpilation/table_tuple_t.hpp"
1715#include " transpilation/to_union.hpp"
1816#include " transpilation/value_t.hpp"
1917
2018namespace sqlgen {
2119
22- template <class ContainerType , class Connection , class ... Selects >
20+ template <class ContainerType , class Connection , class ... SelectTs >
2321 requires is_connection<Connection>
2422auto unite_impl (const Ref<Connection>& _conn,
25- const rfl::Tuple<Selects ...>& _selects) {
23+ const rfl::Tuple<SelectTs ...>& _selects) {
2624 if constexpr (internal::is_range_v<ContainerType>) {
2725 const auto query = transpilation::to_union<ContainerType>(_selects);
2826 return _conn->template read <ContainerType>(query);
@@ -42,32 +40,28 @@ auto unite_impl(const Ref<Connection>& _conn,
4240 return container;
4341 };
4442
45- using NamedTupleTypes = rfl::Tuple<transpilation::fields_to_named_tuple_t <
46- transpilation::table_tuple_t <typename Selects::TableOrQueryType,
47- typename Selects::AliasType,
48- typename Selects::JoinsType>,
49- typename Selects::FieldsType>...>;
50-
51- static_assert (
52- internal::all_same_v<NamedTupleTypes>,
53- " All SELECT statements in a UNION must return the same columns with "
54- " the same types." );
55-
56- using IteratorType =
57- internal::iterator_t <rfl::tuple_element_t <0 , NamedTupleTypes>,
58- decltype (_conn)>;
43+ using IteratorType = internal::iterator_t <
44+ transpilation::fields_to_named_tuple_t <rfl::Tuple<SelectTs...>>,
45+ decltype (_conn)>;
5946
6047 using RangeType = Range<IteratorType>;
6148
6249 return unite_impl<RangeType>(_conn, _selects).and_then (to_container);
6350 }
6451}
6552
66- template <class ContainerType , class ... Selects >
53+ template <class _ContainerType , class ... SelectTs >
6754struct Union {
6855 template <class Connection >
6956 requires is_connection<Connection>
7057 auto operator ()(const Ref<Connection>& _conn) const {
58+ using ContainerType = std::conditional_t <
59+ std::is_same_v<std::remove_cvref_t <_ContainerType>, Nothing>,
60+ Range<internal::iterator_t <
61+ transpilation::fields_to_named_tuple_t <rfl::Tuple<SelectTs...>>,
62+ Connection>>,
63+ _ContainerType>;
64+
7165 return unite_impl<ContainerType>(_conn, selects_);
7266 }
7367
@@ -77,12 +71,37 @@ struct Union {
7771 return _res.and_then ([&](const auto & _conn) { return (*this )(_conn); });
7872 }
7973
80- rfl::Tuple<Selects...> selects_;
74+ rfl::Tuple<SelectTs...> selects_;
75+ };
76+
77+ namespace transpilation {
78+
79+ template <class ContainerType , class ... SelectTs>
80+ struct ExtractTable <Union<ContainerType, SelectTs...>, false > {
81+ using Type = std::conditional_t <
82+ std::is_same_v<std::remove_cvref_t <ContainerType>, Nothing>,
83+ transpilation::fields_to_named_tuple_t <rfl::Tuple<SelectTs...>>,
84+ transpilation::value_t <ContainerType>>;
8185};
8286
83- template <class ContainerType , class ... Selects>
84- auto unite (const Selects&... _selects) {
85- return Union<ContainerType, Selects...>{rfl::Tuple<Selects...>(_selects...)};
87+ template <class ContainerType , class ... SelectTs>
88+ struct ToTableOrQuery <Union<ContainerType, SelectTs...>> {
89+ dynamic::SelectFrom::TableOrQueryType operator ()(const auto & _query) {
90+ return transpilation::to_union<ContainerType>(_query.selects_ );
91+ }
92+ };
93+
94+ } // namespace transpilation
95+
96+ template <class ContainerType , class ... SelectTs>
97+ auto unite (const SelectTs&... _selects) {
98+ return Union<ContainerType, SelectTs...>{
99+ rfl::Tuple<SelectTs...>(_selects...)};
100+ }
101+
102+ template <class ... SelectTs>
103+ auto unite (const SelectTs&... _selects) {
104+ return unite<Nothing>(_selects...);
86105}
87106
88107} // namespace sqlgen
0 commit comments