• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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