mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 18:12:02 +00:00
dbms: better [#METR-19266]
This commit is contained in:
parent
d4da820f6c
commit
ae2d8d9adb
@ -13,9 +13,7 @@ namespace DB
|
||||
/// - if a target column is nullable while the corresponding source
|
||||
/// column is not, we embed the source column into a nullable column;
|
||||
/// - if a source column is nullable while the corresponding target
|
||||
/// column is not, we extract the nested column from the source.
|
||||
/// Moreover all the NULL values are replaced by the default value
|
||||
/// for the nested column;
|
||||
/// column is not, we extract the nested column from the source;
|
||||
/// - otherwise we just perform an identity mapping.
|
||||
class NullableAdapterBlockInputStream : public IProfilingBlockInputStream
|
||||
{
|
||||
@ -26,7 +24,7 @@ private:
|
||||
{
|
||||
/// Do nothing.
|
||||
NONE = 0,
|
||||
/// Convert nullable column to ordinary column. Convert NULLs to default values.
|
||||
/// Convert nullable column to ordinary column.
|
||||
TO_ORDINARY,
|
||||
/// Convert non-nullable column to nullable column.
|
||||
TO_NULLABLE
|
||||
@ -71,63 +69,33 @@ protected:
|
||||
if (actions[i] == TO_ORDINARY)
|
||||
{
|
||||
const auto & nullable_col = static_cast<const ColumnNullable &>(*elem.column);
|
||||
const auto & nested_col = *nullable_col.getNestedColumn();
|
||||
|
||||
const auto & nullable_type = static_cast<const DataTypeNullable &>(*elem.type);
|
||||
|
||||
const auto & null_map = static_cast<const ColumnUInt8 &>(*nullable_col.getNullValuesByteMap()).getData();
|
||||
bool has_nulls = std::any_of(null_map.begin(), null_map.end(), [](UInt8 val){ return val == 1; });
|
||||
|
||||
if (has_nulls)
|
||||
{
|
||||
/// Slow path: since we have NULL values that must be replaced,
|
||||
/// we have to build a new column.
|
||||
ColumnPtr new_col_holder = nullable_col.getNestedColumn()->cloneEmpty();
|
||||
IColumn & new_col = *new_col_holder;
|
||||
new_col.reserve(nullable_col.size());
|
||||
|
||||
for (size_t i = 0; i < nullable_col.size(); ++i)
|
||||
{
|
||||
if (nullable_col.isNullAt(i))
|
||||
new_col.insertDefault();
|
||||
else
|
||||
new_col.insertFrom(nested_col, i);
|
||||
}
|
||||
|
||||
new_elem =
|
||||
{
|
||||
new_col_holder,
|
||||
nullable_type.getNestedType(),
|
||||
elem.name
|
||||
};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Fast path: there are no NULL values.
|
||||
/// Just return the nested column.
|
||||
new_elem =
|
||||
{
|
||||
nullable_col.getNestedColumn(),
|
||||
nullable_type.getNestedType(),
|
||||
elem.name
|
||||
};
|
||||
}
|
||||
|
||||
res.insert(new_elem);
|
||||
/// For performance reasons, if the source column contains a NULL,
|
||||
/// we follow a non-strict approach. We rely on the fact that most
|
||||
/// users will write something such as:
|
||||
///
|
||||
/// INSERT INTO foo(col) SELECT col FROM bar WHERE col IS NOT NULL
|
||||
///
|
||||
/// If required, in a future release we could add a server parameter
|
||||
/// so that customers would be able to decide whether inserting
|
||||
/// a NULL value into an non-nullable column is semantically correct
|
||||
/// or not.
|
||||
res.insert({
|
||||
nullable_col.getNestedColumn(),
|
||||
nullable_type.getNestedType(),
|
||||
elem.name
|
||||
});
|
||||
}
|
||||
else if (actions[i] == TO_NULLABLE)
|
||||
{
|
||||
auto null_map = std::make_shared<ColumnUInt8>(elem.column->size(), 0);
|
||||
|
||||
ColumnWithTypeAndName new_elem
|
||||
{
|
||||
res.insert({
|
||||
std::make_shared<ColumnNullable>(elem.column, null_map),
|
||||
std::make_shared<DataTypeNullable>(elem.type),
|
||||
elem.name
|
||||
};
|
||||
|
||||
res.insert(new_elem);
|
||||
});
|
||||
}
|
||||
else if (actions[i] == NONE)
|
||||
res.insert(elem);
|
||||
|
Loading…
Reference in New Issue
Block a user