blob: ed3b8a651a579992d1a403b5113fbf619cd5a86c [file] [log] [blame]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache, 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, software
* distributed under the License is distributed on an "AS IS",
* WITHOUT WARRANTIES OR CONDITIONS OF ANY, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_TRACE_PROCESSOR_SQLITE_BINDINGS_SQLITE_MODULE_H_
#define SRC_TRACE_PROCESSOR_SQLITE_BINDINGS_SQLITE_MODULE_H_
#include <sqlite3.h>
#include "perfetto/base/logging.h"
namespace perfetto::trace_processor::sqlite {
// Prototype for a virtual table (vtab) module which can be registered with
// SQLite.
//
// See https://www.sqlite.org/vtab.html for how to implement this class.
template <typename Impl>
struct Module {
// Specifies the type of module: implementations can override this field by
// declaring and defining it.
//
// Specifying this to kCreateOnly requires that the |Create| and |Destroy|
// functions are defined.
//
// See the SQLite documentation on what these types mean.
static constexpr enum { kEponymousOnly, kCreateOnly } kType = kCreateOnly;
// Specifies whether this table is supports making changes to it:
// implementations can override this field by declaring and defining it.
//
// Setting this to true requires the |Update| function to be defined.
static constexpr bool kSupportsWrites = true;
// Specifies whether this table supports overloading functions:
// implementations can override this field by declaring and defining it.
//
// Setting this to true requires that the |FindFunction| function is defined.
static constexpr bool kDoesOverloadFunctions = true;
// Specifies the type of context for the module. Implementations should define
// this type to match the context type which is expected to be passed into
// |sqlite3_create_module|.
using Context = void;
// Specifies the type for the vtab created by this module.
//
// Implementations should define this type to match the vtab type they use in
// |Create| and |Connect|.
using Vtab = sqlite3_vtab;
// Specifies the type for the cursor created by this module.
//
// Implementations should define this type to match the cursor type they use
// in |Open| and |Close|.
using Cursor = sqlite3_vtab_cursor;
// Creates a new instance of a virtual table and its backing storage.
//
// Implementations MUST define this function themselves if
// |kType| == |kCreateOnly|; this function is declared but *not* defined so
// linker errors will be thrown if not defined.
static int Create(sqlite3*,
void*,
int,
const char* const*,
sqlite3_vtab**,
char**);
// Destroys the virtual table and its backing storage.
//
// Implementations MUST define this function themselves if
// |kType| == |kCreateOnly|; this function is declared but *not* defined so
// linker errors will be thrown if not defined.
static int Destroy(sqlite3_vtab*);
// Creates a new instance of the virtual table, connecting to existing
// backing storage.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Connect(sqlite3*,
void*,
int,
const char* const*,
sqlite3_vtab**,
char**);
// Destroys the virtual table but *not* its backing storage.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Disconnect(sqlite3_vtab*);
// Specifies filtering and cost information for the query planner.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int BestIndex(sqlite3_vtab*, sqlite3_index_info*);
// Opens a cursor into the given vtab.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Open(sqlite3_vtab*, sqlite3_vtab_cursor**);
// Closes the cursor.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Close(sqlite3_vtab_cursor*);
// Resets this cursor to filter rows matching the provided set of filter
// constraints and order by clauses.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Filter(sqlite3_vtab_cursor*,
int,
const char*,
int,
sqlite3_value**);
// Forwards the cursor to point to the next row.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Next(sqlite3_vtab_cursor*);
// Returns 1 if the cursor has reached its end or 0 otherwise.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Eof(sqlite3_vtab_cursor*);
// Returns the value column at the given index for the current row the cursor
// points to.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Column(sqlite3_vtab_cursor*, sqlite3_context*, int);
// Returns the rowid for the current row.
//
// Implementations MUST define this function themselves; this function is
// declared but *not* defined so linker errors will be thrown if not defined.
static int Rowid(sqlite3_vtab_cursor*, sqlite_int64*);
// Inserts/deletes/updates one row.
//
// Implementations MUST define this function themselves if
// |kSupportsWrites| == |true|; this function is declared but *not* defined so
// linker errors will be thrown if not defined.
static int Update(sqlite3_vtab*, int, sqlite3_value**, sqlite_int64*);
// Overloads a function with the given name when executed with a vtab column
// as the first argument.
//
// Implementations MUST define this function themselves if
// |kDoesOverloadFunctions| == |true|; this function is declared but *not*
// defined so linker errors will be thrown if not defined.
using FindFunctionFn = void(sqlite3_context*, int, sqlite3_value**);
static int FindFunction(sqlite3_vtab*,
int,
const char*,
FindFunctionFn**,
void**);
// Helper function to cast the module context pointer to the correct type.
static auto GetContext(void* ctx) {
return static_cast<typename Impl::Context*>(ctx);
}
// Helper function to cast the vtab pointer to the correct type.
static auto GetVtab(sqlite3_vtab* vtab) {
return static_cast<typename Impl::Vtab*>(vtab);
}
// Helper function to cast the cursor pointer to the correct type.
static auto GetCursor(sqlite3_vtab_cursor* cursor) {
return static_cast<typename Impl::Cursor*>(cursor);
}
// Returns sqlite3_module object corresponding to the module. Used to pass
// information about this module to SQLite.
static constexpr sqlite3_module CreateModule() {
sqlite3_module module{};
module.xBestIndex = &Impl::BestIndex;
module.xOpen = &Impl::Open;
module.xClose = &Impl::Close;
module.xFilter = &Impl::Filter;
module.xNext = &Impl::Next;
module.xEof = &Impl::Eof;
module.xColumn = &Impl::Column;
module.xRowid = &Impl::Rowid;
if constexpr (Impl::kType == kCreateOnly) {
module.xCreate = &Impl::Create;
module.xDestroy = &Impl::Destroy;
module.xConnect = &Impl::Connect;
module.xDisconnect = &Impl::Disconnect;
} else {
module.xCreate = nullptr;
module.xDestroy = [](sqlite3_vtab*) -> int {
PERFETTO_FATAL("Should not be reachable");
};
module.xConnect = &Impl::Connect;
module.xDisconnect = &Impl::Disconnect;
}
if constexpr (Impl::kSupportsWrites) {
module.xUpdate = &Impl::Update;
}
if constexpr (Impl::kDoesOverloadFunctions) {
module.xFindFunction = &Impl::FindFunction;
}
return module;
}
};
} // namespace perfetto::trace_processor::sqlite
#endif // SRC_TRACE_PROCESSOR_SQLITE_BINDINGS_SQLITE_MODULE_H_