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 | |