#include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int LOGICAL_ERROR; } template IColumn::Selector createBlockSelector( const IColumn & column, const std::vector & slots) { const auto total_weight = slots.size(); if (total_weight == 0) throw Exception(ErrorCodes::LOGICAL_ERROR, "weight is zero"); size_t num_rows = column.size(); IColumn::Selector selector(num_rows); /** Modulo of division of negative numbers to positive number in C++11 is negative (so called truncated division). * This is not suitable for our task. So we will process signed numbers as unsigned. * It is not near like remainder of division, but is suitable for our task. */ using UnsignedT = make_unsigned_t; /// const columns contain only one value, therefore we do not need to read it at every iteration if (isColumnConst(column)) { const auto data = assert_cast(column).getValue(); const auto shard_num = slots[static_cast(data) % total_weight]; selector.assign(num_rows, shard_num); } else { /// libdivide support only UInt32 and UInt64. using TUInt32Or64 = std::conditional_t; libdivide::divider divider(static_cast(total_weight)); const auto & data = typeid_cast &>(column).getData(); for (size_t i = 0; i < num_rows; ++i) selector[i] = slots[static_cast(data[i]) - (static_cast(data[i]) / divider) * total_weight]; } return selector; } /// Explicit instantiations to avoid code bloat in headers. template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, const std::vector & slots); }