提交 5f1007a8 编写于 作者: N Nikolai Kochetov

Refactor Join.

上级 e8aa41b6
......@@ -36,10 +36,10 @@ using HashMethodContextPtr = std::shared_ptr<HashMethodContext>;
/// For the case where there is one numeric key.
template <typename Value, typename Mapped, typename FieldType> /// UInt8/16/32/64 for any type with corresponding bit width.
struct HashMethodOneNumber : public columns_hashing_impl::HashMethodBase<Value, Mapped, true>
template <typename Value, typename Mapped, typename FieldType, bool use_cache = true> /// UInt8/16/32/64 for any type with corresponding bit width.
struct HashMethodOneNumber : public columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>
{
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, true>;
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>;
const char * vec;
/// If the keys of a fixed length then key_sizes contains their lengths, empty otherwise.
......@@ -90,10 +90,10 @@ protected:
/// For the case where there is one string key.
template <typename Value, typename Mapped>
struct HashMethodString : public columns_hashing_impl::HashMethodBase<Value, Mapped, true>
template <typename Value, typename Mapped, bool use_cache = true>
struct HashMethodString : public columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>
{
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, true>;
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>;
const IColumn::Offset * offsets;
const UInt8 * chars;
......@@ -107,7 +107,7 @@ struct HashMethodString : public columns_hashing_impl::HashMethodBase<Value, Map
static HashMethodContextPtr createContext(const HashMethodContext::Settings &) { return nullptr; }
StringRef getKey(size_t row) const { return StringRef(chars + offsets[row - 1], offsets[row] - offsets[row - 1] - 1); }
StringRef getKey(ssize_t row) const { return StringRef(chars + offsets[row - 1], offsets[row] - offsets[row - 1] - 1); }
template <typename Data>
ALWAYS_INLINE typename Base::EmplaceResult emplaceKey(Data & data, size_t row, Arena & pool)
......@@ -150,10 +150,10 @@ protected:
/// For the case where there is one fixed-length string key.
template <typename Value, typename Mapped>
struct HashMethodFixedString : public columns_hashing_impl::HashMethodBase<Value, Mapped, true>
template <typename Value, typename Mapped, bool use_cache = true>
struct HashMethodFixedString : public columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>
{
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, true>;
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>;
size_t n;
const ColumnFixedString::Chars * chars;
......@@ -396,10 +396,13 @@ struct HashMethodSingleLowCardinalityColumn : public SingleColumnMethod
if (is_nullable && row == 0)
{
visit_cache[row] = VisitValue::Found;
bool has_null_key = data.hasNullKeyData();
data.hasNullKeyData() = true;
if constexpr (has_mapped)
return EmplaceResult(data.getNullKeyData(), mapped_cache[0], !data.hasNullKeyData());
return EmplaceResult(data.getNullKeyData(), mapped_cache[0], !has_null_key);
else
return EmplaceResult(!data.hasNullKeyData());
return EmplaceResult(!has_null_key);
}
if (visit_cache[row] == VisitValue::Found)
......@@ -446,7 +449,7 @@ struct HashMethodSingleLowCardinalityColumn : public SingleColumnMethod
if (is_nullable && row == 0)
{
if constexpr (has_mapped)
return FindResult(data.hasNullKeyData() ? data.getNullKeyData() : Mapped(), data.hasNullKeyData());
return FindResult(data.hasNullKeyData() ? &data.getNullKeyData() : nullptr, data.hasNullKeyData());
else
return FindResult(data.hasNullKeyData());
}
......@@ -454,7 +457,7 @@ struct HashMethodSingleLowCardinalityColumn : public SingleColumnMethod
if (visit_cache[row] != VisitValue::Empty)
{
if constexpr (has_mapped)
return FindResult(mapped_cache[row], visit_cache[row] == VisitValue::Found);
return FindResult(&mapped_cache[row], visit_cache[row] == VisitValue::Found);
else
return FindResult(visit_cache[row] == VisitValue::Found);
}
......@@ -477,7 +480,7 @@ struct HashMethodSingleLowCardinalityColumn : public SingleColumnMethod
}
if constexpr (has_mapped)
return FindResult(mapped_cache[row], found);
return FindResult(&mapped_cache[row], found);
else
return FindResult(found);
}
......@@ -507,10 +510,10 @@ template <>
struct LowCardinalityKeys<false> {};
/// For the case where all keys are of fixed length, and they fit in N (for example, 128) bits.
template <typename Value, typename Key, typename Mapped, bool has_nullable_keys_ = false, bool has_low_cardinality_ = false>
template <typename Value, typename Key, typename Mapped, bool has_nullable_keys_ = false, bool has_low_cardinality_ = false, bool use_cache = true>
struct HashMethodKeysFixed
: private columns_hashing_impl::BaseStateKeysFixed<Key, has_nullable_keys_>
, public columns_hashing_impl::HashMethodBase<Value, Mapped, true>
, public columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>
{
static constexpr bool has_nullable_keys = has_nullable_keys_;
static constexpr bool has_low_cardinality = has_low_cardinality_;
......@@ -520,7 +523,7 @@ struct HashMethodKeysFixed
size_t keys_size;
using Base = columns_hashing_impl::BaseStateKeysFixed<Key, has_nullable_keys>;
using BaseHashed = columns_hashing_impl::HashMethodBase<Value, Mapped, true>;
using BaseHashed = columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>;
HashMethodKeysFixed(const ColumnRawPtrs & key_columns, const Sizes & key_sizes, const HashMethodContextPtr &)
: key_sizes(std::move(key_sizes)), keys_size(key_columns.size())
......@@ -590,10 +593,10 @@ struct HashMethodKeysFixed
* That is, for example, for strings, it contains first the serialized length of the string, and then the bytes.
* Therefore, when aggregating by several strings, there is no ambiguity.
*/
template <typename Value, typename Mapped>
struct HashMethodSerialized : public columns_hashing_impl::HashMethodBase<Value, Mapped, false>
template <typename Value, typename Mapped, bool use_cache = true>
struct HashMethodSerialized : public columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>
{
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, false>;
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>;
ColumnRawPtrs key_columns;
size_t keys_size;
......@@ -641,5 +644,46 @@ protected:
}
};
/// For the case where there is one string key.
template <typename Value, typename Mapped, bool use_cache = true>
struct HashMethodHashed : public columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>
{
using Base = columns_hashing_impl::HashMethodBase<Value, Mapped, use_cache>;
using Key = UInt128;
ColumnRawPtrs key_columns;
HashMethodHashed(ColumnRawPtrs key_columns, const Sizes &, const HashMethodContextPtr &)
: key_columns(std::move(key_columns)) {}
static HashMethodContextPtr createContext(const HashMethodContext::Settings &) { return nullptr; }
UInt128 getKey(size_t row) const { return hash128(row, key_columns.size(), key_columns); }
template <typename Data>
ALWAYS_INLINE typename Base::EmplaceResult emplaceKey(Data & data, size_t row, Arena & /*pool*/)
{
typename Data::iterator it;
return Base::emplaceKeyImpl(getKey(row), data, it);
}
template <typename Data>
ALWAYS_INLINE typename Base::FindResult findKey(Data & data, size_t row, Arena & /*pool*/)
{
return Base::findKeyImpl(getKey(row), data);
}
template <typename Data>
ALWAYS_INLINE size_t getHash(const Data & data, size_t row, Arena & /*pool*/)
{
return data.hash(getKey(row));
}
static StringRef getValueRef(const Value & value)
{
return StringRef(reinterpret_cast<const char *>(&value.first), sizeof(value.first));
}
};
}
}
......@@ -44,7 +44,7 @@ public:
: value(value), cached_value(cached_value), inserted(inserted) {}
bool isInserted() const { return inserted; }
const auto & getMapped() const { return value; }
auto & getMapped() const { return value; }
void setMapped(const Mapped & mapped) { value = cached_value = mapped; }
};
......@@ -61,13 +61,13 @@ public:
template <typename Mapped>
class FindResultImpl
{
Mapped value;
Mapped * value;
bool found;
public:
FindResultImpl(Mapped value, bool found) : value(value), found(found) {}
FindResultImpl(Mapped * value, bool found) : value(value), found(found) {}
bool isFound() const { return found; }
const Mapped & getMapped() const { return value; }
Mapped & getMapped() const { return *value; }
};
template <>
......@@ -142,7 +142,7 @@ protected:
if (cache.check(key))
{
if constexpr (has_mapped)
return FindResult(cache.found ? cache.value.second : Mapped(), cache.found);
return FindResult(&cache.value.second, cache.found);
else
return FindResult(cache.found);
}
......@@ -168,7 +168,7 @@ protected:
}
if constexpr (has_mapped)
return FindResult(found ? it->second : Mapped(), found);
return FindResult(found ? &it->second : nullptr, found);
else
return FindResult(found);
}
......
......@@ -150,18 +150,54 @@ static size_t getTotalByteCountImpl(const Maps & maps, Join::Type type)
}
template <Join::Type type>
struct KeyGetterForType;
template <Join::Type type, typename Value, typename Mapped>
struct KeyGetterForTypeImpl;
template <> struct KeyGetterForType<Join::Type::key8> { using Type = JoinKeyGetterOneNumber<UInt8>; };
template <> struct KeyGetterForType<Join::Type::key16> { using Type = JoinKeyGetterOneNumber<UInt16>; };
template <> struct KeyGetterForType<Join::Type::key32> { using Type = JoinKeyGetterOneNumber<UInt32>; };
template <> struct KeyGetterForType<Join::Type::key64> { using Type = JoinKeyGetterOneNumber<UInt64>; };
template <> struct KeyGetterForType<Join::Type::key_string> { using Type = JoinKeyGetterString; };
template <> struct KeyGetterForType<Join::Type::key_fixed_string> { using Type = JoinKeyGetterFixedString; };
template <> struct KeyGetterForType<Join::Type::keys128> { using Type = JoinKeyGetterFixed<UInt128>; };
template <> struct KeyGetterForType<Join::Type::keys256> { using Type = JoinKeyGetterFixed<UInt256>; };
template <> struct KeyGetterForType<Join::Type::hashed> { using Type = JoinKeyGetterHashed; };
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::key8, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodOneNumber<Value, Mapped, UInt8, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::key16, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodOneNumber<Value, Mapped, UInt16, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::key32, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodOneNumber<Value, Mapped, UInt32, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::key64, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodOneNumber<Value, Mapped, UInt64, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::key_string, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodString<Value, Mapped, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::key_fixed_string, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodFixedString<Value, Mapped, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::keys128, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodKeysFixed<Value, UInt128, Mapped, false, false, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::keys256, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodKeysFixed<Value, UInt256, Mapped, false, false, false>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<Join::Type::hashed, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodHashed<Value, Mapped, false>;
};
template <Join::Type type, typename Data>
struct KeyGetterForType
{
using Value = typename Data::value_type;
using Mapped_t = typename Data::mapped_type;
using Mapped = std::conditional_t<std::is_const_v<Data>, const Mapped_t, Mapped_t>;
using Type = typename KeyGetterForTypeImpl<type, Value, Mapped>::Type;
};
/// Do I need to use the hash table maps_*_full, in which we remember whether the row was joined.
......@@ -309,40 +345,30 @@ namespace
template <ASTTableJoin::Strictness STRICTNESS, typename Map, typename KeyGetter>
struct Inserter
{
static void insert(Map & map, const typename Map::key_type & key, Block * stored_block, size_t i, Arena & pool);
static void insert(Map & map, KeyGetter & key_getter, Block * stored_block, size_t i, Arena & pool);
};
template <typename Map, typename KeyGetter>
struct Inserter<ASTTableJoin::Strictness::Any, Map, KeyGetter>
{
static void insert(Map & map, const typename Map::key_type & key, Block * stored_block, size_t i, Arena & pool)
static void insert(Map & map, KeyGetter & key_getter, Block * stored_block, size_t i, Arena & pool)
{
typename Map::iterator it;
bool inserted;
map.emplace(key, it, inserted);
auto emplace_result = key_getter.emplaceKey(map, i, pool);
if (inserted)
{
KeyGetter::onNewKey(it->first, pool);
new (&it->second) typename Map::mapped_type(stored_block, i);
}
if (emplace_result.isInserted())
new (&emplace_result.getMapped()) typename Map::mapped_type(stored_block, i);
}
};
template <typename Map, typename KeyGetter>
struct Inserter<ASTTableJoin::Strictness::All, Map, KeyGetter>
{
static void insert(Map & map, const typename Map::key_type & key, Block * stored_block, size_t i, Arena & pool)
static void insert(Map & map, KeyGetter & key_getter, Block * stored_block, size_t i, Arena & pool)
{
typename Map::iterator it;
bool inserted;
map.emplace(key, it, inserted);
auto emplace_result = key_getter.emplaceKey(map, i, pool);
if (inserted)
{
KeyGetter::onNewKey(it->first, pool);
new (&it->second) typename Map::mapped_type(stored_block, i);
}
if (emplace_result.isInserted())
new (&emplace_result.getMapped()) typename Map::mapped_type(stored_block, i);
else
{
/** The first element of the list is stored in the value of the hash table, the rest in the pool.
......@@ -350,9 +376,10 @@ namespace
* That is, the former second element, if it was, will be the third, and so on.
*/
auto elem = pool.alloc<typename Map::mapped_type>();
auto & mapped = emplace_result.getMapped();
elem->next = it->second.next;
it->second.next = elem;
elem->next = mapped.next;
mapped.next = elem;
elem->block = stored_block;
elem->row_num = i;
}
......@@ -363,17 +390,16 @@ namespace
template <ASTTableJoin::Strictness STRICTNESS, typename KeyGetter, typename Map, bool has_null_map>
void NO_INLINE insertFromBlockImplTypeCase(
Map & map, size_t rows, const ColumnRawPtrs & key_columns,
size_t keys_size, const Sizes & key_sizes, Block * stored_block, ConstNullMapPtr null_map, Arena & pool)
const Sizes & key_sizes, Block * stored_block, ConstNullMapPtr null_map, Arena & pool)
{
KeyGetter key_getter(key_columns);
KeyGetter key_getter(key_columns, key_sizes, nullptr);
for (size_t i = 0; i < rows; ++i)
{
if (has_null_map && (*null_map)[i])
continue;
auto key = key_getter.getKey(key_columns, keys_size, i, key_sizes);
Inserter<STRICTNESS, Map, KeyGetter>::insert(map, key, stored_block, i, pool);
Inserter<STRICTNESS, Map, KeyGetter>::insert(map, key_getter, stored_block, i, pool);
}
}
......@@ -381,19 +407,19 @@ namespace
template <ASTTableJoin::Strictness STRICTNESS, typename KeyGetter, typename Map>
void insertFromBlockImplType(
Map & map, size_t rows, const ColumnRawPtrs & key_columns,
size_t keys_size, const Sizes & key_sizes, Block * stored_block, ConstNullMapPtr null_map, Arena & pool)
const Sizes & key_sizes, Block * stored_block, ConstNullMapPtr null_map, Arena & pool)
{
if (null_map)
insertFromBlockImplTypeCase<STRICTNESS, KeyGetter, Map, true>(map, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool);
insertFromBlockImplTypeCase<STRICTNESS, KeyGetter, Map, true>(map, rows, key_columns, key_sizes, stored_block, null_map, pool);
else
insertFromBlockImplTypeCase<STRICTNESS, KeyGetter, Map, false>(map, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool);
insertFromBlockImplTypeCase<STRICTNESS, KeyGetter, Map, false>(map, rows, key_columns, key_sizes, stored_block, null_map, pool);
}
template <ASTTableJoin::Strictness STRICTNESS, typename Maps>
void insertFromBlockImpl(
Join::Type type, Maps & maps, size_t rows, const ColumnRawPtrs & key_columns,
size_t keys_size, const Sizes & key_sizes, Block * stored_block, ConstNullMapPtr null_map, Arena & pool)
const Sizes & key_sizes, Block * stored_block, ConstNullMapPtr null_map, Arena & pool)
{
switch (type)
{
......@@ -402,8 +428,8 @@ namespace
#define M(TYPE) \
case Join::Type::TYPE: \
insertFromBlockImplType<STRICTNESS, typename KeyGetterForType<Join::Type::TYPE>::Type>(\
*maps.TYPE, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); \
insertFromBlockImplType<STRICTNESS, typename KeyGetterForType<Join::Type::TYPE, std::remove_reference_t<decltype(*maps.TYPE)>>::Type>(\
*maps.TYPE, rows, key_columns, key_sizes, stored_block, null_map, pool); \
break;
APPLY_FOR_JOIN_VARIANTS(M)
#undef M
......@@ -486,16 +512,16 @@ bool Join::insertFromBlock(const Block & block)
if (!getFullness(kind))
{
if (strictness == ASTTableJoin::Strictness::Any)
insertFromBlockImpl<ASTTableJoin::Strictness::Any>(type, maps_any, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool);
insertFromBlockImpl<ASTTableJoin::Strictness::Any>(type, maps_any, rows, key_columns, key_sizes, stored_block, null_map, pool);
else
insertFromBlockImpl<ASTTableJoin::Strictness::All>(type, maps_all, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool);
insertFromBlockImpl<ASTTableJoin::Strictness::All>(type, maps_all, rows, key_columns, key_sizes, stored_block, null_map, pool);
}
else
{
if (strictness == ASTTableJoin::Strictness::Any)
insertFromBlockImpl<ASTTableJoin::Strictness::Any>(type, maps_any_full, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool);
insertFromBlockImpl<ASTTableJoin::Strictness::Any>(type, maps_any_full, rows, key_columns, key_sizes, stored_block, null_map, pool);
else
insertFromBlockImpl<ASTTableJoin::Strictness::All>(type, maps_all_full, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool);
insertFromBlockImpl<ASTTableJoin::Strictness::All>(type, maps_all_full, rows, key_columns, key_sizes, stored_block, null_map, pool);
}
}
......@@ -511,14 +537,14 @@ namespace
template <typename Map>
struct Adder<ASTTableJoin::Kind::Left, ASTTableJoin::Strictness::Any, Map>
{
static void addFound(const typename Map::const_iterator & it, size_t num_columns_to_add, MutableColumns & added_columns,
static void addFound(const typename Map::mapped_type & mapped, size_t num_columns_to_add, MutableColumns & added_columns,
size_t i, IColumn::Filter * filter, IColumn::Offset & /*current_offset*/, IColumn::Offsets * /*offsets*/,
const std::vector<size_t> & right_indexes)
{
(*filter)[i] = 1;
for (size_t j = 0; j < num_columns_to_add; ++j)
added_columns[j]->insertFrom(*it->second.block->getByPosition(right_indexes[j]).column.get(), it->second.row_num);
added_columns[j]->insertFrom(*mapped.block->getByPosition(right_indexes[j]).column, mapped.row_num);
}
static void addNotFound(size_t num_columns_to_add, MutableColumns & added_columns,
......@@ -534,14 +560,14 @@ namespace
template <typename Map>
struct Adder<ASTTableJoin::Kind::Inner, ASTTableJoin::Strictness::Any, Map>
{
static void addFound(const typename Map::const_iterator & it, size_t num_columns_to_add, MutableColumns & added_columns,
static void addFound(const typename Map::mapped_type & mapped, size_t num_columns_to_add, MutableColumns & added_columns,
size_t i, IColumn::Filter * filter, IColumn::Offset & /*current_offset*/, IColumn::Offsets * /*offsets*/,
const std::vector<size_t> & right_indexes)
{
(*filter)[i] = 1;
for (size_t j = 0; j < num_columns_to_add; ++j)
added_columns[j]->insertFrom(*it->second.block->getByPosition(right_indexes[j]).column.get(), it->second.row_num);
added_columns[j]->insertFrom(*mapped.block->getByPosition(right_indexes[j]).column, mapped.row_num);
}
static void addNotFound(size_t /*num_columns_to_add*/, MutableColumns & /*added_columns*/,
......@@ -554,14 +580,14 @@ namespace
template <ASTTableJoin::Kind KIND, typename Map>
struct Adder<KIND, ASTTableJoin::Strictness::All, Map>
{
static void addFound(const typename Map::const_iterator & it, size_t num_columns_to_add, MutableColumns & added_columns,
static void addFound(const typename Map::mapped_type & mapped, size_t num_columns_to_add, MutableColumns & added_columns,
size_t i, IColumn::Filter * filter, IColumn::Offset & current_offset, IColumn::Offsets * offsets,
const std::vector<size_t> & right_indexes)
{
(*filter)[i] = 1;
size_t rows_joined = 0;
for (auto current = &static_cast<const typename Map::mapped_type::Base_t &>(it->second); current != nullptr; current = current->next)
for (auto current = &static_cast<const typename Map::mapped_type::Base_t &>(mapped); current != nullptr; current = current->next)
{
for (size_t j = 0; j < num_columns_to_add; ++j)
added_columns[j]->insertFrom(*current->block->getByPosition(right_indexes[j]).column.get(), current->row_num);
......@@ -600,10 +626,10 @@ namespace
IColumn::Offset & current_offset, std::unique_ptr<IColumn::Offsets> & offsets_to_replicate,
const std::vector<size_t> & right_indexes)
{
size_t keys_size = key_columns.size();
size_t num_columns_to_add = right_indexes.size();
KeyGetter key_getter(key_columns);
Arena pool;
KeyGetter key_getter(key_columns, key_sizes, nullptr);
for (size_t i = 0; i < rows; ++i)
{
......@@ -614,14 +640,14 @@ namespace
}
else
{
auto key = key_getter.getKey(key_columns, keys_size, i, key_sizes);
typename Map::const_iterator it = map.find(key);
auto find_result = key_getter.findKey(map, i, pool);
if (it != map.end())
if (find_result.isFound())
{
it->second.setUsed();
auto & mapped = find_result.getMapped();
mapped.setUsed();
Adder<KIND, STRICTNESS, Map>::addFound(
it, num_columns_to_add, added_columns, i, filter.get(), current_offset, offsets_to_replicate.get(), right_indexes);
mapped, num_columns_to_add, added_columns, i, filter.get(), current_offset, offsets_to_replicate.get(), right_indexes);
}
else
Adder<KIND, STRICTNESS, Map>::addNotFound(
......@@ -748,7 +774,7 @@ void Join::joinBlockImpl(
{
#define M(TYPE) \
case Join::Type::TYPE: \
joinBlockImplType<KIND, STRICTNESS, typename KeyGetterForType<Join::Type::TYPE>::Type>(\
joinBlockImplType<KIND, STRICTNESS, typename KeyGetterForType<Join::Type::TYPE, const std::remove_reference_t<decltype(*maps.TYPE)>>::Type>(\
*maps.TYPE, rows, key_columns, key_sizes, added_columns, null_map, \
filter, current_offset, offsets_to_replicate, right_indexes); \
break;
......
......@@ -8,6 +8,7 @@
#include <Interpreters/SettingsCommon.h>
#include <Common/Arena.h>
#include <Common/ColumnsHashing.h>
#include <Common/HashTable/HashMap.h>
#include <Columns/ColumnString.h>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册