|  | /* | 
|  | * Copyright (C) 2019 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_ | 
|  | #define SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_ | 
|  |  | 
|  | #include <sqlite3.h> | 
|  | #include <cstdint> | 
|  | #include <memory> | 
|  | #include <optional> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "perfetto/trace_processor/basic_types.h" | 
|  | #include "src/trace_processor/db/column/types.h" | 
|  | #include "src/trace_processor/db/runtime_table.h" | 
|  | #include "src/trace_processor/db/table.h" | 
|  | #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/static_table_function.h" | 
|  | #include "src/trace_processor/sqlite/bindings/sqlite_module.h" | 
|  | #include "src/trace_processor/sqlite/module_lifecycle_manager.h" | 
|  |  | 
|  | namespace perfetto::trace_processor { | 
|  |  | 
|  | enum class TableComputation { | 
|  | // Table is statically defined. | 
|  | kStatic, | 
|  |  | 
|  | // Table is defined as a function. | 
|  | kTableFunction, | 
|  |  | 
|  | // Table is defined in runtime. | 
|  | kRuntime | 
|  | }; | 
|  |  | 
|  | // Implements the SQLite table interface for db tables. | 
|  | struct DbSqliteModule : public sqlite::Module<DbSqliteModule> { | 
|  | struct State { | 
|  | State(const Table*, Table::Schema); | 
|  | explicit State(std::unique_ptr<RuntimeTable>); | 
|  | explicit State(std::unique_ptr<StaticTableFunction>); | 
|  |  | 
|  | TableComputation computation; | 
|  | Table::Schema schema; | 
|  | int argument_count = 0; | 
|  |  | 
|  | // Only valid when computation == TableComputation::kStatic. | 
|  | const Table* static_table = nullptr; | 
|  |  | 
|  | // Only valid when computation == TableComputation::kRuntime. | 
|  | std::unique_ptr<RuntimeTable> runtime_table; | 
|  |  | 
|  | // Only valid when computation == TableComputation::kTableFunction. | 
|  | std::unique_ptr<StaticTableFunction> static_table_function; | 
|  |  | 
|  | private: | 
|  | State(TableComputation, Table::Schema); | 
|  | }; | 
|  | struct Context { | 
|  | std::unique_ptr<State> temporary_create_state; | 
|  | sqlite::ModuleStateManager<DbSqliteModule> manager; | 
|  | }; | 
|  | struct Vtab : public sqlite::Module<DbSqliteModule>::Vtab { | 
|  | sqlite::ModuleStateManager<DbSqliteModule>::PerVtabState* state; | 
|  | int best_index_num = 0; | 
|  | std::string table_name; | 
|  | }; | 
|  | struct Cursor : public sqlite::Module<DbSqliteModule>::Cursor { | 
|  | enum class Mode { | 
|  | kSingleRow, | 
|  | kTable, | 
|  | }; | 
|  |  | 
|  | const Table* upstream_table = nullptr; | 
|  |  | 
|  | // Only valid for |db_sqlite_table_->computation_| == | 
|  | // TableComputation::kDynamic. | 
|  | std::unique_ptr<Table> dynamic_table; | 
|  |  | 
|  | // Only valid for Mode::kSingleRow. | 
|  | std::optional<uint32_t> single_row; | 
|  |  | 
|  | // Only valid for Mode::kTable. | 
|  | std::optional<Table::Iterator> iterator; | 
|  |  | 
|  | bool eof = true; | 
|  |  | 
|  | // Stores a sorted version of |db_table| sorted on a repeated equals | 
|  | // constraint. This allows speeding up repeated subqueries in joins | 
|  | // significantly. | 
|  | std::optional<Table> sorted_cache_table; | 
|  |  | 
|  | // Stores the count of repeated equality queries to decide whether it is | 
|  | // wortwhile to sort |db_table| to create |sorted_cache_table|. | 
|  | uint32_t repeated_cache_count = 0; | 
|  |  | 
|  | Mode mode = Mode::kSingleRow; | 
|  |  | 
|  | int last_idx_num = -1; | 
|  | Query query; | 
|  |  | 
|  | std::vector<SqlValue> table_function_arguments; | 
|  | }; | 
|  | struct QueryCost { | 
|  | double cost; | 
|  | uint32_t rows; | 
|  | }; | 
|  |  | 
|  | static constexpr bool kSupportsWrites = false; | 
|  | static constexpr bool kDoesOverloadFunctions = false; | 
|  |  | 
|  | static int Create(sqlite3*, | 
|  | void*, | 
|  | int, | 
|  | const char* const*, | 
|  | sqlite3_vtab**, | 
|  | char**); | 
|  | static int Destroy(sqlite3_vtab*); | 
|  |  | 
|  | static int Connect(sqlite3*, | 
|  | void*, | 
|  | int, | 
|  | const char* const*, | 
|  | sqlite3_vtab**, | 
|  | char**); | 
|  | static int Disconnect(sqlite3_vtab*); | 
|  |  | 
|  | static int BestIndex(sqlite3_vtab*, sqlite3_index_info*); | 
|  |  | 
|  | static int Open(sqlite3_vtab*, sqlite3_vtab_cursor**); | 
|  | static int Close(sqlite3_vtab_cursor*); | 
|  |  | 
|  | static int Filter(sqlite3_vtab_cursor*, | 
|  | int, | 
|  | const char*, | 
|  | int, | 
|  | sqlite3_value**); | 
|  | static int Next(sqlite3_vtab_cursor*); | 
|  | static int Eof(sqlite3_vtab_cursor*); | 
|  | static int Column(sqlite3_vtab_cursor*, sqlite3_context*, int); | 
|  | static int Rowid(sqlite3_vtab_cursor*, sqlite_int64*); | 
|  |  | 
|  | // static for testing. | 
|  | static QueryCost EstimateCost(const Table::Schema&, | 
|  | uint32_t row_count, | 
|  | sqlite3_index_info* info, | 
|  | const std::vector<int>&, | 
|  | const std::vector<int>&); | 
|  |  | 
|  | // This needs to happen at the end as it depends on the functions | 
|  | // defined above. | 
|  | static constexpr sqlite3_module kModule = CreateModule(); | 
|  | }; | 
|  |  | 
|  | }  // namespace perfetto::trace_processor | 
|  |  | 
|  | #endif  // SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_ |