Handle correct nullability with low card in HashJoin

This commit is contained in:
vdimir 2021-05-15 17:09:51 +03:00
parent 9091bba3d6
commit 8dddcebe8c
No known key found for this signature in database
GPG Key ID: F57B3E10A21DBB31
5 changed files with 30 additions and 3 deletions

View File

@ -188,6 +188,7 @@ public:
*/ */
bool nestedIsNullable() const { return isColumnNullable(*dictionary.getColumnUnique().getNestedColumn()); } bool nestedIsNullable() const { return isColumnNullable(*dictionary.getColumnUnique().getNestedColumn()); }
void nestedToNullable() { dictionary.getColumnUnique().nestedToNullable(); } void nestedToNullable() { dictionary.getColumnUnique().nestedToNullable(); }
void nestedRemoveNullable() { dictionary.getColumnUnique().nestedRemoveNullable(); }
const IColumnUnique & getDictionary() const { return dictionary.getColumnUnique(); } const IColumnUnique & getDictionary() const { return dictionary.getColumnUnique(); }
const ColumnPtr & getDictionaryPtr() const { return dictionary.getColumnUniquePtr(); } const ColumnPtr & getDictionaryPtr() const { return dictionary.getColumnUniquePtr(); }

View File

@ -51,6 +51,7 @@ public:
const ColumnPtr & getNestedNotNullableColumn() const override { return column_holder; } const ColumnPtr & getNestedNotNullableColumn() const override { return column_holder; }
bool nestedColumnIsNullable() const override { return is_nullable; } bool nestedColumnIsNullable() const override { return is_nullable; }
void nestedToNullable() override; void nestedToNullable() override;
void nestedRemoveNullable() override;
size_t uniqueInsert(const Field & x) override; size_t uniqueInsert(const Field & x) override;
size_t uniqueInsertFrom(const IColumn & src, size_t n) override; size_t uniqueInsertFrom(const IColumn & src, size_t n) override;
@ -271,6 +272,14 @@ void ColumnUnique<ColumnType>::nestedToNullable()
createNullMask(); createNullMask();
} }
template <typename ColumnType>
void ColumnUnique<ColumnType>::nestedRemoveNullable()
{
is_nullable = false;
nested_null_mask = nullptr;
nested_column_nullable = nullptr;
}
template <typename ColumnType> template <typename ColumnType>
const ColumnPtr & ColumnUnique<ColumnType>::getNestedColumn() const const ColumnPtr & ColumnUnique<ColumnType>::getNestedColumn() const
{ {

View File

@ -24,6 +24,7 @@ public:
virtual bool nestedColumnIsNullable() const = 0; virtual bool nestedColumnIsNullable() const = 0;
virtual void nestedToNullable() = 0; virtual void nestedToNullable() = 0;
virtual void nestedRemoveNullable() = 0;
/// Returns array with StringRefHash calculated for each row of getNestedNotNullableColumn() column. /// Returns array with StringRefHash calculated for each row of getNestedNotNullableColumn() column.
/// Returns nullptr if nested column doesn't contain strings. Otherwise calculates hash (if it wasn't). /// Returns nullptr if nested column doesn't contain strings. Otherwise calculates hash (if it wasn't).

View File

@ -160,7 +160,7 @@ static ColumnWithTypeAndName correctNullability(ColumnWithTypeAndName && column,
{ {
if (nullable) if (nullable)
{ {
JoinCommon::convertColumnToNullable(column, false); JoinCommon::convertColumnToNullable(column);
if (column.type->isNullable() && !negative_null_map.empty()) if (column.type->isNullable() && !negative_null_map.empty())
{ {
MutableColumnPtr mutable_column = IColumn::mutate(std::move(column.column)); MutableColumnPtr mutable_column = IColumn::mutate(std::move(column.column));
@ -1085,7 +1085,8 @@ void HashJoin::joinBlockImpl(
ColumnWithTypeAndName right_col(col.column, col.type, right_key.name); ColumnWithTypeAndName right_col(col.column, col.type, right_key.name);
if (right_col.type->lowCardinality() != right_key.type->lowCardinality()) if (right_col.type->lowCardinality() != right_key.type->lowCardinality())
JoinCommon::changeLowCardinalityInplace(right_col); JoinCommon::changeLowCardinalityInplace(right_col);
block.insert(correctNullability(std::move(right_col), is_nullable)); right_col = correctNullability(std::move(right_col), is_nullable);
block.insert(right_col);
} }
} }
else if (has_required_right_keys) else if (has_required_right_keys)
@ -1114,7 +1115,8 @@ void HashJoin::joinBlockImpl(
ColumnWithTypeAndName right_col(thin_column, col.type, right_key.name); ColumnWithTypeAndName right_col(thin_column, col.type, right_key.name);
if (right_col.type->lowCardinality() != right_key.type->lowCardinality()) if (right_col.type->lowCardinality() != right_key.type->lowCardinality())
JoinCommon::changeLowCardinalityInplace(right_col); JoinCommon::changeLowCardinalityInplace(right_col);
block.insert(correctNullability(std::move(right_col), is_nullable, null_map_filter)); right_col = correctNullability(std::move(right_col), is_nullable, null_map_filter);
block.insert(right_col);
if constexpr (need_replication) if constexpr (need_replication)
right_keys_to_replicate.push_back(block.getPositionByName(right_key.name)); right_keys_to_replicate.push_back(block.getPositionByName(right_key.name));

View File

@ -122,6 +122,20 @@ void convertColumnsToNullable(Block & block, size_t starting_pos)
/// @warning It assumes that every NULL has default value in nested column (or it does not matter) /// @warning It assumes that every NULL has default value in nested column (or it does not matter)
void removeColumnNullability(ColumnWithTypeAndName & column) void removeColumnNullability(ColumnWithTypeAndName & column)
{ {
if (column.type->lowCardinality())
{
/// LowCardinality(Nullable(T)) case
ColumnLowCardinality * col_as_lc = assert_cast<ColumnLowCardinality *>(column.column->assumeMutable().get());
if (col_as_lc->nestedIsNullable())
{
col_as_lc->nestedRemoveNullable();
const auto & dict_type = typeid_cast<const DataTypeLowCardinality *>(column.type.get())->getDictionaryType();
column.type = std::make_shared<DataTypeLowCardinality>(removeNullable(dict_type));
}
return;
}
if (!column.type->isNullable()) if (!column.type->isNullable())
return; return;