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 "perfetto/base/status.h" 21 #include "src/trace_processor/containers/bit_vector.h" 22 #include "src/trace_processor/db/table.h" 23 #include "src/trace_processor/prelude/table_functions/table_function.h" 24 #include "src/trace_processor/sqlite/query_cache.h" 25 #include "src/trace_processor/sqlite/sqlite_table.h" 26 27 namespace perfetto { 28 namespace trace_processor { 29 30 enum class DbSqliteTableComputation { 31 // Mode when the table is static (i.e. passed in at construction 32 // time). 33 kStatic, 34 35 // Mode when table is dynamically computed at filter time. 36 kDynamic, 37 }; 38 39 struct DbSqliteTableContext { 40 QueryCache* cache; 41 DbSqliteTableComputation computation; 42 43 // Only valid when computation == TableComputation::kStatic. 44 const Table* static_table; 45 46 // Only valid when computation == TableComputation::kDynamic. 47 std::unique_ptr<TableFunction> generator; 48 }; 49 50 // Implements the SQLite table interface for db tables. 51 class DbSqliteTable final 52 : public TypedSqliteTable<DbSqliteTable, DbSqliteTableContext> { 53 public: 54 using TableComputation = DbSqliteTableComputation; 55 using Context = DbSqliteTableContext; 56 57 class Cursor final : public SqliteTable::BaseCursor { 58 public: 59 Cursor(DbSqliteTable*, QueryCache*); 60 ~Cursor() final; 61 62 Cursor(Cursor&&) noexcept = default; 63 Cursor& operator=(Cursor&&) = default; 64 65 // Implementation of SqliteTable::Cursor. 66 base::Status Filter(const QueryConstraints& qc, 67 sqlite3_value** argv, 68 FilterHistory); 69 base::Status Next(); 70 bool Eof(); 71 base::Status Column(sqlite3_context*, int N); 72 73 private: 74 enum class Mode { 75 kSingleRow, 76 kTable, 77 }; 78 79 // Tries to create a sorted table to cache in |sorted_cache_table_| if the 80 // constraint set matches the requirements. 81 void TryCacheCreateSortedTable(const QueryConstraints&, FilterHistory); 82 SourceTable()83 const Table* SourceTable() const { 84 // Try and use the sorted cache table (if it exists) to speed up the 85 // sorting. Otherwise, just use the original table. 86 return sorted_cache_table_ ? &*sorted_cache_table_ : upstream_table_; 87 } 88 89 Cursor(const Cursor&) = delete; 90 Cursor& operator=(const Cursor&) = delete; 91 92 DbSqliteTable* db_sqlite_table_ = nullptr; 93 QueryCache* cache_ = nullptr; 94 95 const Table* upstream_table_ = nullptr; 96 97 // Only valid for |db_sqlite_table_->computation_| == 98 // TableComputation::kDynamic. 99 std::unique_ptr<Table> dynamic_table_; 100 101 // Only valid for Mode::kSingleRow. 102 std::optional<uint32_t> single_row_; 103 104 // Only valid for Mode::kTable. 105 std::optional<Table> db_table_; 106 std::optional<Table::Iterator> iterator_; 107 108 bool eof_ = true; 109 110 // Stores a sorted version of |db_table_| sorted on a repeated equals 111 // constraint. This allows speeding up repeated subqueries in joins 112 // significantly. 113 std::shared_ptr<Table> sorted_cache_table_; 114 115 // Stores the count of repeated equality queries to decide whether it is 116 // wortwhile to sort |db_table_| to create |sorted_cache_table_|. 117 uint32_t repeated_cache_count_ = 0; 118 119 Mode mode_ = Mode::kSingleRow; 120 121 std::vector<Constraint> constraints_; 122 std::vector<Order> orders_; 123 }; 124 struct QueryCost { 125 double cost; 126 uint32_t rows; 127 }; 128 129 DbSqliteTable(sqlite3*, Context context); 130 virtual ~DbSqliteTable() final; 131 132 // Table implementation. 133 base::Status Init(int, const char* const*, SqliteTable::Schema*) final; 134 std::unique_ptr<SqliteTable::BaseCursor> CreateCursor() final; 135 base::Status ModifyConstraints(QueryConstraints*) final; 136 int BestIndex(const QueryConstraints&, BestIndexInfo*) final; 137 138 // These static functions are useful to allow other callers to make use 139 // of them. 140 static SqliteTable::Schema ComputeSchema(const Table::Schema&, 141 const char* table_name); 142 static void ModifyConstraints(const Table::Schema&, QueryConstraints*); 143 static void BestIndex(const Table::Schema&, 144 uint32_t row_count, 145 const QueryConstraints&, 146 BestIndexInfo*); 147 148 // static for testing. 149 static QueryCost EstimateCost(const Table::Schema&, 150 uint32_t row_count, 151 const QueryConstraints& qc); 152 153 private: 154 QueryCache* cache_ = nullptr; 155 156 TableComputation computation_ = TableComputation::kStatic; 157 158 // Only valid after Init has completed. 159 Table::Schema schema_; 160 161 // Only valid when computation_ == TableComputation::kStatic. 162 const Table* static_table_ = nullptr; 163 164 // Only valid when computation_ == TableComputation::kDynamic. 165 std::unique_ptr<TableFunction> generator_; 166 }; 167 168 } // namespace trace_processor 169 } // namespace perfetto 170 171 #endif // SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_ 172