mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
fix JOIN right table keys nullability
This commit is contained in:
parent
12b57aedf0
commit
deb2406b30
@ -37,11 +37,52 @@ namespace ErrorCodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Converts column to nullable if needed. No backward convertion.
|
static ColumnPtr filterWithBlanks(ColumnPtr src_column, const IColumn::Filter & filter, bool inverse_filter = false)
|
||||||
|
{
|
||||||
|
ColumnPtr column = src_column->convertToFullColumnIfConst();
|
||||||
|
MutableColumnPtr mut_column = column->cloneEmpty();
|
||||||
|
mut_column->reserve(column->size());
|
||||||
|
|
||||||
|
if (inverse_filter)
|
||||||
|
{
|
||||||
|
for (size_t row = 0; row < filter.size(); ++row)
|
||||||
|
{
|
||||||
|
if (filter[row])
|
||||||
|
mut_column->insertDefault();
|
||||||
|
else
|
||||||
|
mut_column->insertFrom(*column, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t row = 0; row < filter.size(); ++row)
|
||||||
|
{
|
||||||
|
if (filter[row])
|
||||||
|
mut_column->insertFrom(*column, row);
|
||||||
|
else
|
||||||
|
mut_column->insertDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mut_column;
|
||||||
|
}
|
||||||
|
|
||||||
static ColumnWithTypeAndName correctNullability(ColumnWithTypeAndName && column, bool nullable)
|
static ColumnWithTypeAndName correctNullability(ColumnWithTypeAndName && column, bool nullable)
|
||||||
{
|
{
|
||||||
if (nullable)
|
if (nullable)
|
||||||
|
{
|
||||||
JoinCommon::convertColumnToNullable(column);
|
JoinCommon::convertColumnToNullable(column);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// We have to replace values masked by NULLs with defaults.
|
||||||
|
if (column.column)
|
||||||
|
if (auto * nullable_column = checkAndGetColumn<ColumnNullable>(*column.column))
|
||||||
|
column.column = filterWithBlanks(column.column, nullable_column->getNullMapColumn().getData(), true);
|
||||||
|
|
||||||
|
JoinCommon::removeColumnNullability(column);
|
||||||
|
}
|
||||||
|
|
||||||
return std::move(column);
|
return std::move(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +98,9 @@ static ColumnWithTypeAndName correctNullability(ColumnWithTypeAndName && column,
|
|||||||
column.column = std::move(mutable_column);
|
column.column = std::move(mutable_column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
JoinCommon::removeColumnNullability(column);
|
||||||
|
|
||||||
return std::move(column);
|
return std::move(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,7 +813,7 @@ void Join::joinBlockImpl(
|
|||||||
for (size_t i = 0; i < existing_columns; ++i)
|
for (size_t i = 0; i < existing_columns; ++i)
|
||||||
block.safeGetByPosition(i).column = block.safeGetByPosition(i).column->filter(row_filter, -1);
|
block.safeGetByPosition(i).column = block.safeGetByPosition(i).column->filter(row_filter, -1);
|
||||||
|
|
||||||
/// Add join key columns from right block if they has different name.
|
/// Add join key columns from right block if needed.
|
||||||
for (size_t i = 0; i < right_table_keys.columns(); ++i)
|
for (size_t i = 0; i < right_table_keys.columns(); ++i)
|
||||||
{
|
{
|
||||||
const auto & right_key = right_table_keys.getByPosition(i);
|
const auto & right_key = right_table_keys.getByPosition(i);
|
||||||
@ -791,7 +835,7 @@ void Join::joinBlockImpl(
|
|||||||
null_map_filter.getData().swap(row_filter);
|
null_map_filter.getData().swap(row_filter);
|
||||||
const IColumn::Filter & filter = null_map_filter.getData();
|
const IColumn::Filter & filter = null_map_filter.getData();
|
||||||
|
|
||||||
/// Add join key columns from right block if they has different name.
|
/// Add join key columns from right block if needed.
|
||||||
for (size_t i = 0; i < right_table_keys.columns(); ++i)
|
for (size_t i = 0; i < right_table_keys.columns(); ++i)
|
||||||
{
|
{
|
||||||
const auto & right_key = right_table_keys.getByPosition(i);
|
const auto & right_key = right_table_keys.getByPosition(i);
|
||||||
@ -800,20 +844,10 @@ void Join::joinBlockImpl(
|
|||||||
if (required_right_keys.count(right_key.name) && !block.has(right_key.name))
|
if (required_right_keys.count(right_key.name) && !block.has(right_key.name))
|
||||||
{
|
{
|
||||||
const auto & col = block.getByName(left_name);
|
const auto & col = block.getByName(left_name);
|
||||||
ColumnPtr column = col.column->convertToFullColumnIfConst();
|
|
||||||
MutableColumnPtr mut_column = column->cloneEmpty();
|
|
||||||
mut_column->reserve(column->size());
|
|
||||||
|
|
||||||
for (size_t row = 0; row < filter.size(); ++row)
|
|
||||||
{
|
|
||||||
if (filter[row])
|
|
||||||
mut_column->insertFrom(*column, row);
|
|
||||||
else
|
|
||||||
mut_column->insertDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_nullable = nullable_right_side || right_key.type->isNullable();
|
bool is_nullable = nullable_right_side || right_key.type->isNullable();
|
||||||
block.insert(correctNullability({std::move(mut_column), col.type, right_key.name}, is_nullable, null_map_filter));
|
|
||||||
|
ColumnPtr thin_column = filterWithBlanks(col.column, filter);
|
||||||
|
block.insert(correctNullability({thin_column, col.type, right_key.name}, is_nullable, null_map_filter));
|
||||||
|
|
||||||
if constexpr (is_all_join)
|
if constexpr (is_all_join)
|
||||||
right_keys_to_replicate.push_back(block.getPositionByName(right_key.name));
|
right_keys_to_replicate.push_back(block.getPositionByName(right_key.name));
|
||||||
|
@ -32,6 +32,22 @@ void convertColumnsToNullable(Block & block, size_t starting_pos)
|
|||||||
convertColumnToNullable(block.getByPosition(i));
|
convertColumnToNullable(block.getByPosition(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @warning It assumes that every NULL has default value in nested column (or it does not matter)
|
||||||
|
void removeColumnNullability(ColumnWithTypeAndName & column)
|
||||||
|
{
|
||||||
|
if (!column.type->isNullable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
column.type = static_cast<const DataTypeNullable &>(*column.type).getNestedType();
|
||||||
|
if (column.column)
|
||||||
|
{
|
||||||
|
auto * nullable_column = checkAndGetColumn<ColumnNullable>(*column.column);
|
||||||
|
ColumnPtr nested_column = nullable_column->getNestedColumnPtr();
|
||||||
|
MutableColumnPtr mutable_column = (*std::move(nested_column)).mutate();
|
||||||
|
column.column = std::move(mutable_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ColumnRawPtrs temporaryMaterializeColumns(const Block & block, const Names & names, Columns & materialized)
|
ColumnRawPtrs temporaryMaterializeColumns(const Block & block, const Names & names, Columns & materialized)
|
||||||
{
|
{
|
||||||
ColumnRawPtrs ptrs;
|
ColumnRawPtrs ptrs;
|
||||||
|
@ -15,6 +15,7 @@ namespace JoinCommon
|
|||||||
|
|
||||||
void convertColumnToNullable(ColumnWithTypeAndName & column);
|
void convertColumnToNullable(ColumnWithTypeAndName & column);
|
||||||
void convertColumnsToNullable(Block & block, size_t starting_pos = 0);
|
void convertColumnsToNullable(Block & block, size_t starting_pos = 0);
|
||||||
|
void removeColumnNullability(ColumnWithTypeAndName & column);
|
||||||
ColumnRawPtrs temporaryMaterializeColumns(const Block & block, const Names & names, Columns & materialized);
|
ColumnRawPtrs temporaryMaterializeColumns(const Block & block, const Names & names, Columns & materialized);
|
||||||
void removeLowCardinalityInplace(Block & block);
|
void removeLowCardinalityInplace(Block & block);
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
\N test 0 1 Nullable(String) Nullable(String)
|
\N test 0 1 Nullable(String) String
|
||||||
bar bar 1 2 Nullable(String) Nullable(String)
|
bar bar 1 2 Nullable(String) String
|
||||||
\N 0 1 Nullable(String) Nullable(String)
|
\N 0 1 Nullable(String) String
|
||||||
foo \N 2 0 Nullable(String) Nullable(String)
|
foo 2 0 Nullable(String) String
|
||||||
\N test 0 1 Nullable(String) Nullable(String)
|
\N test 0 1 Nullable(String) String
|
||||||
bar bar 1 2 Nullable(String) Nullable(String)
|
bar bar 1 2 Nullable(String) String
|
||||||
\N 0 1 Nullable(String) Nullable(String)
|
\N 0 1 Nullable(String) String
|
||||||
foo \N 2 0 Nullable(String) Nullable(String)
|
foo 2 0 Nullable(String) String
|
||||||
foo \N 2 0 String Nullable(String)
|
foo \N 2 0 String Nullable(String)
|
||||||
bar bar 1 2 String Nullable(String)
|
bar bar 1 2 String Nullable(String)
|
||||||
test 0 1 String Nullable(String)
|
test 0 1 String Nullable(String)
|
||||||
|
Loading…
Reference in New Issue
Block a user