blob: d6d40b3867b92af9d87d07cc212df39579cfb6f0 [file] [log] [blame]
Primiano Tucci3bf99f32018-07-24 10:28:28 +01001/*
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
Lalit Maganti737b3762019-08-26 13:46:37 -070017#ifndef SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
18#define SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
Primiano Tucci3bf99f32018-07-24 10:28:28 +010019
Primiano Tucci02c11762019-08-30 00:57:59 +020020#include <sqlite3.h>
21
Primiano Tucci3bf99f32018-07-24 10:28:28 +010022#include <functional>
Lalit Maganti920f4f92020-02-19 13:45:05 +000023#include <limits>
Primiano Tucci3bf99f32018-07-24 10:28:28 +010024#include <memory>
Lalit Maganti4e2303c2023-03-29 15:28:36 +010025#include <optional>
Primiano Tucci3bf99f32018-07-24 10:28:28 +010026#include <string>
27#include <vector>
28
Lalit Maganti3927af82022-05-09 20:23:40 +010029#include "perfetto/base/status.h"
Lalit Maganti9a2b96d2023-05-11 17:13:48 +010030#include "perfetto/ext/base/flat_hash_map.h"
31#include "perfetto/ext/base/status_or.h"
Primiano Tucci22727922019-06-01 10:07:42 +010032#include "perfetto/ext/base/utils.h"
Lalit Maganti7ee6abb2019-05-09 17:57:32 +010033#include "perfetto/trace_processor/basic_types.h"
Lalit Maganti9a2b96d2023-05-11 17:13:48 +010034#include "src/trace_processor/db/table.h"
Lalit Maganti737b3762019-08-26 13:46:37 -070035#include "src/trace_processor/sqlite/query_constraints.h"
Primiano Tucci0e9bca42018-08-31 19:20:58 +020036
Primiano Tucci3bf99f32018-07-24 10:28:28 +010037namespace perfetto {
38namespace trace_processor {
39
Lalit Maganti9a2b96d2023-05-11 17:13:48 +010040class SqliteEngine;
41class TypedSqliteTableBase;
Primiano Tucci3bf99f32018-07-24 10:28:28 +010042
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.
Lalit Maganti5132c652019-07-29 23:31:12 +053046class SqliteTable : public sqlite3_vtab {
Primiano Tucci3bf99f32018-07-24 10:28:28 +010047 public:
Lalit Maganti9c60ce62022-11-11 19:18:50 +000048 // 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 };
Lalit Magantia270b652018-09-26 11:54:33 +010054 // Describes a column of this table.
55 class Column {
56 public:
Lalit Maganti58da68b2019-08-29 14:19:07 +010057 Column(size_t idx,
58 std::string name,
59 SqlValue::Type type,
60 bool hidden = false);
Lalit Magantia270b652018-09-26 11:54:33 +010061
62 size_t index() const { return index_; }
63 const std::string& name() const { return name_; }
Lalit Maganti58da68b2019-08-29 14:19:07 +010064 SqlValue::Type type() const { return type_; }
Lalit Maganti8a39fae2020-01-20 17:22:10 +000065
Lalit Magantia270b652018-09-26 11:54:33 +010066 bool hidden() const { return hidden_; }
Lalit Maganti8a39fae2020-01-20 17:22:10 +000067 void set_hidden(bool hidden) { hidden_ = hidden; }
Lalit Magantia270b652018-09-26 11:54:33 +010068
69 private:
70 size_t index_ = 0;
71 std::string name_;
Lalit Maganti58da68b2019-08-29 14:19:07 +010072 SqlValue::Type type_ = SqlValue::Type::kNull;
Lalit Magantia270b652018-09-26 11:54:33 +010073 bool hidden_ = false;
74 };
75
Primiano Tucci3bf99f32018-07-24 10:28:28 +010076 // Abstract base class representing an SQLite Cursor. Presents a friendlier
77 // API for subclasses to implement.
Lalit Maganti9a2b96d2023-05-11 17:13:48 +010078 class BaseCursor : public sqlite3_vtab_cursor {
Primiano Tucci3bf99f32018-07-24 10:28:28 +010079 public:
Lalit Magantia40168c2019-11-18 14:22:27 +000080 // 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
Lalit Maganti9a2b96d2023-05-11 17:13:48 +010093 explicit BaseCursor(SqliteTable* table);
94 virtual ~BaseCursor();
Primiano Tucci3bf99f32018-07-24 10:28:28 +010095
96 // Methods to be implemented by derived table classes.
Lalit Maganti9a2b96d2023-05-11 17:13:48 +010097 // 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.
Lalit Magantif1a8d522019-04-26 11:05:15 +0100100
101 // Called to intialise the cursor with the constraints of the query.
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100102 base::Status Filter(const QueryConstraints& qc,
103 sqlite3_value**,
104 FilterHistory);
Lalit Magantif1a8d522019-04-26 11:05:15 +0100105
106 // Called to forward the cursor to the next row in the table.
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100107 base::Status Next();
Lalit Magantif1a8d522019-04-26 11:05:15 +0100108
109 // Called to check if the cursor has reached eof. Column will be called iff
110 // this method returns true.
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100111 bool Eof();
Lalit Magantif1a8d522019-04-26 11:05:15 +0100112
113 // Used to extract the value from the column at index |N|.
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100114 base::Status Column(sqlite3_context* context, int N);
115
116 SqliteTable* table() const { return table_; }
Lalit Magantif0b4e172018-09-27 13:43:26 +0100117
Lalit Magantif1a8d522019-04-26 11:05:15 +0100118 protected:
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100119 BaseCursor(BaseCursor&) = delete;
120 BaseCursor& operator=(const BaseCursor&) = delete;
Lalit Magantif0b4e172018-09-27 13:43:26 +0100121
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100122 BaseCursor(BaseCursor&&) noexcept = default;
123 BaseCursor& operator=(BaseCursor&&) = default;
Lalit Magantif4588fc2018-09-24 14:14:49 +0100124
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100125 private:
Lalit Maganti5132c652019-07-29 23:31:12 +0530126 SqliteTable* table_ = nullptr;
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100127 };
128
Lalit Magantia270b652018-09-26 11:54:33 +0100129 // 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.
Lalit Maganti1ebebf12018-10-15 17:24:04 +0100137 Schema(const Schema&);
Lalit Magantia270b652018-09-26 11:54:33 +0100138 Schema& operator=(const Schema& t);
139
Lalit Magantif45f8ad2018-12-06 12:58:15 +0000140 std::string ToCreateTableStmt() const;
Lalit Magantia270b652018-09-26 11:54:33 +0100141
Lalit Magantiacda68b2018-10-29 15:23:25 +0000142 const std::vector<Column>& columns() const { return columns_; }
Lalit Maganti8a39fae2020-01-20 17:22:10 +0000143 std::vector<Column>* mutable_columns() { return &columns_; }
144
Lalit Magantia270b652018-09-26 11:54:33 +0100145 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
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100155 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
Lalit Magantiacda68b2018-10-29 15:23:25 +0000173 protected:
174 // Populated by a BestIndex call to allow subclasses to tweak SQLite's
175 // handling of sets of constraints.
176 struct BestIndexInfo {
Lalit Magantifb574622019-11-12 13:41:26 +0000177 // 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;
Lalit Maganti87069912019-11-07 18:23:46 +0000183
184 // Indicates that SQLite should not double check the result of the order by
185 // clause.
186 //
Lalit Magantifb574622019-11-12 13:41:26 +0000187 // If there are no order by clauses, this value will be ignored and SQLite
Lalit Maganti87069912019-11-07 18:23:46 +0000188 // 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;
Lalit Magantifb574622019-11-12 13:41:26 +0000191
192 // Stores the estimated cost of this query.
Lalit Maganti65852242019-11-22 17:33:23 +0000193 double estimated_cost = 0;
194
Lalit Maganti820373f2019-12-11 13:47:59 +0000195 // Estimated row count.
196 int64_t estimated_rows = 0;
Lalit Magantiacda68b2018-10-29 15:23:25 +0000197 };
198
Lalit Maganti5132c652019-07-29 23:31:12 +0530199 SqliteTable();
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100200
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100201 // Methods to be implemented by derived table classes.
Lalit Maganti3927af82022-05-09 20:23:40 +0100202 virtual base::Status Init(int argc, const char* const* argv, Schema*) = 0;
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100203 virtual std::unique_ptr<BaseCursor> CreateCursor() = 0;
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100204 virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
205
206 // Optional metods to implement.
Lalit Maganti89474472020-06-24 13:21:41 +0100207 using FindFunctionFn = void (*)(sqlite3_context*, int, sqlite3_value**);
Lalit Maganti116d74c2023-05-03 16:57:29 +0100208 virtual base::Status ModifyConstraints(QueryConstraints* qc);
Lalit Maganti89474472020-06-24 13:21:41 +0100209 virtual int FindFunction(const char* name, FindFunctionFn* fn, void** args);
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100210
Lalit Magantif4588fc2018-09-24 14:14:49 +0100211 // At registration time, the function should also pass true for |read_write|.
Lalit Maganti116d74c2023-05-03 16:57:29 +0100212 virtual base::Status Update(int, sqlite3_value**, sqlite3_int64*);
Lalit Maganti43d8f142018-11-12 14:58:15 +0000213
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100214 bool ReadConstraints(int idxNum, const char* idxStr, int argc);
215
Lalit Maganti127479a2019-03-13 18:52:11 +0000216 const Schema& schema() const { return schema_; }
Lalit Maganti52b9dc72022-11-15 17:53:06 +0000217 const std::string& module_name() const { return module_name_; }
Lalit Maganti127479a2019-03-13 18:52:11 +0000218 const std::string& name() const { return name_; }
Lalit Magantiacda68b2018-10-29 15:23:25 +0000219
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100220 private:
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100221 template <typename, typename>
222 friend class TypedSqliteTable;
223 friend class TypedSqliteTableBase;
Lalit Maganti116d74c2023-05-03 16:57:29 +0100224
Lalit Maganti5132c652019-07-29 23:31:12 +0530225 SqliteTable(const SqliteTable&) = delete;
226 SqliteTable& operator=(const SqliteTable&) = delete;
Primiano Tuccib2ea4d42018-08-21 15:05:13 +0200227
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100228 // The engine class this table is registered with. Used for restoring/saving
229 // the table.
230 SqliteEngine* engine_ = nullptr;
231
Lalit Maganti52b9dc72022-11-15 17:53:06 +0000232 // 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
Anna Mayzner46ceee22023-07-31 10:50:00 +0000234 // created tables, this will be the same as the module name registered.
Primiano Tuccib2ea4d42018-08-21 15:05:13 +0200235 std::string name_;
Lalit Maganti52b9dc72022-11-15 17:53:06 +0000236
Anna Mayzner46ceee22023-07-31 10:50:00 +0000237 // The module name is the name that will be registered. This is
238 // differs from the table name (|name_|) where the table was created using
239 // CREATE VIRTUAL TABLE.
Lalit Maganti52b9dc72022-11-15 17:53:06 +0000240 std::string module_name_;
241
Lalit Magantia270b652018-09-26 11:54:33 +0100242 Schema schema_;
243
Primiano Tucci0e9bca42018-08-31 19:20:58 +0200244 QueryConstraints qc_cache_;
245 int qc_hash_ = 0;
246 int best_index_num_ = 0;
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100247};
248
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100249class TypedSqliteTableBase : public SqliteTable {
250 protected:
251 struct BaseModuleArg {
252 sqlite3_module module;
253 SqliteEngine* engine;
Lalit Maganti32c7b042023-06-22 23:00:57 +0100254 TableType table_type;
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100255 };
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
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
290template <typename SubTable, typename Context>
291class TypedSqliteTable : public TypedSqliteTableBase {
292 public:
Alexander Timin7b343562023-06-23 13:32:56 +0100293 struct ModuleArg : public BaseModuleArg {
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100294 Context context;
295 };
296
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;
Alexander Timin7b343562023-06-23 13:32:56 +0100304 arg->table_type = table_type;
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100305 arg->context = std::move(ctx);
306 return arg;
307 }
308
309 private:
310 static constexpr sqlite3_module CreateModule(TableType table_type,
311 bool updatable) {
312 sqlite3_module module;
313 memset(&module, 0, sizeof(sqlite3_module));
314 switch (table_type) {
315 case TableType::kEponymousOnly:
316 // Neither xCreate nor xDestroy should ever be called for
317 // eponymous-only tables.
318 module.xCreate = nullptr;
319 module.xDestroy = &xDestroyFatal;
320
321 // xConnect and xDisconnect will automatically be called with
322 // |module_name| == |name|.
323 module.xConnect = &xCreate;
324 module.xDisconnect = &xDestroy;
325 break;
326 case TableType::kExplicitCreate:
Lalit Maganti204ecd72023-12-05 11:19:09 +0000327 // xCreate and xDestroy will be called when the table is CREATE-ed and
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100328 // DROP-ed respectively.
329 module.xCreate = &xCreate;
330 module.xDestroy = &xDestroy;
331
332 // xConnect and xDisconnect can be called at any time.
333 module.xConnect = &xConnectRestoreTable;
334 module.xDisconnect = &xDisconnectSaveTable;
335 break;
336 }
337 module.xOpen = &xOpen;
338 module.xClose = &xClose;
339 module.xBestIndex = &xBestIndex;
340 module.xFindFunction = &xFindFunction;
341 module.xFilter = &xFilter;
342 module.xNext = &xNext;
343 module.xEof = &xEof;
344 module.xColumn = &xColumn;
345 module.xRowid = &xRowid;
346 if (updatable) {
347 module.xUpdate = &xUpdate;
348 }
349 return module;
350 }
351
352 static int xCreate(sqlite3* xdb,
353 void* arg,
354 int argc,
355 const char* const* argv,
356 sqlite3_vtab** tab,
357 char** pzErr) {
358 auto* xdesc = static_cast<ModuleArg*>(arg);
Lalit Maganti4b379ad2023-08-10 19:00:55 +0100359 std::unique_ptr<SubTable> table(new SubTable(xdb, &*xdesc->context));
Lalit Maganti32c7b042023-06-22 23:00:57 +0100360 SubTable* table_ptr = table.get();
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100361 base::Status status = table->InitInternal(xdesc->engine, argc, argv);
362 if (!status.ok()) {
363 *pzErr = sqlite3_mprintf("%s", status.c_message());
364 return SQLITE_ERROR;
365 }
366 status = DeclareAndAssignVtab(std::move(table), tab);
367 if (!status.ok()) {
368 *pzErr = sqlite3_mprintf("%s", status.c_message());
369 return SQLITE_ERROR;
370 }
Lalit Maganti32c7b042023-06-22 23:00:57 +0100371 xdesc->engine->OnSqliteTableCreated(table_ptr->name(), xdesc->table_type);
Lalit Maganti9a2b96d2023-05-11 17:13:48 +0100372 return SQLITE_OK;
373 }
374 static int xClose(sqlite3_vtab_cursor* c) {
375 delete static_cast<typename SubTable::Cursor*>(c);
376 return SQLITE_OK;
377 }
378 static int xFindFunction(sqlite3_vtab* t,
379 int,
380 const char* name,
381 void (**fn)(sqlite3_context*, int, sqlite3_value**),
382 void** args) {
383 return static_cast<SubTable*>(t)->FindFunction(name, fn, args);
384 }
385 static int xFilter(sqlite3_vtab_cursor* vc,
386 int i,
387 const char* s,
388 int a,
389 sqlite3_value** v) {
390 auto* cursor = static_cast<typename SubTable::Cursor*>(vc);
391 bool is_cached = cursor->table()->ReadConstraints(i, s, a);
392 auto history = is_cached ? BaseCursor::FilterHistory::kSame
393 : BaseCursor::FilterHistory::kDifferent;
394 auto* table = static_cast<SubTable*>(cursor->table());
395 return table->SetStatusAndReturn(
396 cursor->Filter(cursor->table()->qc_cache_, v, history));
397 }
398 static int xNext(sqlite3_vtab_cursor* c) {
399 auto* cursor = static_cast<typename SubTable::Cursor*>(c);
400 auto* table = static_cast<SubTable*>(cursor->table());
401 return table->SetStatusAndReturn(cursor->Next());
402 }
403 static int xEof(sqlite3_vtab_cursor* c) {
404 return static_cast<int>(static_cast<typename SubTable::Cursor*>(c)->Eof());
405 }
406 static int xColumn(sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
407 auto* cursor = static_cast<typename SubTable::Cursor*>(c);
408 auto* table = static_cast<SubTable*>(cursor->table());
409 return table->SetStatusAndReturn(cursor->Column(a, b));
410 }
411 static int xRowid(sqlite3_vtab_cursor*, sqlite3_int64*) {
412 return SQLITE_ERROR;
413 }
414 static int xUpdate(sqlite3_vtab* t,
415 int a,
416 sqlite3_value** v,
417 sqlite3_int64* r) {
418 auto* table = static_cast<SubTable*>(t);
419 return table->SetStatusAndReturn(table->Update(a, v, r));
420 }
421};
422
Primiano Tucci3bf99f32018-07-24 10:28:28 +0100423} // namespace trace_processor
424} // namespace perfetto
425
Lalit Maganti737b3762019-08-26 13:46:37 -0700426#endif // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_