• 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_SQLITE_SQLITE_TABLE_H_
18 #define SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
19 
20 #include <sqlite3.h>
21 
22 #include <functional>
23 #include <limits>
24 #include <memory>
25 #include <string>
26 #include <vector>
27 
28 #include "perfetto/ext/base/optional.h"
29 #include "perfetto/ext/base/utils.h"
30 #include "perfetto/trace_processor/basic_types.h"
31 #include "perfetto/trace_processor/status.h"
32 #include "src/trace_processor/sqlite/query_constraints.h"
33 
34 namespace perfetto {
35 namespace trace_processor {
36 
37 class TraceStorage;
38 
39 // Abstract base class representing a SQLite virtual table. Implements the
40 // common bookeeping required across all tables and allows subclasses to
41 // implement a friendlier API than that required by SQLite.
42 class SqliteTable : public sqlite3_vtab {
43  public:
44   template <typename Context>
45   using Factory =
46       std::function<std::unique_ptr<SqliteTable>(sqlite3*, Context)>;
47 
48   // Describes a column of this table.
49   class Column {
50    public:
51     Column(size_t idx,
52            std::string name,
53            SqlValue::Type type,
54            bool hidden = false);
55 
index()56     size_t index() const { return index_; }
name()57     const std::string& name() const { return name_; }
type()58     SqlValue::Type type() const { return type_; }
59 
hidden()60     bool hidden() const { return hidden_; }
set_hidden(bool hidden)61     void set_hidden(bool hidden) { hidden_ = hidden; }
62 
63    private:
64     size_t index_ = 0;
65     std::string name_;
66     SqlValue::Type type_ = SqlValue::Type::kNull;
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 ~SqliteTable();
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     // Enum for the history of calls to Filter.
81     enum class FilterHistory : uint32_t {
82       // Indicates that constraint set passed is the different to the
83       // previous Filter call.
84       kDifferent = 0,
85 
86       // Indicates that the constraint set passed is the same as the previous
87       // Filter call.
88       // This can be useful for subclasses to perform optimizations on repeated
89       // nested subqueries.
90       kSame = 1,
91     };
92 
93     Cursor(SqliteTable* table);
94     virtual ~Cursor();
95 
96     // Methods to be implemented by derived table classes.
97 
98     // Called to intialise the cursor with the constraints of the query.
99     virtual int Filter(const QueryConstraints& qc,
100                        sqlite3_value**,
101                        FilterHistory) = 0;
102 
103     // Called to forward the cursor to the next row in the table.
104     virtual int Next() = 0;
105 
106     // Called to check if the cursor has reached eof. Column will be called iff
107     // this method returns true.
108     virtual int Eof() = 0;
109 
110     // Used to extract the value from the column at index |N|.
111     virtual int Column(sqlite3_context* context, int N) = 0;
112 
113     // Optional methods to implement.
114     virtual int RowId(sqlite3_int64*);
115 
116    protected:
117     Cursor(Cursor&) = delete;
118     Cursor& operator=(const Cursor&) = delete;
119 
120     Cursor(Cursor&&) noexcept = default;
121     Cursor& operator=(Cursor&&) = default;
122 
123    private:
124     friend class SqliteTable;
125 
126     SqliteTable* table_ = nullptr;
127   };
128 
129   // The schema of the table. Created by subclasses to allow the table class to
130   // do filtering and inform SQLite about the CREATE table statement.
131   class Schema {
132    public:
133     Schema();
134     Schema(std::vector<Column>, std::vector<size_t> primary_keys);
135 
136     // This class is explicitly copiable.
137     Schema(const Schema&);
138     Schema& operator=(const Schema& t);
139 
140     std::string ToCreateTableStmt() const;
141 
columns()142     const std::vector<Column>& columns() const { return columns_; }
mutable_columns()143     std::vector<Column>* mutable_columns() { return &columns_; }
144 
primary_keys()145     const std::vector<size_t> primary_keys() { return primary_keys_; }
146 
147    private:
148     // The names and types of the columns of the table.
149     std::vector<Column> columns_;
150 
151     // The primary keys of the table given by an offset into |columns|.
152     std::vector<size_t> primary_keys_;
153   };
154 
155  protected:
156   // Populated by a BestIndex call to allow subclasses to tweak SQLite's
157   // handling of sets of constraints.
158   struct BestIndexInfo {
159     // Contains bools which indicate whether SQLite should omit double checking
160     // the constraint at that index.
161     //
162     // If there are no constraints, SQLite will be told it can omit checking for
163     // the whole query.
164     std::vector<bool> sqlite_omit_constraint;
165 
166     // Indicates that SQLite should not double check the result of the order by
167     // clause.
168     //
169     // If there are no order by clauses, this value will be ignored and SQLite
170     // will be told that it can omit double checking (i.e. this value will
171     // implicitly be taken to be true).
172     bool sqlite_omit_order_by = false;
173 
174     // Stores the estimated cost of this query.
175     double estimated_cost = 0;
176 
177     // Estimated row count.
178     int64_t estimated_rows = 0;
179   };
180 
181   template <typename Context>
182   struct TableDescriptor {
183     SqliteTable::Factory<Context> factory;
184     Context context;
185     std::string name;
186     sqlite3_module module = {};
187   };
188 
189   SqliteTable();
190 
191   // Called by derived classes to register themselves with the SQLite db.
192   // |read_write| specifies whether the table can also be written to.
193   // |requires_args| should be true if the table requires arguments in order to
194   // be instantiated.
195   // Note: this function is inlined here because we use the TTable template to
196   // devirtualise the function calls.
197   template <typename TTable, typename Context = const TraceStorage*>
198   static void Register(sqlite3* db,
199                        Context ctx,
200                        const std::string& table_name,
201                        bool read_write = false,
202                        bool requires_args = false) {
203     using TCursor = typename TTable::Cursor;
204 
205     std::unique_ptr<TableDescriptor<Context>> desc(
206         new TableDescriptor<Context>());
207     desc->context = std::move(ctx);
208     desc->factory = GetFactory<TTable, Context>();
209     desc->name = table_name;
210     sqlite3_module* module = &desc->module;
211     memset(module, 0, sizeof(*module));
212 
213     auto create_fn = [](sqlite3* xdb, void* arg, int argc,
214                         const char* const* argv, sqlite3_vtab** tab,
215                         char** pzErr) {
216       auto* xdesc = static_cast<TableDescriptor<Context>*>(arg);
217       auto table = xdesc->factory(xdb, std::move(xdesc->context));
218       table->name_ = xdesc->name;
219 
220       Schema schema;
221       util::Status status = table->Init(argc, argv, &schema);
222       if (!status.ok()) {
223         *pzErr = sqlite3_mprintf("%s", status.c_message());
224         return SQLITE_ERROR;
225       }
226 
227       auto create_stmt = schema.ToCreateTableStmt();
228       PERFETTO_DLOG("Create table statement: %s", create_stmt.c_str());
229 
230       int res = sqlite3_declare_vtab(xdb, create_stmt.c_str());
231       if (res != SQLITE_OK)
232         return res;
233 
234       // Freed in xDisconnect().
235       table->schema_ = std::move(schema);
236       *tab = table.release();
237 
238       return SQLITE_OK;
239     };
240     auto destroy_fn = [](sqlite3_vtab* t) {
241       delete static_cast<TTable*>(t);
242       return SQLITE_OK;
243     };
244 
245     module->xCreate = create_fn;
246     module->xConnect = create_fn;
247     module->xDisconnect = destroy_fn;
248     module->xDestroy = destroy_fn;
249     module->xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) {
250       return static_cast<TTable*>(t)->OpenInternal(c);
251     };
252     module->xClose = [](sqlite3_vtab_cursor* c) {
253       delete static_cast<TCursor*>(c);
254       return SQLITE_OK;
255     };
256     module->xBestIndex = [](sqlite3_vtab* t, sqlite3_index_info* i) {
257       return static_cast<TTable*>(t)->BestIndexInternal(i);
258     };
259     module->xFilter = [](sqlite3_vtab_cursor* vc, int i, const char* s, int a,
260                          sqlite3_value** v) {
261       // If the idxNum is equal to kSqliteConstraintBestIndexNum, that means
262       // in BestIndexInternal, we tried to discourage the query planner from
263       // chosing this plan. As the subclass has informed us that it cannot
264       // handle this plan, just return the error now.
265       if (i == kInvalidConstraintsInBestIndexNum)
266         return SQLITE_CONSTRAINT;
267 
268       auto* c = static_cast<Cursor*>(vc);
269       bool is_cached = c->table_->ReadConstraints(i, s, a);
270 
271       auto history = is_cached ? Cursor::FilterHistory::kSame
272                                : Cursor::FilterHistory::kDifferent;
273       return static_cast<TCursor*>(c)->Filter(c->table_->qc_cache_, v, history);
274     };
275     module->xNext = [](sqlite3_vtab_cursor* c) {
276       return static_cast<TCursor*>(c)->Next();
277     };
278     module->xEof = [](sqlite3_vtab_cursor* c) {
279       return static_cast<TCursor*>(c)->Eof();
280     };
281     module->xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
282       return static_cast<TCursor*>(c)->Column(a, b);
283     };
284     module->xRowid = [](sqlite3_vtab_cursor* c, sqlite3_int64* r) {
285       return static_cast<TCursor*>(c)->RowId(r);
286     };
287     module->xFindFunction =
288         [](sqlite3_vtab* t, int, const char* name,
289            void (**fn)(sqlite3_context*, int, sqlite3_value**), void** args) {
290           return static_cast<TTable*>(t)->FindFunction(name, fn, args);
291         };
292 
293     if (read_write) {
294       module->xUpdate = [](sqlite3_vtab* t, int a, sqlite3_value** v,
295                            sqlite3_int64* r) {
296         return static_cast<TTable*>(t)->Update(a, v, r);
297       };
298     }
299 
300     int res = sqlite3_create_module_v2(
301         db, table_name.c_str(), module, desc.release(),
302         [](void* arg) { delete static_cast<TableDescriptor<Context>*>(arg); });
303     PERFETTO_CHECK(res == SQLITE_OK);
304 
305     // Register virtual tables into an internal 'perfetto_tables' table. This is
306     // used for iterating through all the tables during a database export. Note
307     // that virtual tables requiring arguments aren't registered because they
308     // can't be automatically instantiated for exporting.
309     if (!requires_args) {
310       char* insert_sql = sqlite3_mprintf(
311           "INSERT INTO perfetto_tables(name) VALUES('%q')", table_name.c_str());
312       char* error = nullptr;
313       sqlite3_exec(db, insert_sql, nullptr, nullptr, &error);
314       sqlite3_free(insert_sql);
315       if (error) {
316         PERFETTO_ELOG("Error registering table: %s", error);
317         sqlite3_free(error);
318       }
319     }
320   }
321 
322   // Methods to be implemented by derived table classes.
323   virtual util::Status Init(int argc, const char* const* argv, Schema*) = 0;
324   virtual std::unique_ptr<Cursor> CreateCursor() = 0;
325   virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
326 
327   // Optional metods to implement.
328   using FindFunctionFn = void (*)(sqlite3_context*, int, sqlite3_value**);
329   virtual int ModifyConstraints(QueryConstraints* qc);
330   virtual int FindFunction(const char* name, FindFunctionFn* fn, void** args);
331 
332   // At registration time, the function should also pass true for |read_write|.
333   virtual int Update(int, sqlite3_value**, sqlite3_int64*);
334 
SetErrorMessage(char * error)335   void SetErrorMessage(char* error) {
336     sqlite3_free(zErrMsg);
337     zErrMsg = error;
338   }
339 
schema()340   const Schema& schema() const { return schema_; }
name()341   const std::string& name() const { return name_; }
342 
343  private:
344   static constexpr int kInvalidConstraintsInBestIndexNum =
345       std::numeric_limits<int>::max();
346 
347   template <typename TableType, typename Context>
GetFactory()348   static Factory<Context> GetFactory() {
349     return [](sqlite3* db, Context ctx) {
350       return std::unique_ptr<SqliteTable>(new TableType(db, std::move(ctx)));
351     };
352   }
353 
354   bool ReadConstraints(int idxNum, const char* idxStr, int argc);
355 
356   // Overriden functions from sqlite3_vtab.
357   int OpenInternal(sqlite3_vtab_cursor**);
358   int BestIndexInternal(sqlite3_index_info*);
359 
360   SqliteTable(const SqliteTable&) = delete;
361   SqliteTable& operator=(const SqliteTable&) = delete;
362 
363   std::string name_;
364   Schema schema_;
365 
366   QueryConstraints qc_cache_;
367   int qc_hash_ = 0;
368   int best_index_num_ = 0;
369 };
370 
371 }  // namespace trace_processor
372 }  // namespace perfetto
373 
374 #endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
375