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