Support ColumnConst(ColumnLowCardinality) in JoinCommon::convertColumnToNullable

This commit is contained in:
vdimir 2021-08-10 12:44:20 +03:00
parent dfccc85a33
commit ae3726643d
No known key found for this signature in database
GPG Key ID: F57B3E10A21DBB31
3 changed files with 56 additions and 24 deletions

View File

@ -106,15 +106,42 @@ DataTypePtr convertTypeToNullable(const DataTypePtr & type)
return type;
}
static bool canBecomeNullable(const ColumnPtr & col)
/// 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 (const ColumnConst * col_const = checkAndGetColumn<ColumnConst>(*col))
return col_const->getDataColumnPtr()->isNullable() || col_const->getDataColumnPtr()->canBeInsideNullable();
if (isColumnNullable(*col) || col->canBeInsideNullable())
return makeNullable(col);
if (const ColumnLowCardinality * col_lc = checkAndGetColumn<ColumnLowCardinality>(*col))
return col_lc->nestedIsNullable() || col_lc->nestedCanBeInsideNullable();
return isColumnNullable(*col) || col->canBeInsideNullable();
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)
@ -125,23 +152,11 @@ void convertColumnToNullable(ColumnWithTypeAndName & column)
return;
}
if (!canBecomeNullable(column.column))
return;
column.type = convertTypeToNullable(column.type);
if (column.column->lowCardinality())
ColumnPtr nullable_column = tryConvertColumnToNullable(column.column);
if (nullable_column)
{
/// 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
{
column.column = makeNullable(column.column);
column.type = convertTypeToNullable(column.type);
column.column = std::move(nullable_column);
}
}

View File

@ -1 +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))

View File

@ -1 +1,11 @@
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 SETTINGS join_use_nulls=1;
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;