• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdint.h>
21 
22 #include <limits>
23 #include <numeric>
24 #include <vector>
25 
26 #include "perfetto/base/logging.h"
27 #include "perfetto/ext/base/optional.h"
28 #include "src/trace_processor/containers/string_pool.h"
29 #include "src/trace_processor/db/column.h"
30 #include "src/trace_processor/db/typed_column.h"
31 
32 namespace perfetto {
33 namespace trace_processor {
34 
35 // Represents a table of data with named, strongly typed columns.
36 class Table {
37  public:
38   // Iterator over the rows of the table.
39   class Iterator {
40    public:
Iterator(const Table * table)41     Iterator(const Table* table) : table_(table) {
42       for (const auto& rm : table->row_maps()) {
43         its_.emplace_back(rm.IterateRows());
44       }
45     }
46 
47     Iterator(Iterator&&) noexcept = default;
48     Iterator& operator=(Iterator&&) = default;
49 
50     // Advances the iterator to the next row of the table.
Next()51     void Next() {
52       for (auto& it : its_) {
53         it.Next();
54       }
55     }
56 
57     // Returns whether the row the iterator is pointing at is valid.
58     operator bool() const { return its_[0]; }
59 
60     // Returns the value at the current row for column |col_idx|.
Get(uint32_t col_idx)61     SqlValue Get(uint32_t col_idx) const {
62       const auto& col = table_->columns_[col_idx];
63       return col.GetAtIdx(its_[col.row_map_idx_].row());
64     }
65 
66    private:
67     Iterator(const Iterator&) = delete;
68     Iterator& operator=(const Iterator&) = delete;
69 
70     const Table* table_ = nullptr;
71     std::vector<RowMap::Iterator> its_;
72   };
73 
74   // Helper class storing the schema of the table. This allows decisions to be
75   // made about operations on the table without materializing the table - this
76   // may be expensive for dynamically computed tables.
77   //
78   // Subclasses of Table usually provide a method (named Schema()) to statically
79   // generate an instance of this class.
80   struct Schema {
81     struct Column {
82       std::string name;
83       SqlValue::Type type;
84       bool is_id;
85       bool is_sorted;
86       bool is_hidden;
87     };
88     std::vector<Column> columns;
89   };
90 
91   Table();
92   virtual ~Table();
93 
94   // We explicitly define the move constructor here because we need to update
95   // the Table pointer in each column in the table.
Table(Table && other)96   Table(Table&& other) noexcept { *this = std::move(other); }
97   Table& operator=(Table&& other) noexcept;
98 
99   // Filters the Table using the specified filter constraints.
100   Table Filter(
101       const std::vector<Constraint>& cs,
102       RowMap::OptimizeFor optimize_for = RowMap::OptimizeFor::kMemory) const {
103     return Apply(FilterToRowMap(cs, optimize_for));
104   }
105 
106   // Filters the Table using the specified filter constraints optionally
107   // specifying what the returned RowMap should optimize for.
108   // Returns a RowMap which, if applied to the table, would contain the rows
109   // post filter.
110   RowMap FilterToRowMap(
111       const std::vector<Constraint>& cs,
112       RowMap::OptimizeFor optimize_for = RowMap::OptimizeFor::kMemory) const {
113     RowMap rm(0, row_count_, optimize_for);
114     for (const Constraint& c : cs) {
115       columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
116     }
117     return rm;
118   }
119 
120   // Applies the given RowMap to the current table by picking out the rows
121   // specified in the RowMap to be present in the output table.
122   // Note: the RowMap should not reorder this table; this is guaranteed if the
123   // passed RowMap is generated using |FilterToRowMap|.
Apply(RowMap rm)124   Table Apply(RowMap rm) const {
125     Table table = CopyExceptRowMaps();
126     table.row_count_ = rm.size();
127     for (const RowMap& map : row_maps_) {
128       table.row_maps_.emplace_back(map.SelectRows(rm));
129       PERFETTO_DCHECK(table.row_maps_.back().size() == table.row_count());
130     }
131     return table;
132   }
133 
134   // Sorts the Table using the specified order by constraints.
135   Table Sort(const std::vector<Order>& od) const;
136 
137   // Joins |this| table with the |other| table using the values of column |left|
138   // of |this| table to lookup the row in |right| column of the |other| table.
139   //
140   // Concretely, for each row in the returned table we lookup the value of
141   // |left| in |right|. The found row is used as the values for |other|'s
142   // columns in the returned table.
143   //
144   // This means we obtain the following invariants:
145   //  1. this->size() == ret->size()
146   //  2. this->Rows()[i].Get(j) == ret->Rows()[i].Get(j)
147   //
148   // It also means there are few restrictions on the data in |left| and |right|:
149   //  * |left| is not allowed to have any nulls.
150   //  * |left|'s values must exist in |right|
151   Table LookupJoin(JoinKey left, const Table& other, JoinKey right);
152 
153   // Extends the table with a new column called |name| with data |sv|.
154   template <typename T>
ExtendWithColumn(const char * name,std::unique_ptr<NullableVector<T>> sv,uint32_t flags)155   Table ExtendWithColumn(const char* name,
156                          std::unique_ptr<NullableVector<T>> sv,
157                          uint32_t flags) const {
158     PERFETTO_CHECK(sv->size() == row_count_);
159     uint32_t size = sv->size();
160     uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
161     Table ret = Copy();
162     ret.columns_.push_back(Column::WithOwnedStorage(
163         name, std::move(sv), flags, &ret, GetColumnCount(), row_map_count));
164     ret.row_maps_.emplace_back(RowMap(0, size));
165     return ret;
166   }
167 
168   // Extends the table with a new column called |name| with data |sv|.
169   template <typename T>
ExtendWithColumn(const char * name,NullableVector<T> * sv,uint32_t flags)170   Table ExtendWithColumn(const char* name,
171                          NullableVector<T>* sv,
172                          uint32_t flags) const {
173     PERFETTO_CHECK(sv->size() == row_count_);
174     uint32_t size = sv->size();
175     uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
176     Table ret = Copy();
177     ret.columns_.push_back(
178         Column(name, sv, flags, &ret, GetColumnCount(), row_map_count));
179     ret.row_maps_.emplace_back(RowMap(0, size));
180     return ret;
181   }
182 
183   // Returns the column at index |idx| in the Table.
GetColumn(uint32_t idx)184   const Column& GetColumn(uint32_t idx) const { return columns_[idx]; }
185 
186   // Returns the column with the given name or nullptr otherwise.
GetColumnByName(const char * name)187   const Column* GetColumnByName(const char* name) const {
188     auto it = std::find_if(
189         columns_.begin(), columns_.end(),
190         [name](const Column& col) { return strcmp(col.name(), name) == 0; });
191     if (it == columns_.end())
192       return nullptr;
193     return &*it;
194   }
195 
196   template <typename T>
GetTypedColumnByName(const char * name)197   const TypedColumn<T>& GetTypedColumnByName(const char* name) const {
198     return *TypedColumn<T>::FromColumn(GetColumnByName(name));
199   }
200 
201   template <typename T>
GetIdColumnByName(const char * name)202   const IdColumn<T>& GetIdColumnByName(const char* name) const {
203     return *IdColumn<T>::FromColumn(GetColumnByName(name));
204   }
205 
206   // Returns the number of columns in the Table.
GetColumnCount()207   uint32_t GetColumnCount() const {
208     return static_cast<uint32_t>(columns_.size());
209   }
210 
211   // Returns an iterator into the Table.
IterateRows()212   Iterator IterateRows() const { return Iterator(this); }
213 
214   // Creates a copy of this table.
215   Table Copy() const;
216 
row_count()217   uint32_t row_count() const { return row_count_; }
row_maps()218   const std::vector<RowMap>& row_maps() const { return row_maps_; }
219 
220  protected:
221   Table(StringPool* pool, const Table* parent);
222 
223   std::vector<RowMap> row_maps_;
224   std::vector<Column> columns_;
225   uint32_t row_count_ = 0;
226 
227   StringPool* string_pool_ = nullptr;
228 
229  private:
230   friend class Column;
231 
232   Table CopyExceptRowMaps() const;
233 };
234 
235 }  // namespace trace_processor
236 }  // namespace perfetto
237 
238 #endif  // SRC_TRACE_PROCESSOR_DB_TABLE_H_
239