Home | History | Annotate | Download | only in trace_processor
      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 
     58     size_t index() const { return index_; }
     59     const std::string& name() const { return name_; }
     60     ColumnType type() const { return type_; }
     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 
    127     const std::vector<Column>& columns() const { return columns_; }
    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 
    288   void SetErrorMessage(char* error) {
    289     sqlite3_free(zErrMsg);
    290     zErrMsg = error;
    291   }
    292 
    293   const Schema& schema() const { return schema_; }
    294   const std::string& name() const { return name_; }
    295 
    296  private:
    297   template <typename TableType>
    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