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