diff --git a/dbms/src/Interpreters/Join.cpp b/dbms/src/Interpreters/Join.cpp index 0a56a208bf0..230ff8e55dd 100644 --- a/dbms/src/Interpreters/Join.cpp +++ b/dbms/src/Interpreters/Join.cpp @@ -401,13 +401,7 @@ namespace * We will insert each time the element into the second place. * That is, the former second element, if it was, will be the third, and so on. */ - auto elem = pool.alloc(); - auto & mapped = emplace_result.getMapped(); - - elem->next = mapped.next; - mapped.next = elem; - elem->block = stored_block; - elem->row_num = i; + emplace_result.getMapped().insert({stored_block, i}, pool); } } }; @@ -659,9 +653,9 @@ void addFoundRow(const typename Map::mapped_type & mapped, AddedColumns & added, if constexpr (STRICTNESS == ASTTableJoin::Strictness::All) { - for (auto current = &static_cast(mapped); current != nullptr; current = current->next) + for (auto it = mapped.begin(); it.ok(); ++it) { - added.appendFromBlock(*current->block, current->row_num); + added.appendFromBlock(*it->block, it->row_num); ++current_offset; } } @@ -1153,10 +1147,10 @@ struct AdderNonJoined { static void add(const Mapped & mapped, size_t & rows_added, MutableColumns & columns_right) { - for (auto current = &static_cast(mapped); current != nullptr; current = current->next) + for (auto it = mapped.begin(); it.ok(); ++it) { for (size_t j = 0; j < columns_right.size(); ++j) - columns_right[j]->insertFrom(*current->block->getByPosition(j).column.get(), current->row_num); + columns_right[j]->insertFrom(*it->block->getByPosition(j).column.get(), it->row_num); ++rows_added; } diff --git a/dbms/src/Interpreters/RowRefs.h b/dbms/src/Interpreters/RowRefs.h index 76efb33543d..7c79a11ffa7 100644 --- a/dbms/src/Interpreters/RowRefs.h +++ b/dbms/src/Interpreters/RowRefs.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -27,10 +28,39 @@ struct RowRef /// Single linked list of references to rows. Used for ALL JOINs (non-unique JOINs) struct RowRefList : RowRef { - RowRefList * next = nullptr; + class ForwardIterator + { + public: + ForwardIterator(const RowRefList * begin) + : current(begin) + {} + + const RowRef * operator -> () const { return current; } + void operator ++ () { current = current->next; } + bool ok() const { return current; } + + private: + const RowRefList * current; + }; RowRefList() {} RowRefList(const Block * block_, size_t row_num_) : RowRef(block_, row_num_) {} + + ForwardIterator begin() const { return ForwardIterator(this); } + + /// insert element after current one + void insert(RowRef && row_ref, Arena & pool) + { + auto elem = pool.alloc(); + elem->block = row_ref.block; + elem->row_num = row_ref.row_num; + + elem->next = next; + next = elem; + } + +private: + RowRefList * next = nullptr; }; /** diff --git a/dbms/src/Storages/StorageJoin.cpp b/dbms/src/Storages/StorageJoin.cpp index e7debe45107..1c9cca0dc21 100644 --- a/dbms/src/Storages/StorageJoin.cpp +++ b/dbms/src/Storages/StorageJoin.cpp @@ -338,14 +338,13 @@ private: throw Exception("ASOF join storage is not implemented yet", ErrorCodes::NOT_IMPLEMENTED); } else - for (auto current = &static_cast(it->getSecond()); current != nullptr; - current = current->next) + for (auto ref_it = it->getSecond().begin(); ref_it.ok(); ++ref_it) { for (size_t j = 0; j < columns.size(); ++j) if (j == key_pos) columns[j]->insertData(rawData(it->getFirst()), rawSize(it->getFirst())); else - columns[j]->insertFrom(*current->block->getByPosition(column_indices[j]).column.get(), current->row_num); + columns[j]->insertFrom(*ref_it->block->getByPosition(column_indices[j]).column.get(), ref_it->row_num); ++rows_added; }