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