Coverage Report

Created: 2026-09-28 17:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/index/inverted/token_stream.h
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
#pragma once
19
20
#include <unicode/utext.h>
21
#include <unicode/utf8.h>
22
23
#include <algorithm>
24
#include <cstddef>
25
#include <memory>
26
#include <span>
27
#include <string_view>
28
#include <utility>
29
30
#include "CLucene.h"
31
#include "CLucene/analysis/AnalysisHeader.h"
32
#include "common/cast_set.h"
33
#include "storage/index/inverted/util/reader.h"
34
35
using namespace lucene::analysis;
36
37
namespace doris::segment_v2::inverted_index {
38
39
class DorisTokenizer;
40
using TokenizerPtr = std::shared_ptr<DorisTokenizer>;
41
42
using TokenStreamPtr = std::shared_ptr<TokenStream>;
43
44
// Reused analyzers keep ordinary scratch across values; one oversized value must not pin its
45
// capacity for the rest of the writer lifetime.
46
constexpr size_t ANALYZER_SCRATCH_HIGH_WATER_BYTES = 64 * 1024;
47
48
// Longest prefix of text that fits in max_bytes without splitting a rune, and its rune count.
49
98.7k
inline std::pair<size_t, size_t> utf8_prefix_at_most(std::string_view text, size_t max_bytes) {
50
98.7k
    const auto length = static_cast<int32_t>(text.size());
51
98.7k
    const auto limit = static_cast<int32_t>(std::min(text.size(), max_bytes));
52
98.7k
    int32_t offset = 0;
53
98.7k
    size_t rune_count = 0;
54
199k
    while (offset < length) {
55
100k
        int32_t next = offset;
56
100k
        U8_FWD_1(text, next, length);
57
100k
        if (next > limit) {
58
4
            break;
59
4
        }
60
100k
        offset = next;
61
100k
        ++rune_count;
62
100k
    }
63
98.7k
    return {static_cast<size_t>(offset), rune_count};
64
98.7k
}
65
66
template <typename Container>
67
27.0k
void release_oversized_scratch(Container& container) {
68
27.0k
    if (container.capacity() * sizeof(typename Container::value_type) >
69
27.0k
        ANALYZER_SCRATCH_HIGH_WATER_BYTES) {
70
22
        Container().swap(container);
71
22
    }
72
27.0k
}
_ZN5doris10segment_v214inverted_index25release_oversized_scratchISt6vectorIiSaIiEEEEvRT_
Line
Count
Source
67
22.2k
void release_oversized_scratch(Container& container) {
68
22.2k
    if (container.capacity() * sizeof(typename Container::value_type) >
69
22.2k
        ANALYZER_SCRATCH_HIGH_WATER_BYTES) {
70
16
        Container().swap(container);
71
16
    }
72
22.2k
}
_ZN5doris10segment_v214inverted_index25release_oversized_scratchINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvRT_
Line
Count
Source
67
4.80k
void release_oversized_scratch(Container& container) {
68
4.80k
    if (container.capacity() * sizeof(typename Container::value_type) >
69
4.80k
        ANALYZER_SCRATCH_HIGH_WATER_BYTES) {
70
4
        Container().swap(container);
71
4
    }
72
4.80k
}
_ZN5doris10segment_v214inverted_index25release_oversized_scratchISt6vectorINS1_12PinyinFilter8RuneInfoESaIS5_EEEEvRT_
Line
Count
Source
67
34
void release_oversized_scratch(Container& container) {
68
34
    if (container.capacity() * sizeof(typename Container::value_type) >
69
34
        ANALYZER_SCRATCH_HIGH_WATER_BYTES) {
70
2
        Container().swap(container);
71
2
    }
72
34
}
73
74
/**
75
 * All custom tokenizers and token_filters must use the following functions 
76
 * to set token information. Using these unified set methods helps avoid 
77
 * unnecessary data copying.
78
 * 
79
 * Note: Must not mix with other set methods
80
 */
81
class DorisTokenStream {
82
public:
83
1.09k
    DorisTokenStream() = default;
84
1.09k
    virtual ~DorisTokenStream() = default;
85
86
136k
    void set(Token* t, const std::string_view& term, int32_t pos = 1) {
87
136k
        t->setTextNoCopy(term.data(), cast_set<int32_t>(term.size()));
88
136k
        t->setPositionIncrement(pos);
89
136k
    }
90
91
32.2k
    void set_text(Token* t, const std::string_view& term) {
92
32.2k
        t->setTextNoCopy(term.data(), cast_set<int32_t>(term.size()));
93
32.2k
    }
94
95
88.4k
    int32_t get_position_increment(Token* t) { return t->getPositionIncrement(); }
96
86.9k
    void set_position_increment(Token* t, int32_t pos) { t->setPositionIncrement(pos); }
97
98
    // Return each rune's original relative byte start followed by the token's final byte end.
99
0
    virtual std::span<const int32_t> get_source_byte_offsets() const { return {}; }
100
101
    // Return separate rune ends when removed delimiters leave gaps between adjacent runes.
102
0
    virtual std::span<const int32_t> get_source_byte_end_offsets() const { return {}; }
103
104
    // Return a conservative relative source span when exact rune boundaries are unavailable.
105
4.23k
    virtual bool get_conservative_source_byte_span(int32_t& start, int32_t& end) const {
106
4.23k
        return false;
107
4.23k
    }
108
109
    // Enable source-boundary tracking only for streams with a downstream consumer.
110
0
    virtual void set_source_byte_offsets_enabled(bool enabled) {}
111
};
112
113
class TokenStreamWrapper : public TokenStream {
114
public:
115
104
    explicit TokenStreamWrapper(std::shared_ptr<TokenStream> ts) : _impl(std::move(ts)) {}
116
104
    ~TokenStreamWrapper() override = default;
117
118
110k
    Token* next(Token* token) override { return _impl->next(token); }
119
41
    void close() override { _impl->close(); }
120
3
    void reset() override { _impl->reset(); }
121
122
private:
123
    std::shared_ptr<TokenStream> _impl;
124
};
125
126
class TokenStreamComponents {
127
public:
128
    TokenStreamComponents(TokenizerPtr tokenizer, TokenStreamPtr result)
129
220
            : _source(std::move(tokenizer)), _sink(std::move(result)) {}
130
131
    void set_reader(const ReaderPtr& reader);
132
    TokenStreamPtr get_token_stream();
133
    TokenizerPtr get_source();
134
135
private:
136
    TokenizerPtr _source;
137
    TokenStreamPtr _sink;
138
};
139
using TokenStreamComponentsPtr = std::shared_ptr<TokenStreamComponents>;
140
141
}; // namespace doris::segment_v2::inverted_index