// Copyright 2023 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include #include #include #include #include #include namespace DB { struct AggregateFunctionCountData { UInt64 count = 0; }; namespace ErrorCodes { extern const int LOGICAL_ERROR; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } // namespace ErrorCodes /// Simply count number of calls. class AggregateFunctionCount final : public IAggregateFunctionDataHelper { public: String getName() const override { return "count"; } DataTypePtr getReturnType() const override { return std::make_shared(); } void add(AggregateDataPtr __restrict place, const IColumn **, size_t, Arena *) const override { ++data(place).count; } void addBatchSinglePlace( size_t start_offset, size_t batch_size, AggregateDataPtr place, const IColumn ** columns, Arena *, ssize_t if_argument_pos) const override { if (if_argument_pos >= 0) { const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); data(place).count += countBytesInFilter(flags, start_offset, batch_size); } else { data(place).count += batch_size; } } void addBatchSinglePlaceNotNull( size_t start_offset, size_t batch_size, AggregateDataPtr place, const IColumn ** columns, const UInt8 * null_map, Arena *, ssize_t if_argument_pos) const override { if (if_argument_pos >= 0) { const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); data(place).count += countBytesInFilterWithNull(flags, null_map, start_offset, batch_size); } else { data(place).count += batch_size - countBytesInFilter(null_map, start_offset, batch_size); } } void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override { data(place).count += data(rhs).count; } void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf) const override { writeVarUInt(data(place).count, buf); } void deserialize(AggregateDataPtr __restrict place, ReadBuffer & buf, Arena *) const override { readVarUInt(data(place).count, buf); } void insertResultInto(ConstAggregateDataPtr __restrict place, IColumn & to, Arena *) const override { static_cast(to).getData().push_back(data(place).count); } /// May be used for optimization. static void addDelta(AggregateDataPtr __restrict place, UInt64 x) { data(place).count += x; } const char * getHeaderFilePath() const override { return __FILE__; } }; /// Simply count number of not-NULL values. class AggregateFunctionCountNotNullUnary final : public IAggregateFunctionDataHelper { public: explicit AggregateFunctionCountNotNullUnary(const DataTypePtr & argument) { if (!argument->isNullable()) throw Exception( "Logical error: not Nullable data type passed to AggregateFunctionCountNotNullUnary", ErrorCodes::LOGICAL_ERROR); } void addBatchSinglePlace( size_t start_offset, size_t batch_size, AggregateDataPtr place, const IColumn ** columns, Arena * arena, ssize_t if_argument_pos) const override { const auto & nc = assert_cast(*columns[0]); const UInt8 * null_map = nc.getNullMapData().data(); addBatchSinglePlaceNotNull(start_offset, batch_size, place, columns, null_map, arena, if_argument_pos); } void addBatchSinglePlaceNotNull( size_t start_offset, size_t batch_size, AggregateDataPtr place, const IColumn ** columns, const UInt8 * null_map, Arena *, ssize_t if_argument_pos) const override { if (if_argument_pos >= 0) { const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); data(place).count += countBytesInFilterWithNull(flags, null_map, start_offset, batch_size); } else { data(place).count += batch_size - countBytesInFilter(null_map, start_offset, batch_size); } } String getName() const override { return "count"; } DataTypePtr getReturnType() const override { return std::make_shared(); } void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override { data(place).count += !static_cast(*columns[0]).isNullAt(row_num); } void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override { data(place).count += data(rhs).count; } void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf) const override { writeVarUInt(data(place).count, buf); } void deserialize(AggregateDataPtr __restrict place, ReadBuffer & buf, Arena *) const override { readVarUInt(data(place).count, buf); } void insertResultInto(ConstAggregateDataPtr __restrict place, IColumn & to, Arena *) const override { static_cast(to).getData().push_back(data(place).count); } const char * getHeaderFilePath() const override { return __FILE__; } }; /// Count number of calls where all arguments are not NULL. class AggregateFunctionCountNotNullVariadic final : public IAggregateFunctionDataHelper { public: explicit AggregateFunctionCountNotNullVariadic(const DataTypes & arguments) { number_of_arguments = arguments.size(); if (number_of_arguments == 1) throw Exception( "Logical error: single argument is passed to AggregateFunctionCountNotNullVariadic", ErrorCodes::LOGICAL_ERROR); if (number_of_arguments > MAX_ARGS) throw Exception( "Maximum number of arguments for aggregate function with Nullable types is " + toString(static_cast(MAX_ARGS)), ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); for (size_t i = 0; i < number_of_arguments; ++i) is_nullable[i] = arguments[i]->isNullable(); } String getName() const override { return "count"; } DataTypePtr getReturnType() const override { return std::make_shared(); } void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override { for (size_t i = 0; i < number_of_arguments; ++i) if (is_nullable[i] && static_cast(*columns[i]).isNullAt(row_num)) return; ++data(place).count; } void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override { data(place).count += data(rhs).count; } void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf) const override { writeVarUInt(data(place).count, buf); } void deserialize(AggregateDataPtr __restrict place, ReadBuffer & buf, Arena *) const override { readVarUInt(data(place).count, buf); } void insertResultInto(ConstAggregateDataPtr __restrict place, IColumn & to, Arena *) const override { static_cast(to).getData().push_back(data(place).count); } const char * getHeaderFilePath() const override { return __FILE__; } private: enum { MAX_ARGS = 8 }; size_t number_of_arguments = 0; std::array is_nullable{}; /// Plain array is better than std::vector due to one indirection less. }; } // namespace DB