Coverage Report

Created: 2026-05-14 17:56

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
    auto query_type_value = arguments[0].column->get_data_at(0);
69
1
    auto query_type = get_query_type(query_type_value.to_string());
70
1
    if (query_type == InvertedIndexQueryType::UNKNOWN_QUERY) {
71
0
        return Status::RuntimeError(
72
0
                "parameter query type incorrect for function multi_match: query_type = {}",
73
0
                query_type);
74
0
    }
75
76
    // query
77
1
    auto query_str_ref = arguments[1].column->get_data_at(0);
78
1
    auto param_type = arguments[1].type->get_primitive_type();
79
1
    if (!is_string_type(param_type)) {
80
0
        return Status::Error<ErrorCode::INDEX_INVALID_PARAMETERS>(
81
0
                "arguments for multi_match must be string");
82
0
    }
83
    // search
84
1
    InvertedIndexParam param;
85
1
    param.query_value = Field::create_field<TYPE_STRING>(query_str_ref.to_string());
86
1
    param.query_type = query_type;
87
1
    param.num_rows = num_rows;
88
1
    for (size_t i = 0; i < data_type_with_names.size(); i++) {
89
1
        auto column_name = data_type_with_names[i].first;
90
1
        auto* iter = iterators[i];
91
1
        if (iter == nullptr) {
92
1
            std::string error_msg = "Inverted index iterator is null for column '" + column_name +
93
1
                                    "' during multi_match execution";
94
1
            return Status::Error<ErrorCode::INVERTED_INDEX_CLUCENE_ERROR>(error_msg);
95
1
        }
96
97
0
        param.column_name = column_name;
98
0
        param.column_type = data_type_with_names[i].second;
99
0
        param.roaring = std::make_shared<roaring::Roaring>();
100
0
        param.analyzer_ctx = analyzer_ctx;
101
0
        RETURN_IF_ERROR(iter->read_from_index(segment_v2::IndexParam {&param}));
102
0
        *roaring |= *param.roaring;
103
0
    }
104
0
    segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
105
0
    bitmap_result = result;
106
107
0
    return Status::OK();
108
1
}
109
110
1
void register_function_multi_match(SimpleFunctionFactory& factory) {
111
1
    factory.register_function<FunctionMultiMatch>();
112
1
}
113
114
} // namespace doris