1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, 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 writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_function.h"
18
19 #include <queue>
20 #include <stack>
21
22 #include "perfetto/base/status.h"
23 #include "perfetto/trace_processor/basic_types.h"
24 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
25 #include "src/trace_processor/perfetto_sql/parser/function_util.h"
26 #include "src/trace_processor/sqlite/sql_source.h"
27 #include "src/trace_processor/sqlite/sqlite_utils.h"
28 #include "src/trace_processor/util/sql_argument.h"
29 #include "src/trace_processor/util/status_macros.h"
30
31 namespace perfetto::trace_processor {
32
Run(PerfettoSqlEngine * engine,size_t argc,sqlite3_value ** argv,SqlValue &,Destructors &)33 base::Status CreateFunction::Run(PerfettoSqlEngine* engine,
34 size_t argc,
35 sqlite3_value** argv,
36 SqlValue&,
37 Destructors&) {
38 RETURN_IF_ERROR(sqlite::utils::CheckArgCount("CREATE_FUNCTION", argc, 3u));
39
40 sqlite3_value* prototype_value = argv[0];
41 sqlite3_value* return_type_value = argv[1];
42 sqlite3_value* sql_defn_value = argv[2];
43
44 // Type check all the arguments.
45 {
46 auto type_check = [prototype_value](sqlite3_value* value,
47 SqlValue::Type type, const char* desc) {
48 base::Status status = sqlite::utils::TypeCheckSqliteValue(value, type);
49 if (!status.ok()) {
50 return base::ErrStatus("CREATE_FUNCTION[prototype=%s]: %s %s",
51 sqlite3_value_text(prototype_value), desc,
52 status.c_message());
53 }
54 return base::OkStatus();
55 };
56
57 RETURN_IF_ERROR(type_check(prototype_value, SqlValue::Type::kString,
58 "function prototype (first argument)"));
59 RETURN_IF_ERROR(type_check(return_type_value, SqlValue::Type::kString,
60 "return type (second argument)"));
61 RETURN_IF_ERROR(type_check(sql_defn_value, SqlValue::Type::kString,
62 "SQL definition (third argument)"));
63 }
64
65 // Extract the arguments from the value wrappers.
66 auto extract_string = [](sqlite3_value* value) -> base::StringView {
67 return reinterpret_cast<const char*>(sqlite3_value_text(value));
68 };
69 std::string prototype_str = extract_string(prototype_value).ToStdString();
70 std::string return_type_str = extract_string(return_type_value).ToStdString();
71 std::string sql_defn_str = extract_string(sql_defn_value).ToStdString();
72
73 FunctionPrototype prototype;
74 RETURN_IF_ERROR(ParsePrototype(base::StringView(prototype_str), prototype));
75 auto type = sql_argument::ParseType(base::StringView(return_type_str));
76 if (!type) {
77 return base::ErrStatus("CREATE_FUNCTION: unknown return type %s",
78 return_type_str.c_str());
79 }
80 return engine->RegisterRuntimeFunction(
81 true /* replace */, prototype, *type,
82 SqlSource::FromTraceProcessorImplementation(std::move(sql_defn_str)));
83 }
84
Run(PerfettoSqlEngine * engine,size_t argc,sqlite3_value ** argv,SqlValue &,Destructors &)85 base::Status ExperimentalMemoize::Run(PerfettoSqlEngine* engine,
86 size_t argc,
87 sqlite3_value** argv,
88 SqlValue&,
89 Destructors&) {
90 RETURN_IF_ERROR(
91 sqlite::utils::CheckArgCount("EXPERIMENTAL_MEMOIZE", argc, 1));
92 base::StatusOr<std::string> function_name =
93 sqlite::utils::ExtractStringArg("MEMOIZE", "function_name", argv[0]);
94 RETURN_IF_ERROR(function_name.status());
95 return engine->EnableSqlFunctionMemoization(*function_name);
96 }
97
98 } // namespace perfetto::trace_processor
99