mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-17 13:13:36 +00:00
Remove unneeded branches of code
This commit is contained in:
parent
15ea9b3f22
commit
ce1b9b20d5
@ -13,11 +13,7 @@ public:
|
||||
static constexpr auto name = "arrayFold";
|
||||
static FunctionPtr create(const Context &) { return std::make_shared<FunctionArrayFold>(); }
|
||||
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
String getName() const override { return name; }
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
@ -56,176 +52,134 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
size_t min_args = 2;
|
||||
if (arguments.size() < min_args)
|
||||
throw Exception("Function " + getName() + " needs at least "
|
||||
+ toString(min_args) + " argument; passed "
|
||||
if (arguments.size() < 2)
|
||||
throw Exception("Function " + getName() + " needs at least 2 arguments; passed "
|
||||
+ toString(arguments.size()) + ".",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
if (arguments.size() == 1)
|
||||
{
|
||||
const auto * array_type = checkAndGetDataType<DataTypeArray>(arguments[0].type.get());
|
||||
if (!array_type)
|
||||
throw Exception("The only argument for function " + getName() + " must be array. Found "
|
||||
+ arguments[0].type->getName() + " instead.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
return array_type->getNestedType();
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto * data_type_function = checkAndGetDataType<DataTypeFunction>(arguments[0].type.get());
|
||||
|
||||
if (!data_type_function)
|
||||
throw Exception("First argument for function " + getName() + " must be a function.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
/// The types of the remaining arguments are already checked in getLambdaArgumentTypes.
|
||||
DataTypePtr return_type = removeLowCardinality(data_type_function->getReturnType());
|
||||
const auto accum_type = arguments.back().type;
|
||||
return accum_type;
|
||||
}
|
||||
const auto * data_type_function = checkAndGetDataType<DataTypeFunction>(arguments[0].type.get());
|
||||
if (!data_type_function)
|
||||
throw Exception("First argument for function " + getName() + " must be a function.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
/// The types of the remaining arguments are already checked in getLambdaArgumentTypes.
|
||||
DataTypePtr return_type = removeLowCardinality(data_type_function->getReturnType());
|
||||
const auto accum_type = arguments.back().type;
|
||||
return accum_type;
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
if (arguments.size() == 1)
|
||||
const auto & column_with_type_and_name = arguments[0];
|
||||
|
||||
if (!column_with_type_and_name.column)
|
||||
throw Exception("First argument for function " + getName() + " must be a function.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
const auto * column_function = typeid_cast<const ColumnFunction *>(column_with_type_and_name.column.get());
|
||||
|
||||
if (!column_function)
|
||||
throw Exception("First argument for function " + getName() + " must be a function.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
ColumnPtr offsets_column;
|
||||
ColumnPtr column_first_array_ptr;
|
||||
const ColumnArray * column_first_array = nullptr;
|
||||
ColumnsWithTypeAndName arrays;
|
||||
arrays.reserve(arguments.size() - 1);
|
||||
|
||||
for (size_t i = 1; i < arguments.size() - 1; ++i)
|
||||
{
|
||||
ColumnPtr column_array_ptr = arguments[0].column;
|
||||
const auto & array_with_type_and_name = arguments[i];
|
||||
ColumnPtr column_array_ptr = array_with_type_and_name.column;
|
||||
const auto * column_array = checkAndGetColumn<ColumnArray>(column_array_ptr.get());
|
||||
const DataTypePtr & array_type_ptr = array_with_type_and_name.type;
|
||||
const auto * array_type = checkAndGetDataType<DataTypeArray>(array_type_ptr.get());
|
||||
if (!column_array)
|
||||
{
|
||||
const ColumnConst * column_const_array = checkAndGetColumnConst<ColumnArray>(column_array_ptr.get());
|
||||
if (!column_const_array)
|
||||
throw Exception("Expected array column, found " + column_array_ptr->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
column_array_ptr = column_const_array->convertToFullColumn();
|
||||
column_array = assert_cast<const ColumnArray *>(column_array_ptr.get());
|
||||
column_array_ptr = recursiveRemoveLowCardinality(column_const_array->convertToFullColumn());
|
||||
column_array = checkAndGetColumn<ColumnArray>(column_array_ptr.get());
|
||||
}
|
||||
auto res = column_array->getDataPtr();
|
||||
return res->empty() ? res : res->cut(0, 1); // TODO recheck
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto & column_with_type_and_name = arguments[0];
|
||||
|
||||
if (!column_with_type_and_name.column)
|
||||
throw Exception("First argument for function " + getName() + " must be a function.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
const auto * column_function = typeid_cast<const ColumnFunction *>(column_with_type_and_name.column.get());
|
||||
|
||||
if (!column_function)
|
||||
throw Exception("First argument for function " + getName() + " must be a function.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
ColumnPtr offsets_column;
|
||||
|
||||
ColumnPtr column_first_array_ptr;
|
||||
const ColumnArray * column_first_array = nullptr;
|
||||
|
||||
ColumnsWithTypeAndName arrays;
|
||||
arrays.reserve(arguments.size() - 1);
|
||||
|
||||
for (size_t i = 1; i < arguments.size() - 1; ++i)
|
||||
if (!array_type)
|
||||
throw Exception("Expected array type, found " + array_type_ptr->getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
if (!offsets_column)
|
||||
{
|
||||
const auto & array_with_type_and_name = arguments[i];
|
||||
|
||||
ColumnPtr column_array_ptr = array_with_type_and_name.column;
|
||||
const auto * column_array = checkAndGetColumn<ColumnArray>(column_array_ptr.get());
|
||||
|
||||
const DataTypePtr & array_type_ptr = array_with_type_and_name.type;
|
||||
const auto * array_type = checkAndGetDataType<DataTypeArray>(array_type_ptr.get());
|
||||
|
||||
if (!column_array)
|
||||
{
|
||||
const ColumnConst * column_const_array = checkAndGetColumnConst<ColumnArray>(column_array_ptr.get());
|
||||
if (!column_const_array)
|
||||
throw Exception("Expected array column, found " + column_array_ptr->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
column_array_ptr = recursiveRemoveLowCardinality(column_const_array->convertToFullColumn());
|
||||
column_array = checkAndGetColumn<ColumnArray>(column_array_ptr.get());
|
||||
}
|
||||
|
||||
if (!array_type)
|
||||
throw Exception("Expected array type, found " + array_type_ptr->getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
if (!offsets_column)
|
||||
{
|
||||
offsets_column = column_array->getOffsetsPtr();
|
||||
}
|
||||
else
|
||||
{
|
||||
/// The first condition is optimization: do not compare data if the pointers are equal.
|
||||
if (column_array->getOffsetsPtr() != offsets_column
|
||||
&& column_array->getOffsets() != typeid_cast<const ColumnArray::ColumnOffsets &>(*offsets_column).getData())
|
||||
throw Exception("Arrays passed to " + getName() + " must have equal size", ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH);
|
||||
}
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
column_first_array_ptr = column_array_ptr;
|
||||
column_first_array = column_array;
|
||||
}
|
||||
|
||||
arrays.emplace_back(ColumnWithTypeAndName(column_array->getDataPtr(),
|
||||
recursiveRemoveLowCardinality(array_type->getNestedType()),
|
||||
array_with_type_and_name.name));
|
||||
}
|
||||
arrays.emplace_back(arguments.back());
|
||||
|
||||
if (! column_first_array->getData().empty())
|
||||
{
|
||||
size_t arr_cursor = 0;
|
||||
MutableColumnPtr result = arguments.back().column->convertToFullColumnIfConst()->cloneEmpty();
|
||||
for (size_t irow = 0; irow < column_first_array->size(); ++irow) // for each row of result
|
||||
{
|
||||
// Make accumulator column for this row
|
||||
ColumnWithTypeAndName accumulator_column = arguments.back();
|
||||
ColumnPtr acc(accumulator_column.column->cut(irow, 1));
|
||||
auto accumulator = ColumnWithTypeAndName(acc,
|
||||
accumulator_column.type,
|
||||
accumulator_column.name);
|
||||
|
||||
ColumnPtr res(acc);
|
||||
size_t const arr_next = column_first_array->getOffsets()[irow]; // when we do folding
|
||||
for (size_t iter = 0; arr_cursor < arr_next; ++iter, ++arr_cursor)
|
||||
{
|
||||
// Make slice of input arrays and accumulator for lambda
|
||||
ColumnsWithTypeAndName iter_arrays;
|
||||
iter_arrays.reserve(arrays.size() + 1);
|
||||
for (size_t icolumn = 0; icolumn < arrays.size() - 1; ++icolumn)
|
||||
{
|
||||
auto const & arr = arrays[icolumn];
|
||||
iter_arrays.emplace_back(ColumnWithTypeAndName(arr.column->cut(arr_cursor, 1),
|
||||
arr.type,
|
||||
arr.name));
|
||||
}
|
||||
iter_arrays.emplace_back(accumulator);
|
||||
// Calculate function on arguments
|
||||
auto replicated_column_function_ptr = IColumn::mutate(column_function->replicate(ColumnArray::Offsets(column_first_array->getOffsets().size(), 1)));
|
||||
auto * replicated_column_function = typeid_cast<ColumnFunction *>(replicated_column_function_ptr.get());
|
||||
replicated_column_function->appendArguments(iter_arrays);
|
||||
auto lambda_result = replicated_column_function->reduce().column;
|
||||
if (lambda_result->lowCardinality())
|
||||
lambda_result = lambda_result->convertToFullColumnIfLowCardinality();
|
||||
res = lambda_result->empty() ? lambda_result : lambda_result->cut(0, 1); // TODO recheck this
|
||||
accumulator.column = res;
|
||||
}
|
||||
result->insert((*res)[0]);
|
||||
}
|
||||
return result;
|
||||
offsets_column = column_array->getOffsetsPtr();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: for what this branch is needed?
|
||||
// empty function
|
||||
//
|
||||
/// Put all the necessary columns multiplied by the sizes of arrays into the columns.
|
||||
auto replicated_column_function_ptr = IColumn::mutate(column_function->replicate(column_first_array->getOffsets()));
|
||||
auto * replicated_column_function = typeid_cast<ColumnFunction *>(replicated_column_function_ptr.get());
|
||||
replicated_column_function->appendArguments(arrays);
|
||||
auto lambda_result = replicated_column_function->reduce().column;
|
||||
if (lambda_result->lowCardinality())
|
||||
lambda_result = lambda_result->convertToFullColumnIfLowCardinality();
|
||||
return lambda_result->empty() ? lambda_result : lambda_result->cut(0, 1); // TODO recheck this
|
||||
/// The first condition is optimization: do not compare data if the pointers are equal.
|
||||
if (column_array->getOffsetsPtr() != offsets_column
|
||||
&& column_array->getOffsets() != typeid_cast<const ColumnArray::ColumnOffsets &>(*offsets_column).getData())
|
||||
throw Exception("Arrays passed to " + getName() + " must have equal size", ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH);
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
column_first_array_ptr = column_array_ptr;
|
||||
column_first_array = column_array;
|
||||
}
|
||||
arrays.emplace_back(ColumnWithTypeAndName(column_array->getDataPtr(),
|
||||
recursiveRemoveLowCardinality(array_type->getNestedType()),
|
||||
array_with_type_and_name.name));
|
||||
}
|
||||
arrays.emplace_back(arguments.back());
|
||||
|
||||
if (! column_first_array->getData().empty())
|
||||
{
|
||||
size_t arr_cursor = 0;
|
||||
MutableColumnPtr result = arguments.back().column->convertToFullColumnIfConst()->cloneEmpty();
|
||||
for (size_t irow = 0; irow < column_first_array->size(); ++irow) // for each row of result
|
||||
{
|
||||
// Make accumulator column for this row
|
||||
ColumnWithTypeAndName accumulator_column = arguments.back();
|
||||
ColumnPtr acc(accumulator_column.column->cut(irow, 1));
|
||||
auto accumulator = ColumnWithTypeAndName(acc,
|
||||
accumulator_column.type,
|
||||
accumulator_column.name);
|
||||
ColumnPtr res(acc);
|
||||
size_t const arr_next = column_first_array->getOffsets()[irow]; // when we do folding
|
||||
for (size_t iter = 0; arr_cursor < arr_next; ++iter, ++arr_cursor)
|
||||
{
|
||||
// Make slice of input arrays and accumulator for lambda
|
||||
ColumnsWithTypeAndName iter_arrays;
|
||||
iter_arrays.reserve(arrays.size() + 1);
|
||||
for (size_t icolumn = 0; icolumn < arrays.size() - 1; ++icolumn)
|
||||
{
|
||||
auto const & arr = arrays[icolumn];
|
||||
iter_arrays.emplace_back(ColumnWithTypeAndName(arr.column->cut(arr_cursor, 1),
|
||||
arr.type,
|
||||
arr.name));
|
||||
}
|
||||
iter_arrays.emplace_back(accumulator);
|
||||
// Calculate function on arguments
|
||||
auto replicated_column_function_ptr = IColumn::mutate(column_function->replicate(ColumnArray::Offsets(column_first_array->getOffsets().size(), 1)));
|
||||
auto * replicated_column_function = typeid_cast<ColumnFunction *>(replicated_column_function_ptr.get());
|
||||
replicated_column_function->appendArguments(iter_arrays);
|
||||
auto lambda_result = replicated_column_function->reduce().column;
|
||||
if (lambda_result->lowCardinality())
|
||||
lambda_result = lambda_result->convertToFullColumnIfLowCardinality();
|
||||
res = lambda_result->empty() ? lambda_result : lambda_result->cut(0, 1); // TODO recheck this
|
||||
accumulator.column = res;
|
||||
}
|
||||
result->insert((*res)[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: for what this branch is needed?
|
||||
// empty function
|
||||
//
|
||||
/// Put all the necessary columns multiplied by the sizes of arrays into the columns.
|
||||
auto replicated_column_function_ptr = IColumn::mutate(column_function->replicate(column_first_array->getOffsets()));
|
||||
auto * replicated_column_function = typeid_cast<ColumnFunction *>(replicated_column_function_ptr.get());
|
||||
replicated_column_function->appendArguments(arrays);
|
||||
auto lambda_result = replicated_column_function->reduce().column;
|
||||
if (lambda_result->lowCardinality())
|
||||
lambda_result = lambda_result->convertToFullColumnIfLowCardinality();
|
||||
// return lambda_result->empty() ? lambda_result : lambda_result->cut(0, 1); // TODO recheck this
|
||||
return lambda_result; // TODO recheck this
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user