Supported nullable for runningDifference function. #2590

This commit is contained in:
Nikolai Kochetov 2018-07-04 18:34:47 +03:00 committed by alexey-milovidov
parent 7a06e6375b
commit 5e3c0c0238

View File

@ -33,6 +33,7 @@
#include <Storages/IStorage.h> #include <Storages/IStorage.h>
#include <Common/typeid_cast.h> #include <Common/typeid_cast.h>
#include <Storages/getStructureOfRemoteTable.h> #include <Storages/getStructureOfRemoteTable.h>
#include <DataTypes/DataTypeNullable.h>
namespace DB namespace DB
@ -1468,7 +1469,7 @@ private:
/// It is possible to track value from previous block, to calculate continuously across all blocks. Not implemented. /// It is possible to track value from previous block, to calculate continuously across all blocks. Not implemented.
template <typename Src, typename Dst> template <typename Src, typename Dst>
static void process(const PaddedPODArray<Src> & src, PaddedPODArray<Dst> & dst) static void process(const PaddedPODArray<Src> & src, PaddedPODArray<Dst> & dst, const NullMap * null_map)
{ {
size_t size = src.size(); size_t size = src.size();
dst.resize(size); dst.resize(size);
@ -1478,15 +1479,28 @@ private:
/// It is possible to SIMD optimize this loop. By no need for that in practice. /// It is possible to SIMD optimize this loop. By no need for that in practice.
dst[0] = is_first_line_zero ? 0 : src[0]; Src prev;
Src prev = src[0]; bool has_prev_value = false;
for (size_t i = 1; i < size; ++i)
for (size_t i = 0; i < size; ++i)
{
if (null_map && (*null_map)[i])
continue;
if (!has_prev_value)
{
dst[i] = is_first_line_zero ? 0 : src[i];
prev = src[i];
has_prev_value = true;
}
else
{ {
auto cur = src[i]; auto cur = src[i];
dst[i] = static_cast<Dst>(cur) - prev; dst[i] = static_cast<Dst>(cur) - prev;
prev = cur; prev = cur;
} }
} }
}
/// Result type is same as result of subtraction of argument types. /// Result type is same as result of subtraction of argument types.
template <typename SrcFieldType> template <typename SrcFieldType>
@ -1547,14 +1561,19 @@ public:
return false; return false;
} }
bool useDefaultImplementationForNulls() const override { return false; }
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{ {
DataTypePtr res; DataTypePtr res;
dispatchForSourceType(*arguments[0], [&](auto field_type_tag) dispatchForSourceType(*removeNullable(arguments[0]), [&](auto field_type_tag)
{ {
res = std::make_shared<DataTypeNumber<DstFieldType<decltype(field_type_tag)>>>(); res = std::make_shared<DataTypeNumber<DstFieldType<decltype(field_type_tag)>>>();
}); });
if (arguments[0]->isNullable())
res = makeNullable(res);
return res; return res;
} }
@ -1570,15 +1589,28 @@ public:
return; return;
} }
auto res_column = res_type->createColumn(); auto res_column = removeNullable(res_type)->createColumn();
auto * src_column = src.column.get();
ColumnPtr null_map_column = nullptr;
const NullMap * null_map = nullptr;
if (auto * nullable_column = checkAndGetColumn<ColumnNullable>(src_column))
{
src_column = &nullable_column->getNestedColumn();
null_map_column = nullable_column->getNullMapColumnPtr();
null_map = &nullable_column->getNullMapData();
}
dispatchForSourceType(*src.type, [&](auto field_type_tag) dispatchForSourceType(*removeNullable(src.type), [&](auto field_type_tag)
{ {
using SrcFieldType = decltype(field_type_tag); using SrcFieldType = decltype(field_type_tag);
process(static_cast<const ColumnVector<SrcFieldType> &>(*src.column).getData(),
static_cast<ColumnVector<DstFieldType<SrcFieldType>> &>(*res_column).getData()); process(static_cast<const ColumnVector<SrcFieldType> &>(*src_column).getData(),
static_cast<ColumnVector<DstFieldType<SrcFieldType>> &>(*res_column).getData(), null_map);
}); });
if (null_map_column)
block.getByPosition(result).column = ColumnNullable::create(std::move(res_column), null_map_column);
else
block.getByPosition(result).column = std::move(res_column); block.getByPosition(result).column = std::move(res_column);
} }
}; };