1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache, 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, software 11 * distributed under the License is distributed on an "AS IS", 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY, 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_BINDINGS_SQLITE_MODULE_H_ 18 #define SRC_TRACE_PROCESSOR_SQLITE_BINDINGS_SQLITE_MODULE_H_ 19 20 #include <sqlite3.h> 21 22 #include "perfetto/base/logging.h" 23 24 namespace perfetto::trace_processor::sqlite { 25 26 // Prototype for a virtual table (vtab) module which can be registered with 27 // SQLite. 28 // 29 // See https://www.sqlite.org/vtab.html for how to implement this class. 30 template <typename Impl> 31 struct Module { 32 // Specifies the type of module: implementations can override this field by 33 // declaring and defining it. 34 // 35 // Specifying this to kCreateOnly requires that the |Create| and |Destroy| 36 // functions are defined. 37 // 38 // See the SQLite documentation on what these types mean. 39 static constexpr enum { kEponymousOnly, kCreateOnly } kType = kCreateOnly; 40 41 // Specifies whether this table is supports making changes to it: 42 // implementations can override this field by declaring and defining it. 43 // 44 // Setting this to true requires the |Update| function to be defined. 45 static constexpr bool kSupportsWrites = true; 46 47 // Specifies whether this table supports overloading functions: 48 // implementations can override this field by declaring and defining it. 49 // 50 // Setting this to true requires that the |FindFunction| function is defined. 51 static constexpr bool kDoesOverloadFunctions = true; 52 53 // Specifies the type of context for the module. Implementations should define 54 // this type to match the context type which is expected to be passed into 55 // |sqlite3_create_module|. 56 using Context = void; 57 58 // Specifies the type for the vtab created by this module. 59 // 60 // Implementations should define this type to match the vtab type they use in 61 // |Create| and |Connect|. 62 using Vtab = sqlite3_vtab; 63 64 // Specifies the type for the cursor created by this module. 65 // 66 // Implementations should define this type to match the cursor type they use 67 // in |Open| and |Close|. 68 using Cursor = sqlite3_vtab_cursor; 69 70 // Creates a new instance of a virtual table and its backing storage. 71 // 72 // Implementations MUST define this function themselves if 73 // |kType| == |kCreateOnly|; this function is declared but *not* defined so 74 // linker errors will be thrown if not defined. 75 static int Create(sqlite3*, 76 void*, 77 int, 78 const char* const*, 79 sqlite3_vtab**, 80 char**); 81 82 // Destroys the virtual table and its backing storage. 83 // 84 // Implementations MUST define this function themselves if 85 // |kType| == |kCreateOnly|; this function is declared but *not* defined so 86 // linker errors will be thrown if not defined. 87 static int Destroy(sqlite3_vtab*); 88 89 // Creates a new instance of the virtual table, connecting to existing 90 // backing storage. 91 // 92 // Implementations MUST define this function themselves; this function is 93 // declared but *not* defined so linker errors will be thrown if not defined. 94 static int Connect(sqlite3*, 95 void*, 96 int, 97 const char* const*, 98 sqlite3_vtab**, 99 char**); 100 101 // Destroys the virtual table but *not* its backing storage. 102 // 103 // Implementations MUST define this function themselves; this function is 104 // declared but *not* defined so linker errors will be thrown if not defined. 105 static int Disconnect(sqlite3_vtab*); 106 107 // Specifies filtering and cost information for the query planner. 108 // 109 // Implementations MUST define this function themselves; this function is 110 // declared but *not* defined so linker errors will be thrown if not defined. 111 static int BestIndex(sqlite3_vtab*, sqlite3_index_info*); 112 113 // Opens a cursor into the given vtab. 114 // 115 // Implementations MUST define this function themselves; this function is 116 // declared but *not* defined so linker errors will be thrown if not defined. 117 static int Open(sqlite3_vtab*, sqlite3_vtab_cursor**); 118 119 // Closes the cursor. 120 // 121 // Implementations MUST define this function themselves; this function is 122 // declared but *not* defined so linker errors will be thrown if not defined. 123 static int Close(sqlite3_vtab_cursor*); 124 125 // Resets this cursor to filter rows matching the provided set of filter 126 // constraints and order by clauses. 127 // 128 // Implementations MUST define this function themselves; this function is 129 // declared but *not* defined so linker errors will be thrown if not defined. 130 static int Filter(sqlite3_vtab_cursor*, 131 int, 132 const char*, 133 int, 134 sqlite3_value**); 135 136 // Forwards the cursor to point to the next row. 137 // 138 // Implementations MUST define this function themselves; this function is 139 // declared but *not* defined so linker errors will be thrown if not defined. 140 static int Next(sqlite3_vtab_cursor*); 141 142 // Returns 1 if the cursor has reached its end or 0 otherwise. 143 // 144 // Implementations MUST define this function themselves; this function is 145 // declared but *not* defined so linker errors will be thrown if not defined. 146 static int Eof(sqlite3_vtab_cursor*); 147 148 // Returns the value column at the given index for the current row the cursor 149 // points to. 150 // 151 // Implementations MUST define this function themselves; this function is 152 // declared but *not* defined so linker errors will be thrown if not defined. 153 static int Column(sqlite3_vtab_cursor*, sqlite3_context*, int); 154 155 // Returns the rowid for the current row. 156 // 157 // Implementations MUST define this function themselves; this function is 158 // declared but *not* defined so linker errors will be thrown if not defined. 159 static int Rowid(sqlite3_vtab_cursor*, sqlite_int64*); 160 161 // Inserts/deletes/updates one row. 162 // 163 // Implementations MUST define this function themselves if 164 // |kSupportsWrites| == |true|; this function is declared but *not* defined so 165 // linker errors will be thrown if not defined. 166 static int Update(sqlite3_vtab*, int, sqlite3_value**, sqlite_int64*); 167 168 // Overloads a function with the given name when executed with a vtab column 169 // as the first argument. 170 // 171 // Implementations MUST define this function themselves if 172 // |kDoesOverloadFunctions| == |true|; this function is declared but *not* 173 // defined so linker errors will be thrown if not defined. 174 using FindFunctionFn = void(sqlite3_context*, int, sqlite3_value**); 175 static int FindFunction(sqlite3_vtab*, 176 int, 177 const char*, 178 FindFunctionFn**, 179 void**); 180 181 // Helper function to cast the module context pointer to the correct type. GetContextModule182 static auto GetContext(void* ctx) { 183 return static_cast<typename Impl::Context*>(ctx); 184 } 185 186 // Helper function to cast the vtab pointer to the correct type. GetVtabModule187 static auto GetVtab(sqlite3_vtab* vtab) { 188 return static_cast<typename Impl::Vtab*>(vtab); 189 } 190 191 // Helper function to cast the cursor pointer to the correct type. GetCursorModule192 static auto GetCursor(sqlite3_vtab_cursor* cursor) { 193 return static_cast<typename Impl::Cursor*>(cursor); 194 } 195 196 // Returns sqlite3_module object corresponding to the module. Used to pass 197 // information about this module to SQLite. CreateModuleModule198 static constexpr sqlite3_module CreateModule() { 199 sqlite3_module module{}; 200 module.xBestIndex = &Impl::BestIndex; 201 module.xOpen = &Impl::Open; 202 module.xClose = &Impl::Close; 203 module.xFilter = &Impl::Filter; 204 module.xNext = &Impl::Next; 205 module.xEof = &Impl::Eof; 206 module.xColumn = &Impl::Column; 207 module.xRowid = &Impl::Rowid; 208 if constexpr (Impl::kType == kCreateOnly) { 209 module.xCreate = &Impl::Create; 210 module.xDestroy = &Impl::Destroy; 211 module.xConnect = &Impl::Connect; 212 module.xDisconnect = &Impl::Disconnect; 213 } else { 214 module.xCreate = nullptr; 215 module.xDestroy = [](sqlite3_vtab*) -> int { 216 PERFETTO_FATAL("Should not be reachable"); 217 }; 218 module.xConnect = &Impl::Connect; 219 module.xDisconnect = &Impl::Disconnect; 220 } 221 if constexpr (Impl::kSupportsWrites) { 222 module.xUpdate = &Impl::Update; 223 } 224 if constexpr (Impl::kDoesOverloadFunctions) { 225 module.xFindFunction = &Impl::FindFunction; 226 } 227 return module; 228 } 229 }; 230 231 } // namespace perfetto::trace_processor::sqlite 232 233 #endif // SRC_TRACE_PROCESSOR_SQLITE_BINDINGS_SQLITE_MODULE_H_ 234