| 1 | #pragma once |
| 2 | |
| 3 | #include <array> |
| 4 | #include <common/constexpr_helpers.h> |
| 5 | |
| 6 | #include <Interpreters/Join.h> |
| 7 | |
| 8 | |
| 9 | /** Used in implementation of Join to process different data structures. |
| 10 | */ |
| 11 | |
| 12 | namespace DB |
| 13 | { |
| 14 | |
| 15 | template <ASTTableJoin::Kind kind, typename ASTTableJoin::Strictness> |
| 16 | struct MapGetter; |
| 17 | |
| 18 | template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOne; }; |
| 19 | template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOne; }; |
| 20 | template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOneFlagged; }; |
| 21 | template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOneFlagged; }; |
| 22 | |
| 23 | template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Any> { using Map = Join::MapsOne; }; |
| 24 | template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Any> { using Map = Join::MapsOneFlagged; }; |
| 25 | template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::Any> { using Map = Join::MapsAllFlagged; }; |
| 26 | template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::Any> { using Map = Join::MapsAllFlagged; }; |
| 27 | |
| 28 | template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::All> { using Map = Join::MapsAll; }; |
| 29 | template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::All> { using Map = Join::MapsAll; }; |
| 30 | template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::All> { using Map = Join::MapsAllFlagged; }; |
| 31 | template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::All> { using Map = Join::MapsAllFlagged; }; |
| 32 | |
| 33 | /// Only SEMI LEFT and SEMI RIGHT are valid. INNER and FULL are here for templates instantiation. |
| 34 | template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsOne; }; |
| 35 | template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsOne; }; |
| 36 | template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsAllFlagged; }; |
| 37 | template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsOne; }; |
| 38 | |
| 39 | /// Only SEMI LEFT and SEMI RIGHT are valid. INNER and FULL are here for templates instantiation. |
| 40 | template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsOne; }; |
| 41 | template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsOne; }; |
| 42 | template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsAllFlagged; }; |
| 43 | template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsOne; }; |
| 44 | |
| 45 | template <ASTTableJoin::Kind kind> |
| 46 | struct MapGetter<kind, ASTTableJoin::Strictness::Asof> |
| 47 | { |
| 48 | using Map = Join::MapsAsof; |
| 49 | }; |
| 50 | |
| 51 | |
| 52 | static constexpr std::array<ASTTableJoin::Strictness, 6> STRICTNESSES = { |
| 53 | ASTTableJoin::Strictness::RightAny, |
| 54 | ASTTableJoin::Strictness::Any, |
| 55 | ASTTableJoin::Strictness::All, |
| 56 | ASTTableJoin::Strictness::Asof, |
| 57 | ASTTableJoin::Strictness::Semi, |
| 58 | ASTTableJoin::Strictness::Anti, |
| 59 | }; |
| 60 | |
| 61 | static constexpr std::array<ASTTableJoin::Kind, 4> KINDS = { |
| 62 | ASTTableJoin::Kind::Left, |
| 63 | ASTTableJoin::Kind::Inner, |
| 64 | ASTTableJoin::Kind::Full, |
| 65 | ASTTableJoin::Kind::Right |
| 66 | }; |
| 67 | |
| 68 | /// Init specified join map |
| 69 | inline bool joinDispatchInit(ASTTableJoin::Kind kind, ASTTableJoin::Strictness strictness, Join::MapsVariant & maps) |
| 70 | { |
| 71 | return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) |
| 72 | { |
| 73 | constexpr auto i = ij / STRICTNESSES.size(); |
| 74 | constexpr auto j = ij % STRICTNESSES.size(); |
| 75 | if (kind == KINDS[i] && strictness == STRICTNESSES[j]) |
| 76 | { |
| 77 | maps = typename MapGetter<KINDS[i], STRICTNESSES[j]>::Map(); |
| 78 | return true; |
| 79 | } |
| 80 | return false; |
| 81 | }); |
| 82 | } |
| 83 | |
| 84 | /// Call function on specified join map |
| 85 | template <typename MapsVariant, typename Func> |
| 86 | inline bool joinDispatch(ASTTableJoin::Kind kind, ASTTableJoin::Strictness strictness, MapsVariant & maps, Func && func) |
| 87 | { |
| 88 | return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) |
| 89 | { |
| 90 | // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways |
| 91 | // See https://stackoverflow.com/questions/44386415/gcc-and-clang-disagree-about-c17-constexpr-lambda-captures |
| 92 | constexpr auto i = ij / STRICTNESSES.size(); |
| 93 | constexpr auto j = ij % STRICTNESSES.size(); |
| 94 | if (kind == KINDS[i] && strictness == STRICTNESSES[j]) |
| 95 | { |
| 96 | func( |
| 97 | std::integral_constant<ASTTableJoin::Kind, KINDS[i]>(), |
| 98 | std::integral_constant<ASTTableJoin::Strictness, STRICTNESSES[j]>(), |
| 99 | std::get<typename MapGetter<KINDS[i], STRICTNESSES[j]>::Map>(maps)); |
| 100 | return true; |
| 101 | } |
| 102 | return false; |
| 103 | }); |
| 104 | } |
| 105 | |
| 106 | } |
| 107 | |