aboutsummaryrefslogtreecommitdiff
path: root/src/trace_processor/prelude/functions/register_function.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/trace_processor/prelude/functions/register_function.h')
-rw-r--r--src/trace_processor/prelude/functions/register_function.h233
1 files changed, 0 insertions, 233 deletions
diff --git a/src/trace_processor/prelude/functions/register_function.h b/src/trace_processor/prelude/functions/register_function.h
deleted file mode 100644
index acca3e62a..000000000
--- a/src/trace_processor/prelude/functions/register_function.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2020 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_PRELUDE_FUNCTIONS_REGISTER_FUNCTION_H_
-#define SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_REGISTER_FUNCTION_H_
-
-#include <sqlite3.h>
-#include <memory>
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Prototype for a C++ function which can be registered with SQLite.
-//
-// Usage
-//
-// Define a subclass of this struct as follows:
-// struct YourFunction : public SqlFunction {
-// // Optional if you want a custom context object (i.e. an object
-// // passed in at registration time which will be passed to Run on
-// // every invocation)
-// struct YourContext { /* define context fields here */ };
-//
-// static base::Status Run(/* see parameters below */) {
-// /* function body here */
-// }
-//
-// static base::Status Cleanup(/* see parameters below */) {
-// /* function body here */
-// }
-// }
-//
-// Then, register this function with SQLite using RegisterFunction (see below);
-// you'll likely want to do this in TraceProcessorImpl:
-// RegisterFunction<YourFunction>(/* see arguments below */)
-struct SqlFunction {
- // The type of the context object which will be passed to the function.
- // Can be redefined in any sub-classes to override the context.
- using Context = void;
-
- // Indicates whether this function is "void" (i.e. doesn't actually want
- // to return a value). While the function will still return null in SQL
- // (because SQLite does not actually allow null functions), for accounting
- // purposes, this null will be ignored when verifying whether this statement
- // has any output.
- // Can be redefined in any sub-classes to override it.
- // If this is set to true, subclasses must not modify |out| or |destructors|.
- static constexpr bool kVoidReturn = false;
-
- // Struct which holds destructors for strings/bytes returned from the
- // function. Passed as an argument to |Run| to allow implementations to
- // override the destructors.
- struct Destructors {
- sqlite3_destructor_type string_destructor = sqlite_utils::kSqliteTransient;
- sqlite3_destructor_type bytes_destructor = sqlite_utils::kSqliteTransient;
- };
-
- // The function which will be exectued with the arguments from SQL.
- //
- // Implementations MUST define this function themselves; this function is
- // declared but *not* defined so linker errors will be thrown if not defined.
- //
- // |ctx|: the context object passed at registration time.
- // |argc|: number of arguments.
- // |argv|: arguments to the function.
- // |out|: the return value of the function.
- // |destructors|: destructors for string/bytes return values.
- static base::Status Run(Context* ctx,
- size_t argc,
- sqlite3_value** argv,
- SqlValue& out,
- Destructors& destructors);
-
- // Executed after the result from |Run| is reported to SQLite.
- // Allows implementations to verify post-conditions without needing to worry
- // about overwriting return types.
- //
- // Implementations do not need to define this function; a default no-op
- // implementation will be used in this case.
- static base::Status VerifyPostConditions(Context*);
-
- // Executed after the result from |Run| is reported to SQLite.
- // Allows any pending state to be cleaned up post-copy of results by SQLite:
- // this function will be called even if |Run| or |PostRun| returned errors.
- //
- // Implementations do not need to define this function; a default no-op
- // implementation will be used in this case.
- static void Cleanup(Context*);
-};
-
-// Registers a C++ function to be runnable from SQL.
-// The format of the function is given by the |SqlFunction|; see the
-// documentaion above.
-//
-// |db|: sqlite3 database object
-// |name|: name of the function in SQL
-// |argc|: number of arguments for this function, -1 if variable
-// |ctx|: context object for the function (see SqlFunction::Run above);
-// this object *must* outlive the function so should likely be
-// either static or scoped to the lifetime of TraceProcessor.
-// |determistic|: whether this function has deterministic output given the
-// same set of arguments.
-template <typename Function>
-base::Status RegisterSqlFunction(sqlite3* db,
- const char* name,
- int argc,
- typename Function::Context* ctx,
- bool deterministic = true);
-
-// Same as above except allows a unique_ptr to be passed for the context; this
-// allows for SQLite to manage the lifetime of this pointer instead of the
-// essentially static requirement of the context pointer above.
-template <typename Function>
-base::Status RegisterSqlFunction(
- sqlite3* db,
- const char* name,
- int argc,
- std::unique_ptr<typename Function::Context> ctx,
- bool deterministic = true);
-
-} // namespace trace_processor
-} // namespace perfetto
-
-// The rest of this file is just implementation details which we need
-// in the header file because it is templated code. We separate it out
-// like this to keep the API people actually care about easy to read.
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace sqlite_internal {
-
-// RAII type to call Function::Cleanup when destroyed.
-template <typename Function>
-struct ScopedCleanup {
- typename Function::Context* ctx;
- ~ScopedCleanup() { Function::Cleanup(ctx); }
-};
-
-template <typename Function>
-void WrapSqlFunction(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
- using Context = typename Function::Context;
- Context* ud = static_cast<Context*>(sqlite3_user_data(ctx));
-
- ScopedCleanup<Function> scoped_cleanup{ud};
- SqlValue value{};
- SqlFunction::Destructors destructors{};
- base::Status status =
- Function::Run(ud, static_cast<size_t>(argc), argv, value, destructors);
- if (!status.ok()) {
- sqlite3_result_error(ctx, status.c_message(), -1);
- return;
- }
-
- if (Function::kVoidReturn) {
- if (!value.is_null()) {
- sqlite3_result_error(ctx, "void SQL function returned value", -1);
- return;
- }
-
- // If the function doesn't want to return anything, set the "VOID"
- // pointer type to a non-null value. Note that because of the weird
- // way |sqlite3_value_pointer| works, we need to set some value even
- // if we don't actually read it - just set it to a pointer to an empty
- // string for this reason.
- static char kVoidValue[] = "";
- sqlite3_result_pointer(ctx, kVoidValue, "VOID", nullptr);
- } else {
- sqlite_utils::ReportSqlValue(ctx, value, destructors.string_destructor,
- destructors.bytes_destructor);
- }
-
- status = Function::VerifyPostConditions(ud);
- if (!status.ok()) {
- sqlite3_result_error(ctx, status.c_message(), -1);
- return;
- }
-}
-} // namespace sqlite_internal
-
-template <typename Function>
-base::Status RegisterSqlFunction(sqlite3* db,
- const char* name,
- int argc,
- typename Function::Context* ctx,
- bool deterministic) {
- int flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0);
- int ret = sqlite3_create_function_v2(
- db, name, static_cast<int>(argc), flags, ctx,
- sqlite_internal::WrapSqlFunction<Function>, nullptr, nullptr, nullptr);
- if (ret != SQLITE_OK) {
- return base::ErrStatus("Unable to register function with name %s", name);
- }
- return base::OkStatus();
-}
-
-template <typename Function>
-base::Status RegisterSqlFunction(
- sqlite3* db,
- const char* name,
- int argc,
- std::unique_ptr<typename Function::Context> user_data,
- bool deterministic) {
- int flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0);
- int ret = sqlite3_create_function_v2(
- db, name, static_cast<int>(argc), flags, user_data.release(),
- sqlite_internal::WrapSqlFunction<Function>, nullptr, nullptr,
- [](void* ptr) { delete static_cast<typename Function::Context*>(ptr); });
- if (ret != SQLITE_OK) {
- return base::ErrStatus("Unable to register function with name %s", name);
- }
- return base::OkStatus();
-}
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_REGISTER_FUNCTION_H_