• 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   template <typename T>
ExtendWithColumn(const char * name,std::unique_ptr<NullableVector<T>> sv,uint32_t flags)154   Table ExtendWithColumn(const char* name,
155                          std::unique_ptr<NullableVector<T>> sv,
156                          uint32_t flags) const {
157     PERFETTO_DCHECK(sv->size() == row_count_);
158     uint32_t size = sv->size();
159     uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
160     Table ret = Copy();
161     ret.columns_.push_back(Column::WithOwnedStorage(
162         name, std::move(sv), flags, &ret, GetColumnCount(), row_map_count));
163     ret.row_maps_.emplace_back(RowMap(0, size));
164     return ret;
165   }
166 
167   // Returns the column at index |idx| in the Table.
GetColumn(uint32_t idx)168   const Column& GetColumn(uint32_t idx) const { return columns_[idx]; }
169 
170   // Returns the column with the given name or nullptr otherwise.
GetColumnByName(const char * name)171   const Column* GetColumnByName(const char* name) const {
172     auto it = std::find_if(
173         columns_.begin(), columns_.end(),
174         [name](const Column& col) { return strcmp(col.name(), name) == 0; });
175     if (it == columns_.end())
176       return nullptr;
177     return &*it;
178   }
179 
180   template <typename T>
GetTypedColumnByName(const char * name)181   const TypedColumn<T>* GetTypedColumnByName(const char* name) const {
182     return TypedColumn<T>::FromColumn(GetColumnByName(name));
183   }
184 
185   template <typename T>
GetIdColumnByName(const char * name)186   const IdColumn<T>* GetIdColumnByName(const char* name) const {
187     return IdColumn<T>::FromColumn(GetColumnByName(name));
188   }
189 
190   // Returns the number of columns in the Table.
GetColumnCount()191   uint32_t GetColumnCount() const {
192     return static_cast<uint32_t>(columns_.size());
193   }
194 
195   // Returns an iterator into the Table.
IterateRows()196   Iterator IterateRows() const { return Iterator(this); }
197 
row_count()198   uint32_t row_count() const { return row_count_; }
row_maps()199   const std::vector<RowMap>& row_maps() const { return row_maps_; }
200 
201  protected:
202   Table(StringPool* pool, const Table* parent);
203 
204   std::vector<RowMap> row_maps_;
205   std::vector<Column> columns_;
206   uint32_t row_count_ = 0;
207 
208   StringPool* string_pool_ = nullptr;
209 
210  private:
211   friend class Column;
212 
213   Table Copy() const;
214   Table CopyExceptRowMaps() const;
215 };
216 
217 }  // namespace trace_processor
218 }  // namespace perfetto
219 
220 #endif  // SRC_TRACE_PROCESSOR_DB_TABLE_H_
221