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 <cstddef> |
21 | | #include <memory> |
22 | | #include <set> |
23 | | |
24 | | #include "agent/be_exec_version_manager.h" |
25 | | #include "common/status.h" |
26 | | #include "core/block/block.h" |
27 | | #include "exprs/score_runtime.h" |
28 | | #include "exprs/vexpr.h" |
29 | | #include "io/io_common.h" |
30 | | #include "runtime/runtime_state.h" |
31 | | #include "storage/index/ann/ann_topn_runtime.h" |
32 | | #include "storage/olap_common.h" |
33 | | #include "storage/predicate/block_column_predicate.h" |
34 | | #include "storage/predicate/column_predicate.h" |
35 | | #include "storage/row_cursor.h" |
36 | | #include "storage/segment/row_ranges.h" |
37 | | #include "storage/segment/variant/variant_compaction_paths.h" |
38 | | #include "storage/tablet/tablet_schema.h" |
39 | | |
40 | | namespace doris { |
41 | | |
42 | | class ReadSchema; |
43 | | class ColumnPredicate; |
44 | | |
45 | | struct IteratorRowRef; |
46 | | |
47 | | class StorageReadOptions { |
48 | | public: |
49 | | // Every storage read needs a statistics sink. Deleting the default constructor keeps copied |
50 | | // options valid from creation; for example, SegmentIterator stores a copy and later |
51 | | // dereferences stats while reading pages. |
52 | | StorageReadOptions() = delete; |
53 | | |
54 | 6.51M | explicit StorageReadOptions(OlapReaderStatistics& stats_) noexcept : stats(&stats_) {} |
55 | | |
56 | | // Query reads use their RuntimeState; background reads without one use the newest version. |
57 | 17.6M | int get_be_exec_version() const { |
58 | 17.6M | return runtime_state != nullptr ? runtime_state->be_exec_version() |
59 | 17.6M | : BeExecVersionManager::get_newest_version(); |
60 | 17.6M | } |
61 | | |
62 | | struct KeyRange { |
63 | | KeyRange() |
64 | | : lower_key(nullptr), |
65 | | include_lower(false), |
66 | | upper_key(nullptr), |
67 | 0 | include_upper(false) {} |
68 | | |
69 | | KeyRange(const RowCursor* lower_key_, bool include_lower_, const RowCursor* upper_key_, |
70 | | bool include_upper_) |
71 | 3.70M | : lower_key(lower_key_), |
72 | 3.70M | include_lower(include_lower_), |
73 | 3.70M | upper_key(upper_key_), |
74 | 3.70M | include_upper(include_upper_) {} |
75 | | |
76 | | // the lower bound of the range, nullptr if not existed |
77 | | const RowCursor* lower_key = nullptr; |
78 | | // whether `lower_key` is included in the range |
79 | | bool include_lower; |
80 | | // the upper bound of the range, nullptr if not existed |
81 | | const RowCursor* upper_key = nullptr; |
82 | | // whether `upper_key` is included in the range |
83 | | bool include_upper; |
84 | | |
85 | 3.57M | uint64_t get_digest(uint64_t seed) const { |
86 | 3.58M | if (lower_key != nullptr) { |
87 | 3.58M | auto key_str = lower_key->to_string(); |
88 | 3.58M | seed = HashUtil::hash64(key_str.c_str(), key_str.size(), seed); |
89 | 3.58M | seed = HashUtil::hash64(&include_lower, sizeof(include_lower), seed); |
90 | 3.58M | } |
91 | | |
92 | 3.59M | if (upper_key != nullptr) { |
93 | 3.59M | auto key_str = upper_key->to_string(); |
94 | 3.59M | seed = HashUtil::hash64(key_str.c_str(), key_str.size(), seed); |
95 | 3.59M | seed = HashUtil::hash64(&include_upper, sizeof(include_upper), seed); |
96 | 3.59M | } |
97 | | |
98 | 3.57M | return seed; |
99 | 3.57M | } |
100 | | }; |
101 | | |
102 | | // reader's key ranges, empty if not existed. |
103 | | // used by short key index to filter row blocks |
104 | | std::vector<KeyRange> key_ranges; |
105 | | |
106 | | // For unique-key merge-on-write, the effect is similar to delete_conditions |
107 | | // that filters out rows that are deleted in realtime. |
108 | | // For a particular row, if delete_bitmap.contains(rowid) means that row is |
109 | | // marked deleted and invisible to user anymore. |
110 | | // segment_id -> roaring::Roaring* |
111 | | std::unordered_map<uint32_t, std::shared_ptr<roaring::Roaring>> delete_bitmap; |
112 | | |
113 | | std::shared_ptr<AndBlockColumnPredicate> delete_condition_predicates = |
114 | | AndBlockColumnPredicate::create_shared(); |
115 | | // reader's column predicate, nullptr if not existed |
116 | | // used to fiter rows in row block |
117 | | std::vector<std::shared_ptr<ColumnPredicate>> column_predicates; |
118 | | std::unordered_map<int32_t, std::shared_ptr<AndBlockColumnPredicate>> col_id_to_predicates; |
119 | | std::unordered_map<int32_t, std::vector<std::shared_ptr<const ColumnPredicate>>> |
120 | | del_predicates_for_zone_map; |
121 | | TPushAggOp::type push_down_agg_type_opt = TPushAggOp::NONE; |
122 | | // Non-key columns whose predicates were proven always true by the segment zone map and then |
123 | | // removed from column_predicates. SegmentIterator can skip reading these non-output columns, |
124 | | // or COUNT_ON_INDEX columns, because the column values no longer affect filtering or counting. |
125 | | std::set<uint32_t> zonemap_always_true_pred_cols; |
126 | | |
127 | | // Non-owning and initialized to a valid object by the constructor. |
128 | | OlapReaderStatistics* stats; |
129 | | bool use_page_cache = false; |
130 | | uint32_t block_row_max = 4096 - 32; // see https://github.com/apache/doris/pull/11816 |
131 | | // Effective adaptive batch size byte budget. |
132 | | size_t preferred_block_size_bytes = 8388608UL; |
133 | | |
134 | | // Whether the tablet schema this read targets materializes variant subcolumns as extracted |
135 | | // columns. A compaction read then takes them as flat leaves. |
136 | | bool tablet_has_extracted_variant_columns = false; |
137 | | // The compaction output schema's variant path layout; null outside a variant compaction. |
138 | | VariantCompactionPathsSPtr variant_compaction_paths; |
139 | | bool enable_unique_key_merge_on_write = false; |
140 | | std::vector<int> topn_filter_source_node_ids; |
141 | | // used for special optimization for query : ORDER BY key DESC LIMIT n |
142 | | bool read_orderby_key_reverse = false; |
143 | | // For rows with the same key, use ascending order (small-to-large) for tie-breakers. |
144 | | // For example, use lower rowset version / segment id first. |
145 | | bool use_insert_order_when_same = false; |
146 | | bool read_changelog = false; |
147 | | int changelog_tso_idx = -1; |
148 | | // columns for orderby keys |
149 | | std::vector<uint32_t>* read_orderby_key_columns = nullptr; |
150 | | io::IOContext io_ctx; |
151 | | VExprContextSPtrs common_expr_ctxs_push_down; |
152 | | const std::set<int32_t>* output_columns = nullptr; |
153 | | // Extra storage key columns that are included only to keep the scan schema |
154 | | // aligned with the storage key prefix. SegmentIterator can synthesize |
155 | | // placeholders only after proving predicates, delete conditions, and |
156 | | // expressions do not need their real values. |
157 | | std::set<ColumnId> extra_columns; |
158 | | // runtime state |
159 | | RuntimeState* runtime_state = nullptr; |
160 | | RowsetId rowset_id; |
161 | | Version version; |
162 | | TsoRange commit_tso; |
163 | | int64_t tablet_id = 0; |
164 | | // slots that cast may be eliminated in storage layer |
165 | | std::map<std::string, DataTypePtr> target_cast_type_for_variants; |
166 | | RowRanges row_ranges; |
167 | | |
168 | | // Per-segment row budget pushed down from the scanner (topn or general |
169 | | // limit). SegmentIterator applies it after predicate/common-expr filtering; |
170 | | // _can_opt_limit_reads() only decides whether the pre-filter read can also |
171 | | // be capped. 0 disables the optimization. |
172 | | size_t read_limit = 0; |
173 | | |
174 | | std::map<ColumnId, VExprContextSPtr> virtual_column_exprs; |
175 | | std::shared_ptr<segment_v2::AnnTopNRuntime> ann_topn_runtime; |
176 | | |
177 | | std::map<int32_t, TColumnAccessPaths> all_access_paths; |
178 | | std::map<int32_t, TColumnAccessPaths> predicate_access_paths; |
179 | | |
180 | | std::shared_ptr<ScoreRuntime> score_runtime; |
181 | | CollectionStatisticsPtr collection_statistics; |
182 | | |
183 | | uint64_t condition_cache_digest = 0; |
184 | | }; |
185 | | |
186 | | struct CompactionSampleInfo { |
187 | | int64_t bytes = 0; |
188 | | int64_t rows = 0; |
189 | | int64_t group_data_size = 0; |
190 | | int64_t null_count = 0; // Number of NULL cells in this column group |
191 | | }; |
192 | | |
193 | | struct BlockWithSameBit { |
194 | | Block* block; |
195 | | std::vector<bool>& same_bit; |
196 | | |
197 | 201 | bool empty() const { return block->rows() == 0; } |
198 | | }; |
199 | | |
200 | | class RowwiseIterator; |
201 | | using RowwiseIteratorUPtr = std::unique_ptr<RowwiseIterator>; |
202 | | class RowwiseIterator { |
203 | | public: |
204 | 4.14M | RowwiseIterator() = default; |
205 | 4.16M | virtual ~RowwiseIterator() = default; |
206 | | |
207 | | // Initialize this iterator and make it ready to read with |
208 | | // input options. |
209 | | // Input options may contain scan range in which this scan. |
210 | | // Return Status::OK() if init successfully, |
211 | | // Return other error otherwise |
212 | 0 | virtual Status init(const StorageReadOptions& opts) { |
213 | 0 | return Status::InternalError("to be implemented, current class: " + |
214 | 0 | demangle(typeid(*this).name())); |
215 | 0 | } |
216 | | |
217 | 0 | virtual Status init(const StorageReadOptions& opts, CompactionSampleInfo* sample_info) { |
218 | 0 | return Status::InternalError("should not reach here, current class: " + |
219 | 0 | demangle(typeid(*this).name())); |
220 | 0 | } |
221 | | |
222 | | // If there is any valid data, this function will load data |
223 | | // into input batch with Status::OK() returned |
224 | | // If there is no data to read, will return Status::EndOfFile. |
225 | | // If other error happens, other error code will be returned. |
226 | 0 | virtual Status next_batch(Block* block) { |
227 | 0 | return Status::InternalError("should not reach here, current class: " + |
228 | 0 | demangle(typeid(*this).name())); |
229 | 0 | } |
230 | | |
231 | 0 | virtual Status next_batch(BlockWithSameBit* block_with_same_bit) { |
232 | 0 | return Status::InternalError("should not reach here, current class: " + |
233 | 0 | demangle(typeid(*this).name())); |
234 | 0 | } |
235 | | |
236 | 0 | virtual Status next_batch(BlockView* block_view) { |
237 | 0 | return Status::InternalError("should not reach here, current class: " + |
238 | 0 | demangle(typeid(*this).name())); |
239 | 0 | } |
240 | | |
241 | 0 | virtual Status next_row(IteratorRowRef* ref) { |
242 | 0 | return Status::InternalError("should not reach here, current class: " + |
243 | 0 | demangle(typeid(*this).name())); |
244 | 0 | } |
245 | 0 | virtual Status unique_key_next_row(IteratorRowRef* ref) { |
246 | 0 | return Status::InternalError("should not reach here, current class: " + |
247 | 0 | demangle(typeid(*this).name())); |
248 | 0 | } |
249 | | |
250 | 0 | virtual bool is_merge_iterator() const { return false; } |
251 | | |
252 | | // return schema for this Iterator |
253 | | virtual const ReadSchema& schema() const = 0; |
254 | | |
255 | | // Return the data id such as segment id, used for keep the insert order when do |
256 | | // merge sort in priority queue |
257 | 26.0k | virtual uint64_t data_id() const { return 0; } |
258 | | |
259 | 5.59k | virtual void update_profile(RuntimeProfile* profile) {} |
260 | | // return rows merged count by iterator |
261 | 0 | virtual uint64_t merged_rows() const { return 0; } |
262 | | |
263 | | // return if it's an empty iterator |
264 | 1.40M | virtual bool empty() const { return false; } |
265 | | }; |
266 | | |
267 | | } // namespace doris |