blob: ba7fab7d84674827c50fe5220ca9fd2a15ba075c [file] [log] [blame]
/*
* Copyright (C) 2023 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_SQL_FUNCTION_H_
#define SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_SQL_FUNCTION_H_
#include <sqlite3.h>
#include <memory>
#include "perfetto/base/status.h"
#include "perfetto/trace_processor/basic_types.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 {
// This matches SQLITE_TRANSIENT constant which we cannot use because it
// expands to a C-style cast, causing compiler warnings.
sqlite3_destructor_type string_destructor =
reinterpret_cast<sqlite3_destructor_type>(-1);
sqlite3_destructor_type bytes_destructor =
reinterpret_cast<sqlite3_destructor_type>(-1);
};
// The function which will be executed 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*);
};
} // namespace trace_processor
} // namespace perfetto
#endif // SRC_TRACE_PROCESSOR_PRELUDE_FUNCTIONS_SQL_FUNCTION_H_