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
12namespace DB
13{
14
15template <ASTTableJoin::Kind kind, typename ASTTableJoin::Strictness>
16struct MapGetter;
17
18template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOne; };
19template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOne; };
20template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOneFlagged; };
21template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::RightAny> { using Map = Join::MapsOneFlagged; };
22
23template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Any> { using Map = Join::MapsOne; };
24template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Any> { using Map = Join::MapsOneFlagged; };
25template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::Any> { using Map = Join::MapsAllFlagged; };
26template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::Any> { using Map = Join::MapsAllFlagged; };
27
28template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::All> { using Map = Join::MapsAll; };
29template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::All> { using Map = Join::MapsAll; };
30template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::All> { using Map = Join::MapsAllFlagged; };
31template <> 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.
34template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsOne; };
35template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsOne; };
36template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::Semi> { using Map = Join::MapsAllFlagged; };
37template <> 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.
40template <> struct MapGetter<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsOne; };
41template <> struct MapGetter<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsOne; };
42template <> struct MapGetter<ASTTableJoin::Kind::Right, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsAllFlagged; };
43template <> struct MapGetter<ASTTableJoin::Kind::Full, ASTTableJoin::Strictness::Anti> { using Map = Join::MapsOne; };
44
45template <ASTTableJoin::Kind kind>
46struct MapGetter<kind, ASTTableJoin::Strictness::Asof>
47{
48 using Map = Join::MapsAsof;
49};
50
51
52static 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
61static 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
69inline 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
85template <typename MapsVariant, typename Func>
86inline 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