ClickHouse
120 строк · 4.2 Кб
1#include <Columns/ColumnLowCardinality.h>2#include <Columns/ColumnNullable.h>3#include <Columns/ColumnVariant.h>4#include <Core/ColumnNumbers.h>5#include <DataTypes/DataTypesNumber.h>6#include <Functions/FunctionFactory.h>7#include <Functions/FunctionHelpers.h>8#include <Functions/IFunction.h>9#include <Functions/PerformanceAdaptors.h>10#include <Common/assert_cast.h>11
12namespace DB13{
14namespace
15{
16
17/// Implements the function isNotNull which returns true if a value
18/// is not null, false otherwise.
19class FunctionIsNotNull : public IFunction20{
21public:22static constexpr auto name = "isNotNull";23
24static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIsNotNull>(); }25
26std::string getName() const override27{28return name;29}30
31size_t getNumberOfArguments() const override { return 1; }32bool useDefaultImplementationForNulls() const override { return false; }33bool useDefaultImplementationForConstants() const override { return true; }34bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }35bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }36ColumnNumbers getArgumentsThatDontImplyNullableReturnType(size_t /*number_of_arguments*/) const override { return {0}; }37
38DataTypePtr getReturnTypeImpl(const DataTypes &) const override39{40return std::make_shared<DataTypeUInt8>();41}42
43ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override44{45const ColumnWithTypeAndName & elem = arguments[0];46
47if (isVariant(elem.type))48{49const auto & discriminators = checkAndGetColumn<ColumnVariant>(*elem.column)->getLocalDiscriminators();50auto res = DataTypeUInt8().createColumn();51auto & data = typeid_cast<ColumnUInt8 &>(*res).getData();52data.resize(discriminators.size());53for (size_t i = 0; i < discriminators.size(); ++i)54data[i] = discriminators[i] != ColumnVariant::NULL_DISCRIMINATOR;55return res;56}57
58if (elem.type->isLowCardinalityNullable())59{60const auto * low_cardinality_column = checkAndGetColumn<ColumnLowCardinality>(*elem.column);61const size_t null_index = low_cardinality_column->getDictionary().getNullValueIndex();62auto res = DataTypeUInt8().createColumn();63auto & data = typeid_cast<ColumnUInt8 &>(*res).getData();64data.resize(low_cardinality_column->size());65for (size_t i = 0; i != low_cardinality_column->size(); ++i)66data[i] = (low_cardinality_column->getIndexAt(i) != null_index);67return res;68}69
70if (const auto * nullable = checkAndGetColumn<ColumnNullable>(*elem.column))71{72/// Return the negated null map.73auto res_column = ColumnUInt8::create(input_rows_count);74const auto & src_data = nullable->getNullMapData();75auto & res_data = assert_cast<ColumnUInt8 &>(*res_column).getData();76vector(src_data, res_data);77return res_column;78}79else80{81/// Since no element is nullable, return a constant one.82return DataTypeUInt8().createColumnConst(elem.column->size(), 1u);83}84}85
86private:87MULTITARGET_FUNCTION_AVX2_SSE42(88MULTITARGET_FUNCTION_HEADER(static void NO_INLINE), vectorImpl, MULTITARGET_FUNCTION_BODY((const PaddedPODArray<UInt8> & null_map, PaddedPODArray<UInt8> & res) /// NOLINT89{90size_t size = null_map.size();91for (size_t i = 0; i < size; ++i)92res[i] = !null_map[i];93}))94
95static void NO_INLINE vector(const PaddedPODArray<UInt8> & null_map, PaddedPODArray<UInt8> & res)96{97#if USE_MULTITARGET_CODE98if (isArchSupported(TargetArch::AVX2))99{100vectorImplAVX2(null_map, res);101return;102}103
104if (isArchSupported(TargetArch::SSE42))105{106vectorImplSSE42(null_map, res);107return;108}109#endif110vectorImpl(null_map, res);111}112};113}
114
115REGISTER_FUNCTION(IsNotNull)116{
117factory.registerFunction<FunctionIsNotNull>();118}
119
120}
121