1 /* 2 * Copyright (C) 2019 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_DB_SQLITE_TABLE_H_ 18 #define SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_ 19 20 #include "src/trace_processor/containers/bit_vector.h" 21 #include "src/trace_processor/db/table.h" 22 #include "src/trace_processor/sqlite/query_cache.h" 23 #include "src/trace_processor/sqlite/sqlite_table.h" 24 25 namespace perfetto { 26 namespace trace_processor { 27 28 // Implements the SQLite table interface for db tables. 29 class DbSqliteTable : public SqliteTable { 30 public: 31 enum class TableComputation { 32 // Mode when the table is static (i.e. passed in at construction 33 // time). 34 kStatic, 35 36 // Mode when table is dynamically computed at filter time. 37 kDynamic, 38 }; 39 40 // Interface which can be subclassed to allow generation of tables dynamically 41 // at filter time. 42 // This class is used to implement table-valued functions and other similar 43 // tables. 44 class DynamicTableGenerator { 45 public: 46 virtual ~DynamicTableGenerator(); 47 48 // Returns the schema of the table that will be returned by ComputeTable. 49 virtual Table::Schema CreateSchema() = 0; 50 51 // Returns the name of the dynamic table. 52 // This will be used to register the table with SQLite. 53 virtual std::string TableName() = 0; 54 55 // Returns the estimated number of rows the table would generate. 56 virtual uint32_t EstimateRowCount() = 0; 57 58 // Checks that the constraint set is valid. 59 // 60 // Returning base::OkStatus means that the required constraints are present 61 // in |qc| for dynamically computing the table (e.g. any required 62 // constraints on hidden columns for table-valued functions are present). 63 virtual base::Status ValidateConstraints(const QueryConstraints& qc) = 0; 64 65 // Dynamically computes the table given the constraints and order by 66 // vectors. 67 // The table is returned via |table_return|. There are no guarantees on 68 // its value if the method returns a non-ok status. 69 virtual base::Status ComputeTable(const std::vector<Constraint>& cs, 70 const std::vector<Order>& ob, 71 const BitVector& cols_used, 72 std::unique_ptr<Table>& table_return) = 0; 73 }; 74 75 class Cursor : public SqliteTable::Cursor { 76 public: 77 Cursor(DbSqliteTable*, QueryCache*); 78 79 Cursor(Cursor&&) noexcept = default; 80 Cursor& operator=(Cursor&&) = default; 81 82 // Implementation of SqliteTable::Cursor. 83 int Filter(const QueryConstraints& qc, 84 sqlite3_value** argv, 85 FilterHistory) override; 86 int Next() override; 87 int Eof() override; 88 int Column(sqlite3_context*, int N) override; 89 90 private: 91 enum class Mode { 92 kSingleRow, 93 kTable, 94 }; 95 96 // Tries to create a sorted table to cache in |sorted_cache_table_| if the 97 // constraint set matches the requirements. 98 void TryCacheCreateSortedTable(const QueryConstraints&, FilterHistory); 99 SourceTable()100 const Table* SourceTable() const { 101 // Try and use the sorted cache table (if it exists) to speed up the 102 // sorting. Otherwise, just use the original table. 103 return sorted_cache_table_ ? &*sorted_cache_table_ : upstream_table_; 104 } 105 106 Cursor(const Cursor&) = delete; 107 Cursor& operator=(const Cursor&) = delete; 108 109 DbSqliteTable* db_sqlite_table_ = nullptr; 110 QueryCache* cache_ = nullptr; 111 112 const Table* upstream_table_ = nullptr; 113 114 // Only valid for |db_sqlite_table_->computation_| == 115 // TableComputation::kDynamic. 116 std::unique_ptr<Table> dynamic_table_; 117 118 // Only valid for Mode::kSingleRow. 119 base::Optional<uint32_t> single_row_; 120 121 // Only valid for Mode::kTable. 122 base::Optional<Table> db_table_; 123 base::Optional<Table::Iterator> iterator_; 124 125 bool eof_ = true; 126 127 // Stores a sorted version of |db_table_| sorted on a repeated equals 128 // constraint. This allows speeding up repeated subqueries in joins 129 // significantly. 130 std::shared_ptr<Table> sorted_cache_table_; 131 132 // Stores the count of repeated equality queries to decide whether it is 133 // wortwhile to sort |db_table_| to create |sorted_cache_table_|. 134 uint32_t repeated_cache_count_ = 0; 135 136 Mode mode_ = Mode::kSingleRow; 137 138 std::vector<Constraint> constraints_; 139 std::vector<Order> orders_; 140 }; 141 struct QueryCost { 142 double cost; 143 uint32_t rows; 144 }; 145 struct Context { 146 QueryCache* cache; 147 Table::Schema schema; 148 TableComputation computation; 149 150 // Only valid when computation == TableComputation::kStatic. 151 const Table* static_table; 152 153 // Only valid when computation == TableComputation::kDynamic. 154 std::unique_ptr<DynamicTableGenerator> generator; 155 }; 156 157 static void RegisterTable(sqlite3* db, 158 QueryCache* cache, 159 Table::Schema schema, 160 const Table* table, 161 const std::string& name); 162 163 static void RegisterTable(sqlite3* db, 164 QueryCache* cache, 165 std::unique_ptr<DynamicTableGenerator> generator); 166 167 DbSqliteTable(sqlite3*, Context context); 168 virtual ~DbSqliteTable() override; 169 170 // Table implementation. 171 base::Status Init(int, 172 const char* const*, 173 SqliteTable::Schema*) override final; 174 std::unique_ptr<SqliteTable::Cursor> CreateCursor() override; 175 int ModifyConstraints(QueryConstraints*) override final; 176 int BestIndex(const QueryConstraints&, BestIndexInfo*) override final; 177 178 // These static functions are useful to allow other callers to make use 179 // of them. 180 static SqliteTable::Schema ComputeSchema(const Table::Schema&, 181 const char* table_name); 182 static void ModifyConstraints(const Table::Schema&, QueryConstraints*); 183 static void BestIndex(const Table::Schema&, 184 uint32_t row_count, 185 const QueryConstraints&, 186 BestIndexInfo*); 187 188 // static for testing. 189 static QueryCost EstimateCost(const Table::Schema&, 190 uint32_t row_count, 191 const QueryConstraints& qc); 192 193 private: 194 QueryCache* cache_ = nullptr; 195 Table::Schema schema_; 196 197 TableComputation computation_ = TableComputation::kStatic; 198 199 // Only valid when computation_ == TableComputation::kStatic. 200 const Table* static_table_ = nullptr; 201 202 // Only valid when computation_ == TableComputation::kDynamic. 203 std::unique_ptr<DynamicTableGenerator> generator_; 204 }; 205 206 } // namespace trace_processor 207 } // namespace perfetto 208 209 #endif // SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_ 210