diff --git a/dbms/src/Interpreters/IJoin.cpp b/dbms/src/Interpreters/IJoin.cpp index 46497a8ed30..84c014efe22 100644 --- a/dbms/src/Interpreters/IJoin.cpp +++ b/dbms/src/Interpreters/IJoin.cpp @@ -32,6 +32,22 @@ void convertColumnsToNullable(Block & block, size_t starting_pos) convertColumnToNullable(block.getByPosition(i)); } +ColumnRawPtrs temporaryMaterializeColumns(const Block & block, const Names & names, Columns & materialized) +{ + ColumnRawPtrs ptrs; + ptrs.reserve(names.size()); + materialized.reserve(names.size()); + + for (auto & column_name : names) + { + const auto & src_column = block.getByName(column_name).column; + materialized.emplace_back(recursiveRemoveLowCardinality(src_column->convertToFullColumnIfConst())); + ptrs.push_back(materialized.back().get()); + } + + return ptrs; +} + ColumnRawPtrs extractKeysForJoin(const Names & key_names_right, const Block & right_sample_block, Block & sample_block_with_keys, Block & sample_block_with_columns_to_add) { diff --git a/dbms/src/Interpreters/IJoin.h b/dbms/src/Interpreters/IJoin.h index 42eada1c43e..e716a1335bb 100644 --- a/dbms/src/Interpreters/IJoin.h +++ b/dbms/src/Interpreters/IJoin.h @@ -4,6 +4,7 @@ #include #include +#include namespace DB { @@ -41,6 +42,7 @@ namespace JoinCommon void convertColumnToNullable(ColumnWithTypeAndName & column); void convertColumnsToNullable(Block & block, size_t starting_pos = 0); +ColumnRawPtrs temporaryMaterializeColumns(const Block & block, const Names & names, Columns & materialized); /// Split key and other columns by keys name list ColumnRawPtrs extractKeysForJoin(const Names & key_names_right, const Block & right_sample_block, diff --git a/dbms/src/Interpreters/Join.cpp b/dbms/src/Interpreters/Join.cpp index 6b3d9351740..f064eaf0be1 100644 --- a/dbms/src/Interpreters/Join.cpp +++ b/dbms/src/Interpreters/Join.cpp @@ -453,19 +453,9 @@ bool Join::addJoinedBlock(const Block & block) if (empty()) throw Exception("Logical error: Join was not initialized", ErrorCodes::LOGICAL_ERROR); - size_t keys_size = key_names_right.size(); - ColumnRawPtrs key_columns(keys_size); - /// Rare case, when keys are constant. To avoid code bloat, simply materialize them. Columns materialized_columns; - materialized_columns.reserve(keys_size); - - /// Memoize key columns to work. - for (size_t i = 0; i < keys_size; ++i) - { - materialized_columns.emplace_back(recursiveRemoveLowCardinality(block.getByName(key_names_right[i]).column->convertToFullColumnIfConst())); - key_columns[i] = materialized_columns.back().get(); - } + ColumnRawPtrs key_columns = JoinCommon::temporaryMaterializeColumns(block, key_names_right, materialized_columns); /// We will insert to the map only keys, where all components are not NULL. ConstNullMapPtr null_map{}; @@ -478,15 +468,12 @@ bool Join::addJoinedBlock(const Block & block) prepareBlockListStructure(*stored_block); - size_t size = stored_block->columns(); - /// Rare case, when joined columns are constant. To avoid code bloat, simply materialize them. - for (size_t i = 0; i < size; ++i) - stored_block->safeGetByPosition(i).column = stored_block->safeGetByPosition(i).column->convertToFullColumnIfConst(); + *stored_block = materializeBlock(*stored_block); /// In case of LEFT and FULL joins, if use_nulls, convert joined columns to Nullable. if (use_nulls && isLeftOrFull(kind)) - JoinCommon::convertColumnsToNullable(*stored_block, (isFull(kind) ? keys_size : 0)); + JoinCommon::convertColumnsToNullable(*stored_block, (isFull(kind) ? key_names_right.size() : 0)); if (kind != ASTTableJoin::Kind::Cross) { @@ -723,19 +710,9 @@ void Join::joinBlockImpl( const Block & block_with_columns_to_add, const Maps & maps_) const { - size_t keys_size = key_names_left.size(); - ColumnRawPtrs key_columns(keys_size); - /// Rare case, when keys are constant. To avoid code bloat, simply materialize them. Columns materialized_columns; - materialized_columns.reserve(keys_size); - - /// Memoize key columns to work with. - for (size_t i = 0; i < keys_size; ++i) - { - materialized_columns.emplace_back(recursiveRemoveLowCardinality(block.getByName(key_names_left[i]).column->convertToFullColumnIfConst())); - key_columns[i] = materialized_columns.back().get(); - } + ColumnRawPtrs key_columns = JoinCommon::temporaryMaterializeColumns(block, key_names_left, materialized_columns); /// Keys with NULL value in any column won't join to anything. ConstNullMapPtr null_map{};