xref: /aosp_15_r20/external/perfetto/src/trace_processor/db/table.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_TRACE_PROCESSOR_DB_TABLE_H_
18 #define SRC_TRACE_PROCESSOR_DB_TABLE_H_
19 
20 #include <algorithm>
21 #include <cstdint>
22 #include <memory>
23 #include <optional>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 #include "perfetto/base/logging.h"
29 #include "perfetto/base/status.h"
30 #include "perfetto/trace_processor/basic_types.h"
31 #include "perfetto/trace_processor/ref_counted.h"
32 #include "src/trace_processor/containers/row_map.h"
33 #include "src/trace_processor/containers/string_pool.h"
34 #include "src/trace_processor/db/column.h"
35 #include "src/trace_processor/db/column/data_layer.h"
36 #include "src/trace_processor/db/column/overlay_layer.h"
37 #include "src/trace_processor/db/column/storage_layer.h"
38 #include "src/trace_processor/db/column/types.h"
39 #include "src/trace_processor/db/column_storage_overlay.h"
40 
41 namespace perfetto::trace_processor {
42 
43 namespace {
44 
45 using OrderedIndices = column::DataLayerChain::OrderedIndices;
46 
OrderedIndicesFromIndex(const std::vector<uint32_t> & index)47 OrderedIndices OrderedIndicesFromIndex(const std::vector<uint32_t>& index) {
48   OrderedIndices o;
49   o.data = index.data();
50   o.size = static_cast<uint32_t>(index.size());
51   return o;
52 }
53 
54 }  // namespace
55 
56 // Represents a table of data with named, strongly typed columns.
57 class Table {
58  public:
59   // Iterator over the rows of the table.
60   class Iterator {
61    public:
Iterator(const Table * table)62     explicit Iterator(const Table* table) : table_(table) {
63       its_.reserve(table->overlays().size());
64       for (const auto& rm : table->overlays()) {
65         its_.emplace_back(rm.IterateRows());
66       }
67     }
68 
69     // Creates an iterator which iterates over |table| by first creating
70     // overlays by Applying |apply| to the existing overlays and using the
71     // indices there for iteration.
Iterator(const Table * table,RowMap apply)72     explicit Iterator(const Table* table, RowMap apply) : table_(table) {
73       overlays_.reserve(table->overlays().size());
74       its_.reserve(table->overlays().size());
75       for (const auto& rm : table->overlays()) {
76         overlays_.emplace_back(rm.SelectRows(apply));
77         its_.emplace_back(overlays_.back().IterateRows());
78       }
79     }
80 
81     Iterator(Iterator&&) noexcept = default;
82     Iterator& operator=(Iterator&&) = default;
83 
84     Iterator(const Iterator&) = delete;
85     Iterator& operator=(const Iterator&) = delete;
86 
87     // Advances the iterator to the next row of the table.
88     Iterator& operator++() {
89       for (auto& it : its_) {
90         it.Next();
91       }
92       return *this;
93     }
94 
95     // Returns whether the row the iterator is pointing at is valid.
96     explicit operator bool() const { return bool(its_[0]); }
97 
98     // Returns the value at the current row for column |col_idx|.
Get(uint32_t col_idx)99     SqlValue Get(uint32_t col_idx) const {
100       const auto& col = table_->columns_[col_idx];
101       return col.GetAtIdx(its_[col.overlay_index()].index());
102     }
103 
104     // Returns the storage index for the current row for column |col_idx|.
StorageIndexForColumn(uint32_t col_idx)105     uint32_t StorageIndexForColumn(uint32_t col_idx) const {
106       const auto& col = table_->columns_[col_idx];
107       return its_[col.overlay_index()].index();
108     }
109 
110     // Returns the storage index for the last overlay.
StorageIndexForLastOverlay()111     uint32_t StorageIndexForLastOverlay() const { return its_.back().index(); }
112 
113    private:
114     const Table* table_ = nullptr;
115     std::vector<ColumnStorageOverlay> overlays_;
116     std::vector<ColumnStorageOverlay::Iterator> its_;
117   };
118 
119   // Helper class storing the schema of the table. This allows decisions to be
120   // made about operations on the table without materializing the table - this
121   // may be expensive for dynamically computed tables.
122   //
123   // Subclasses of Table usually provide a method (named Schema()) to statically
124   // generate an instance of this class.
125   struct Schema {
126     struct Column {
127       std::string name;
128       SqlValue::Type type;
129       bool is_id;
130       bool is_sorted;
131       bool is_hidden;
132       bool is_set_id;
133     };
134     std::vector<Column> columns;
135   };
136 
137   virtual ~Table();
138 
139   // We explicitly define the move constructor here because we need to update
140   // the Table pointer in each column in the table.
Table(Table && other)141   Table(Table&& other) noexcept { *this = std::move(other); }
142   Table& operator=(Table&& other) noexcept;
143 
144   // Filters and sorts the tables with the arguments specified, returning the
145   // result as a RowMap.
146   RowMap QueryToRowMap(const Query&) const;
147 
148   // Applies the RowMap |rm| onto this table and returns an iterator over the
149   // resulting rows.
QueryToIterator(const Query & q)150   Iterator QueryToIterator(const Query& q) const {
151     return ApplyAndIterateRows(QueryToRowMap(q));
152   }
153 
154   // Do not add any further uses.
155   // TODO(lalitm): make this private.
ApplyAndIterateRows(RowMap rm)156   Iterator ApplyAndIterateRows(RowMap rm) const {
157     return Iterator(this, std::move(rm));
158   }
159 
GetIndex(const std::vector<uint32_t> & cols)160   std::optional<OrderedIndices> GetIndex(
161       const std::vector<uint32_t>& cols) const {
162     for (const auto& idx : indexes_) {
163       if (cols.size() > idx.columns.size()) {
164         continue;
165       }
166       if (std::equal(cols.begin(), cols.end(), idx.columns.begin())) {
167         return OrderedIndicesFromIndex(idx.index);
168       }
169     }
170     return std::nullopt;
171   }
172 
173   // Adds an index onto column.
174   // Returns an error if index already exists and `!replace`.
175   base::Status CreateIndex(const std::string& name,
176                            std::vector<uint32_t> col_idxs,
177                            bool replace);
178 
179   // Removes index from the table.
180   // Returns an error if index doesn't exist.
181   base::Status DropIndex(const std::string& name);
182 
183   // Sorts the table using the specified order by constraints.
184   Table Sort(const std::vector<Order>&) const;
185 
186   // Returns an iterator over the rows in this table.
IterateRows()187   Iterator IterateRows() const { return Iterator(this); }
188 
189   // Creates a copy of this table.
190   Table Copy() const;
191 
192   // Looks for a column in a table.
193   // TODO(mayzner): This is not a long term function, it should be used with
194   // caution.
ColumnIdxFromName(const std::string & col_name)195   std::optional<uint32_t> ColumnIdxFromName(const std::string& col_name) const {
196     auto x = std::find_if(
197         columns_.begin(), columns_.end(),
198         [col_name](const ColumnLegacy& col) { return col_name == col.name(); });
199     return x == columns_.end() ? std::nullopt
200                                : std::make_optional(x->index_in_table());
201   }
202 
row_count()203   uint32_t row_count() const { return row_count_; }
columns()204   const std::vector<ColumnLegacy>& columns() const { return columns_; }
string_pool()205   StringPool* string_pool() const { return string_pool_; }
206 
storage_layers()207   const std::vector<RefPtr<column::StorageLayer>>& storage_layers() const {
208     return storage_layers_;
209   }
null_layers()210   const std::vector<RefPtr<column::OverlayLayer>>& null_layers() const {
211     return null_layers_;
212   }
213 
214  protected:
215   Table(StringPool*,
216         uint32_t row_count,
217         std::vector<ColumnLegacy>,
218         std::vector<ColumnStorageOverlay>);
219 
CopyLastInsertFrom(const std::vector<ColumnStorageOverlay> & overlays)220   void CopyLastInsertFrom(const std::vector<ColumnStorageOverlay>& overlays) {
221     PERFETTO_DCHECK(overlays.size() <= overlays_.size());
222 
223     // Add the last inserted row in each of the parent row maps to the
224     // corresponding row map in the child.
225     for (uint32_t i = 0; i < overlays.size(); ++i) {
226       const ColumnStorageOverlay& other = overlays[i];
227       overlays_[i].Insert(other.Get(other.size() - 1));
228     }
229   }
230 
IncrementRowCountAndAddToLastOverlay()231   void IncrementRowCountAndAddToLastOverlay() {
232     // Also add the index of the new row to the identity row map and increment
233     // the size.
234     overlays_.back().Insert(row_count_++);
235   }
236 
237   void OnConstructionCompleted(
238       std::vector<RefPtr<column::StorageLayer>> storage_layers,
239       std::vector<RefPtr<column::OverlayLayer>> null_layers,
240       std::vector<RefPtr<column::OverlayLayer>> overlay_layers);
241 
GetColumn(uint32_t index)242   ColumnLegacy* GetColumn(uint32_t index) { return &columns_[index]; }
243 
overlays()244   const std::vector<ColumnStorageOverlay>& overlays() const {
245     return overlays_;
246   }
247 
248  private:
249   friend class ColumnLegacy;
250   friend class QueryExecutor;
251 
252   struct ColumnIndex {
253     std::string name;
254     std::vector<uint32_t> columns;
255     std::vector<uint32_t> index;
256   };
257 
258   bool HasNullOrOverlayLayer(uint32_t col_idx) const;
259 
260   void CreateChains() const;
261 
262   Table CopyExceptOverlays() const;
263 
264   void ApplyDistinct(const Query&, RowMap*) const;
265   void ApplySort(const Query&, RowMap*) const;
266 
267   RowMap TryApplyIndex(const std::vector<Constraint>&,
268                        uint32_t& cs_offset) const;
269   RowMap ApplyIdJoinConstraints(const std::vector<Constraint>&,
270                                 uint32_t& cs_offset) const;
271 
ChainForColumn(uint32_t col_idx)272   const column::DataLayerChain& ChainForColumn(uint32_t col_idx) const {
273     return *chains_[col_idx];
274   }
275 
276   StringPool* string_pool_ = nullptr;
277   uint32_t row_count_ = 0;
278   std::vector<ColumnStorageOverlay> overlays_;
279   std::vector<ColumnLegacy> columns_;
280 
281   std::vector<RefPtr<column::StorageLayer>> storage_layers_;
282   std::vector<RefPtr<column::OverlayLayer>> null_layers_;
283   std::vector<RefPtr<column::OverlayLayer>> overlay_layers_;
284   mutable std::vector<std::unique_ptr<column::DataLayerChain>> chains_;
285 
286   std::vector<ColumnIndex> indexes_;
287 };
288 
289 }  // namespace perfetto::trace_processor
290 
291 #endif  // SRC_TRACE_PROCESSOR_DB_TABLE_H_
292