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 explicit 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_].index()); 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 // Extends the table with a new column called |name| with data |sv|. 138 template <typename T> ExtendWithColumn(const char * name,std::unique_ptr<NullableVector<T>> sv,uint32_t flags)139 Table ExtendWithColumn(const char* name, 140 std::unique_ptr<NullableVector<T>> sv, 141 uint32_t flags) const { 142 PERFETTO_CHECK(sv->size() == row_count_); 143 uint32_t size = sv->size(); 144 uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size()); 145 Table ret = Copy(); 146 ret.columns_.push_back(Column::WithOwnedStorage( 147 name, std::move(sv), flags, &ret, GetColumnCount(), row_map_count)); 148 ret.row_maps_.emplace_back(RowMap(0, size)); 149 return ret; 150 } 151 152 // Extends the table with a new column called |name| with data |sv|. 153 template <typename T> ExtendWithColumn(const char * name,NullableVector<T> * sv,uint32_t flags)154 Table ExtendWithColumn(const char* name, 155 NullableVector<T>* sv, 156 uint32_t flags) const { 157 PERFETTO_CHECK(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( 162 Column(name, 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 198 // Creates a copy of this table. 199 Table Copy() const; 200 row_count()201 uint32_t row_count() const { return row_count_; } row_maps()202 const std::vector<RowMap>& row_maps() const { return row_maps_; } 203 204 protected: 205 Table(StringPool* pool, const Table* parent); 206 207 std::vector<RowMap> row_maps_; 208 std::vector<Column> columns_; 209 uint32_t row_count_ = 0; 210 211 StringPool* string_pool_ = nullptr; 212 213 private: 214 friend class Column; 215 216 Table CopyExceptRowMaps() const; 217 }; 218 219 } // namespace trace_processor 220 } // namespace perfetto 221 222 #endif // SRC_TRACE_PROCESSOR_DB_TABLE_H_ 223