1 /* 2 * Copyright (C) 2018 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_TABLE_H_ 18 #define SRC_TRACE_PROCESSOR_TABLE_H_ 19 20 #include <sqlite3.h> 21 22 #include <functional> 23 #include <memory> 24 #include <string> 25 #include <vector> 26 27 #include "perfetto/base/optional.h" 28 #include "src/trace_processor/query_constraints.h" 29 30 namespace perfetto { 31 namespace trace_processor { 32 33 class TraceStorage; 34 35 // Abstract base class representing a SQLite virtual table. Implements the 36 // common bookeeping required across all tables and allows subclasses to 37 // implement a friendlier API than that required by SQLite. 38 class Table : public sqlite3_vtab { 39 public: 40 using Factory = 41 std::function<std::unique_ptr<Table>(sqlite3*, const TraceStorage*)>; 42 43 // Allowed types for columns in a table. 44 enum ColumnType { 45 kString = 1, 46 kUint = 2, 47 kLong = 3, 48 kInt = 4, 49 kDouble = 5, 50 kUnknown = 6, 51 }; 52 53 // Describes a column of this table. 54 class Column { 55 public: 56 Column(size_t idx, std::string name, ColumnType type, bool hidden = false); 57 index()58 size_t index() const { return index_; } name()59 const std::string& name() const { return name_; } type()60 ColumnType type() const { return type_; } hidden()61 bool hidden() const { return hidden_; } 62 63 private: 64 size_t index_ = 0; 65 std::string name_; 66 ColumnType type_ = ColumnType::kString; 67 bool hidden_ = false; 68 }; 69 70 // When set it logs all BestIndex and Filter actions on the console. 71 static bool debug; 72 73 // Public for unique_ptr destructor calls. 74 virtual ~Table(); 75 76 // Abstract base class representing an SQLite Cursor. Presents a friendlier 77 // API for subclasses to implement. 78 class Cursor : public sqlite3_vtab_cursor { 79 public: 80 Cursor(Table* table); 81 virtual ~Cursor(); 82 83 // Methods to be implemented by derived table classes. 84 85 // Called to intialise the cursor with the constraints of the query. 86 virtual int Filter(const QueryConstraints& qc, sqlite3_value**) = 0; 87 88 // Called to forward the cursor to the next row in the table. 89 virtual int Next() = 0; 90 91 // Called to check if the cursor has reached eof. Column will be called iff 92 // this method returns true. 93 virtual int Eof() = 0; 94 95 // Used to extract the value from the column at index |N|. 96 virtual int Column(sqlite3_context* context, int N) = 0; 97 98 // Optional methods to implement. 99 virtual int RowId(sqlite3_int64*); 100 101 protected: 102 Cursor(Cursor&) = delete; 103 Cursor& operator=(const Cursor&) = delete; 104 105 Cursor(Cursor&&) noexcept = default; 106 Cursor& operator=(Cursor&&) = default; 107 108 private: 109 friend class Table; 110 111 Table* table_ = nullptr; 112 }; 113 114 // The schema of the table. Created by subclasses to allow the table class to 115 // do filtering and inform SQLite about the CREATE table statement. 116 class Schema { 117 public: 118 Schema(); 119 Schema(std::vector<Column>, std::vector<size_t> primary_keys); 120 121 // This class is explicitly copiable. 122 Schema(const Schema&); 123 Schema& operator=(const Schema& t); 124 125 std::string ToCreateTableStmt() const; 126 columns()127 const std::vector<Column>& columns() const { return columns_; } primary_keys()128 const std::vector<size_t> primary_keys() { return primary_keys_; } 129 130 private: 131 // The names and types of the columns of the table. 132 std::vector<Column> columns_; 133 134 // The primary keys of the table given by an offset into |columns|. 135 std::vector<size_t> primary_keys_; 136 }; 137 138 protected: 139 // Populated by a BestIndex call to allow subclasses to tweak SQLite's 140 // handling of sets of constraints. 141 struct BestIndexInfo { 142 bool order_by_consumed = false; 143 uint32_t estimated_cost = 0; 144 std::vector<bool> omit; 145 }; 146 147 struct TableDescriptor { 148 Table::Factory factory; 149 const TraceStorage* storage = nullptr; 150 std::string name; 151 sqlite3_module module = {}; 152 }; 153 154 Table(); 155 156 // Called by derived classes to register themselves with the SQLite db. 157 // |read_write| specifies whether the table can also be written to. 158 // |requires_args| should be true if the table requires arguments in order to 159 // be instantiated. 160 // Note: this function is inlined here because we use the TTable template to 161 // devirtualise the function calls. 162 template <typename TTable> 163 static void Register(sqlite3* db, 164 const TraceStorage* storage, 165 const std::string& table_name, 166 bool read_write = false, 167 bool requires_args = false) { 168 using TCursor = typename TTable::Cursor; 169 170 std::unique_ptr<TableDescriptor> desc(new TableDescriptor()); 171 desc->storage = storage; 172 desc->factory = GetFactory<TTable>(); 173 desc->name = table_name; 174 sqlite3_module* module = &desc->module; 175 memset(module, 0, sizeof(*module)); 176 177 auto create_fn = [](sqlite3* xdb, void* arg, int argc, 178 const char* const* argv, sqlite3_vtab** tab, char**) { 179 const TableDescriptor* xdesc = static_cast<const TableDescriptor*>(arg); 180 auto table = xdesc->factory(xdb, xdesc->storage); 181 table->name_ = xdesc->name; 182 183 auto opt_schema = table->Init(argc, argv); 184 if (!opt_schema.has_value()) { 185 PERFETTO_ELOG("Failed to create schema (table %s)", 186 xdesc->name.c_str()); 187 return SQLITE_ERROR; 188 } 189 190 const auto& schema = opt_schema.value(); 191 auto create_stmt = schema.ToCreateTableStmt(); 192 PERFETTO_DLOG("Create table statement: %s", create_stmt.c_str()); 193 194 int res = sqlite3_declare_vtab(xdb, create_stmt.c_str()); 195 if (res != SQLITE_OK) 196 return res; 197 198 // Freed in xDisconnect(). 199 table->schema_ = std::move(schema); 200 *tab = table.release(); 201 202 return SQLITE_OK; 203 }; 204 auto destroy_fn = [](sqlite3_vtab* t) { 205 delete static_cast<TTable*>(t); 206 return SQLITE_OK; 207 }; 208 209 module->xCreate = create_fn; 210 module->xConnect = create_fn; 211 module->xDisconnect = destroy_fn; 212 module->xDestroy = destroy_fn; 213 module->xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) { 214 return static_cast<TTable*>(t)->OpenInternal(c); 215 }; 216 module->xClose = [](sqlite3_vtab_cursor* c) { 217 delete static_cast<TCursor*>(c); 218 return SQLITE_OK; 219 }; 220 module->xBestIndex = [](sqlite3_vtab* t, sqlite3_index_info* i) { 221 return static_cast<TTable*>(t)->BestIndexInternal(i); 222 }; 223 module->xFilter = [](sqlite3_vtab_cursor* c, int i, const char* s, int a, 224 sqlite3_value** v) { 225 const auto& qc = 226 static_cast<Cursor*>(c)->table_->ParseConstraints(i, s, a); 227 return static_cast<TCursor*>(c)->Filter(qc, v); 228 }; 229 module->xNext = [](sqlite3_vtab_cursor* c) { 230 return static_cast<TCursor*>(c)->Next(); 231 }; 232 module->xEof = [](sqlite3_vtab_cursor* c) { 233 return static_cast<TCursor*>(c)->Eof(); 234 }; 235 module->xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) { 236 return static_cast<TCursor*>(c)->Column(a, b); 237 }; 238 module->xRowid = [](sqlite3_vtab_cursor* c, sqlite3_int64* r) { 239 return static_cast<TCursor*>(c)->RowId(r); 240 }; 241 module->xFindFunction = 242 [](sqlite3_vtab* t, int, const char* name, 243 void (**fn)(sqlite3_context*, int, sqlite3_value**), void** args) { 244 return static_cast<TTable*>(t)->FindFunction(name, fn, args); 245 }; 246 247 if (read_write) { 248 module->xUpdate = [](sqlite3_vtab* t, int a, sqlite3_value** v, 249 sqlite3_int64* r) { 250 return static_cast<TTable*>(t)->Update(a, v, r); 251 }; 252 } 253 254 int res = sqlite3_create_module_v2( 255 db, table_name.c_str(), module, desc.release(), 256 [](void* arg) { delete static_cast<TableDescriptor*>(arg); }); 257 PERFETTO_CHECK(res == SQLITE_OK); 258 259 // Register virtual tables into an internal 'perfetto_tables' table. This is 260 // used for iterating through all the tables during a database export. Note 261 // that virtual tables requiring arguments aren't registered because they 262 // can't be automatically instantiated for exporting. 263 if (!requires_args) { 264 char* insert_sql = sqlite3_mprintf( 265 "INSERT INTO perfetto_tables(name) VALUES('%q')", table_name.c_str()); 266 char* error = nullptr; 267 sqlite3_exec(db, insert_sql, 0, 0, &error); 268 sqlite3_free(insert_sql); 269 if (error) { 270 PERFETTO_ELOG("Error registering table: %s", error); 271 sqlite3_free(error); 272 } 273 } 274 } 275 276 // Methods to be implemented by derived table classes. 277 virtual base::Optional<Schema> Init(int argc, const char* const* argv) = 0; 278 virtual std::unique_ptr<Cursor> CreateCursor() = 0; 279 virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0; 280 281 // Optional metods to implement. 282 using FindFunctionFn = void (**)(sqlite3_context*, int, sqlite3_value**); 283 virtual int FindFunction(const char* name, FindFunctionFn fn, void** args); 284 285 // At registration time, the function should also pass true for |read_write|. 286 virtual int Update(int, sqlite3_value**, sqlite3_int64*); 287 SetErrorMessage(char * error)288 void SetErrorMessage(char* error) { 289 sqlite3_free(zErrMsg); 290 zErrMsg = error; 291 } 292 schema()293 const Schema& schema() const { return schema_; } name()294 const std::string& name() const { return name_; } 295 296 private: 297 template <typename TableType> GetFactory()298 static Factory GetFactory() { 299 return [](sqlite3* db, const TraceStorage* storage) { 300 return std::unique_ptr<Table>(new TableType(db, storage)); 301 }; 302 } 303 304 static void RegisterInternal(sqlite3* db, 305 const TraceStorage*, 306 const std::string& name, 307 bool read_write, 308 bool requires_args, 309 Factory); 310 311 const QueryConstraints& ParseConstraints(int idxNum, 312 const char* idxStr, 313 int argc); 314 315 // Overriden functions from sqlite3_vtab. 316 int OpenInternal(sqlite3_vtab_cursor**); 317 int BestIndexInternal(sqlite3_index_info*); 318 319 Table(const Table&) = delete; 320 Table& operator=(const Table&) = delete; 321 322 std::string name_; 323 Schema schema_; 324 325 QueryConstraints qc_cache_; 326 int qc_hash_ = 0; 327 int best_index_num_ = 0; 328 }; 329 330 } // namespace trace_processor 331 } // namespace perfetto 332 333 #endif // SRC_TRACE_PROCESSOR_TABLE_H_ 334