mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Fixed problem with calculating ternary logic OPs in multiple batches
This commit is contained in:
parent
b2fd151dd0
commit
f29db2ed68
@ -282,29 +282,33 @@ template <
|
||||
typename Op, template <typename, size_t> typename OperationApplierImpl, size_t N = 10>
|
||||
struct OperationApplier
|
||||
{
|
||||
template <typename Columns, typename ResultColumn>
|
||||
static void apply(Columns & in, ResultColumn & result)
|
||||
template <typename Columns, typename ResultData>
|
||||
static void apply(Columns & in, ResultData & result_data)
|
||||
{
|
||||
while (in.size() > 1)
|
||||
{
|
||||
doBatchedApply(in, result->getData());
|
||||
in.push_back(result.get());
|
||||
}
|
||||
/// TODO: Maybe reuse this code for constants (which may form precalculated result)
|
||||
doBatchedApply<false>(in, result_data);
|
||||
|
||||
while (in.size() > 0)
|
||||
doBatchedApply<true>(in, result_data);
|
||||
}
|
||||
|
||||
template <typename Columns, typename ResultData>
|
||||
template <bool carryResult, typename Columns, typename ResultData>
|
||||
static void NO_INLINE doBatchedApply(Columns & in, ResultData & result_data)
|
||||
{
|
||||
if (N > in.size())
|
||||
{
|
||||
OperationApplier<Op, OperationApplierImpl, N - 1>::doBatchedApply(in, result_data);
|
||||
OperationApplier<Op, OperationApplierImpl, N - 1>
|
||||
::template doBatchedApply<carryResult>(in, result_data);
|
||||
return;
|
||||
}
|
||||
|
||||
const OperationApplierImpl<Op, N> operationApplierImpl(in);
|
||||
size_t i = 0;
|
||||
for (auto & res : result_data)
|
||||
res = operationApplierImpl.apply(i++);
|
||||
if constexpr (carryResult)
|
||||
res = Op::apply(res, operationApplierImpl.apply(i++));
|
||||
else
|
||||
res = operationApplierImpl.apply(i++);
|
||||
|
||||
in.erase(in.end() - N, in.end());
|
||||
}
|
||||
@ -312,9 +316,9 @@ struct OperationApplier
|
||||
|
||||
template <
|
||||
typename Op, template <typename, size_t> typename OperationApplierImpl>
|
||||
struct OperationApplier<Op, OperationApplierImpl, 1>
|
||||
struct OperationApplier<Op, OperationApplierImpl, 0>
|
||||
{
|
||||
template <typename Columns, typename Result>
|
||||
template <bool, typename Columns, typename Result>
|
||||
static void NO_INLINE doBatchedApply(Columns &, Result &)
|
||||
{
|
||||
throw Exception(
|
||||
@ -350,7 +354,7 @@ static void executeForTernaryLogicImpl(ColumnRawPtrs arguments, ColumnWithTypeAn
|
||||
arguments.push_back(const_column_holder.get());
|
||||
}
|
||||
|
||||
OperationApplier<Op, AssociativeGenericApplierImpl>::apply(arguments, result_column);
|
||||
OperationApplier<Op, AssociativeGenericApplierImpl>::apply(arguments, result_column->getData());
|
||||
|
||||
result_info.column = convertFromTernaryData(result_column->getData(), result_info.type->isNullable());
|
||||
}
|
||||
@ -425,32 +429,30 @@ static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & re
|
||||
if (has_consts && Op::apply(const_val, 0) == 0 && Op::apply(const_val, 1) == 1)
|
||||
has_consts = false;
|
||||
|
||||
UInt8ColumnPtrs uint8_args;
|
||||
|
||||
auto col_res = ColumnUInt8::create();
|
||||
auto col_res = ColumnUInt8::create(input_rows_count, const_val);
|
||||
UInt8Container & vec_res = col_res->getData();
|
||||
if (has_consts)
|
||||
{
|
||||
vec_res.assign(input_rows_count, const_val);
|
||||
uint8_args.push_back(col_res.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_res.resize(input_rows_count);
|
||||
}
|
||||
|
||||
/// FastPath detection goes in here
|
||||
if (arguments.size() == (has_consts ? 1 : 2))
|
||||
{
|
||||
if (has_consts)
|
||||
FastApplierImpl<Op>::apply(*arguments[0], *col_res, col_res->getData());
|
||||
FastApplierImpl<Op>::apply(*arguments[0], *col_res, vec_res);
|
||||
else
|
||||
FastApplierImpl<Op>::apply(*arguments[0], *arguments[1], col_res->getData());
|
||||
FastApplierImpl<Op>::apply(*arguments[0], *arguments[1], vec_res);
|
||||
|
||||
result_info.column = std::move(col_res);
|
||||
return;
|
||||
}
|
||||
|
||||
UInt8ColumnPtrs uint8_args;
|
||||
if (has_consts)
|
||||
{
|
||||
/// TODO: This will FAIL (or not =) ) after correction b/c we now overwrite
|
||||
/// the result column in the first pass of OperationApplier
|
||||
// vec_res.assign(input_rows_count, const_val);
|
||||
uint8_args.push_back(col_res.get());
|
||||
}
|
||||
|
||||
/// Convert all columns to UInt8
|
||||
Columns converted_columns;
|
||||
for (const IColumn * column : arguments)
|
||||
@ -466,11 +468,17 @@ static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & re
|
||||
}
|
||||
}
|
||||
|
||||
OperationApplier<Op, AssociativeApplierImpl>::apply(uint8_args, col_res);
|
||||
OperationApplier<Op, AssociativeApplierImpl>::apply(uint8_args, col_res->getData());
|
||||
|
||||
/// TODO: The following code is obsolete and is to be removed now
|
||||
///
|
||||
/// This is possible if there is exactly one non-constant among the arguments, and it is of type UInt8.
|
||||
/// Suppose we have all constants folded into a neutral value and there is only one non-constant column.
|
||||
/// Although not all logical functions have a neutral value.
|
||||
/*
|
||||
if (uint8_args[0] != col_res.get())
|
||||
vec_res.assign(uint8_args[0]->getData());
|
||||
*/
|
||||
|
||||
result_info.column = std::move(col_res);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user