Coverage Report

Created: 2026-03-16 19:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/array/function_array_count.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "core/column/column_array.h"
19
#include "core/column/column_nullable.h"
20
#include "core/data_type/data_type_array.h"
21
#include "core/data_type/data_type_number.h"
22
#include "exprs/function/function.h"
23
#include "exprs/function/function_helpers.h"
24
#include "exprs/function/simple_function_factory.h"
25
26
namespace doris {
27
28
// array_count([0, 1, 1, 1, 0, 0]) -> [3]
29
class FunctionArrayCount : public IFunction {
30
public:
31
    static constexpr auto name = "array_count";
32
33
2
    static FunctionPtr create() { return std::make_shared<FunctionArrayCount>(); }
34
35
1
    String get_name() const override { return name; }
36
37
1
    bool is_variadic() const override { return false; }
38
39
0
    size_t get_number_of_arguments() const override { return 1; }
40
41
0
    bool use_default_implementation_for_nulls() const override { return false; }
42
43
0
    ColumnNumbers get_arguments_that_are_always_constant() const override { return {1}; }
44
45
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
46
0
        return std::make_shared<DataTypeInt64>();
47
0
    }
48
49
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
50
0
                        uint32_t result, size_t input_rows_count) const override {
51
0
        const auto& [src_column, src_const] =
52
0
                unpack_if_const(block.get_by_position(arguments[0]).column);
53
0
        const ColumnArray* array_column = nullptr;
54
0
        const UInt8* array_null_map = nullptr;
55
0
        if (src_column->is_nullable()) {
56
0
            auto nullable_array = assert_cast<const ColumnNullable*>(src_column.get());
57
0
            array_column = assert_cast<const ColumnArray*>(&nullable_array->get_nested_column());
58
0
            array_null_map = nullable_array->get_null_map_column().get_data().data();
59
0
        } else {
60
0
            array_column = assert_cast<const ColumnArray*>(src_column.get());
61
0
        }
62
63
0
        if (!array_column) {
64
0
            return Status::RuntimeError("unsupported types for function {}({})", get_name(),
65
0
                                        block.get_by_position(arguments[0]).type->get_name());
66
0
        }
67
68
0
        const auto& offsets = array_column->get_offsets();
69
0
        ColumnPtr nested_column = nullptr;
70
0
        const UInt8* nested_null_map = nullptr;
71
0
        if (array_column->get_data().is_nullable()) {
72
0
            const auto& nested_null_column =
73
0
                    assert_cast<const ColumnNullable&>(array_column->get_data());
74
0
            nested_null_map = nested_null_column.get_null_map_column().get_data().data();
75
0
            nested_column = nested_null_column.get_nested_column_ptr();
76
0
        } else {
77
0
            nested_column = array_column->get_data_ptr();
78
0
        }
79
80
0
        const auto& nested_data = assert_cast<const ColumnUInt8&>(*nested_column).get_data();
81
82
0
        auto dst_column = ColumnInt64::create(offsets.size());
83
0
        auto& dst_data = dst_column->get_data();
84
85
0
        for (size_t row = 0; row < offsets.size(); ++row) {
86
0
            Int64 res = 0;
87
0
            if (array_null_map && array_null_map[row]) {
88
0
                dst_data[row] = res;
89
0
                continue;
90
0
            }
91
0
            size_t off = offsets[row - 1];
92
0
            size_t len = offsets[row] - off;
93
0
            for (size_t pos = 0; pos < len; ++pos) {
94
0
                if (nested_null_map && nested_null_map[pos + off]) {
95
0
                    continue;
96
0
                }
97
0
                if (nested_data[pos + off] != 0) {
98
0
                    ++res;
99
0
                }
100
0
            }
101
0
            dst_data[row] = res;
102
0
        }
103
104
0
        block.replace_by_position(result, std::move(dst_column));
105
0
        return Status::OK();
106
0
    }
107
};
108
109
1
void register_function_array_count(SimpleFunctionFactory& factory) {
110
1
    factory.register_function<FunctionArrayCount>();
111
1
}
112
} // namespace doris