#include #include #include #include #include namespace DB { namespace { /// maps enum values to types template void callWithType(AsofRowRefs::Type which, F && f) { switch (which) { case AsofRowRefs::Type::key32: return f(UInt32()); case AsofRowRefs::Type::key64: return f(UInt64()); case AsofRowRefs::Type::keyf32: return f(Float32()); case AsofRowRefs::Type::keyf64: return f(Float64()); } __builtin_unreachable(); } } AsofRowRefs::AsofRowRefs(Type type) { auto call = [&](const auto & t) { using T = std::decay_t; using LookupType = typename Entry::LookupType; lookups = std::make_unique(); }; callWithType(type, call); } void AsofRowRefs::insert(Type type, const IColumn * asof_column, const Block * block, size_t row_num) { auto call = [&](const auto & t) { using T = std::decay_t; using LookupPtr = typename Entry::LookupPtr; auto * column = typeid_cast *>(asof_column); T key = column->getElement(row_num); auto entry = Entry(key, RowRef(block, row_num)); std::get(lookups)->insert(entry); }; callWithType(type, call); } const RowRef * AsofRowRefs::findAsof(Type type, const IColumn * asof_column, size_t row_num) const { const RowRef * out = nullptr; auto call = [&](const auto & t) { using T = std::decay_t; using LookupPtr = typename Entry::LookupPtr; auto * column = typeid_cast *>(asof_column); T key = column->getElement(row_num); auto & typed_lookup = std::get(lookups); // The first thread that calls upper_bound ensures that the data is sorted auto it = typed_lookup->upper_bound(Entry(key)); // cbegin() is safe to call now because the array is immutable after sorting // hence the pointer to a entry can be returned if (it != typed_lookup->cbegin()) out = &((--it)->row_ref); }; callWithType(type, call); return out; } std::optional AsofRowRefs::getTypeSize(const IColumn * asof_column, size_t & size) { if (typeid_cast *>(asof_column)) { size = sizeof(UInt32); return Type::key32; } else if (typeid_cast *>(asof_column)) { size = sizeof(UInt64); return Type::key64; } else if (typeid_cast *>(asof_column)) { size = sizeof(Float32); return Type::keyf32; } else if (typeid_cast *>(asof_column)) { size = sizeof(Float64); return Type::keyf64; } size = 0; return {}; } }