Coverage Report

Created: 2026-07-07 13:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/function_multi_match.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 "exprs/function/function_multi_match.h"
19
20
#include <glog/logging.h>
21
22
#include <memory>
23
#include <roaring/roaring.hh>
24
#include <string>
25
#include <vector>
26
27
#include "core/column/column.h"
28
#include "core/field.h"
29
#include "exprs/function/simple_function_factory.h"
30
#include "exprs/vslot_ref.h"
31
#include "io/fs/file_reader.h"
32
#include "storage/index/inverted/query/phrase_prefix_query.h"
33
#include "storage/segment/segment_iterator.h"
34
35
namespace doris {
36
37
Status FunctionMultiMatch::execute_impl(FunctionContext* /*context*/, Block& block,
38
                                        const ColumnNumbers& arguments, uint32_t result,
39
0
                                        size_t /*input_rows_count*/) const {
40
0
    return Status::RuntimeError("only inverted index queries are supported");
41
0
}
42
43
1
InvertedIndexQueryType get_query_type(const std::string& query_type) {
44
1
    if (query_type == "any") {
45
0
        return InvertedIndexQueryType::MATCH_ANY_QUERY;
46
1
    } else if (query_type == "all") {
47
0
        return InvertedIndexQueryType::MATCH_ALL_QUERY;
48
1
    } else if (query_type == "phrase") {
49
1
        return InvertedIndexQueryType::MATCH_PHRASE_QUERY;
50
1
    } else if (query_type == "phrase_prefix") {
51
0
        return InvertedIndexQueryType::MATCH_PHRASE_PREFIX_QUERY;
52
0
    } else {
53
0
        return InvertedIndexQueryType::UNKNOWN_QUERY;
54
0
    }
55
1
}
56
57
Status FunctionMultiMatch::evaluate_inverted_index(
58
        const ColumnsWithTypeAndName& arguments,
59
        const std::vector<IndexFieldNameAndTypePair>& data_type_with_names,
60
        std::vector<segment_v2::IndexIterator*> iterators, uint32_t num_rows,
61
        const InvertedIndexAnalyzerCtx* analyzer_ctx,
62
1
        segment_v2::InvertedIndexResultBitmap& bitmap_result) const {
63
1
    DCHECK(arguments.size() == 2);
64
1
    std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
65
1
    std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
66
67
    // type
68
1
    Field query_type_value;
69
1
    arguments[0].column->get(0, query_type_value);
70
1
    if (query_type_value.is_null()) {
71
0
        return Status::RuntimeError("query_type can not be NULL");
72
0
    }
73
1
    auto query_type = get_query_type(query_type_value.get<TYPE_STRING>());
74
1
    if (query_type == InvertedIndexQueryType::UNKNOWN_QUERY) {
75
0
        return Status::RuntimeError(
76
0
                "parameter query type incorrect for function multi_match: query_type = {}",
77
0
                query_type);
78
0
    }
79
80
    // query
81
1
    Field query_str_value;
82
1
    arguments[1].column->get(0, query_str_value);
83
1
    if (query_str_value.is_null()) {
84
0
        bitmap_result = segment_v2::InvertedIndexResultBitmap(roaring, null_bitmap);
85
0
        return Status::OK();
86
0
    }
87
1
    auto param_type = arguments[1].type->get_primitive_type();
88
1
    if (!is_string_type(param_type)) {
89
0
        return Status::Error<ErrorCode::INDEX_INVALID_PARAMETERS>(
90
0
                "arguments for multi_match must be string");
91
0
    }
92
    // search
93
1
    InvertedIndexParam param;
94
1
    param.query_value = query_str_value;
95
1
    param.query_type = query_type;
96
1
    param.num_rows = num_rows;
97
1
    for (size_t i = 0; i < data_type_with_names.size(); i++) {
98
1
        auto column_name = data_type_with_names[i].first;
99
1
        auto* iter = iterators[i];
100
1
        if (iter == nullptr) {
101
1
            std::string error_msg = "Inverted index iterator is null for column '" + column_name +
102
1
                                    "' during multi_match execution";
103
1
            return Status::Error<ErrorCode::INVERTED_INDEX_CLUCENE_ERROR>(error_msg);
104
1
        }
105
106
0
        param.column_name = column_name;
107
0
        param.column_type = data_type_with_names[i].second;
108
0
        param.roaring = std::make_shared<roaring::Roaring>();
109
0
        param.analyzer_ctx = analyzer_ctx;
110
0
        RETURN_IF_ERROR(iter->read_from_index(segment_v2::IndexParam {&param}));
111
0
        *roaring |= *param.roaring;
112
0
    }
113
0
    segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
114
0
    bitmap_result = result;
115
116
0
    return Status::OK();
117
1
}
118
119
1
void register_function_multi_match(SimpleFunctionFactory& factory) {
120
1
    factory.register_function<FunctionMultiMatch>();
121
1
}
122
123
} // namespace doris