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