Coverage Report

Created: 2026-09-15 08:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/scan/file_scanner_v2.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 <list>
21
#include <map>
22
#include <memory>
23
#include <optional>
24
#include <string>
25
#include <unordered_map>
26
#include <vector>
27
28
#include "common/factory_creator.h"
29
#include "common/status.h"
30
#include "core/block/adaptive_block_size_predictor.h"
31
#include "core/block/block.h"
32
#include "exec/operator/file_scan_operator.h"
33
#include "exec/scan/scanner.h"
34
#include "exec/scan/split_source_connector.h"
35
#include "exprs/vexpr_fwd.h"
36
#include "format_v2/column_mapper.h"
37
#include "format_v2/table_reader.h"
38
#include "gen_cpp/Descriptors_types.h"
39
#include "gen_cpp/PlanNodes_types.h"
40
#include "io/io_common.h"
41
#include "runtime/runtime_profile.h"
42
43
namespace doris {
44
45
class RuntimeState;
46
class SlotDescriptor;
47
class TFileRangeDesc;
48
class TFileScanRangeParams;
49
class ShardedKVCache;
50
51
class FileScannerV2 final : public Scanner {
52
    ENABLE_FACTORY_CREATOR(FileScannerV2);
53
54
public:
55
    static constexpr const char* NAME = "FileScannerV2";
56
    static constexpr size_t ADAPTIVE_BATCH_INITIAL_PROBE_ROWS = 32;
57
    static const std::string FileReadBytesProfile;
58
    static const std::string FileReadTimeProfile;
59
60
    struct RealtimeCounterDeltas {
61
        int64_t scan_rows = 0;
62
        int64_t scan_bytes = 0;
63
        int64_t scan_bytes_from_local_storage = 0;
64
        int64_t scan_bytes_from_remote_storage = 0;
65
    };
66
67
    enum class UncachedReaderBytesStorage { LOCAL, REMOTE, NONE };
68
69
    static bool is_supported(const TFileScanRangeParams& params, const TFileRangeDesc& range);
70
#ifdef BE_TEST
71
    FileScannerV2(RuntimeState* state, RuntimeProfile* profile,
72
                  std::unique_ptr<format::TableReader> table_reader);
73
    static Status TEST_validate_scan_range(const TFileScanRangeParams& params,
74
                                           const TFileRangeDesc& range);
75
    static Status TEST_to_file_format(TFileFormatType::type format_type,
76
                                      format::FileFormat* file_format);
77
    static bool TEST_is_partition_slot(const TFileScanSlotInfo& slot_info,
78
                                       const std::string& column_name);
79
    static bool TEST_is_data_file_slot(const TFileScanSlotInfo& slot_info,
80
                                       const std::string& column_name);
81
    static Status TEST_rewrite_slot_refs_to_global_index(
82
            VExprSPtr* expr,
83
            const std::unordered_map<int32_t, format::GlobalIndex>& slot_id_to_global_index);
84
    static RealtimeCounterDeltas TEST_collect_realtime_counter_deltas(
85
            const io::FileReaderStats& file_reader_stats,
86
            const io::FileCacheStatistics& file_cache_statistics,
87
            UncachedReaderBytesStorage uncached_reader_bytes_storage, int64_t* last_read_bytes,
88
            int64_t* last_read_rows, int64_t* last_bytes_read_from_local,
89
            int64_t* last_bytes_read_from_remote);
90
    static void TEST_report_file_cache_profile(
91
            RuntimeProfile* profile, const io::FileCacheStatistics& file_cache_statistics);
92
    static bool TEST_should_skip_not_found(const Status& status, bool ignore_not_found);
93
    static bool TEST_should_skip_empty(const Status& status, bool stopped);
94
    static Status TEST_validate_variant_projection(TFileFormatType::type format_type,
95
                                                   bool has_variant_projection) {
96
        return _validate_variant_projection(format_type, has_variant_projection);
97
    }
98
    static Status TEST_contextualize_output_filter_status(Status status,
99
                                                          TFileFormatType::type format_type) {
100
        return _contextualize_output_filter_status(std::move(status), format_type);
101
    }
102
    static bool TEST_should_run_adaptive_batch_size(bool predictor_initialized,
103
                                                    bool current_split_uses_metadata_count) {
104
        return _should_run_adaptive_batch_size(predictor_initialized,
105
                                               current_split_uses_metadata_count);
106
    }
107
#endif
108
109
    FileScannerV2(RuntimeState* state, FileScanLocalState* parent, int64_t limit,
110
                  std::shared_ptr<SplitSourceConnector> split_source, RuntimeProfile* profile,
111
                  ShardedKVCache* kv_cache,
112
                  const std::unordered_map<std::string, int>* colname_to_slot_id);
113
114
    // Standalone scanner used by TopN two-phase materialization.
115
    FileScannerV2(RuntimeState* state, RuntimeProfile* profile, const TFileScanRangeParams* params,
116
                  const std::unordered_map<std::string, int>* colname_to_slot_id,
117
                  TupleDescriptor* tuple_desc)
118
16
            : Scanner(state, profile), _params(params) {
119
16
        (void)colname_to_slot_id;
120
16
        _output_tuple_desc = tuple_desc;
121
16
    }
122
123
    Status read_by_rows(const TFileRangeDesc& range, const std::list<int64_t>& row_ids,
124
                        Block* result_block, int64_t* init_reader_ms, int64_t* get_block_ms);
125
126
    Status init(RuntimeState* state, const VExprContextSPtrs& conjuncts) override;
127
    Status _open_impl(RuntimeState* state) override;
128
    Status close(RuntimeState* state) override;
129
    void try_stop() override;
130
0
    std::string get_name() override { return FileScannerV2::NAME; }
131
0
    std::string get_current_scan_range_name() override { return _current_range_path; }
132
    void update_realtime_counters() override;
133
134
protected:
135
    Status _get_block_impl(RuntimeState* state, Block* block, bool* eof) override;
136
    bool _can_merge_padding_blocks(const Block& left, const Block& right) const override;
137
    Status _filter_output_block(Block* block) override;
138
    void _collect_profile_before_close() override;
139
    bool _should_update_load_counters() const override;
140
141
private:
142
    static Status _validate_scan_range(const TFileScanRangeParams& params,
143
                                       const TFileRangeDesc& range);
144
    static Status _validate_variant_projection(TFileFormatType::type format_type,
145
                                               bool has_variant_projection);
146
    Status _get_next_scan_range(bool* has_next);
147
    TFileFormatType::type _get_current_format_type() const;
148
    Status _init_io_ctx();
149
    Status _init_expr_ctxes();
150
    Status _prepare_next_split(bool* eos);
151
    Status _init_table_reader(const TFileRangeDesc& range);
152
    Status _create_table_reader_for_format(const TFileRangeDesc& range,
153
                                           std::unique_ptr<format::TableReader>* reader) const;
154
    Status _prepare_table_reader_split(const TFileRangeDesc& range,
155
                                       std::map<std::string, Field> partition_values);
156
    static bool _should_skip_not_found(const Status& status, bool ignore_not_found);
157
    static bool _should_skip_empty(const Status& status, bool stopped);
158
    static Status _contextualize_output_filter_status(Status status,
159
                                                      TFileFormatType::type format_type);
160
    bool _should_enable_file_meta_cache() const;
161
    std::optional<format::GlobalRowIdContext> _create_global_rowid_context(
162
            const TFileRangeDesc& range) const;
163
    Status _generate_partition_values(const TFileRangeDesc& range,
164
                                      std::map<std::string, Field>* partition_values) const;
165
    Status _parse_partition_value(const SlotDescriptor* slot_desc, const std::string& value,
166
                                  bool is_null, Field* field) const;
167
    Status _build_projected_columns(const format::TableReader& table_reader);
168
    Status _build_default_expr(const TFileScanSlotInfo& slot_info, VExprContextSPtr* ctx) const;
169
    static format::ColumnDefinition _build_table_column(const SlotDescriptor* slot_desc);
170
    Status _build_table_conjuncts(VExprContextSPtrs* conjuncts) const;
171
    static Status _to_file_format(TFileFormatType::type format_type,
172
                                  format::FileFormat* file_format);
173
    void _reset_adaptive_batch_size_state();
174
    void _init_adaptive_batch_size_state(TFileFormatType::type format_type);
175
    bool _should_enable_adaptive_batch_size(TFileFormatType::type format_type) const;
176
    bool _should_run_adaptive_batch_size() const;
177
    static bool _should_run_adaptive_batch_size(bool predictor_initialized,
178
                                                bool current_split_uses_metadata_count);
179
    size_t _predict_reader_batch_rows();
180
    void _update_adaptive_batch_size(const Block& block);
181
    static RealtimeCounterDeltas _collect_realtime_counter_deltas(
182
            const io::FileReaderStats& file_reader_stats,
183
            const io::FileCacheStatistics& file_cache_statistics,
184
            UncachedReaderBytesStorage uncached_reader_bytes_storage, int64_t* last_read_bytes,
185
            int64_t* last_read_rows, int64_t* last_bytes_read_from_local,
186
            int64_t* last_bytes_read_from_remote);
187
    static UncachedReaderBytesStorage _uncached_reader_bytes_storage(TFileType::type file_type);
188
    static void _report_file_cache_profile(RuntimeProfile* profile,
189
                                           const io::FileCacheStatistics& file_cache_statistics);
190
    void _report_file_reader_predicate_filtered_rows();
191
    void _report_condition_cache_profile();
192
193
    struct PartitionSlotInfo {
194
        const SlotDescriptor* slot_desc = nullptr;
195
        std::string canonical_name;
196
    };
197
198
    const TFileScanRangeParams* _params = nullptr;
199
    std::shared_ptr<SplitSourceConnector> _split_source;
200
    bool _first_scan_range = false;
201
    bool _has_prepared_split = false;
202
    int _table_reader_rf_num = 0;
203
    TFileRangeDesc _current_range;
204
    std::string _current_range_path;
205
206
    std::unique_ptr<format::TableReader> _table_reader;
207
    std::vector<format::ColumnDefinition> _projected_columns;
208
    bool _has_variant_projection = false;
209
    // File formats without embedded schema, such as CSV, still need the FE slot descriptors in
210
    // file-column order. This mirrors old FileScanner::_file_slot_descs and is passed only to
211
    // readers that cannot derive their schema from file metadata.
212
    std::vector<SlotDescriptor*> _file_slot_descs;
213
    bool _need_global_rowid_column = false;
214
    std::unordered_map<int32_t, const SlotDescriptor*> _slot_id_to_desc;
215
    std::unordered_map<int32_t, format::GlobalIndex> _slot_id_to_global_index;
216
    std::unordered_map<std::string, PartitionSlotInfo> _partition_slot_descs;
217
218
    std::unique_ptr<io::FileCacheStatistics> _file_cache_statistics;
219
    io::FileCacheStatistics _reported_file_cache_statistics;
220
    std::unique_ptr<io::FileReaderStats> _file_reader_stats;
221
    std::shared_ptr<io::IOContext> _io_ctx;
222
    ShardedKVCache* _kv_cache = nullptr;
223
224
    RuntimeProfile::Counter* _scanner_total_timer = nullptr;
225
    RuntimeProfile::Counter* _init_timer = nullptr;
226
    RuntimeProfile::Counter* _open_timer = nullptr;
227
    RuntimeProfile::Counter* _get_block_timer = nullptr;
228
    RuntimeProfile::Counter* _empty_file_counter = nullptr;
229
    RuntimeProfile::Counter* _prepare_split_timer = nullptr;
230
    RuntimeProfile::Counter* _get_next_range_timer = nullptr;
231
    RuntimeProfile::Counter* _close_timer = nullptr;
232
    RuntimeProfile::Counter* _io_timer = nullptr;
233
    RuntimeProfile::Counter* _not_found_file_counter = nullptr;
234
    RuntimeProfile::Counter* _file_counter = nullptr;
235
    RuntimeProfile::Counter* _file_read_bytes_counter = nullptr;
236
    RuntimeProfile::Counter* _file_read_calls_counter = nullptr;
237
    RuntimeProfile::Counter* _file_read_time_counter = nullptr;
238
    RuntimeProfile::Counter* _adaptive_batch_predicted_rows_counter = nullptr;
239
    RuntimeProfile::Counter* _adaptive_batch_actual_bytes_counter = nullptr;
240
    RuntimeProfile::Counter* _adaptive_batch_probe_count_counter = nullptr;
241
    std::unique_ptr<AdaptiveBlockSizePredictor> _block_size_predictor;
242
    int64_t _reported_predicate_filtered_rows = 0;
243
    int64_t _reported_condition_cache_hit_count = 0;
244
    int64_t _reported_condition_cache_filtered_rows = 0;
245
    int64_t _last_read_bytes = 0;
246
    int64_t _last_read_rows = 0;
247
    int64_t _last_bytes_read_from_local = 0;
248
    int64_t _last_bytes_read_from_remote = 0;
249
    int64_t _reported_io_read_time = 0;
250
};
251
252
} // namespace doris