Coverage Report

Created: 2026-03-15 22:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/tablet/tablet_reader.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 "storage/tablet/tablet_reader.h"
19
20
#include <gen_cpp/olap_file.pb.h>
21
#include <gen_cpp/segment_v2.pb.h>
22
#include <thrift/protocol/TDebugProtocol.h>
23
24
#include <algorithm>
25
#include <functional>
26
#include <iterator>
27
#include <memory>
28
#include <numeric>
29
#include <ostream>
30
#include <shared_mutex>
31
32
#include "common/compiler_util.h" // IWYU pragma: keep
33
#include "common/config.h"
34
#include "common/exception.h"
35
#include "common/logging.h"
36
#include "common/status.h"
37
#include "core/arena.h"
38
#include "core/block/block.h"
39
#include "exec/common/variant_util.h"
40
#include "exprs/bitmapfilter_predicate.h"
41
#include "exprs/bloom_filter_func.h"
42
#include "exprs/create_predicate_function.h"
43
#include "exprs/hybrid_set.h"
44
#include "runtime/query_context.h"
45
#include "runtime/runtime_predicate.h"
46
#include "runtime/runtime_state.h"
47
#include "storage/index/bloom_filter/bloom_filter.h"
48
#include "storage/itoken_extractor.h"
49
#include "storage/olap_common.h"
50
#include "storage/olap_define.h"
51
#include "storage/predicate/column_predicate.h"
52
#include "storage/predicate/like_column_predicate.h"
53
#include "storage/predicate/predicate_creator.h"
54
#include "storage/row_cursor.h"
55
#include "storage/schema.h"
56
#include "storage/tablet/tablet.h"
57
#include "storage/tablet/tablet_meta.h"
58
#include "storage/tablet/tablet_schema.h"
59
60
namespace doris {
61
#include "common/compile_check_begin.h"
62
using namespace ErrorCode;
63
64
1.03M
void TabletReader::ReaderParams::check_validation() const {
65
1.03M
    if (UNLIKELY(version.first == -1 && is_segcompaction == false)) {
66
0
        throw Exception(Status::FatalError("version is not set. tablet={}", tablet->tablet_id()));
67
0
    }
68
1.03M
}
69
70
0
std::string TabletReader::ReaderParams::to_string() const {
71
0
    std::stringstream ss;
72
0
    ss << "tablet=" << tablet->tablet_id() << " reader_type=" << int(reader_type)
73
0
       << " aggregation=" << aggregation << " version=" << version
74
0
       << " start_key_include=" << start_key_include << " end_key_include=" << end_key_include;
75
76
0
    for (const auto& key : start_key) {
77
0
        ss << " keys=" << key;
78
0
    }
79
80
0
    for (const auto& key : end_key) {
81
0
        ss << " end_keys=" << key;
82
0
    }
83
84
0
    return ss.str();
85
0
}
86
87
1.03M
Status TabletReader::init(const ReaderParams& read_params) {
88
1.03M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_init_timer_ns);
89
90
1.03M
    Status res = _init_params(read_params);
91
1.03M
    if (!res.ok()) {
92
0
        LOG(WARNING) << "fail to init reader when init params. res:" << res
93
0
                     << ", tablet_id:" << read_params.tablet->tablet_id()
94
0
                     << ", schema_hash:" << read_params.tablet->schema_hash()
95
0
                     << ", reader type:" << int(read_params.reader_type)
96
0
                     << ", version:" << read_params.version;
97
0
    }
98
1.03M
    return res;
99
1.03M
}
100
101
1.03M
Status TabletReader::_capture_rs_readers(const ReaderParams& read_params) {
102
1.03M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_capture_rs_readers_timer_ns);
103
1.03M
    if (read_params.rs_splits.empty()) {
104
0
        return Status::InternalError("fail to acquire data sources. tablet={}",
105
0
                                     _tablet->tablet_id());
106
0
    }
107
108
1.03M
    bool eof = false;
109
1.03M
    bool is_lower_key_included = _keys_param.start_key_include;
110
1.03M
    bool is_upper_key_included = _keys_param.end_key_include;
111
112
2.60M
    for (int i = 0; i < _keys_param.start_keys.size(); ++i) {
113
        // lower bound
114
1.57M
        RowCursor& start_key = _keys_param.start_keys[i];
115
1.57M
        RowCursor& end_key = _keys_param.end_keys[i];
116
117
1.57M
        if (!is_lower_key_included) {
118
952
            if (compare_row_key(start_key, end_key) >= 0) {
119
16
                VLOG_NOTICE << "return EOF when lower key not include"
120
0
                            << ", start_key=" << start_key.to_string()
121
0
                            << ", end_key=" << end_key.to_string();
122
16
                eof = true;
123
16
                break;
124
16
            }
125
1.57M
        } else {
126
1.57M
            if (compare_row_key(start_key, end_key) > 0) {
127
0
                VLOG_NOTICE << "return EOF when lower key include="
128
0
                            << ", start_key=" << start_key.to_string()
129
0
                            << ", end_key=" << end_key.to_string();
130
0
                eof = true;
131
0
                break;
132
0
            }
133
1.57M
        }
134
135
1.57M
        _is_lower_keys_included.push_back(is_lower_key_included);
136
1.57M
        _is_upper_keys_included.push_back(is_upper_key_included);
137
1.57M
    }
138
139
1.03M
    if (eof) {
140
16
        return Status::EndOfFile("reach end of scan range. tablet={}", _tablet->tablet_id());
141
16
    }
142
143
1.03M
    bool need_ordered_result = true;
144
1.03M
    if (read_params.reader_type == ReaderType::READER_QUERY) {
145
998k
        if (_tablet_schema->keys_type() == DUP_KEYS) {
146
            // duplicated keys are allowed, no need to merge sort keys in rowset
147
461k
            need_ordered_result = false;
148
461k
        }
149
998k
        if (_tablet_schema->keys_type() == UNIQUE_KEYS &&
150
998k
            _tablet->enable_unique_key_merge_on_write()) {
151
            // unique keys with merge on write, no need to merge sort keys in rowset
152
489k
            need_ordered_result = false;
153
489k
        }
154
998k
        if (_aggregation) {
155
            // compute engine will aggregate rows with the same key,
156
            // it's ok for rowset to return unordered result
157
955k
            need_ordered_result = false;
158
955k
        }
159
160
998k
        if (_direct_mode) {
161
            // direct mode indicates that the storage layer does not need to merge,
162
            // it's ok for rowset to return unordered result
163
989k
            need_ordered_result = false;
164
989k
        }
165
166
998k
        if (read_params.read_orderby_key) {
167
2.03k
            need_ordered_result = true;
168
2.03k
        }
169
998k
    }
170
171
1.03M
    _reader_context.reader_type = read_params.reader_type;
172
1.03M
    _reader_context.version = read_params.version;
173
1.03M
    _reader_context.tablet_schema = _tablet_schema;
174
1.03M
    _reader_context.need_ordered_result = need_ordered_result;
175
1.03M
    _reader_context.topn_filter_source_node_ids = read_params.topn_filter_source_node_ids;
176
1.03M
    _reader_context.topn_filter_target_node_id = read_params.topn_filter_target_node_id;
177
1.03M
    _reader_context.read_orderby_key_reverse = read_params.read_orderby_key_reverse;
178
1.03M
    _reader_context.read_orderby_key_limit = read_params.read_orderby_key_limit;
179
1.03M
    _reader_context.filter_block_conjuncts = read_params.filter_block_conjuncts;
180
1.03M
    _reader_context.return_columns = &_return_columns;
181
1.03M
    _reader_context.read_orderby_key_columns =
182
1.03M
            !_orderby_key_columns.empty() ? &_orderby_key_columns : nullptr;
183
1.03M
    _reader_context.predicates = &_col_predicates;
184
1.03M
    _reader_context.value_predicates = &_value_col_predicates;
185
1.03M
    _reader_context.lower_bound_keys = &_keys_param.start_keys;
186
1.03M
    _reader_context.is_lower_keys_included = &_is_lower_keys_included;
187
1.03M
    _reader_context.upper_bound_keys = &_keys_param.end_keys;
188
1.03M
    _reader_context.is_upper_keys_included = &_is_upper_keys_included;
189
1.03M
    _reader_context.delete_handler = &_delete_handler;
190
1.03M
    _reader_context.stats = &_stats;
191
1.03M
    _reader_context.use_page_cache = read_params.use_page_cache;
192
1.03M
    _reader_context.sequence_id_idx = _sequence_col_idx;
193
1.03M
    _reader_context.is_unique = tablet()->keys_type() == UNIQUE_KEYS;
194
1.03M
    _reader_context.merged_rows = &_merged_rows;
195
1.03M
    _reader_context.delete_bitmap = read_params.delete_bitmap;
196
1.03M
    _reader_context.enable_unique_key_merge_on_write = tablet()->enable_unique_key_merge_on_write();
197
1.03M
    _reader_context.record_rowids = read_params.record_rowids;
198
1.03M
    _reader_context.rowid_conversion = read_params.rowid_conversion;
199
1.03M
    _reader_context.is_key_column_group = read_params.is_key_column_group;
200
1.03M
    _reader_context.remaining_conjunct_roots = read_params.remaining_conjunct_roots;
201
1.03M
    _reader_context.common_expr_ctxs_push_down = read_params.common_expr_ctxs_push_down;
202
1.03M
    _reader_context.output_columns = &read_params.output_columns;
203
1.03M
    _reader_context.push_down_agg_type_opt = read_params.push_down_agg_type_opt;
204
1.03M
    _reader_context.ttl_seconds = _tablet->ttl_seconds();
205
1.03M
    _reader_context.score_runtime = read_params.score_runtime;
206
1.03M
    _reader_context.collection_statistics = read_params.collection_statistics;
207
208
1.03M
    _reader_context.virtual_column_exprs = read_params.virtual_column_exprs;
209
1.03M
    _reader_context.vir_cid_to_idx_in_block = read_params.vir_cid_to_idx_in_block;
210
1.03M
    _reader_context.vir_col_idx_to_type = read_params.vir_col_idx_to_type;
211
1.03M
    _reader_context.ann_topn_runtime = read_params.ann_topn_runtime;
212
213
1.03M
    _reader_context.condition_cache_digest = read_params.condition_cache_digest;
214
1.03M
    _reader_context.all_access_paths = read_params.all_access_paths;
215
1.03M
    _reader_context.predicate_access_paths = read_params.predicate_access_paths;
216
217
1.03M
    return Status::OK();
218
1.03M
}
219
220
320
TabletColumn TabletReader::materialize_column(const TabletColumn& orig) {
221
320
    if (!orig.is_variant_type()) {
222
303
        return orig;
223
303
    }
224
17
    TabletColumn column_with_cast_type = orig;
225
17
    auto cast_type = _reader_context.target_cast_type_for_variants.at(orig.name());
226
17
    return variant_util::get_column_by_type(cast_type, orig.name(),
227
17
                                            {
228
17
                                                    .unique_id = orig.unique_id(),
229
17
                                                    .parent_unique_id = orig.parent_unique_id(),
230
17
                                                    .path_info = *orig.path_info_ptr(),
231
17
                                            });
232
320
}
233
234
1.03M
Status TabletReader::_init_params(const ReaderParams& read_params) {
235
1.03M
    read_params.check_validation();
236
237
1.03M
    _direct_mode = read_params.direct_mode;
238
1.03M
    _aggregation = read_params.aggregation;
239
1.03M
    _reader_type = read_params.reader_type;
240
1.03M
    _tablet = read_params.tablet;
241
1.03M
    _tablet_schema = read_params.tablet_schema;
242
1.03M
    _reader_context.runtime_state = read_params.runtime_state;
243
1.03M
    _reader_context.target_cast_type_for_variants = read_params.target_cast_type_for_variants;
244
245
1.03M
    RETURN_IF_ERROR(_init_conditions_param(read_params));
246
247
1.03M
    Status res = _init_delete_condition(read_params);
248
1.03M
    if (!res.ok()) {
249
0
        LOG(WARNING) << "fail to init delete param. res = " << res;
250
0
        return res;
251
0
    }
252
253
1.03M
    res = _init_return_columns(read_params);
254
1.03M
    if (!res.ok()) {
255
0
        LOG(WARNING) << "fail to init return columns. res = " << res;
256
0
        return res;
257
0
    }
258
259
1.03M
    res = _init_keys_param(read_params);
260
1.03M
    if (!res.ok()) {
261
0
        LOG(WARNING) << "fail to init keys param. res=" << res;
262
0
        return res;
263
0
    }
264
1.03M
    res = _init_orderby_keys_param(read_params);
265
1.03M
    if (!res.ok()) {
266
0
        LOG(WARNING) << "fail to init orderby keys param. res=" << res;
267
0
        return res;
268
0
    }
269
1.03M
    if (_tablet_schema->has_sequence_col()) {
270
5.30k
        auto sequence_col_idx = _tablet_schema->sequence_col_idx();
271
5.30k
        DCHECK_NE(sequence_col_idx, -1);
272
20.8k
        for (auto col : _return_columns) {
273
            // query has sequence col
274
20.8k
            if (col == sequence_col_idx) {
275
504
                _sequence_col_idx = sequence_col_idx;
276
504
                break;
277
504
            }
278
20.8k
        }
279
5.30k
    }
280
281
1.03M
    return res;
282
1.03M
}
283
284
1.03M
Status TabletReader::_init_return_columns(const ReaderParams& read_params) {
285
1.03M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_init_return_columns_timer_ns);
286
1.03M
    if (read_params.reader_type == ReaderType::READER_QUERY) {
287
1.00M
        _return_columns = read_params.return_columns;
288
1.00M
        _tablet_columns_convert_to_null_set = read_params.tablet_columns_convert_to_null_set;
289
8.77M
        for (auto id : read_params.return_columns) {
290
8.77M
            if (_tablet_schema->column(id).is_key()) {
291
3.73M
                _key_cids.push_back(id);
292
5.04M
            } else {
293
5.04M
                _value_cids.push_back(id);
294
5.04M
            }
295
8.77M
        }
296
1.00M
    } else if (read_params.return_columns.empty()) {
297
0
        for (uint32_t i = 0; i < _tablet_schema->num_columns(); ++i) {
298
0
            _return_columns.push_back(i);
299
0
            if (_tablet_schema->column(i).is_key()) {
300
0
                _key_cids.push_back(i);
301
0
            } else {
302
0
                _value_cids.push_back(i);
303
0
            }
304
0
        }
305
0
        VLOG_NOTICE << "return column is empty, using full column as default.";
306
28.8k
    } else if ((read_params.reader_type == ReaderType::READER_CUMULATIVE_COMPACTION ||
307
28.8k
                read_params.reader_type == ReaderType::READER_SEGMENT_COMPACTION ||
308
28.8k
                read_params.reader_type == ReaderType::READER_BASE_COMPACTION ||
309
28.8k
                read_params.reader_type == ReaderType::READER_FULL_COMPACTION ||
310
28.8k
                read_params.reader_type == ReaderType::READER_COLD_DATA_COMPACTION ||
311
28.8k
                read_params.reader_type == ReaderType::READER_ALTER_TABLE) &&
312
31.0k
               !read_params.return_columns.empty()) {
313
31.0k
        _return_columns = read_params.return_columns;
314
121k
        for (auto id : read_params.return_columns) {
315
121k
            if (_tablet_schema->column(id).is_key()) {
316
38.4k
                _key_cids.push_back(id);
317
83.3k
            } else {
318
83.3k
                _value_cids.push_back(id);
319
83.3k
            }
320
121k
        }
321
18.4E
    } else if (read_params.reader_type == ReaderType::READER_CHECKSUM) {
322
0
        _return_columns = read_params.return_columns;
323
0
        for (auto id : read_params.return_columns) {
324
0
            if (_tablet_schema->column(id).is_key()) {
325
0
                _key_cids.push_back(id);
326
0
            } else {
327
0
                _value_cids.push_back(id);
328
0
            }
329
0
        }
330
18.4E
    } else {
331
18.4E
        return Status::Error<INVALID_ARGUMENT>(
332
18.4E
                "fail to init return columns. reader_type={}, return_columns_size={}",
333
18.4E
                int(read_params.reader_type), read_params.return_columns.size());
334
18.4E
    }
335
336
1.03M
    std::sort(_key_cids.begin(), _key_cids.end(), std::greater<>());
337
338
1.03M
    return Status::OK();
339
1.03M
}
340
341
1.03M
Status TabletReader::_init_keys_param(const ReaderParams& read_params) {
342
1.03M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_init_keys_param_timer_ns);
343
1.03M
    if (read_params.start_key.empty()) {
344
244k
        return Status::OK();
345
244k
    }
346
347
787k
    _keys_param.start_key_include = read_params.start_key_include;
348
787k
    _keys_param.end_key_include = read_params.end_key_include;
349
350
787k
    size_t start_key_size = read_params.start_key.size();
351
    //_keys_param.start_keys.resize(start_key_size);
352
787k
    std::vector<RowCursor>(start_key_size).swap(_keys_param.start_keys);
353
354
787k
    size_t scan_key_size = read_params.start_key.front().size();
355
787k
    if (scan_key_size > _tablet_schema->num_columns()) {
356
0
        return Status::Error<INVALID_ARGUMENT>(
357
0
                "Input param are invalid. Column count is bigger than num_columns of schema. "
358
0
                "column_count={}, schema.num_columns={}",
359
0
                scan_key_size, _tablet_schema->num_columns());
360
0
    }
361
362
787k
    std::vector<uint32_t> columns(scan_key_size);
363
787k
    std::iota(columns.begin(), columns.end(), 0);
364
365
787k
    std::shared_ptr<Schema> schema = std::make_shared<Schema>(_tablet_schema->columns(), columns);
366
367
2.35M
    for (size_t i = 0; i < start_key_size; ++i) {
368
1.56M
        if (read_params.start_key[i].size() != scan_key_size) {
369
0
            return Status::Error<INVALID_ARGUMENT>(
370
0
                    "The start_key.at({}).size={}, not equals the scan_key_size={}", i,
371
0
                    read_params.start_key[i].size(), scan_key_size);
372
0
        }
373
374
1.56M
        Status res = _keys_param.start_keys[i].init_scan_key(
375
1.56M
                _tablet_schema, read_params.start_key[i].values(), schema);
376
1.56M
        if (!res.ok()) {
377
0
            LOG(WARNING) << "fail to init row cursor. res = " << res;
378
0
            return res;
379
0
        }
380
1.56M
        res = _keys_param.start_keys[i].from_tuple(read_params.start_key[i]);
381
1.56M
        if (!res.ok()) {
382
0
            LOG(WARNING) << "fail to init row cursor from Keys. res=" << res << "key_index=" << i;
383
0
            return res;
384
0
        }
385
1.56M
    }
386
387
787k
    size_t end_key_size = read_params.end_key.size();
388
    //_keys_param.end_keys.resize(end_key_size);
389
787k
    std::vector<RowCursor>(end_key_size).swap(_keys_param.end_keys);
390
2.35M
    for (size_t i = 0; i < end_key_size; ++i) {
391
1.56M
        if (read_params.end_key[i].size() != scan_key_size) {
392
0
            return Status::Error<INVALID_ARGUMENT>(
393
0
                    "The end_key.at({}).size={}, not equals the scan_key_size={}", i,
394
0
                    read_params.end_key[i].size(), scan_key_size);
395
0
        }
396
397
1.56M
        Status res = _keys_param.end_keys[i].init_scan_key(_tablet_schema,
398
1.56M
                                                           read_params.end_key[i].values(), schema);
399
1.56M
        if (!res.ok()) {
400
0
            LOG(WARNING) << "fail to init row cursor. res = " << res;
401
0
            return res;
402
0
        }
403
404
1.56M
        res = _keys_param.end_keys[i].from_tuple(read_params.end_key[i]);
405
1.56M
        if (!res.ok()) {
406
0
            LOG(WARNING) << "fail to init row cursor from Keys. res=" << res << " key_index=" << i;
407
0
            return res;
408
0
        }
409
1.56M
    }
410
411
    //TODO:check the valid of start_key and end_key.(eg. start_key <= end_key)
412
413
787k
    return Status::OK();
414
787k
}
415
416
1.02M
Status TabletReader::_init_orderby_keys_param(const ReaderParams& read_params) {
417
1.02M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_init_orderby_keys_param_timer_ns);
418
    // UNIQUE_KEYS will compare all keys as before
419
1.02M
    if (_tablet_schema->keys_type() == DUP_KEYS || (_tablet_schema->keys_type() == UNIQUE_KEYS &&
420
980k
                                                    _tablet->enable_unique_key_merge_on_write())) {
421
980k
        if (!_tablet_schema->cluster_key_uids().empty()) {
422
5.94k
            if (read_params.read_orderby_key_num_prefix_columns >
423
5.94k
                _tablet_schema->cluster_key_uids().size()) {
424
0
                return Status::Error<ErrorCode::INTERNAL_ERROR>(
425
0
                        "read_orderby_key_num_prefix_columns={} > cluster_keys.size()={}",
426
0
                        read_params.read_orderby_key_num_prefix_columns,
427
0
                        _tablet_schema->cluster_key_uids().size());
428
0
            }
429
5.95k
            for (uint32_t i = 0; i < read_params.read_orderby_key_num_prefix_columns; i++) {
430
10
                auto cid = _tablet_schema->cluster_key_uids()[i];
431
10
                auto index = _tablet_schema->field_index(cid);
432
10
                if (index < 0) {
433
0
                    return Status::Error<ErrorCode::INTERNAL_ERROR>(
434
0
                            "could not find cluster key column with unique_id=" +
435
0
                            std::to_string(cid) +
436
0
                            " in tablet schema, tablet_id=" + std::to_string(_tablet->tablet_id()));
437
0
                }
438
20
                for (uint32_t idx = 0; idx < _return_columns.size(); idx++) {
439
20
                    if (_return_columns[idx] == index) {
440
10
                        _orderby_key_columns.push_back(idx);
441
10
                        break;
442
10
                    }
443
20
                }
444
10
            }
445
974k
        } else {
446
            // find index in vector _return_columns
447
            //   for the read_orderby_key_num_prefix_columns orderby keys
448
976k
            for (uint32_t i = 0; i < read_params.read_orderby_key_num_prefix_columns; i++) {
449
3.30k
                for (uint32_t idx = 0; idx < _return_columns.size(); idx++) {
450
3.30k
                    if (_return_columns[idx] == i) {
451
2.50k
                        _orderby_key_columns.push_back(idx);
452
2.50k
                        break;
453
2.50k
                    }
454
3.30k
                }
455
2.49k
            }
456
974k
        }
457
980k
        if (read_params.read_orderby_key_num_prefix_columns != _orderby_key_columns.size()) {
458
0
            return Status::Error<ErrorCode::INTERNAL_ERROR>(
459
0
                    "read_orderby_key_num_prefix_columns != _orderby_key_columns.size, "
460
0
                    "read_params.read_orderby_key_num_prefix_columns={}, "
461
0
                    "_orderby_key_columns.size()={}",
462
0
                    read_params.read_orderby_key_num_prefix_columns, _orderby_key_columns.size());
463
0
        }
464
980k
    }
465
466
1.02M
    return Status::OK();
467
1.02M
}
468
469
1.03M
Status TabletReader::_init_conditions_param(const ReaderParams& read_params) {
470
1.03M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_init_conditions_param_timer_ns);
471
1.03M
    std::vector<std::shared_ptr<ColumnPredicate>> predicates;
472
1.03M
    std::copy(read_params.predicates.cbegin(), read_params.predicates.cend(),
473
1.03M
              std::inserter(predicates, predicates.begin()));
474
    // Function filter push down to storage engine
475
1.03M
    auto is_like_predicate = [](std::shared_ptr<ColumnPredicate> _pred) {
476
321
        return dynamic_cast<LikeColumnPredicate<TYPE_CHAR>*>(_pred.get()) != nullptr ||
477
321
               dynamic_cast<LikeColumnPredicate<TYPE_STRING>*>(_pred.get()) != nullptr;
478
321
    };
479
480
1.03M
    for (const auto& filter : read_params.function_filters) {
481
319
        predicates.emplace_back(_parse_to_predicate(filter));
482
319
        auto pred = predicates.back();
483
484
319
        const auto& col = _tablet_schema->column(pred->column_id());
485
319
        const auto* tablet_index = _tablet_schema->get_ngram_bf_index(col.unique_id());
486
321
        if (is_like_predicate(pred) && tablet_index && config::enable_query_like_bloom_filter) {
487
13
            std::unique_ptr<segment_v2::BloomFilter> ng_bf;
488
13
            std::string pattern = pred->get_search_str();
489
13
            auto gram_bf_size = tablet_index->get_gram_bf_size();
490
13
            auto gram_size = tablet_index->get_gram_size();
491
492
13
            RETURN_IF_ERROR(segment_v2::BloomFilter::create(segment_v2::NGRAM_BLOOM_FILTER, &ng_bf,
493
13
                                                            gram_bf_size));
494
13
            NgramTokenExtractor _token_extractor(gram_size);
495
496
13
            if (_token_extractor.string_like_to_bloom_filter(pattern.data(), pattern.length(),
497
13
                                                             *ng_bf)) {
498
12
                pred->set_page_ng_bf(std::move(ng_bf));
499
12
            }
500
13
        }
501
319
    }
502
503
1.03M
    for (auto predicate : predicates) {
504
719k
        auto column = _tablet_schema->column(predicate->column_id());
505
719k
        if (column.aggregation() != FieldAggregationMethod::OLAP_FIELD_AGGREGATION_NONE) {
506
3.00k
            _value_col_predicates.push_back(predicate);
507
716k
        } else {
508
716k
            _col_predicates.push_back(predicate);
509
716k
        }
510
719k
    }
511
512
1.03M
    return Status::OK();
513
1.03M
}
514
515
std::shared_ptr<ColumnPredicate> TabletReader::_parse_to_predicate(
516
318
        const FunctionFilter& function_filter) {
517
318
    int32_t index = _tablet_schema->field_index(function_filter._col_name);
518
318
    if (index < 0) {
519
0
        throw Exception(Status::InternalError("Column {} not found in tablet schema",
520
0
                                              function_filter._col_name));
521
0
        return nullptr;
522
0
    }
523
318
    const TabletColumn& column = materialize_column(_tablet_schema->column(index));
524
318
    return create_column_predicate(index, std::make_shared<FunctionFilter>(function_filter),
525
318
                                   column.type(), &column);
526
318
}
527
528
1.03M
Status TabletReader::_init_delete_condition(const ReaderParams& read_params) {
529
1.03M
    SCOPED_RAW_TIMER(&_stats.tablet_reader_init_delete_condition_param_timer_ns);
530
    // If it's cumu and not allow do delete when cumu
531
1.03M
    if (read_params.reader_type == ReaderType::READER_SEGMENT_COMPACTION ||
532
1.03M
        (read_params.reader_type == ReaderType::READER_CUMULATIVE_COMPACTION &&
533
1.03M
         !config::enable_delete_when_cumu_compaction)) {
534
28.5k
        return Status::OK();
535
28.5k
    }
536
1.00M
    bool cumu_delete = read_params.reader_type == ReaderType::READER_CUMULATIVE_COMPACTION &&
537
1.00M
                       config::enable_delete_when_cumu_compaction;
538
    // Delete sign could not be applied when delete on cumu compaction is enabled, bucause it is meant for delete with predicates.
539
    // If delete design is applied on cumu compaction, it will lose effect when doing base compaction.
540
    // `_delete_sign_available` indicates the condition where we could apply delete signs to data.
541
1.00M
    _delete_sign_available = (((read_params.reader_type == ReaderType::READER_BASE_COMPACTION ||
542
1.00M
                                read_params.reader_type == ReaderType::READER_FULL_COMPACTION) &&
543
1.00M
                               config::enable_prune_delete_sign_when_base_compaction) ||
544
1.00M
                              read_params.reader_type == ReaderType::READER_COLD_DATA_COMPACTION ||
545
1.00M
                              read_params.reader_type == ReaderType::READER_CHECKSUM);
546
547
    // `_filter_delete` indicates the condition where we should execlude deleted tuples when reading data.
548
    // However, queries will not use this condition but generate special where predicates to filter data.
549
    // (Though a lille bit confused, it is how the current logic working...)
550
1.00M
    _filter_delete = _delete_sign_available || cumu_delete;
551
1.00M
    return _delete_handler.init(_tablet_schema, read_params.delete_predicates,
552
1.00M
                                read_params.version.second);
553
1.03M
}
554
555
Status TabletReader::init_reader_params_and_create_block(
556
        TabletSharedPtr tablet, ReaderType reader_type,
557
        const std::vector<RowsetSharedPtr>& input_rowsets,
558
0
        TabletReader::ReaderParams* reader_params, Block* block) {
559
0
    reader_params->tablet = tablet;
560
0
    reader_params->reader_type = reader_type;
561
0
    reader_params->version =
562
0
            Version(input_rowsets.front()->start_version(), input_rowsets.back()->end_version());
563
564
0
    TabletReadSource read_source;
565
0
    for (const auto& rowset : input_rowsets) {
566
0
        RowsetReaderSharedPtr rs_reader;
567
0
        RETURN_IF_ERROR(rowset->create_reader(&rs_reader));
568
0
        read_source.rs_splits.emplace_back(std::move(rs_reader));
569
0
    }
570
0
    read_source.fill_delete_predicates();
571
0
    reader_params->set_read_source(std::move(read_source));
572
573
0
    std::vector<RowsetMetaSharedPtr> rowset_metas(input_rowsets.size());
574
0
    std::transform(input_rowsets.begin(), input_rowsets.end(), rowset_metas.begin(),
575
0
                   [](const RowsetSharedPtr& rowset) { return rowset->rowset_meta(); });
576
0
    TabletSchemaSPtr read_tablet_schema =
577
0
            tablet->tablet_schema_with_merged_max_schema_version(rowset_metas);
578
0
    TabletSchemaSPtr merge_tablet_schema = std::make_shared<TabletSchema>();
579
0
    merge_tablet_schema->copy_from(*read_tablet_schema);
580
581
    // Merge the columns in delete predicate that not in latest schema in to current tablet schema
582
0
    for (auto& del_pred : reader_params->delete_predicates) {
583
0
        merge_tablet_schema->merge_dropped_columns(*del_pred->tablet_schema());
584
0
    }
585
0
    reader_params->tablet_schema = merge_tablet_schema;
586
587
0
    reader_params->return_columns.resize(read_tablet_schema->num_columns());
588
0
    std::iota(reader_params->return_columns.begin(), reader_params->return_columns.end(), 0);
589
0
    reader_params->origin_return_columns = &reader_params->return_columns;
590
591
0
    *block = read_tablet_schema->create_block();
592
593
0
    return Status::OK();
594
0
}
595
596
#include "common/compile_check_end.h"
597
} // namespace doris