#pragma once #include #include #include /** Used in implementation of Join to process different data structures. */ namespace DB { template struct MapGetter; template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsOneFlagged; }; template <> struct MapGetter { using Map = Join::MapsOneFlagged; }; template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsOneFlagged; }; template <> struct MapGetter { using Map = Join::MapsAllFlagged; }; template <> struct MapGetter { using Map = Join::MapsAllFlagged; }; template <> struct MapGetter { using Map = Join::MapsAll; }; template <> struct MapGetter { using Map = Join::MapsAll; }; template <> struct MapGetter { using Map = Join::MapsAllFlagged; }; template <> struct MapGetter { using Map = Join::MapsAllFlagged; }; /// Only SEMI LEFT and SEMI RIGHT are valid. INNER and FULL are here for templates instantiation. template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsAllFlagged; }; template <> struct MapGetter { using Map = Join::MapsOne; }; /// Only SEMI LEFT and SEMI RIGHT are valid. INNER and FULL are here for templates instantiation. template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsOne; }; template <> struct MapGetter { using Map = Join::MapsAllFlagged; }; template <> struct MapGetter { using Map = Join::MapsOne; }; template struct MapGetter { using Map = Join::MapsAsof; }; static constexpr std::array STRICTNESSES = { ASTTableJoin::Strictness::RightAny, ASTTableJoin::Strictness::Any, ASTTableJoin::Strictness::All, ASTTableJoin::Strictness::Asof, ASTTableJoin::Strictness::Semi, ASTTableJoin::Strictness::Anti, }; static constexpr std::array KINDS = { ASTTableJoin::Kind::Left, ASTTableJoin::Kind::Inner, ASTTableJoin::Kind::Full, ASTTableJoin::Kind::Right }; /// Init specified join map inline bool joinDispatchInit(ASTTableJoin::Kind kind, ASTTableJoin::Strictness strictness, Join::MapsVariant & maps) { return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) { constexpr auto i = ij / STRICTNESSES.size(); constexpr auto j = ij % STRICTNESSES.size(); if (kind == KINDS[i] && strictness == STRICTNESSES[j]) { maps = typename MapGetter::Map(); return true; } return false; }); } /// Call function on specified join map template inline bool joinDispatch(ASTTableJoin::Kind kind, ASTTableJoin::Strictness strictness, MapsVariant & maps, Func && func) { return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) { // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways // See https://stackoverflow.com/questions/44386415/gcc-and-clang-disagree-about-c17-constexpr-lambda-captures constexpr auto i = ij / STRICTNESSES.size(); constexpr auto j = ij % STRICTNESSES.size(); if (kind == KINDS[i] && strictness == STRICTNESSES[j]) { func( std::integral_constant(), std::integral_constant(), std::get::Map>(maps)); return true; } return false; }); } }