mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-24 18:50:49 +00:00
dbms: Better code for functions processing. Code cleanup. [#METR-19266]
This commit is contained in:
parent
96855a06b8
commit
f4e77aaf97
@ -28,7 +28,7 @@ public:
|
||||
|
||||
String getName() const override
|
||||
{
|
||||
return nested_function.get()->getName();
|
||||
return nested_function->getName();
|
||||
}
|
||||
|
||||
void setArguments(const DataTypes & arguments) override
|
||||
@ -38,7 +38,7 @@ public:
|
||||
|
||||
for (const auto & arg : arguments)
|
||||
{
|
||||
bool res = arg.get()->isNullable();
|
||||
bool res = arg->isNullable();
|
||||
is_nullable.push_back(res);
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public:
|
||||
|
||||
for (const auto & arg : arguments)
|
||||
{
|
||||
if (arg.get()->isNullable())
|
||||
if (arg->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*arg);
|
||||
const DataTypePtr & nested_type = nullable_type.getNestedType();
|
||||
@ -57,42 +57,42 @@ public:
|
||||
new_args.push_back(arg);
|
||||
}
|
||||
|
||||
nested_function.get()->setArguments(new_args);
|
||||
nested_function->setArguments(new_args);
|
||||
}
|
||||
|
||||
void setParameters(const Array & params)
|
||||
{
|
||||
nested_function.get()->setParameters(params);
|
||||
nested_function->setParameters(params);
|
||||
}
|
||||
|
||||
DataTypePtr getReturnType() const override
|
||||
{
|
||||
return nested_function.get()->getReturnType();
|
||||
return nested_function->getReturnType();
|
||||
}
|
||||
|
||||
void create(AggregateDataPtr place) const override
|
||||
{
|
||||
nested_function.get()->create(place);
|
||||
nested_function->create(place);
|
||||
}
|
||||
|
||||
void destroy(AggregateDataPtr place) const noexcept override
|
||||
{
|
||||
nested_function.get()->destroy(place);
|
||||
nested_function->destroy(place);
|
||||
}
|
||||
|
||||
bool hasTrivialDestructor() const override
|
||||
{
|
||||
return nested_function.get()->hasTrivialDestructor();
|
||||
return nested_function->hasTrivialDestructor();
|
||||
}
|
||||
|
||||
size_t sizeOfData() const override
|
||||
{
|
||||
return nested_function.get()->sizeOfData();
|
||||
return nested_function->sizeOfData();
|
||||
}
|
||||
|
||||
size_t alignOfData() const override
|
||||
{
|
||||
return nested_function.get()->alignOfData();
|
||||
return nested_function->alignOfData();
|
||||
}
|
||||
|
||||
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num) const override
|
||||
@ -117,27 +117,27 @@ public:
|
||||
passed_columns[i] = columns[i];
|
||||
}
|
||||
|
||||
nested_function.get()->add(place, passed_columns, row_num);
|
||||
nested_function->add(place, passed_columns, row_num);
|
||||
}
|
||||
|
||||
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs) const override
|
||||
{
|
||||
nested_function.get()->merge(place, rhs);
|
||||
nested_function->merge(place, rhs);
|
||||
}
|
||||
|
||||
void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override
|
||||
{
|
||||
nested_function.get()->serialize(place, buf);
|
||||
nested_function->serialize(place, buf);
|
||||
}
|
||||
|
||||
void deserialize(AggregateDataPtr place, ReadBuffer & buf) const override
|
||||
{
|
||||
nested_function.get()->deserialize(place, buf);
|
||||
nested_function->deserialize(place, buf);
|
||||
}
|
||||
|
||||
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
|
||||
{
|
||||
nested_function.get()->insertResultInto(place, to);
|
||||
nested_function->insertResultInto(place, to);
|
||||
}
|
||||
|
||||
static void addFree(const IAggregateFunction * that, AggregateDataPtr place, const IColumn ** columns, size_t row_num)
|
||||
|
@ -141,21 +141,34 @@ protected:
|
||||
/// Returns the copy of a given block in which each column specified in
|
||||
/// the "arguments" parameter is replaced with its respective nested
|
||||
/// column if it is nullable.
|
||||
static Block extractNonNullableBlock(const Block & block, ColumnNumbers args);
|
||||
static Block createBlockWithNestedColumns(const Block & block, ColumnNumbers args);
|
||||
|
||||
private:
|
||||
/// Internal method used for implementing both the execute() methods.
|
||||
/// The "performer" argument specifies which version of executeImpl() must be used.
|
||||
/// Except for functions, such as multiIf, whose method hasSpecialSupportForNulls()
|
||||
/// returns true, we deal with nullable and null arguments as follows:
|
||||
/// - if at least one argument is NULL, we return NULL;
|
||||
/// - if at least one argument is nullable, we call the function implementation
|
||||
/// Strategy to apply when executing a function.
|
||||
enum Strategy
|
||||
{
|
||||
/// Merely perform the function on its columns.
|
||||
DIRECTLY_EXECUTE = 0,
|
||||
/// If at least one argument is nullable, call the function implementation
|
||||
/// with a block in which nullable columns that correspond to function arguments
|
||||
/// have been replaced with their respective nested columns;
|
||||
/// - if at least one function argument is nullable, the result column is wrapped
|
||||
/// into a nullable column.
|
||||
template <typename Fun>
|
||||
void perform(Block & block, const ColumnNumbers & arguments, size_t result, const Fun & performer);
|
||||
/// have been replaced with their respective nested columns. Subsequently, the
|
||||
/// result column is wrapped into a nullable column.
|
||||
PROCESS_NULLABLE_COLUMNS,
|
||||
/// If at least one argument is NULL, return NULL.
|
||||
RETURN_NULL
|
||||
};
|
||||
|
||||
private:
|
||||
/// Choose the strategy for performing the function.
|
||||
Strategy chooseStrategy(const Block & block, const ColumnNumbers & args);
|
||||
|
||||
/// If required by the specified strategy, process the given block, then
|
||||
/// return the processed block. Otherwise return an empty block.
|
||||
Block preProcessBlock(Strategy strategy, const Block & block, const ColumnNumbers & args);
|
||||
|
||||
/// If required by the specified strategy, post-process the result column.
|
||||
void postProcessResult(Strategy strategy, Block & block, const Block & processed_block,
|
||||
const ColumnNumbers & args, size_t result);
|
||||
};
|
||||
|
||||
|
||||
|
@ -99,7 +99,7 @@ AggregateFunctionPtr AggregateFunctionFactory::get(const String & name, const Da
|
||||
bool has_nullable_types = false;
|
||||
for (const auto & arg_type : argument_types)
|
||||
{
|
||||
if (arg_type.get()->isNullable())
|
||||
if (arg_type->isNullable())
|
||||
{
|
||||
has_nullable_types = true;
|
||||
break;
|
||||
@ -113,7 +113,7 @@ AggregateFunctionPtr AggregateFunctionFactory::get(const String & name, const Da
|
||||
|
||||
for (const auto & arg_type : argument_types)
|
||||
{
|
||||
if (arg_type.get()->isNullable())
|
||||
if (arg_type->isNullable())
|
||||
{
|
||||
const DataTypeNullable & actual_type = static_cast<const DataTypeNullable &>(*arg_type.get());
|
||||
const DataTypePtr & nested_type = actual_type.getNestedType();
|
||||
|
@ -103,7 +103,7 @@ ColumnPtr ColumnNullable::cloneResized(size_t size) const
|
||||
|
||||
/// Create a new null byte map for the cloned column.
|
||||
/// Resize it if required.
|
||||
new_col.null_map = null_map.get()->clone();
|
||||
new_col.null_map = null_map->clone();
|
||||
if (size != this->size())
|
||||
new_col.getNullMapContent().getData().resize_fill(size, 0);
|
||||
|
||||
@ -114,7 +114,7 @@ ColumnPtr ColumnNullable::cloneEmpty() const
|
||||
{
|
||||
ColumnPtr new_col_holder = std::make_shared<ColumnNullable>(nested_column->cloneEmpty());
|
||||
auto & new_col = static_cast<ColumnNullable &>(*new_col_holder);
|
||||
new_col.null_map = null_map.get()->cloneEmpty();
|
||||
new_col.null_map = null_map->cloneEmpty();
|
||||
return new_col_holder;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ Block MaterializingBlockInputStream::readImpl()
|
||||
{
|
||||
src = converted;
|
||||
auto & type = element.type;
|
||||
if (type.get()->isNull())
|
||||
if (type->isNull())
|
||||
{
|
||||
/// A ColumnNull that is converted to a full column
|
||||
/// has the type DataTypeNullable(DataTypeUInt8).
|
||||
|
@ -66,7 +66,7 @@ Block MaterializingBlockOutputStream::materialize(const Block & original_block)
|
||||
{
|
||||
src = converted;
|
||||
auto & type = element.type;
|
||||
if (type.get()->isNull())
|
||||
if (type->isNull())
|
||||
{
|
||||
/// A ColumnNull that is converted to a full column
|
||||
/// has the type DataTypeNullable(DataTypeUInt8).
|
||||
|
@ -49,13 +49,13 @@ void PrettyBlockOutputStream::calculateWidths(Block & block, Widths_t & max_widt
|
||||
|
||||
auto has_null_value = [](const ColumnPtr & col, size_t row)
|
||||
{
|
||||
if (col.get()->isNullable())
|
||||
if (col->isNullable())
|
||||
{
|
||||
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(*col);
|
||||
if (nullable_col.isNullAt(row))
|
||||
return true;
|
||||
}
|
||||
else if (col.get()->isNull())
|
||||
else if (col->isNull())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -83,13 +83,13 @@ void PrettyCompactBlockOutputStream::writeRow(
|
||||
{
|
||||
auto has_null_value = [](const ColumnPtr & col, size_t row)
|
||||
{
|
||||
if (col.get()->isNullable())
|
||||
if (col->isNullable())
|
||||
{
|
||||
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(*col);
|
||||
if (nullable_col.isNullAt(row))
|
||||
return true;
|
||||
}
|
||||
else if (col.get()->isNull())
|
||||
else if (col->isNull())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -115,7 +115,7 @@ void PrettyCompactBlockOutputStream::writeRow(
|
||||
ColumnPtr res_col = block.getByPosition(columns + j).column;
|
||||
|
||||
IColumn * observed_col;
|
||||
if (res_col.get()->isNullable())
|
||||
if (res_col->isNullable())
|
||||
{
|
||||
ColumnNullable & nullable_col = static_cast<ColumnNullable &>(*res_col);
|
||||
observed_col = nullable_col.getNestedColumn().get();
|
||||
|
@ -56,7 +56,7 @@ DataTypeNullable::DataTypeNullable(DataTypePtr nested_data_type_)
|
||||
|
||||
std::string DataTypeNullable::getName() const
|
||||
{
|
||||
return "Nullable(" + nested_data_type.get()->getName() + ")";
|
||||
return "Nullable(" + nested_data_type->getName() + ")";
|
||||
}
|
||||
|
||||
bool DataTypeNullable::isNullable() const
|
||||
@ -66,17 +66,17 @@ bool DataTypeNullable::isNullable() const
|
||||
|
||||
bool DataTypeNullable::isNumeric() const
|
||||
{
|
||||
return nested_data_type.get()->isNumeric();
|
||||
return nested_data_type->isNumeric();
|
||||
}
|
||||
|
||||
bool DataTypeNullable::behavesAsNumber() const
|
||||
{
|
||||
return nested_data_type.get()->behavesAsNumber();
|
||||
return nested_data_type->behavesAsNumber();
|
||||
}
|
||||
|
||||
DataTypePtr DataTypeNullable::clone() const
|
||||
{
|
||||
return std::make_shared<DataTypeNullable>(nested_data_type.get()->clone());
|
||||
return std::make_shared<DataTypeNullable>(nested_data_type->clone());
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeBinary(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
|
||||
@ -85,7 +85,7 @@ void DataTypeNullable::serializeBinary(const IColumn & column, WriteBuffer & ost
|
||||
if (col == nullptr)
|
||||
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
nested_data_type.get()->serializeBinary(*col->getNestedColumn(), ostr, offset, limit);
|
||||
nested_data_type->serializeBinary(*col->getNestedColumn(), ostr, offset, limit);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const
|
||||
@ -94,17 +94,17 @@ void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr, si
|
||||
if (col == nullptr)
|
||||
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
nested_data_type.get()->deserializeBinary(*col->getNestedColumn(), istr, limit, avg_value_size_hint);
|
||||
nested_data_type->deserializeBinary(*col->getNestedColumn(), istr, limit, avg_value_size_hint);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeBinary(const Field & field, WriteBuffer & ostr) const
|
||||
{
|
||||
nested_data_type.get()->serializeBinary(field, ostr);
|
||||
nested_data_type->serializeBinary(field, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeBinary(Field & field, ReadBuffer & istr) const
|
||||
{
|
||||
nested_data_type.get()->deserializeBinary(field, istr);
|
||||
nested_data_type->deserializeBinary(field, istr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -113,7 +113,7 @@ void DataTypeNullable::serializeBinary(const IColumn & column, size_t row_num, W
|
||||
if (col == nullptr)
|
||||
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
nested_data_type.get()->serializeBinary(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeBinary(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr) const
|
||||
@ -122,7 +122,7 @@ void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr) co
|
||||
if (col == nullptr)
|
||||
throw Exception{"Discrepancy between data type and column type", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
nested_data_type.get()->deserializeBinary(*col->getNestedColumn(), istr);
|
||||
nested_data_type->deserializeBinary(*col->getNestedColumn(), istr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -137,7 +137,7 @@ void DataTypeNullable::serializeTextEscaped(const IColumn & column, size_t row_n
|
||||
if (isNullValue(&null_map, row_num))
|
||||
writeCString(NullSymbol::Escaped::name, ostr);
|
||||
else
|
||||
nested_data_type.get()->serializeTextEscaped(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeTextEscaped(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const
|
||||
@ -152,10 +152,10 @@ void DataTypeNullable::deserializeTextEscaped(IColumn & column, ReadBuffer & ist
|
||||
if (Deserializer<NullSymbol::Escaped>::execute(column, istr, &null_map))
|
||||
{
|
||||
ColumnPtr & nested_col = col->getNestedColumn();
|
||||
nested_col.get()->insertDefault();
|
||||
nested_col->insertDefault();
|
||||
}
|
||||
else
|
||||
nested_data_type.get()->deserializeTextEscaped(*col->getNestedColumn(), istr);
|
||||
nested_data_type->deserializeTextEscaped(*col->getNestedColumn(), istr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -170,7 +170,7 @@ void DataTypeNullable::serializeTextQuoted(const IColumn & column, size_t row_nu
|
||||
if (isNullValue(&null_map, row_num))
|
||||
writeCString(NullSymbol::Quoted::name, ostr);
|
||||
else
|
||||
nested_data_type.get()->serializeTextQuoted(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeTextQuoted(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const
|
||||
@ -185,10 +185,10 @@ void DataTypeNullable::deserializeTextQuoted(IColumn & column, ReadBuffer & istr
|
||||
if (Deserializer<NullSymbol::Quoted>::execute(column, istr, &null_map))
|
||||
{
|
||||
ColumnPtr & nested_col = col->getNestedColumn();
|
||||
nested_col.get()->insertDefault();
|
||||
nested_col->insertDefault();
|
||||
}
|
||||
else
|
||||
nested_data_type.get()->deserializeTextQuoted(*col->getNestedColumn(), istr);
|
||||
nested_data_type->deserializeTextQuoted(*col->getNestedColumn(), istr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -203,7 +203,7 @@ void DataTypeNullable::serializeTextCSV(const IColumn & column, size_t row_num,
|
||||
if (isNullValue(&null_map, row_num))
|
||||
writeCString(NullSymbol::Quoted::name, ostr);
|
||||
else
|
||||
nested_data_type.get()->serializeTextCSV(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeTextCSV(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const
|
||||
@ -218,10 +218,10 @@ void DataTypeNullable::deserializeTextCSV(IColumn & column, ReadBuffer & istr, c
|
||||
if (Deserializer<NullSymbol::Quoted>::execute(column, istr, &null_map))
|
||||
{
|
||||
ColumnPtr & nested_col = col->getNestedColumn();
|
||||
nested_col.get()->insertDefault();
|
||||
nested_col->insertDefault();
|
||||
}
|
||||
else
|
||||
nested_data_type.get()->deserializeTextCSV(*col->getNestedColumn(), istr, delimiter);
|
||||
nested_data_type->deserializeTextCSV(*col->getNestedColumn(), istr, delimiter);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -236,7 +236,7 @@ void DataTypeNullable::serializeText(const IColumn & column, size_t row_num, Wri
|
||||
if (isNullValue(&null_map, row_num))
|
||||
writeCString(NullSymbol::Plain::name, ostr);
|
||||
else
|
||||
nested_data_type.get()->serializeText(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeText(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -251,7 +251,7 @@ void DataTypeNullable::serializeTextJSON(const IColumn & column, size_t row_num,
|
||||
if (isNullValue(&null_map, row_num))
|
||||
writeCString(NullSymbol::JSON::name, ostr);
|
||||
else
|
||||
nested_data_type.get()->serializeTextJSON(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeTextJSON(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::deserializeTextJSON(IColumn & column, ReadBuffer & istr) const
|
||||
@ -266,10 +266,10 @@ void DataTypeNullable::deserializeTextJSON(IColumn & column, ReadBuffer & istr)
|
||||
if (Deserializer<NullSymbol::JSON>::execute(column, istr, &null_map))
|
||||
{
|
||||
ColumnPtr & nested_col = col->getNestedColumn();
|
||||
nested_col.get()->insertDefault();
|
||||
nested_col->insertDefault();
|
||||
}
|
||||
else
|
||||
nested_data_type.get()->deserializeTextJSON(*col->getNestedColumn(), istr);
|
||||
nested_data_type->deserializeTextJSON(*col->getNestedColumn(), istr);
|
||||
}
|
||||
|
||||
void DataTypeNullable::serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
@ -284,12 +284,12 @@ void DataTypeNullable::serializeTextXML(const IColumn & column, size_t row_num,
|
||||
if (isNullValue(&null_map, row_num))
|
||||
writeCString(NullSymbol::XML::name, ostr);
|
||||
else
|
||||
nested_data_type.get()->serializeTextXML(*col->getNestedColumn(), row_num, ostr);
|
||||
nested_data_type->serializeTextXML(*col->getNestedColumn(), row_num, ostr);
|
||||
}
|
||||
|
||||
ColumnPtr DataTypeNullable::createColumn() const
|
||||
{
|
||||
ColumnPtr new_col_holder = std::make_shared<ColumnNullable>(nested_data_type.get()->createColumn());
|
||||
ColumnPtr new_col_holder = std::make_shared<ColumnNullable>(nested_data_type->createColumn());
|
||||
ColumnNullable & nullable_col = static_cast<ColumnNullable &>(*new_col_holder);
|
||||
nullable_col.getNullValuesByteMap() = std::make_shared<ColumnUInt8>();
|
||||
return new_col_holder;
|
||||
@ -297,7 +297,7 @@ ColumnPtr DataTypeNullable::createColumn() const
|
||||
|
||||
ColumnPtr DataTypeNullable::createConstColumn(size_t size, const Field & field) const
|
||||
{
|
||||
ColumnPtr new_col_holder = std::make_shared<ColumnNullable>(nested_data_type.get()->createConstColumn(size, field));
|
||||
ColumnPtr new_col_holder = std::make_shared<ColumnNullable>(nested_data_type->createConstColumn(size, field));
|
||||
ColumnNullable & nullable_col = static_cast<ColumnNullable &>(*new_col_holder);
|
||||
nullable_col.getNullValuesByteMap() = std::make_shared<ColumnUInt8>(size);
|
||||
return new_col_holder;
|
||||
@ -305,12 +305,12 @@ ColumnPtr DataTypeNullable::createConstColumn(size_t size, const Field & field)
|
||||
|
||||
Field DataTypeNullable::getDefault() const
|
||||
{
|
||||
return nested_data_type.get()->getDefault();
|
||||
return nested_data_type->getDefault();
|
||||
}
|
||||
|
||||
size_t DataTypeNullable::getSizeOfField() const
|
||||
{
|
||||
return nested_data_type.get()->getSizeOfField();
|
||||
return nested_data_type->getSizeOfField();
|
||||
}
|
||||
|
||||
DataTypePtr & DataTypeNullable::getNestedType()
|
||||
|
@ -98,7 +98,7 @@ struct TypeChecker
|
||||
{
|
||||
static bool execute(const DataTypePtr & arg)
|
||||
{
|
||||
if (arg.get()->isNullable())
|
||||
if (arg->isNullable())
|
||||
return false;
|
||||
return typeid_cast<const TType *>(arg.get()) != nullptr;
|
||||
}
|
||||
@ -109,7 +109,7 @@ struct TypeChecker<Nullable<TType>>
|
||||
{
|
||||
static bool execute(const DataTypePtr & arg)
|
||||
{
|
||||
if (!arg.get()->isNullable())
|
||||
if (!arg->isNullable())
|
||||
return false;
|
||||
|
||||
const DataTypeNullable & nullable_type = static_cast<DataTypeNullable &>(*arg);
|
||||
@ -203,7 +203,7 @@ bool hasArithmeticBranches(const DataTypes & args)
|
||||
|
||||
auto check = [&](size_t i)
|
||||
{
|
||||
return args[i].get()->behavesAsNumber();
|
||||
return args[i]->behavesAsNumber();
|
||||
};
|
||||
|
||||
for (size_t i = firstThen(); i < else_arg; i = nextThen(i))
|
||||
@ -222,7 +222,7 @@ bool hasArrayBranches(const DataTypes & args)
|
||||
auto check = [&](size_t i)
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -230,7 +230,7 @@ bool hasArrayBranches(const DataTypes & args)
|
||||
else
|
||||
observed_type = args[i].get();
|
||||
|
||||
return (typeid_cast<const DataTypeArray *>(observed_type) != nullptr) || args[i].get()->isNull();
|
||||
return (typeid_cast<const DataTypeArray *>(observed_type) != nullptr) || args[i]->isNull();
|
||||
};
|
||||
|
||||
for (size_t i = firstThen(); i < elseArg(args); i = nextThen(i))
|
||||
@ -250,10 +250,10 @@ bool hasIdenticalTypes(const DataTypes & args)
|
||||
|
||||
for (size_t i = firstThen(); i < else_arg; i = nextThen(i))
|
||||
{
|
||||
if (!args[i].get()->isNullable())
|
||||
if (!args[i]->isNullable())
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -273,10 +273,10 @@ bool hasIdenticalTypes(const DataTypes & args)
|
||||
}
|
||||
}
|
||||
|
||||
if (!args[else_arg].get()->isNull())
|
||||
if (!args[else_arg]->isNull())
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[else_arg].get()->isNullable())
|
||||
if (args[else_arg]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[else_arg]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -302,7 +302,7 @@ bool hasFixedStrings(const DataTypes & args)
|
||||
auto check = [&](size_t i)
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -310,7 +310,7 @@ bool hasFixedStrings(const DataTypes & args)
|
||||
else
|
||||
observed_type = args[i].get();
|
||||
|
||||
return (typeid_cast<const DataTypeFixedString *>(observed_type) != nullptr) || (args[i].get()->isNull());
|
||||
return (typeid_cast<const DataTypeFixedString *>(observed_type) != nullptr) || (args[i]->isNull());
|
||||
};
|
||||
|
||||
for (size_t i = firstThen(); i < elseArg(args); i = nextThen(i))
|
||||
@ -341,7 +341,7 @@ bool hasFixedStringsOfIdenticalLength(const DataTypes & args)
|
||||
for (size_t i = firstThen(); i < else_arg; i = nextThen(i))
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (!args[i].get()->isNullable())
|
||||
if (!args[i]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -363,10 +363,10 @@ bool hasFixedStringsOfIdenticalLength(const DataTypes & args)
|
||||
}
|
||||
}
|
||||
|
||||
if (!args[else_arg].get()->isNull())
|
||||
if (!args[else_arg]->isNull())
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[else_arg].get()->isNullable())
|
||||
if (args[else_arg]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[else_arg]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -392,7 +392,7 @@ bool hasStrings(const DataTypes & args)
|
||||
auto check = [&](size_t i)
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -401,7 +401,7 @@ bool hasStrings(const DataTypes & args)
|
||||
observed_type = args[i].get();
|
||||
|
||||
return (typeid_cast<const DataTypeFixedString *>(observed_type) != nullptr) ||
|
||||
(typeid_cast<const DataTypeString *>(observed_type) != nullptr) || args[i].get()->isNull();
|
||||
(typeid_cast<const DataTypeString *>(observed_type) != nullptr) || args[i]->isNull();
|
||||
};
|
||||
|
||||
for (size_t i = firstThen(); i < elseArg(args); i = nextThen(i))
|
||||
|
@ -32,7 +32,7 @@ const ColumnPtr CondSource::initMaterializedCol(const Block & block, const Colum
|
||||
{
|
||||
const ColumnPtr & col = block.getByPosition(args[i]).column;
|
||||
|
||||
if (col.get()->isNull())
|
||||
if (col->isNull())
|
||||
{
|
||||
const ColumnNull & null_col = static_cast<const ColumnNull &>(*col);
|
||||
return null_col.convertToFullColumn();
|
||||
@ -40,7 +40,7 @@ const ColumnPtr CondSource::initMaterializedCol(const Block & block, const Colum
|
||||
|
||||
const IColumn * observed_col;
|
||||
|
||||
if (col.get()->isNullable())
|
||||
if (col->isNullable())
|
||||
{
|
||||
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(*col);
|
||||
observed_col = nullable_col.getNestedColumn().get();
|
||||
@ -91,7 +91,7 @@ const PaddedPODArray<UInt8> & CondSource::initDataArray(const Block & block, con
|
||||
const PaddedPODArray<UInt8> & CondSource::initNullMap(const Block & block, const ColumnNumbers & args, size_t i)
|
||||
{
|
||||
const ColumnPtr & col = block.getByPosition(args[i]).column;
|
||||
if (col.get()->isNullable())
|
||||
if (col->isNullable())
|
||||
{
|
||||
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(*col);
|
||||
const ColumnPtr & null_map = nullable_col.getNullValuesByteMap();
|
||||
|
@ -89,7 +89,7 @@ struct TypeChecker
|
||||
{
|
||||
static bool execute(const DataTypePtr & arg)
|
||||
{
|
||||
if (arg.get()->isNullable())
|
||||
if (arg->isNullable())
|
||||
return false;
|
||||
return typeid_cast<const TType *>(arg.get()) != nullptr;
|
||||
}
|
||||
@ -100,7 +100,7 @@ struct TypeChecker<Nullable<TType>>
|
||||
{
|
||||
static bool execute(const DataTypePtr & arg)
|
||||
{
|
||||
if (!arg.get()->isNullable())
|
||||
if (!arg->isNullable())
|
||||
return false;
|
||||
|
||||
const DataTypeNullable & nullable_type = static_cast<DataTypeNullable &>(*arg);
|
||||
|
@ -17,9 +17,9 @@ namespace DB
|
||||
namespace
|
||||
{
|
||||
|
||||
/// Check whether at least one of the specified columns is either nullable
|
||||
/// or null inside its block.
|
||||
bool hasNullableBranches(const Block & block, const ColumnNumbers & args)
|
||||
/// Check whether at least one of the specified branches of the function multiIf
|
||||
/// is either a nullable column or a null column inside a given block.
|
||||
bool blockHasNullableBranches(const Block & block, const ColumnNumbers & args)
|
||||
{
|
||||
auto check = [](const Block & block, size_t arg)
|
||||
{
|
||||
@ -40,30 +40,30 @@ bool hasNullableBranches(const Block & block, const ColumnNumbers & args)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasNullableArgs(const DataTypes & args)
|
||||
bool hasNullableDataTypes(const DataTypes & args)
|
||||
{
|
||||
size_t else_arg = Conditional::elseArg(args);
|
||||
|
||||
for (size_t i = Conditional::firstThen(); i < else_arg; i = Conditional::nextThen(i))
|
||||
{
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
return true;
|
||||
}
|
||||
|
||||
return args[else_arg].get()->isNullable();
|
||||
return args[else_arg]->isNullable();
|
||||
}
|
||||
|
||||
bool hasNullArgs(const DataTypes & args)
|
||||
bool hasNullDataTypes(const DataTypes & args)
|
||||
{
|
||||
size_t else_arg = Conditional::elseArg(args);
|
||||
|
||||
for (size_t i = Conditional::firstThen(); i < else_arg; i = Conditional::nextThen(i))
|
||||
{
|
||||
if (args[i].get()->isNull())
|
||||
if (args[i]->isNull())
|
||||
return true;
|
||||
}
|
||||
|
||||
return args[else_arg].get()->isNull();
|
||||
return args[else_arg]->isNull();
|
||||
}
|
||||
|
||||
}
|
||||
@ -138,7 +138,7 @@ void FunctionMultiIf::executeImpl(Block & block, const ColumnNumbers & args, siz
|
||||
|
||||
try
|
||||
{
|
||||
if (!hasNullableBranches(block, args))
|
||||
if (!blockHasNullableBranches(block, args))
|
||||
{
|
||||
perform_multi_if(block, args, result, result);
|
||||
return;
|
||||
@ -162,21 +162,21 @@ void FunctionMultiIf::executeImpl(Block & block, const ColumnNumbers & args, siz
|
||||
args_to_transform.push_back(args[i]);
|
||||
args_to_transform.push_back(args[else_arg]);
|
||||
|
||||
Block non_nullable_block = extractNonNullableBlock(block, args_to_transform);
|
||||
Block block_with_nested_cols = createBlockWithNestedColumns(block, args_to_transform);
|
||||
|
||||
/// Append a column that tracks, for each result of multiIf, the index
|
||||
/// of the originating column.
|
||||
ColumnWithTypeAndName elem;
|
||||
elem.type = std::make_shared<DataTypeUInt16>();
|
||||
|
||||
size_t tracker = non_nullable_block.columns();
|
||||
non_nullable_block.insert(elem);
|
||||
size_t tracker = block_with_nested_cols.columns();
|
||||
block_with_nested_cols.insert(elem);
|
||||
|
||||
/// Really perform multiIf.
|
||||
perform_multi_if(non_nullable_block, args, result, tracker);
|
||||
perform_multi_if(block_with_nested_cols, args, result, tracker);
|
||||
|
||||
/// Store the result.
|
||||
const ColumnWithTypeAndName & source_col = non_nullable_block.unsafeGetByPosition(result);
|
||||
const ColumnWithTypeAndName & source_col = block_with_nested_cols.unsafeGetByPosition(result);
|
||||
ColumnWithTypeAndName & dest_col = block.unsafeGetByPosition(result);
|
||||
|
||||
if (source_col.column->isNull())
|
||||
@ -189,7 +189,7 @@ void FunctionMultiIf::executeImpl(Block & block, const ColumnNumbers & args, siz
|
||||
dest_col.column = std::make_shared<ColumnNullable>(source_col.column);
|
||||
|
||||
/// Setup the null byte map of the result column by using the branch tracker column values.
|
||||
ColumnPtr tracker_holder = non_nullable_block.unsafeGetByPosition(tracker).column;
|
||||
ColumnPtr tracker_holder = block_with_nested_cols.unsafeGetByPosition(tracker).column;
|
||||
ColumnNullable & nullable_col = static_cast<ColumnNullable &>(*dest_col.column);
|
||||
|
||||
if (auto col = typeid_cast<ColumnConstUInt16 *>(tracker_holder.get()))
|
||||
@ -213,29 +213,30 @@ void FunctionMultiIf::executeImpl(Block & block, const ColumnNumbers & args, siz
|
||||
}
|
||||
else if (auto col = typeid_cast<ColumnUInt16 *>(tracker_holder.get()))
|
||||
{
|
||||
/// Keep track of which columns are nullable.
|
||||
/// Remember which columns are nullable. This avoids us many costly
|
||||
/// calls to virtual functions.
|
||||
std::vector<UInt8> nullable_cols_map;
|
||||
nullable_cols_map.resize(args.size());
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
const auto & col = block.unsafeGetByPosition(arg).column;
|
||||
bool may_have_null = col->isNullable();
|
||||
nullable_cols_map[arg] = may_have_null ? 1 : 0;
|
||||
bool is_nullable = col->isNullable();
|
||||
nullable_cols_map[arg] = is_nullable ? 1 : 0;
|
||||
}
|
||||
|
||||
/// Keep track of which columns are null.
|
||||
/// Remember which columns are null. The same remark as above applies.
|
||||
std::vector<UInt8> null_cols_map;
|
||||
null_cols_map.resize(args.size());
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
const auto & col = block.unsafeGetByPosition(arg).column;
|
||||
bool has_null = col->isNull();
|
||||
null_cols_map[arg] = has_null ? 1 : 0;
|
||||
bool is_null = col->isNull();
|
||||
null_cols_map[arg] = is_null ? 1 : 0;
|
||||
}
|
||||
|
||||
auto null_map = std::make_shared<ColumnUInt8>(row_count);
|
||||
nullable_col.getNullValuesByteMap() = null_map;
|
||||
auto & null_map_data = null_map.get()->getData();
|
||||
auto & null_map_data = null_map->getData();
|
||||
|
||||
const auto & data = col->getData();
|
||||
for (size_t row = 0; row < row_count; ++row)
|
||||
@ -278,11 +279,11 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH};
|
||||
}
|
||||
|
||||
/// Check conditions types.
|
||||
/// Check that conditions have valid types.
|
||||
for (size_t i = Conditional::firstCond(); i < Conditional::elseArg(args); i = Conditional::nextCond(i))
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -302,8 +303,8 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
}
|
||||
}
|
||||
|
||||
bool has_nullable_args = hasNullableArgs(args);
|
||||
bool has_null_args = hasNullArgs(args);
|
||||
bool has_nullable_types = hasNullableDataTypes(args);
|
||||
bool has_null_types = hasNullDataTypes(args);
|
||||
|
||||
if (Conditional::hasArithmeticBranches(args))
|
||||
return Conditional::getReturnTypeForArithmeticArgs(args);
|
||||
@ -315,12 +316,12 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
|
||||
auto push_branch_arg = [&args, &new_args](size_t i)
|
||||
{
|
||||
if (args[i].get()->isNull())
|
||||
if (args[i]->isNull())
|
||||
new_args.push_back(args[i]);
|
||||
else
|
||||
{
|
||||
const IDataType * observed_type;
|
||||
if (args[i].get()->isNullable())
|
||||
if (args[i]->isNullable())
|
||||
{
|
||||
const auto & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
@ -350,14 +351,14 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
/// deal with null arguments and arrays that contain null elements.
|
||||
/// For now we assume that arrays do not contain any such elements.
|
||||
DataTypePtr elt_type = getReturnTypeImpl(new_args);
|
||||
if (elt_type.get()->isNullable())
|
||||
if (elt_type->isNullable())
|
||||
{
|
||||
DataTypeNullable & nullable_type = static_cast<DataTypeNullable &>(*elt_type);
|
||||
elt_type = nullable_type.getNestedType();
|
||||
}
|
||||
|
||||
DataTypePtr type = std::make_shared<DataTypeArray>(elt_type);
|
||||
if (has_nullable_args || has_null_args)
|
||||
if (has_nullable_types || has_null_types)
|
||||
type = std::make_shared<DataTypeNullable>(type);
|
||||
return type;
|
||||
}
|
||||
@ -384,14 +385,14 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
throw Exception{"Internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
DataTypePtr type = std::make_shared<DataTypeFixedString>(fixed_str->getN());
|
||||
if (has_nullable_args || has_null_args)
|
||||
if (has_nullable_types || has_null_types)
|
||||
type = std::make_shared<DataTypeNullable>(type);
|
||||
return type;
|
||||
}
|
||||
else if (Conditional::hasStrings(args))
|
||||
{
|
||||
DataTypePtr type = std::make_shared<DataTypeString>();
|
||||
if (has_nullable_args || has_null_args)
|
||||
if (has_nullable_types || has_null_types)
|
||||
type = std::make_shared<DataTypeNullable>(type);
|
||||
return type;
|
||||
}
|
||||
@ -413,11 +414,11 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
/// Make it nullable if there is at least one nullable branch
|
||||
/// or one null branch.
|
||||
|
||||
auto get_type_to_return = [has_nullable_args, has_null_args](const DataTypePtr & arg) -> DataTypePtr
|
||||
auto get_type_to_return = [has_nullable_types, has_null_types](const DataTypePtr & arg) -> DataTypePtr
|
||||
{
|
||||
if (arg.get()->isNullable())
|
||||
if (arg->isNullable())
|
||||
return arg;
|
||||
else if (has_nullable_args || has_null_args)
|
||||
else if (has_nullable_types || has_null_types)
|
||||
return std::make_shared<DataTypeNullable>(arg);
|
||||
else
|
||||
return arg;
|
||||
@ -425,12 +426,12 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
||||
|
||||
for (size_t i = Conditional::firstThen(); i < Conditional::elseArg(args); i = Conditional::nextThen(i))
|
||||
{
|
||||
if (!args[i].get()->isNull())
|
||||
if (!args[i]->isNull())
|
||||
return get_type_to_return(args[i]);
|
||||
}
|
||||
|
||||
size_t i = Conditional::elseArg(args);
|
||||
if (!args[i].get()->isNull())
|
||||
if (!args[i]->isNull())
|
||||
return get_type_to_return(args[i]);
|
||||
|
||||
/// All the branches are null.
|
||||
@ -452,9 +453,9 @@ bool FunctionMultiIf::performTrivialCase(Block & block, const ColumnNumbers & ar
|
||||
size_t else_arg = Conditional::elseArg(args);
|
||||
for (size_t i = Conditional::firstThen(); i < else_arg; i = Conditional::nextThen(i))
|
||||
{
|
||||
if (!block.getByPosition(args[i]).type.get()->isNull())
|
||||
if (!block.getByPosition(args[i]).type->isNull())
|
||||
{
|
||||
const auto & name = block.getByPosition(args[i]).type.get()->getName();
|
||||
const auto & name = block.getByPosition(args[i]).type->getName();
|
||||
if (first_type_name.empty())
|
||||
{
|
||||
first_type_name = name;
|
||||
@ -469,7 +470,7 @@ bool FunctionMultiIf::performTrivialCase(Block & block, const ColumnNumbers & ar
|
||||
}
|
||||
}
|
||||
|
||||
if (!block.getByPosition(args[else_arg]).type.get()->isNull())
|
||||
if (!block.getByPosition(args[else_arg]).type->isNull())
|
||||
{
|
||||
if (first_type_name.empty())
|
||||
{
|
||||
@ -478,7 +479,7 @@ bool FunctionMultiIf::performTrivialCase(Block & block, const ColumnNumbers & ar
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto & name = block.getByPosition(args[else_arg]).type.get()->getName();
|
||||
const auto & name = block.getByPosition(args[else_arg]).type->getName();
|
||||
if (name != first_type_name)
|
||||
return false;
|
||||
}
|
||||
@ -514,8 +515,8 @@ bool FunctionMultiIf::performTrivialCase(Block & block, const ColumnNumbers & ar
|
||||
auto make_result = [&](size_t index)
|
||||
{
|
||||
res_col = block.getByPosition(index).column;
|
||||
if (res_col.get()->isNull())
|
||||
res_col = type.get()->createConstColumn(row_count, sample);
|
||||
if (res_col->isNull())
|
||||
res_col = type->createConstColumn(row_count, sample);
|
||||
if (tracker != result)
|
||||
{
|
||||
ColumnPtr & col = block.getByPosition(tracker).column;
|
||||
|
@ -308,9 +308,9 @@ DataTypePtr FunctionAssumeNotNull::getReturnTypeImpl(const DataTypes & arguments
|
||||
+ toString(arguments.size()) + ", should be 1.",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH};
|
||||
|
||||
if (arguments[0].get()->isNull())
|
||||
if (arguments[0]->isNull())
|
||||
throw Exception{"NULL is an invalid value for function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
else if (arguments[0].get()->isNullable())
|
||||
else if (arguments[0]->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*arguments[0]);
|
||||
return nullable_type.getNestedType();
|
||||
@ -324,9 +324,9 @@ void FunctionAssumeNotNull::executeImpl(Block & block, const ColumnNumbers & arg
|
||||
const ColumnPtr & col = block.getByPosition(arguments[0]).column;
|
||||
ColumnPtr & res_col = block.getByPosition(result).column;
|
||||
|
||||
if (col.get()->isNull())
|
||||
if (col->isNull())
|
||||
throw Exception{"NULL is an invalid value for function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
else if (col.get()->isNullable())
|
||||
else if (col->isNullable())
|
||||
{
|
||||
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(*col);
|
||||
res_col = nullable_col.getNestedColumn();
|
||||
|
@ -22,11 +22,8 @@ void createNullValuesByteMap(Block & block, const ColumnNumbers & args, size_t r
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg == result)
|
||||
continue;
|
||||
|
||||
const ColumnWithTypeAndName & elem = block.unsafeGetByPosition(arg);
|
||||
if (elem.column && elem.column->isNullable())
|
||||
if (elem.column->isNullable())
|
||||
{
|
||||
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(*elem.column);
|
||||
res_col.updateNullValuesByteMap(nullable_col);
|
||||
@ -34,87 +31,105 @@ void createNullValuesByteMap(Block & block, const ColumnNumbers & args, size_t r
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a block contains at least one null column.
|
||||
bool blockHasNullColumns(const Block & block, const ColumnNumbers & arguments)
|
||||
/// In a set of objects (columns of a block / set of columns / set of data types),
|
||||
/// are there any "special" (i.e. nullable or null) objects?
|
||||
enum class Category
|
||||
{
|
||||
for (const auto & arg : arguments)
|
||||
/// No nullable objects. No null objects.
|
||||
IS_ORDINARY = 0,
|
||||
/// At least one nullable object. No null objects.
|
||||
IS_NULLABLE,
|
||||
/// At least one null object.
|
||||
IS_NULL
|
||||
};
|
||||
|
||||
/// Check if a block contains at least one special column, in the sense
|
||||
/// defined above, among the specified columns.
|
||||
Category blockHasSpecialColumns(const Block & block, const ColumnNumbers & args)
|
||||
{
|
||||
bool found_nullable = false;
|
||||
bool found_null = false;
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
const auto & elem = block.unsafeGetByPosition(arg);
|
||||
if (elem.column && elem.column->isNull())
|
||||
return true;
|
||||
|
||||
if (!found_null && elem.column->isNull())
|
||||
{
|
||||
found_null = true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
else if (!found_nullable & elem.column->isNullable())
|
||||
found_nullable = true;
|
||||
}
|
||||
|
||||
if (found_null)
|
||||
return Category::IS_NULL;
|
||||
else if (found_nullable)
|
||||
return Category::IS_NULLABLE;
|
||||
else
|
||||
return Category::IS_ORDINARY;
|
||||
}
|
||||
|
||||
/// Check if at least one column is null.
|
||||
bool hasNullColumns(const ColumnsWithTypeAndName & args)
|
||||
/// Check if at least one column is special in the sense defined above.
|
||||
Category hasSpecialColumns(const ColumnsWithTypeAndName & args)
|
||||
{
|
||||
bool found_nullable = false;
|
||||
bool found_null = false;
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg.type.get()->isNull())
|
||||
return true;
|
||||
if (!found_null && arg.type->isNull())
|
||||
{
|
||||
found_null = true;
|
||||
break;
|
||||
}
|
||||
else if (!found_nullable & arg.type->isNullable())
|
||||
found_nullable = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (found_null)
|
||||
return Category::IS_NULL;
|
||||
else if (found_nullable)
|
||||
return Category::IS_NULLABLE;
|
||||
else
|
||||
return Category::IS_ORDINARY;
|
||||
}
|
||||
|
||||
/// Check if at least one argument is null.
|
||||
bool hasNullArguments(const DataTypes & args)
|
||||
/// Check if at least one data type is special in the sense defined above.
|
||||
Category hasSpecialDataTypes(const DataTypes & args)
|
||||
{
|
||||
bool found_nullable = false;
|
||||
bool found_null = false;
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg.get()->isNull())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if a block contains at least one nullable column.
|
||||
bool blockHasNullableColumns(const Block & block, const ColumnNumbers & arguments)
|
||||
{
|
||||
for (const auto & arg : arguments)
|
||||
if (!found_null && arg->isNull())
|
||||
{
|
||||
const auto & elem = block.unsafeGetByPosition(arg);
|
||||
if (elem.column && elem.column->isNullable())
|
||||
return true;
|
||||
found_null = true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if at least one column is nullable.
|
||||
bool hasNullableColumns(const ColumnsWithTypeAndName & args)
|
||||
{
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg.type.get()->isNullable())
|
||||
return true;
|
||||
else if (!found_nullable & arg->isNullable())
|
||||
found_nullable = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (found_null)
|
||||
return Category::IS_NULL;
|
||||
else if (found_nullable)
|
||||
return Category::IS_NULLABLE;
|
||||
else
|
||||
return Category::IS_ORDINARY;
|
||||
}
|
||||
|
||||
/// Check if at least one argument is nullable.
|
||||
bool hasNullableArguments(const DataTypes & args)
|
||||
{
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg.get()->isNullable())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Turn the specified set of columns into a set of non-nullable columns.
|
||||
ColumnsWithTypeAndName toNonNullableColumns(const ColumnsWithTypeAndName & args)
|
||||
/// Turn the specified set of columns into their respective nested columns.
|
||||
ColumnsWithTypeAndName toNestedColumns(const ColumnsWithTypeAndName & args)
|
||||
{
|
||||
ColumnsWithTypeAndName new_args;
|
||||
new_args.reserve(args.size());
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg.type.get()->isNullable())
|
||||
if (arg.type->isNullable())
|
||||
{
|
||||
auto nullable_col = static_cast<const ColumnNullable *>(arg.column.get());
|
||||
ColumnPtr nested_col = (nullable_col != nullptr) ? nullable_col->getNestedColumn() : nullptr;
|
||||
@ -130,15 +145,15 @@ ColumnsWithTypeAndName toNonNullableColumns(const ColumnsWithTypeAndName & args)
|
||||
return new_args;
|
||||
}
|
||||
|
||||
/// Turn the specified set of data types into a set of non-nullable data types.
|
||||
DataTypes toNonNullableArguments(const DataTypes & args)
|
||||
/// Turn the specified set of data types into their respective nested data types.
|
||||
DataTypes toNestedDataTypes(const DataTypes & args)
|
||||
{
|
||||
DataTypes new_args;
|
||||
new_args.reserve(args.size());
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
if (arg.get()->isNullable())
|
||||
if (arg->isNullable())
|
||||
{
|
||||
auto nullable_type = static_cast<const DataTypeNullable *>(arg.get());
|
||||
DataTypePtr nested_type = nullable_type->getNestedType();
|
||||
@ -155,15 +170,27 @@ DataTypes toNonNullableArguments(const DataTypes & args)
|
||||
|
||||
DataTypePtr IFunction::getReturnType(const DataTypes & arguments) const
|
||||
{
|
||||
if (!hasSpecialSupportForNulls() && hasNullArguments(arguments))
|
||||
return std::make_shared<DataTypeNull>();
|
||||
auto category = hasSpecialDataTypes(arguments);
|
||||
|
||||
if (!hasSpecialSupportForNulls() && hasNullableArguments(arguments))
|
||||
if (category == Category::IS_ORDINARY)
|
||||
{
|
||||
const DataTypes new_args = toNonNullableArguments(arguments);
|
||||
}
|
||||
else if (category == Category::IS_NULL)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
return std::make_shared<DataTypeNull>();
|
||||
}
|
||||
else if (category == Category::IS_NULLABLE)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
{
|
||||
const DataTypes new_args = toNestedDataTypes(arguments);
|
||||
return getReturnTypeImpl(new_args);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Exception{"IFunction: internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
return getReturnTypeImpl(arguments);
|
||||
}
|
||||
|
||||
@ -172,50 +199,168 @@ void IFunction::getReturnTypeAndPrerequisites(
|
||||
DataTypePtr & out_return_type,
|
||||
std::vector<ExpressionAction> & out_prerequisites)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls() && hasNullColumns(arguments))
|
||||
{
|
||||
out_return_type = std::make_shared<DataTypeNull>();
|
||||
return;
|
||||
}
|
||||
auto category = hasSpecialColumns(arguments);
|
||||
|
||||
if (!hasSpecialSupportForNulls() && hasNullableColumns(arguments))
|
||||
if (category == Category::IS_ORDINARY)
|
||||
{
|
||||
const ColumnsWithTypeAndName new_args = toNonNullableColumns(arguments);
|
||||
}
|
||||
else if (category == Category::IS_NULL)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
out_return_type = std::make_shared<DataTypeNull>();
|
||||
}
|
||||
else if (category == Category::IS_NULLABLE)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
{
|
||||
const ColumnsWithTypeAndName new_args = toNestedColumns(arguments);
|
||||
getReturnTypeAndPrerequisitesImpl(new_args, out_return_type, out_prerequisites);
|
||||
out_return_type = std::make_shared<DataTypeNullable>(out_return_type);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Exception{"IFunction: internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
getReturnTypeAndPrerequisitesImpl(arguments, out_return_type, out_prerequisites);
|
||||
}
|
||||
|
||||
void IFunction::getLambdaArgumentTypes(DataTypes & arguments) const
|
||||
{
|
||||
if (!hasSpecialSupportForNulls() && hasNullArguments(arguments))
|
||||
return;
|
||||
auto category = hasSpecialDataTypes(arguments);
|
||||
|
||||
if (!hasSpecialSupportForNulls() && hasNullableArguments(arguments))
|
||||
if (category == Category::IS_ORDINARY)
|
||||
{
|
||||
DataTypes new_args = toNonNullableArguments(arguments);
|
||||
}
|
||||
else if (category == Category::IS_NULL)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
return;
|
||||
}
|
||||
else if (category == Category::IS_NULLABLE)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
{
|
||||
DataTypes new_args = toNestedDataTypes(arguments);
|
||||
getLambdaArgumentTypesImpl(new_args);
|
||||
arguments = std::move(new_args);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Exception{"IFunction: internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
getLambdaArgumentTypesImpl(arguments);
|
||||
}
|
||||
|
||||
void IFunction::execute(Block & block, const ColumnNumbers & args, size_t result)
|
||||
{
|
||||
auto strategy = chooseStrategy(block, args);
|
||||
Block processed_block = preProcessBlock(strategy, block, args);
|
||||
|
||||
if (strategy != RETURN_NULL)
|
||||
{
|
||||
Block & src = processed_block ? processed_block : block;
|
||||
executeImpl(src, args, result);
|
||||
}
|
||||
|
||||
postProcessResult(strategy, block, processed_block, args, result);
|
||||
}
|
||||
|
||||
void IFunction::execute(Block & block, const ColumnNumbers & args, const ColumnNumbers & prerequisites, size_t result)
|
||||
{
|
||||
auto strategy = chooseStrategy(block, args);
|
||||
Block processed_block = preProcessBlock(strategy, block, args);
|
||||
|
||||
if (strategy != RETURN_NULL)
|
||||
{
|
||||
Block & src = processed_block ? processed_block : block;
|
||||
executeImpl(src, args, prerequisites, result);
|
||||
}
|
||||
|
||||
postProcessResult(strategy, block, processed_block, args, result);
|
||||
}
|
||||
|
||||
IFunction::Strategy IFunction::chooseStrategy(const Block & block, const ColumnNumbers & args)
|
||||
{
|
||||
auto category = blockHasSpecialColumns(block, args);
|
||||
|
||||
if (category == Category::IS_ORDINARY)
|
||||
{
|
||||
}
|
||||
else if (category == Category::IS_NULL)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
return RETURN_NULL;
|
||||
}
|
||||
else if (category == Category::IS_NULLABLE)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls())
|
||||
return PROCESS_NULLABLE_COLUMNS;
|
||||
}
|
||||
else
|
||||
throw Exception{"IFunction: internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
|
||||
return DIRECTLY_EXECUTE;
|
||||
}
|
||||
|
||||
Block IFunction::preProcessBlock(Strategy strategy, const Block & block, const ColumnNumbers & args)
|
||||
{
|
||||
if (strategy == DIRECTLY_EXECUTE)
|
||||
return {};
|
||||
else if (strategy == RETURN_NULL)
|
||||
return {};
|
||||
else if (strategy == PROCESS_NULLABLE_COLUMNS)
|
||||
{
|
||||
/// Run the function on a block whose nullable columns have been replaced
|
||||
/// with their respective nested columns.
|
||||
return createBlockWithNestedColumns(block, args);
|
||||
}
|
||||
else
|
||||
throw Exception{"IFunction: internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
}
|
||||
|
||||
void IFunction::postProcessResult(Strategy strategy, Block & block, const Block & processed_block,
|
||||
const ColumnNumbers & args, size_t result)
|
||||
{
|
||||
if (strategy == DIRECTLY_EXECUTE)
|
||||
{
|
||||
}
|
||||
else if (strategy == RETURN_NULL)
|
||||
{
|
||||
/// We have found at least one NULL argument. Therefore we return NULL.
|
||||
ColumnWithTypeAndName & dest_col = block.getByPosition(result);
|
||||
dest_col.column = std::make_shared<ColumnNull>(block.rowsInFirstColumn(), Null());
|
||||
}
|
||||
else if (strategy == PROCESS_NULLABLE_COLUMNS)
|
||||
{
|
||||
/// Initialize the result column.
|
||||
const ColumnWithTypeAndName & source_col = processed_block.getByPosition(result);
|
||||
ColumnWithTypeAndName & dest_col = block.getByPosition(result);
|
||||
dest_col.column = std::make_shared<ColumnNullable>(source_col.column);
|
||||
|
||||
/// Make a null map for the result.
|
||||
ColumnNullable & nullable_col = static_cast<ColumnNullable &>(*dest_col.column);
|
||||
nullable_col.getNullValuesByteMap() = std::make_shared<ColumnUInt8>(dest_col.column->size(), 0);
|
||||
createNullValuesByteMap(block, args, result);
|
||||
}
|
||||
else
|
||||
throw Exception{"IFunction: internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
}
|
||||
|
||||
/// Return a copy of a given block in which the specified columns are replaced by
|
||||
/// their respective nested columns if they are nullable.
|
||||
Block IFunction::extractNonNullableBlock(const Block & block, ColumnNumbers args)
|
||||
Block IFunction::createBlockWithNestedColumns(const Block & block, ColumnNumbers args)
|
||||
{
|
||||
std::sort(args.begin(), args.end());
|
||||
|
||||
Block non_nullable_block;
|
||||
Block res;
|
||||
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < block.columns(); ++i)
|
||||
{
|
||||
const auto & col = block.unsafeGetByPosition(i);
|
||||
|
||||
bool found = std::binary_search(args.begin(), args.end(), i) && col.column && col.type;
|
||||
bool found = (i == args[j]);
|
||||
//bool found = std::binary_search(args.begin(), args.end(), i);
|
||||
|
||||
if (found && col.column->isNullable())
|
||||
{
|
||||
@ -225,65 +370,13 @@ Block IFunction::extractNonNullableBlock(const Block & block, ColumnNumbers args
|
||||
auto nullable_type = static_cast<const DataTypeNullable *>(col.type.get());
|
||||
DataTypePtr nested_type = nullable_type->getNestedType();
|
||||
|
||||
non_nullable_block.insert(i, {nested_col, nested_type, col.name});
|
||||
res.insert(i, {nested_col, nested_type, col.name});
|
||||
}
|
||||
else
|
||||
non_nullable_block.insert(i, col);
|
||||
res.insert(i, col);
|
||||
}
|
||||
|
||||
return non_nullable_block;
|
||||
}
|
||||
|
||||
template <typename Fun>
|
||||
void IFunction::perform(Block & block, const ColumnNumbers & arguments, size_t result, const Fun & performer)
|
||||
{
|
||||
if (!hasSpecialSupportForNulls() && blockHasNullColumns(block, arguments))
|
||||
{
|
||||
/// We have found at least one NULL argument. Therefore we return NULL.
|
||||
ColumnWithTypeAndName & dest_col = block.getByPosition(result);
|
||||
dest_col.column = std::make_shared<ColumnNull>(block.rowsInFirstColumn(), Null());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasSpecialSupportForNulls() && blockHasNullableColumns(block, arguments))
|
||||
{
|
||||
/// Run the function on a block whose nullable columns have been replaced
|
||||
/// with their respective nested columns.
|
||||
Block non_nullable_block = extractNonNullableBlock(block, arguments);
|
||||
performer(non_nullable_block, arguments, result);
|
||||
|
||||
/// Initialize the result column.
|
||||
const ColumnWithTypeAndName & source_col = non_nullable_block.getByPosition(result);
|
||||
ColumnWithTypeAndName & dest_col = block.getByPosition(result);
|
||||
dest_col.column = std::make_shared<ColumnNullable>(source_col.column);
|
||||
|
||||
/// Make a null map for the result.
|
||||
ColumnNullable & nullable_col = static_cast<ColumnNullable &>(*dest_col.column);
|
||||
nullable_col.getNullValuesByteMap() = std::make_shared<ColumnUInt8>(dest_col.column->size(), 0);
|
||||
createNullValuesByteMap(block, arguments, result);
|
||||
}
|
||||
else
|
||||
performer(block, arguments, result);
|
||||
}
|
||||
|
||||
void IFunction::execute(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
auto performer = [&](Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
executeImpl(block, arguments, result);
|
||||
};
|
||||
|
||||
perform(block, arguments, result, performer);
|
||||
}
|
||||
|
||||
void IFunction::execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & prerequisites, size_t result)
|
||||
{
|
||||
auto performer = [&](Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
executeImpl(block, arguments, prerequisites, result);
|
||||
};
|
||||
|
||||
perform(block, arguments, result, performer);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ Block LogBlockInputStream::readImpl()
|
||||
bool read_offsets = true;
|
||||
|
||||
const IDataType * observed_type;
|
||||
if (column.type.get()->isNullable())
|
||||
if (column.type->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*column.type);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
|
@ -3414,7 +3414,7 @@ void StorageReplicatedMergeTree::reshardPartitions(ASTPtr query, const String &
|
||||
block_number = resharding_worker.subscribe(coordinator_id, queryToString(query));
|
||||
|
||||
NameAndTypePair column_desc = ITableDeclaration::getColumn(sharding_key_expr->getColumnName());
|
||||
if (column_desc.type.get()->isNullable())
|
||||
if (column_desc.type->isNullable())
|
||||
throw Exception{"Sharding key must not be nullable", ErrorCodes::RESHARDING_NULLABLE_SHARDING_KEY};
|
||||
|
||||
for (const auto & weighted_path : weighted_zookeeper_paths)
|
||||
|
@ -202,7 +202,7 @@ Block TinyLogBlockInputStream::readImpl()
|
||||
bool read_offsets = true;
|
||||
|
||||
const IDataType * observed_type;
|
||||
if (column.type.get()->isNullable())
|
||||
if (column.type->isNullable())
|
||||
{
|
||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*column.type);
|
||||
observed_type = nullable_type.getNestedType().get();
|
||||
|
Loading…
Reference in New Issue
Block a user