• 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 <optional>
26 #include <string>
27 #include <vector>
28 
29 #include "perfetto/base/status.h"
30 #include "perfetto/ext/base/flat_hash_map.h"
31 #include "perfetto/ext/base/status_or.h"
32 #include "perfetto/ext/base/utils.h"
33 #include "perfetto/trace_processor/basic_types.h"
34 #include "src/trace_processor/db/table.h"
35 #include "src/trace_processor/sqlite/query_constraints.h"
36 
37 namespace perfetto {
38 namespace trace_processor {
39 
40 class SqliteEngine;
41 class TypedSqliteTableBase;
42 
43 // Abstract base class representing a SQLite virtual table. Implements the
44 // common bookeeping required across all tables and allows subclasses to
45 // implement a friendlier API than that required by SQLite.
46 class SqliteTable : public sqlite3_vtab {
47  public:
48   // Custom opcodes used by subclasses of SqliteTable.
49   // Stored here as we need a central repository of opcodes to prevent clashes
50   // between different sub-classes.
51   enum CustomFilterOpcode {
52     kSourceGeqOpCode = SQLITE_INDEX_CONSTRAINT_FUNCTION + 1,
53   };
54   // Describes a column of this table.
55   class Column {
56    public:
57     Column(size_t idx,
58            std::string name,
59            SqlValue::Type type,
60            bool hidden = false);
61 
index()62     size_t index() const { return index_; }
name()63     const std::string& name() const { return name_; }
type()64     SqlValue::Type type() const { return type_; }
65 
hidden()66     bool hidden() const { return hidden_; }
set_hidden(bool hidden)67     void set_hidden(bool hidden) { hidden_ = hidden; }
68 
69    private:
70     size_t index_ = 0;
71     std::string name_;
72     SqlValue::Type type_ = SqlValue::Type::kNull;
73     bool hidden_ = false;
74   };
75 
76   // Abstract base class representing an SQLite Cursor. Presents a friendlier
77   // API for subclasses to implement.
78   class BaseCursor : 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     explicit BaseCursor(SqliteTable* table);
94     virtual ~BaseCursor();
95 
96     // Methods to be implemented by derived table classes.
97     // Note: these methods are intentionally not virtual for performance
98     // reasons. As these methods are not defined, there will be compile errors
99     // thrown if any of these methods are missing.
100 
101     // Called to intialise the cursor with the constraints of the query.
102     base::Status Filter(const QueryConstraints& qc,
103                         sqlite3_value**,
104                         FilterHistory);
105 
106     // Called to forward the cursor to the next row in the table.
107     base::Status Next();
108 
109     // Called to check if the cursor has reached eof. Column will be called iff
110     // this method returns true.
111     bool Eof();
112 
113     // Used to extract the value from the column at index |N|.
114     base::Status Column(sqlite3_context* context, int N);
115 
table()116     SqliteTable* table() const { return table_; }
117 
118    protected:
119     BaseCursor(BaseCursor&) = delete;
120     BaseCursor& operator=(const BaseCursor&) = delete;
121 
122     BaseCursor(BaseCursor&&) noexcept = default;
123     BaseCursor& operator=(BaseCursor&&) = default;
124 
125    private:
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   enum TableType {
156     // A table which automatically exists in the main schema and cannot be
157     // created with CREATE VIRTUAL TABLE.
158     // Note: the name value here matches the naming in the vtable docs of
159     // SQLite.
160     kEponymousOnly,
161 
162     // A table which must be explicitly created using a CREATE VIRTUAL TABLE
163     // statement (i.e. does exist automatically).
164     kExplicitCreate,
165   };
166 
167   // Public for unique_ptr destructor calls.
168   virtual ~SqliteTable();
169 
170   // When set it logs all BestIndex and Filter actions on the console.
171   static bool debug;
172 
173  protected:
174   // Populated by a BestIndex call to allow subclasses to tweak SQLite's
175   // handling of sets of constraints.
176   struct BestIndexInfo {
177     // Contains bools which indicate whether SQLite should omit double checking
178     // the constraint at that index.
179     //
180     // If there are no constraints, SQLite will be told it can omit checking for
181     // the whole query.
182     std::vector<bool> sqlite_omit_constraint;
183 
184     // Indicates that SQLite should not double check the result of the order by
185     // clause.
186     //
187     // If there are no order by clauses, this value will be ignored and SQLite
188     // will be told that it can omit double checking (i.e. this value will
189     // implicitly be taken to be true).
190     bool sqlite_omit_order_by = false;
191 
192     // Stores the estimated cost of this query.
193     double estimated_cost = 0;
194 
195     // Estimated row count.
196     int64_t estimated_rows = 0;
197   };
198 
199   SqliteTable();
200 
201   // Methods to be implemented by derived table classes.
202   virtual base::Status Init(int argc, const char* const* argv, Schema*) = 0;
203   virtual std::unique_ptr<BaseCursor> CreateCursor() = 0;
204   virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
205 
206   // Optional metods to implement.
207   using FindFunctionFn = void (*)(sqlite3_context*, int, sqlite3_value**);
208   virtual base::Status ModifyConstraints(QueryConstraints* qc);
209   virtual int FindFunction(const char* name, FindFunctionFn* fn, void** args);
210 
211   // At registration time, the function should also pass true for |read_write|.
212   virtual base::Status Update(int, sqlite3_value**, sqlite3_int64*);
213 
214   bool ReadConstraints(int idxNum, const char* idxStr, int argc);
215 
schema()216   const Schema& schema() const { return schema_; }
module_name()217   const std::string& module_name() const { return module_name_; }
name()218   const std::string& name() const { return name_; }
219 
220  private:
221   template <typename, typename>
222   friend class TypedSqliteTable;
223   friend class TypedSqliteTableBase;
224 
225   SqliteTable(const SqliteTable&) = delete;
226   SqliteTable& operator=(const SqliteTable&) = delete;
227 
228   // The engine class this table is registered with. Used for restoring/saving
229   // the table.
230   SqliteEngine* engine_ = nullptr;
231 
232   // This name of the table. For tables created using CREATE VIRTUAL TABLE, this
233   // will be the name of the table specified by the query. For automatically
234   // created tables, this will be the same as the module name passed to
235   // RegisterTable.
236   std::string name_;
237 
238   // The module name is the name passed to RegisterTable. This is differs from
239   // the table name (|name_|) where the table was created using CREATE VIRTUAL
240   // TABLE.
241   std::string module_name_;
242 
243   Schema schema_;
244 
245   QueryConstraints qc_cache_;
246   int qc_hash_ = 0;
247   int best_index_num_ = 0;
248 };
249 
250 class TypedSqliteTableBase : public SqliteTable {
251  protected:
252   struct BaseModuleArg {
253     sqlite3_module module;
254     SqliteEngine* engine;
255   };
256 
257   ~TypedSqliteTableBase() override;
258 
259   static int xDestroy(sqlite3_vtab*);
260   static int xDestroyFatal(sqlite3_vtab*);
261 
262   static int xConnectRestoreTable(sqlite3* xdb,
263                                   void* arg,
264                                   int argc,
265                                   const char* const* argv,
266                                   sqlite3_vtab** tab,
267                                   char** pzErr);
268   static int xDisconnectSaveTable(sqlite3_vtab*);
269 
270   static int xOpen(sqlite3_vtab*, sqlite3_vtab_cursor**);
271   static int xBestIndex(sqlite3_vtab*, sqlite3_index_info*);
272 
273   static base::Status DeclareAndAssignVtab(std::unique_ptr<SqliteTable> table,
274                                            sqlite3_vtab** tab);
275 
276   base::Status InitInternal(SqliteEngine* engine,
277                             int argc,
278                             const char* const* argv);
279 
SetStatusAndReturn(base::Status status)280   int SetStatusAndReturn(base::Status status) {
281     if (!status.ok()) {
282       sqlite3_free(zErrMsg);
283       zErrMsg = sqlite3_mprintf("%s", status.c_message());
284       return SQLITE_ERROR;
285     }
286     return SQLITE_OK;
287   }
288 };
289 
290 template <typename SubTable, typename Context>
291 class TypedSqliteTable : public TypedSqliteTableBase {
292  public:
293   struct ModuleArg : BaseModuleArg {
294     Context context;
295   };
296 
CreateModuleArg(SqliteEngine * engine,Context ctx,TableType table_type,bool updatable)297   static std::unique_ptr<ModuleArg> CreateModuleArg(SqliteEngine* engine,
298                                                     Context ctx,
299                                                     TableType table_type,
300                                                     bool updatable) {
301     auto arg = std::make_unique<ModuleArg>();
302     arg->module = CreateModule(table_type, updatable);
303     arg->engine = engine;
304     arg->context = std::move(ctx);
305     return arg;
306   }
307 
308  private:
CreateModule(TableType table_type,bool updatable)309   static constexpr sqlite3_module CreateModule(TableType table_type,
310                                                bool updatable) {
311     sqlite3_module module;
312     memset(&module, 0, sizeof(sqlite3_module));
313     switch (table_type) {
314       case TableType::kEponymousOnly:
315         // Neither xCreate nor xDestroy should ever be called for
316         // eponymous-only tables.
317         module.xCreate = nullptr;
318         module.xDestroy = &xDestroyFatal;
319 
320         // xConnect and xDisconnect will automatically be called with
321         // |module_name| == |name|.
322         module.xConnect = &xCreate;
323         module.xDisconnect = &xDestroy;
324         break;
325       case TableType::kExplicitCreate:
326         // xConnect and xDestroy will be called when the table is CREATE-ed and
327         // DROP-ed respectively.
328         module.xCreate = &xCreate;
329         module.xDestroy = &xDestroy;
330 
331         // xConnect and xDisconnect can be called at any time.
332         module.xConnect = &xConnectRestoreTable;
333         module.xDisconnect = &xDisconnectSaveTable;
334         break;
335     }
336     module.xOpen = &xOpen;
337     module.xClose = &xClose;
338     module.xBestIndex = &xBestIndex;
339     module.xFindFunction = &xFindFunction;
340     module.xFilter = &xFilter;
341     module.xNext = &xNext;
342     module.xEof = &xEof;
343     module.xColumn = &xColumn;
344     module.xRowid = &xRowid;
345     if (updatable) {
346       module.xUpdate = &xUpdate;
347     }
348     return module;
349   }
350 
xCreate(sqlite3 * xdb,void * arg,int argc,const char * const * argv,sqlite3_vtab ** tab,char ** pzErr)351   static int xCreate(sqlite3* xdb,
352                      void* arg,
353                      int argc,
354                      const char* const* argv,
355                      sqlite3_vtab** tab,
356                      char** pzErr) {
357     auto* xdesc = static_cast<ModuleArg*>(arg);
358     std::unique_ptr<SubTable> table(
359         new SubTable(xdb, std::move(xdesc->context)));
360     base::Status status = table->InitInternal(xdesc->engine, argc, argv);
361     if (!status.ok()) {
362       *pzErr = sqlite3_mprintf("%s", status.c_message());
363       return SQLITE_ERROR;
364     }
365     status = DeclareAndAssignVtab(std::move(table), tab);
366     if (!status.ok()) {
367       *pzErr = sqlite3_mprintf("%s", status.c_message());
368       return SQLITE_ERROR;
369     }
370     return SQLITE_OK;
371   }
xClose(sqlite3_vtab_cursor * c)372   static int xClose(sqlite3_vtab_cursor* c) {
373     delete static_cast<typename SubTable::Cursor*>(c);
374     return SQLITE_OK;
375   }
xFindFunction(sqlite3_vtab * t,int,const char * name,void (** fn)(sqlite3_context *,int,sqlite3_value **),void ** args)376   static int xFindFunction(sqlite3_vtab* t,
377                            int,
378                            const char* name,
379                            void (**fn)(sqlite3_context*, int, sqlite3_value**),
380                            void** args) {
381     return static_cast<SubTable*>(t)->FindFunction(name, fn, args);
382   }
xFilter(sqlite3_vtab_cursor * vc,int i,const char * s,int a,sqlite3_value ** v)383   static int xFilter(sqlite3_vtab_cursor* vc,
384                      int i,
385                      const char* s,
386                      int a,
387                      sqlite3_value** v) {
388     auto* cursor = static_cast<typename SubTable::Cursor*>(vc);
389     bool is_cached = cursor->table()->ReadConstraints(i, s, a);
390     auto history = is_cached ? BaseCursor::FilterHistory::kSame
391                              : BaseCursor::FilterHistory::kDifferent;
392     auto* table = static_cast<SubTable*>(cursor->table());
393     return table->SetStatusAndReturn(
394         cursor->Filter(cursor->table()->qc_cache_, v, history));
395   }
xNext(sqlite3_vtab_cursor * c)396   static int xNext(sqlite3_vtab_cursor* c) {
397     auto* cursor = static_cast<typename SubTable::Cursor*>(c);
398     auto* table = static_cast<SubTable*>(cursor->table());
399     return table->SetStatusAndReturn(cursor->Next());
400   }
xEof(sqlite3_vtab_cursor * c)401   static int xEof(sqlite3_vtab_cursor* c) {
402     return static_cast<int>(static_cast<typename SubTable::Cursor*>(c)->Eof());
403   }
xColumn(sqlite3_vtab_cursor * c,sqlite3_context * a,int b)404   static int xColumn(sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
405     auto* cursor = static_cast<typename SubTable::Cursor*>(c);
406     auto* table = static_cast<SubTable*>(cursor->table());
407     return table->SetStatusAndReturn(cursor->Column(a, b));
408   }
xRowid(sqlite3_vtab_cursor *,sqlite3_int64 *)409   static int xRowid(sqlite3_vtab_cursor*, sqlite3_int64*) {
410     return SQLITE_ERROR;
411   }
xUpdate(sqlite3_vtab * t,int a,sqlite3_value ** v,sqlite3_int64 * r)412   static int xUpdate(sqlite3_vtab* t,
413                      int a,
414                      sqlite3_value** v,
415                      sqlite3_int64* r) {
416     auto* table = static_cast<SubTable*>(t);
417     return table->SetStatusAndReturn(table->Update(a, v, r));
418   }
419 };
420 
421 }  // namespace trace_processor
422 }  // namespace perfetto
423 
424 #endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
425