mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Merge pull request #27516 from vdimir/fix-join-const-nullable
Fix Nullable const columns in JOIN
This commit is contained in:
commit
f0a7c6ec94
@ -187,6 +187,7 @@ public:
|
||||
* So LC(Nullable(T)) would return true, LC(U) -- false.
|
||||
*/
|
||||
bool nestedIsNullable() const { return isColumnNullable(*dictionary.getColumnUnique().getNestedColumn()); }
|
||||
bool nestedCanBeInsideNullable() const { return dictionary.getColumnUnique().getNestedColumn()->canBeInsideNullable(); }
|
||||
void nestedToNullable() { dictionary.getColumnUnique().nestedToNullable(); }
|
||||
void nestedRemoveNullable() { dictionary.getColumnUnique().nestedRemoveNullable(); }
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <Columns/ColumnLowCardinality.h>
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
|
||||
#include <DataStreams/materializeBlock.h>
|
||||
|
||||
@ -105,25 +106,57 @@ DataTypePtr convertTypeToNullable(const DataTypePtr & type)
|
||||
return type;
|
||||
}
|
||||
|
||||
/// Convert column to nullable. If column LowCardinality or Const, convert nested column.
|
||||
/// Returns nullptr if conversion cannot be performed.
|
||||
static ColumnPtr tryConvertColumnToNullable(const ColumnPtr & col)
|
||||
{
|
||||
if (isColumnNullable(*col) || col->canBeInsideNullable())
|
||||
return makeNullable(col);
|
||||
|
||||
if (col->lowCardinality())
|
||||
{
|
||||
auto mut_col = IColumn::mutate(std::move(col));
|
||||
ColumnLowCardinality * col_lc = assert_cast<ColumnLowCardinality *>(mut_col.get());
|
||||
if (col_lc->nestedIsNullable())
|
||||
{
|
||||
return mut_col;
|
||||
}
|
||||
else if (col_lc->nestedCanBeInsideNullable())
|
||||
{
|
||||
col_lc->nestedToNullable();
|
||||
return mut_col;
|
||||
}
|
||||
}
|
||||
else if (const ColumnConst * col_const = checkAndGetColumn<ColumnConst>(*col))
|
||||
{
|
||||
const auto & nested = col_const->getDataColumnPtr();
|
||||
if (nested->isNullable() || nested->canBeInsideNullable())
|
||||
{
|
||||
return makeNullable(col);
|
||||
}
|
||||
else if (nested->lowCardinality())
|
||||
{
|
||||
ColumnPtr nested_nullable = tryConvertColumnToNullable(nested);
|
||||
if (nested_nullable)
|
||||
return ColumnConst::create(nested_nullable, col_const->size());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void convertColumnToNullable(ColumnWithTypeAndName & column)
|
||||
{
|
||||
column.type = convertTypeToNullable(column.type);
|
||||
|
||||
if (!column.column)
|
||||
{
|
||||
column.type = convertTypeToNullable(column.type);
|
||||
return;
|
||||
|
||||
if (column.column->lowCardinality())
|
||||
{
|
||||
/// Convert nested to nullable, not LowCardinality itself
|
||||
auto mut_col = IColumn::mutate(std::move(column.column));
|
||||
ColumnLowCardinality * col_as_lc = assert_cast<ColumnLowCardinality *>(mut_col.get());
|
||||
if (!col_as_lc->nestedIsNullable())
|
||||
col_as_lc->nestedToNullable();
|
||||
column.column = std::move(mut_col);
|
||||
}
|
||||
else if (column.column->canBeInsideNullable())
|
||||
|
||||
ColumnPtr nullable_column = tryConvertColumnToNullable(column.column);
|
||||
if (nullable_column)
|
||||
{
|
||||
column.column = makeNullable(column.column);
|
||||
column.type = convertTypeToNullable(column.type);
|
||||
column.column = std::move(nullable_column);
|
||||
}
|
||||
}
|
||||
|
||||
|
8
tests/queries/0_stateless/02007_join_use_nulls.reference
Normal file
8
tests/queries/0_stateless/02007_join_use_nulls.reference
Normal file
@ -0,0 +1,8 @@
|
||||
1 2 3 1 3
|
||||
1 UInt8 2 UInt8 3 Nullable(UInt8)
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 3 LowCardinality(Nullable(UInt8))
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 1 LowCardinality(Nullable(UInt8))
|
||||
1 UInt8 2 UInt8 3 Nullable(UInt8)
|
||||
1 UInt8 2 UInt8 1 Nullable(UInt8) 3 Nullable(UInt8)
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 3 LowCardinality(Nullable(UInt8))
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 1 LowCardinality(Nullable(UInt8)) 3 LowCardinality(Nullable(UInt8))
|
11
tests/queries/0_stateless/02007_join_use_nulls.sql
Normal file
11
tests/queries/0_stateless/02007_join_use_nulls.sql
Normal file
@ -0,0 +1,11 @@
|
||||
SET join_use_nulls = 1;
|
||||
|
||||
SELECT *, d.* FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.id, toTypeName(d.id) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.id, toTypeName(d.id) , d.values, toTypeName(d.values) FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.id, toTypeName(d.id) , d.values, toTypeName(d.values) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
Loading…
Reference in New Issue
Block a user