| 1 | #pragma once |
| 2 | |
| 3 | #include "Algorithms.h" |
| 4 | #include "ArraySourceVisitor.h" |
| 5 | #include "ArraySinkVisitor.h" |
| 6 | #include "ValueSourceVisitor.h" |
| 7 | |
| 8 | |
| 9 | namespace DB::GatherUtils |
| 10 | { |
| 11 | /// Base classes which selects template function implementation with concrete ArraySource or ArraySink |
| 12 | /// Derived classes should implement selectImpl for ArraySourceSelector and ArraySinkSelector, |
| 13 | /// selectSourceSink for ArraySinkSourceSelector and selectSourcePair for ArraySourcePairSelector |
| 14 | |
| 15 | template <typename Base, typename Tuple, int index, typename ... Args> |
| 16 | void callSelectMemberFunctionWithTupleArgument(Tuple & tuple, Args && ... args) |
| 17 | { |
| 18 | if constexpr (index == std::tuple_size<Tuple>::value) |
| 19 | Base::selectImpl(args ...); |
| 20 | else |
| 21 | callSelectMemberFunctionWithTupleArgument<Base, Tuple, index + 1>(tuple, args ..., std::get<index>(tuple)); |
| 22 | } |
| 23 | |
| 24 | template <typename Base, typename ... Args> |
| 25 | struct ArraySourceSelectorVisitor : public ArraySourceVisitorImpl<ArraySourceSelectorVisitor<Base, Args ...>> |
| 26 | { |
| 27 | explicit ArraySourceSelectorVisitor(Args && ... args) : packed_args(args ...) {} |
| 28 | |
| 29 | using Tuple = std::tuple<Args && ...>; |
| 30 | |
| 31 | template <typename Source> |
| 32 | void visitImpl(Source & source) |
| 33 | { |
| 34 | callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source); |
| 35 | } |
| 36 | |
| 37 | Tuple packed_args; |
| 38 | }; |
| 39 | |
| 40 | template <typename Base> |
| 41 | struct ArraySourceSelector |
| 42 | { |
| 43 | template <typename ... Args> |
| 44 | static void select(IArraySource & source, Args && ... args) |
| 45 | { |
| 46 | ArraySourceSelectorVisitor<Base, Args ...> visitor(args ...); |
| 47 | source.accept(visitor); |
| 48 | } |
| 49 | }; |
| 50 | |
| 51 | |
| 52 | template <typename Base, typename ... Args> |
| 53 | struct ArraySinkSelectorVisitor : public ArraySinkVisitorImpl<ArraySinkSelectorVisitor<Base, Args ...>> |
| 54 | { |
| 55 | explicit ArraySinkSelectorVisitor(Args && ... args) : packed_args(args ...) {} |
| 56 | |
| 57 | using Tuple = std::tuple<Args && ...>; |
| 58 | |
| 59 | template <typename Sink> |
| 60 | void visitImpl(Sink & sink) |
| 61 | { |
| 62 | callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, sink); |
| 63 | } |
| 64 | |
| 65 | Tuple packed_args; |
| 66 | }; |
| 67 | |
| 68 | template <typename Base> |
| 69 | struct ArraySinkSelector |
| 70 | { |
| 71 | template <typename ... Args> |
| 72 | static void select(IArraySink & sink, Args && ... args) |
| 73 | { |
| 74 | ArraySinkSelectorVisitor<Base, Args ...> visitor(args ...); |
| 75 | sink.accept(visitor); |
| 76 | } |
| 77 | }; |
| 78 | |
| 79 | |
| 80 | template <typename Base, typename ... Args> |
| 81 | struct ValueSourceSelectorVisitor : public ValueSourceVisitorImpl<ValueSourceSelectorVisitor<Base, Args ...>> |
| 82 | { |
| 83 | explicit ValueSourceSelectorVisitor(Args && ... args) : packed_args(args ...) {} |
| 84 | |
| 85 | using Tuple = std::tuple<Args && ...>; |
| 86 | |
| 87 | template <typename Source> |
| 88 | void visitImpl(Source & source) |
| 89 | { |
| 90 | callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source); |
| 91 | } |
| 92 | |
| 93 | Tuple packed_args; |
| 94 | }; |
| 95 | |
| 96 | template <typename Base> |
| 97 | struct ValueSourceSelector |
| 98 | { |
| 99 | template <typename ... Args> |
| 100 | static void select(IValueSource & source, Args && ... args) |
| 101 | { |
| 102 | ValueSourceSelectorVisitor<Base, Args ...> visitor(args ...); |
| 103 | source.accept(visitor); |
| 104 | } |
| 105 | }; |
| 106 | |
| 107 | template <typename Base> |
| 108 | struct ArraySinkSourceSelector |
| 109 | { |
| 110 | template <typename ... Args> |
| 111 | static void select(IArraySource & source, IArraySink & sink, Args && ... args) |
| 112 | { |
| 113 | ArraySinkSelector<Base>::select(sink, source, args ...); |
| 114 | } |
| 115 | |
| 116 | template <typename Sink, typename ... Args> |
| 117 | static void selectImpl(Sink && sink, IArraySource & source, Args && ... args) |
| 118 | { |
| 119 | ArraySourceSelector<Base>::select(source, sink, args ...); |
| 120 | } |
| 121 | |
| 122 | template <typename Source, typename Sink, typename ... Args> |
| 123 | static void selectImpl(Source && source, Sink && sink, Args && ... args) |
| 124 | { |
| 125 | Base::selectSourceSink(source, sink, args ...); |
| 126 | } |
| 127 | }; |
| 128 | |
| 129 | template <typename Base> |
| 130 | struct ArraySourcePairSelector |
| 131 | { |
| 132 | template <typename ... Args> |
| 133 | static void select(IArraySource & first, IArraySource & second, Args && ... args) |
| 134 | { |
| 135 | ArraySourceSelector<Base>::select(first, second, args ...); |
| 136 | } |
| 137 | |
| 138 | template <typename FirstSource, typename ... Args> |
| 139 | static void selectImpl(FirstSource && first, IArraySource & second, Args && ... args) |
| 140 | { |
| 141 | ArraySourceSelector<Base>::select(second, first, args ...); |
| 142 | } |
| 143 | |
| 144 | template <typename SecondSource, typename FirstSource, typename ... Args> |
| 145 | static void selectImpl(SecondSource && second, FirstSource && first, Args && ... args) |
| 146 | { |
| 147 | Base::selectSourcePair(first, second, args ...); |
| 148 | } |
| 149 | }; |
| 150 | |
| 151 | template <typename Base> |
| 152 | struct ArrayAndValueSourceSelectorBySink : public ArraySinkSelector<ArrayAndValueSourceSelectorBySink<Base>> |
| 153 | { |
| 154 | template <typename Sink, typename ... Args> |
| 155 | static void selectImpl(Sink && sink, IArraySource & array_source, IValueSource & value_source, Args && ... args) |
| 156 | { |
| 157 | using SynkType = typename std::decay<Sink>::type; |
| 158 | using ArraySource = typename SynkType::CompatibleArraySource; |
| 159 | using ValueSource = typename SynkType::CompatibleValueSource; |
| 160 | |
| 161 | auto checkType = [] (auto source_ptr) |
| 162 | { |
| 163 | if (source_ptr == nullptr) |
| 164 | throw Exception(demangle(typeid(Base).name()) + " expected " |
| 165 | + demangle(typeid(typename SynkType::CompatibleArraySource).name()) |
| 166 | + " or " + demangle(typeid(ConstSource<typename SynkType::CompatibleArraySource>).name()) |
| 167 | + " or " + demangle(typeid(typename SynkType::CompatibleValueSource).name()) + |
| 168 | + " or " + demangle(typeid(ConstSource<typename SynkType::CompatibleValueSource>).name()) |
| 169 | + " but got " + demangle(typeid(*source_ptr).name()), ErrorCodes::LOGICAL_ERROR); |
| 170 | }; |
| 171 | auto checkTypeAndCallConcat = [& sink, & checkType, & args ...] (auto array_source_ptr, auto value_source_ptr) |
| 172 | { |
| 173 | checkType(array_source_ptr); |
| 174 | checkType(value_source_ptr); |
| 175 | |
| 176 | Base::selectArrayAndValueSourceBySink(*array_source_ptr, *value_source_ptr, sink, args ...); |
| 177 | }; |
| 178 | |
| 179 | if (array_source.isConst() && value_source.isConst()) |
| 180 | checkTypeAndCallConcat(typeid_cast<ConstSource<ArraySource> *>(&array_source), |
| 181 | typeid_cast<ConstSource<ValueSource> *>(&value_source)); |
| 182 | else if (array_source.isConst()) |
| 183 | checkTypeAndCallConcat(typeid_cast<ConstSource<ArraySource> *>(&array_source), |
| 184 | typeid_cast<ValueSource *>(&value_source)); |
| 185 | else if (value_source.isConst()) |
| 186 | checkTypeAndCallConcat(typeid_cast<ArraySource *>(&array_source), |
| 187 | typeid_cast<ConstSource<ValueSource> *>(&value_source)); |
| 188 | else |
| 189 | checkTypeAndCallConcat(typeid_cast<ArraySource *>(&array_source), |
| 190 | typeid_cast<ValueSource *>(&value_source)); |
| 191 | } |
| 192 | }; |
| 193 | |
| 194 | } |
| 195 | |